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