001    package org.apache.ojb.broker.core.proxy;
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    
019    import java.lang.reflect.Constructor;
020    import java.lang.reflect.InvocationHandler;
021    import java.lang.reflect.Proxy;
022    import java.util.HashMap;
023    
024    
025    
026    /**
027     * @author andrew.clute
028     *
029     */
030    public class ProxyFactoryJDKImpl extends AbstractProxyFactory {
031    
032        /**
033         * JMM: Cache information about the interfaces need for dynamic proxy.
034         */
035        private HashMap foundInterfaces = new HashMap();
036        
037        
038        public Class getDefaultIndirectionHandlerClass()
039        {
040            return IndirectionHandlerJDKImpl.class;
041        }
042        
043        
044        /**
045         * Returns the class of the base class that the given IndirectionHandler must extend/implement
046         * 
047         */
048        public Class getIndirectionHandlerBaseClass()
049        {
050            return IndirectionHandlerJDK.class;
051        }
052            
053        
054    
055        public OJBProxy createProxy(Class baseClass, IndirectionHandler handler) throws Exception {
056            Class proxyClass = getDynamicProxyClass(baseClass);
057            Constructor constructor = proxyClass.getDeclaredConstructor(new Class[] { InvocationHandler.class });
058            return (OJBProxy)constructor.newInstance(new Object[] { handler });
059        }
060    
061        public IndirectionHandler getDynamicIndirectionHandler(Object obj) {
062            return (IndirectionHandler)Proxy.getInvocationHandler(obj);
063        }        
064    
065        public boolean isNormalOjbProxy(Object proxyOrObject) {
066            return super.isNormalOjbProxy(proxyOrObject) && (proxyOrObject instanceof Proxy) && Proxy.isProxyClass(proxyOrObject.getClass());
067        }
068    
069        /**
070         * returns a dynamic Proxy that implements all interfaces of the
071         * class described by this ClassDescriptor.
072         *
073         * @return Class the dynamically created proxy class
074         */
075        private Class getDynamicProxyClass(Class baseClass) {
076            Class[] m_dynamicProxyClassInterfaces;
077            if (foundInterfaces.containsKey(baseClass)) {
078                m_dynamicProxyClassInterfaces = (Class[])foundInterfaces.get(baseClass);
079            } else {
080                m_dynamicProxyClassInterfaces = getInterfaces(baseClass);
081                foundInterfaces.put(baseClass, m_dynamicProxyClassInterfaces);
082            }
083    
084            // return dynymic Proxy Class implementing all interfaces
085            Class proxyClazz = Proxy.getProxyClass(baseClass.getClassLoader(), m_dynamicProxyClassInterfaces);
086            return proxyClazz;
087        }
088    
089        /**
090         * Get interfaces implemented by clazz
091         *
092         * @param clazz
093         * @return
094         */
095        private Class[] getInterfaces(Class clazz) {
096            Class superClazz = clazz;
097            Class[] interfaces = clazz.getInterfaces();
098    
099            // clazz can be an interface itself and when getInterfaces()
100            // is called on an interface it returns only the extending
101            // interfaces, not the interface itself.
102            if (clazz.isInterface()) {
103                Class[] tempInterfaces = new Class[interfaces.length + 1];
104                tempInterfaces[0] = clazz;
105    
106                System.arraycopy(interfaces, 0, tempInterfaces, 1, interfaces.length);
107                interfaces = tempInterfaces;
108            }
109    
110            // add all interfaces implemented by superclasses to the interfaces array
111            while ((superClazz = superClazz.getSuperclass()) != null) {
112                Class[] superInterfaces = superClazz.getInterfaces();
113                Class[] combInterfaces = new Class[interfaces.length + superInterfaces.length];
114                System.arraycopy(interfaces, 0, combInterfaces, 0, interfaces.length);
115                System.arraycopy(superInterfaces, 0, combInterfaces, interfaces.length, superInterfaces.length);
116                interfaces = combInterfaces;
117            }
118    
119            /**
120             * Must remove duplicate interfaces before calling Proxy.getProxyClass().
121             * Duplicates can occur if a subclass re-declares that it implements
122             * the same interface as one of its ancestor classes.
123             **/
124            HashMap unique = new HashMap();
125            for (int i = 0; i < interfaces.length; i++) {
126                unique.put(interfaces[i].getName(), interfaces[i]);
127            }
128            /* Add the OJBProxy interface as well */
129            unique.put(OJBProxy.class.getName(), OJBProxy.class);
130    
131            interfaces = (Class[])unique.values().toArray(new Class[unique.size()]);
132    
133            return interfaces;
134        }
135        
136        public boolean interfaceRequiredForProxyGeneration() {
137            return true;
138        }
139    
140    }