com.caucho.config.gen.InterceptorGenerator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of resin-kernel Show documentation
Show all versions of resin-kernel Show documentation
Kernel for Resin Java Application Server
The newest version!
/*
* Copyright (c) 1998-2012 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 Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.config.gen;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.enterprise.inject.Stereotype;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.InterceptionType;
import javax.enterprise.inject.spi.Interceptor;
import javax.enterprise.util.Nonbinding;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InterceptorBinding;
import com.caucho.config.ConfigException;
import com.caucho.config.inject.DependentCreationalContext;
import com.caucho.config.inject.InjectManager;
import com.caucho.config.inject.InterceptorBean;
import com.caucho.config.inject.InterceptorRuntimeBean;
import com.caucho.config.inject.InterceptorSelfBean;
import com.caucho.config.reflect.AnnotatedTypeUtil;
import com.caucho.inject.Module;
import com.caucho.java.JavaWriter;
/**
* Represents the interception
*/
@Module
public class InterceptorGenerator
extends AbstractAspectGenerator
{
private static final Logger log
= Logger.getLogger(InterceptorGenerator.class.getName());
private static final String INTERCEPTOR_MAP = "caucho.interceptor.map";
private static final Method _nullMethod;
private InterceptorFactory _factory;
private String _uniqueName;
private String _chainName;
private boolean _isChainNew;
// private boolean _isExcludeDefaultInterceptors;
// private boolean _isExcludeClassInterceptors;
private InterceptionType _interceptionType = InterceptionType.AROUND_INVOKE;
private ArrayList _interceptorBinding
= new ArrayList();
private ArrayList> _interceptors
= new ArrayList>();
private boolean _isEpilogue;
private InterceptionBinding _bindingEntry;
// map from the interceptor class to the local variable for the interceptor
private HashMap, String> _interceptorVarMap
= new HashMap, String>();
// interceptors we're responsible for initializing
private ArrayList> _ownInterceptors = new ArrayList>();
// decorators
private HashSet> _decoratorSet;
private final String _decoratorClass = "__caucho_decorator_class";
private final String _decoratorBeansVar = "__caucho_decorator_beans";
private final String _decoratorIndexVar = "__caucho_delegates";
private final String _decoratorLocalVar = _decoratorClass + "_tl";
private final String _delegateVar = "__caucho_delegate";
private String _decoratorSetName;
public InterceptorGenerator(InterceptorFactory factory,
AnnotatedMethod super X> method,
AspectGenerator next,
InterceptionType type,
HashSet> methodInterceptors,
HashMap, Annotation> methodInterceptorMap,
HashSet> decoratorSet,
boolean isExcludeClassInterceptors)
{
super(factory, method, next);
_factory = factory;
_interceptionType = type;
if (methodInterceptors != null)
_interceptors.addAll(methodInterceptors);
if (methodInterceptorMap != null)
_interceptorBinding.addAll(methodInterceptorMap.values());
_decoratorSet = decoratorSet;
introspect();
}
public InterceptorGenerator(InterceptorFactory factory,
HashSet> lifecycleInterceptors,
InterceptionType type)
{
super(factory, null, (NullGenerator) NullGenerator.NULL);
_factory = factory;
if (lifecycleInterceptors != null)
_interceptors.addAll(lifecycleInterceptors);
_interceptionType = type;
if (factory.getClassInterceptorBindings() != null)
_interceptorBinding.addAll(factory.getClassInterceptorBindings().values());
_isEpilogue = true;
}
public ArrayList> getInterceptors()
{
return _interceptors;
}
private AnnotatedMethod super X> getAroundInvokeMethod()
{
return _factory.getAroundInvokeMethod();
}
private boolean isProxy()
{
return _factory.getAspectBeanFactory().isProxy();
}
//
// introspection
//
/**
* Introspects the @Interceptors annotation on the method and the class.
*/
private void introspect()
{
/*
if (implMethod.isAnnotationPresent(Inject.class)
|| implMethod.isAnnotationPresent(PostConstruct.class)) {
// ioc/0a23, ioc/0c57
return;
}
*/
introspectInterceptors();
// introspectDefaults();
}
private void introspectInterceptors()
{
}
//
// bean instance generation
//
public void generateClassPostConstruct(JavaWriter out,
HashMap map)
throws IOException
{
super.generatePostConstruct(out, map);
_uniqueName = (String) map.get("caucho.interceptor.postConstructName");
generateInterceptorCall(out, map);
map.put("caucho.interceptor.postConstructName", _uniqueName);
}
public void generateClassPreDestroy(JavaWriter out,
HashMap map)
throws IOException
{
super.generatePreDestroy(out, map);
_uniqueName = (String) map.get("caucho.interceptor.preDestroyName");
generateInterceptorCall(out, map);
map.put("caucho.interceptor.preDestroyName", _uniqueName);
}
@Override
public void generateEpilogue(JavaWriter out,
HashMap map)
throws IOException
{
super.generateEpilogue(out, map);
String key = null;
if (_interceptionType == InterceptionType.POST_CONSTRUCT)
key = "caucho.interceptor.postConstructName";
else if (_interceptionType == InterceptionType.PRE_DESTROY)
key = "caucho.interceptor.preDestroyName";
_uniqueName = (String) map.get(key);
/*
if (_uniqueName == null)
return;
*/
generateBeanPrologue(out, map);
generateMethodPrologue(out, map);
out.println("static {");
out.pushDepth();
out.println("try {");
out.pushDepth();
out.print(CandiUtil.class.getName());
out.print(".createInterceptors(__caucho_manager, __caucho_interceptor_beans");
for (int i = 0; i < _interceptorBinding.size(); i++) {
out.print(", ");
generateAnnotation(out, _interceptorBinding.get(i));
}
out.println(");");
if (isPassivating()) {
String beanClassName = getFactory().getAspectBeanFactory().getInstanceClassName();
out.println();
out.print("com.caucho.config.gen.CandiUtil.validatePassivating(");
out.print(beanClassName + ".class, ");
out.println("__caucho_interceptor_beans);");
}
out.popDepth();
out.println("} catch (Exception e) {");
out.println(" __caucho_log.log(java.util.logging.Level.WARNING, e.toString(), e);");
out.println(" __caucho_exception = com.caucho.config.ConfigException.create(e);");
out.println("}");
out.popDepth();
out.println("}");
map.put(key, _uniqueName);
}
private boolean isPassivating()
{
if (_factory.isPassivating())
return true;
else if (_factory.isStateful())
return _interceptorBinding.size() > 0 || _decoratorSet != null;
else
return false;
}
/**
* Generates the prologue for the bean instance.
*/
@Override
public void generateBeanPrologue(JavaWriter out,
HashMap map)
throws IOException
{
super.generateBeanPrologue(out, map);
if (map.get("__caucho_interceptor_objects") == null) {
map.put("__caucho_interceptor_objects", true);
out.println();
out.print("private transient Object []");
out.println("__caucho_interceptor_objects;");
out.println("Object []_caucho_getInterceptorObjects()");
out.println("{ return __caucho_interceptor_objects; }");
}
generateBeanInterceptorChain(out, map);
// if (getMethod() != null)
generateTail(out);
/*
else
generateNullTail(out);
*/
}
@Override
public void generateBeanConstructor(JavaWriter out,
HashMap map)
throws IOException
{
super.generateBeanConstructor(out, map);
/*
if (hasInterceptor()) {
generateInterceptorBeanConstructor(out, map);
}
*/
if (hasDecorator()) {
generateDecoratorBeanConstructor(out, map);
}
}
@Override
public void generateInject(JavaWriter out,
HashMap map)
throws IOException
{
super.generateInject(out, map);
if (hasInterceptor()) {
generateInterceptorBeanInject(out, map);
}
if (hasDecorator()) {
generateDecoratorBeanInject(out, map);
}
}
@Override
public void generateProxyConstructor(JavaWriter out,
HashMap map)
throws IOException
{
super.generateProxyConstructor(out, map);
if (hasDecorator()) {
// generateDecoratorProxyConstructor(out, map);
}
}
private void generateInterceptorBeanInject(JavaWriter out,
HashMap map)
throws IOException
{
if (map.get("interceptor_object_init") != null)
return;
map.put("interceptor_object_init", true);
out.println("int size = __caucho_interceptor_beans.size();");
out.println("if (interceptors == null) {");
out.pushDepth();
out.println("interceptors = new Object[size];");
out.println();
// XXX: should be parent bean
// out.println(" = __caucho_manager.createCreationalContext(null);");
out.println();
out.println("for (int i = 0; i < size; i++) {");
out.pushDepth();
out.println("javax.enterprise.inject.spi.Bean bean");
out.println(" = __caucho_interceptor_beans.get(i);");
out.println("javax.enterprise.context.spi.CreationalContext env");
out.println(" = new " + DependentCreationalContext.class.getName() + "(bean, parentEnv, null);");
out.print("interceptors[i] = ");
out.println("__caucho_manager.getReference(bean, bean.getBeanClass(), env);");
// ejb/6032
out.print("if (interceptors[i] == null && (bean instanceof ");
out.printClass(InterceptorSelfBean.class);
out.println("))");
out.print(" interceptors[i] = ");
out.print(getBeanFactory().getBeanInstance());
out.println(";");
out.println("else if (interceptors[i] == null)");
out.println(" throw new NullPointerException(String.valueOf(bean));");
out.popDepth();
out.println("}");
out.popDepth();
out.println("}");
out.println("__caucho_interceptor_objects = interceptors;");
for (Class> iClass : _ownInterceptors) {
String var = _interceptorVarMap.get(iClass);
out.println("if (" + var + "_f == null)");
out.println(" " + var + "_f = __caucho_manager.createTransient("
+ iClass.getName() + ".class);");
out.print(var + " = (");
out.printClass(iClass);
out.println(") __caucho_manager.getInstance(" + var + "_f);");
}
}
// XXX This map is really a Map, so putting in an
// InterceptionBinding seems wrong. Also, it doesn't discriminate the
// chainName -- see the generated code for test1() in ejb/10a5
private void generateBeanInterceptorChain(JavaWriter out,
HashMap map)
throws IOException
{
_chainName = getChainName(out, map);
if (_interceptors.size() > 0) {
List> interceptors = (List>) map.get("@Interceptors");
if (interceptors == null)
interceptors = new ArrayList>();
// int []indexChain = new int[_interceptors.size()];
}
}
//
// business method interception
//
/**
* Generates the prologue for a method.
*/
@Override
public void generateMethodPrologue(JavaWriter out,
HashMap map)
throws IOException
{
super.generateMethodPrologue(out, map);
if (map.get("__caucho_manager") == null) {
map.put("__caucho_manager", true);
out.println();
out.print("private static ");
out.printClass(InjectManager.class);
out.println(" __caucho_manager");
out.print(" = ");
out.printClass(InjectManager.class);
out.println(".create();");
}
/* XXX:
if (! _isExcludeDefaultInterceptors)
_interceptors.addAll(_view.getBean().getDefaultInterceptors());
*/
if (hasInterceptor())
generateInterceptorMethodPrologue(out, map);
if (hasDecorator())
generateDecoratorMethodPrologue(out, map);
// _bizMethod.generateInterceptorTarget(out);
}
@Override
public void generatePreTry(JavaWriter out)
throws IOException
{
// ejb/12a0
super.generatePreTry(out);
if (hasDecorator()) {
generateDecoratorPreTry(out);
}
}
@Override
public void generatePreCall(JavaWriter out)
throws IOException
{
if (hasDecorator()) {
generateDecoratorPreCall(out);
}
}
@Override
public void generateCall(JavaWriter out)
throws IOException
{
if (hasInterceptor()) {
HashMap map = null;
generateInterceptorCall(out, map);
}
else if (hasDecorator()) {
generateDecoratorCall(out);
}
else {
throw new IllegalStateException(toString());
}
}
@Override
public void generateFinally(JavaWriter out)
throws IOException
{
// server/12a0
super.generateFinally(out);
if (hasDecorator()) {
generateDecoratorFinally(out);
}
}
//
// interceptor
//
@Override
protected Method getJavaMethod()
{
AnnotatedMethod super X> method = getMethod();
if (method != null)
return method.getJavaMember();
else
return _nullMethod;
}
private void generateInterceptorMethodPrologue(JavaWriter out,
HashMap map)
throws IOException
{
if (map.get("__caucho_interceptor_beans") == null) {
map.put("__caucho_interceptor_beans", true);
out.println();
out.print("private static final ");
out.print("java.util.ArrayList<");
out.printClass(InterceptorRuntimeBean.class);
out.println(">> __caucho_interceptor_static_beans");
out.print(" = new java.util.ArrayList<");
out.printClass(InterceptorRuntimeBean.class);
out.println(">>();");
out.println();
out.print("private static final ");
out.print("java.util.ArrayList<");
out.printClass(Interceptor.class);
out.println(">> __caucho_interceptor_beans");
out.print(" = new java.util.ArrayList<");
out.printClass(Interceptor.class);
out.println(">>();");
}
generateInterceptorMethod(out, map);
generateInterceptorChain(out, map);
}
private void generateInterceptorMethod(JavaWriter out,
HashMap map)
throws IOException
{
Method javaMethod = getJavaMethod();
out.println();
out.println("private static java.lang.reflect.Method "
+ getUniqueName(out) + "_method;");
out.println("private static java.lang.reflect.Method "
+ getUniqueName(out) + "_implMethod;");
boolean isAroundInvokePrologue = false;
if (getAroundInvokeMethod() != null
&& map.get("ejb.around-invoke") == null) {
isAroundInvokePrologue = true;
map.put("ejb.around-invoke", "_caucho_aroundInvokeMethod");
out.println(
"private static java.lang.reflect.Method __caucho_aroundInvokeMethod;");
}
out.println();
out.println("static {");
out.pushDepth();
out.println("try {");
out.pushDepth();
out.print(getUniqueName(out) + "_method = ");
String declaringClassName = javaMethod.getDeclaringClass().getName();
if (hasDecorator()) {
// ioc/0c22
declaringClassName = _decoratorSet.iterator().next().getName();
}
generateGetMethod(out,
declaringClassName,
javaMethod.getName(),
javaMethod.getParameterTypes());
out.println(";");
out.println(getUniqueName(out) + "_method.setAccessible(true);");
String superMethodName = getSuperMethodName();
out.print(getUniqueName(out) + "_implMethod = ");
String className;
if (javaMethod.getDeclaringClass().equals(getClass())) {
className = InterceptorGenerator.class.getName();
superMethodName = javaMethod.getName();
}
else {
// ioc/0c22
// className = getBeanFactory().getInstanceClassName();
className = declaringClassName;
// ejb/6030 vs ioc/0c00
if (getBeanFactory().isProxy()) {
superMethodName = javaMethod.getName();
}
}
// ejb/1061
if (Modifier.isStatic(javaMethod.getModifiers())) {
generateGetMethod(out,
javaMethod.getDeclaringClass().getName(),
javaMethod.getName(),
javaMethod.getParameterTypes());
}
else {
generateGetMethod(out,
className,
superMethodName,
javaMethod.getParameterTypes());
}
out.println(";");
/*
out.print(getUniqueName(out) + "_implMethod = ");
out.println(getUniqueName(out) + "_method;");
out.println(getUniqueName(out) + "_implMethod.setAccessible(true);");
*/
if (isAroundInvokePrologue) {
AnnotatedMethod super X> aroundInvoke = getAroundInvokeMethod();
out.print("__caucho_aroundInvokeMethod = ");
generateGetMethod(out,
aroundInvoke.getJavaMember().getDeclaringClass().getName(),
aroundInvoke.getJavaMember().getName(),
aroundInvoke.getJavaMember().getParameterTypes());
out.println(";");
out.println("__caucho_aroundInvokeMethod.setAccessible(true);");
}
out.popDepth();
out.println("} catch (Exception e) {");
out.println(" __caucho_log.log(java.util.logging.Level.WARNING, e.toString(), e);");
out.println(" __caucho_exception = com.caucho.config.ConfigException.create(e);");
out.println("}");
out.popDepth();
out.println("}");
}
private String getSuperMethodName()
{
Method javaMethod = getJavaMethod();
String declName = javaMethod.getDeclaringClass().getSimpleName();
if (hasDecorator())
return "__caucho_" + javaMethod.getName() + "_decorator";
else if (isProxy())
return javaMethod.getName();
else {
return ("__caucho_" + declName
+ "_" + javaMethod.getName()
+ "_" + _interceptionType);
}
}
private String getChainName(JavaWriter out, HashMap map)
{
if (_chainName != null)
return _chainName;
HashMap bindingMap = (HashMap) map.get(INTERCEPTOR_MAP);
if (bindingMap == null) {
bindingMap = new HashMap();
map.put(INTERCEPTOR_MAP, bindingMap);
}
_bindingEntry
= new InterceptionBinding(_interceptionType,
_interceptorBinding,
_interceptors);
_chainName = (String) bindingMap.get(_bindingEntry);
if (_chainName != null) {
return _chainName;
}
_chainName = getUniqueName(out);
_isChainNew = true;
bindingMap.put(_bindingEntry, _chainName);
return _chainName;
}
private void generateInterceptorChain(JavaWriter out,
HashMap map)
throws IOException
{
String chainName = getChainName(out, map);
if (! _isChainNew)
return;
if (_interceptors.size() > 0) {
List> interceptors = (List>) map.get("@Interceptors");
if (interceptors == null) {
interceptors = new ArrayList>();
map.put("@Interceptors", interceptors);
}
ArrayList indexChain = new ArrayList();
out.println("static {");
out.pushDepth();
for (int i = 0; i < _interceptors.size(); i++) {
Class> iClass = _interceptors.get(i);
int index = interceptors.indexOf(iClass);
if (index > -1) {
indexChain.add(index);
}
else {
indexChain.add(interceptors.size());
interceptors.add(iClass);
if (iClass.isAssignableFrom(getJavaClass())) {
out.print("__caucho_interceptor_static_beans.add(new ");
out.printClass(InterceptorSelfBean.class);
out.print("(");
//out.printClass(iClass);
out.printClass(getJavaClass());
out.println(".class));");
}
else {
out.print("__caucho_interceptor_static_beans.add(new ");
out.printClass(InterceptorBean.class);
out.print("(");
out.printClass(iClass);
out.println(".class));");
}
}
}
out.popDepth();
out.println("}");
out.println();
out.print("private static int []" + chainName
+ "_objectIndexStaticChain = new int[] {");
for (int i : indexChain) {
out.print(i);
out.print(',');
}
out.println("};");
} else {
out.println("private static int []"
+ chainName + "_objectIndexStaticChain;");
}
out.println("private static int []"
+ chainName + "_objectIndexChain;");
out.println("private static javax.enterprise.inject.spi.Interceptor []"
+ chainName + "_methodChain;");
out.println();
out.println("static {");
out.pushDepth();
out.println("try {");
out.pushDepth();
generateMethodChain(out, map);
out.popDepth();
out.println("} catch (Exception e) {");
out.println(" __caucho_log.log(java.util.logging.Level.WARNING, e.toString(), e);");
out.println(" __caucho_exception = com.caucho.config.ConfigException.create(e);");
out.println("}");
out.popDepth();
out.println("}");
}
private void generateMethodChain(JavaWriter out, HashMap map)
throws IOException
{
String chainName = getChainName(out, map);
out.println(chainName + "_objectIndexChain =");
out.println(" com.caucho.config.gen.CandiUtil.createInterceptors(");
out.println(" __caucho_manager,");
out.println(" __caucho_interceptor_static_beans,");
out.println(" __caucho_interceptor_beans,");
out.println(" " + chainName+ "_objectIndexStaticChain,");
out.print(" " + InterceptionType.class.getName()
+ "." + _interceptionType);
for (int i = 0; i < _interceptorBinding.size(); i++) {
out.println(",");
out.pushDepth();
out.pushDepth();
generateAnnotation(out, _interceptorBinding.get(i));
out.popDepth();
out.popDepth();
}
out.println(");");
out.println();
out.println(chainName + "_methodChain = ");
out.println(" com.caucho.config.gen.CandiUtil.createMethods(");
out.println(" __caucho_interceptor_beans,");
out.println(" " + InterceptionType.class.getName()
+ "." + _interceptionType + ",");
out.println(" " + chainName + "_objectIndexChain);");
if (isPassivating()) {
String beanClassName = getFactory().getAspectBeanFactory().getInstanceClassName();
out.println();
out.print("com.caucho.config.gen.CandiUtil.validatePassivating(");
out.print(beanClassName + ".class, ");
out.println("__caucho_interceptor_beans);");
}
}
private void generateInterceptorCall(JavaWriter out,
HashMap map)
throws IOException
{
Method javaMethod = getJavaMethod();
String uniqueName = getUniqueName(out);
String chainName = getChainName(out, map);
out.println("try {");
out.pushDepth();
if (javaMethod != null && ! void.class.equals(javaMethod.getReturnType())) {
out.print("result = (");
printCastClass(out, getMethod().getBaseType());
out.print(") ");
}
out.print("new ");
out.printClass(CandiInvocationContext.class);
out.println("(");
out.pushDepth();
out.pushDepth();
out.printClass(InterceptionType.class);
out.println("." + _interceptionType + ", ");
if (hasDecorator())
out.print("delegate");
else
out.print(_factory.getAspectBeanFactory().getInterceptorInstance());
out.println(", ");
// generateThis(out);
if (_interceptionType == InterceptionType.AROUND_INVOKE)
out.println(uniqueName + "_method, ");
else
out.println("null, ");
// generateThis(out);
out.println(uniqueName + "_implMethod, ");
// generateThis(out);
out.println(chainName + "_methodChain, ");
out.print(_factory.getAspectBeanFactory().getBeanInfo());
out.println("._caucho_getInterceptorObjects(), ");
// generateThis(out);
out.println(chainName + "_objectIndexChain, ");
Class>[] paramTypes
= (javaMethod != null ? javaMethod.getParameterTypes() : null);
if (getMethod() == null
|| getMethod().isAnnotationPresent(PostConstruct.class)) {
out.println("null");
}
else if (paramTypes == null || paramTypes.length == 0) {
out.println("com.caucho.config.gen.CandiUtil.NULL_OBJECT_ARRAY");
}
else {
out.print("new Object[] { ");
for (int i = 0; i < javaMethod.getParameterTypes().length; i++) {
out.print("a" + i + ", ");
}
out.println("}");
}
out.println(").proceed();");
out.popDepth();
out.popDepth();
/*
// super.generatePostCall(out);
if (! void.class.equals(_implMethod.getReturnType())) {
out.println("return result;");
}
*/
out.popDepth();
out.println("} catch (RuntimeException e) {");
out.println(" throw e;");
boolean isException = false;
Class>[] exnList;
if (javaMethod != null)
exnList = javaMethod.getExceptionTypes();
else
exnList = new Class>[0];
for (Class> cl : exnList) {
if (RuntimeException.class.isAssignableFrom(cl))
continue;
if (! isMostGeneralException(exnList, cl))
continue;
if (cl.isAssignableFrom(Exception.class))
isException = true;
out.println("} catch (" + cl.getName() + " e) {");
out.println(" throw e;");
}
if (! isException) {
out.println("} catch (Exception e) {");
out.println(" throw new RuntimeException(e);");
}
out.println("}");
}
//
// decorator method
//
private void generateDecoratorBeanConstructor(JavaWriter out,
HashMap map)
throws IOException
{
}
private void generateDecoratorBeanInject(JavaWriter out,
HashMap map)
throws IOException
{
if (_decoratorSet == null)
return;
out.println("__caucho_delegates = delegates;");
}
private void generateDecoratorMethodPrologue(JavaWriter out,
HashMap map)
throws IOException
{
generateDecoratorClass(out, map);
String decoratorSetName = getDecoratorSetName(out, map);
if (hasInterceptor())
generateDecoratorMethod(out);
if (map.get("decorator_bean_" + decoratorSetName) != null)
return;
map.put("decorator_bean_" + decoratorSetName, true);
if (map.get("decorator_delegate_decl") == null) {
map.put("decorator_delegate_decl", true);
out.print("private static ");
out.print(_decoratorClass);
out.println(" " + _delegateVar + ";");
out.println();
out.println("private static "
+ "java.util.List> "
+ _decoratorBeansVar + ";");
out.println();
out.println("static final ThreadLocal<" + _decoratorClass + "> "
+ _decoratorLocalVar);
out.println(" = new ThreadLocal<" + _decoratorClass + ">();");
out.println();
out.println("private transient Object [] " + _decoratorIndexVar + ";");
out.println();
out.println("final Object []__caucho_getDelegates()");
out.println("{");
out.println(" return " + _decoratorIndexVar + ";");
out.println("}");
generateDecoratorInit(out);
}
}
private void generateDecoratorInit(JavaWriter out)
throws IOException
{
out.println();
out.println("public static Object __caucho_decorator_init()");
out.println("{");
out.pushDepth();
out.println("if (__caucho_delegate == null)");
out.println(" __caucho_delegate = new __caucho_decorator_class(0, null, null);");
out.println();
out.println("return __caucho_delegate;");
out.popDepth();
out.println("}");
}
private void generateDecoratorClass(JavaWriter out,
HashMap map)
throws IOException
{
if (map.get("decorator_class_decl") != null)
return;
map.put("decorator_class_decl", true);
String className = _decoratorClass;
ArrayList methodList = new ArrayList();
HashMap>, String> apiMap
= new HashMap>, String>();
for (Class> decoratorClass : _factory.getDecoratorClasses()) {
for (Method method : decoratorClass.getMethods()) {
if (Modifier.isFinal(method.getModifiers())
|| Modifier.isStatic(method.getModifiers())
|| Modifier.isPrivate(method.getModifiers())
|| (method.getDeclaringClass() == Object.class)) {
//|| (method.getDeclaringClass() == Object.class
// && ! method.getName().equals("toString"))) {
continue;
}
if (! containsMethod(methodList, method)) {
methodList.add(method);
}
}
}
for (Method method : methodList) {
generateDecoratorMethodDecl(out, method);
}
out.println();
out.println("public static void __caucho_init_decorators(java.util.List> decoratorList)");
out.println("{");
out.pushDepth();
for (Method method : methodList) {
out.print("_caucho_decorator_" + method.getName() + "_m");
out.print(" = com.caucho.config.gen.CandiUtil.createDecoratorMethods(decoratorList, ");
out.print("\"" + method.getName() + "\"");
for (int i = 0; i < method.getParameterTypes().length; i++) {
out.print(", ");
out.printClass(method.getParameterTypes()[i]);
out.print(".class");
}
out.println(");");
}
if (isPassivating()) {
String beanClassName = getFactory().getAspectBeanFactory().getInstanceClassName();
out.println();
out.print("com.caucho.config.gen.CandiUtil.validatePassivatingDecorators(");
out.print(beanClassName + ".class, ");
out.println("decoratorList);");
}
out.popDepth();
out.println("}");
out.println();
out.print("static class ");
out.print(className);
out.print(" ");
for (Class> cl : _factory.getDecoratorClasses()) {
if (! cl.isInterface()) {
out.print(" extends ");
out.printClass(cl);
}
}
boolean isFirst = true;
for (Class> cl : _factory.getDecoratorClasses()) {
if (! cl.isInterface())
continue;
if (isFirst)
out.print(" implements ");
else
out.print(", ");
isFirst = false;
out.printClass(cl);
}
out.println(" {");
out.pushDepth();
// String beanClassName = getBeanType().getJavaClass().getName();
String beanClassName = _factory.getInstanceClassName();
out.println("private int _index;");
out.println("private " + beanClassName + " _bean;");
out.println("private Object [] _delegates;");
out.println();
out.print(className + "(int index, " + beanClassName + " bean, Object []delegates)");
out.println("{");
out.println(" _index = index;");
out.println(" _bean = bean;");
out.println(" _delegates = delegates;");
out.println("}");
out.println();
out.println("final " + beanClassName + " __caucho_getBean()");
out.println("{");
/*
out.println(" return " + getBusinessMethod().getView().getViewClassName()
+ ".this;");
*/
out.println(" return _bean;");
out.println("}");
for (Method method : methodList) {
generateDecoratorMethod(out, method, apiMap);
}
out.popDepth();
out.println("}");
for (Map.Entry>, String> entry : apiMap.entrySet()) {
ArrayList> apis = entry.getKey();
String name = entry.getValue();
out.println();
out.println("static final Class []" + name + " = new Class[] {");
out.pushDepth();
for (int i = 0; i < apis.size(); i++) {
out.printClass(apis.get(i));
out.println(".class,");
}
out.popDepth();
out.println("};");
}
}
private void generateDecoratorMethodDecl(JavaWriter out, Method method)
throws IOException
{
out.println("static java.lang.reflect.Method []_caucho_decorator_" + method.getName() + "_m;");
}
private void generateDecoratorMethod(JavaWriter out,
Method method,
HashMap>, String> apiMap)
throws IOException
{
AnnotatedMethod super X> annMethod
= AnnotatedTypeUtil.findMethod(getBeanType(),
method.getName(),
method.getParameterTypes());
String uniqueName = getUniqueName(out);
ArrayList> apis = getMethodApis(method);
String apiName = apiMap.get(apis);
if (apiName == null && apis.size() > 1) {
apiName = uniqueName + "_api_" + apiMap.size();
apiMap.put(apis, apiName);
}
out.println();
out.print("public ");
out.printClass(method.getReturnType());
out.print(" ");
out.print(method.getName());
out.print("(");
Class>[] paramTypes = method.getParameterTypes();
for (int i = 0; i < paramTypes.length; i++) {
if (i != 0)
out.print(", ");
out.printClass(paramTypes[i]);
out.print(" a" + i);
}
out.println(")");
Class>[] exnTypes = method.getExceptionTypes();
if (exnTypes.length > 0) {
out.print(" throws ");
for (int i = 0; i < exnTypes.length; i++) {
if (i != 0)
out.print(", ");
out.printClass(exnTypes[i]);
}
}
out.println("{");
out.pushDepth();
if (annMethod != null && annMethod.isAnnotationPresent(Inject.class)) {
out.println(_decoratorClass + " var = " + _decoratorLocalVar + ".get();");
printDecoratorSuperCall(out, method, annMethod);
}
else {
out.println(_decoratorClass + " var = " + _decoratorLocalVar + ".get();");
// out.println("Object []delegates = var.__caucho_getBean()." + _decoratorIndexVar + ";");
// out.println("Object []delegates = _bean != null ? _bean." + _decoratorIndexVar + " : null;");
// out.println("Object []delegates = var._bean.__caucho_getDelegates();");
out.println("Object []delegates = var._delegates;");
out.println();
out.print("var._index = com.caucho.config.gen.CandiUtil.nextDelegate(");
out.print("delegates, ");
/*
if (apis.size() > 1) {
out.print(apiName);
}
else {
out.printClass(decoratorType);
out.print(".class");
}
*/
out.print("_caucho_decorator_" + method.getName() + "_m");
out.println(", var._index);");
out.println();
out.println("if (var._index >= 0) {");
out.pushDepth();
out.println("Object delegate = delegates[var._index];");
for (int j = 0; j < apis.size(); j++) {
if (j > 0)
out.print("else ");
if (j + 1 < apis.size()) {
out.print("if (delegate instanceof ");
out.printClass(apis.get(j));
out.print(")");
}
if (apis.size() > 1) {
out.println();
out.print(" ");
}
if (! void.class.equals(method.getReturnType())) {
out.print("return (");
out.printClass(method.getReturnType());
out.print(") ");
}
/*
out.print("((");
out.printClass(apis.get(j));
out.print(") delegate)." + method.getName());
*/
out.print("com.caucho.config.gen.CandiUtil.invoke(");
out.print("_caucho_decorator_" + method.getName() + "_m[");
out.print("var._index");
out.print("], delegate");
for (int i = 0; i < paramTypes.length; i++) {
out.print(", ");
out.print("a" + i);
}
out.println(");");
}
out.popDepth();
out.println("}");
out.println("else");
out.pushDepth();
printDecoratorSuperCall(out, method, annMethod);
}
out.popDepth();
out.println("}");
}
private void printDecoratorSuperCall(JavaWriter out,
Method method,
AnnotatedMethod super X> annMethod)
throws IOException
{
Class>[] paramTypes = method.getParameterTypes();
if (! void.class.equals(method.getReturnType()))
out.print("return ");
if (isProxy()
|| annMethod != null && annMethod.isAnnotationPresent(Inject.class)) {
out.print("var.__caucho_getBean().");
out.print(method.getName());
}
else {
out.print("var.__caucho_getBean().");
String declName = annMethod.getDeclaringType().getJavaClass().getSimpleName();
out.print("__caucho_" + declName + "_" + method.getName() + "_" + _interceptionType);
}
out.print("(");
for (int i = 0; i < paramTypes.length; i++) {
if (i != 0)
out.print(", ");
out.print("a" + i);
}
out.println(");");
out.popDepth();
}
//
// method generators
//
private void generateDecoratorMethod(JavaWriter out)
throws IOException
{
Method javaMethod = getJavaMethod();
out.println();
out.print("private ");
out.printClass(javaMethod.getReturnType());
out.print(" __caucho_");
out.print(javaMethod.getName());
out.print("_decorator(");
Class>[] types = javaMethod.getParameterTypes();
for (int i = 0; i < types.length; i++) {
Class> type = types[i];
if (i != 0)
out.print(", ");
out.printClass(type);
out.print(" a" + i);
}
out.println(")");
AspectGeneratorUtil.generateThrows(out, javaMethod.getExceptionTypes());
out.println("{");
out.pushDepth();
if (! void.class.equals(javaMethod.getReturnType())) {
out.printClass(javaMethod.getReturnType());
out.println(" result;");
}
generateDecoratorCall(out);
if (! void.class.equals(javaMethod.getReturnType())) {
out.println("return result;");
}
out.popDepth();
out.println("}");
}
private void generateDecoratorPreTry(JavaWriter out)
throws IOException
{
out.print(_decoratorClass + " oldDecorator = ");
out.println(_decoratorLocalVar + ".get();");
}
private void generateDecoratorPreCall(JavaWriter out)
throws IOException
{
String decoratorSetName = _decoratorSetName;
assert(decoratorSetName != null);
out.println("Object []caucho_delegates = "
+ getBeanFactory().getBeanInfo() + ".__caucho_getDelegates();");
out.println();
out.print(_decoratorClass + " delegate = ");
out.print("new " + _decoratorClass + "(");
out.print("caucho_delegates.length, ");
out.print(_factory.getAspectBeanFactory().getBeanInstance() + ", ");
out.print("caucho_delegates");
out.println(");");
out.print(_decoratorLocalVar);
out.println(".set(delegate);");
}
/**
* Generates the low-level decorator call at the end of the chain.
*/
private void generateDecoratorCall(JavaWriter out)
throws IOException
{
String decoratorSetName = _decoratorSetName;
assert(decoratorSetName != null);
Method javaMethod = getJavaMethod();
//_bizMethod.generateTailCall(out);
if (! void.class.equals(javaMethod.getReturnType()))
out.print("result = ");
out.print("__caucho_delegate.");
out.print(javaMethod.getName());
out.print("(");
for (int i = 0; i < javaMethod.getParameterTypes().length; i++) {
if (i != 0)
out.print(", ");
out.print("a" + i);
}
out.println(");");
}
private void generateDecoratorFinally(JavaWriter out)
throws IOException
{
out.print(_decoratorLocalVar);
out.println(".set(oldDecorator);");
}
//
// utilities
//
private String getUniqueName(JavaWriter out)
{
if (_uniqueName == null) {
String name = getJavaMethod().getName();
_uniqueName = ("_" + name + "_" + _interceptionType
+ "_" + out.generateId());
}
return _uniqueName;
}
private String getDecoratorSetName(JavaWriter out,
Map map)
{
if (_decoratorSetName != null)
return _decoratorSetName;
HashMap>,String> nameMap;
nameMap = (HashMap>,String>) map.get("decorator_name_map");
if (nameMap == null) {
nameMap = new HashMap>,String>();
map.put("decorator_name_map", nameMap);
}
String name = nameMap.get(_decoratorSet);
if (name == null) {
name = "__caucho_decorator_" + out.generateId();
nameMap.put(_decoratorSet, name);
}
_decoratorSetName = name;
return name;
}
private void generateAnnotation(JavaWriter out,
Annotation ann)
throws IOException
{
out.print("new javax.enterprise.util.AnnotationLiteral<");
out.printClass(ann.annotationType());
out.print(">() {");
boolean isFirst = true;
for (Method method : ann.annotationType().getMethods()) {
if (method.getDeclaringClass().equals(Object.class))
continue;
if (method.getDeclaringClass().equals(Annotation.class))
continue;
if (method.getName().equals("annotationType"))
continue;
if (method.getParameterTypes().length > 0)
continue;
if (void.class.equals(method.getReturnType()))
continue;
if (method.isAnnotationPresent(Nonbinding.class))
continue;
out.pushDepth();
/*
if (! isFirst)
out.print(",");
*/
isFirst = false;
out.println();
out.print("public ");
out.printClass(method.getReturnType());
out.print(" " + method.getName() + "() { return ");
Object value = null;
try {
method.setAccessible(true);
value = method.invoke(ann);
}
catch (Exception e) {
throw ConfigException.create(e);
}
printValue(out, value);
out.println("; }");
out.popDepth();
}
out.print("}");
}
private void printValue(JavaWriter out, Object value)
throws IOException
{
if (value == null)
out.print("null");
else if (value instanceof String) {
out.print("\"");
out.printJavaString((String) value);
out.print("\"");
}
else if (value instanceof Character) {
out.print("\'");
out.printJavaString(String.valueOf(value));
out.print("\'");
}
else if (value instanceof Enum>) {
out.printClass(value.getClass());
out.print("." + value);
}
else if (value instanceof Class>) {
out.printClass((Class>) value);
out.print(".class");
}
else if (value.getClass().isArray()) {
out.print("new ");
out.printClass(value.getClass().getComponentType());
out.print("[] {");
Object []v = (Object []) value;
for (int i = 0; i < v.length; i++) {
printValue(out, v[i]);
out.print(", ");
}
out.print("}");
}
else
out.print(value);
}
private ArrayList> getMethodApis(Method method)
{
ArrayList> apis = new ArrayList>();
for (Class> decoratorClass : _factory.getDecoratorClasses()) {
if (containsMethod(decoratorClass.getMethods(), method)
&& ! apis.contains(decoratorClass))
apis.add(decoratorClass);
}
return apis;
}
private boolean hasInterceptor()
{
return (_interceptors != null && _interceptors.size() > 0
|| _interceptorBinding != null && _interceptorBinding.size() > 0
|| getAroundInvokeMethod() != null
|| _factory.isSelfInterceptor()
|| _isEpilogue);
}
private boolean hasDecorator()
{
return _decoratorSet != null;
}
private void generateTail(JavaWriter out)
throws IOException
{
Method javaMethod = getJavaMethod();
out.println();
out.print("private ");
out.printClass(javaMethod.getReturnType());
out.print(" __caucho_");
out.print(javaMethod.getDeclaringClass().getSimpleName());
out.print("_" + javaMethod.getName());
out.print("_" + _interceptionType);
out.print("(");
Class>[] types = javaMethod.getParameterTypes();
for (int i = 0; i < types.length; i++) {
Class> type = types[i];
if (i != 0)
out.print(", ");
out.printClass(type);
out.print(" a" + i);
}
out.println(")");
AspectGeneratorUtil.generateThrows(out, javaMethod.getExceptionTypes());
out.println();
out.println("{");
out.pushDepth();
if (! void.class.equals(javaMethod.getReturnType())) {
out.printClass(javaMethod.getReturnType());
out.println(" result;");
}
generateTailCall(out, getFactory().getAspectBeanFactory().getBeanSuper());
if (! void.class.equals(javaMethod.getReturnType()))
out.println("return result;");
out.popDepth();
out.println("}");
}
private void generateNullTail(JavaWriter out)
throws IOException
{
out.println();
out.println("private void __caucho_nullPostConstruct()");
out.println("{");
out.pushDepth();
out.popDepth();
out.println("}");
out.println();
out.println("private void __caucho_nullPreDestroy()");
out.println("{");
out.pushDepth();
out.popDepth();
out.println("}");
}
/**
* Generates the call to the implementation bean.
*
* @param superVar java code to reference the implementation
*/
public void generateTailCall(JavaWriter out, String superVar)
throws IOException
{
super.generateCall(out);
/*
Method javaMethod = getJavaMethod();
if (Modifier.isStatic(javaMethod.getModifiers()))
superVar = javaMethod.getDeclaringClass().getName();
out.println();
if (! void.class.equals(javaMethod.getReturnType())) {
out.print("result = ");
}
out.print(superVar + "." + javaMethod.getName() + "(");
Class>[] types = javaMethod.getParameterTypes();
for (int i = 0; i < types.length; i++) {
if (i != 0)
out.print(", ");
out.print(" a" + i);
}
out.println(");");
*/
/*
// ejb/12b0
if (! "super".equals(superVar))
generatePostCall(out);
*/
}
private boolean containsMethod(ArrayList methodList, Method method)
{
for (Method oldMethod : methodList) {
if (isMatch(oldMethod, method))
return true;
}
return false;
}
private void addInterceptorBindings(HashMap,Annotation> interceptorTypes,
Annotation ann)
{
Class> annType = ann.annotationType();
if (annType.isAnnotationPresent(InterceptorBinding.class)) {
interceptorTypes.put(ann.annotationType(), ann);
}
if (annType.isAnnotationPresent(Stereotype.class)) {
for (Annotation subAnn : annType.getAnnotations()) {
addInterceptorBindings(interceptorTypes, subAnn);
}
}
}
private boolean containsMethod(Method[] methodList, Method method)
{
for (Method oldMethod : methodList) {
if (isMatch(oldMethod, method))
return true;
}
return false;
}
private boolean isMostGeneralException(Class>[] exnList, Class> cl)
{
for (Class> exn : exnList) {
if (exn != cl && exn.isAssignableFrom(cl))
return false;
}
return true;
}
private Method findInterceptorMethod(Class> cl)
{
if (cl == null)
return null;
for (Method method : cl.getDeclaredMethods()) {
if (method.isAnnotationPresent(AroundInvoke.class))
return method;
}
return findInterceptorMethod(cl.getSuperclass());
}
private boolean isMatch(Method methodA, Method methodB)
{
if (! methodA.getName().equals(methodB.getName()))
return false;
Class>[] paramA = methodA.getParameterTypes();
Class>[] paramB = methodB.getParameterTypes();
if (paramA.length != paramB.length)
return false;
for (int i = 0; i < paramA.length; i++) {
if (! paramA[i].equals(paramB[i]))
return false;
}
return true;
}
private void generateGetMethod(JavaWriter out,
String className,
String methodName,
Class>[] paramTypes)
throws IOException
{
if (false && _interceptionType == InterceptionType.POST_CONSTRUCT) {
out.printClass(CandiUtil.class);
out.print(".findAccessible(");
out.print(_factory.getGeneratedClassName());
out.print(".class, \"__caucho_postConstruct_" + methodName + "\");");
}
else {
out.printClass(CandiUtil.class);
out.print(".findAccessibleMethod(");
out.print(className);
out.print(".class, \"" + methodName + "\"");
for (Class> type : paramTypes) {
out.print(", ");
out.printClass(type);
out.print(".class");
}
out.print(")");
}
}
protected void printCastClass(JavaWriter out, Type type)
throws IOException
{
if (boolean.class.equals(type))
out.print("Boolean");
else if (char.class.equals(type))
out.print("Character");
else if (byte.class.equals(type))
out.print("Byte");
else if (short.class.equals(type))
out.print("Short");
else if (int.class.equals(type))
out.print("Integer");
else if (long.class.equals(type))
out.print("Long");
else if (float.class.equals(type))
out.print("Float");
else if (double.class.equals(type))
out.print("Double");
else
out.printType(type);
}
public static void nullMethod()
{
}
static class InterceptionBinding {
private final InterceptionType _type;
private final ArrayList _binding;
private final ArrayList> _interceptors;
public InterceptionBinding(InterceptionType type,
ArrayList binding,
ArrayList> interceptors)
{
_type = type;
_binding = binding;
_interceptors = interceptors;
}
@Override
public int hashCode()
{
int hashCode = _type.hashCode() * 65521;
if (_binding != null)
hashCode += _binding.hashCode();
if (_interceptors != null)
hashCode += _interceptors.hashCode();
return hashCode;
}
@Override
public boolean equals(Object o)
{
if (o == this)
return true;
else if (! (o instanceof InterceptionBinding))
return false;
InterceptionBinding binding = (InterceptionBinding) o;
if (! _type.equals(binding._type))
return false;
if (_binding == binding._binding) {
}
else if (_binding == null || ! _binding.equals(binding._binding))
return false;
if (_interceptors == binding._interceptors) {
}
else if (_interceptors == null
|| ! _interceptors.equals(binding._interceptors))
return false;
return true;
}
}
static {
Method nullMethod = null;
try {
nullMethod = InterceptorGenerator.class.getMethod("nullMethod");
} catch (Exception e) {
e.printStackTrace();
log.log(Level.WARNING, e.toString(), e);
}
_nullMethod = nullMethod;
}
}