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    }