001    //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/portal/wac/WAClient.java $
002    /*----------------    FILE HEADER  ------------------------------------------
003    
004     This file is part of deegree.
005     Copyright (C) 2001-2008 by:
006     University of Bonn
007     http://www.giub.uni-bonn.de/deegree/
008     lat/lon GmbH
009     http://www.lat-lon.de
010    
011     This library is free software; you can redistribute it and/or
012     modify it under the terms of the GNU Lesser General Public
013     License as published by the Free Software Foundation; either
014     version 2.1 of the License, or (at your option) any later version.
015    
016     This library is distributed in the hope that it will be useful,
017     but WITHOUT ANY WARRANTY; without even the implied warranty of
018     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
019     Lesser General Public License for more details.
020    
021     You should have received a copy of the GNU Lesser General Public
022     License along with this library; if not, write to the Free Software
023     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
024    
025     Contact:
026    
027     Andreas Poth
028     lat/lon GmbH
029     Aennchenstr. 19
030     53115 Bonn
031     Germany
032     E-Mail: poth@lat-lon.de
033    
034     Klaus Greve
035     Department of Geography
036     University of Bonn
037     Meckenheimer Allee 166
038     53115 Bonn
039     Germany
040     E-Mail: klaus.greve@uni-bonn.de
041    
042     ---------------------------------------------------------------------------*/
043    package org.deegree.portal.wac;
044    
045    import java.io.BufferedReader;
046    import java.io.IOException;
047    import java.io.InputStream;
048    import java.io.InputStreamReader;
049    import java.net.URL;
050    import java.net.URLEncoder;
051    import java.net.UnknownHostException;
052    
053    import org.apache.commons.httpclient.Header;
054    import org.apache.commons.httpclient.HeaderElement;
055    import org.apache.commons.httpclient.HttpClient;
056    import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
057    import org.apache.commons.httpclient.methods.GetMethod;
058    import org.apache.commons.httpclient.protocol.Protocol;
059    import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
060    import org.deegree.enterprise.WebUtils;
061    import org.deegree.framework.util.CharsetUtils;
062    import org.deegree.framework.xml.XMLFragment;
063    import org.w3c.dom.Document;
064    import org.xml.sax.SAXException;
065    
066    /**
067     * The class offers methods to enable a using program/class to act as a client to a Web Security
068     * Service (WSS) as specified in GDI-NRW. This implementation just supports authentication through
069     * sessionIDs and user/password. If other authentication mechanisms are needed this class should be
070     * extended by defining additional <tt>performDoService</tt> methods.
071     * 
072     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
073     * @author last edited by: $Author: apoth $
074     * 
075     * @version $Revision: 9346 $, $Date: 2007-12-27 17:39:07 +0100 (Do, 27 Dez 2007) $
076     */
077    public class WAClient {
078    
079        private String host = null;
080    
081        private String path = null;
082    
083        private int port = 443;
084    
085        private String contentType = null;
086    
087        /**
088         * The constructor assumes that the the certificate to be used is set by starting the java VM
089         * using -Djavax.net.ssl.trustStore parameter. The port to be used is set to SSL standard 443
090         * 
091         * @param host
092         * @param path
093         */
094        public WAClient( String host, String path ) {
095            this( host, path, 443 );
096        }
097    
098        /**
099         * The constructor assumes that the the certificate to be used is set by starting the java VM
100         * using -Djavax.net.ssl.trustStore parameter.
101         * 
102         * @param host
103         * @param path
104         * @param port
105         */
106        public WAClient( String host, String path, int port ) {
107            this( host, path, port, null );
108        }
109    
110        /**
111         * 
112         * @param host
113         * @param path
114         * @param port
115         * @param trustStore
116         */
117        public WAClient( String host, String path, int port, String trustStore ) {
118            this.host = host;
119            this.port = port;
120            this.path = path;
121            if ( trustStore != null ) {
122                System.setProperty( "javax.net.ssl.trustStore", trustStore );
123            }
124        }
125    
126        /**
127         * returns the name of the content type of the result to the last performed request
128         * 
129         * @return name of the content type
130         */
131        public String getContentType() {
132            return contentType;
133        }
134    
135        private void extractContentType( Header header ) {
136            // code taken from deegree1:
137            if ( header != null ) {
138                HeaderElement[] element = header.getElements();
139                if ( element != null && element.length > 0 ) {
140                    this.contentType = element[0].getValue();
141                }
142            }
143        }
144    
145        /**
146         * performs a GetCapabilities request against the WSS that is assigned to a client
147         * 
148         * @return Capabilities document if request was successful otherwise an exception document will
149         *         be returned
150         * @throws WACException
151         */
152        public Document performGetCapabilities()
153                                throws WACException {
154            Document doc;
155            try {
156                StringBuffer sb = new StringBuffer( 200 );
157                sb.append( path ).append( "?service=WSS&request=GetCapabilities&version=1.0.0" );
158                HttpClient httpclient = new HttpClient();
159                httpclient = WebUtils.enableProxyUsage( httpclient, new URL( path ) );
160                EasySSLProtocolSocketFactory fac = new EasySSLProtocolSocketFactory();
161                Protocol myhttps = new Protocol( "https", (ProtocolSocketFactory) fac, port );
162                httpclient.getHostConfiguration().setHost( host, port, myhttps );
163                GetMethod httpget = new GetMethod( sb.toString() );
164                httpclient.executeMethod( httpget );
165                extractContentType( httpget.getResponseHeader( "" ) );
166    
167                XMLFragment xml = new XMLFragment();
168                InputStream is = httpget.getResponseBodyAsStream();
169                xml.load( is, path );
170                is.close();
171                doc = xml.getRootElement().getOwnerDocument();
172            } catch ( IOException e ) {
173                throw new WACException( "can not access WSS", e );
174            } catch ( SAXException e ) {
175                throw new WACException( "could not parse result from WSS GetCapabilities request", e );
176            }
177            return doc;
178        }
179    
180        /**
181         * performs a GetSession request against the WSS that is assigned to a client. The method
182         * assumed that user/password (urn:x-gdi-nrw:authnMethod:1.0:password) is used for authentication
183         * 
184         * @param user
185         *            name of the user who like to get a session
186         * @param password
187         *            password of the user
188         * @return GetSession result string if request was successful, otherwise ?
189         * @throws WACException
190         */
191        public String performGetSession( String user, String password )
192                                throws WACException {
193            String s = null;
194            try {
195                StringBuffer sb = new StringBuffer( 200 );
196                sb.append( path ).append( "?service=WSS&request=GetSession&version=1.0.0&" );
197                sb.append( "AUTHMETHOD=urn:x-gdi-nrw:authnMethod:1.0:password&" );
198                sb.append( "CREDENTIALS=" ).append( user ).append( ',' ).append( password );
199    
200                HttpClient httpclient = new HttpClient();
201                httpclient = WebUtils.enableProxyUsage( httpclient, new URL( path ) );
202                EasySSLProtocolSocketFactory fac = new EasySSLProtocolSocketFactory();
203                Protocol myhttps = new Protocol( "https", (ProtocolSocketFactory) fac, port );
204                httpclient.getHostConfiguration().setHost( host, port, myhttps );
205                GetMethod httpget = new GetMethod( sb.toString() );
206                httpclient.executeMethod( httpget );
207                extractContentType( httpget.getResponseHeader( "" ) );
208    
209                InputStream is = httpget.getResponseBodyAsStream();
210                InputStreamReader ireader = new InputStreamReader( is );
211                BufferedReader br = new BufferedReader( ireader );
212                StringBuffer sb2 = new StringBuffer( 5000 );
213                while ( ( s = br.readLine() ) != null ) {
214                    sb2.append( s );
215                }
216                s = sb2.toString();
217                br.close();            
218            } catch ( UnknownHostException e ) {
219                throw new WACException( "Host: " + host + " is not known. Host must be set without protocol", e );
220            } catch ( IOException e ) {
221                throw new WACException( "can not access WSS", e );
222            }
223            return s;
224        }
225    
226        /**
227         * closes a Session by sending a CloseSession request against the WSS that is assigned to a
228         * client. If the passed sessionID is not valid an WSS exception document will be returned
229         * instead of the success message/answer.
230         * 
231         * @param sessionID
232         * @return document that indicates that session has been closed otherwise an exception document
233         *         will be returned
234         * @throws WACException
235         */
236        public Document performCloseSession( String sessionID )
237                                throws WACException {
238            Document doc;
239            try {
240                StringBuffer sb = new StringBuffer( 200 );
241                sb.append( path ).append( "?service=WSS&request=CloseSession&version=1.0.0&" );
242                sb.append( "SESSIONID=" ).append( sessionID );
243                HttpClient httpclient = new HttpClient();
244                httpclient = WebUtils.enableProxyUsage( httpclient, new URL( path ) );
245                EasySSLProtocolSocketFactory fac = new EasySSLProtocolSocketFactory();
246                Protocol myhttps = new Protocol( "https", (ProtocolSocketFactory) fac, port );
247                httpclient.getHostConfiguration().setHost( host, port, myhttps );
248                GetMethod httpget = new GetMethod( sb.toString() );
249                httpclient.executeMethod( httpget );
250                extractContentType( httpget.getResponseHeader( "" ) );
251                XMLFragment xml = new XMLFragment();
252                InputStream is = httpget.getResponseBodyAsStream();
253                xml.load( is, path );
254                is.close();
255                doc = xml.getRootElement().getOwnerDocument();
256            } catch ( IOException e ) {
257                throw new WACException( "can not access WSS", e );
258            } catch ( SAXException e ) {
259                throw new WACException( "could not parse result from WSS GetCapabilities request", e );
260            }
261            return doc;
262        }
263    
264        /**
265         * performs a DoService request against the WSS that is assigned to a client. According to the
266         * WSS specification the request will be send using HTTP POST.<BR>
267         * The method uses a user/password authentification
268         * 
269         * @see #performDoService(String, String)
270         * 
271         * @param request
272         *            request to perform
273         * @param user
274         *            name of the user who like to get a session
275         * @param password
276         *            password of the user
277         * @return result of the passed request. the type depends on target service and request
278         * @throws WACException
279         */
280        public InputStream performDoService( String request, String user, String password )
281                                throws WACException {
282            InputStream is = null;
283            try {
284                StringBuffer sb = new StringBuffer( 2000 );
285                sb.append( path ).append( "?service=WSS&request=DoService&version=1.0.0&" );
286                sb.append( "AUTHMETHOD=USERPASSWORD&" );
287                sb.append( "CREDENTIALS=" ).append( user ).append( ';' ).append( password );
288                sb.append( "&SERVICEREQUEST=" ).append( URLEncoder.encode( request, CharsetUtils.getSystemCharset() ) );
289                HttpClient httpclient = new HttpClient();
290                httpclient = WebUtils.enableProxyUsage( httpclient, new URL( path ) );
291                EasySSLProtocolSocketFactory fac = new EasySSLProtocolSocketFactory();
292                Protocol myhttps = new Protocol( "https", (ProtocolSocketFactory) fac, port );
293                httpclient.getHostConfiguration().setHost( host, port, myhttps );
294                GetMethod httpget = new GetMethod( sb.toString() );
295                httpclient.executeMethod( httpget );
296                extractContentType( httpget.getResponseHeader( "" ) );
297                is = httpget.getResponseBodyAsStream();
298            } catch ( IOException e ) {
299                throw new WACException( "can not access WSS", e );
300            }
301            return is;
302        }
303    
304        /**
305         * performs a DoService request against the WSS that is assigned to a client. According to the
306         * WSS specification the request will be send using HTTP POST.<BR>
307         * The method uses an authentification through a sessionID
308         * 
309         * @see #performDoService(String, String, String)
310         * 
311         * @param request
312         *            request to perform
313         * @param sessionID
314         *            id to authentificate a user
315         * @return result of the passed request. the type depends on target service and request
316         * @throws WACException
317         */
318        public InputStream performDoService( String request, String sessionID )
319                                throws WACException {
320            InputStream is = null;
321            try {
322                StringBuffer sb = new StringBuffer( 2000 );
323                sb.append( path ).append( "?service=WSS&request=DoService&version=1.0.0&" );
324                sb.append( "AUTHMETHOD=urn:x-gdi-nrw:authnMethod:1.0:session&" );
325                sb.append( "DCP=http_get&" );
326                sb.append( "CREDENTIALS=" ).append( sessionID ).append( "&" );
327                sb.append( "SERVICEREQUEST=" ).append( URLEncoder.encode( request, CharsetUtils.getSystemCharset() ) );
328                
329                HttpClient httpclient = new HttpClient();
330                httpclient = WebUtils.enableProxyUsage( httpclient, new URL( path ) );
331                EasySSLProtocolSocketFactory fac = new EasySSLProtocolSocketFactory();            
332                Protocol myhttps = new Protocol( "https", (ProtocolSocketFactory) fac, port );
333                httpclient.getHostConfiguration().setHost( host, port, myhttps );
334                GetMethod httpget = new GetMethod( sb.toString() );
335                httpclient.executeMethod( httpget );
336                extractContentType( httpget.getResponseHeader( "" ) );
337                is = httpget.getResponseBodyAsStream();
338            } catch ( IOException e ) {
339                throw new WACException( "can not access WSS", e );
340            }
341            return is;
342        }
343    
344    }