All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.sun.ejb.EjbInvocation Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2022 Contributors to the Eclipse Foundation
 * Copyright (c) 1997, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package com.sun.ejb;

import com.sun.ejb.containers.BaseContainer;
import com.sun.ejb.containers.EJBContextImpl;
import com.sun.ejb.containers.EJBLocalRemoteObject;
import com.sun.ejb.containers.EjbContainerUtilImpl;
import com.sun.ejb.containers.EjbFutureTask;
import com.sun.ejb.containers.SimpleEjbResourceHandlerImpl;
import com.sun.ejb.containers.interceptors.InterceptorManager;
import com.sun.ejb.containers.interceptors.InterceptorUtil;
import com.sun.enterprise.deployment.EjbBundleDescriptor;
import com.sun.enterprise.deployment.MethodDescriptor;
import com.sun.enterprise.transaction.spi.TransactionOperationsManager;

import jakarta.ejb.EJBContext;
import jakarta.ejb.Timer;
import jakarta.interceptor.InvocationContext;
import jakarta.transaction.Transaction;
import jakarta.xml.soap.SOAPMessage;
import jakarta.xml.ws.WebServiceContext;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.rmi.UnmarshalException;
import java.util.HashMap;
import java.util.Map;

import javax.naming.NameNotFoundException;

import org.glassfish.api.invocation.ComponentInvocation;
import org.glassfish.api.invocation.ResourceHandler;
import org.glassfish.ejb.api.EJBInvocation;

/**
 * The EjbInvocation object contains state associated with an invocation on an EJB or EJBHome
 * (local/remote).
 * 

* It is usually created by generated code in *ObjectImpl and *HomeImpl classes. It is passed as * a parameter to Container.preInvoke() * and postInvoke(), which are called by * the EJB(Local)Object/EJB(Local)Home before and after an invocation. */ public class EjbInvocation extends ComponentInvocation implements InvocationContext, TransactionOperationsManager, EJBInvocation, InterceptorManager.AroundInvokeContext { public ComponentContext context; private TransactionOperationsManager transactionOperationsManager; EjbInvocation(String compEnvId, Container container) { super.componentId = compEnvId; super.container = container; super.setComponentInvocationType(ComponentInvocation.ComponentInvocationType.EJB_INVOCATION); EjbBundleDescriptor ejbBundleDesc = container.getEjbDescriptor().getEjbBundleDescriptor(); moduleName = ejbBundleDesc.getModuleName(); appName = ejbBundleDesc.getApplication().getAppName(); // By default we enable TransactionOperationsManager checks. But EjbInvocation.clone() // clears transactionOperationsManager so that, be default, cloned invocations // doesn't enforce Transaction Operations checks. transactionOperationsManager = this; } /** * The EJBObject/EJBLocalObject which created this EjbInvocation object. This identifies the target bean. */ public EJBLocalRemoteObject ejbObject; /** * Local flag: true if this invocation was through the 2.x (or earlier) Local client view, the 3.x local client view or a * no-interface client view. */ public boolean isLocal = false; /** * True if this invocation was made through the 2.x (or earlier) Remote client view or the 3.x remote client view. */ public boolean isRemote = false; /** * InvocationInfo object caches information about the current method */ public InvocationInfo invocationInfo; /** * True if this invocation was made through a local business interface or bean local view or a remote business interface. */ public boolean isBusinessInterface; /** * true if this is a web service invocation */ public boolean isWebService = false; /** * true if this is an ejb timeout method invocation */ public boolean isTimerCallback = false; /** * true if this is a message-driven bean invocation */ public boolean isMessageDriven = false; /** * true if this is an invocation on the home object this is required for jacc. */ public boolean isHome = false; /** * Home, Remote, LocalHome, Local, WebService, or business interface through which a synchronous ejb invocation was made. */ public Class clientInterface; /** * Method to be invoked. This is a method of the EJB's local/remote component interface for invocations on EJB(Local)Objects, or * of the local/remote Home interface for invocations on the EJBHome. Set by the EJB(Local)Object/EJB(Local)Home before calling * Container.preInvoke(). */ public java.lang.reflect.Method method; /** * The EJB instance to be invoked. Set by Container and used by EJBObject/EJBHome. */ public Object ejb; /** * This reflects any exception that has occurred during this invocation, including preInvoke, bean method execution, and * postInvoke. */ public Throwable exception; /** * Set to any exception directly thrown from bean method invocation, which could be either an application exception or a runtime * exception. This is set *in addition to* the this.exception field. Some container processing logic, e.g. @Remove, depends * specifically on whether a bean method threw an exception. */ public Throwable exceptionFromBeanMethod; /** * The client's transaction if any. Set by the Container during preInvoke() and used by the Container during postInvoke(). */ public Transaction clientTx; /** * The EJBContext object of the bean instance being invoked. Set by the Container during preInvoke() and used by the Container * during postInvoke(). */ // Moved to com/sun/enterprise/ComponentInvocation // public ComponentContext context; /** * The transaction attribute of the bean method. Set in generated EJBObject/Home/LocalObject/LocalHome class. */ public int transactionAttribute; /** * Used by MessageBeanContainer. true if container started a transaction for this invocation. */ private boolean containerStartsTx; /** * Used by MessageBeanContainer to keep track of the context class loader that was active before message delivery began. */ private ClassLoader originalContextClassLoader; /** * Used for JACC PolicyContextHandlers. The handler can query the container back for parameters on the ejb. This is set during * the method invocation and is not available for preInvoke calls. */ public Object[] methodParams; public Timer timer; /** * Result of txManager.getStatus() performed at the beginning of BaseContainer.preInvoke() and valid up until preinvokeTx(). * txManager.getStatus() accesses a thread-local which is an expensive operation. Storing status in the invocation makes it * easier for some of the other early pre-invoke operations to re-use it. */ private Integer preInvokeTxStatus; /** * Tells if a CMP2.x bean was found in the Tx cache. Applicable only for CMP2.x beans */ public boolean foundInTxCache = false; /** * Tells if a fast path can be taken for a business method invocation. */ public boolean useFastPath = false; private java.util.concurrent.locks.Lock cmcLock; private boolean doTxProcessingInPostInvoke; private long invId; private boolean yetToSubmitStatus = true; private EjbFutureTask asyncFuture; private boolean wasCancelCalled = false; private Method webServiceMethod; // True if lock is currently held for this invocation private boolean holdingSFSBSerializedLock = false; public ClassLoader getOriginalContextClassLoader() { return originalContextClassLoader; } public void setOriginalContextClassLoader(ClassLoader originalContextClassLoader) { this.originalContextClassLoader = originalContextClassLoader; } public EjbFutureTask getEjbFutureTask() { return asyncFuture; } public void setEjbFutureTask(EjbFutureTask future) { asyncFuture = future; } public void setWasCancelCalled(boolean flag) { wasCancelCalled = flag; } public boolean getWasCancelCalled() { return wasCancelCalled; } public long getInvId() { return invId; } public void setInvId(long invId) { this.invId = invId; } public boolean mustInvokeAsynchronously() { return (invocationInfo != null) && invocationInfo.isAsynchronous() && yetToSubmitStatus; } public void clearYetToSubmitStatus() { yetToSubmitStatus = false; } public boolean getDoTxProcessingInPostInvoke() { return doTxProcessingInPostInvoke; } public void setDoTxProcessingInPostInvoke(boolean doTxProcessingInPostInvoke) { this.doTxProcessingInPostInvoke = doTxProcessingInPostInvoke; } @Override public EjbInvocation clone() { EjbInvocation newInv = (EjbInvocation) super.clone(); newInv.ejb = null; newInv.exception = null; newInv.exceptionFromBeanMethod = null; newInv.clientTx = null; newInv.preInvokeTxStatus = null; newInv.originalContextClassLoader = null; //The cloned invocation contains a ResourceHandler that points to the same // resource list as the original invocation. If any one of these resource lists // are modified, then we may get a ConcurrentModification exception. // //To avoid this, we will create a new ResourceHandler for the cloned invocation. I // have simply reused SimpleEjbResourceHandlerImpl that was used in async Ejb invocation. newInv.setResourceHandler( SimpleEjbResourceHandlerImpl.createResourceHandler(EjbContainerUtilImpl.getInstance().getTransactionManager())); //The cloned invocation is most likely to be used for running a batch task. // In this case, we don't want TransactionOperationsManager restricting the Batch runtime // from performing a java:comp/UserTransaction lookup. So, we explicitly set a null // TransactionOperationsManager in this case. newInv.setTransactionOperationsManager(null); //We also don't want any JPA EMs registry entries from being shared. newInv.clearRegistry(); return newInv; } @Override public Object getJaccEjb() { if (container == null) { return null; } return ((Container) container).getJaccEjb(this); } /** * This method returns the method interface constant for this EjbInvocation. */ public String getMethodInterface() { if (isWebService) { return MethodDescriptor.EJB_WEB_SERVICE; } else if (isMessageDriven) { return MethodDescriptor.EJB_BEAN; } else if (isLocal) { return (isHome) ? MethodDescriptor.EJB_LOCALHOME : MethodDescriptor.EJB_LOCAL; } else { return (isHome) ? MethodDescriptor.EJB_HOME : MethodDescriptor.EJB_REMOTE; } } /** * Returns CachedPermission associated with this invocation, or null if not available. */ public Object getCachedPermission() { return (invocationInfo != null) ? invocationInfo.cachedPermission : null; } /** * @return Returns the ejbCtx. */ @Override public EJBContext getEJBContext() { return (EJBContext) this.context; } public Integer getPreInvokeTxStatus() { return preInvokeTxStatus; } public void setPreInvokeTxStatus(Integer txStatus) { // Can be null, which means preInvokeTxStatus is no longer applicable. preInvokeTxStatus = txStatus; } public java.util.concurrent.locks.Lock getCMCLock() { return cmcLock; } public void setCMCLock(java.util.concurrent.locks.Lock l) { cmcLock = l; } public boolean holdingSFSBSerializedLock() { return this.holdingSFSBSerializedLock; } public void setHoldingSFSBSerializedLock(boolean flag) { holdingSFSBSerializedLock = flag; } @Override public Object getTransactionOperationsManager() { return transactionOperationsManager; } public void setTransactionOperationsManager(TransactionOperationsManager transactionOperationsManager) { //Note: clone() clears transactionOperationsManager so that, be default, cloned invocations // doesn't enforce Transaction Operations checks. this.transactionOperationsManager = transactionOperationsManager; } //Implementation of TransactionOperationsManager methods /** * Called by the UserTransaction implementation to verify access to the UserTransaction methods. */ @Override public boolean userTransactionMethodsAllowed() { return ((Container) container).userTransactionMethodsAllowed(this); } /** * Called by the UserTransaction lookup to verify access to the UserTransaction itself. */ @Override public void userTransactionLookupAllowed() throws NameNotFoundException { ((BaseContainer) container).checkUserTransactionLookup(this); } /** * Called by the UserTransaction when transaction is started. */ @Override public void doAfterUtxBegin() { ((Container) container).doAfterBegin(this); } //Implementation of InvocationContext methods private int interceptorIndex; public Method beanMethod; // Only set for web service invocations. private WebServiceContext webServiceContext; // Only set for EJB JAXWS //FIXME: private Message message = null; private Object message; private SOAPMessage soapMessage = null; private Map contextData; public InterceptorManager.InterceptorChain getInterceptorChain() { return (invocationInfo == null) ? null : invocationInfo.interceptorChain; } /** * @return Returns the bean instance. */ @Override public Object getTarget() { return this.ejb; } /** * @return Returns the timer instance. */ @Override public Object getTimer() { return timer; } /** * @return For AroundInvoke/AroundTimeout methods, returns the bean class method being invoked. For lifecycle callback methods, * returns null. */ @Override public Method getMethod() { return getBeanMethod(); } public Method getBeanMethod() { return this.beanMethod; } @Override public Constructor getConstructor() { return null; } /** * @return Returns the parameters that will be used to invoke the business method. If setParameters has been called, * getParameters() returns the values to which the parameters have been set. */ @Override public Object[] getParameters() { return this.methodParams; } /** * Set the parameters that will be used to invoke the business method. * */ @Override public void setParameters(Object[] params) { InterceptorUtil.checkSetParameters(params, getMethod()); this.methodParams = params; } /* * Method takes Object to decouple EJBInvocation interface * from jaxws (which isn't available in all profiles). */ @Override public void setWebServiceContext(Object webServiceContext) { // shouldn't be necessary, but to be safe if (webServiceContext instanceof WebServiceContext) { this.webServiceContext = (WebServiceContext) webServiceContext; } } /** * @return Returns the contextMetaData. */ @Override public Map getContextData() { if (this.contextData == null) { if (webServiceContext != null) { this.contextData = webServiceContext.getMessageContext(); } else { this.contextData = new HashMap(); } } return contextData; } /** * This is for EJB JAXWS only. * * @param message an unconsumed message */ @Override public void setMessage(T message) { this.message = message; } /** * This is for EJB JAXWS only. * * @return the JAXWS message */ @Override public Object getMessage() { return this.message; } /** * This is for EJB JAXWS only. */ public SOAPMessage getSOAPMessage() { if (message != null && soapMessage == null) { try { //FIXME: soapMessage = message.readAsSOAPMessage(); soapMessage = (SOAPMessage) message; } catch (Exception e) { throw new RuntimeException(e); } //message consumed, set it to null message = null; } return soapMessage; } /* (non-Javadoc) * @see jakarta.interceptor.InvocationContext#proceed() */ @Override public Object proceed() throws Exception { try { //TODO: Internal error if getInterceptorChain() is null interceptorIndex++; return getInterceptorChain().invokeNext(interceptorIndex, this); } catch (Exception ex) { throw ex; } catch (Error error) { throw error; } catch (Throwable t) { // This shouldn't be possible since we specifically catch // Exception and Error before this, but ... throw new RuntimeException(t); } finally { interceptorIndex--; } } /** * Print most useful fields. Don't do all of them (yet) since there are a large number. * * @return */ @Override public String toString() { StringBuffer sbuf = new StringBuffer(); sbuf.append("EjbInvocation "); sbuf.append("componentId=" + getComponentId()); sbuf.append(",isLocal=" + isLocal); sbuf.append(",isRemote=" + isRemote); sbuf.append(",isBusinessInterface=" + isBusinessInterface); sbuf.append(",isWebService=" + isWebService); sbuf.append(",isMessageDriven=" + isMessageDriven); sbuf.append(",isHome=" + isHome); sbuf.append(",clientInterface=" + clientInterface); sbuf.append(",method=" + method); sbuf.append(",ejb=" + ejb); sbuf.append(",exception=" + exception); sbuf.append(",exceptionFromBeanMethod=" + exceptionFromBeanMethod); sbuf.append(",invId=" + invId); sbuf.append(",wasCancelCalled=" + wasCancelCalled); sbuf.append(",yetToSubmitStatus=" + yetToSubmitStatus); return sbuf.toString(); } // Implementation of AroundInvokeContext @Override public Object[] getInterceptorInstances() { return ((EJBContextImpl) context).getInterceptorInstances(); } @Override public Object invokeBeanMethod() throws Throwable { return ((BaseContainer) container).invokeBeanMethod(this); } /*********************************************************/ public com.sun.enterprise.security.SecurityManager getEjbSecurityManager() { return ((BaseContainer) container).getSecurityManager(); } @Override public boolean isAWebService() { return this.isWebService; } @Override public Object[] getMethodParams() { return this.methodParams; } @Override public boolean authorizeWebService(Method m) throws Exception { Exception ie = null; if (isAWebService()) { try { this.method = m; if (!((com.sun.ejb.Container) container).authorize(this)) { ie = new Exception("Client not authorized for invocation of method {" + method + "}"); } else { // Record the method on which the successful // authorization check was performed. setWebServiceMethod(m); } } catch (Exception e) { String errorMsg = "Error unmarshalling method {" + method + "} for ejb "; ie = new UnmarshalException(errorMsg); ie.initCause(e); } if (ie != null) { exception = ie; throw ie; } } else { setWebServiceMethod(null); } return true; } /** * Implements the method in org.glassfish.ejb.api.EJBInvocation * * @return true if the SecurityManager reports that the caller is in role */ @Override public boolean isCallerInRole(String role) { return getEjbSecurityManager().isCallerInRole(role); } @Override public void setWebServiceMethod(Method method) { webServiceMethod = method; } @Override public Method getWebServiceMethod() { return webServiceMethod; } @Override public ResourceHandler getResourceHandler() { ResourceHandler rh = super.getResourceHandler(); if (rh == null) { rh = context; } return rh; } public boolean isContainerStartsTx() { return containerStartsTx; } public void setContainerStartsTx(boolean containerStartsTx) { this.containerStartsTx = containerStartsTx; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy