001    package org.apache.fulcrum.yaafi.framework.interceptor;
002    
003    /*
004     * Licensed to the Apache Software Foundation (ASF) under one
005     * or more contributor license agreements.  See the NOTICE file
006     * distributed with this work for additional information
007     * regarding copyright ownership.  The ASF licenses this file
008     * to you under the Apache License, Version 2.0 (the
009     * "License"); you may not use this file except in compliance
010     * with the License.  You may obtain a copy of the License at
011     *
012     *   http://www.apache.org/licenses/LICENSE-2.0
013     *
014     * Unless required by applicable law or agreed to in writing,
015     * software distributed under the License is distributed on an
016     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017     * KIND, either express or implied.  See the License for the
018     * specific language governing permissions and limitations
019     * under the License.
020     */
021    
022    import java.lang.reflect.InvocationHandler;
023    import java.lang.reflect.Proxy;
024    import java.util.List;
025    
026    import org.apache.avalon.framework.service.ServiceException;
027    import org.apache.avalon.framework.service.ServiceManager;
028    import org.apache.fulcrum.yaafi.framework.constant.AvalonYaafiConstants;
029    import org.apache.fulcrum.yaafi.framework.reflection.Clazz;
030    import org.apache.fulcrum.yaafi.framework.util.Validate;
031    
032    
033    /**
034     * A factory for creating dynamic proxies for Avalon services.
035     *
036     * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
037     */
038    
039    public class AvalonInterceptorFactory
040    {
041        /**
042         * Creates a dynamic proxy wrapping a service instance.
043         *
044         * @param serviceName the name of the service
045         * @param serviceShorthand the shorthand of the service being intercepted
046         * @param serviceManager the corresponding service manager
047         * @param serviceInterceptorList the list of interceptors to be installed
048         * @param serviceDelegate the service implementation
049         * @return a dynamic proxy
050         * @throws ServiceException an interceptor was not found
051         */
052        public static Object create(
053            String serviceName,
054            String serviceShorthand,
055            ServiceManager serviceManager,
056            String[] serviceInterceptorList,
057            Object serviceDelegate )
058            throws ServiceException
059        {
060            Validate.notEmpty(serviceName,"serviceName");
061            Validate.notEmpty(serviceShorthand,"serviceShorthand");
062            Validate.notNull(serviceManager,"serviceManager");
063            Validate.notNull(serviceInterceptorList,"serviceInterceptorList");
064            Validate.notNull(serviceDelegate,"serviceDelegate");
065    
066            Object result = null;
067    
068            Class clazz = serviceDelegate.getClass();
069            ClassLoader classLoader = clazz.getClassLoader();
070            List interfaceList = Clazz.getAllInterfaces(clazz);
071    
072            // get the service interfaces to avoid lookups
073    
074            AvalonInterceptorService[] avalonInterceptorServices = resolve(
075                serviceManager,
076                serviceInterceptorList
077                );
078    
079            InvocationHandler invocationHandler = new AvalonInterceptorInvocationHandler(
080                serviceName,
081                serviceShorthand,
082                serviceDelegate,
083                avalonInterceptorServices
084                );
085    
086            result = Proxy.newProxyInstance(
087                classLoader,
088                (Class[]) interfaceList.toArray(new Class[interfaceList.size()]),
089                invocationHandler
090                );
091    
092            return result;
093        }
094    
095        /**
096         * Resolve all interceptor service names to service interfaces.
097         *
098         * @param serviceManager to lookup the services
099         * @param interceptorList the list of service names
100         * @return a list of interceptor services
101         * @throws ServiceException an interceptor service was not found
102         */
103        private static AvalonInterceptorService[] resolve( ServiceManager serviceManager, String[] interceptorList )
104            throws ServiceException
105        {
106            String interceptorServiceName = null;
107            AvalonInterceptorService[] result = new AvalonInterceptorService[interceptorList.length];
108    
109            for( int i=0; i<interceptorList.length; i++ )
110            {
111                interceptorServiceName = interceptorList[i];
112                Object currService = serviceManager.lookup(interceptorServiceName);
113    
114                if (currService instanceof AvalonInterceptorService)
115                {
116                    result[i] = (AvalonInterceptorService) currService;
117                }
118                else
119                {
120                    String msg = "The following service is not an AvalonInterceptorService : " + interceptorServiceName;
121                    throw new ServiceException(AvalonYaafiConstants.AVALON_CONTAINER_YAAFI,msg);
122                }
123            }
124    
125            return result;
126        }
127    }