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
033/**
034 * 
035 */
036public class HttpMethodConfiguration
037{
038
039    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
040
041    private static final String COERCE_PATTERN = "%(\\w+),(.+)";
042
043    private Boolean useDefaultHeaders;
044
045    private Properties headers = new Properties();
046
047    private Properties params = new Properties();
048
049    private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
050
051    public boolean isUseDefaultHeaders()
052    {
053        return useDefaultHeaders == null ? true : useDefaultHeaders.booleanValue();
054    }
055
056    public HttpMethodConfiguration setUseDefaultHeaders( boolean useDefaultHeaders )
057    {
058        this.useDefaultHeaders = Boolean.valueOf( useDefaultHeaders );
059        return this;
060    }
061
062    public Boolean getUseDefaultHeaders()
063    {
064        return useDefaultHeaders;
065    }
066
067    public HttpMethodConfiguration addHeader( String header, String value )
068    {
069        headers.setProperty( header, value );
070        return this;
071    }
072
073    public Properties getHeaders()
074    {
075        return headers;
076    }
077
078    public HttpMethodConfiguration setHeaders( Properties headers )
079    {
080        this.headers = headers;
081        return this;
082    }
083
084    public HttpMethodConfiguration addParam( String param, String value )
085    {
086        params.setProperty( param, value );
087        return this;
088    }
089
090    public Properties getParams()
091    {
092        return params;
093    }
094
095    public HttpMethodConfiguration setParams( Properties params )
096    {
097        this.params = params;
098        return this;
099    }
100
101    public int getConnectionTimeout()
102    {
103        return connectionTimeout;
104    }
105
106    public HttpMethodConfiguration setConnectionTimeout( int connectionTimeout )
107    {
108        this.connectionTimeout = connectionTimeout;
109        return this;
110    }
111
112    public HttpMethodParams asMethodParams( HttpMethodParams defaults )
113    {
114        if ( !hasParams() )
115        {
116            return null;
117        }
118
119        HttpMethodParams p = new HttpMethodParams();
120        p.setDefaults( defaults );
121
122        fillParams( p );
123
124        return p;
125    }
126
127    private boolean hasParams()
128    {
129        if ( connectionTimeout < 1 && params == null )
130        {
131            return false;
132        }
133
134        return true;
135    }
136
137    private void fillParams( HttpMethodParams p )
138    {
139        if ( !hasParams() )
140        {
141            return;
142        }
143
144        if ( connectionTimeout > 0 )
145        {
146            p.setSoTimeout( connectionTimeout );
147        }
148
149        if ( params != null )
150        {
151            Pattern coercePattern = Pattern.compile( COERCE_PATTERN );
152
153            for ( Map.Entry<Object, Object> entry : params.entrySet() )
154            {
155                String key = (String) entry.getKey();
156                String value = (String) entry.getValue();
157
158                Matcher matcher = coercePattern.matcher( value );
159                if ( matcher.matches() )
160                {
161                    char type = matcher.group( 1 ).charAt( 0 );
162                    value = matcher.group( 2 );
163
164                    // CHECKSTYLE_OFF: AvoidNestedBlocks
165                    switch ( type )
166                    {
167                        case 'i':
168                            p.setIntParameter( key, Integer.parseInt( value ) );
169                            break;
170
171                        case 'd':
172                            p.setDoubleParameter( key, Double.parseDouble( value ) );
173                            break;
174
175                        case 'l':
176                            p.setLongParameter( key, Long.parseLong( value ) );
177                            break;
178
179                        case 'b':
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                        default:
217                    }
218                    // CHECKSTYLE_ON: AvoidNestedBlocks
219                }
220                else
221                {
222                    p.setParameter( key, value );
223                }
224            }
225        }
226    }
227
228    public Header[] asRequestHeaders()
229    {
230        if ( headers == null )
231        {
232            return new Header[0];
233        }
234
235        Header[] result = new Header[headers.size()];
236
237        int index = 0;
238        for ( Map.Entry<Object, Object> entry : headers.entrySet() )
239        {
240            String key = (String) entry.getKey();
241            String value = (String) entry.getValue();
242
243            Header header = new Header( key, value );
244            result[index++] = header;
245        }
246
247        return result;
248    }
249
250    private HttpMethodConfiguration copy()
251    {
252        HttpMethodConfiguration copy = new HttpMethodConfiguration();
253
254        copy.setConnectionTimeout( getConnectionTimeout() );
255        if ( getHeaders() != null )
256        {
257            copy.setHeaders( getHeaders() );
258        }
259
260        if ( getParams() != null )
261        {
262            copy.setParams( getParams() );
263        }
264
265        copy.setUseDefaultHeaders( isUseDefaultHeaders() );
266
267        return copy;
268    }
269
270    public static HttpMethodConfiguration merge( HttpMethodConfiguration defaults, HttpMethodConfiguration base,
271                                                 HttpMethodConfiguration local )
272    {
273        HttpMethodConfiguration result = merge( defaults, base );
274        return merge( result, local );
275    }
276
277    public static HttpMethodConfiguration merge( HttpMethodConfiguration base, HttpMethodConfiguration local )
278    {
279        if ( base == null && local == null )
280        {
281            return null;
282        }
283        else if ( base == null )
284        {
285            return local;
286        }
287        else if ( local == null )
288        {
289            return base;
290        }
291        else
292        {
293            HttpMethodConfiguration result = base.copy();
294
295            if ( local.getConnectionTimeout() != DEFAULT_CONNECTION_TIMEOUT )
296            {
297                result.setConnectionTimeout( local.getConnectionTimeout() );
298            }
299
300            if ( local.getHeaders() != null )
301            {
302                result.getHeaders().putAll( local.getHeaders() );
303            }
304
305            if ( local.getParams() != null )
306            {
307                result.getParams().putAll( local.getParams() );
308            }
309
310            if ( local.getUseDefaultHeaders() != null )
311            {
312                result.setUseDefaultHeaders( local.isUseDefaultHeaders() );
313            }
314
315            return result;
316        }
317    }
318
319}