[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openejb-cvs
Subject:    svn commit: r672684 - in /openejb/trunk/openejb3: api/ejb31-api-experimental/
From:       dblevins () apache ! org
Date:       2008-06-30 0:00:26
Message-ID: 20080630000027.2C0E22388A02 () eris ! apache ! org
[Download RAW message or body]

Author: dblevins
Date: Sun Jun 29 17:00:25 2008
New Revision: 672684

URL: http://svn.apache.org/viewvc?rev=672684&view=rev
Log:
Good chunk of the container side of the following:
OPENEJB-837: Singleton Bean-Managed Concurrency
OPENEJB-838: Singleton Container-Managed Concurrency
OPENEJB-839: ReadOnly and ReadWrite method locking

No deployment support yet, though

Added:
    openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagement.java
  openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagementType.java
  openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrentAccessTimeoutException.java
  openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Lock.java
    openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/LockType.java
  openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Duration.java
  openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DurationTest.java
 Modified:
    openejb/trunk/openejb3/api/ejb31-api-experimental/pom.xml
    openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
  openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/Instance.java
  openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
  openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java
  openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
  openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml


Modified: openejb/trunk/openejb3/api/ejb31-api-experimental/pom.xml
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/pom.xml?rev=672684&r1=672683&r2=672684&view=diff
 ==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/pom.xml (original)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/pom.xml Sun Jun 29 17:00:25 \
2008 @@ -27,4 +27,12 @@
   <packaging>jar</packaging>
   <name>OpenEJB :: APIs :: EJB 3.1 Experimental</name>
 
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.openejb</groupId>
+      <artifactId>javaee-api</artifactId>
+      <version>5.0-1</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
 </project>

Added: openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagement.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagement.java?rev=672684&view=auto
 ==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagement.java \
                (added)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagement.java \
Sun Jun 29 17:00:25 2008 @@ -0,0 +1,12 @@
+package javax.ejb;
+
+import static javax.ejb.ConcurrencyManagementType.CONTAINER;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
+
+@java.lang.annotation.Target(value = {METHOD, TYPE})
+@java.lang.annotation.Retention(value = RUNTIME)
+public @interface ConcurrencyManagement {
+    javax.ejb.ConcurrencyManagementType value() default CONTAINER;
+}

Added: openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagementType.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagementType.java?rev=672684&view=auto
 ==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagementType.java \
                (added)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrencyManagementType.java \
Sun Jun 29 17:00:25 2008 @@ -0,0 +1,30 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ */
+
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.ejb;
+
+/**
+ * @version $Revision$ $Date$
+ */
+public enum ConcurrencyManagementType {
+    CONTAINER, BEAN;
+}

Added: openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrentAccessTimeoutException.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrentAccessTimeoutException.java?rev=672684&view=auto
 ==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrentAccessTimeoutException.java \
                (added)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/ConcurrentAccessTimeoutException.java \
Sun Jun 29 17:00:25 2008 @@ -0,0 +1,40 @@
+/**
+ *
+ * Copyright 2006 The Apache Software Foundation
+ *
+ *  Licensed 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.
+ */
+
+//
+// This source code implements specifications defined by the Java
+// Community Process. In order to remain compliant with the specification
+// DO NOT add / change / or delete method signatures!
+//
+package javax.ejb;
+
+/**
+ * @version $Revision$ $Date$
+ */
+public class ConcurrentAccessTimeoutException extends \
javax.ejb.ConcurrentAccessException { +
+    public ConcurrentAccessTimeoutException() {
+    }
+
+    public ConcurrentAccessTimeoutException(String string) {
+        super(string);
+    }
+
+    public ConcurrentAccessTimeoutException(String string, Exception exception) {
+        super(string, exception);
+    }
+}

Added: openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Lock.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Lock.java?rev=672684&view=auto
 ==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Lock.java \
                (added)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/Lock.java \
Sun Jun 29 17:00:25 2008 @@ -0,0 +1,12 @@
+package javax.ejb;
+
+import static javax.ejb.LockType.WRITE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.ElementType.METHOD;
+
+@java.lang.annotation.Target(value = {METHOD, TYPE})
+@java.lang.annotation.Retention(value = RUNTIME)
+public @interface Lock {
+    javax.ejb.LockType value() default WRITE;
+}

Added: openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/LockType.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/LockType.java?rev=672684&view=auto
 ==============================================================================
--- openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/LockType.java \
                (added)
+++ openejb/trunk/openejb3/api/ejb31-api-experimental/src/main/java/javax/ejb/LockType.java \
Sun Jun 29 17:00:25 2008 @@ -0,0 +1,8 @@
+package javax.ejb;
+
+/**
+ * @version $Revision$ $Date$
+ */
+public enum LockType {
+    WRITE, READ;
+}

Modified: openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/assembly/openejb-tomcat/opene \
jb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml?rev=672684&r1=672683&r2=672684&view=diff
 ==============================================================================
--- openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml \
                (original)
+++ openejb/trunk/openejb3/assembly/openejb-tomcat/openejb-tomcat-webapp/src/main/resources/META-INF/org.apache.openejb.tomcat/service-jar.xml \
Sun Jun 29 17:00:25 2008 @@ -132,6 +132,8 @@
           constructor="id, transactionManager, securityService"
           class-name="org.apache.openejb.core.singleton.SingletonContainer">
 
+    AccessTimeout = 30 seconds
+    
   </ServiceProvider>
 
 

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/Instance.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/ma \
in/java/org/apache/openejb/core/singleton/Instance.java?rev=672684&r1=672683&r2=672684&view=diff
 ==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/Instance.java \
                (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/Instance.java \
Sun Jun 29 17:00:25 2008 @@ -16,9 +16,8 @@
  */
 package org.apache.openejb.core.singleton;
 
-import java.util.List;
-import java.util.Collections;
 import java.util.Map;
+import java.util.concurrent.locks.ReadWriteLock;
 
 /**
  * @version $Rev$ $Date$
@@ -26,9 +25,11 @@
 public class Instance {
     public final Object bean;
     public final Map<String,Object> interceptors;
+    public final ReadWriteLock lock;
 
-    public Instance(Object bean, Map<String, Object> interceptors) {
+    public Instance(Object bean, Map<String, Object> interceptors, ReadWriteLock \
lock) {  this.bean = bean;
         this.interceptors = interceptors;
+        this.lock = lock;
     }
 }

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/ma \
in/java/org/apache/openejb/core/singleton/SingletonContainer.java?rev=672684&r1=672683&r2=672684&view=diff
 ==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java \
                (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonContainer.java \
Sun Jun 29 17:00:25 2008 @@ -21,12 +21,15 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.TimeUnit;
 
 import javax.ejb.EJBAccessException;
 import javax.ejb.EJBHome;
 import javax.ejb.EJBLocalHome;
 import javax.ejb.EJBLocalObject;
 import javax.ejb.EJBObject;
+import javax.ejb.ConcurrentAccessTimeoutException;
 import javax.interceptor.AroundInvoke;
 import javax.transaction.TransactionManager;
 
@@ -35,6 +38,7 @@
 import org.apache.openejb.OpenEJBException;
 import org.apache.openejb.ProxyInfo;
 import org.apache.openejb.InterfaceType;
+import org.apache.openejb.util.Duration;
 import org.apache.openejb.core.CoreDeploymentInfo;
 import org.apache.openejb.core.Operation;
 import org.apache.openejb.core.ThreadContext;
@@ -60,6 +64,9 @@
     private Object containerID = null;
     private TransactionManager transactionManager;
     private SecurityService securityService;
+    private long wait = 30;
+    private TimeUnit unit = TimeUnit.SECONDS;
+
 
     public SingletonContainer(Object id, TransactionManager transactionManager, \
SecurityService securityService) throws OpenEJBException {  this.containerID = id;
@@ -74,6 +81,11 @@
         }
     }
 
+    public void setAccessTimeout(Duration duration){
+        this.unit = duration.getUnit();
+        this.wait = duration.getTime();
+    }
+
     public synchronized DeploymentInfo [] deployments() {
         return deploymentRegistry.values().toArray(new \
DeploymentInfo[deploymentRegistry.size()]);  }
@@ -153,7 +165,7 @@
                 return null;// EJBObject.remove( ) and other EJBObject methods are \
not process by the container  }
 
-            Object bean = instanceManager.getInstance(callContext);
+            Instance instance = instanceManager.getInstance(callContext);
 
             callContext.setCurrentOperation(Operation.BUSINESS);
             callContext.setCurrentAllowedStates(SingletonContext.getStates());
@@ -162,8 +174,7 @@
 
             callContext.set(Method.class, runMethod);
             callContext.setInvokedInterface(callInterface);
-            Object retValue = _invoke(callInterface, callMethod, runMethod, args, \
                bean, callContext);
-            instanceManager.poolInstance(callContext, bean);
+            Object retValue = _invoke(callInterface, callMethod, runMethod, args, \
instance, callContext);  
             return retValue;
 
@@ -196,53 +207,80 @@
         TransactionContext txContext = new TransactionContext(callContext, \
getTransactionManager());  txContext.callContext = callContext;
 
-        txPolicy.beforeInvoke(instance, txContext);
 
-        Object returnValue = null;
+        boolean read = false; // TODO: get meta data from DeploymentInfo
+        final Lock lock = aquireLock(read, instance);
+
+        Object returnValue;
         try {
-            InterfaceType type = deploymentInfo.getInterfaceType(callInterface);
-            if (type == InterfaceType.SERVICE_ENDPOINT){
-                callContext.setCurrentOperation(Operation.BUSINESS_WS);
-                returnValue = invokeWebService(args, deploymentInfo, runMethod, \
                instance, returnValue);
-            } else {
-                List<InterceptorData> interceptors = \
                deploymentInfo.getMethodInterceptors(runMethod);
-                InterceptorStack interceptorStack = new \
InterceptorStack(instance.bean, runMethod, Operation.BUSINESS, interceptors, \
                instance.interceptors);
-                returnValue = interceptorStack.invoke(args);
-            }
-        } catch (Throwable re) {// handle reflection exception
-            ExceptionType type = deploymentInfo.getExceptionType(re);
-            if (type == ExceptionType.SYSTEM) {
-                /* System Exception ****************************/
-
-                /**
-                 * The bean instance is not put into the pool via \
                instanceManager.poolInstance
-                 * and therefore the instance will be garbage collected and \
                destroyed.
-                 * For this reason the discardInstance method of the \
                StatelessInstanceManager
-                 * does nothing.
-                 */
-
-                txPolicy.handleSystemException(re, instance, txContext);
-            } else {
-                /* Application Exception ***********************/
+            txPolicy.beforeInvoke(instance, txContext);
 
-                txPolicy.handleApplicationException(re, type == \
ExceptionType.APPLICATION_ROLLBACK, txContext); +            returnValue = null;
+            try {
+                InterfaceType type = deploymentInfo.getInterfaceType(callInterface);
+                if (type == InterfaceType.SERVICE_ENDPOINT){
+                    callContext.setCurrentOperation(Operation.BUSINESS_WS);
+                    returnValue = invokeWebService(args, deploymentInfo, runMethod, \
instance); +                } else {
+                    List<InterceptorData> interceptors = \
deploymentInfo.getMethodInterceptors(runMethod); +                    \
InterceptorStack interceptorStack = new InterceptorStack(instance.bean, runMethod, \
Operation.BUSINESS, interceptors, instance.interceptors); +                    \
returnValue = interceptorStack.invoke(args); +                }
+            } catch (Throwable re) {// handle reflection exception
+                ExceptionType type = deploymentInfo.getExceptionType(re);
+                if (type == ExceptionType.SYSTEM) {
+                    /* System Exception ****************************/
+
+                    /**
+                     * The bean instance is not put into the pool via \
instanceManager.poolInstance +                     * and therefore the instance will \
be garbage collected and destroyed. +                     * For this reason the \
discardInstance method of the StatelessInstanceManager +                     * does \
nothing. +                     */
+
+                    txPolicy.handleSystemException(re, instance, txContext);
+                } else {
+                    /* Application Exception ***********************/
+
+                    txPolicy.handleApplicationException(re, type == \
ExceptionType.APPLICATION_ROLLBACK, txContext); +                }
+            } finally {
+                txPolicy.afterInvoke(instance, txContext);
             }
         } finally {
-            instanceManager.poolInstance(callContext, instance);
-
-            txPolicy.afterInvoke(instance, txContext);
+            lock.unlock();
         }
 
         return returnValue;
     }
 
-    private Object invokeWebService(Object[] args, CoreDeploymentInfo \
deploymentInfo, Method runMethod, Instance instance, Object returnValue) throws \
Exception { +    private Lock aquireLock(boolean read, Instance instance) {
+        final Lock lock;
+        if (read) {
+            lock = instance.lock.readLock();
+        } else {
+            lock = instance.lock.writeLock();
+        }
+
+        try {
+            if (!lock.tryLock(wait, unit)){
+                throw new ConcurrentAccessTimeoutException();
+            }
+        } catch (InterruptedException e) {
+            throw (ConcurrentAccessTimeoutException) new \
ConcurrentAccessTimeoutException().initCause(e); +        }
+        return lock;
+    }
+
+    private Object invokeWebService(Object[] args, CoreDeploymentInfo \
deploymentInfo, Method runMethod, Instance instance) throws Exception {  if \
                (args.length != 2){
             throw new IllegalArgumentException("WebService calls must follow format \
{messageContext, interceptor}.");  }
 
         Object messageContext = args[0];
 
+        if (messageContext == null) throw new \
IllegalArgumentException("MessageContext is null."); +
         // This object will be used as an interceptor in the stack and will be \
                responsible
         // for unmarshalling the soap message parts into an argument list that will \
be  // used for the actual method invocation.
@@ -251,6 +289,7 @@
         // of our stack.
         Object interceptor = args[1];
 
+        if (interceptor == null) throw new IllegalArgumentException("Interceptor \
instance is null.");  
         //  Add the webservice interceptor to the list of interceptor instances
         Map<String, Object> interceptors = new HashMap<String, \
Object>(instance.interceptors); @@ -271,12 +310,12 @@
         Object[] params = new Object[runMethod.getParameterTypes().length];
         if (messageContext instanceof javax.xml.rpc.handler.MessageContext) {
             ThreadContext.getThreadContext().set(javax.xml.rpc.handler.MessageContext.class, \
                (javax.xml.rpc.handler.MessageContext) messageContext);
-            returnValue = \
interceptorStack.invoke((javax.xml.rpc.handler.MessageContext) messageContext, \
params); +            return \
interceptorStack.invoke((javax.xml.rpc.handler.MessageContext) messageContext, \
                params);
         } else if (messageContext instanceof javax.xml.ws.handler.MessageContext) {
             ThreadContext.getThreadContext().set(javax.xml.ws.handler.MessageContext.class, \
                (javax.xml.ws.handler.MessageContext) messageContext);
-            returnValue = \
interceptorStack.invoke((javax.xml.ws.handler.MessageContext) messageContext, \
params); +            return \
interceptorStack.invoke((javax.xml.ws.handler.MessageContext) messageContext, \
params);  }
-        return returnValue;
+        throw new IllegalArgumentException("Uknown MessageContext type: " + \
messageContext.getClass().getName());  }
 
     private TransactionManager getTransactionManager() {

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/ma \
in/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java?rev=672684&r1=672683&r2=672684&view=diff
 ==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java \
                (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/core/singleton/SingletonInstanceManager.java \
Sun Jun 29 17:00:25 2008 @@ -22,7 +22,11 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.concurrent.Semaphore;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.TimeUnit;
 
 import javax.ejb.SessionBean;
 import javax.ejb.SessionContext;
@@ -33,7 +37,6 @@
 
 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;
@@ -41,11 +44,9 @@
 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;
@@ -54,12 +55,6 @@
 public class SingletonInstanceManager {
     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 HashMap<Object,Semaphore> semaphores;
-
     protected final SafeToolkit toolkit = \
SafeToolkit.getToolkit("SingletonInstanceManager");  private TransactionManager \
transactionManager;  private SecurityService securityService;
@@ -67,12 +62,6 @@
     public SingletonInstanceManager(TransactionManager transactionManager, \
SecurityService securityService) {  this.transactionManager = transactionManager;
         this.securityService = securityService;
-        this.poolLimit = 1;
-        this.strictPooling = true;
-
-        if (this.strictPooling) {
-            this.semaphores = new HashMap();
-        }
     }
 
     /**
@@ -90,21 +79,12 @@
      * @return
      * @throws OpenEJBException
      */
-    public Object getInstance(ThreadContext callContext)
+    public Instance getInstance(ThreadContext callContext)
             throws OpenEJBException {
         CoreDeploymentInfo deploymentInfo = callContext.getDeploymentInfo();
         Data data = (Data) deploymentInfo.getContainerData();
-        Stack pool = data.getPool();
-        if(strictPooling){
-            try {
-                semaphores.get(deploymentInfo.getDeploymentID()).acquire();
-            } catch (InterruptedException e2) {
-                throw new OpenEJBException("Unexpected Interruption of current \
                thread: ",e2);
-            }
-        }
-        Object bean = pool.pop();
 
-        if (bean == null) {
+        if (data.instance == null) {
 
             Class beanClass = deploymentInfo.getBeanClass();
             ObjectRecipe objectRecipe = new ObjectRecipe(beanClass);
@@ -150,7 +130,7 @@
 
                 fillInjectionProperties(objectRecipe, beanClass, deploymentInfo, \
ctx);  
-                bean = objectRecipe.create(beanClass.getClassLoader());
+                Object bean = objectRecipe.create(beanClass.getClassLoader());
                 Map unsetProperties = objectRecipe.getUnsetProperties();
                 if (unsetProperties.size() > 0) {
                     for (Object property : unsetProperties.keySet()) {
@@ -205,12 +185,21 @@
                     throw e;
                 }
 
-                bean = new Instance(bean, interceptorInstances);
+                ReadWriteLock lock;
+                if (false){ // TODO: Get metadata from DeploymentInfo
+                    // Bean-Managed Concurrency
+                    lock = new BeanManagedLock();
+                } else {
+                    // Container-Managed Concurrency
+                    lock = new ReentrantReadWriteLock();
+                }
+
+                data.instance = new Instance(bean, interceptorInstances, lock);
             } 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; +                String t = "The bean instance threw a system \
exception:" + e;  logger.error(t, e);
                 throw new org.apache.openejb.ApplicationException(new \
RemoteException("Cannot obtain a free instance.", e));  } finally {
@@ -218,7 +207,8 @@
                 callContext.setCurrentAllowedStates(originalAllowedStates);
             }
         }
-        return bean;
+
+        return data.instance;
     }
 
     private static void fillInjectionProperties(ObjectRecipe objectRecipe, Class \
clazz, CoreDeploymentInfo deploymentInfo, Context context) { @@ -271,41 +261,7 @@
         return new SingletonContext(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);
-            semaphores.get(deploymentInfo.getDeploymentID()).release();
-        } else {
-            if (pool.size() >= poolLimit) {
-                freeInstance(callContext, (Instance)bean);
-            } else {
-                pool.push(bean);
-            }
-        }
-    }
-
+    // TODO: Call on system shutdown
     private void freeInstance(ThreadContext callContext, Instance instance) {
         try {
             callContext.setCurrentOperation(Operation.PRE_DESTROY);
@@ -337,36 +293,51 @@
     }
 
     public void deploy(CoreDeploymentInfo deploymentInfo) {
-        Data data = new Data(poolLimit);
+        Data data = new Data();
         deploymentInfo.setContainerData(data);      
-        if (this.strictPooling) {
-            this.semaphores.put(deploymentInfo.getDeploymentID(), new \
                Semaphore(poolLimit));
-        }
-
     }
 
     public void undeploy(CoreDeploymentInfo deploymentInfo) {
         Data data = (Data) deploymentInfo.getContainerData();
-        if (this.strictPooling) {
-            semaphores.remove(deploymentInfo.getDeploymentID());
-        }
         if (data == null) return;
-        Stack pool = data.getPool();
-        //TODO ejbRemove on each bean in pool.
-        //clean pool
         deploymentInfo.setContainerData(null);
     }
 
     private static final class Data {
-        private final Stack pool;
+        private Instance instance;
+    }
+
+
+    private static class BeanManagedLock implements ReadWriteLock {
+        private final Lock lock =  new Lock(){
+            public void lock() {
+            }
 
-        public Data(int poolLimit) {
-            pool = new LinkedListStack(poolLimit);
+            public void lockInterruptibly() {
+            }
+
+            public Condition newCondition() {
+                throw new java.lang.UnsupportedOperationException("newCondition()");
+            }
+
+            public boolean tryLock() {
+                return true;
+            }
+
+            public boolean tryLock(long time, TimeUnit unit) {
+                return true;
+            }
+
+            public void unlock() {
+            }
+        };
+
+        public Lock readLock() {
+            return lock;
         }
 
-        public Stack getPool() {
-            return pool;
+        public Lock writeLock() {
+            return lock;
         }
     }
-
 }

Added: openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Duration.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Duration.java?rev=672684&view=auto
 ==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Duration.java \
                (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/java/org/apache/openejb/util/Duration.java \
Sun Jun 29 17:00:25 2008 @@ -0,0 +1,241 @@
+/**
+ * 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.util;
+
+import java.beans.PropertyEditorManager;
+import java.util.concurrent.TimeUnit;
+
+public class Duration {
+
+    private long time;
+    private TimeUnit unit;
+
+    public Duration() {
+    }
+
+    public Duration(long time, TimeUnit unit) {
+        this.time = time;
+        this.unit = unit;
+    }
+
+    public Duration(String string) {
+        parse(string, this);
+    }
+
+    public long getTime() {
+        return time;
+    }
+
+    public void setTime(long time) {
+        this.time = time;
+    }
+
+    public TimeUnit getUnit() {
+        return unit;
+    }
+
+    public void setUnit(TimeUnit unit) {
+        this.unit = unit;
+    }
+
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        final Duration duration = (Duration) o;
+
+        if (time != duration.time) return false;
+        if (unit != duration.unit) return false;
+
+        return true;
+    }
+
+    public int hashCode() {
+        int result;
+        result = (int) (time ^ (time >>> 32));
+        result = 29 * result + (unit != null ? unit.hashCode() : 0);
+        return result;
+    }
+
+    public String toString() {
+        if (unit == null){
+            return time + "";
+        } else {
+            return time + " " + unit;
+        }
+    }
+
+    public static Duration parse(String text) {
+        Duration d = new Duration();
+        parse(text, d);
+        return d;
+    }
+
+    private static void parse(String text, Duration d) {
+        text = text.trim();
+
+        StringBuilder t = new StringBuilder();
+        StringBuilder u = new StringBuilder();
+
+        int i = 0;
+
+        // get the number
+        for (; i < text.length(); i++) {
+            char c = text.charAt(i);
+            System.out.println("a "+c);
+            if (Character.isDigit(c) || i == 0 && c == '-') {
+                t.append(c);
+            } else {
+                break;
+            }
+        }
+
+        if (t.length() == 0){
+            invalidFormat(text);
+        }
+
+        // skip whitespace
+        for (; i < text.length(); i++) {
+            char c = text.charAt(i);
+            System.out.println("b "+c);
+            if (Character.isWhitespace(c)) {
+            } else {
+                break;
+            }
+        }
+
+        // get time unit text part
+        for (; i < text.length(); i++) {
+            char c = text.charAt(i);
+            System.out.println("c "+c);
+            if (Character.isLetter(c)) {
+                u.append(c);
+            } else {
+                invalidFormat(text);
+            }
+        }
+
+        d.time = Integer.parseInt(t.toString());
+
+        Unit unit = parseUnit(u.toString());
+
+        if (unit != null) switch (unit) {
+            case days: {
+                d.time *= 60 * 60 * 24;
+                d.unit = TimeUnit.SECONDS;
+            }
+            ;
+            break;
+            case hours: {
+                d.time *= 60 * 60;
+                d.unit = TimeUnit.SECONDS;
+            }
+            ;
+            break;
+            case minutes: {
+                d.time *= 60;
+                d.unit = TimeUnit.SECONDS;
+            }
+            ;
+            break;
+            case seconds: {
+                d.unit = TimeUnit.SECONDS;
+            }
+            ;
+            break;
+            case milliseconds: {
+                d.unit = TimeUnit.MILLISECONDS;
+            }
+            ;
+            break;
+            case microseconds: {
+                d.unit = TimeUnit.MICROSECONDS;
+            }
+            ;
+            break;
+            case nanoseconds: {
+                d.unit = TimeUnit.NANOSECONDS;
+            }
+            ;
+            break;
+        }
+    }
+
+    private static void invalidFormat(String text) {
+        throw new IllegalArgumentException("Illegal duration format: '"+text+"'.  \
Valid examples are '10s' or '10 seconds'."); +    }
+
+    private static Unit parseUnit(String u) {
+        if (u.length() == 0) return null;
+
+        if (u.equalsIgnoreCase("NANOSECONDS")) return Unit.nanoseconds;
+        if (u.equalsIgnoreCase("NANOSECOND")) return Unit.nanoseconds;
+        if (u.equalsIgnoreCase("NANOS")) return Unit.nanoseconds;
+        if (u.equalsIgnoreCase("NANO")) return Unit.nanoseconds;
+        if (u.equalsIgnoreCase("NS")) return Unit.nanoseconds;
+
+        if (u.equalsIgnoreCase("MICROSECONDS")) return Unit.microseconds;
+        if (u.equalsIgnoreCase("MICROSECOND")) return Unit.microseconds;
+        if (u.equalsIgnoreCase("MICROS")) return Unit.microseconds;
+        if (u.equalsIgnoreCase("MICRO")) return Unit.microseconds;
+
+        if (u.equalsIgnoreCase("MILLISECONDS")) return Unit.milliseconds;
+        if (u.equalsIgnoreCase("MILLISECOND")) return Unit.milliseconds;
+        if (u.equalsIgnoreCase("MILLIS")) return Unit.milliseconds;
+        if (u.equalsIgnoreCase("MILLI")) return Unit.milliseconds;
+        if (u.equalsIgnoreCase("MS")) return Unit.milliseconds;
+
+        if (u.equalsIgnoreCase("SECONDS")) return Unit.seconds;
+        if (u.equalsIgnoreCase("SECOND")) return Unit.seconds;
+        if (u.equalsIgnoreCase("SEC")) return Unit.seconds;
+        if (u.equalsIgnoreCase("S")) return Unit.seconds;
+
+        if (u.equalsIgnoreCase("MINUTES")) return Unit.minutes;
+        if (u.equalsIgnoreCase("MINUTE")) return Unit.minutes;
+        if (u.equalsIgnoreCase("MIN")) return Unit.minutes;
+        if (u.equalsIgnoreCase("M")) return Unit.minutes;
+
+        if (u.equalsIgnoreCase("HOURS")) return Unit.hours;
+        if (u.equalsIgnoreCase("HOUR")) return Unit.hours;
+        if (u.equalsIgnoreCase("HRS")) return Unit.hours;
+        if (u.equalsIgnoreCase("HR")) return Unit.hours;
+        if (u.equalsIgnoreCase("H")) return Unit.hours;
+
+        if (u.equalsIgnoreCase("DAYS")) return Unit.days;
+        if (u.equalsIgnoreCase("DAY")) return Unit.days;
+        if (u.equalsIgnoreCase("D")) return Unit.days;
+
+        throw new IllegalArgumentException("Unknown time unit '" + u + "'.  \
Supported units " + Join.join(", ", Unit.values())); +    }
+
+
+    static {
+        PropertyEditorManager.registerEditor(Duration.class, Editor.class);
+    }
+
+    public static class Editor extends java.beans.PropertyEditorSupport {
+        public void setAsText(String text) {
+            Duration d = parse(text);
+            setValue(d);
+        }
+    }
+
+    public static enum Unit {
+        // All lowercase so they look good displayed in help
+        nanoseconds, microseconds, milliseconds, seconds, minutes, hours, days;
+    }
+}

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/ma \
in/resources/META-INF/org.apache.openejb.embedded/service-jar.xml?rev=672684&r1=672683&r2=672684&view=diff
 ==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml \
                (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb.embedded/service-jar.xml \
Sun Jun 29 17:00:25 2008 @@ -124,6 +124,8 @@
           constructor="id, transactionManager, securityService"
           class-name="org.apache.openejb.core.singleton.SingletonContainer">
 
+    AccessTimeout = 30 seconds
+    
   </ServiceProvider>
 
 

Modified: openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/ma \
in/resources/META-INF/org.apache.openejb/service-jar.xml?rev=672684&r1=672683&r2=672684&view=diff
 ==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml \
                (original)
+++ openejb/trunk/openejb3/container/openejb-core/src/main/resources/META-INF/org.apache.openejb/service-jar.xml \
Sun Jun 29 17:00:25 2008 @@ -127,6 +127,8 @@
           constructor="id, transactionManager, securityService"
           class-name="org.apache.openejb.core.singleton.SingletonContainer">
 
+    AccessTimeout = 30 seconds
+    
   </ServiceProvider>
 
 

Added: openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DurationTest.java
                
URL: http://svn.apache.org/viewvc/openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DurationTest.java?rev=672684&view=auto
 ==============================================================================
--- openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DurationTest.java \
                (added)
+++ openejb/trunk/openejb3/container/openejb-core/src/test/java/org/apache/openejb/util/DurationTest.java \
Sun Jun 29 17:00:25 2008 @@ -0,0 +1,49 @@
+/**
+ * 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.util;
+
+import junit.framework.TestCase;
+
+import static java.util.concurrent.TimeUnit.MICROSECONDS;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class DurationTest extends TestCase {
+
+    public void test() throws Exception {
+
+        assertEquals(new Duration(1000, MILLISECONDS), new Duration("1000ms"));
+        assertEquals(new Duration(1000, MILLISECONDS), new Duration("1000 ms"));
+        assertEquals(new Duration(1000, MILLISECONDS), new Duration("1000  ms"));
+
+        assertEquals(new Duration(60, SECONDS), new Duration("1m"));
+        assertEquals(new Duration(3600, SECONDS), new Duration("1h"));
+        assertEquals(new Duration(86400, SECONDS), new Duration("1d"));
+
+        assertEquals(new Duration(1000, MICROSECONDS), new Duration("1000 \
microseconds")); +        assertEquals(new Duration(1000, NANOSECONDS), new \
Duration("1000 nanoseconds")); +
+        assertEquals(new Duration(1, null), new Duration("1"));
+        assertEquals(new Duration(234, null), new Duration("234"));
+        assertEquals(new Duration(123, null), new Duration("123"));
+        assertEquals(new Duration(-1, null), new Duration("-1"));
+    }
+}


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic