Return-Path: Delivered-To: apmail-openejb-commits-archive@www.apache.org Received: (qmail 79141 invoked from network); 2 Apr 2008 13:32:54 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 2 Apr 2008 13:32:54 -0000 Received: (qmail 70210 invoked by uid 500); 2 Apr 2008 13:32:54 -0000 Delivered-To: apmail-openejb-commits-archive@openejb.apache.org Received: (qmail 70159 invoked by uid 500); 2 Apr 2008 13:32:53 -0000 Mailing-List: contact commits-help@openejb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openejb.apache.org Delivered-To: mailing list commits@openejb.apache.org Received: (qmail 70150 invoked by uid 99); 2 Apr 2008 13:32:53 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Apr 2008 06:32:53 -0700 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 02 Apr 2008 13:32:09 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id C696D1A9832; Wed, 2 Apr 2008 06:32:27 -0700 (PDT) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r643904 - /openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java Date: Wed, 02 Apr 2008 13:32:27 -0000 To: commits@openejb.apache.org From: manugeorge@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080402133227.C696D1A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: manugeorge Date: Wed Apr 2 06:32:25 2008 New Revision: 643904 URL: http://svn.apache.org/viewvc?rev=643904&view=rev Log: reverting back to older revision = 643871 Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java?rev=643904&r1=643903&r2=643904&view=diff ============================================================================== --- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java (original) +++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/stateless/StatelessInstanceManager.java Wed Apr 2 06:32:25 2008 @@ -1,376 +1,368 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.openejb.core.stateless; - -import java.lang.reflect.Method; -import java.rmi.RemoteException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.ejb.SessionBean; -import javax.ejb.SessionContext; -import javax.naming.Context; -import javax.naming.NamingException; -import javax.transaction.TransactionManager; -import javax.xml.ws.WebServiceContext; - -import org.apache.openejb.Injection; -import org.apache.openejb.OpenEJBException; -import org.apache.openejb.SystemException; -import org.apache.openejb.core.BaseContext; -import org.apache.openejb.core.CoreDeploymentInfo; -import org.apache.openejb.core.Operation; -import org.apache.openejb.core.ThreadContext; -import org.apache.openejb.core.interceptor.InterceptorData; -import org.apache.openejb.core.interceptor.InterceptorStack; -import org.apache.openejb.spi.SecurityService; -import org.apache.openejb.util.LinkedListStack; -import org.apache.openejb.util.LogCategory; -import org.apache.openejb.util.Logger; -import org.apache.openejb.util.SafeToolkit; -import org.apache.openejb.util.Stack; -import org.apache.xbean.recipe.ConstructionException; -import org.apache.xbean.recipe.ObjectRecipe; -import org.apache.xbean.recipe.Option; -import org.apache.xbean.recipe.StaticRecipe; - -public class StatelessInstanceManager { - private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources"); - - protected int poolLimit = 0; - protected int beanCount = 0; - protected boolean strictPooling = false; - - protected PoolQueue poolQueue = null; - - protected final SafeToolkit toolkit = SafeToolkit.getToolkit("StatefulInstanceManager"); - private TransactionManager transactionManager; - private SecurityService securityService; - - public StatelessInstanceManager(TransactionManager transactionManager, SecurityService securityService, int timeout, int poolSize, boolean strictPooling) { - this.transactionManager = transactionManager; - this.securityService = securityService; - this.poolLimit = poolSize; - this.strictPooling = strictPooling; - - if (strictPooling && poolSize < 1) { - throw new IllegalArgumentException("Cannot use strict pooling with a pool size less than one. Strict pooling blocks threads till an instance in the pool is available. Please increase the pool size or set strict pooling to false"); - } - - if (this.strictPooling) { - poolQueue = new PoolQueue(timeout); - } - } - - /** - * Removes an instance from the pool and returns it for use - * by the container in business methods. - * - * If the pool is at it's limit the StrictPooling flag will - * cause this thread to wait. - * - * If StrictPooling is not enabled this method will create a - * new stateless bean instance performing all required injection - * and callbacks before returning it in a method ready state. - * - * @param callContext - * @return - * @throws OpenEJBException - */ - public Object getInstance(ThreadContext callContext) - throws OpenEJBException { - CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo(); - Data data = (Data) deploymentInfo.getContainerData(); - Stack pool = data.getPool(); - Object bean = pool.pop(); - if(strictPooling){ - synchronized(pool){ - while (bean == null && pool.size() >= poolLimit) { - poolQueue.waitForAvailableInstance(); - bean = pool.pop(); - } - } - } - if (bean == null) { - - Class beanClass = deploymentInfo.getBeanClass(); - ObjectRecipe objectRecipe = new ObjectRecipe(beanClass); - objectRecipe.allow(Option.FIELD_INJECTION); - objectRecipe.allow(Option.PRIVATE_PROPERTIES); - objectRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); - - Operation originalOperation = callContext.getCurrentOperation(); - BaseContext.State[] originalAllowedStates = callContext.getCurrentAllowedStates(); - - try { - Context ctx = deploymentInfo.getJndiEnc(); - SessionContext sessionContext; - // This needs to be synchronized as this code is multi-threaded. - // In between the lookup and the bind a bind may take place in another Thread. - // This is a fix for GERONIMO-3444 - synchronized(this){ - try { - sessionContext = (SessionContext) ctx.lookup("java:comp/EJBContext"); - } catch (NamingException e1) { - sessionContext = createSessionContext(); - // TODO: This should work - ctx.bind("java:comp/EJBContext", sessionContext); - } - } - if (javax.ejb.SessionBean.class.isAssignableFrom(beanClass) || hasSetSessionContext(beanClass)) { - callContext.setCurrentOperation(Operation.INJECTION); - callContext.setCurrentAllowedStates(StatelessContext.getStates()); - objectRecipe.setProperty("sessionContext", new StaticRecipe(sessionContext)); - } - - WebServiceContext wsContext; - // This is a fix for GERONIMO-3444 - synchronized(this){ - try { - wsContext = (WebServiceContext) ctx.lookup("java:comp/WebServiceContext"); - } catch (NamingException e) { - wsContext = new EjbWsContext(sessionContext); - ctx.bind("java:comp/WebServiceContext", wsContext); - } - } - - fillInjectionProperties(objectRecipe, beanClass, deploymentInfo, ctx); - - bean = objectRecipe.create(beanClass.getClassLoader()); - Map unsetProperties = objectRecipe.getUnsetProperties(); - if (unsetProperties.size() > 0) { - for (Object property : unsetProperties.keySet()) { - logger.warning("Injection: No such property '" + property + "' in class " + beanClass.getName()); - } - } - - HashMap interceptorInstances = new HashMap(); - for (InterceptorData interceptorData : deploymentInfo.getAllInterceptors()) { - if (interceptorData.getInterceptorClass().equals(beanClass)) continue; - - Class clazz = interceptorData.getInterceptorClass(); - ObjectRecipe interceptorRecipe = new ObjectRecipe(clazz); - interceptorRecipe.allow(Option.FIELD_INJECTION); - interceptorRecipe.allow(Option.PRIVATE_PROPERTIES); - interceptorRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); - - fillInjectionProperties(interceptorRecipe, clazz, deploymentInfo, ctx); - - try { - Object interceptorInstance = interceptorRecipe.create(clazz.getClassLoader()); - interceptorInstances.put(clazz.getName(), interceptorInstance); - } catch (ConstructionException e) { - throw new Exception("Failed to create interceptor: " + clazz.getName(), e); - } - } - - interceptorInstances.put(beanClass.getName(), bean); - - - try { - callContext.setCurrentOperation(Operation.POST_CONSTRUCT); - callContext.setCurrentAllowedStates(StatelessContext.getStates()); - - List callbackInterceptors = deploymentInfo.getCallbackInterceptors(); - InterceptorStack interceptorStack = new InterceptorStack(bean, null, Operation.POST_CONSTRUCT, callbackInterceptors, interceptorInstances); - interceptorStack.invoke(); - } catch (Exception e) { - throw e; - } - - try { - if (bean instanceof SessionBean){ - callContext.setCurrentOperation(Operation.CREATE); - callContext.setCurrentAllowedStates(StatelessContext.getStates()); - Method create = deploymentInfo.getCreateMethod(); - InterceptorStack interceptorStack = new InterceptorStack(bean, create, Operation.CREATE, new ArrayList(), new HashMap()); - interceptorStack.invoke(); - } - } catch (Exception e) { - throw e; - } - - bean = new Instance(bean, interceptorInstances); - } catch (Throwable e) { - if (e instanceof java.lang.reflect.InvocationTargetException) { - e = ((java.lang.reflect.InvocationTargetException) e).getTargetException(); - } - String t = "The bean instance " + bean + " threw a system exception:" + e; - logger.error(t, e); - throw new org.apache.openejb.ApplicationException(new RemoteException("Cannot obtain a free instance.", e)); - } finally { - callContext.setCurrentOperation(originalOperation); - callContext.setCurrentAllowedStates(originalAllowedStates); - } - } - return bean; - } - - private static void fillInjectionProperties(ObjectRecipe objectRecipe, Class clazz, CoreDeploymentInfo deploymentInfo, Context context) { - for (Injection injection : deploymentInfo.getInjections()) { - if (!injection.getTarget().isAssignableFrom(clazz)) continue; - try { - String jndiName = injection.getJndiName(); - Object object = context.lookup("java:comp/env/" + jndiName); - if (object instanceof String) { - String string = (String) object; - // Pass it in raw so it could be potentially converted to - // another data type by an xbean-reflect property editor - objectRecipe.setProperty(injection.getTarget().getName() + "/" + injection.getName(), string); - } else { - objectRecipe.setProperty(injection.getTarget().getName() + "/" + injection.getName(), new StaticRecipe(object)); - } - } catch (NamingException e) { - logger.warning("Injection data not found in enc: jndiName='" + injection.getJndiName() + "', target=" + injection.getTarget() + "/" + injection.getName()); - } - } - } - - private boolean hasSetSessionContext(Class beanClass) { - try { - beanClass.getMethod("setSessionContext", SessionContext.class); - return true; - } catch (NoSuchMethodException e) { - return false; - } - } - - private SessionContext createSessionContext() { - return new StatelessContext(transactionManager, securityService); - } - - /** - * All instances are removed from the pool in getInstance(...). They are only - * returned by the StatelessContainer via this method under two circumstances. - * - * 1. The business method returns normally - * 2. The business method throws an application exception - * - * Instances are not returned to the pool if the business method threw a system - * exception. - * - * @param callContext - * @param bean - * @throws OpenEJBException - */ - public void poolInstance(ThreadContext callContext, Object bean) throws OpenEJBException { - if (bean == null) { - throw new SystemException("Invalid arguments"); - } - - CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo(); - Data data = (Data) deploymentInfo.getContainerData(); - Stack pool = data.getPool(); - - if (strictPooling) { - synchronized (pool) { - if (pool.size() < poolLimit) { - pool.push(bean); - poolQueue.notifyWaitingThreads(); - } else { - freeInstance(callContext, (Instance) bean); - } - } - } else { - if (pool.size() >= poolLimit) { - freeInstance(callContext, (Instance)bean); - } else { - pool.push(bean); - } - } - } - - private void freeInstance(ThreadContext callContext, Instance instance) { - try { - callContext.setCurrentOperation(Operation.PRE_DESTROY); - callContext.setCurrentAllowedStates(StatelessContext.getStates()); - CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo(); - - Method remove = instance.bean instanceof SessionBean? deploymentInfo.getCreateMethod(): null; - - List callbackInterceptors = deploymentInfo.getCallbackInterceptors(); - InterceptorStack interceptorStack = new InterceptorStack(instance.bean, remove, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors); - - interceptorStack.invoke(); - } catch (Throwable re) { - logger.error("The bean instance " + instance + " threw a system exception:" + re, re); - } - - } - - /** - * This method has no work to do as all instances are removed from - * the pool on getInstance(...) and not returned via poolInstance(...) - * if they threw a system exception. - * - * @param callContext - * @param bean - */ - public void discardInstance(ThreadContext callContext, Object bean) { - - } - - public void deploy(CoreDeploymentInfo deploymentInfo) { - Data data = new Data(poolLimit); - deploymentInfo.setContainerData(data); - } - - public void undeploy(CoreDeploymentInfo deploymentInfo) { - Data data = (Data) deploymentInfo.getContainerData(); - if (data == null) return; - Stack pool = data.getPool(); - //TODO ejbRemove on each bean in pool. - //clean pool - deploymentInfo.setContainerData(null); - } - - static class PoolQueue { - private final long waitPeriod; - - public PoolQueue(long time) { - waitPeriod = time; - } - - public synchronized void waitForAvailableInstance() - throws org.apache.openejb.InvalidateReferenceException { - try { - wait(waitPeriod); - } catch (InterruptedException ie) { - throw new org.apache.openejb.InvalidateReferenceException(new RemoteException("No instance available to service request", ie)); - } - } - - public synchronized void notifyWaitingThreads() { - notify(); - } - } - - private static final class Data { - private final Stack pool; - - public Data(int poolLimit) { - pool = new LinkedListStack(poolLimit); - } - - public Stack getPool() { - return pool; - } - } - -} +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.core.stateless; + +import java.lang.reflect.Method; +import java.rmi.RemoteException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.ejb.SessionBean; +import javax.ejb.SessionContext; +import javax.naming.Context; +import javax.naming.NamingException; +import javax.transaction.TransactionManager; +import javax.xml.ws.WebServiceContext; + +import org.apache.openejb.Injection; +import org.apache.openejb.OpenEJBException; +import org.apache.openejb.SystemException; +import org.apache.openejb.core.BaseContext; +import org.apache.openejb.core.CoreDeploymentInfo; +import org.apache.openejb.core.Operation; +import org.apache.openejb.core.ThreadContext; +import org.apache.openejb.core.interceptor.InterceptorData; +import org.apache.openejb.core.interceptor.InterceptorStack; +import org.apache.openejb.spi.SecurityService; +import org.apache.openejb.util.LinkedListStack; +import org.apache.openejb.util.LogCategory; +import org.apache.openejb.util.Logger; +import org.apache.openejb.util.SafeToolkit; +import org.apache.openejb.util.Stack; +import org.apache.xbean.recipe.ConstructionException; +import org.apache.xbean.recipe.ObjectRecipe; +import org.apache.xbean.recipe.Option; +import org.apache.xbean.recipe.StaticRecipe; + +public class StatelessInstanceManager { + private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.util.resources"); + + protected int poolLimit = 0; + protected int beanCount = 0; + protected boolean strictPooling = false; + + protected PoolQueue poolQueue = null; + + protected final SafeToolkit toolkit = SafeToolkit.getToolkit("StatefulInstanceManager"); + private TransactionManager transactionManager; + private SecurityService securityService; + + public StatelessInstanceManager(TransactionManager transactionManager, SecurityService securityService, int timeout, int poolSize, boolean strictPooling) { + this.transactionManager = transactionManager; + this.securityService = securityService; + this.poolLimit = poolSize; + this.strictPooling = strictPooling; + + if (strictPooling && poolSize < 1) { + throw new IllegalArgumentException("Cannot use strict pooling with a pool size less than one. Strict pooling blocks threads till an instance in the pool is available. Please increase the pool size or set strict pooling to false"); + } + + if (this.strictPooling) { + poolQueue = new PoolQueue(timeout); + } + } + + /** + * Removes an instance from the pool and returns it for use + * by the container in business methods. + * + * If the pool is at it's limit the StrictPooling flag will + * cause this thread to wait. + * + * If StrictPooling is not enabled this method will create a + * new stateless bean instance performing all required injection + * and callbacks before returning it in a method ready state. + * + * @param callContext + * @return + * @throws OpenEJBException + */ + public Object getInstance(ThreadContext callContext) + throws OpenEJBException { + CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo(); + Data data = (Data) deploymentInfo.getContainerData(); + Stack pool = data.getPool(); + Object bean = pool.pop(); + + while (strictPooling && bean == null && pool.size() >= poolLimit) { + poolQueue.waitForAvailableInstance(); + bean = pool.pop(); + } + + if (bean == null) { + + Class beanClass = deploymentInfo.getBeanClass(); + ObjectRecipe objectRecipe = new ObjectRecipe(beanClass); + objectRecipe.allow(Option.FIELD_INJECTION); + objectRecipe.allow(Option.PRIVATE_PROPERTIES); + objectRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); + + Operation originalOperation = callContext.getCurrentOperation(); + BaseContext.State[] originalAllowedStates = callContext.getCurrentAllowedStates(); + + try { + Context ctx = deploymentInfo.getJndiEnc(); + SessionContext sessionContext; + // This needs to be synchronized as this code is multi-threaded. + // In between the lookup and the bind a bind may take place in another Thread. + // This is a fix for GERONIMO-3444 + synchronized(this){ + try { + sessionContext = (SessionContext) ctx.lookup("java:comp/EJBContext"); + } catch (NamingException e1) { + sessionContext = createSessionContext(); + // TODO: This should work + ctx.bind("java:comp/EJBContext", sessionContext); + } + } + if (javax.ejb.SessionBean.class.isAssignableFrom(beanClass) || hasSetSessionContext(beanClass)) { + callContext.setCurrentOperation(Operation.INJECTION); + callContext.setCurrentAllowedStates(StatelessContext.getStates()); + objectRecipe.setProperty("sessionContext", new StaticRecipe(sessionContext)); + } + + WebServiceContext wsContext; + // This is a fix for GERONIMO-3444 + synchronized(this){ + try { + wsContext = (WebServiceContext) ctx.lookup("java:comp/WebServiceContext"); + } catch (NamingException e) { + wsContext = new EjbWsContext(sessionContext); + ctx.bind("java:comp/WebServiceContext", wsContext); + } + } + + fillInjectionProperties(objectRecipe, beanClass, deploymentInfo, ctx); + + bean = objectRecipe.create(beanClass.getClassLoader()); + Map unsetProperties = objectRecipe.getUnsetProperties(); + if (unsetProperties.size() > 0) { + for (Object property : unsetProperties.keySet()) { + logger.warning("Injection: No such property '" + property + "' in class " + beanClass.getName()); + } + } + + HashMap interceptorInstances = new HashMap(); + for (InterceptorData interceptorData : deploymentInfo.getAllInterceptors()) { + if (interceptorData.getInterceptorClass().equals(beanClass)) continue; + + Class clazz = interceptorData.getInterceptorClass(); + ObjectRecipe interceptorRecipe = new ObjectRecipe(clazz); + interceptorRecipe.allow(Option.FIELD_INJECTION); + interceptorRecipe.allow(Option.PRIVATE_PROPERTIES); + interceptorRecipe.allow(Option.IGNORE_MISSING_PROPERTIES); + + fillInjectionProperties(interceptorRecipe, clazz, deploymentInfo, ctx); + + try { + Object interceptorInstance = interceptorRecipe.create(clazz.getClassLoader()); + interceptorInstances.put(clazz.getName(), interceptorInstance); + } catch (ConstructionException e) { + throw new Exception("Failed to create interceptor: " + clazz.getName(), e); + } + } + + interceptorInstances.put(beanClass.getName(), bean); + + + try { + callContext.setCurrentOperation(Operation.POST_CONSTRUCT); + callContext.setCurrentAllowedStates(StatelessContext.getStates()); + + List callbackInterceptors = deploymentInfo.getCallbackInterceptors(); + InterceptorStack interceptorStack = new InterceptorStack(bean, null, Operation.POST_CONSTRUCT, callbackInterceptors, interceptorInstances); + interceptorStack.invoke(); + } catch (Exception e) { + throw e; + } + + try { + if (bean instanceof SessionBean){ + callContext.setCurrentOperation(Operation.CREATE); + callContext.setCurrentAllowedStates(StatelessContext.getStates()); + Method create = deploymentInfo.getCreateMethod(); + InterceptorStack interceptorStack = new InterceptorStack(bean, create, Operation.CREATE, new ArrayList(), new HashMap()); + interceptorStack.invoke(); + } + } catch (Exception e) { + throw e; + } + + bean = new Instance(bean, interceptorInstances); + } catch (Throwable e) { + if (e instanceof java.lang.reflect.InvocationTargetException) { + e = ((java.lang.reflect.InvocationTargetException) e).getTargetException(); + } + String t = "The bean instance " + bean + " threw a system exception:" + e; + logger.error(t, e); + throw new org.apache.openejb.ApplicationException(new RemoteException("Cannot obtain a free instance.", e)); + } finally { + callContext.setCurrentOperation(originalOperation); + callContext.setCurrentAllowedStates(originalAllowedStates); + } + } + return bean; + } + + private static void fillInjectionProperties(ObjectRecipe objectRecipe, Class clazz, CoreDeploymentInfo deploymentInfo, Context context) { + for (Injection injection : deploymentInfo.getInjections()) { + if (!injection.getTarget().isAssignableFrom(clazz)) continue; + try { + String jndiName = injection.getJndiName(); + Object object = context.lookup("java:comp/env/" + jndiName); + if (object instanceof String) { + String string = (String) object; + // Pass it in raw so it could be potentially converted to + // another data type by an xbean-reflect property editor + objectRecipe.setProperty(injection.getTarget().getName() + "/" + injection.getName(), string); + } else { + objectRecipe.setProperty(injection.getTarget().getName() + "/" + injection.getName(), new StaticRecipe(object)); + } + } catch (NamingException e) { + logger.warning("Injection data not found in enc: jndiName='" + injection.getJndiName() + "', target=" + injection.getTarget() + "/" + injection.getName()); + } + } + } + + private boolean hasSetSessionContext(Class beanClass) { + try { + beanClass.getMethod("setSessionContext", SessionContext.class); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } + + private SessionContext createSessionContext() { + return new StatelessContext(transactionManager, securityService); + } + + /** + * All instances are removed from the pool in getInstance(...). They are only + * returned by the StatelessContainer via this method under two circumstances. + * + * 1. The business method returns normally + * 2. The business method throws an application exception + * + * Instances are not returned to the pool if the business method threw a system + * exception. + * + * @param callContext + * @param bean + * @throws OpenEJBException + */ + public void poolInstance(ThreadContext callContext, Object bean) throws OpenEJBException { + if (bean == null) { + throw new SystemException("Invalid arguments"); + } + + CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo(); + Data data = (Data) deploymentInfo.getContainerData(); + Stack pool = data.getPool(); + + if (strictPooling) { + pool.push(bean); + poolQueue.notifyWaitingThreads(); + } else { + if (pool.size() >= poolLimit) { + freeInstance(callContext, (Instance)bean); + } else { + pool.push(bean); + } + } + } + + private void freeInstance(ThreadContext callContext, Instance instance) { + try { + callContext.setCurrentOperation(Operation.PRE_DESTROY); + callContext.setCurrentAllowedStates(StatelessContext.getStates()); + CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo(); + + Method remove = instance.bean instanceof SessionBean? deploymentInfo.getCreateMethod(): null; + + List callbackInterceptors = deploymentInfo.getCallbackInterceptors(); + InterceptorStack interceptorStack = new InterceptorStack(instance.bean, remove, Operation.PRE_DESTROY, callbackInterceptors, instance.interceptors); + + interceptorStack.invoke(); + } catch (Throwable re) { + logger.error("The bean instance " + instance + " threw a system exception:" + re, re); + } + + } + + /** + * This method has no work to do as all instances are removed from + * the pool on getInstance(...) and not returned via poolInstance(...) + * if they threw a system exception. + * + * @param callContext + * @param bean + */ + public void discardInstance(ThreadContext callContext, Object bean) { + + } + + public void deploy(CoreDeploymentInfo deploymentInfo) { + Data data = new Data(poolLimit); + deploymentInfo.setContainerData(data); + } + + public void undeploy(CoreDeploymentInfo deploymentInfo) { + Data data = (Data) deploymentInfo.getContainerData(); + if (data == null) return; + Stack pool = data.getPool(); + //TODO ejbRemove on each bean in pool. + //clean pool + deploymentInfo.setContainerData(null); + } + + static class PoolQueue { + private final long waitPeriod; + + public PoolQueue(long time) { + waitPeriod = time; + } + + public synchronized void waitForAvailableInstance() + throws org.apache.openejb.InvalidateReferenceException { + try { + wait(waitPeriod); + } catch (InterruptedException ie) { + throw new org.apache.openejb.InvalidateReferenceException(new RemoteException("No instance available to service request", ie)); + } + } + + public synchronized void notifyWaitingThreads() { + notify(); + } + } + + private static final class Data { + private final Stack pool; + + public Data(int poolLimit) { + pool = new LinkedListStack(poolLimit); + } + + public Stack getPool() { + return pool; + } + } + +}