001package org.apache.maven.wagon.shared.http;
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.Iterator;
027import java.util.LinkedHashMap;
028import java.util.List;
029import java.util.Map;
030import java.util.Properties;
031import java.util.regex.Matcher;
032import java.util.regex.Pattern;
033
034public class HttpMethodConfiguration
035{
036
037    public static final int DEFAULT_CONNECTION_TIMEOUT = 60000;
038
039    private static final String COERCE_PATTERN = "%(\\w+),(.+)";
040
041    private Boolean useDefaultHeaders;
042
043    private Properties headers = new Properties();
044
045    private Properties params = new Properties();
046
047    private int connectionTimeout = DEFAULT_CONNECTION_TIMEOUT;
048
049    public boolean isUseDefaultHeaders()
050    {
051        return useDefaultHeaders == null ? true : useDefaultHeaders.booleanValue();
052    }
053
054    public HttpMethodConfiguration setUseDefaultHeaders( boolean useDefaultHeaders )
055    {
056        this.useDefaultHeaders = Boolean.valueOf( useDefaultHeaders );
057        return this;
058    }
059
060    public Boolean getUseDefaultHeaders()
061    {
062        return useDefaultHeaders;
063    }
064
065    public HttpMethodConfiguration addHeader( String header, String value )
066    {
067        headers.setProperty( header, value );
068        return this;
069    }
070
071    public Properties getHeaders()
072    {
073        return headers;
074    }
075
076    public HttpMethodConfiguration setHeaders( Properties headers )
077    {
078        this.headers = headers;
079        return this;
080    }
081
082    public HttpMethodConfiguration addParam( String param, String value )
083    {
084        params.setProperty( param, value );
085        return this;
086    }
087
088    public Properties getParams()
089    {
090        return params;
091    }
092
093    public HttpMethodConfiguration setParams( Properties params )
094    {
095        this.params = params;
096        return this;
097    }
098
099    public int getConnectionTimeout()
100    {
101        return connectionTimeout;
102    }
103
104    public HttpMethodConfiguration setConnectionTimeout( int connectionTimeout )
105    {
106        this.connectionTimeout = connectionTimeout;
107        return this;
108    }
109
110    public HttpMethodParams asMethodParams( HttpMethodParams defaults )
111    {
112        if ( !hasParams() )
113        {
114            return null;
115        }
116
117        HttpMethodParams p = new HttpMethodParams();
118        p.setDefaults( defaults );
119
120        fillParams( p );
121
122        return p;
123    }
124
125    private boolean hasParams()
126    {
127        if ( connectionTimeout < 1 && params == null )
128        {
129            return false;
130        }
131
132        return true;
133    }
134
135    private void fillParams( HttpMethodParams p )
136    {
137        if ( !hasParams() )
138        {
139            return;
140        }
141
142        if ( connectionTimeout > 0 )
143        {
144            p.setSoTimeout( connectionTimeout );
145        }
146
147        if ( params != null )
148        {
149            Pattern coercePattern = Pattern.compile( COERCE_PATTERN );
150
151            for ( Iterator it = params.entrySet().iterator(); it.hasNext(); )
152            {
153                Map.Entry entry = (Map.Entry) it.next();
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                    switch ( type )
165                    {
166                        case 'i':
167                        {
168                            p.setIntParameter( key, Integer.parseInt( value ) );
169                            break;
170                        }
171                        case 'd':
172                        {
173                            p.setDoubleParameter( key, Double.parseDouble( value ) );
174                            break;
175                        }
176                        case 'l':
177                        {
178                            p.setLongParameter( key, Long.parseLong( value ) );
179                            break;
180                        }
181                        case 'b':
182                        {
183                            p.setBooleanParameter( key, Boolean.valueOf( value ).booleanValue() );
184                            break;
185                        }
186                        case 'c':
187                        {
188                            String[] entries = value.split( "," );
189                            List collection = new ArrayList();
190                            for ( int i = 0; i < entries.length; i++ )
191                            {
192                                collection.add( entries[i].trim() );
193                            }
194
195                            p.setParameter( key, collection );
196                            break;
197                        }
198                        case 'm':
199                        {
200                            String[] entries = value.split( "," );
201
202                            Map map = new LinkedHashMap();
203                            for ( int i = 0; i < entries.length; i++ )
204                            {
205                                int idx = entries[i].indexOf( "=>" );
206                                if ( idx < 1 )
207                                {
208                                    break;
209                                }
210
211                                String mapKey = entries[i].substring( 0, idx );
212                                String mapVal = entries[i].substring( idx + 1, entries[i].length() );
213                                map.put( mapKey.trim(), mapVal.trim() );
214                            }
215
216                            p.setParameter( key, map );
217                            break;
218                        }
219                    }
220                }
221                else
222                {
223                    p.setParameter( key, value );
224                }
225            }
226        }
227    }
228
229    public Header[] asRequestHeaders()
230    {
231        if ( headers == null )
232        {
233            return new Header[0];
234        }
235
236        Header[] result = new Header[headers.size()];
237
238        int index = 0;
239        for ( Iterator it = headers.entrySet().iterator(); it.hasNext(); )
240        {
241            Map.Entry entry = (Map.Entry) it.next();
242
243            String key = (String) entry.getKey();
244            String value = (String) entry.getValue();
245
246            Header header = new Header( key, value );
247            result[index++] = header;
248        }
249
250        return result;
251    }
252
253    private HttpMethodConfiguration copy()
254    {
255        HttpMethodConfiguration copy = new HttpMethodConfiguration();
256
257        copy.setConnectionTimeout( getConnectionTimeout() );
258        if ( getHeaders() != null )
259        {
260            copy.setHeaders( getHeaders() );
261        }
262
263        if ( getParams() != null )
264        {
265            copy.setParams( getParams() );
266        }
267
268        copy.setUseDefaultHeaders( isUseDefaultHeaders() );
269
270        return copy;
271    }
272
273    public static HttpMethodConfiguration merge( HttpMethodConfiguration defaults, HttpMethodConfiguration base,
274                                                 HttpMethodConfiguration local )
275    {
276        HttpMethodConfiguration result = merge( defaults, base );
277        return merge( result, local );
278    }
279
280    public static HttpMethodConfiguration merge( HttpMethodConfiguration base, HttpMethodConfiguration local )
281    {
282        if ( base == null && local == null )
283        {
284            return null;
285        }
286        else if ( base == null )
287        {
288            return local;
289        }
290        else if ( local == null )
291        {
292            return base;
293        }
294        else
295        {
296            HttpMethodConfiguration result = base.copy();
297
298            if ( local.getConnectionTimeout() != DEFAULT_CONNECTION_TIMEOUT )
299            {
300                result.setConnectionTimeout( local.getConnectionTimeout() );
301            }
302
303            if ( local.getHeaders() != null )
304            {
305                result.getHeaders().putAll( local.getHeaders() );
306            }
307
308            if ( local.getParams() != null )
309            {
310                result.getParams().putAll( local.getParams() );
311            }
312
313            if ( local.getUseDefaultHeaders() != null )
314            {
315                result.setUseDefaultHeaders( local.isUseDefaultHeaders() );
316            }
317
318            return result;
319        }
320    }
321
322}