001    //$HeadURL: http://svn.wald.intevation.org/svn/deegree/base/trunk/src/org/deegree/framework/util/HttpUtils.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003     This file is part of deegree.
004     Copyright (C) 2001-2008 by:
005     Department of Geography, University of Bonn
006     http://www.giub.uni-bonn.de/deegree/
007     lat/lon GmbH
008     http://www.lat-lon.de
009    
010     This library is free software; you can redistribute it and/or
011     modify it under the terms of the GNU Lesser General Public
012     License as published by the Free Software Foundation; either
013     version 2.1 of the License, or (at your option) any later version.
014     This library is distributed in the hope that it will be useful,
015     but WITHOUT ANY WARRANTY; without even the implied warranty of
016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
017     Lesser General Public License for more details.
018     You should have received a copy of the GNU Lesser General Public
019     License along with this library; if not, write to the Free Software
020     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
021     Contact:
022    
023     Andreas Poth
024     lat/lon GmbH
025     Aennchenstr. 19
026     53177 Bonn
027     Germany
028     E-Mail: poth@lat-lon.de
029    
030     Prof. Dr. Klaus Greve
031     Department of Geography
032     University of Bonn
033     Meckenheimer Allee 166
034     53115 Bonn
035     Germany
036     E-Mail: greve@giub.uni-bonn.de
037     ---------------------------------------------------------------------------*/
038    
039    package org.deegree.framework.util;
040    
041    import java.io.ByteArrayOutputStream;
042    import java.io.IOException;
043    import java.io.InputStream;
044    import java.net.HttpURLConnection;
045    import java.net.InetAddress;
046    import java.net.MalformedURLException;
047    import java.net.URISyntaxException;
048    import java.net.URL;
049    import java.util.Iterator;
050    import java.util.Map;
051    import java.util.Properties;
052    
053    import javax.xml.transform.OutputKeys;
054    
055    import org.apache.commons.codec.binary.Base64;
056    import org.apache.commons.httpclient.Header;
057    import org.apache.commons.httpclient.HttpClient;
058    import org.apache.commons.httpclient.HttpException;
059    import org.apache.commons.httpclient.HttpMethod;
060    import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
061    import org.apache.commons.httpclient.methods.GetMethod;
062    import org.apache.commons.httpclient.methods.HeadMethod;
063    import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
064    import org.apache.commons.httpclient.methods.PostMethod;
065    import org.apache.commons.httpclient.methods.StringRequestEntity;
066    import org.deegree.enterprise.WebUtils;
067    import org.deegree.framework.log.ILogger;
068    import org.deegree.framework.log.LoggerFactory;
069    import org.deegree.framework.xml.XMLFragment;
070    
071    /**
072     * utility class for performing HTTP requests
073     * 
074     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
075     * @author last edited by: $Author: apoth $
076     * 
077     * @version. $Revision: 30454 $, $Date: 2011-04-14 14:03:42 +0200 (Thu, 14 Apr 2011) $
078     */
079    public class HttpUtils {
080    
081        private static final ILogger LOG = LoggerFactory.getLogger( HttpUtils.class );
082    
083        /**
084         * validates passed URL. If it is not a valid URL or a client can not connect to it an exception will be thrown
085         * 
086         * @param url
087         * @throws IOException
088         */
089        public static int validateURL( String url )
090                                throws IOException {
091            return validateURL( url, null, null );
092        }
093    
094        /**
095         * validates passed URL. If it is not a valid URL or a client can not connect to it an exception will be thrown
096         * 
097         * @param url
098         * @param user
099         * @param password
100         * @throws IOException
101         */
102        public static int validateURL( String url, String user, String password )
103                                throws IOException {
104            if ( url.startsWith( "http:" ) ) {
105                URL tmp = new URL( url );
106                HeadMethod hm = new HeadMethod( url );
107                setHTTPCredentials( hm, user, password );
108                InetAddress.getByName( tmp.getHost() );
109                HttpClient client = new HttpClient();
110                client.executeMethod( hm );
111                if ( hm.getStatusCode() != HttpURLConnection.HTTP_OK ) {
112                    if ( hm.getStatusCode() != HttpURLConnection.HTTP_UNAUTHORIZED && hm.getStatusCode() != 401 ) {
113                        // this method just evaluates if a URL/host is valid; it does not takes care
114                        // if authorization is available/valid
115                        throw new IOException( "Host " + tmp.getHost() + " of URL + " + url + " does not exists" );
116                    }
117                }
118                return hm.getStatusCode();
119            } else if ( url.startsWith( "file:" ) ) {
120                URL tmp = new URL( url );
121                InputStream is = tmp.openStream();
122                is.close();
123                return 200;
124            }
125            return HttpURLConnection.HTTP_UNAVAILABLE;
126        }
127    
128        /**
129         * 
130         * @param url
131         * @param content
132         * @param timeout
133         *            timeout in milliseconds
134         * @param user
135         *            (can be <code>null</code>)
136         * @param password
137         *            (can be <code>null</code>)
138         * @param contentType
139         *            request content mime type (can be <code>null</code>)
140         * @param encoding
141         *            request encoding (can be <code>null</code>)
142         * @param header
143         * 
144         * @return result of http post request
145         * @throws HttpException
146         * @throws IOException
147         */
148        public static HttpMethod performHttpPost( String url, InputStream content, int timeout, String user,
149                                                  String password, String contentType, String encoding,
150                                                  Map<String, String> header )
151                                throws HttpException, IOException {
152            HttpClient client = new HttpClient();
153            URL tmp = new URL( url );
154            WebUtils.enableProxyUsage( client, tmp );
155            url = tmp.toExternalForm();
156            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
157            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
158    
159            PostMethod pm = new PostMethod( url );
160            String ct = contentType;
161            if ( ct != null && encoding != null ) {
162                ct += ( "; " + encoding );
163            }
164            if ( ct != null ) {
165                pm.setRequestEntity( new InputStreamRequestEntity( content, ct ) );
166            } else {
167                pm.setRequestEntity( new InputStreamRequestEntity( content ) );
168            }
169            if ( header != null ) {
170                Iterator<String> iter = header.keySet().iterator();
171                while ( iter.hasNext() ) {
172                    String key = (String) iter.next();
173                    if ( !"content-length".equalsIgnoreCase( key ) ) {
174                        pm.addRequestHeader( new Header( key, header.get( key ) ) );
175                    }
176                }
177            }
178    
179            setHTTPCredentials( pm, user, password );
180            client.executeMethod( pm );
181            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
182                LOG.logDebug( pm.getResponseBodyAsString() );
183            }
184            if ( pm.getStatusCode() != 200 ) {
185                throw new HttpException( "status code: " + pm.getStatusCode() );
186            }
187            return pm;
188        }
189    
190        /**
191         * 
192         * @param url
193         * @param content
194         * @param timeout
195         *            timeout in milliseconds
196         * @param user
197         *            (can <code>null</code>)
198         * @param password
199         *            (can <code>null</code>)
200         * @param contentType
201         *            request content mime type (can be <code>null</code>)
202         * @param encoding
203         *            request encoding (can be <code>null</code>)
204         * @param header
205         * @return result of http post request
206         * @throws HttpException
207         * @throws IOException
208         */
209        public static HttpMethod performHttpPost( String url, String content, int timeout, String user, String password,
210                                                  String contentType, String encoding, Map<String, String> header )
211                                throws HttpException, IOException {
212            HttpClient client = new HttpClient();
213            URL tmp = new URL( url );
214            WebUtils.enableProxyUsage( client, tmp );
215            url = tmp.toExternalForm();
216            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
217            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
218            PostMethod pm = new PostMethod( url );
219    
220            pm.setRequestEntity( new StringRequestEntity( content, contentType, encoding ) );
221    
222            if ( header != null ) {
223                Iterator<String> iter = header.keySet().iterator();
224                while ( iter.hasNext() ) {
225                    String key = (String) iter.next();
226                    if ( !"content-length".equalsIgnoreCase( key ) ) {
227                        pm.addRequestHeader( new Header( key, header.get( key ) ) );
228                    }
229                }
230            }
231            pm.addRequestHeader( new Header( "content-length", Integer.toString( content.getBytes().length ) ) );
232    
233            setHTTPCredentials( pm, user, password );
234            client.executeMethod( pm );
235            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
236                LOG.logDebug( pm.getResponseBodyAsString() );
237            }
238            if ( pm.getStatusCode() != 200 ) {
239                throw new HttpException( "status code: " + pm.getStatusCode() );
240            }
241            return pm;
242        }
243    
244        /**
245         * 
246         * @param url
247         * @param content
248         * @param timeout
249         *            timeout in milliseconds
250         * @param user
251         *            (can <code>null</code>)
252         * @param password
253         *            (can <code>null</code>)
254         * @param header
255         * @return result of http post request
256         * @throws HttpException
257         * @throws IOException
258         */
259        public static HttpMethod performHttpPost( String url, XMLFragment content, int timeout, String user,
260                                                  String password, Map<String, String> header )
261                                throws HttpException, IOException {
262            
263            HttpClient client = new HttpClient();
264            URL tmp = new URL( url );
265            WebUtils.enableProxyUsage( client, tmp );
266            url = tmp.toExternalForm();
267            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
268            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
269            PostMethod pm = new PostMethod( url );        
270    
271            ByteArrayOutputStream bos = new ByteArrayOutputStream( 1000000 );
272            Properties props = new Properties();
273            props.put( OutputKeys.ENCODING, "UTF-8" );
274            content.write( bos, props );        
275    
276            pm.setRequestEntity( new ByteArrayRequestEntity( bos.toByteArray(), "text/xml" ) );
277    
278            if ( header != null ) {
279                Iterator<String> iter = header.keySet().iterator();
280                while ( iter.hasNext() ) {
281                    String key = (String) iter.next();
282                    if ( !"content-length".equalsIgnoreCase( key ) ) {
283                        pm.addRequestHeader( new Header( key, header.get( key ) ) );
284                    }
285                }
286            }
287            pm.addRequestHeader( new Header( "content-length", Integer.toString( bos.toByteArray().length ) ) );
288            bos.close();
289    
290            setHTTPCredentials( pm, user, password );
291            client.executeMethod( pm );
292            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
293                LOG.logDebug( pm.getResponseBodyAsString() );
294            }
295            if ( pm.getStatusCode() != 200 ) {
296                throw new HttpException( "status code: " + pm.getStatusCode() );
297            }
298            return pm;
299        }
300    
301        /**
302         * 
303         * @param url
304         *            e.g. http://localhost:8080/deegree/services
305         * @param request
306         *            e.g. service=WMS&request=GetCapabilities
307         * @param timeout
308         *            timeout in milliseconds
309         * @param user
310         *            (can be <code>null</code>)
311         * @param password
312         *            (can be <code>null</code>)
313         * @param header
314         * @return result of http get request
315         * @throws HttpException
316         * @throws IOException
317         */
318        public static HttpMethod performHttpGet( String url, String request, int timeout, String user, String password,
319                                                 Map<String, String> header )
320                                throws HttpException, IOException {
321            if ( request != null && request.startsWith( "&" ) ) {
322                request = request.substring( 1 );
323            }
324            if ( url != null && url.endsWith( "?" ) ) {
325                url = url.substring( 0, url.length() - 1 );
326            }
327            LOG.logDebug( "HTTP GET URL: ", url );
328            LOG.logDebug( "HTTP GET request: ", request );
329            GetMethod gm = null;
330            if ( url.indexOf( '?' ) > -1 && request != null ) {
331                gm = new GetMethod( StringTools.concat( 500, url, '&', request ) );
332            } else if ( request != null && !request.startsWith( "http://" ) ) {
333                gm = new GetMethod( StringTools.concat( 500, url, '?', request ) );
334            } else if ( request != null && request.startsWith( "http://" ) ) {
335                gm = new GetMethod( request );
336            } else {
337                gm = new GetMethod( url );
338            }
339    
340            if ( header != null ) {
341                Iterator<String> iter = header.keySet().iterator();
342                while ( iter.hasNext() ) {
343                    String key = (String) iter.next();
344                    if ( !"content-length".equalsIgnoreCase( key ) ) {
345                        gm.addRequestHeader( new Header( key, header.get( key ) ) );
346                    }
347    
348                }
349            }
350    
351            setHTTPCredentials( gm, user, password );
352    
353            HttpClient client = new HttpClient();
354            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
355            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
356            WebUtils.enableProxyUsage( client, new URL( url ) );
357            client.executeMethod( gm );
358            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
359                LOG.logDebug( gm.getResponseBodyAsString() );
360            }
361            if ( gm.getStatusCode() != 200 ) {
362                throw new HttpException( "status code: " + gm.getStatusCode() );
363            }
364            return gm;
365        }
366    
367        /**
368         * 
369         * @param url
370         * @param user
371         * @param password
372         * @param sessionID
373         * @return URL with attached authentication information (if not null)
374         */
375        public static String addAuthenticationForKVP( String url, String user, String password, String sessionID ) {
376            if ( sessionID != null && sessionID.trim().length() > 0 ) {
377                url = url + "&sessionID=" + sessionID;
378            } else if ( user != null ) {
379                url = url + "&user=" + user;
380                if ( password == null ) {
381                    password = "";
382                }
383                url = url + "&password=" + password;
384            }
385            return url;
386        }
387    
388        /**
389         * 
390         * @param xml
391         * @param user
392         * @param password
393         * @param sessionID
394         * @return XML document with authentication information (if not null) as attributes of the root element
395         */
396        public static XMLFragment addAuthenticationForXML( XMLFragment xml, String user, String password, String sessionID ) {
397            if ( sessionID != null ) {
398                xml.getRootElement().setAttribute( "sessionID", sessionID );
399            } else if ( user != null ) {
400                xml.getRootElement().setAttribute( "user", user );
401                if ( password != null ) {
402                    xml.getRootElement().setAttribute( "password", password );
403                }
404            }
405            return xml;
406        }
407    
408        /**
409         * 
410         * @param url
411         * @return URL as String with protocol and path but without request params
412         * @throws URISyntaxException
413         */
414        public static String normalizeURL( URL url ) {
415            String pr = url.getProtocol();
416            String ho = url.getHost();
417            int po = url.getPort();
418            String pa = url.getPath();
419            String s = pr + "://" + ho + ':' + po;
420            if ( pa != null && pa.length() > 0 ) {
421                s += pa;
422            }
423            return s;
424        }
425    
426        /**
427         * 
428         * @param url
429         * @return URL as String with protocol and path but without request params
430         * @throws URISyntaxException
431         */
432        public static String normalizeURL( String url ) {
433            try {
434                return normalizeURL( new URL( url ) );
435            } catch ( MalformedURLException e ) {
436                LOG.logWarning( e.getMessage(), e );
437            }
438            return url;
439        }
440    
441        private static void setHTTPCredentials( HttpMethod m, String user, String password ) {
442            if ( user != null ) {
443                if ( password == null ) {
444                    password = "";
445                }
446                String s = new String( Base64.encodeBase64( ( user + ":" + password ).getBytes() ) );
447                m.setRequestHeader( "authorization", "Basic " + s );
448            }
449        }
450    
451    }