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