001package org.apache.maven.wagon.providers.webdav;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import org.apache.commons.httpclient.Header;
023import org.apache.commons.httpclient.params.HttpMethodParams;
024
025import java.util.ArrayList;
026import java.util.LinkedHashMap;
027import java.util.List;
028import java.util.Map;
029import java.util.Properties;
030import java.util.regex.Matcher;
031import java.util.regex.Pattern;
032
033public class HttpMethodConfiguration
034{
035
036    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
037
038    private static final String COERCE_PATTERN = "%(\\w+),(.+)";
039
040    private Boolean useDefaultHeaders;
041
042    private Properties headers = new Properties();
043
044    private Properties params = new Properties();
045
046    private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
047
048    public boolean isUseDefaultHeaders()
049    {
050        return useDefaultHeaders == null ? true : useDefaultHeaders.booleanValue();
051    }
052
053    public HttpMethodConfiguration setUseDefaultHeaders( boolean useDefaultHeaders )
054    {
055        this.useDefaultHeaders = Boolean.valueOf( useDefaultHeaders );
056        return this;
057    }
058
059    public Boolean getUseDefaultHeaders()
060    {
061        return useDefaultHeaders;
062    }
063
064    public HttpMethodConfiguration addHeader( String header, String value )
065    {
066        headers.setProperty( header, value );
067        return this;
068    }
069
070    public Properties getHeaders()
071    {
072        return headers;
073    }
074
075    public HttpMethodConfiguration setHeaders( Properties headers )
076    {
077        this.headers = headers;
078        return this;
079    }
080
081    public HttpMethodConfiguration addParam( String param, String value )
082    {
083        params.setProperty( param, value );
084        return this;
085    }
086
087    public Properties getParams()
088    {
089        return params;
090    }
091
092    public HttpMethodConfiguration setParams( Properties params )
093    {
094        this.params = params;
095        return this;
096    }
097
098    public int getConnectionTimeout()
099    {
100        return connectionTimeout;
101    }
102
103    public HttpMethodConfiguration setConnectionTimeout( int connectionTimeout )
104    {
105        this.connectionTimeout = connectionTimeout;
106        return this;
107    }
108
109    public HttpMethodParams asMethodParams( HttpMethodParams defaults )
110    {
111        if ( !hasParams() )
112        {
113            return null;
114        }
115
116        HttpMethodParams p = new HttpMethodParams();
117        p.setDefaults( defaults );
118
119        fillParams( p );
120
121        return p;
122    }
123
124    private boolean hasParams()
125    {
126        if ( connectionTimeout < 1 && params == null )
127        {
128            return false;
129        }
130
131        return true;
132    }
133
134    private void fillParams( HttpMethodParams p )
135    {
136        if ( !hasParams() )
137        {
138            return;
139        }
140
141        if ( connectionTimeout > 0 )
142        {
143            p.setSoTimeout( connectionTimeout );
144        }
145
146        if ( params != null )
147        {
148            Pattern coercePattern = Pattern.compile( COERCE_PATTERN );
149
150            for ( Map.Entry<Object, Object> entry : params.entrySet() )
151            {
152                String key = (String) entry.getKey();
153                String value = (String) entry.getValue();
154
155                Matcher matcher = coercePattern.matcher( value );
156                if ( matcher.matches() )
157                {
158                    char type = matcher.group( 1 ).charAt( 0 );
159                    value = matcher.group( 2 );
160
161                    switch ( type )
162                    {
163                        case 'i':
164                        {
165                            p.setIntParameter( key, Integer.parseInt( value ) );
166                            break;
167                        }
168                        case 'd':
169                        {
170                            p.setDoubleParameter( key, Double.parseDouble( value ) );
171                            break;
172                        }
173                        case 'l':
174                        {
175                            p.setLongParameter( key, Long.parseLong( value ) );
176                            break;
177                        }
178                        case 'b':
179                        {
180                            p.setBooleanParameter( key, Boolean.valueOf( value ).booleanValue() );
181                            break;
182                        }
183                        case 'c':
184                        {
185                            String[] entries = value.split( "," );
186                            List<String> collection = new ArrayList<String>();
187                            for (String e : entries)
188                            {
189                                collection.add( e.trim() );
190                            }
191
192                            p.setParameter( key, collection );
193                            break;
194                        }
195                        case 'm':
196                        {
197                            String[] entries = value.split( "," );
198
199                            Map<String, String> map = new LinkedHashMap<String, String>();
200                            for ( String e : entries )
201                            {
202                                int idx = e.indexOf( "=>" );
203                                if ( idx < 1 )
204                                {
205                                    break;
206                                }
207
208                                String mapKey = e.substring( 0, idx );
209                                String mapVal = e.substring( idx + 1, e.length() );
210                                map.put( mapKey.trim(), mapVal.trim() );
211                            }
212
213                            p.setParameter( key, map );
214                            break;
215                        }
216                    }
217                }
218                else
219                {
220                    p.setParameter( key, value );
221                }
222            }
223        }
224    }
225
226    public Header[] asRequestHeaders()
227    {
228        if ( headers == null )
229        {
230            return new Header[0];
231        }
232
233        Header[] result = new Header[headers.size()];
234
235        int index = 0;
236        for ( Map.Entry<Object, Object> entry : headers.entrySet() )
237        {
238            String key = (String) entry.getKey();
239            String value = (String) entry.getValue();
240
241            Header header = new Header( key, value );
242            result[index++] = header;
243        }
244
245        return result;
246    }
247
248    private HttpMethodConfiguration copy()
249    {
250        HttpMethodConfiguration copy = new HttpMethodConfiguration();
251
252        copy.setConnectionTimeout( getConnectionTimeout() );
253        if ( getHeaders() != null )
254        {
255            copy.setHeaders( getHeaders() );
256        }
257
258        if ( getParams() != null )
259        {
260            copy.setParams( getParams() );
261        }
262
263        copy.setUseDefaultHeaders( isUseDefaultHeaders() );
264
265        return copy;
266    }
267
268    public static HttpMethodConfiguration merge( HttpMethodConfiguration defaults, HttpMethodConfiguration base,
269                                                 HttpMethodConfiguration local )
270    {
271        HttpMethodConfiguration result = merge( defaults, base );
272        return merge( result, local );
273    }
274
275    public static HttpMethodConfiguration merge( HttpMethodConfiguration base, HttpMethodConfiguration local )
276    {
277        if ( base == null && local == null )
278        {
279            return null;
280        }
281        else if ( base == null )
282        {
283            return local;
284        }
285        else if ( local == null )
286        {
287            return base;
288        }
289        else
290        {
291            HttpMethodConfiguration result = base.copy();
292
293            if ( local.getConnectionTimeout() != DEFAULT_CONNECTION_TIMEOUT )
294            {
295                result.setConnectionTimeout( local.getConnectionTimeout() );
296            }
297
298            if ( local.getHeaders() != null )
299            {
300                result.getHeaders().putAll( local.getHeaders() );
301            }
302
303            if ( local.getParams() != null )
304            {
305                result.getParams().putAll( local.getParams() );
306            }
307
308            if ( local.getUseDefaultHeaders() != null )
309            {
310                result.setUseDefaultHeaders( local.isUseDefaultHeaders() );
311            }
312
313            return result;
314        }
315    }
316
317}