protected Object businessMethod(
      BeanContext beanContext,
      Object primKey,
      Class callInterface,
      Method callMethod,
      Object[] args,
      InterfaceType interfaceType)
      throws OpenEJBException {
    ThreadContext callContext = new ThreadContext(beanContext, primKey);
    ThreadContext oldCallContext = ThreadContext.enter(callContext);
    try {
      // Security check
      checkAuthorization(callMethod, interfaceType);

      // Start transaction
      TransactionPolicy txPolicy =
          createTransactionPolicy(
              callContext.getBeanContext().getTransactionType(callMethod, interfaceType),
              callContext);

      Object returnValue = null;
      Instance instance = null;
      try {
        // Obtain instance
        instance = obtainInstance(primKey, callContext);

        // Resume previous Bean transaction if there was one
        if (txPolicy instanceof BeanTransactionPolicy) {
          SuspendedTransaction suspendedTransaction = instance.getBeanTransaction();
          if (suspendedTransaction != null) {
            instance.setBeanTransaction(null);
            BeanTransactionPolicy beanTxEnv = (BeanTransactionPolicy) txPolicy;
            beanTxEnv.resumeUserTransaction(suspendedTransaction);
          }
        }

        // Register the entity managers
        registerEntityManagers(instance, callContext);
        // Register for synchronization callbacks
        registerSessionSynchronization(instance, callContext);

        // Setup for business invocation
        callContext.setCurrentOperation(Operation.BUSINESS);
        callContext.setCurrentAllowedStates(null);
        callContext.setInvokedInterface(callInterface);
        Method runMethod = beanContext.getMatchingBeanMethod(callMethod);
        callContext.set(Method.class, runMethod);

        // Initialize interceptor stack
        List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod);
        InterceptorStack interceptorStack =
            new InterceptorStack(
                instance.bean, runMethod, Operation.BUSINESS, interceptors, instance.interceptors);

        // Invoke
        returnValue = interceptorStack.invoke(args);
      } catch (Throwable e) {
        handleException(callContext, txPolicy, e);
      } finally {
        // Commit transaction
        afterInvoke(callContext, txPolicy, instance);
      }
      return returnValue;
    } finally {
      ThreadContext.exit(oldCallContext);
    }
  }
  public Object invoke(
      Object deployID,
      InterfaceType type,
      Class callInterface,
      Method callMethod,
      Object[] args,
      Object primKey)
      throws OpenEJBException {
    BeanContext beanContext = this.getBeanContext(deployID);

    if (beanContext == null)
      throw new OpenEJBException(
          "Deployment does not exist in this container. Deployment(id='"
              + deployID
              + "'), Container(id='"
              + containerID
              + "')");

    // Use the backup way to determine call type if null was supplied.
    if (type == null) type = beanContext.getInterfaceType(callInterface);

    Method runMethod = beanContext.getMatchingBeanMethod(callMethod);

    ThreadContext callContext = new ThreadContext(beanContext, primKey);
    ThreadContext oldCallContext = ThreadContext.enter(callContext);
    Object bean = null;
    try {
      boolean authorized =
          type == InterfaceType.TIMEOUT
              || getSecurityService().isCallerAuthorized(callMethod, type);
      if (!authorized)
        throw new org.apache.openejb.ApplicationException(
            new EJBAccessException("Unauthorized Access by Principal Denied"));

      Class declaringClass = callMethod.getDeclaringClass();
      if (EJBHome.class.isAssignableFrom(declaringClass)
          || EJBLocalHome.class.isAssignableFrom(declaringClass)) {
        if (callMethod.getName().startsWith("create")) {
          return createEJBObject(beanContext, callMethod);
        } else
          return null; // EJBHome.remove( ) and other EJBHome methods are not process by the
                       // container
      } else if (EJBObject.class == declaringClass || EJBLocalObject.class == declaringClass) {
        return null; // EJBObject.remove( ) and other EJBObject methods are not process by the
                     // container
      }

      bean = instanceManager.getInstance(callContext);

      callContext.setCurrentOperation(
          type == InterfaceType.TIMEOUT ? Operation.TIMEOUT : Operation.BUSINESS);
      callContext.set(Method.class, runMethod);
      callContext.setInvokedInterface(callInterface);
      Object retValue = _invoke(callMethod, runMethod, args, (Instance) bean, callContext, type);

      return retValue;

    } finally {
      if (bean != null) {
        if (callContext.isDiscardInstance()) {
          instanceManager.discardInstance(callContext, bean);
        } else {
          instanceManager.poolInstance(callContext, bean);
        }
      }
      ThreadContext.exit(oldCallContext);
    }
  }
  protected Object removeEJBObject(
      BeanContext beanContext,
      Object primKey,
      Class callInterface,
      Method callMethod,
      Object[] args,
      InterfaceType interfaceType)
      throws OpenEJBException {
    if (primKey == null) throw new NullPointerException("primKey is null");

    ThreadContext callContext = new ThreadContext(beanContext, primKey);
    ThreadContext oldCallContext = ThreadContext.enter(callContext);
    try {
      // Security check
      checkAuthorization(callMethod, interfaceType);

      // If a bean managed transaction is active, the bean can not be removed
      if (interfaceType.isComponent()) {
        Instance instance = checkedOutInstances.get(primKey);

        /**
         * According to EJB 3.0 "4.4.4 Restrictions for Transactions" any remove methods from home
         * or component interfaces must not be allowed if the bean instance is in a transaction.
         * Unfortunately, the Java EE 5 TCK has tests that ignore the restrictions in 4.4.4 and
         * expect beans in transactions can be removed via their home or component interface. The
         * test to see if the bean instance implements javax.ejb.SessionBean is a workaround for
         * passing the TCK while the tests in question can be challenged or the spec can be
         * changed/updated.
         */
        if (instance != null && instance.bean instanceof javax.ejb.SessionBean) {
          throw new ApplicationException(
              new RemoveException("A stateful EJB enrolled in a transaction can not be removed"));
        }
      }

      // Start transaction
      TransactionPolicy txPolicy =
          createTransactionPolicy(
              callContext.getBeanContext().getTransactionType(callMethod, interfaceType),
              callContext);

      Object returnValue = null;
      boolean retain = false;
      Instance instance = null;
      Method runMethod = null;
      try {
        // Obtain instance
        instance = obtainInstance(primKey, callContext);

        // Resume previous Bean transaction if there was one
        if (txPolicy instanceof BeanTransactionPolicy) {
          // Resume previous Bean transaction if there was one
          SuspendedTransaction suspendedTransaction = instance.getBeanTransaction();
          if (suspendedTransaction != null) {
            instance.setBeanTransaction(null);
            BeanTransactionPolicy beanTxEnv = (BeanTransactionPolicy) txPolicy;
            beanTxEnv.resumeUserTransaction(suspendedTransaction);
          }
        }

        // Register the entity managers
        registerEntityManagers(instance, callContext);

        // Register for synchronization callbacks
        registerSessionSynchronization(instance, callContext);

        // Setup for remove invocation
        callContext.setCurrentOperation(Operation.REMOVE);
        callContext.setCurrentAllowedStates(null);
        callContext.setInvokedInterface(callInterface);
        runMethod = beanContext.getMatchingBeanMethod(callMethod);
        callContext.set(Method.class, runMethod);

        // Do not pass arguments on home.remove(remote) calls
        Class<?> declaringClass = callMethod.getDeclaringClass();
        if (declaringClass.equals(EJBHome.class) || declaringClass.equals(EJBLocalHome.class)) {
          args = new Object[] {};
        }

        // Initialize interceptor stack
        List<InterceptorData> interceptors = beanContext.getMethodInterceptors(runMethod);
        InterceptorStack interceptorStack =
            new InterceptorStack(
                instance.bean, runMethod, Operation.REMOVE, interceptors, instance.interceptors);

        // Invoke
        if (args == null) {
          returnValue = interceptorStack.invoke();
        } else {
          returnValue = interceptorStack.invoke(args);
        }
      } catch (InvalidateReferenceException e) {
        throw e;
      } catch (Throwable e) {
        if (interfaceType.isBusiness()) {
          retain = beanContext.retainIfExeption(runMethod);
          handleException(callContext, txPolicy, e);
        } else {
          try {
            handleException(callContext, txPolicy, e);
          } catch (ApplicationException ae) {
            // Don't throw application exceptions for non-business interface removes
          }
        }
      } finally {
        if (!retain) {
          try {
            callContext.setCurrentOperation(Operation.PRE_DESTROY);
            List<InterceptorData> callbackInterceptors = beanContext.getCallbackInterceptors();
            InterceptorStack interceptorStack =
                new InterceptorStack(
                    instance.bean,
                    null,
                    Operation.PRE_DESTROY,
                    callbackInterceptors,
                    instance.interceptors);
            interceptorStack.invoke();
          } catch (Throwable callbackException) {
            String logMessage =
                "An unexpected exception occured while invoking the preDestroy method on the removed Stateful SessionBean instance; "
                    + callbackException.getClass().getName()
                    + " "
                    + callbackException.getMessage();

            /* [1] Log the exception or error */
            logger.error(logMessage);

          } finally {
            callContext.setCurrentOperation(Operation.REMOVE);
          }

          // todo destroy extended persistence contexts
          discardInstance(callContext);
        }

        // Commit transaction
        afterInvoke(callContext, txPolicy, instance);
      }

      return returnValue;
    } finally {
      ThreadContext.exit(oldCallContext);
    }
  }
  protected ProxyInfo createEJBObject(
      BeanContext beanContext, Method callMethod, Object[] args, InterfaceType interfaceType)
      throws OpenEJBException {
    // generate a new primary key
    Object primaryKey = newPrimaryKey();

    ThreadContext createContext = new ThreadContext(beanContext, primaryKey);
    ThreadContext oldCallContext = ThreadContext.enter(createContext);
    try {
      // Security check
      checkAuthorization(callMethod, interfaceType);

      // Create the extended entity managers for this instance
      Index<EntityManagerFactory, JtaEntityManagerRegistry.EntityManagerTracker> entityManagers =
          createEntityManagers(beanContext);

      // Register the newly created entity managers
      if (entityManagers != null) {
        try {
          entityManagerRegistry.addEntityManagers(
              (String) beanContext.getDeploymentID(), primaryKey, entityManagers);
        } catch (EntityManagerAlreadyRegisteredException e) {
          throw new EJBException(e);
        }
      }

      createContext.setCurrentOperation(Operation.CREATE);
      createContext.setCurrentAllowedStates(null);

      // Start transaction
      TransactionPolicy txPolicy =
          createTransactionPolicy(
              createContext.getBeanContext().getTransactionType(callMethod, interfaceType),
              createContext);

      Instance instance = null;
      try {
        // Create new instance

        try {
          final InstanceContext context = beanContext.newInstance();

          // Wrap-up everthing into a object
          instance =
              new Instance(
                  beanContext,
                  primaryKey,
                  context.getBean(),
                  context.getInterceptors(),
                  context.getCreationalContext(),
                  entityManagers);

        } catch (Throwable throwable) {
          ThreadContext callContext = ThreadContext.getThreadContext();
          handleSystemException(callContext.getTransactionPolicy(), throwable, callContext);
          throw new IllegalStateException(throwable); // should never be reached
        }

        // add to cache
        cache.add(primaryKey, instance);

        // instance starts checked-out
        checkedOutInstances.put(primaryKey, instance);

        // Register for synchronization callbacks
        registerSessionSynchronization(instance, createContext);

        // Invoke create for legacy beans
        if (!callMethod.getDeclaringClass().equals(BeanContext.BusinessLocalHome.class)
            && !callMethod.getDeclaringClass().equals(BeanContext.BusinessRemoteHome.class)
            && !callMethod.getDeclaringClass().equals(BeanContext.BusinessLocalBeanHome.class)) {

          // Setup for business invocation
          Method createOrInit = beanContext.getMatchingBeanMethod(callMethod);
          createContext.set(Method.class, createOrInit);

          // Initialize interceptor stack
          InterceptorStack interceptorStack =
              new InterceptorStack(
                  instance.bean,
                  createOrInit,
                  Operation.CREATE,
                  new ArrayList<InterceptorData>(),
                  new HashMap<String, Object>());

          // Invoke
          if (args == null) {
            interceptorStack.invoke();
          } else {
            interceptorStack.invoke(args);
          }
        }
      } catch (Throwable e) {
        handleException(createContext, txPolicy, e);
      } finally {
        afterInvoke(createContext, txPolicy, instance);
      }

      return new ProxyInfo(beanContext, primaryKey);
    } finally {
      ThreadContext.exit(oldCallContext);
    }
  }
예제 #5
0
  private ProxyInfo createEJBObject(
      final Method callMethod,
      final Object[] args,
      final ThreadContext callContext,
      final InterfaceType interfaceType)
      throws OpenEJBException {
    final BeanContext beanContext = callContext.getBeanContext();

    final TransactionPolicy txPolicy =
        createTransactionPolicy(
            beanContext.getTransactionType(callMethod, interfaceType), callContext);

    final EntityBean bean;
    Object primaryKey = null;

    try {
      // Obtain a bean instance from the method ready pool
      bean = createNewInstance(callContext);

      // set the entity context
      setEntityContext(bean);

      // Obtain the proper ejbCreate() method
      final Method ejbCreateMethod = beanContext.getMatchingBeanMethod(callMethod);

      // Set current operation for allowed operations
      callContext.setCurrentOperation(Operation.CREATE);

      // Invoke the proper ejbCreate() method on the instance
      ejbCreateMethod.invoke(bean, args);

      // create the new bean
      primaryKey = cmpEngine.createBean(bean, callContext);

      // determine post create callback method
      final Method ejbPostCreateMethod = beanContext.getMatchingPostCreateMethod(ejbCreateMethod);

      // create a new context containing the pk for the post create call
      final ThreadContext postCreateContext = new ThreadContext(beanContext, primaryKey);
      postCreateContext.setCurrentOperation(Operation.POST_CREATE);

      final ThreadContext oldContext = ThreadContext.enter(postCreateContext);
      try {
        // Invoke the ejbPostCreate method on the bean instance
        ejbPostCreateMethod.invoke(bean, args);

        // According to section 9.1.5.1 of the EJB 1.1 specification, the "ejbPostCreate(...)
        // method executes in the same transaction context as the previous ejbCreate(...) method."
        //
        // The bean is first insterted using db.create( ) and then after ejbPostCreate( ) its
        // updated using db.update(). This protocol allows for visablity of the bean after ejbCreate
        // within the current trasnaction.
      } finally {
        ThreadContext.exit(oldContext);
      }

      // when there is not transaction, merge the data from the bean back into the cmp engine
      cmpEngine.storeBeanIfNoTx(callContext, bean);
    } catch (Throwable e) {
      if (e instanceof InvocationTargetException) {
        e = ((InvocationTargetException) e).getTargetException();
      }

      final ExceptionType type = callContext.getBeanContext().getExceptionType(e);
      if (type == ExceptionType.SYSTEM) {
        /* System Exception ****************************/
        handleSystemException(txPolicy, e, callContext);
      } else {
        /* Application Exception ***********************/
        handleApplicationException(txPolicy, e, type == ExceptionType.APPLICATION_ROLLBACK);
      }
    } finally {
      afterInvoke(txPolicy, callContext);
    }

    return new ProxyInfo(beanContext, primaryKey);
  }
예제 #6
0
  private Object homeMethod(
      final Method callMethod,
      final Object[] args,
      final ThreadContext callContext,
      final InterfaceType interfaceType)
      throws OpenEJBException {
    final BeanContext beanContext = callContext.getBeanContext();

    final TransactionPolicy txPolicy =
        createTransactionPolicy(
            beanContext.getTransactionType(callMethod, interfaceType), callContext);

    final EntityBean bean;
    Object returnValue = null;
    try {
      /*
        Obtain a bean instance from the method ready pool
      */
      bean = createNewInstance(callContext);

      // set the entity context
      setEntityContext(bean);

      try {
        callContext.setCurrentOperation(Operation.HOME);

        final Method runMethod = beanContext.getMatchingBeanMethod(callMethod);

        try {
          returnValue = runMethod.invoke(bean, args);
        } catch (final IllegalArgumentException e) {
          System.out.println("********************************************************");
          System.out.println("callMethod = " + callMethod);
          System.out.println("runMethod = " + runMethod);
          System.out.println("bean = " + bean.getClass().getName());

          throw e;
        }
      } finally {
        unsetEntityContext(bean);
      }
    } catch (Throwable e) {
      if (e instanceof InvocationTargetException) {
        e = ((InvocationTargetException) e).getTargetException();
      }

      final ExceptionType type = callContext.getBeanContext().getExceptionType(e);
      if (type == ExceptionType.SYSTEM) {
        /* System Exception ****************************/
        handleSystemException(txPolicy, e, callContext);

      } else {
        /* Application Exception ***********************/
        handleApplicationException(txPolicy, e, type == ExceptionType.APPLICATION_ROLLBACK);
      }
    } finally {
      afterInvoke(txPolicy, callContext);
    }

    return returnValue;
  }
예제 #7
0
  @Override
  public Object invoke(
      final Object deployID,
      InterfaceType type,
      final Class callInterface,
      final Method callMethod,
      final Object[] args,
      final Object primKey)
      throws OpenEJBException {
    final BeanContext beanContext = this.getBeanContext(deployID);

    if (beanContext == null) {
      throw new OpenEJBException(
          "Deployment does not exist in this container. Deployment(id='"
              + deployID
              + "'), Container(id='"
              + containerID
              + "')");
    }

    // Use the backup way to determine call type if null was supplied.
    if (type == null) {
      type = beanContext.getInterfaceType(callInterface);
    }

    final ThreadContext callContext = new ThreadContext(beanContext, primKey);

    final ThreadContext oldCallContext = ThreadContext.enter(callContext);
    try {

      final boolean authorized = securityService.isCallerAuthorized(callMethod, type);

      if (!authorized) {
        throw new ApplicationException(
            new EJBAccessException("Unauthorized Access by Principal Denied"));
      }

      final Class declaringClass = callMethod.getDeclaringClass();
      final String methodName = callMethod.getName();

      if (EJBHome.class.isAssignableFrom(declaringClass)
          || EJBLocalHome.class.isAssignableFrom(declaringClass)) {
        if (declaringClass != EJBHome.class && declaringClass != EJBLocalHome.class) {
          if (methodName.startsWith("create")) {
            return createEJBObject(callMethod, args, callContext, type);
          } else if (methodName.equals("findByPrimaryKey")) {
            return findByPrimaryKey(callMethod, args, callContext, type);
          } else if (methodName.startsWith("find")) {
            return findEJBObject(callMethod, args, callContext, type);
          } else {
            return homeMethod(callMethod, args, callContext, type);
          }
        } else if (methodName.equals("remove")) {
          removeEJBObject(callMethod, callContext, type);
          return null;
        }
      } else if ((EJBObject.class == declaringClass || EJBLocalObject.class == declaringClass)
          && methodName.equals("remove")) {
        removeEJBObject(callMethod, callContext, type);
        return null;
      }

      // business method
      callContext.setCurrentOperation(Operation.BUSINESS);
      final Method runMethod = beanContext.getMatchingBeanMethod(callMethod);

      callContext.set(Method.class, runMethod);

      return businessMethod(callMethod, runMethod, args, callContext, type);
    } finally {
      ThreadContext.exit(oldCallContext);
    }
  }