Save This Page
Home » openejb-3.0-src » org.apache » openejb » server » ejbd » [javadoc | source]
    1   /**
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.openejb.server.ejbd;
   18   
   19   import java.io.ObjectInputStream;
   20   import java.io.ObjectOutputStream;
   21   import java.rmi.RemoteException;
   22   import java.util.ArrayList;
   23   import java.util.Collection;
   24   
   25   import org.apache.openejb.DeploymentInfo;
   26   import org.apache.openejb.ProxyInfo;
   27   import org.apache.openejb.RpcContainer;
   28   import org.apache.openejb.client.EJBHomeProxyHandle;
   29   import org.apache.openejb.client.EJBObjectProxyHandle;
   30   import org.apache.openejb.client.EJBRequest;
   31   import org.apache.openejb.client.EJBResponse;
   32   import org.apache.openejb.client.RequestMethodConstants;
   33   import org.apache.openejb.client.ResponseCodes;
   34   import org.apache.openejb.client.ThrowableArtifact;
   35   import org.apache.openejb.loader.SystemInstance;
   36   import org.apache.openejb.spi.SecurityService;
   37   import org.apache.openejb.util.LogCategory;
   38   import org.apache.openejb.util.Logger;
   39   
   40   class EjbRequestHandler {
   41       public static final ServerSideResolver SERVER_SIDE_RESOLVER = new ServerSideResolver();
   42   
   43       private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB_SERVER_REMOTE.createChild("ejb"), "org.apache.openejb.server.util.resources");
   44       private final EjbDaemon daemon;
   45   
   46       private final ClusterableRequestHandler clusterableRequestHandler;
   47   
   48       EjbRequestHandler(EjbDaemon daemon) {
   49           this.daemon = daemon;
   50           
   51           clusterableRequestHandler = newClusterableRequestHandler();
   52       }
   53   
   54       protected BasicClusterableRequestHandler newClusterableRequestHandler() {
   55           return new BasicClusterableRequestHandler();
   56       }
   57   
   58       public void processRequest(ObjectInputStream in, ObjectOutputStream out) {
   59           // Setup the client proxy replacement to replace
   60           // the proxies with the IntraVM proxy implementations
   61           EJBHomeProxyHandle.resolver.set(SERVER_SIDE_RESOLVER);
   62           EJBObjectProxyHandle.resolver.set(SERVER_SIDE_RESOLVER);
   63   
   64           EJBRequest req = new EJBRequest();
   65           EJBResponse res = new EJBResponse();
   66   
   67           try {
   68               req.readExternal(in);
   69           } catch (Throwable t) {
   70               replyWithFatalError(out, t, "Error caught during request processing");
   71               return;
   72           }
   73   
   74           CallContext call = null;
   75           DeploymentInfo di = null;
   76           RpcContainer c = null;
   77   
   78           try {
   79               di = this.daemon.getDeployment(req);
   80           } catch (RemoteException e) {
   81               replyWithFatalError
   82                       (out, e, "No such deployment");
   83               return;
   84               /*
   85                   logger.warn( req + "No such deployment: "+e.getMessage());
   86                   res.setResponse( EJB_SYS_EXCEPTION, e);
   87                   res.writeExternal( out );
   88                   return;
   89               */
   90           } catch (Throwable t) {
   91               replyWithFatalError
   92                       (out, t, "Unkown error occured while retrieving deployment");
   93               return;
   94           }
   95   
   96           //  Need to set this for deserialization of the body
   97           ClassLoader classLoader = di.getBeanClass().getClassLoader();
   98           Thread.currentThread().setContextClassLoader(classLoader);
   99   
  100           try {
  101               req.getBody().readExternal(in);
  102           } catch (Throwable t) {
  103               replyWithFatalError(out, t, "Error caught during request processing");
  104               return;
  105           }
  106   
  107           try {
  108               call = CallContext.getCallContext();
  109               call.setEJBRequest(req);
  110               call.setDeploymentInfo(di);
  111           } catch (Throwable t) {
  112               replyWithFatalError(out, t, "Unable to set the thread context for this request");
  113               return;
  114           }
  115   
  116           SecurityService securityService = SystemInstance.get().getComponent(SecurityService.class);
  117           try {
  118               Object clientIdentity = req.getClientIdentity();
  119               if (clientIdentity != null) securityService.associate(clientIdentity);
  120           } catch (Throwable t) {
  121               replyWithFatalError(out, t, "Security system failed to associate thread with the thread");
  122               return;
  123           }
  124   
  125           try {
  126               switch (req.getRequestMethod()) {
  127               // Remote interface methods
  128                   case RequestMethodConstants.EJB_OBJECT_BUSINESS_METHOD:
  129                       doEjbObject_BUSINESS_METHOD(req, res);
  130                       updateServer(req, res);
  131                       break;
  132   
  133                   // Home interface methods
  134                   case RequestMethodConstants.EJB_HOME_CREATE:
  135                       doEjbHome_CREATE(req, res);
  136                       updateServer(req, res);
  137                       break;
  138   
  139                   // Home interface methods
  140                   case RequestMethodConstants.EJB_HOME_METHOD:
  141                       doEjbHome_METHOD(req, res);
  142                       updateServer(req, res);
  143                       break;
  144   
  145                   case RequestMethodConstants.EJB_HOME_FIND:
  146                       doEjbHome_FIND(req, res);
  147                       updateServer(req, res);
  148                       break;
  149   
  150                   // javax.ejb.EJBObject methods
  151                   case RequestMethodConstants.EJB_OBJECT_GET_EJB_HOME:
  152                       doEjbObject_GET_EJB_HOME(req, res);
  153                       updateServer(req, res);
  154                       break;
  155   
  156                   case RequestMethodConstants.EJB_OBJECT_GET_HANDLE:
  157                       doEjbObject_GET_HANDLE(req, res);
  158                       updateServer(req, res);
  159                       break;
  160   
  161                   case RequestMethodConstants.EJB_OBJECT_GET_PRIMARY_KEY:
  162                       doEjbObject_GET_PRIMARY_KEY(req, res);
  163                       updateServer(req, res);
  164                       break;
  165   
  166                   case RequestMethodConstants.EJB_OBJECT_IS_IDENTICAL:
  167                       doEjbObject_IS_IDENTICAL(req, res);
  168                       updateServer(req, res);
  169                       break;
  170   
  171                   case RequestMethodConstants.EJB_OBJECT_REMOVE:
  172                       doEjbObject_REMOVE(req, res);
  173                       break;
  174   
  175                   // javax.ejb.EJBHome methods
  176                   case RequestMethodConstants.EJB_HOME_GET_EJB_META_DATA:
  177                       doEjbHome_GET_EJB_META_DATA(req, res);
  178                       updateServer(req, res);
  179                       break;
  180   
  181                   case RequestMethodConstants.EJB_HOME_GET_HOME_HANDLE:
  182                       doEjbHome_GET_HOME_HANDLE(req, res);
  183                       updateServer(req, res);
  184                       break;
  185   
  186                   case RequestMethodConstants.EJB_HOME_REMOVE_BY_HANDLE:
  187                       doEjbHome_REMOVE_BY_HANDLE(req, res);
  188                       break;
  189   
  190                   case RequestMethodConstants.EJB_HOME_REMOVE_BY_PKEY:
  191                       doEjbHome_REMOVE_BY_PKEY(req, res);
  192                       break;
  193               }
  194   
  195           } catch (org.apache.openejb.InvalidateReferenceException e) {
  196               res.setResponse(ResponseCodes.EJB_SYS_EXCEPTION, new ThrowableArtifact(e.getRootCause()));
  197           } catch (org.apache.openejb.ApplicationException e) {
  198               res.setResponse(ResponseCodes.EJB_APP_EXCEPTION, new ThrowableArtifact(e.getRootCause()));
  199           } catch (org.apache.openejb.SystemException e) {
  200               res.setResponse(ResponseCodes.EJB_ERROR, new ThrowableArtifact(e.getRootCause()));
  201   
  202               logger.fatal(req + ": OpenEJB encountered an unknown system error in container: ", e);
  203           } catch (java.lang.Throwable t) {
  204               // todo this causes the response to be written twice but the code below
  205               replyWithFatalError
  206                       (out, t, "Unknown error in container");
  207               return;
  208           } finally {
  209               if (logger.isDebugEnabled()){
  210                   try {
  211                       logger.debug("EJB REQUEST: "+req+" -- RESPONSE: " + res);
  212                   } catch (Exception justInCase) {}
  213               }
  214               try {
  215                   res.writeExternal(out);
  216               } catch (java.io.IOException ie) {
  217                   logger.fatal("Couldn't write EjbResponse to output stream", ie);
  218               }
  219               securityService.disassociate();
  220               call.reset();
  221               EJBHomeProxyHandle.resolver.set(null);
  222               EJBObjectProxyHandle.resolver.set(null);
  223   
  224           }
  225       }
  226   
  227       protected void updateServer(EJBRequest req, EJBResponse res) {
  228           CallContext callContext = CallContext.getCallContext();
  229           DeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
  230           clusterableRequestHandler.updateServer(deploymentInfo, req, res);
  231       }
  232   
  233       protected void doEjbObject_BUSINESS_METHOD(EJBRequest req, EJBResponse res) throws Exception {
  234   
  235           CallContext call = CallContext.getCallContext();
  236           RpcContainer c = (RpcContainer) call.getDeploymentInfo().getContainer();
  237   
  238           Object result = c.invoke(req.getDeploymentId(),
  239                   req.getInterfaceClass(), req.getMethodInstance(),
  240                   req.getMethodParameters(),
  241                   req.getPrimaryKey()
  242           );
  243           
  244           res.setResponse(ResponseCodes.EJB_OK, result);
  245       }
  246   
  247       protected void doEjbHome_METHOD(EJBRequest req, EJBResponse res) throws Exception {
  248   
  249           CallContext call = CallContext.getCallContext();
  250           RpcContainer c = (RpcContainer) call.getDeploymentInfo().getContainer();
  251   
  252           Object result = c.invoke(req.getDeploymentId(),
  253                   req.getInterfaceClass(), req.getMethodInstance(),
  254                   req.getMethodParameters(),
  255                   req.getPrimaryKey()
  256           );
  257   
  258           res.setResponse(ResponseCodes.EJB_OK, result);
  259       }
  260   
  261       protected void doEjbHome_CREATE(EJBRequest req, EJBResponse res) throws Exception {
  262   
  263           CallContext call = CallContext.getCallContext();
  264           RpcContainer c = (RpcContainer) call.getDeploymentInfo().getContainer();
  265   
  266           Object result = c.invoke(req.getDeploymentId(),
  267                   req.getInterfaceClass(), req.getMethodInstance(),
  268                   req.getMethodParameters(),
  269                   req.getPrimaryKey()
  270           );
  271   
  272           if (result instanceof ProxyInfo) {
  273               ProxyInfo info = (ProxyInfo) result;
  274               res.setResponse(ResponseCodes.EJB_OK, info.getPrimaryKey());
  275           } else {
  276   
  277               result = new RemoteException("The bean is not EJB compliant.  The bean should be created or and exception should be thrown.");
  278               logger.error(req + "The bean is not EJB compliant.  The bean should be created or and exception should be thrown.");
  279               res.setResponse(ResponseCodes.EJB_SYS_EXCEPTION, new ThrowableArtifact((Throwable) result));
  280           }
  281       }
  282   
  283       protected void doEjbHome_FIND(EJBRequest req, EJBResponse res) throws Exception {
  284   
  285           CallContext call = CallContext.getCallContext();
  286           RpcContainer c = (RpcContainer) call.getDeploymentInfo().getContainer();
  287   
  288           Object result = c.invoke(req.getDeploymentId(),
  289                   req.getInterfaceClass(), req.getMethodInstance(),
  290                   req.getMethodParameters(),
  291                   req.getPrimaryKey()
  292           );
  293   
  294           /* Multiple instances found */
  295           if (result instanceof Collection) {
  296   
  297               Object [] primaryKeys = ((Collection) result).toArray();
  298   
  299               for (int i = 0; i < primaryKeys.length; i++) {
  300                   ProxyInfo proxyInfo = ((ProxyInfo) primaryKeys[i]);
  301                   if (proxyInfo == null) {
  302                       primaryKeys[i] = null;
  303                   } else {
  304                       primaryKeys[i] = proxyInfo.getPrimaryKey();
  305                   }
  306               }
  307   
  308               res.setResponse(ResponseCodes.EJB_OK_FOUND_COLLECTION, primaryKeys);
  309   
  310           } else if (result instanceof java.util.Enumeration) {
  311   
  312               java.util.Enumeration resultAsEnum = (java.util.Enumeration) result;
  313               java.util.List<Object> listOfPKs = new ArrayList<Object>();
  314               while (resultAsEnum.hasMoreElements()) {
  315                   ProxyInfo proxyInfo = ((ProxyInfo) resultAsEnum.nextElement());
  316                   if (proxyInfo == null) {
  317                       listOfPKs.add(null);
  318                   } else {
  319                       listOfPKs.add(proxyInfo.getPrimaryKey());
  320                   }
  321               }
  322   
  323               res.setResponse(ResponseCodes.EJB_OK_FOUND_ENUMERATION, listOfPKs.toArray(new Object[listOfPKs.size()]));
  324               /* Single instance found */
  325           } else if (result instanceof ProxyInfo) {
  326               ProxyInfo proxyInfo = ((ProxyInfo) result);
  327               result = proxyInfo.getPrimaryKey();
  328               res.setResponse(ResponseCodes.EJB_OK_FOUND, result);
  329           } else if (result == null) {
  330               res.setResponse(ResponseCodes.EJB_OK_FOUND, null);
  331           } else {
  332   
  333               final String message = "The bean is not EJB compliant. " +
  334                       "The finder method [" + req.getMethodInstance().getName() + "] is declared " +
  335                       "to return neither Collection nor the Remote Interface, " +
  336                       "but [" + result.getClass().getName() + "]";
  337               result = new RemoteException(message);
  338               logger.error(req + " " + message);
  339               res.setResponse(ResponseCodes.EJB_SYS_EXCEPTION, result);
  340           }
  341       }
  342   
  343       protected void doEjbObject_GET_EJB_HOME(EJBRequest req, EJBResponse res) throws Exception {
  344           checkMethodAuthorization(req, res);
  345       }
  346   
  347       protected void doEjbObject_GET_HANDLE(EJBRequest req, EJBResponse res) throws Exception {
  348           checkMethodAuthorization(req, res);
  349       }
  350   
  351       protected void doEjbObject_GET_PRIMARY_KEY(EJBRequest req, EJBResponse res) throws Exception {
  352           checkMethodAuthorization(req, res);
  353       }
  354   
  355       protected void doEjbObject_IS_IDENTICAL(EJBRequest req, EJBResponse res) throws Exception {
  356           checkMethodAuthorization(req, res);
  357       }
  358   
  359       protected void doEjbObject_REMOVE(EJBRequest req, EJBResponse res) throws Exception {
  360   
  361           CallContext call = CallContext.getCallContext();
  362           RpcContainer c = (RpcContainer) call.getDeploymentInfo().getContainer();
  363   
  364           Object result = c.invoke(req.getDeploymentId(),
  365                   req.getInterfaceClass(), req.getMethodInstance(),
  366                   req.getMethodParameters(),
  367                   req.getPrimaryKey()
  368           );
  369   
  370           res.setResponse(ResponseCodes.EJB_OK, null);
  371       }
  372   
  373       protected void doEjbHome_GET_EJB_META_DATA(EJBRequest req, EJBResponse res) throws Exception {
  374           checkMethodAuthorization(req, res);
  375       }
  376   
  377       protected void doEjbHome_GET_HOME_HANDLE(EJBRequest req, EJBResponse res) throws Exception {
  378           checkMethodAuthorization(req, res);
  379       }
  380   
  381       protected void doEjbHome_REMOVE_BY_HANDLE(EJBRequest req, EJBResponse res) throws Exception {
  382   
  383           CallContext call = CallContext.getCallContext();
  384           RpcContainer c = (RpcContainer) call.getDeploymentInfo().getContainer();
  385   
  386           Object result = c.invoke(req.getDeploymentId(),
  387                   req.getInterfaceClass(), req.getMethodInstance(),
  388                   req.getMethodParameters(),
  389                   req.getPrimaryKey()
  390           );
  391   
  392           res.setResponse(ResponseCodes.EJB_OK, null);
  393       }
  394   
  395       protected void doEjbHome_REMOVE_BY_PKEY(EJBRequest req, EJBResponse res) throws Exception {
  396   
  397           CallContext call = CallContext.getCallContext();
  398           RpcContainer c = (RpcContainer) call.getDeploymentInfo().getContainer();
  399   
  400           Object result = c.invoke(req.getDeploymentId(),
  401                   req.getInterfaceClass(), req.getMethodInstance(),
  402                   req.getMethodParameters(),
  403                   req.getPrimaryKey()
  404           );
  405   
  406           res.setResponse(ResponseCodes.EJB_OK, null);
  407       }
  408   
  409       protected void checkMethodAuthorization(EJBRequest req, EJBResponse res) throws Exception {
  410           res.setResponse(ResponseCodes.EJB_OK, null);
  411   //        SecurityService sec = SystemInstance.get().getComponent(SecurityService.class);
  412   //        CallContext caller = CallContext.getCallContext();
  413   //        DeploymentInfo di = caller.getDeploymentInfo();
  414   //
  415   //        if (sec.isCallerAuthorized(req.getMethodInstance(), null)) {
  416   //            res.setResponse(ResponseCodes.EJB_OK, null);
  417   //        } else {
  418   //            logger.info(req + "Unauthorized Access by Principal Denied");
  419   //            res.setResponse(ResponseCodes.EJB_APP_EXCEPTION, new ThrowableArtifact(new EJBAccessException("Unauthorized Access by Principal Denied")));
  420   //        }
  421       }
  422   
  423       private void replyWithFatalError(ObjectOutputStream out, Throwable error, String message) {
  424           logger.fatal(message, error);
  425           RemoteException re = new RemoteException
  426                   ("The server has encountered a fatal error: " + message + " " + error, error);
  427           EJBResponse res = new EJBResponse();
  428           res.setResponse(ResponseCodes.EJB_ERROR, new ThrowableArtifact(re));
  429           try {
  430               res.writeExternal(out);
  431           } catch (java.io.IOException ie) {
  432               logger.error("Failed to write to EJBResponse", ie);
  433           }
  434       }
  435   }

Save This Page
Home » openejb-3.0-src » org.apache » openejb » server » ejbd » [javadoc | source]