001    //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/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: 27357 $, $Date: 2010-10-18 18:06:09 +0200 (Mo, 18 Okt 2010) $
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            HttpClient client = new HttpClient();
263            URL tmp = new URL( url );
264            WebUtils.enableProxyUsage( client, tmp );
265            url = tmp.toExternalForm();
266            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
267            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
268            PostMethod pm = new PostMethod( url );
269    
270            ByteArrayOutputStream bos = new ByteArrayOutputStream( 1000000 );
271            Properties props = new Properties();
272            props.put( OutputKeys.ENCODING, "UTF-8" );
273            content.write( bos, props );
274    
275            pm.setRequestEntity( new ByteArrayRequestEntity( bos.toByteArray(), "text/xml" ) );
276    
277            if ( header != null ) {
278                Iterator<String> iter = header.keySet().iterator();
279                while ( iter.hasNext() ) {
280                    String key = (String) iter.next();
281                    if ( !"content-length".equalsIgnoreCase( key ) ) {
282                        pm.addRequestHeader( new Header( key, header.get( key ) ) );
283                    }
284                }
285            }
286            pm.addRequestHeader( new Header( "content-length", Integer.toString( bos.toByteArray().length ) ) );
287            bos.close();
288    
289            setHTTPCredentials( pm, user, password );
290            client.executeMethod( pm );
291            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
292                LOG.logDebug( pm.getResponseBodyAsString() );
293            }
294            if ( pm.getStatusCode() != 200 ) {
295                throw new HttpException( "status code: " + pm.getStatusCode() );
296            }
297            return pm;
298        }
299    
300        /**
301         * 
302         * @param url
303         *            e.g. http://localhost:8080/deegree/services
304         * @param request
305         *            e.g. service=WMS&request=GetCapabilities
306         * @param timeout
307         *            timeout in milliseconds
308         * @param user
309         *            (can be <code>null</code>)
310         * @param password
311         *            (can be <code>null</code>)
312         * @param header
313         * @return result of http get request
314         * @throws HttpException
315         * @throws IOException
316         */
317        public static HttpMethod performHttpGet( String url, String request, int timeout, String user, String password,
318                                                 Map<String, String> header )
319                                throws HttpException, IOException {
320            if ( request != null && request.startsWith( "&" ) ) {
321                request = request.substring( 1 );
322            }
323            if ( url != null && url.endsWith( "?" ) ) {
324                url = url.substring( 0, url.length() - 1 );
325            }
326            LOG.logDebug( "HTTP GET URL: ", url );
327            LOG.logDebug( "HTTP GET request: ", request );
328            GetMethod gm = null;
329            if ( url.indexOf( '?' ) > -1 && request != null ) {
330                gm = new GetMethod( StringTools.concat( 500, url, '&', request ) );
331            } else if ( request != null && !request.startsWith( "http://" ) ) {
332                gm = new GetMethod( StringTools.concat( 500, url, '?', request ) );
333            } else if ( request != null && request.startsWith( "http://" ) ) {
334                gm = new GetMethod( request );
335            } else {
336                gm = new GetMethod( url );
337            }
338    
339            if ( header != null ) {
340                Iterator<String> iter = header.keySet().iterator();
341                while ( iter.hasNext() ) {
342                    String key = (String) iter.next();
343                    if ( !"content-length".equalsIgnoreCase( key ) ) {
344                        gm.addRequestHeader( new Header( key, header.get( key ) ) );
345                    }
346    
347                }
348            }
349    
350            setHTTPCredentials( gm, user, password );
351    
352            HttpClient client = new HttpClient();
353            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
354            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
355            WebUtils.enableProxyUsage( client, new URL( url ) );
356            client.executeMethod( gm );
357            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
358                LOG.logDebug( gm.getResponseBodyAsString() );
359            }
360            if ( gm.getStatusCode() != 200 ) {
361                throw new HttpException( "status code: " + gm.getStatusCode() );
362            }
363            return gm;
364        }
365    
366        /**
367         * 
368         * @param url
369         * @param user
370         * @param password
371         * @param sessionID
372         * @return URL with attached authentication information (if not null)
373         */
374        public static String addAuthenticationForKVP( String url, String user, String password, String sessionID ) {
375            if ( sessionID != null && sessionID.trim().length() > 0 ) {
376                url = url + "&sessionID=" + sessionID;
377            } else if ( user != null ) {
378                url = url + "&user=" + user;
379                if ( password == null ) {
380                    password = "";
381                }
382                url = url + "&password=" + password;
383            }
384            return url;
385        }
386    
387        /**
388         * 
389         * @param xml
390         * @param user
391         * @param password
392         * @param sessionID
393         * @return XML document with authentication information (if not null) as attributes of the root element
394         */
395        public static XMLFragment addAuthenticationForXML( XMLFragment xml, String user, String password, String sessionID ) {
396            if ( sessionID != null ) {
397                xml.getRootElement().setAttribute( "sessionID", sessionID );
398            } else if ( user != null ) {
399                xml.getRootElement().setAttribute( "user", user );
400                if ( password != null ) {
401                    xml.getRootElement().setAttribute( "password", password );
402                }
403            }
404            return xml;
405        }
406    
407        /**
408         * 
409         * @param url
410         * @return URL as String with protocol and path but without request params
411         * @throws URISyntaxException
412         */
413        public static String normalizeURL( URL url ) {
414            String pr = url.getProtocol();
415            String ho = url.getHost();
416            int po = url.getPort();
417            String pa = url.getPath();
418            String s = pr + "://" + ho + ':' + po;
419            if ( pa != null && pa.length() > 0 ) {
420                s += pa;
421            }
422            return s;
423        }
424    
425        /**
426         * 
427         * @param url
428         * @return URL as String with protocol and path but without request params
429         * @throws URISyntaxException
430         */
431        public static String normalizeURL( String url ) {
432            try {
433                return normalizeURL( new URL( url ) );
434            } catch ( MalformedURLException e ) {
435                LOG.logWarning( e.getMessage(), e );
436            }
437            return url;
438        }
439    
440        private static void setHTTPCredentials( HttpMethod m, String user, String password ) {
441            if ( user != null ) {
442                if ( password == null ) {
443                    password = "";
444                }
445                String s = new String( Base64.encodeBase64( ( user + ":" + password ).getBytes() ) );
446                m.setRequestHeader( "authorization", "Basic " + s );
447            }
448        }
449    
450    }