Save This Page
Home » openejb-3.1.2-src » org.apache » openejb » core » stateless » [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.core.stateless;
   18   
   19   import java.lang.reflect.Method;
   20   import java.util.ArrayList;
   21   import java.util.HashMap;
   22   import java.util.List;
   23   import java.util.Map;
   24   import java.util.concurrent.TimeUnit;
   25   
   26   import javax.ejb.EJBAccessException;
   27   import javax.ejb.EJBHome;
   28   import javax.ejb.EJBLocalHome;
   29   import javax.ejb.EJBLocalObject;
   30   import javax.ejb.EJBObject;
   31   import javax.interceptor.AroundInvoke;
   32   
   33   import org.apache.openejb;
   34   import org.apache.openejb.core.CoreDeploymentInfo;
   35   import org.apache.openejb.core.ExceptionType;
   36   import org.apache.openejb.core.Operation;
   37   import org.apache.openejb.core.ThreadContext;
   38   import org.apache.openejb.core.interceptor.InterceptorData;
   39   import org.apache.openejb.core.interceptor.InterceptorStack;
   40   import org.apache.openejb.core.timer.EjbTimerService;
   41   import org.apache.openejb.core.transaction.TransactionPolicy;
   42   import org.apache.openejb.core.webservices.AddressingSupport;
   43   import org.apache.openejb.core.webservices.NoAddressingSupport;
   44   
   45   import static org.apache.openejb.core.transaction.EjbTransactionUtil.handleApplicationException;
   46   import static org.apache.openejb.core.transaction.EjbTransactionUtil.handleSystemException;
   47   import static org.apache.openejb.core.transaction.EjbTransactionUtil.afterInvoke;
   48   import static org.apache.openejb.core.transaction.EjbTransactionUtil.createTransactionPolicy;
   49   import org.apache.openejb.spi.SecurityService;
   50   import org.apache.openejb.util.Duration;
   51   import org.apache.xbean.finder.ClassFinder;
   52   
   53   /**
   54    * @org.apache.xbean.XBean element="statelessContainer"
   55    */
   56   public class StatelessContainer implements org.apache.openejb.RpcContainer {
   57   
   58       private StatelessInstanceManager instanceManager;
   59   
   60       private HashMap<String,DeploymentInfo> deploymentRegistry = new HashMap<String,DeploymentInfo>();
   61   
   62       private Object containerID = null;
   63       private SecurityService securityService;
   64   
   65       public StatelessContainer(Object id, SecurityService securityService, int timeOut, int poolSize, boolean strictPooling) throws OpenEJBException {
   66           this.containerID = id;
   67           this.securityService = securityService;
   68   
   69           instanceManager = new StatelessInstanceManager(securityService, new Duration(timeOut,TimeUnit.MILLISECONDS), poolSize, strictPooling);
   70   
   71           for (DeploymentInfo deploymentInfo : deploymentRegistry.values()) {
   72               org.apache.openejb.core.CoreDeploymentInfo di = (org.apache.openejb.core.CoreDeploymentInfo) deploymentInfo;
   73               di.setContainer(this);
   74           }
   75       }
   76   
   77       public synchronized DeploymentInfo [] deployments() {
   78           return deploymentRegistry.values().toArray(new DeploymentInfo[deploymentRegistry.size()]);
   79       }
   80   
   81       public synchronized DeploymentInfo getDeploymentInfo(Object deploymentID) {
   82           String id = (String) deploymentID;
   83           return deploymentRegistry.get(id);
   84       }
   85   
   86       public ContainerType getContainerType() {
   87           return ContainerType.STATELESS;
   88       }
   89   
   90       public Object getContainerID() {
   91           return containerID;
   92       }
   93   
   94       public void deploy(DeploymentInfo info) throws OpenEJBException {
   95           CoreDeploymentInfo deploymentInfo = (CoreDeploymentInfo) info;
   96           instanceManager.deploy(deploymentInfo);
   97           String id = (String) deploymentInfo.getDeploymentID();
   98           synchronized (this) {
   99               deploymentRegistry.put(id, deploymentInfo);
  100               deploymentInfo.setContainer(this);
  101           }
  102   
  103           EjbTimerService timerService = deploymentInfo.getEjbTimerService();
  104           if (timerService != null) {
  105               timerService.start();
  106           }
  107       }
  108   
  109       public void undeploy(DeploymentInfo info) {
  110           undeploy((CoreDeploymentInfo)info);
  111       }
  112   
  113       private void undeploy(CoreDeploymentInfo deploymentInfo) {
  114           instanceManager.undeploy(deploymentInfo);
  115           EjbTimerService timerService = deploymentInfo.getEjbTimerService();
  116           if (timerService != null) {
  117               timerService.stop();
  118           }
  119   
  120           synchronized (this) {
  121               String id = (String) deploymentInfo.getDeploymentID();
  122               deploymentInfo.setContainer(null);
  123               deploymentInfo.setContainerData(null);
  124               deploymentRegistry.remove(id);
  125           }
  126       }
  127   
  128       /**
  129        * @deprecated use invoke signature without 'securityIdentity' argument.
  130        */
  131       public Object invoke(Object deployID, Method callMethod, Object[] args, Object primKey, Object securityIdentity) throws OpenEJBException {
  132           return invoke(deployID, null, callMethod.getDeclaringClass(), callMethod, args, primKey);
  133       }
  134   
  135       public Object invoke(Object deployID, Class callInterface, Method callMethod, Object[] args, Object primKey) throws OpenEJBException {
  136           return invoke(deployID, null, callInterface, callMethod, args, primKey);
  137       }
  138   
  139       public Object invoke(Object deployID, InterfaceType type, Class callInterface, Method callMethod, Object[] args, Object primKey) throws OpenEJBException {
  140           CoreDeploymentInfo deployInfo = (CoreDeploymentInfo) this.getDeploymentInfo(deployID);
  141   
  142           if (deployInfo == null) throw new OpenEJBException("Deployment does not exist in this container. Deployment(id='"+deployID+"'), Container(id='"+containerID+"')");
  143   
  144           // Use the backup way to determine call type if null was supplied.
  145           if (type == null) type = deployInfo.getInterfaceType(callInterface);
  146   
  147           ThreadContext callContext = new ThreadContext(deployInfo, primKey);
  148           ThreadContext oldCallContext = ThreadContext.enter(callContext);
  149           Object bean = null;
  150           try {
  151               boolean authorized = getSecurityService().isCallerAuthorized(callMethod, type);
  152               if (!authorized)
  153                   throw new org.apache.openejb.ApplicationException(new EJBAccessException("Unauthorized Access by Principal Denied"));
  154   
  155               Class declaringClass = callMethod.getDeclaringClass();
  156               if (EJBHome.class.isAssignableFrom(declaringClass) || EJBLocalHome.class.isAssignableFrom(declaringClass)) {
  157                   if (callMethod.getName().startsWith("create")) {
  158                       return createEJBObject(deployInfo, callMethod);
  159                   } else
  160                       return null;// EJBHome.remove( ) and other EJBHome methods are not process by the container
  161               } else if (EJBObject.class == declaringClass || EJBLocalObject.class == declaringClass) {
  162                   return null;// EJBObject.remove( ) and other EJBObject methods are not process by the container
  163               }
  164   
  165               bean = instanceManager.getInstance(callContext);
  166   
  167               callContext.setCurrentOperation(Operation.BUSINESS);
  168               callContext.setCurrentAllowedStates(StatelessContext.getStates());
  169   
  170               Method runMethod = deployInfo.getMatchingBeanMethod(callMethod);
  171   
  172               callContext.set(Method.class, runMethod);
  173               callContext.setInvokedInterface(callInterface);
  174               Object retValue = _invoke(callMethod, runMethod, args, (Instance) bean, callContext, type);
  175   
  176               return retValue;
  177   
  178           } finally {
  179               if (bean != null) {
  180                   if (callContext.isDiscardInstance()) {
  181                       instanceManager.discardInstance(callContext);
  182                   } else {
  183                       instanceManager.poolInstance(callContext, bean);
  184                   }
  185               }
  186               ThreadContext.exit(oldCallContext);
  187           }
  188       }
  189   
  190       private SecurityService getSecurityService() {
  191           return securityService;
  192       }
  193   
  194       public StatelessInstanceManager getInstanceManager() {
  195           return instanceManager;
  196       }
  197   
  198       /**
  199        * @deprecated
  200        */
  201       protected Object _invoke(Class callInterface, Method callMethod, Method runMethod, Object[] args, Object object, ThreadContext callContext)
  202               throws OpenEJBException {
  203           return _invoke(callMethod, runMethod, args, (Instance) object, callContext, null);
  204       }
  205   
  206       protected Object _invoke(Method callMethod, Method runMethod, Object[] args, Instance instance, ThreadContext callContext, InterfaceType type)
  207               throws OpenEJBException {
  208   
  209           CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
  210   
  211           TransactionPolicy txPolicy = createTransactionPolicy(deploymentInfo.getTransactionType(callMethod), callContext);
  212   
  213           Object returnValue = null;
  214           try {
  215               if (type == InterfaceType.SERVICE_ENDPOINT){
  216                   callContext.setCurrentOperation(Operation.BUSINESS_WS);
  217                   returnValue = invokeWebService(args, deploymentInfo, runMethod, instance, returnValue);
  218               } else {
  219                   List<InterceptorData> interceptors = deploymentInfo.getMethodInterceptors(runMethod);
  220                   InterceptorStack interceptorStack = new InterceptorStack(instance.bean, runMethod, Operation.BUSINESS, interceptors, instance.interceptors);
  221                   returnValue = interceptorStack.invoke(args);
  222               }
  223           } catch (Throwable re) {// handle reflection exception
  224               ExceptionType exceptionType = deploymentInfo.getExceptionType(re);
  225               if (exceptionType == ExceptionType.SYSTEM) {
  226                   /* System Exception ****************************/
  227   
  228                   // The bean instance is not put into the pool via instanceManager.poolInstance
  229                   // and therefore the instance will be garbage collected and destroyed.
  230                   // In case of StrictPooling flag being set to true we also release the semaphore
  231               	// in the discardInstance method of the instanceManager.
  232               	callContext.setDiscardInstance(true);
  233                   handleSystemException(txPolicy, re, callContext);
  234               } else {
  235                   /* Application Exception ***********************/
  236   
  237                   handleApplicationException(txPolicy, re, exceptionType == ExceptionType.APPLICATION_ROLLBACK);
  238               }
  239           } finally {
  240               try {
  241                   afterInvoke(txPolicy, callContext);
  242               } catch (SystemException e) {
  243                   callContext.setDiscardInstance(true);
  244                   throw e;
  245               } catch (ApplicationException e) {
  246                   throw e;
  247               } catch (RuntimeException e) {
  248                   callContext.setDiscardInstance(true);
  249                   throw e;
  250               }
  251           }
  252   
  253           return returnValue;
  254       }
  255   
  256       private Object invokeWebService(Object[] args, CoreDeploymentInfo deploymentInfo, Method runMethod, Instance instance, Object returnValue) throws Exception {
  257           if (args.length < 2) {
  258               throw new IllegalArgumentException("WebService calls must follow format {messageContext, interceptor, [arg...]}.");
  259           }
  260   
  261           Object messageContext = args[0];
  262   
  263           // This object will be used as an interceptor in the stack and will be responsible
  264           // for unmarshalling the soap message parts into an argument list that will be
  265           // used for the actual method invocation.
  266           //
  267           // We just need to make it an interceptor in the OpenEJB sense and tack it on the end
  268           // of our stack.
  269           Object interceptor = args[1];
  270   
  271   
  272           //  Add the webservice interceptor to the list of interceptor instances
  273           Map<String, Object> interceptors = new HashMap<String, Object>(instance.interceptors);
  274           {
  275               interceptors.put(interceptor.getClass().getName(), interceptor);
  276           }
  277   
  278           //  Create an InterceptorData for the webservice interceptor to the list of interceptorDatas for this method
  279           List<InterceptorData> interceptorDatas = new ArrayList<InterceptorData>(deploymentInfo.getMethodInterceptors(runMethod));
  280           {
  281               InterceptorData providerData = new InterceptorData(interceptor.getClass());
  282               ClassFinder finder = new ClassFinder(interceptor.getClass());
  283               providerData.getAroundInvoke().addAll(finder.findAnnotatedMethods(AroundInvoke.class));
  284   //            interceptorDatas.add(providerData);
  285               interceptorDatas.add(0, providerData);
  286           }
  287   
  288           InterceptorStack interceptorStack = new InterceptorStack(instance.bean, runMethod, Operation.BUSINESS_WS, interceptorDatas, interceptors);
  289           Object[] params = new Object[runMethod.getParameterTypes().length];
  290           if (messageContext instanceof javax.xml.rpc.handler.MessageContext) {
  291               ThreadContext.getThreadContext().set(javax.xml.rpc.handler.MessageContext.class, (javax.xml.rpc.handler.MessageContext) messageContext);
  292               returnValue = interceptorStack.invoke((javax.xml.rpc.handler.MessageContext) messageContext, params);
  293           } else if (messageContext instanceof javax.xml.ws.handler.MessageContext) {
  294               AddressingSupport wsaSupport = NoAddressingSupport.INSTANCE;
  295               for (int i = 2; i < args.length; i++) {
  296                   if (args[i] instanceof AddressingSupport) {
  297                       wsaSupport = (AddressingSupport)args[i];
  298                   }
  299               }
  300               ThreadContext.getThreadContext().set(AddressingSupport.class, wsaSupport);
  301               ThreadContext.getThreadContext().set(javax.xml.ws.handler.MessageContext.class, (javax.xml.ws.handler.MessageContext) messageContext);
  302               returnValue = interceptorStack.invoke((javax.xml.ws.handler.MessageContext) messageContext, params);
  303           }
  304           return returnValue;
  305       }
  306   
  307       protected ProxyInfo createEJBObject(org.apache.openejb.core.CoreDeploymentInfo deploymentInfo, Method callMethod) {
  308           return new ProxyInfo(deploymentInfo, null);
  309       }
  310   }

Save This Page
Home » openejb-3.1.2-src » org.apache » openejb » core » stateless » [javadoc | source]