KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openejb > server > ejbd > EjbRequestHandler


1 /**
2  * Redistribution and use of this software and associated documentation
3  * ("Software"), with or without modification, are permitted provided
4  * that the following conditions are met:
5  *
6  * 1. Redistributions of source code must retain copyright
7  * statements and notices. Redistributions must also contain a
8  * copy of this document.
9  *
10  * 2. Redistributions in binary form must reproduce the
11  * above copyright notice, this list of conditions and the
12  * following disclaimer in the documentation and/or other
13  * materials provided with the distribution.
14  *
15  * 3. The name "OpenEJB" must not be used to endorse or promote
16  * products derived from this Software without prior written
17  * permission of The OpenEJB Group. For written permission,
18  * please contact dev@openejb.org.
19  *
20  * 4. Products derived from this Software may not be called "OpenEJB"
21  * nor may "OpenEJB" appear in their names without prior written
22  * permission of The OpenEJB Group. OpenEJB is a registered
23  * trademark of The OpenEJB Group.
24  *
25  * 5. Due credit should be given to the OpenEJB Project
26  * (http://www.openejb.org/).
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
29  * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
32  * THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39  * OF THE POSSIBILITY OF SUCH DAMAGE.
40  *
41  * Copyright 2001 (C) The OpenEJB Group. All Rights Reserved.
42  *
43  * $Id: EjbRequestHandler.java 1912 2005-06-16 22:29:56Z jlaskowski $
44  */

45 package org.openejb.server.ejbd;
46
47 import java.io.ObjectInputStream JavaDoc;
48 import java.io.ObjectOutputStream JavaDoc;
49 import java.rmi.RemoteException JavaDoc;
50 import java.util.Collection JavaDoc;
51
52 import javax.ejb.EJBHome JavaDoc;
53 import javax.ejb.EJBObject JavaDoc;
54
55 import org.openejb.DeploymentInfo;
56 import org.openejb.OpenEJB;
57 import org.openejb.ProxyInfo;
58 import org.openejb.RpcContainer;
59 import org.openejb.client.EJBRequest;
60 import org.openejb.client.EJBResponse;
61 import org.openejb.client.RequestMethods;
62 import org.openejb.client.ResponseCodes;
63 import org.openejb.spi.SecurityService;
64
65
66 /**
67  * @author <a HREF="mailto:david.blevins@visi.com">David Blevins</a>
68  */

69 class EjbRequestHandler implements ResponseCodes, RequestMethods {
70     private final EjbDaemon daemon;
71     /**
72      * @param EjbDaemon
73      */

74     EjbRequestHandler(EjbDaemon daemon) {
75         this.daemon = daemon;
76         // TODO Auto-generated constructor stub
77
}
78
79     public void processRequest(ObjectInputStream JavaDoc in, ObjectOutputStream JavaDoc out) {
80         EJBRequest req = new EJBRequest();
81         EJBResponse res = new EJBResponse();
82
83         // TODO:2: This method can throw a large number of exceptions, we should
84
// be prepared to handle them all. Look in the ObejctOutputStream code
85
// for a full list of the exceptions thrown.
86
// java.io.WriteAbortedException can be thrown containing a
87
//
88
try {
89             req.readExternal( in );
90
91             /*
92                 } catch (java.io.WriteAbortedException e){
93                     if ( e.detail instanceof java.io.NotSerializableException){
94                         //TODO:1: Log this warning better. Include information on what bean is to blame
95                         throw new Exception("Client attempting to serialize unserializable object: "+ e.detail.getMessage());
96                     } else {
97                         throw e.detail;
98                     }
99                 } catch (java.io.EOFException e) {
100                     throw new Exception("Reached the end of the stream before the full request could be read");
101                 } catch (Throwable t){
102                     throw new Exception("Cannot read client request: "+ t.getClass().getName()+" "+ t.getMessage());
103                 }
104             */

105
106         } catch (Throwable JavaDoc t) {
107             replyWithFatalError
108             (out, t, "Error caught during request processing");
109             return;
110         }
111
112         CallContext call = null;
113         DeploymentInfo di = null;
114         RpcContainer c = null;;
115
116         try {
117             di = this.daemon.getDeployment(req);
118         } catch (RemoteException JavaDoc e) {
119             replyWithFatalError
120             (out, e, "No such deployment");
121             return;
122             /*
123                 logger.warn( req + "No such deployment: "+e.getMessage());
124                 res.setResponse( EJB_SYS_EXCEPTION, e);
125                 res.writeExternal( out );
126                 return;
127             */

128         } catch ( Throwable JavaDoc t ) {
129             replyWithFatalError
130             (out, t, "Unkown error occured while retrieving deployment");
131             return;
132         }
133
134         try {
135             call = CallContext.getCallContext();
136             call.setEJBRequest( req );
137             call.setDeploymentInfo( di );
138         } catch ( Throwable JavaDoc t ) {
139             replyWithFatalError
140             (out, t, "Unable to set the thread context for this request");
141             return;
142         }
143
144         //logger.info( "EJB REQUEST : "+req );
145

146         try {
147             switch (req.getRequestMethod()) {
148             // Remote interface methods
149
case EJB_OBJECT_BUSINESS_METHOD:
150                 doEjbObject_BUSINESS_METHOD( req, res );
151                 break;
152
153                 // Home interface methods
154
case EJB_HOME_CREATE:
155                 doEjbHome_CREATE( req, res );
156                 break;
157
158             case EJB_HOME_FIND:
159                 doEjbHome_FIND( req, res );
160                 break;
161
162                 // javax.ejb.EJBObject methods
163
case EJB_OBJECT_GET_EJB_HOME:
164                 doEjbObject_GET_EJB_HOME( req, res );
165                 break;
166
167             case EJB_OBJECT_GET_HANDLE:
168                 doEjbObject_GET_HANDLE( req, res );
169                 break;
170
171             case EJB_OBJECT_GET_PRIMARY_KEY:
172                 doEjbObject_GET_PRIMARY_KEY( req, res );
173                 break;
174
175             case EJB_OBJECT_IS_IDENTICAL:
176                 doEjbObject_IS_IDENTICAL( req, res );
177                 break;
178
179             case EJB_OBJECT_REMOVE:
180                 doEjbObject_REMOVE( req, res );
181                 break;
182
183                 // javax.ejb.EJBHome methods
184
case EJB_HOME_GET_EJB_META_DATA:
185                 doEjbHome_GET_EJB_META_DATA( req, res );
186                 break;
187
188             case EJB_HOME_GET_HOME_HANDLE:
189                 doEjbHome_GET_HOME_HANDLE( req, res );
190                 break;
191
192             case EJB_HOME_REMOVE_BY_HANDLE:
193                 doEjbHome_REMOVE_BY_HANDLE( req, res );
194                 break;
195
196             case EJB_HOME_REMOVE_BY_PKEY:
197                 doEjbHome_REMOVE_BY_PKEY( req, res );
198                 break;
199             }
200
201
202         } catch (org.openejb.InvalidateReferenceException e) {
203             res.setResponse(EJB_SYS_EXCEPTION, e.getRootCause());
204         } catch (org.openejb.ApplicationException e) {
205             res.setResponse(EJB_APP_EXCEPTION, e.getRootCause());
206         } catch (org.openejb.SystemException e) {
207             res.setResponse(EJB_ERROR, e.getRootCause());
208             // TODO:2: This means a severe error occured in OpenEJB
209
// we should restart the container system or take other
210
// aggressive actions to attempt recovery.
211
this.daemon.logger.fatal( req+": OpenEJB encountered an unknown system error in container: ", e);
212         } catch (java.lang.Throwable JavaDoc t) {
213             //System.out.println(req+": Unkown error in container: ");
214
replyWithFatalError
215             (out, t, "Unknown error in container");
216             return;
217         } finally {
218             this.daemon.logger.info( "EJB RESPONSE: "+res );
219             try {
220                 res.writeExternal( out );
221             } catch (java.io.IOException JavaDoc ie) {
222                 this.daemon.logger.fatal("Couldn't write EjbResponse to output stream", ie);
223             }
224             call.reset();
225         }
226     }
227
228     protected void doEjbObject_BUSINESS_METHOD( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
229
230         CallContext call = CallContext.getCallContext();
231         RpcContainer c = (RpcContainer)call.getDeploymentInfo().getContainer();
232
233         Object JavaDoc result = c.invoke( req.getDeploymentId(),
234                                   req.getMethodInstance(),
235                                   req.getMethodParameters(),
236                                   req.getPrimaryKey(),
237                                   req.getClientIdentity());
238
239         if (result instanceof ProxyInfo) {
240             ProxyInfo info = (ProxyInfo)result;
241
242             if ( EJBObject JavaDoc.class.isAssignableFrom(info.getInterface()) ) {
243                 result = this.daemon.clientObjectFactory._getEJBObject(call, info);
244             } else if ( EJBHome JavaDoc.class.isAssignableFrom(info.getInterface()) ) {
245                 result = this.daemon.clientObjectFactory._getEJBHome(call, info);
246             } else {
247                 // Freak condition
248
//TODO:3: Localize all error messages in an separate file.
249
result = new RemoteException JavaDoc("The container returned a ProxyInfo object that is neither a javax.ejb.EJBObject or javax.ejb.EJBHome: "+info.getInterface());
250                 this.daemon.logger.error( req + "The container returned a ProxyInfo object that is neither a javax.ejb.EJBObject or javax.ejb.EJBHome: "+info.getInterface());
251                 res.setResponse( EJB_SYS_EXCEPTION, result);
252                 return;
253             }
254         }
255
256         res.setResponse( EJB_OK, result);
257     }
258
259
260     // Home interface methods
261
protected void doEjbHome_CREATE( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
262
263         CallContext call = CallContext.getCallContext();
264         RpcContainer c = (RpcContainer)call.getDeploymentInfo().getContainer();
265
266         Object JavaDoc result = c.invoke( req.getDeploymentId(),
267                                   req.getMethodInstance(),
268                                   req.getMethodParameters(),
269                                   req.getPrimaryKey(),
270                                   req.getClientIdentity());
271
272         if (result instanceof ProxyInfo) {
273             ProxyInfo info = (ProxyInfo)result;
274             res.setResponse(EJB_OK, info.getPrimaryKey());
275         } else {
276             // There should be no else, the entity should be found
277
// or and exception should be thrown.
278
//TODO:3: Localize all error messages in an separate file.
279
result = new RemoteException JavaDoc("The bean is not EJB compliant. The should be created or and exception should be thrown.");
280             this.daemon.logger.error( req + "The bean is not EJB compliant. The should be created or and exception should be thrown.");
281             res.setResponse( EJB_SYS_EXCEPTION, result);
282         }
283     }
284
285     /**
286      * EJB 1.1 --
287      * 9.1.8 Finder method return type
288      *
289      * 9.1.8.1 Single-object finder
290      *
291      * Some finder methods (such as ejbFindByPrimaryKey) are designed to return
292      * at most one entity object. For these single-object finders, the result type
293      * of the find<METHOD>(...)method defined in the entity bean’s home interface
294      * is the entity bean’s remote interface. The result type of the corresponding
295      * ejbFind<METHOD>(...) method defined in the entity’s implementation class is
296      * the entity bean’s primary key type.
297      *
298      * 9.1.8.2 Multi-object finders
299      *
300      * Some finder methods are designed to return multiple entity objects. For
301      * these multi-object finders, the result type of the find<METHOD>(...)method
302      * defined in the entity bean’s home interface is a col-lection of objects
303      * implementing the entity bean’s remote interface. The result type of the
304      * corresponding ejbFind<METHOD>(...) implementation method defined in the
305      * entity bean’s implementation class is a collection of objects of the entity
306      * bean’s primary key type.
307      *
308      * The Bean Provider can choose two types to define a collection type for a finder:
309      * • the JDK™ 1.1 java.util.Enumeration interface
310      * • the Java™ 2 java.util.Collection interface
311      *
312      * A Bean Provider that wants to ensure that the entity bean is compatible
313      * with containers and clients based on JDK TM 1.1 software must use the
314      * java.util.Enumeration interface for the finder’s result type.
315      * </P>
316      *
317      * @param req
318      * @param in
319      * @param out
320      * @exception Exception
321      */

322     protected void doEjbHome_FIND( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
323
324         CallContext call = CallContext.getCallContext();
325         RpcContainer c = (RpcContainer)call.getDeploymentInfo().getContainer();
326
327         Object JavaDoc result = c.invoke( req.getDeploymentId(),
328                                   req.getMethodInstance(),
329                                   req.getMethodParameters(),
330                                   req.getPrimaryKey(),
331                                   req.getClientIdentity());
332
333
334         /* Multiple instances found */
335         if ( result instanceof Collection JavaDoc ) {
336
337             Object JavaDoc [] primaryKeys = ((Collection JavaDoc)result).toArray();
338
339             for (int i=0; i < primaryKeys.length; i++) {
340                 primaryKeys[i] = ((ProxyInfo)primaryKeys[i]).getPrimaryKey();
341             }
342
343             res.setResponse( EJB_OK_FOUND_COLLECTION , primaryKeys );
344
345         } else if (result instanceof java.util.Enumeration JavaDoc ) {
346             
347             java.util.Enumeration JavaDoc resultAsEnum = (java.util.Enumeration JavaDoc) result;
348             java.util.List JavaDoc listOfPKs = new java.util.ArrayList JavaDoc();
349             while ( resultAsEnum.hasMoreElements() ) {
350                 listOfPKs.add( ((ProxyInfo)resultAsEnum.nextElement()).getPrimaryKey() );
351             }
352             
353             res.setResponse( EJB_OK_FOUND_ENUMERATION , listOfPKs.toArray( new Object JavaDoc[listOfPKs.size()]) );
354         /* Single instance found */
355         } else if (result instanceof ProxyInfo) {
356             result = ((ProxyInfo)result).getPrimaryKey();
357             res.setResponse( EJB_OK_FOUND , result );
358
359         } else {
360             // There should be no else, the entity should be found
361
// or an exception should be thrown.
362
//TODO:3: Localize all error messages in an separate file.
363
// TODO:4: It should provide more info on the wrong method
364
final String JavaDoc message = "The bean is not EJB compliant. " +
365                 "The finder method ["+req.getMethodInstance().getName()+"] is declared " +
366                 "to return neither Collection nor the Remote Interface, " +
367                 "but [" +result.getClass().getName()+ "]";
368             result = new RemoteException JavaDoc( message );
369             this.daemon.logger.error( req + " " + message);
370             res.setResponse( EJB_SYS_EXCEPTION, result);
371         }
372     }
373
374     // javax.ejb.EJBObject methods
375
protected void doEjbObject_GET_EJB_HOME( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
376         checkMethodAuthorization( req, res );
377     }
378
379     protected void doEjbObject_GET_HANDLE( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
380         checkMethodAuthorization( req, res );
381     }
382
383     protected void doEjbObject_GET_PRIMARY_KEY( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
384         checkMethodAuthorization( req, res );
385     }
386
387     protected void doEjbObject_IS_IDENTICAL( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
388         checkMethodAuthorization( req, res );
389     }
390
391     protected void doEjbObject_REMOVE( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
392
393         CallContext call = CallContext.getCallContext();
394         RpcContainer c = (RpcContainer)call.getDeploymentInfo().getContainer();
395
396         Object JavaDoc result = c.invoke( req.getDeploymentId(),
397                                   req.getMethodInstance(),
398                                   req.getMethodParameters(),
399                                   req.getPrimaryKey(),
400                                   req.getClientIdentity());
401
402         res.setResponse( EJB_OK, null);
403     }
404
405     // javax.ejb.EJBHome methods
406
protected void doEjbHome_GET_EJB_META_DATA( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
407         checkMethodAuthorization( req, res );
408     }
409
410     protected void doEjbHome_GET_HOME_HANDLE( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
411         checkMethodAuthorization( req, res );
412     }
413
414     protected void doEjbHome_REMOVE_BY_HANDLE( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
415
416         CallContext call = CallContext.getCallContext();
417         RpcContainer c = (RpcContainer)call.getDeploymentInfo().getContainer();
418
419         Object JavaDoc result = c.invoke( req.getDeploymentId(),
420                                   req.getMethodInstance(),
421                                   req.getMethodParameters(),
422                                   req.getPrimaryKey(),
423                                   req.getClientIdentity());
424
425         res.setResponse( EJB_OK, null);
426     }
427
428     protected void doEjbHome_REMOVE_BY_PKEY( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
429
430         CallContext call = CallContext.getCallContext();
431         RpcContainer c = (RpcContainer)call.getDeploymentInfo().getContainer();
432
433         Object JavaDoc result = c.invoke( req.getDeploymentId(),
434                                   req.getMethodInstance(),
435                                   req.getMethodParameters(),
436                                   req.getPrimaryKey(),
437                                   req.getClientIdentity());
438
439         res.setResponse( EJB_OK, null);
440     }
441
442     protected void checkMethodAuthorization( EJBRequest req, EJBResponse res ) throws Exception JavaDoc {
443         // Nothing to do here other than check to see if the client
444
// is authorized to call this method
445
// TODO:3: Keep a cache in the client-side handler of methods it can't access
446

447         SecurityService sec = OpenEJB.getSecurityService();
448         CallContext caller = CallContext.getCallContext();
449         DeploymentInfo di = caller.getDeploymentInfo();
450         String JavaDoc[] authRoles = di.getAuthorizedRoles( req.getMethodInstance() );
451
452         if (sec.isCallerAuthorized( req.getClientIdentity(), authRoles )) {
453             res.setResponse( EJB_OK, null );
454         } else {
455             this.daemon.logger.info(req + "Unauthorized Access by Principal Denied");
456             res.setResponse( EJB_APP_EXCEPTION , new RemoteException JavaDoc("Unauthorized Access by Principal Denied") );
457         }
458     }
459
460     private void replyWithFatalError(ObjectOutputStream JavaDoc out,Throwable JavaDoc error,String JavaDoc message) {
461         this.daemon.logger.fatal(message, error);
462         RemoteException JavaDoc re = new RemoteException JavaDoc
463                              ("The server has encountered a fatal error: "+message+" "+error);
464         EJBResponse res = new EJBResponse();
465         res.setResponse(EJB_ERROR, re);
466         try {
467             res.writeExternal(out);
468         } catch (java.io.IOException JavaDoc ie) {
469             this.daemon.logger.error("Failed to write to EJBResponse", ie);
470         }
471     }
472 }
473
Popular Tags