org.apache.wink.common.internal.lifecycle.JSR250LifecycleManagerUtils Maven / Gradle / Ivy
/*******************************************************************************
* 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 preDestroyMethodCache = new HashMap();
@SuppressWarnings("unchecked")
private static Map postConstructMethodCache = new HashMap();
public static ObjectFactory createSingletonObjectFactory(T object) {
ObjectFactory factory = LifecycleManagerUtils.createSingletonObjectFactory(object);
executePostConstructMethod(factory.getInstance(null));
return new JSR250SingletonObjectFactory(factory.getInstance(null));
}
public static ObjectFactory createSingletonObjectFactory(final Class cls) {
ObjectFactory factory = LifecycleManagerUtils.createSingletonObjectFactory(cls);
executePostConstructMethod(factory.getInstance(null));
return new JSR250SingletonObjectFactory(factory.getInstance(null));
}
public static ObjectFactory createPrototypeObjectFactory(final Class cls) {
ClassMetadata classMetadata = collectClassMetadata(cls, true);
return new JSR250PrototypeObjectFactory(classMetadata);
}
@SuppressWarnings("unchecked")
protected static void executePostConstructMethod(T object) {
if (object != null) {
// check the cache
if (postConstructMethodCache.containsKey((Class)object.getClass())) {
Method m = postConstructMethodCache.get((Class)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)object.getClass()});
}
} else {
if(logger.isTraceEnabled()) {
logger.trace("No PostConstruct annotated method found for class {}", new Object[]{(Class)object.getClass()});
}
}
return;
}
// no cache entry; do the search and populate the cache
postConstructMethodCache.put((Class)object.getClass(), new PostConstructMethod(null));
List methods = getMethods(object.getClass());
for (Method method : methods) {
if (isPostConstruct(method)) {
invokeMethod(object, method, null);
// cache it
postConstructMethodCache.put((Class)object.getClass(), new PostConstructMethod(method));
// don't invoke all the @PostConstruct methods
break;
}
}
// logging:
Method m = postConstructMethodCache.get((Class)object.getClass()).getMethod();
if (m != null) {
if(logger.isTraceEnabled()) {
logger.trace("Invoked and cached PostConstruct annotated method {} for class {}", new Object[]{m, (Class)object.getClass()});
}
} else {
if(logger.isTraceEnabled()) {
logger.trace("No PostConstruct annotated method found for class {}, null value cached", new Object[]{(Class)object.getClass()});
}
}
}
}
@SuppressWarnings("unchecked")
protected static void executePreDestroyMethod(T object) {
if (object != null) {
// check the cache
if (preDestroyMethodCache.containsKey((Class)object.getClass())) {
Method m = preDestroyMethodCache.get((Class)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)object.getClass()});
}
} else {
if(logger.isTraceEnabled()) {
logger.trace("No PreDestroy annotated method found for class {}", new Object[]{(Class)object.getClass()});
}
}
return;
}
// no cache entry; do the search and populate the cache
preDestroyMethodCache.put((Class)object.getClass(), new PreDestroyMethod(null));
List methods = getMethods(object.getClass());
for (Method method : methods) {
if (isPreDestroy(method)) {
invokeMethod(object, method, null);
// cache it
preDestroyMethodCache.put((Class)object.getClass(), new PreDestroyMethod(method));
// don't invoke all the @PreDestroy methods
break;
}
}
// logging:
Method m = preDestroyMethodCache.get((Class)object.getClass()).getMethod();
if (m != null) {
if(logger.isTraceEnabled()) {
logger.trace("Invoked and cached PreDestroy annotated method {} for class {}", new Object[]{m, (Class)object.getClass()});
}
} else {
if(logger.isTraceEnabled()) {
logger.trace("No PreDestroy annotated method found for class {}, null value cached", new Object[]{(Class)object.getClass()});
}
}
}
}
// utility to detect existence of any method annotated with either @PostConstruct or @PreDestroy
@SuppressWarnings("unchecked")
protected static boolean hasJSR250AnnotatedMethod(Class clazz) {
List 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 getMethods(final Class beanClass) {
// This class must remain private due to Java 2 Security concerns
List methods;
methods = (List)AccessController.doPrivileged(
new PrivilegedAction() {
public Object run() {
List methods = new ArrayList();
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;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy