001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.util;
024:
025: import java.lang.reflect.InvocationHandler;
026: import java.lang.reflect.Method;
027: import java.lang.reflect.Proxy;
028:
029: /**
030: * Creates a proxy which combines several classes and sequentially searches for
031: * matching method to invoke. This allows to implement lazy instantiation for
032: * situations where you have part of object data in cheaply accessible storage (cache or DB)
033: * and the other part in expensively accessible storage (e.g. XML file shall be
034: * parsed to access all object data).
035: * @author Pavel Vlasov
036: * @version $Revision: 1.1 $
037: */
038: public class CompositeProxyFactory {
039:
040: /**
041: * @author Pavel Vlasov
042: * @version $Revision: 1.1 $
043: */
044: public interface TargetFactory {
045:
046: /**
047: * @return target class for the proxy to know which methods it implements.
048: * You might want to return only one of class interfaces or base classes
049: * to limit number of exposed methods.
050: */
051: Class getTargetClass();
052:
053: /**
054: * @return target itself to perform invocation.
055: */
056: Object getTarget();
057: }
058:
059: private ClassLoader classLoader;
060:
061: /**
062: * Creates factory which uses default classloader.
063: */
064: public CompositeProxyFactory() {
065: super ();
066: classLoader = getClass().getClassLoader();
067: }
068:
069: /**
070: * Creates factory whith specified classloader which will be
071: * passed to createProxy(ClassLoader, Class[], TargetFactory[])
072: */
073: public CompositeProxyFactory(ClassLoader classLoader) {
074: super ();
075: this .classLoader = classLoader;
076: }
077:
078: public static Object createProxy(ClassLoader classLoader,
079: Class[] interfaces, final TargetFactory[] targetFactories) {
080: return Proxy.newProxyInstance(classLoader, interfaces,
081: new InvocationHandler() {
082: public Object invoke(Object proxy, Method method,
083: Object[] args) throws Throwable {
084: for (int i = 0; i < targetFactories.length; i++) {
085: try {
086: return targetFactories[i]
087: .getTargetClass()
088: .getMethod(
089: method.getName(),
090: method
091: .getParameterTypes())
092: .invoke(
093: targetFactories[i]
094: .getTarget(),
095: args);
096: } catch (NoSuchMethodException e) {
097: // Ignore it.
098: }
099: }
100:
101: throw new NoSuchMethodException(
102: "Method not found in targets: "
103: + method);
104: }
105: });
106:
107: }
108:
109: public Object createProxy(Class[] interfaces,
110: TargetFactory[] targetFactories) {
111: return createProxy(classLoader, interfaces, targetFactories);
112: }
113: }
|