001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_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.Map;
050    import java.util.Properties;
051    
052    import javax.xml.transform.OutputKeys;
053    
054    import org.apache.commons.codec.binary.Base64;
055    import org.apache.commons.httpclient.HttpClient;
056    import org.apache.commons.httpclient.HttpException;
057    import org.apache.commons.httpclient.HttpMethod;
058    import org.apache.commons.httpclient.methods.ByteArrayRequestEntity;
059    import org.apache.commons.httpclient.methods.GetMethod;
060    import org.apache.commons.httpclient.methods.HeadMethod;
061    import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
062    import org.apache.commons.httpclient.methods.PostMethod;
063    import org.apache.commons.httpclient.methods.StringRequestEntity;
064    import org.deegree.enterprise.WebUtils;
065    import org.deegree.framework.log.ILogger;
066    import org.deegree.framework.log.LoggerFactory;
067    import org.deegree.framework.xml.XMLFragment;
068    
069    /**
070     * utility class for performing HTTP requests
071     * 
072     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
073     * @author last edited by: $Author: apoth $
074     * 
075     * @version. $Revision: 25236 $, $Date: 2010-07-09 11:29:33 +0200 (Fr, 09. Jul 2010) $
076     */
077    public class HttpUtils {
078    
079        private static final ILogger LOG = LoggerFactory.getLogger( HttpUtils.class );
080    
081        /**
082         * validates passed URL. If it is not a valid URL or a client can not connect to it an exception will be thrown
083         * 
084         * @param url
085         * @throws IOException
086         */
087        public static int validateURL( String url )
088                                throws IOException {
089            return validateURL( url, null, null );
090        }
091    
092        /**
093         * validates passed URL. If it is not a valid URL or a client can not connect to it an exception will be thrown
094         * 
095         * @param url
096         * @param user
097         * @param password
098         * @throws IOException
099         */
100        public static int validateURL( String url, String user, String password )
101                                throws IOException {
102            if ( url.startsWith( "http:" ) ) {
103                URL tmp = new URL( url );
104                HeadMethod hm = new HeadMethod( url );
105                setHTTPCredentials( hm, user, password );
106                InetAddress.getByName( tmp.getHost() );
107                HttpClient client = new HttpClient();
108                client.executeMethod( hm );
109                if ( hm.getStatusCode() != HttpURLConnection.HTTP_OK ) {
110                    if ( hm.getStatusCode() != HttpURLConnection.HTTP_UNAUTHORIZED && hm.getStatusCode() != 401 ) {
111                        // this method just evaluates if a URL/host is valid; it does not takes care
112                        // if authorization is available/valid
113                        throw new IOException( "Host " + tmp.getHost() + " of URL + " + url + " does not exists" );
114                    }
115                }
116                return hm.getStatusCode();
117            } else if ( url.startsWith( "file:" ) ) {
118                URL tmp = new URL( url );
119                InputStream is = tmp.openStream();
120                is.close();
121                return 200;
122            }
123            return HttpURLConnection.HTTP_UNAVAILABLE;
124        }
125    
126        /**
127         * 
128         * @param url
129         * @param content
130         * @param timeout
131         *            timeout in milliseconds
132         * @param user
133         *            (can be <code>null</code>)
134         * @param password
135         *            (can be <code>null</code>)
136         * @param contentType
137         *            request content mime type (can be <code>null</code>)
138         * @param encoding
139         *            request encoding (can be <code>null</code>)
140         * @param header
141         *            not supported yet
142         * @return result of http post request
143         * @throws HttpException
144         * @throws IOException
145         */
146        public static HttpMethod performHttpPost( String url, InputStream content, int timeout, String user,
147                                                  String password, String contentType, String encoding,
148                                                  Map<String, String> header )
149                                throws HttpException, IOException {
150            HttpClient client = new HttpClient();
151            URL tmp = new URL( url );
152            WebUtils.enableProxyUsage( client, tmp );
153            url = tmp.toExternalForm();
154            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
155            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
156    
157            PostMethod pm = new PostMethod( url );
158            String ct = contentType;
159            if ( ct != null && encoding != null ) {
160                ct += ( "; " + encoding );
161            }
162            if ( ct != null ) {
163                pm.setRequestEntity( new InputStreamRequestEntity( content, ct ) );
164            } else {
165                pm.setRequestEntity( new InputStreamRequestEntity( content ) );
166            }
167    
168            setHTTPCredentials( pm, user, password );
169            client.executeMethod( pm );
170            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
171                LOG.logDebug( pm.getResponseBodyAsString() );
172            }
173            if ( pm.getStatusCode() != 200 ) {
174                throw new HttpException( "status code: " + pm.getStatusCode() );
175            }
176            return pm;
177        }
178    
179        /**
180         * 
181         * @param url
182         * @param content
183         * @param timeout
184         *            timeout in milliseconds
185         * @param user
186         *            (can <code>null</code>)
187         * @param password
188         *            (can <code>null</code>)
189         * @param contentType
190         *            request content mime type (can be <code>null</code>)
191         * @param encoding
192         *            request encoding (can be <code>null</code>)
193         * @param header
194         *            not supported yet
195         * @return result of http post request
196         * @throws HttpException
197         * @throws IOException
198         */
199        public static HttpMethod performHttpPost( String url, String content, int timeout, String user, String password,
200                                                  String contentType, String encoding, Map<String, String> header )
201                                throws HttpException, IOException {
202            HttpClient client = new HttpClient();
203            URL tmp = new URL( url );
204            WebUtils.enableProxyUsage( client, tmp );
205            url = tmp.toExternalForm();
206            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
207            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
208            PostMethod pm = new PostMethod( url );
209    
210            pm.setRequestEntity( new StringRequestEntity( content, contentType, encoding ) );
211    
212            setHTTPCredentials( pm, user, password );
213            client.executeMethod( pm );
214            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
215                LOG.logDebug( pm.getResponseBodyAsString() );
216            }
217            if ( pm.getStatusCode() != 200 ) {
218                throw new HttpException( "status code: " + pm.getStatusCode() );
219            }
220            return pm;
221        }
222        
223        /**
224         * 
225         * @param url
226         * @param content
227         * @param timeout
228         *            timeout in milliseconds
229         * @param user
230         *            (can <code>null</code>)
231         * @param password
232         *            (can <code>null</code>)
233         * @param header
234         *            not supported yet
235         * @return result of http post request
236         * @throws HttpException
237         * @throws IOException
238         */
239        public static HttpMethod performHttpPost( String url, XMLFragment content, int timeout, String user, String password,
240                                                  Map<String, String> header )
241                                throws HttpException, IOException {
242            HttpClient client = new HttpClient();
243            URL tmp = new URL( url );
244            WebUtils.enableProxyUsage( client, tmp );
245            url = tmp.toExternalForm();
246            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
247            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
248            PostMethod pm = new PostMethod( url );
249    
250            ByteArrayOutputStream bos = new ByteArrayOutputStream( 1000000 );
251            Properties props = new Properties();
252            props.put( OutputKeys.ENCODING, "UTF-8" );
253            content.write( bos, props );
254            bos.close();
255            pm.setRequestEntity( new ByteArrayRequestEntity( bos.toByteArray(), "text/xml" ) );
256    
257            setHTTPCredentials( pm, user, password );
258            client.executeMethod( pm );
259            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
260                LOG.logDebug( pm.getResponseBodyAsString() );
261            }
262            if ( pm.getStatusCode() != 200 ) {
263                throw new HttpException( "status code: " + pm.getStatusCode() );
264            }
265            return pm;
266        }
267    
268        /**
269         * 
270         * @param url
271         *            e.g. http://localhost:8080/deegree/services
272         * @param request
273         *            e.g. service=WMS&request=GetCapabilities
274         * @param timeout
275         *            timeout in milliseconds
276         * @param user
277         *            (can be <code>null</code>)
278         * @param password
279         *            (can be <code>null</code>)
280         * @param header
281         *            (not supported yet)
282         * @return result of http get request
283         * @throws HttpException
284         * @throws IOException
285         */
286        public static HttpMethod performHttpGet( String url, String request, int timeout, String user, String password,
287                                                 Map<String, String> header )
288                                throws HttpException, IOException {
289            if ( request != null && request.startsWith( "&" ) ) {
290                request = request.substring( 1 );
291            }
292            if ( url != null && url.endsWith( "?" ) ) {
293                url = url.substring( 0, url.length() - 1 );
294            }
295            LOG.logDebug( "HTTP GET URL: ", url );
296            LOG.logDebug( "HTTP GET request: ", request );
297            GetMethod gm = null;
298            if ( url.indexOf( '?' ) > -1 && request != null ) {
299                gm = new GetMethod( StringTools.concat( 500, url, '&', request ) );
300            } else if ( request != null && !request.startsWith( "http://" ) ) {
301                gm = new GetMethod( StringTools.concat( 500, url, '?', request ) );
302            } else if ( request != null && request.startsWith( "http://" ) ) {
303                gm = new GetMethod( request );
304            } else {
305                gm = new GetMethod( url );
306            }
307    
308            setHTTPCredentials( gm, user, password );
309    
310            HttpClient client = new HttpClient();
311            client.getHttpConnectionManager().getParams().setSoTimeout( timeout );
312            client.getHttpConnectionManager().getParams().setConnectionTimeout( timeout );
313            WebUtils.enableProxyUsage( client, new URL( url ) );
314            client.executeMethod( gm );
315            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
316                LOG.logDebug( gm.getResponseBodyAsString() );
317            }
318            if ( gm.getStatusCode() != 200 ) {
319                throw new HttpException( "status code: " + gm.getStatusCode() );
320            }
321            return gm;
322        }
323    
324        /**
325         * 
326         * @param url
327         * @param user
328         * @param password
329         * @param sessionID
330         * @return URL with attached authentication information (if not null)
331         */
332        public static String addAuthenticationForKVP( String url, String user, String password, String sessionID ) {
333            if ( sessionID != null && sessionID.trim().length() > 0 ) {
334                url = url + "&sessionID=" + sessionID;
335            } else if ( user != null ) {
336                url = url + "&user=" + user;
337                if ( password == null ) {
338                    password = "";
339                }
340                url = url + "&password=" + password;
341            }
342            return url;
343        }
344    
345        /**
346         * 
347         * @param xml
348         * @param user
349         * @param password
350         * @param sessionID
351         * @return XML document with authentication information (if not null) as attributes of the root element
352         */
353        public static XMLFragment addAuthenticationForXML( XMLFragment xml, String user, String password, String sessionID ) {
354            if ( sessionID != null ) {
355                xml.getRootElement().setAttribute( "sessionID", sessionID );
356            } else if ( user != null ) {
357                xml.getRootElement().setAttribute( "user", user );
358                if ( password != null ) {
359                    xml.getRootElement().setAttribute( "password", password );
360                }
361            }
362            return xml;
363        }
364    
365        /**
366         * 
367         * @param url
368         * @return URL as String with protocol and path but without request params
369         * @throws URISyntaxException
370         */
371        public static String normalizeURL( URL url ) {
372            String pr = url.getProtocol();
373            String ho = url.getHost();
374            int po = url.getPort();
375            String pa = url.getPath();
376            String s = pr + "://" + ho + ':' + po;
377            if ( pa != null && pa.length() > 0 ) {
378                s += pa;
379            }
380            return s;
381        }
382    
383        /**
384         * 
385         * @param url
386         * @return URL as String with protocol and path but without request params
387         * @throws URISyntaxException
388         */
389        public static String normalizeURL( String url ) {
390            try {
391                return normalizeURL( new URL( url ) );
392            } catch ( MalformedURLException e ) {
393                LOG.logWarning( e.getMessage(), e );
394            }
395            return url;
396        }
397    
398        private static void setHTTPCredentials( HttpMethod m, String user, String password ) {
399            if ( user != null ) {
400                if ( password == null ) {
401                    password = "";
402                }
403                String s = new String( Base64.encodeBase64( ( user + ":" + password ).getBytes() ) );
404                m.setRequestHeader( "authorization", "Basic " + s );
405            }
406        }
407    
408    }