001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.proxy;
023:
024: import java.lang.reflect.Proxy;
025: import java.util.ArrayList;
026: import java.util.Arrays;
027: import java.util.HashMap;
028: import javax.management.ObjectName;
029:
030: import org.jboss.invocation.InvocationContext;
031: import org.jboss.invocation.InvocationKey;
032: import org.jboss.invocation.Invoker;
033: import org.jboss.system.Registry;
034: import org.jboss.util.NestedRuntimeException;
035:
036: /** A generic factory of java.lang.reflect.Proxy that constructs a proxy
037: * that is a composite of ClientContainer/Interceptors/Invoker
038: *
039: * @todo generalize the proxy/invoker factory object
040: * @author Scott.Stark@jboss.org
041: * @version $Revision: 57209 $
042: */
043: public class GenericProxyFactory {
044:
045: /** Create a composite proxy for the given interfaces, invoker.
046: @param id the cache id for the target object if any
047: @param targetName the name of the server side service
048: @param invoker the detached invoker stub to embed in the proxy
049: @param jndiName the JNDI name the proxy will be bound under if not null
050: @param proxyBindingName the invoker-proxy-binding name if not null
051: @param interceptorClasses the Class objects for the interceptors
052: @param loader the ClassLoader to associate the the Proxy
053: @param ifaces the Class objects for the interfaces the Proxy implements
054: */
055: public Object createProxy(Object id, ObjectName targetName,
056: Invoker invoker, String jndiName, String proxyBindingName,
057: ArrayList interceptorClasses, ClassLoader loader,
058: Class[] ifaces) {
059: return createProxy(id, targetName, invoker, jndiName,
060: proxyBindingName, interceptorClasses, loader, ifaces,
061: null);
062: }
063:
064: /** Create a composite proxy for the given interfaces, invoker.
065: @param id the cache id for the target object if any
066: @param targetName the name of the server side service
067: @param invokerName the name of the server side JMX invoker
068: @param jndiName the JNDI name the proxy will be bound under if not null
069: @param proxyBindingName the invoker-proxy-binding name if not null
070: @param interceptorClasses the Class objects for the interceptors
071: @param loader the ClassLoader to associate the the Proxy
072: @param ifaces the Class objects for the interfaces the Proxy implements
073: */
074: public Object createProxy(Object id, ObjectName targetName,
075: ObjectName invokerName, String jndiName,
076: String proxyBindingName, ArrayList interceptorClasses,
077: ClassLoader loader, Class[] ifaces) {
078: Invoker invoker = (Invoker) Registry.lookup(invokerName);
079: if (invoker == null)
080: throw new RuntimeException(
081: "Failed to find invoker for name: " + invokerName);
082: return createProxy(id, targetName, invoker, jndiName,
083: proxyBindingName, interceptorClasses, loader, ifaces,
084: null);
085: }
086:
087: /** Create a composite proxy for the given interfaces, invoker.
088: @param id the cache id for the target object if any
089: @param targetName the name of the server side service
090: @param invoker the detached invoker stub to embed in the proxy
091: @param jndiName the JNDI name the proxy will be bound under if not null
092: @param proxyBindingName the invoker-proxy-binding name if not null
093: @param interceptorClasses the Class objects for the interceptors
094: @param loader the ClassLoader to associate the the Proxy
095: @param ifaces the Class objects for the interfaces the Proxy implements
096: @param ctx any context to add the invocation context proxy
097: */
098: public Object createProxy(Object id, ObjectName targetName,
099: Invoker invoker, String jndiName, String proxyBindingName,
100: ArrayList interceptorClasses, ClassLoader loader,
101: Class[] ifaces, HashMap ctx) {
102: InvocationContext context;
103: if (ctx != null)
104: context = new InvocationContext(ctx);
105: else
106: context = new InvocationContext();
107: Integer nameHash = new Integer(targetName.hashCode());
108: context.setObjectName(nameHash);
109: context.setCacheId(id);
110: if (jndiName != null)
111: context.setValue(InvocationKey.JNDI_NAME, jndiName);
112:
113: if (invoker == null)
114: throw new RuntimeException("Null invoker given for name: "
115: + targetName);
116: context.setInvoker(invoker);
117: if (proxyBindingName != null)
118: context.setInvokerProxyBinding(proxyBindingName);
119:
120: // If the IClientContainer interceptor was specified, use the ClientContainerEx
121: boolean wantIClientAccess = false;
122: for (int n = 0; wantIClientAccess == false
123: && n < interceptorClasses.size(); n++) {
124: Class type = (Class) interceptorClasses.get(n);
125: wantIClientAccess = type
126: .isAssignableFrom(IClientContainer.class);
127: }
128: ClientContainer client;
129: if (wantIClientAccess) {
130: client = new ClientContainerEx(context);
131: } else {
132: client = new ClientContainer(context);
133: }
134:
135: try {
136: loadInterceptorChain(interceptorClasses, client);
137: } catch (Exception e) {
138: throw new NestedRuntimeException(
139: "Failed to load interceptor chain", e);
140: }
141:
142: ArrayList tmp = new ArrayList(Arrays.asList(ifaces));
143: Class[] ifaces2 = new Class[tmp.size()];
144: tmp.toArray(ifaces2);
145: return Proxy.newProxyInstance(
146: // Classloaders
147: loader,
148: // Interfaces
149: ifaces2,
150: // Client container as invocation handler
151: client);
152: }
153:
154: /** The loadInterceptorChain create instances of interceptor
155: * classes from the list of classes given by the chain array.
156: *
157: * @exception Exception if an error occurs
158: */
159: protected void loadInterceptorChain(ArrayList chain,
160: ClientContainer client) throws Exception {
161: Interceptor last = null;
162: for (int i = 0; i < chain.size(); i++) {
163: Class clazz = (Class) chain.get(i);
164: Interceptor interceptor = (Interceptor) clazz.newInstance();
165: if (last == null) {
166: last = interceptor;
167: client.setNext(interceptor);
168: } else {
169: last.setNext(interceptor);
170: last = interceptor;
171: }
172: }
173: }
174: }
|