KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > rift > coad > lib > httpd > HttpServiceHandler


1 /*
2  * CoadunationLib: The coaduntion implementation library.
3  * Copyright (C) 2006 Rift IT Contracting
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  *
19  * HttpServiceHandler.java
20  *
21  * This object is responsible for handling the HTTP service requests.
22  * It handles both WebService requests and the RMI class loader requests.
23  *
24  */

25
26 // package path
27
package com.rift.coad.lib.httpd;
28
29 // java imports
30
import java.io.ByteArrayOutputStream JavaDoc;
31 import java.io.File JavaDoc;
32 import java.io.IOException JavaDoc;
33 import java.net.Socket JavaDoc;
34 import java.net.URL JavaDoc;
35 import java.net.URLDecoder JavaDoc;
36 import java.util.Iterator JavaDoc;
37 import java.lang.reflect.Constructor JavaDoc;
38
39 // logging import
40
import org.apache.log4j.Logger;
41
42 // apache imports
43
import org.apache.http.HttpServerConnection;
44 import org.apache.http.protocol.HttpService;
45 import org.apache.http.HttpException;
46 import org.apache.http.HttpRequest;
47 import org.apache.http.HttpResponse;
48 import org.apache.http.Header;
49 import org.apache.http.HttpStatus;
50 import org.apache.http.HttpEntity;
51 import org.apache.http.entity.StringEntity;
52 import org.apache.http.entity.FileEntity;
53 import org.apache.http.message.BasicHttpEntityEnclosingRequest;
54 import org.apache.http.message.HttpPost;
55 import org.apache.http.params.HttpParams;
56
57
58 // axis libraries
59
import org.apache.axis.configuration.EngineConfigurationFactoryFinder;
60 import org.apache.axis.EngineConfiguration;
61 import org.apache.axis.AxisEngine;
62 import org.apache.axis.server.AxisServer;
63 import org.apache.axis.management.ServiceAdmin;
64 import org.apache.axis.Message;
65 import org.apache.axis.MessageContext;
66 import org.apache.axis.handlers.JAXRPCHandler;
67 import org.w3c.dom.Document JavaDoc;
68 import org.apache.axis.utils.XMLUtils;
69 import org.apache.axis.handlers.soap.SOAPService;
70 import org.apache.axis.providers.java.RPCProvider;
71 import org.apache.axis.constants.Scope;
72 import org.apache.http.Header;
73 import javax.xml.soap.MimeHeader JavaDoc;
74 import javax.xml.soap.MimeHeaders JavaDoc;
75 import javax.xml.soap.SOAPMessage JavaDoc;
76 import org.apache.axis.Constants;
77 import org.apache.axis.transport.http.NonBlockingBufferedInputStream;
78
79
80 // coadunation imports
81
import com.rift.coad.lib.configuration.Configuration;
82 import com.rift.coad.lib.configuration.ConfigurationFactory;
83 import com.rift.coad.lib.deployment.webservice.WebServiceConnector;
84 import com.rift.coad.lib.security.AuthorizationException;
85 import com.rift.coad.lib.security.UserSession;
86 import com.rift.coad.lib.security.Validator;
87 import com.rift.coad.lib.security.login.AuthenticationException;
88 import com.rift.coad.lib.security.login.SessionLogin;
89 import com.rift.coad.lib.security.login.handlers.PasswordInfoHandler;
90 import com.rift.coad.lib.security.sudo.Sudo;
91 import com.rift.coad.lib.security.sudo.SudoCallbackHandler;
92 import com.rift.coad.lib.security.user.UserSessionManager;
93 import com.rift.coad.lib.security.user.UserSessionManagerAccessor;
94 import com.rift.coad.lib.thread.BasicThread;
95 import com.rift.coad.lib.thirdparty.axis.AxisManager;
96 import com.rift.coad.lib.thirdparty.base64.Base64;
97 import com.rift.coad.lib.webservice.WebServiceWrapper;
98 import com.rift.coad.lib.webservice.WebServiceException;
99
100
101 /**
102  * This object is responsible for handling the HTTP service requests.
103  * It handles both the WebService requests and the RMI class loader requests.
104  *
105  * @author Brett Chaldecott
106  */

107 public class HttpServiceHandler extends HttpService
108         implements SudoCallbackHandler, RequestInterface {
109     
110     
111     // class static member variables
112
private final static String JavaDoc AUTH_HEADER = "Authorization";
113     private final static String JavaDoc CHALLENGE_HEADER = "WWW-Authenticate";
114     private final static String JavaDoc BASIC = "Basic";
115     private final static String JavaDoc SESSION_ID = "sessionid";
116     private final static String JavaDoc CODE_BASE = "/codebase/";
117     
118     // the private member variables
119
private Logger log =
120             Logger.getLogger(HttpServiceHandler.class.getName());
121     private Socket JavaDoc socket = null;
122     private HttpRequestCookieManager httpRequestCookieManager = null;
123     private String JavaDoc realm = null;
124     private HttpRequest request = null;
125     private HttpResponse response = null;
126     private String JavaDoc clientStubDir = null;
127     
128     
129     /**
130      * Creates a new instance of HttpServiceHandler
131      *
132      * @param conn The http server connection object.
133      * @param socket The socket that all the information is retrieved from.
134      * @param realm The security realm for the challange
135      */

136     public HttpServiceHandler(HttpServerConnection conn,Socket JavaDoc socket,
137             String JavaDoc realm) throws HttpException {
138         super(conn);
139         this.socket = socket;
140         this.realm = realm;
141         try {
142             Configuration config = ConfigurationFactory.getInstance().getConfig(
143                     HttpServiceHandler.class);
144             clientStubDir = config.getString("Client_Stub");
145         } catch (Exception JavaDoc ex) {
146             throw new HttpException("Failed to init the http service handler : "
147                     + ex.getMessage(),ex);
148         }
149         
150     }
151     
152     
153     /**
154      * This method is responsible for responding to the http server requests.
155      *
156      * @param request The object containing the request value.
157      * @param response The method that encloses the http response value.
158      * @exception HttpException
159      * @exception IOException
160      */

161     protected void doService(HttpRequest request, HttpResponse response)
162     throws HttpException, IOException JavaDoc {
163         try {
164             this.request = request;
165             this.response = response;
166             
167             // Here we check for a client stub code request.
168
log.debug("Received a requests");
169             String JavaDoc target = request.getRequestLine().getUri();
170             String JavaDoc filePath = URLDecoder.decode(target,MimeTypes.UTF_8);
171             if (filePath.indexOf(CODE_BASE) == 0) {
172                 returnClientStubCode(request, response, filePath);
173                 return;
174             }
175             
176             
177             // instanciate the HttpRequestCookieManager
178
httpRequestCookieManager = new
179                     HttpRequestCookieManager(request, response);
180             
181             // authenticate the user
182
if (sudoAndProcess() == false) {
183                 response.setStatusCode(HttpStatus.SC_UNAUTHORIZED);
184                 response.addHeader(new Header(CHALLENGE_HEADER,BASIC + " realm="
185                         + "\"" + realm + "\""));
186                 return;
187             }
188             
189         } catch (Exception JavaDoc ex) {
190             log.error("Failed to respond to the request : " + ex.getMessage(),
191                     ex);
192             response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
193             response.setEntity(new StringEntity("Internal server error [" +
194                         ex.getMessage() + "].","UTF-8"));
195         }
196     }
197     
198     /**
199      * This method returns the client stub code.
200      *
201      * @param request The request on the client.
202      * @param response The response to the client request.
203      * @param path The path to make the request on.
204      */

205     private void returnClientStubCode(HttpRequest request,
206             HttpResponse response, String JavaDoc path) throws HttpException {
207         try {
208             File JavaDoc file = new File JavaDoc(clientStubDir,path.substring(
209                     CODE_BASE.length() - 1));
210             if (!file.exists()) {
211                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);
212                 StringEntity body = new StringEntity("File not found [" +
213                         file.getPath() + "]","UTF-8");
214                 response.setEntity(body);
215                 return;
216             } else if (!file.canRead() || file.isDirectory()) {
217                 response.setStatusCode(HttpStatus.SC_FORBIDDEN);
218                 StringEntity body = new StringEntity("Access Denied","UTF-8");
219                 response.setEntity(body);
220                 return;
221             }
222             response.setStatusCode(HttpStatus.SC_OK);
223             FileEntity fileEntity = new FileEntity(file,
224                     "application/x-compressed");
225             response.setEntity(fileEntity);
226             log.info("Return the file [" + file.getPath() + "]");
227         } catch (Exception JavaDoc ex) {
228             log.error("Failed to retrieve the file : " +
229                     ex.getMessage(),ex);
230             throw new HttpException("Failed to retrieve the file : " +
231                     ex.getMessage(),ex);
232         }
233     }
234     
235     
236     /**
237      * This method is called to authenticate a user
238      *
239      * @exception HttpdException
240      */

241     private boolean sudoAndProcess() throws HttpdException {
242         
243         try {
244             // check for an active session
245
CookieWrapper cookieWrapper =
246                     httpRequestCookieManager.getCookie(SESSION_ID);
247             
248             // check if the session is valid
249
log.debug("Check for cookie [" + cookieWrapper + "]");
250             if (cookieWrapper != null) {
251                 String JavaDoc sessionId = cookieWrapper.getValue();
252                 log.info("Retrieve the session id [" + sessionId
253                         + "] from cookie.");
254                 try {
255                     UserSessionManagerAccessor.getInstance().
256                             getUserSessionManager().getSessionById(sessionId);
257                     Sudo.sudoThreadBySessionId(sessionId,this);
258                     return true;
259                 } catch (com.rift.coad.lib.security.user.UserException ex) {
260                     // ignore
261
}
262             }
263             
264             // check for auth
265
log.debug("Check for an auth header.");
266             if (request.containsHeader(AUTH_HEADER)) {
267                 log.info("Auth user.");
268                 Header header = request.getFirstHeader(AUTH_HEADER);
269                 if (!checkForBasic(header)) {
270                     return false;
271                 }
272                 String JavaDoc decodedValue = decodeHeader(header);
273                 String JavaDoc sessionId = authenticate(decodedValue);
274                 log.debug("Session id is [" + sessionId + "]");
275                 httpRequestCookieManager.addCookie(new CookieWrapper(
276                         SESSION_ID,sessionId));
277                 Sudo.sudoThreadBySessionId(sessionId,this);
278                 return true;
279             }
280             
281             // assuming that the user will run as a guest.
282
process();
283             return true;
284         } catch (AuthorizationException ex) {
285             log.error("Insufficiant permission [" + ex.getMessage() + "]",ex);
286             return false;
287         } catch (AuthenticationException ex) {
288             log.info("Authentication failed [" + ex.getMessage() + "]",ex);
289             return false;
290         } catch (Exception JavaDoc ex) {
291             throw new HttpdException("Failed to auth the user because : " +
292                     ex.getMessage(),ex);
293         }
294     }
295     
296     
297     /**
298      * This method performs the actuall processing of the request.
299      */

300     public void process() throws Exception JavaDoc {
301         
302         try {
303             // retrieve the file path
304
String JavaDoc target = request.getRequestLine().getUri();
305             String JavaDoc filePath = URLDecoder.decode(target,MimeTypes.UTF_8);
306             
307             // strip the file and look for question mark
308
String JavaDoc strippedFile = filePath;
309             int getParam = filePath.indexOf('?');
310             if (getParam != -1) {
311                 strippedFile = filePath.substring(0,getParam);
312             }
313             
314             // retrieve the web service
315
log.info("Find the file [" + strippedFile + "]");
316             WebServiceWrapper webServiceWrapper = (WebServiceWrapper)
317                     WebServiceConnector.getInstance().getService(strippedFile);
318             if (webServiceWrapper == null) {
319                 response.setStatusCode(HttpStatus.SC_NOT_FOUND);
320                 response.setEntity(new StringEntity("The Web Service [" +
321                         strippedFile + "] does not exist.",MimeTypes.UTF_8));
322                 return;
323             }
324             
325             // validate that we can call it
326
Validator.validate(this.getClass(),webServiceWrapper.getRole());
327             
328             // retrieve the request type
329
String JavaDoc method = request.getRequestLine().getMethod();
330             
331             if (method.equalsIgnoreCase("GET") &&
332                     getParam != -1 && (filePath.substring(getParam + 1).
333                 equalsIgnoreCase("wsdl"))){
334                 String JavaDoc result = webServiceWrapper.generateWSDL();
335                 StringEntity stringEntity = new StringEntity(result);
336                 stringEntity.setContentType(MimeTypes.XML);
337                 response.setEntity(stringEntity);
338                 return;
339             }
340             else if (request instanceof BasicHttpEntityEnclosingRequest) {
341                 BasicHttpEntityEnclosingRequest post =
342                         (BasicHttpEntityEnclosingRequest)request;
343                 HttpEntity entity = post.getEntity();
344                 
345                 // setup the mime headers
346
MimeHeaders JavaDoc mimeHeaders = new MimeHeaders JavaDoc();
347                 Header[] headerList = request.getAllHeaders();
348                 for (int i = 0; i < headerList.length; i++) {
349                     mimeHeaders.addHeader(headerList[i].getName(),
350                             headerList[i].getValue());
351                 }
352                 
353                 String JavaDoc result = webServiceWrapper.processRequest(
354                         entity.getContent(),mimeHeaders);
355                 StringEntity stringEntity = new StringEntity(result);
356                 stringEntity.setContentType(MimeTypes.XML);
357                 response.setEntity(stringEntity);
358                 return;
359             }
360             response.setStatusCode(HttpStatus.SC_BAD_REQUEST);
361             response.setEntity(new StringEntity("Unrecognised request",
362                     MimeTypes.UTF_8));
363         } catch (AuthorizationException ex) {
364             log.error("In sufficiant privaleges : " + ex.getMessage(),
365                     ex);
366             throw ex;
367         } catch (WebServiceException ex) {
368             log.error("Failed to process the soap request : " + ex.getMessage(),
369                     ex);
370             response.setStatusCode(HttpStatus.SC_INTERNAL_SERVER_ERROR);
371             StringEntity stringEntity = new StringEntity(ex.getMessage(),
372                     MimeTypes.UTF_8);
373             stringEntity.setContentEncoding(ex.getEncoding());
374             response.setEntity(stringEntity);
375             
376         } catch (Exception JavaDoc ex) {
377             log.error("Failed to process the soap request : " + ex.getMessage(),
378                     ex);
379             response.setStatusCode(HttpStatus.SC_NOT_FOUND);
380             response.setEntity(new StringEntity("Failed to invoke the request " +
381                     "because : " + ex.getMessage(),MimeTypes.UTF_8));
382         }
383     }
384     
385     
386     /**
387      * This method validates that a basic auth request has been made.
388      *
389      * @return TRUE if a basic auth request has been made, FALSE if not.
390      * @param authHeader The auth header to retrieve.
391      */

392     private boolean checkForBasic(Header authHeader) {
393         if (authHeader.getValue().toLowerCase().contains(BASIC.toLowerCase())) {
394             return true;
395         }
396         return false;
397     }
398     
399     
400     /**
401      * This method decodes the header.
402      *
403      * @return The string value of the decoded header.
404      * @param authHeader The header to containing the auth information.
405      */

406     private String JavaDoc decodeHeader(Header authHeader) {
407         String JavaDoc encodedValue = authHeader.getValue().trim();
408         String JavaDoc fullValue = encodedValue;
409         encodedValue = encodedValue.substring(encodedValue.indexOf(" ")).trim();
410         String JavaDoc decodedValue = new String JavaDoc(Base64.decode(encodedValue));
411         log.debug("Full value [" + fullValue + "] Encoded value ["
412                 + encodedValue + "] decoded value ["
413                 + decodedValue + "]");
414         return decodedValue;
415     }
416     
417     
418     /**
419      * This method uses the decoded header authenticate the user.
420      *
421      * @return The string containing the new session id.
422      * @param decodedHeaderValue The decoded header value containing the user
423      * name and password.
424      */

425     private String JavaDoc authenticate(String JavaDoc decodedHeaderValue)
426             throws AuthenticationException, HttpdException {
427         try {
428             log.debug("Decoded header value [" + decodedHeaderValue
429                     + "] colon value [" + decodedHeaderValue.indexOf(':')
430                     + "]");
431             // check for a traditional = seperator
432
String JavaDoc username = null;
433             String JavaDoc password = null;
434             int pos = decodedHeaderValue.indexOf('=');
435             if (pos != -1) {
436                 username = decodedHeaderValue.substring(0,pos);
437                 password = decodedHeaderValue.substring(pos + 1);
438                 
439             }
440             // check for a colon seperator
441
else if ((pos = decodedHeaderValue.indexOf(':')) != -1) {
442                 username = decodedHeaderValue.substring(0,pos).trim();
443                 password = decodedHeaderValue.substring(pos + 1).trim();
444             } else {
445                 throw new HttpdException("Authentication not recognised.");
446             }
447             
448             // authenticate
449
log.debug("User name [" + username + "] password [" + password + "]");
450             SessionLogin sessionLogin = new SessionLogin(
451                     new PasswordInfoHandler(username,password));
452             sessionLogin.login();
453             return sessionLogin.getUser().getSessionId();
454         } catch (AuthenticationException ex) {
455             throw ex;
456         } catch (Exception JavaDoc ex) {
457             throw new HttpdException("Failed to authenticate the user : " +
458                     ex.getMessage(),ex);
459         }
460     }
461 }
462
Popular Tags