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 }