001 // Copyright 2008, 2009, 2010, 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.ioc.internal.services;
016
017 import java.lang.reflect.Method;
018 import java.util.Arrays;
019 import java.util.Set;
020
021 import org.apache.tapestry5.ioc.AnnotationAccess;
022 import org.apache.tapestry5.ioc.AnnotationProvider;
023 import org.apache.tapestry5.ioc.MethodAdvice;
024 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
025 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
026 import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
027 import org.apache.tapestry5.plastic.PlasticClass;
028 import org.apache.tapestry5.plastic.PlasticClassTransformation;
029 import org.apache.tapestry5.plastic.PlasticField;
030
031 @SuppressWarnings("all")
032 public class AspectInterceptorBuilderImpl<T> extends AbtractAspectInterceptorBuilder<T>
033 {
034 private final Class<T> serviceInterface;
035
036 private final Set<Method> allMethods = CollectionFactory.newSet();
037
038 private final PlasticClassTransformation transformation;
039
040 private final PlasticClass plasticClass;
041
042 public AspectInterceptorBuilderImpl(AnnotationAccess annotationAccess, PlasticProxyFactory plasticProxyFactory,
043 Class<T> serviceInterface, T delegate, String description)
044 {
045 super(annotationAccess);
046
047 this.serviceInterface = serviceInterface;
048
049 transformation = plasticProxyFactory.createProxyTransformation(serviceInterface);
050 plasticClass = transformation.getPlasticClass();
051
052 plasticClass.addToString(description);
053
054 allMethods.addAll(Arrays.asList(serviceInterface.getMethods()));
055
056 PlasticField delegateField = plasticClass.introduceField(serviceInterface, "delegate").inject(delegate);
057
058 for (Method method : allMethods)
059 {
060 plasticClass.introduceMethod(method).delegateTo(delegateField);
061 }
062 }
063
064 public void adviseMethod(Method method, MethodAdvice advice)
065 {
066 assert method != null;
067 assert advice != null;
068
069 AnnotationProvider methodAnnotationProvider = getMethodAnnotationProvider(method.getName(),
070 method.getParameterTypes());
071
072 adviseMethod(method, InternalUtils.toPlasticMethodAdvice(advice, methodAnnotationProvider));
073 }
074
075 public void adviseAllMethods(MethodAdvice advice)
076 {
077 for (Method m : serviceInterface.getMethods())
078 adviseMethod(m, advice);
079 }
080
081 public void adviseMethod(Method method, org.apache.tapestry5.plastic.MethodAdvice advice)
082 {
083 assert method != null;
084 assert advice != null;
085
086 if (!allMethods.contains(method))
087 throw new IllegalArgumentException(String.format("Method %s is not defined for interface %s.", method,
088 serviceInterface));
089
090 plasticClass.introduceMethod(method).addAdvice(advice);
091 }
092
093 public void adviseAllMethods(org.apache.tapestry5.plastic.MethodAdvice advice)
094 {
095 for (Method m : serviceInterface.getMethods())
096 {
097 adviseMethod(m, advice);
098 }
099 }
100
101 public Class getInterface()
102 {
103 return serviceInterface;
104 }
105
106 public T build()
107 {
108 return (T) transformation.createInstantiator().newInstance();
109 }
110 }