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    
019    import org.apache.tapestry5.ioc.AnnotationAccess;
020    import org.apache.tapestry5.ioc.MethodAdvice;
021    import org.apache.tapestry5.ioc.annotations.PreventServiceDecoration;
022    import org.apache.tapestry5.ioc.internal.AnnotationAccessImpl;
023    import org.apache.tapestry5.ioc.internal.util.InternalUtils;
024    import org.apache.tapestry5.ioc.services.AspectDecorator;
025    import org.apache.tapestry5.ioc.services.AspectInterceptorBuilder;
026    import org.apache.tapestry5.ioc.services.Builtin;
027    import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
028    
029    @PreventServiceDecoration
030    public class AspectDecoratorImpl implements AspectDecorator
031    {
032        private final PlasticProxyFactory proxyFactory;
033    
034        public AspectDecoratorImpl(@Builtin
035        PlasticProxyFactory proxyFactory)
036        {
037            this.proxyFactory = proxyFactory;
038        }
039    
040        public <T> T build(Class<T> serviceInterface, T delegate, MethodAdvice advice, String description)
041        {
042            assert advice != null;
043            AspectInterceptorBuilder<T> builder = createBuilder(serviceInterface, delegate, description);
044    
045            builder.adviseAllMethods(advice);
046    
047            return builder.build();
048        }
049    
050        public <T> AspectInterceptorBuilder<T> createBuilder(Class<T> serviceInterface, final T delegate, String description)
051        {
052            return createBuilder(serviceInterface, delegate, new AnnotationAccessImpl(serviceInterface), description);
053        }
054    
055        public <T> AspectInterceptorBuilder<T> createBuilder(final Class<T> serviceInterface, final T delegate,
056                AnnotationAccess annotationAccess, final String description)
057        {
058            assert serviceInterface != null;
059            assert delegate != null;
060            assert InternalUtils.isNonBlank(description);
061    
062            // The inner class here prevents the needless creation of the AspectInterceptorBuilderImpl,
063            // and the various Plastic related overhead, until there's some actual advice.
064    
065            return new AbtractAspectInterceptorBuilder<T>(annotationAccess)
066            {
067                private AspectInterceptorBuilder<T> builder;
068    
069                public void adviseMethod(Method method, MethodAdvice advice)
070                {
071                    getBuilder().adviseMethod(method, advice);
072                }
073    
074                public void adviseAllMethods(MethodAdvice advice)
075                {
076                    getBuilder().adviseAllMethods(advice);
077                }
078    
079                public void adviseMethod(Method method, org.apache.tapestry5.plastic.MethodAdvice advice)
080                {
081                    getBuilder().adviseMethod(method, advice);
082                }
083    
084                public void adviseAllMethods(org.apache.tapestry5.plastic.MethodAdvice advice)
085                {
086                    getBuilder().adviseAllMethods(advice);
087                }
088    
089                public Class getInterface()
090                {
091                    return serviceInterface;
092                }
093    
094                public T build()
095                {
096                    return builder == null ? delegate : builder.build();
097                }
098    
099                private AspectInterceptorBuilder<T> getBuilder()
100                {
101                    if (builder == null)
102                        builder = new AspectInterceptorBuilderImpl<T>(annotationAccess, proxyFactory, serviceInterface,
103                                delegate, description);
104    
105                    return builder;
106                }
107            };
108        }
109    }