001    package org.apache.ojb.broker.util.interceptor;
002    
003    /* Copyright 2002-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    //#ifdef JDK13
019    import java.lang.reflect.Proxy;
020    import java.lang.reflect.InvocationHandler;
021    //#else
022    /*
023    import net.sf.cglib.proxy.Proxy;
024    import net.sf.cglib.proxy.InvocationHandler;
025    */
026    //#endif
027    
028    import java.util.HashMap;
029    
030    import org.apache.ojb.broker.util.configuration.Configurable;
031    import org.apache.ojb.broker.util.configuration.Configuration;
032    import org.apache.ojb.broker.util.configuration.ConfigurationException;
033    import org.apache.ojb.broker.util.configuration.impl.OjbConfigurator;
034    import org.apache.ojb.broker.util.logging.LoggerFactory;
035    import org.apache.ojb.broker.util.ClassHelper;
036    
037    /**
038     * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
039     * @version $Id: InterceptorFactory.java,v 1.1 2007-08-24 22:17:39 ewestfal Exp $
040     */
041    public class InterceptorFactory implements Configurable
042    {
043    
044            private static InterceptorFactory instance = null;
045    
046            private Class interceptorClassToBeUsed = null;
047    
048            /**
049             * Returns the instance.
050             * @return InterceptorFactory
051             */
052            public static InterceptorFactory getInstance()
053            {
054                    if (instance == null)
055                    {
056                            instance = new InterceptorFactory();
057                            OjbConfigurator.getInstance().configure(instance);
058                    }
059                    return instance;
060            }
061    
062    
063            /**
064             * @see org.apache.ojb.broker.util.configuration.Configurable#configure(Configuration)
065             */
066            public void configure(Configuration pConfig) throws ConfigurationException
067            {
068                    Class clazz = pConfig.getClass("InterceptorClass", Object.class);
069                    if(!clazz.equals(Object.class)) setInterceptorClassToBeUsed(clazz);
070            }
071    
072            public Object createInterceptorFor(Object instanceToIntercept)
073            {
074                    if (getInterceptorClassToBeUsed() != null)
075                    {
076                            try
077                            {
078    
079    
080    //                              Class[] parameterTypes = {Object.class};
081    //                              Object[] parameters = {instanceToIntercept};
082    //              Constructor constructor = getInterceptorClassToBeUsed().getConstructor(parameterTypes);
083    //                              InvocationHandler handler = (InvocationHandler) constructor.newInstance(parameters);
084                    // use helper class to instantiate
085                    InvocationHandler handler = (InvocationHandler) ClassHelper.newInstance(
086                                                getInterceptorClassToBeUsed(), Object.class, instanceToIntercept);
087                                    Class[] interfaces = computeInterfaceArrayFor(instanceToIntercept.getClass());
088                                    Object result =
089                                            Proxy.newProxyInstance(
090                                                    ClassHelper.getClassLoader(),
091                                                    interfaces,
092                                                    handler);
093                                    return result;
094                            }
095                            catch (Throwable t)
096                            {
097                                    LoggerFactory.getDefaultLogger().error("can't use Interceptor " + getInterceptorClassToBeUsed().getName() +
098                                            "for " + instanceToIntercept.getClass().getName(), t);
099                                    return instanceToIntercept;
100                            }
101                    }
102                    else
103                    {
104                            return instanceToIntercept;
105                    }
106            }
107    
108    
109    
110            public Class[] computeInterfaceArrayFor(Class clazz)
111            {
112                    Class superClass = clazz;
113                    Class[] interfaces = clazz.getInterfaces();
114    
115                    // clazz can be an interface itself and when getInterfaces()
116                    // is called on an interface it returns only the extending
117                    // interfaces, not the interface itself.
118                    if (clazz.isInterface())
119                    {
120                            Class[] tempInterfaces = new Class[interfaces.length + 1];
121                            tempInterfaces[0] = clazz;
122    
123                            System.arraycopy(interfaces, 0, tempInterfaces, 1, interfaces.length);
124                            interfaces = tempInterfaces;
125                    }
126    
127                    // add all interfaces implemented by superclasses to the interfaces array
128                    while ((superClass = superClass.getSuperclass()) != null)
129                    {
130                            Class[] superInterfaces = superClass.getInterfaces();
131                            Class[] combInterfaces = new Class[interfaces.length + superInterfaces.length];
132                            System.arraycopy(interfaces, 0, combInterfaces, 0, interfaces.length);
133                            System.arraycopy(
134                                    superInterfaces,
135                                    0,
136                                    combInterfaces,
137                                    interfaces.length,
138                                    superInterfaces.length);
139                            interfaces = combInterfaces;
140                    }
141    
142                    /**
143                     * Must remove duplicate interfaces before calling Proxy.getProxyClass().
144                     * Duplicates can occur if a subclass re-declares that it implements
145                     * the same interface as one of its ancestor classes.
146                    **/
147                    HashMap unique = new HashMap();
148                    for (int i = 0; i < interfaces.length; i++)
149                    {
150                            unique.put(interfaces[i].getName(), interfaces[i]);
151                    }
152                    interfaces = (Class[]) unique.values().toArray(new Class[unique.size()]);
153    
154                    return interfaces;
155            }
156    
157    
158    
159            /**
160             * Returns the interceptorClassToBeUsed.
161             * @return Class
162             */
163            public Class getInterceptorClassToBeUsed()
164            {
165                    return interceptorClassToBeUsed;
166            }
167    
168            /**
169             * Sets the interceptorClassToBeUsed.
170             * @param interceptorClassToBeUsed The interceptorClassToBeUsed to set
171             */
172            public void setInterceptorClassToBeUsed(Class interceptorClassToBeUsed)
173            {
174                    this.interceptorClassToBeUsed = interceptorClassToBeUsed;
175            }
176    
177    }