wink-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jra...@apache.org
Subject svn commit: r1026140 - in /incubator/wink/trunk/wink-common: ./ src/main/java/org/apache/wink/common/internal/lifecycle/ src/test/java/org/apache/wink/common/internal/lifecycle/
Date Thu, 21 Oct 2010 20:59:11 GMT
Author: jramos
Date: Thu Oct 21 20:59:10 2010
New Revision: 1026140

URL: http://svn.apache.org/viewvc?rev=1026140&view=rev
Log:
[WINK-322] Add JSR250 lifecycle management support

Added:
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManager.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManagerUtils.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250PrototypeObjectFactory.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250SingletonObjectFactory.java
    incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/lifecycle/JSR250OFFactoryTest.java
Modified:
    incubator/wink/trunk/wink-common/pom.xml
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/LifecycleManagerUtils.java
    incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/SingletonObjectFactory.java

Modified: incubator/wink/trunk/wink-common/pom.xml
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/pom.xml?rev=1026140&r1=1026139&r2=1026140&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/pom.xml (original)
+++ incubator/wink/trunk/wink-common/pom.xml Thu Oct 21 20:59:10 2010
@@ -47,10 +47,12 @@
         <dependency>
             <groupId>xmlunit</groupId>
             <artifactId>xmlunit</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
+            <scope>test</scope>
         </dependency>
         <dependency>
             <groupId>javax.xml.bind</groupId>
@@ -82,6 +84,12 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-annotation_1.1_spec</artifactId>
+            <version>1.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
             <groupId>org.jmock</groupId>
             <artifactId>jmock-legacy</artifactId>
             <scope>test</scope>

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManager.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManager.java?rev=1026140&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManager.java
(added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManager.java
Thu Oct 21 20:59:10 2010
@@ -0,0 +1,93 @@
+/*******************************************************************************
+ * 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.wink.common.internal.lifecycle;
+
+import org.apache.wink.common.internal.registry.metadata.ApplicationMetadataCollector;
+import org.apache.wink.common.internal.registry.metadata.ProviderMetadataCollector;
+import org.apache.wink.common.internal.registry.metadata.ResourceMetadataCollector;
+
+/**
+ * <p>
+ * implementation for LifecycleManager according to JAX RS (JSR 311) that supports
+ * JSR250 PostConstruct and PreDestroy annotations
+ * <p>
+ * For <tt>createObjectFactory(T object)</tt> the factory will always return
a
+ * SingletonObjectFactory.
+ * <p>
+ * For <tt>createObjectFactory(final Class<T> cls)</tt> the factory will
return:
+ * <ul>
+ * <li>SingletonObjectFactory - for Providers</li>
+ * <li>ClassMetadataPrototypeOF - for Resources</li>
+ * <li>SimplePrototypeOF - for Resources (marked with DispatchedPath annotation)
+ * </li>
+ * </ul>
+ * and throw IllegalArgumentException otherwise.
+ * 
+ * @param <T>
+ * @see SingletonObjectFactory
+ * @see PrototypeObjectFactory
+ * @see SimplePrototypeOF
+ */
+public class JSR250LifecycleManager<T> implements LifecycleManager<T> {
+
+    public ObjectFactory<T> createObjectFactory(T object) {
+
+        if (object == null) {
+            return null;
+        }
+
+        @SuppressWarnings("unchecked")
+        final Class<T> cls = (Class<T>)object.getClass();
+
+        if (JSR250LifecycleManagerUtils.hasJSR250AnnotatedMethod(cls)) {
+            return JSR250LifecycleManagerUtils.createSingletonObjectFactory(cls);
+        }
+        
+        // has no JSR250 annotations, do nothing
+        return null;
+    }
+
+    public ObjectFactory<T> createObjectFactory(Class<T> cls) {
+
+        if (cls == null) {
+            return null;
+        }
+
+        if (JSR250LifecycleManagerUtils.hasJSR250AnnotatedMethod(cls)) {
+            ObjectFactory<T> ret = null;
+            if (ApplicationMetadataCollector.isApplication(cls)) {
+                // by default application subclasses are singletons
+                ret = JSR250LifecycleManagerUtils.createSingletonObjectFactory(cls);
+            } else if (ProviderMetadataCollector.isProvider(cls)) {
+                // by default providers are singletons
+                ret = JSR250LifecycleManagerUtils.createSingletonObjectFactory(cls);
+            } else if (ResourceMetadataCollector.isStaticResource(cls)) {
+                // by default resources are prototypes (created per request)
+                ret = JSR250LifecycleManagerUtils.createPrototypeObjectFactory(cls);
+            }
+
+            return ret;
+        }
+        
+        // has no JSR250 annotations, do nothing
+        return null;
+    }
+
+}

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManagerUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManagerUtils.java?rev=1026140&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManagerUtils.java
(added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250LifecycleManagerUtils.java
Thu Oct 21 20:59:10 2010
@@ -0,0 +1,268 @@
+/*******************************************************************************
+ * 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.wink.common.internal.lifecycle;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.apache.wink.common.internal.registry.metadata.ClassMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 
+ * The only reason to extend LifecycleManagerUtils is to get easy access to collectClassMetadata
method
+ *
+ */
+public class JSR250LifecycleManagerUtils extends LifecycleManagerUtils {
+
+    private static Logger logger = LoggerFactory.getLogger(JSR250LifecycleManagerUtils.class);
+    
+    // cache the @PostConstruct and @PreDestroy annotated methods so we don't have to do
reflective search each time
+    private static class PreDestroyMethod {
+        private Method m;
+        public PreDestroyMethod(Method _m) {
+            m = _m;
+        }
+        public Method getMethod() {
+            return m;
+        }
+    }
+    private static class PostConstructMethod {
+        private Method m;
+        public PostConstructMethod(Method _m) {
+            m = _m;
+        }
+        public Method getMethod() {
+            return m;
+        }
+    }
+    @SuppressWarnings("unchecked")
+    private static Map<Class, PreDestroyMethod> preDestroyMethodCache = new HashMap<Class,
PreDestroyMethod>();
+    @SuppressWarnings("unchecked")
+    private static Map<Class, PostConstructMethod> postConstructMethodCache = new HashMap<Class,
PostConstructMethod>();
+
+    
+    public static <T> ObjectFactory<T> createSingletonObjectFactory(T object)
{
+        ObjectFactory<T> factory = LifecycleManagerUtils.createSingletonObjectFactory(object);
+        executePostConstructMethod(factory.getInstance(null));
+        return new JSR250SingletonObjectFactory<T>(factory.getInstance(null));
+    }
+
+    public static <T> ObjectFactory<T> createSingletonObjectFactory(final Class<T>
cls) {
+        ObjectFactory<T> factory = LifecycleManagerUtils.createSingletonObjectFactory(cls);
+        executePostConstructMethod(factory.getInstance(null));
+        return new JSR250SingletonObjectFactory<T>(factory.getInstance(null));
+    }
+    
+    public static <T> ObjectFactory<T> createPrototypeObjectFactory(final Class<T>
cls) {
+        ClassMetadata classMetadata = collectClassMetadata(cls, true);
+        return new JSR250PrototypeObjectFactory<T>(classMetadata);
+    }
+    
+    @SuppressWarnings("unchecked")
+    protected static <T> void executePostConstructMethod(T object) {
+        if (object != null) {
+            // check the cache
+            if (postConstructMethodCache.containsKey((Class<T>)object.getClass()))
{
+                Method m = postConstructMethodCache.get((Class<T>)object.getClass()).getMethod();
+                if (m != null) {
+                    invokeMethod(object, m, null);
+                    if(logger.isTraceEnabled()) {
+                        logger.trace("Invoked PostConstruct annotated method {} for class
{}", new Object[]{m, (Class<T>)object.getClass()});
+                    }
+                } else {
+                    if(logger.isTraceEnabled()) {
+                        logger.trace("No PostConstruct annotated method found for class {}",
new Object[]{(Class<T>)object.getClass()});
+                    }
+                }
+                return;
+            }
+            // no cache entry; do the search and populate the cache
+            postConstructMethodCache.put((Class<T>)object.getClass(), new PostConstructMethod(null));
+            List<Method> methods = getMethods(object.getClass());
+            for (Method method : methods) {
+                if (isPostConstruct(method)) {
+                    invokeMethod(object, method, null);
+                    // cache it
+                    postConstructMethodCache.put((Class<T>)object.getClass(), new PostConstructMethod(method));
+                    // don't invoke all the @PostConstruct methods
+                    break;
+                }
+            }
+            // logging:
+            Method m = postConstructMethodCache.get((Class<T>)object.getClass()).getMethod();
+            if (m != null) {
+                if(logger.isTraceEnabled()) {
+                    logger.trace("Invoked and cached PostConstruct annotated method {} for
class {}", new Object[]{m, (Class<T>)object.getClass()});
+                }
+            } else {
+                if(logger.isTraceEnabled()) {
+                    logger.trace("No PostConstruct annotated method found for class {}, null
value cached", new Object[]{(Class<T>)object.getClass()});
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected static <T> void executePreDestroyMethod(T object) {
+        if (object != null) {
+            // check the cache
+            if (preDestroyMethodCache.containsKey((Class<T>)object.getClass())) {
+                Method m = preDestroyMethodCache.get((Class<T>)object.getClass()).getMethod();
+                if (m != null) {
+                    invokeMethod(object, m, null);
+                    if(logger.isTraceEnabled()) {
+                        logger.trace("Invoked PreDestroy annotated method {} for class {}",
new Object[]{m, (Class<T>)object.getClass()});
+                    }
+                } else {
+                    if(logger.isTraceEnabled()) {
+                        logger.trace("No PreDestroy annotated method found for class {}",
new Object[]{(Class<T>)object.getClass()});
+                    }
+                }
+                return;
+            }
+            // no cache entry; do the search and populate the cache
+            preDestroyMethodCache.put((Class<T>)object.getClass(), new PreDestroyMethod(null));
+            List<Method> methods = getMethods(object.getClass());
+            for (Method method : methods) {
+                if (isPreDestroy(method)) {
+                    invokeMethod(object, method, null);
+                    // cache it
+                    preDestroyMethodCache.put((Class<T>)object.getClass(), new PreDestroyMethod(method));
+                    // don't invoke all the @PreDestroy methods
+                    break;
+                }
+            }
+            // logging:
+            Method m = preDestroyMethodCache.get((Class<T>)object.getClass()).getMethod();
+            if (m != null) {
+                if(logger.isTraceEnabled()) {
+                    logger.trace("Invoked and cached PreDestroy annotated method {} for class
{}", new Object[]{m, (Class<T>)object.getClass()});
+                }
+            } else {
+                if(logger.isTraceEnabled()) {
+                    logger.trace("No PreDestroy annotated method found for class {}, null
value cached", new Object[]{(Class<T>)object.getClass()});
+                }
+            }
+        }
+    }
+    
+    // utility to detect existence of any method annotated with either @PostConstruct or
@PreDestroy
+    @SuppressWarnings("unchecked")
+    protected static boolean hasJSR250AnnotatedMethod(Class clazz) {
+        List<Method> methods = getMethods(clazz);
+        for (Method method : methods) {
+            if (isPreDestroy(method) || isPostConstruct(method)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    @SuppressWarnings("unchecked")
+    private static void invokeMethod(final Object object, final Method m, final Object[]
params) throws ObjectCreationException {
+        try {
+            AccessController.doPrivileged(
+                    new PrivilegedExceptionAction() {
+                        public Object run() throws InvocationTargetException, IllegalAccessException
{
+                            return m.invoke(object, params);
+                        }
+                    }
+            );
+        } catch (PrivilegedActionException e) {
+            throw new ObjectCreationException(e.getException());
+        }
+    }
+
+    
+    /**
+     * Gets all of the methods in this class and the super classes
+     *
+     * @param beanClass
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    private static List<Method> getMethods(final Class beanClass) {
+        // This class must remain private due to Java 2 Security concerns
+        List<Method> methods;
+        methods = (List<Method>)AccessController.doPrivileged(
+                new PrivilegedAction() {
+                    public Object run() {
+                        List<Method> methods = new ArrayList<Method>();
+                        Class cls = beanClass;
+                        while (cls != null) {
+                            Method[] methodArray = cls.getDeclaredMethods();
+                            for (Method method : methodArray) {
+                                methods.add(method);
+                            }
+                            cls = cls.getSuperclass();
+                        }
+                        return methods;
+                    }
+                }
+        );
+
+        return methods;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static boolean isPostConstruct(final Method method) {
+        Annotation[] annotations = (Annotation[]) AccessController.doPrivileged(
+                new PrivilegedAction() {
+                    public Object run() {
+                        return method.getDeclaredAnnotations();
+                    }
+                }
+        );
+        for (Annotation annotation : annotations) {
+            return PostConstruct.class.isAssignableFrom(annotation.annotationType());
+        }
+        return false;
+    }
+
+    @SuppressWarnings("unchecked")
+    private static boolean isPreDestroy(final Method method) {
+        Annotation[] annotations = (Annotation[]) AccessController.doPrivileged(
+                new PrivilegedAction() {
+                    public Object run() {
+                        return method.getDeclaredAnnotations();
+                    }
+                }
+        );
+        for (Annotation annotation : annotations) {
+            return PreDestroy.class.isAssignableFrom(annotation.annotationType());
+        }
+        return false;
+    }
+
+}

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250PrototypeObjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250PrototypeObjectFactory.java?rev=1026140&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250PrototypeObjectFactory.java
(added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250PrototypeObjectFactory.java
Thu Oct 21 20:59:10 2010
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.wink.common.internal.lifecycle;
+
+import org.apache.wink.common.RuntimeContext;
+import org.apache.wink.common.internal.registry.metadata.ClassMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Implements ObjectFactory that creates a new object for each call based on its
+ * ClassMetadata, with JSR250 PostConstruct and PreDestroy support.
+ * 
+ * @param <T>
+ */
+class JSR250PrototypeObjectFactory<T> extends PrototypeObjectFactory<T> {
+
+    private static Logger logger = LoggerFactory.getLogger(JSR250PrototypeObjectFactory.class);
+    
+    public JSR250PrototypeObjectFactory(ClassMetadata metadata) {
+        super(metadata);
+    }
+
+    @Override
+    public T getInstance(RuntimeContext context) {
+        T instance = super.getInstance(context);
+        // TODO instead of below, get the method that has the postconstruct
+        JSR250LifecycleManagerUtils.executePostConstructMethod(instance);
+        return instance;
+    }
+
+    @Override
+    public void releaseInstance(T instance, RuntimeContext context) {
+        JSR250LifecycleManagerUtils.executePreDestroyMethod(instance);
+    }
+
+}

Added: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250SingletonObjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250SingletonObjectFactory.java?rev=1026140&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250SingletonObjectFactory.java
(added)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/JSR250SingletonObjectFactory.java
Thu Oct 21 20:59:10 2010
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * 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.wink.common.internal.lifecycle;
+
+import org.apache.wink.common.RuntimeContext;
+
+public class JSR250SingletonObjectFactory<T> extends SingletonObjectFactory<T>
{
+
+    public JSR250SingletonObjectFactory(T object) {
+        super(object);
+    }
+
+    /*
+     * Do not override releaseInstance since this is a singleton.  The SingletonObjectFactory
is a holder for an instance;
+     * it does *not* create objects per request, but releaseInstance may be called per request.
 That would be bad.
+     */
+    
+    @Override
+    public void releaseAll(RuntimeContext context) {
+        JSR250LifecycleManagerUtils.executePreDestroyMethod(object);
+    }
+
+}

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/LifecycleManagerUtils.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/LifecycleManagerUtils.java?rev=1026140&r1=1026139&r2=1026140&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/LifecycleManagerUtils.java
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/LifecycleManagerUtils.java
Thu Oct 21 20:59:10 2010
@@ -67,7 +67,7 @@ public class LifecycleManagerUtils {
         return new PrototypeObjectFactory<T>(classMetadata);
     }
 
-    private static <T> ClassMetadata collectClassMetadata(final Class<T> cls,
+    protected static <T> ClassMetadata collectClassMetadata(final Class<T> cls,
                                                           boolean validateConstructor) {
         ClassMetadata classMetadata = null;
         if (ProviderMetadataCollector.isProvider(cls)) {

Modified: incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/SingletonObjectFactory.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/SingletonObjectFactory.java?rev=1026140&r1=1026139&r2=1026140&view=diff
==============================================================================
--- incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/SingletonObjectFactory.java
(original)
+++ incubator/wink/trunk/wink-common/src/main/java/org/apache/wink/common/internal/lifecycle/SingletonObjectFactory.java
Thu Oct 21 20:59:10 2010
@@ -28,8 +28,8 @@ import org.apache.wink.common.RuntimeCon
  */
 class SingletonObjectFactory<T> implements ObjectFactory<T> {
 
-    private final T        object;
-    private final Class<T> objectClass;
+    protected final T        object;
+    protected final Class<T> objectClass;
 
     @SuppressWarnings("unchecked")
     public SingletonObjectFactory(T object) {

Added: incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/lifecycle/JSR250OFFactoryTest.java
URL: http://svn.apache.org/viewvc/incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/lifecycle/JSR250OFFactoryTest.java?rev=1026140&view=auto
==============================================================================
--- incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/lifecycle/JSR250OFFactoryTest.java
(added)
+++ incubator/wink/trunk/wink-common/src/test/java/org/apache/wink/common/internal/lifecycle/JSR250OFFactoryTest.java
Thu Oct 21 20:59:10 2010
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * 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.wink.common.internal.lifecycle;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import javax.ws.rs.Path;
+import javax.ws.rs.ext.Provider;
+
+import junit.framework.TestCase;
+
+import org.apache.wink.common.RuntimeContext;
+import org.apache.wink.common.internal.runtime.RuntimeContextTLS;
+
+public class JSR250OFFactoryTest extends TestCase {
+
+    protected static String called;
+    LifecycleManagersRegistry factoryRegistry;
+    
+    @Provider
+    public static class ProviderPostConstructSingleton {
+
+        @PostConstruct
+        public void postConstruct() {
+            called = this.getClass().getSimpleName() + ".postConstruct()";
+        }
+        
+    }
+    
+    @Provider
+    public static class ProviderPreDestroySingleton {
+
+        @PreDestroy
+        public void preDestroy() {
+            called = this.getClass().getSimpleName() + ".preDestroy()";
+        }
+        
+    }
+    
+    @Provider
+    public static class ProviderBothSingleton {
+
+        @PostConstruct
+        public void postConstruct() {
+            called = this.getClass().getSimpleName() + ".postConstruct()";
+        }
+        
+        @PreDestroy
+        public void preDestroy() {
+            called = this.getClass().getSimpleName() + ".preDestroy()";
+        }
+        
+    }
+    
+    @Provider
+    public static class ProviderPostConstructDoubleSingleton {
+        @PostConstruct
+        public void postConstruct1() {
+            called = this.getClass().getSimpleName() + ".postConstruct1()";
+        }
+        @PostConstruct
+        public void postConstruct2() {
+            called = this.getClass().getSimpleName() + ".postConstruct2()";
+        }
+    }
+    
+    @Path("")
+    public static class MyResource {
+        @PostConstruct
+        public void postConstruct() {
+            called = this.getClass().getSimpleName() + ".postConstruct()";
+        }
+        
+        @PreDestroy
+        public void preDestroy() {
+            called = this.getClass().getSimpleName() + ".preDestroy()";
+        }
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void setUp() {
+        called = null;
+        factoryRegistry = new LifecycleManagersRegistry();
+        factoryRegistry.addFactoryFactory(new JSR250LifecycleManager());
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testCorrectOF() {
+        ObjectFactory of = factoryRegistry.getObjectFactory(ProviderPostConstructSingleton.class);
+        assertEquals(JSR250SingletonObjectFactory.class, of.getClass());
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testCorrectOF2() {
+        ObjectFactory of = factoryRegistry.getObjectFactory(ProviderPreDestroySingleton.class);
+        assertEquals(JSR250SingletonObjectFactory.class, of.getClass());
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testCorrectOF3() {
+        ObjectFactory of = factoryRegistry.getObjectFactory(ProviderBothSingleton.class);
+        assertEquals(JSR250SingletonObjectFactory.class, of.getClass());
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testPostConstructCalled() {
+        ObjectFactory of = factoryRegistry.getObjectFactory(ProviderPostConstructSingleton.class);
+        assertEquals(JSR250SingletonObjectFactory.class, of.getClass());
+        // due to behavior of singleton instances, the object will have already been created
without 
+        // calling of.getInstance(RuntimeContext)
+        assertEquals(called, ProviderPostConstructSingleton.class.getSimpleName() + ".postConstruct()");
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testFirstPostConstructCalled() {
+        ObjectFactory of = factoryRegistry.getObjectFactory(ProviderPostConstructDoubleSingleton.class);
+        assertEquals(JSR250SingletonObjectFactory.class, of.getClass());
+        // due to behavior of singleton instances, the object will have already been created
without 
+        // calling of.getInstance(RuntimeContext)
+        assertEquals(called, ProviderPostConstructDoubleSingleton.class.getSimpleName() +
".postConstruct1()");
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testPreDestroyCalled() {
+        ObjectFactory of = factoryRegistry.getObjectFactory(ProviderPreDestroySingleton.class);
+        assertEquals(JSR250SingletonObjectFactory.class, of.getClass());
+        // no PostConstruct in ProviderPreDestroySingleton
+        assertEquals(called, null);
+        RuntimeContext context = RuntimeContextTLS.getRuntimeContext();
+        of.releaseInstance(of.getInstance(context), context);
+        assertEquals(called, null);  // we don't want releaseInstance to call @PreDestroy
annotated method for singletons
+        of.releaseAll(context);
+        assertEquals(called, ProviderPreDestroySingleton.class.getSimpleName() + ".preDestroy()");
+    }
+    
+    @SuppressWarnings("unchecked")
+    public void testResource() {
+        ObjectFactory of = factoryRegistry.getObjectFactory(MyResource.class);
+        assertEquals(JSR250PrototypeObjectFactory.class, of.getClass());
+        // due to being a "Prototype" object factory, instances are only created upon request
+        assertEquals(called, null);
+        RuntimeContext context = RuntimeContextTLS.getRuntimeContext();
+        of.getInstance(null);
+        assertEquals(called, MyResource.class.getSimpleName() + ".postConstruct()");
+        called = null;
+        of.releaseAll(context);
+        assertEquals(called, null);  // instances created by "Prototype" object factories
are per-request instances, not per-app or per-jvm
+        of.releaseInstance(of.getInstance(context), context);
+        assertEquals(called, MyResource.class.getSimpleName() + ".preDestroy()");  // we
*do* want releaseInstance to call @PreDestroy annotated method for per-request instances
+    }
+}



Mime
View raw message