/* * Copyright (c) 1998-2011 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free SoftwareFoundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Rodrigo Westrupp */ package com.caucho.ejb.cfg; import com.caucho.bytecode.*; import com.caucho.util.L10N; import com.caucho.vfs.PersistentDependency; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.ArrayList; import java.util.logging.Logger; import javax.annotation.PostConstruct; import javax.interceptor.AroundInvoke; import javax.interceptor.InvocationContext; /** * Configuration for an interceptor. */ public class Interceptor { private static Logger log = Logger.getLogger(Interceptor.class.getName()); private static final L10N L = new L10N(Interceptor.class); private String _interceptorClass; private String _aroundInvokeMethodName; private AroundInvokeConfig _aroundInvokeConfig; private PreDestroyConfig _preDestroyConfig; private PostConstructConfig _postConstructConfig; private PrePassivateConfig _prePassivateConfig; private PostActivateConfig _postActivateConfig; private String _postConstructMethodName; private ClassLoader _loader; protected JClassLoader _jClassLoader; private JClass _interceptorJClass; ArrayList<PersistentDependency> _dependList = new ArrayList<PersistentDependency>(); public Interceptor() { _loader = Thread.currentThread().getContextClassLoader(); _jClassLoader = JClassLoaderWrapper.create(_loader); } public JClass getInterceptorJClass() { return _interceptorJClass; } public String getInterceptorClass() { return _interceptorClass; } public void setInterceptorClass(String interceptorClass) { _interceptorClass = interceptorClass; } public void init() { // ejb/0fb5 if (_aroundInvokeConfig != null) _aroundInvokeMethodName = _aroundInvokeConfig.getMethodName(); // ejb/0fbi if (_postConstructConfig != null) _postConstructMethodName = _postConstructConfig.getLifecycleCallbackMethod(); if (_aroundInvokeMethodName == null || _postConstructMethodName == null) { // XXX: EnhancerManager getJavaClassLoader() // ClassLoader parentLoader = Thread.currentThread().getContextClassLoader(); // JClassLoader jClassLoader = EnhancerManager.create(parentLoader).getJavaClassLoader(); _interceptorJClass = _jClassLoader.forName(_interceptorClass); JClass cl = _interceptorJClass; do { for (JMethod method : _interceptorJClass.getDeclaredMethods()) { if (method.isAnnotationPresent(AroundInvoke.class)) { // XXX: throw exception for invalid final or static. if (_aroundInvokeMethodName == null) _aroundInvokeMethodName = method.getName(); else if (cl == _interceptorJClass) { // XXX: throw exception for invalid duplicated @AroundInvoke methods. } } if (method.isAnnotationPresent(PostConstruct.class)) { // XXX: throw exception for invalid final or static. if (_postConstructMethodName == null) _postConstructMethodName = method.getName(); else if (cl == _interceptorJClass) { // XXX: throw exception for invalid duplicated @PostConstruct methods. } else { // XXX: needs to call superclass lifecycle callback methods. } } } } while ((cl = cl.getSuperClass()) != null); } } public static void makeAccessible(final Method method) { try { AccessController.doPrivileged(new PrivilegedExceptionAction() { public Object run() { method.setAccessible(true); return null; } }); } catch (PrivilegedActionException e) { throw new RuntimeException(e.getException()); } } public Method getAroundInvokeMethod() { return getAroundInvokeMethod(_interceptorJClass.getJavaClass(), _aroundInvokeMethodName); } public static Method getAroundInvokeMethod(Class cl, String methodName) { // ejb/0fbm for (Method method : cl.getDeclaredMethods()) { if (method.getName().equals(methodName)) { Class paramTypes[] = method.getParameterTypes(); if (paramTypes.length != 1) continue; if (! paramTypes[0].equals(InvocationContext.class)) continue; method.setAccessible(true); return method; } } return null; } public String getAroundInvokeMethodName() { return _aroundInvokeMethodName; } public String getPostConstructMethodName() { return _postConstructMethodName; } public PostActivateConfig getPostActivate() { return _postActivateConfig; } public PostConstructConfig getPostConstruct() { return _postConstructConfig; } public PreDestroyConfig getPreDestroy() { return _preDestroyConfig; } public PrePassivateConfig getPrePassivate() { return _prePassivateConfig; } public void setAroundInvoke(AroundInvokeConfig aroundInvoke) { _aroundInvokeConfig = aroundInvoke; } public void setPostActivate(PostActivateConfig postActivate) { _postActivateConfig = postActivate; } public void setPostConstruct(PostConstructConfig postConstruct) { _postConstructConfig = postConstruct; } public void setPreDestroy(PreDestroyConfig preDestroy) { _preDestroyConfig = preDestroy; } public void setPrePassivate(PrePassivateConfig prePassivate) { _prePassivateConfig = prePassivate; } public String toString() { return "Interceptor[" + _interceptorClass + "]"; } }