2
* JBoss, Home of Professional Open Source
3
* Copyright 2005, JBoss Inc., and individual contributors as indicated
4
* by the @authors tag. See the copyright.txt in the distribution for a
5
* full listing of individual contributors.
7
* This is free software; you can redistribute it and/or modify it
8
* under the terms of the GNU Lesser General Public License as
9
* published by the Free Software Foundation; either version 2.1 of
10
* the License, or (at your option) any later version.
12
* This software is distributed in the hope that it will be useful,
13
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
* Lesser General Public License for more details.
17
* You should have received a copy of the GNU Lesser General Public
18
* License along with this software; if not, write to the Free
19
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
23
package org.jboss.remoting.transporter;
25
import org.jboss.logging.Logger;
26
import org.jboss.remoting.CannotConnectException;
27
import org.jboss.remoting.Client;
28
import org.jboss.remoting.InvokerLocator;
29
import org.jboss.remoting.detection.ServerInvokerMetadata;
30
import org.jboss.remoting.detection.multicast.MulticastDetector;
31
import org.jboss.remoting.invocation.NameBasedInvocation;
32
import org.jboss.remoting.network.NetworkInstance;
33
import org.jboss.remoting.network.NetworkRegistry;
34
import org.jboss.remoting.util.SecurityUtility;
36
import javax.management.MBeanServer;
37
import javax.management.MBeanServerFactory;
39
import java.io.Serializable;
40
import java.lang.reflect.InvocationHandler;
41
import java.lang.reflect.InvocationTargetException;
42
import java.lang.reflect.Method;
43
import java.lang.reflect.Proxy;
44
import java.security.AccessController;
45
import java.security.PrivilegedAction;
46
import java.security.PrivilegedActionException;
47
import java.security.PrivilegedExceptionAction;
48
import java.util.ArrayList;
51
* Class to be used as a factory via static method calls to get
52
* remote proxy to POJO that exists within a external process.
53
* Note, if using clustered, will use the multicast detector by default.
55
* @author <a href="mailto:tom.elrod@jboss.com">Tom Elrod</a>
57
public class TransporterClient implements InvocationHandler, Serializable
59
private Client remotingClient = null;
60
private boolean isClustered = false;
61
private String subSystem = null;
63
private LoadBalancer loadBalancer = new DefaultLoadBalancer();
65
private final Logger log = Logger.getLogger(TransporterClient.class);
66
private static final long serialVersionUID = 7418567482011657189L;
69
* Creates the remoting client to server POJO.
75
private TransporterClient(InvokerLocator locator) throws Exception
77
remotingClient = new Client(locator);
78
remotingClient.connect();
82
* Creates the remoting client to server POJO.
86
* @param targetSubsystem
89
private TransporterClient(InvokerLocator locator, String targetSubsystem) throws Exception
91
remotingClient = new Client(locator, targetSubsystem);
92
remotingClient.connect();
93
this.isClustered = true;
94
this.subSystem = targetSubsystem;
98
* Creates the remoting client to server POJO.
102
* @param targetSubsystem
103
* @param loadbalancer policy
106
private TransporterClient(InvokerLocator locator, String targetSubsystem, LoadBalancer loadbalancer) throws Exception
108
this.loadBalancer = loadbalancer;
109
remotingClient = new Client(locator, targetSubsystem);
110
remotingClient.connect();
111
this.isClustered = true;
112
this.subSystem = targetSubsystem;
116
* Disconnects the remoting client
118
private void disconnect()
120
if (remotingClient != null)
122
remotingClient.disconnect();
127
* Will set up network registry and detector for clustering (to identify other
128
* remoting servers running on network).
132
private static void setupDetector() throws Exception
134
InternalTransporterServices services = InternalTransporterServices.getInstance();
136
// if no one has setup our internal services yet, let's do it now
137
if (!services.isSetup())
139
// we need an MBeanServer to store our network registry and multicast detector services
140
MBeanServer server = createMBeanServer();
142
// multicast detector will detect new network registries that come online
143
MulticastDetector detector = new MulticastDetector();
144
NetworkRegistry registry = NetworkRegistry.getInstance();
145
services.setup(server, detector, null, registry, null, true, true);
150
// the internal services singleton is already setup, but make sure it has the services we need
151
if (services.getDetector() == null)
153
MulticastDetector detector = new MulticastDetector();
154
services.assignDetector(detector, null, true);
158
if (services.getNetworkRegistry() == null)
160
NetworkRegistry registry = NetworkRegistry.getInstance();
161
services.assignNetworkRegistry(registry, null, true);
169
* Create a remote proxy to a POJO on a remote server.
171
* @param locatorURI - the remoting locator uri to the target server where the target POJO exists.
172
* @param targetClass - the interface class of the POJO will be calling upon.
173
* @param clustered - true will cause the transporter to look for other remoting serves that have the POJO running
174
* and include it in the client's target list. If a call on first target fails, will seamlessly fail over to one
175
* of the other discovered targets.
176
* @return dynamic remote proxy typed to the interface specified by the targetClass param.
179
public static Object createTransporterClient(String locatorURI, Class targetClass, boolean clustered) throws Exception
183
return createTransporterClient(locatorURI, targetClass);
187
if (InternalTransporterServices.getInstance().getNetworkRegistry() == null)
191
InvokerLocator locator = new InvokerLocator(locatorURI);
192
TransporterClient client = new TransporterClient(locator, targetClass.getName());
193
ClassLoader tcl = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
197
return Thread.currentThread().getContextClassLoader();
200
return Proxy.newProxyInstance(tcl, new Class[]{targetClass}, client);
205
* Create a remote proxy to a POJO on a remote server.
207
* @param locatorURI - the remoting locator uri to the target server where the target POJO exists.
208
* @param targetClass - the interface class of the POJO will be calling upon.
209
* @param loadBalancer - policy for selecting which target server to use from list of available servers.
210
* @return dynamic remote proxy typed to the interface specified by the targetClass param.
213
public static Object createTransporterClient(String locatorURI, Class targetClass, LoadBalancer loadBalancer) throws Exception
215
if (InternalTransporterServices.getInstance().getNetworkRegistry() == null)
219
InvokerLocator locator = new InvokerLocator(locatorURI);
220
TransporterClient client = new TransporterClient(locator, targetClass.getName(), loadBalancer);
221
ClassLoader tcl = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
225
return Thread.currentThread().getContextClassLoader();
228
return Proxy.newProxyInstance(tcl, new Class[]{targetClass}, client);
232
* Create a remote proxy to a POJO on a remote server.
234
* @param locatorURI - the remoting locator uri to the target server where the target POJO exists.
235
* @param targetClass - the interface class of the POJO will be calling upon.
236
* @return dynamic remote proxy typed to the interface specified by the targetClass param.
239
public static Object createTransporterClient(String locatorURI, Class targetClass) throws Exception
241
InvokerLocator locator = new InvokerLocator(locatorURI);
242
return createTransporterClient(locator, targetClass);
246
* Create a remote proxy to a POJO on a remote server.
248
* @param locator - the remoting locator to the target server where the target POJO exists.
249
* @param targetClass - the interface class of the POJO will be calling upon.
250
* @return dynamic remote proxy typed to the interface specified by the targetClass param.
253
public static Object createTransporterClient(InvokerLocator locator, Class targetClass) throws Exception
255
TransporterClient client = new TransporterClient(locator, targetClass.getName());
256
ClassLoader tcl = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
260
return Thread.currentThread().getContextClassLoader();
263
return Proxy.newProxyInstance(tcl, new Class[]{targetClass}, client);
267
* Needs to be called by user when no longer need to make calls on remote POJO. Otherwise will
268
* maintain remote connection until this is called.
270
* @param transporterClient
272
public static void destroyTransporterClient(Object transporterClient)
274
if (transporterClient instanceof Proxy)
276
InvocationHandler handler = Proxy.getInvocationHandler(transporterClient);
277
if (handler instanceof TransporterClient)
279
TransporterClient client = (TransporterClient) handler;
284
throw new IllegalArgumentException("Object is not a transporter client.");
289
throw new IllegalArgumentException("Object is not a transporter client.");
294
* The method called when anyone calls on the dynamic proxy returned by getProcessor().
295
* This method will simply convert the proxy call info into a remoting invocation on the
296
* target remoting server (using a NameBaseInvocation).
304
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
306
String methodName = method.getName();
307
String[] paramSig = createParamSignature(method.getParameterTypes());
309
NameBasedInvocation request = new NameBasedInvocation(methodName,
312
Object response = null;
314
boolean failOver = false;
321
response = remotingClient.invoke(request);
323
catch (CannotConnectException cnc)
325
failOver = findAlternativeTarget();
331
catch (InvocationTargetException itex)
333
Throwable rootEx = itex.getCause();
343
* Will check to see if the network registry has found any other remoting servers. Then will check
344
* to see if any of them contain the subsystem we are interested in (which will corespond to the proxy type we
345
* are using). If one is found, will try to create a remoting client and connect to it.
346
* If can't find one, will return fasle.
350
private boolean findAlternativeTarget()
352
boolean failover = false;
353
ArrayList availableList = new ArrayList();
354
NetworkRegistry registry = InternalTransporterServices.getInstance().getNetworkRegistry();
355
if (registry != null)
357
NetworkInstance[] instances = registry.getServers();
358
if (instances != null)
360
for (int x = 0; x < instances.length; x++)
362
NetworkInstance netInstance = instances[x];
363
ServerInvokerMetadata[] metadata = netInstance.getServerInvokers();
364
for (int i = 0; i < metadata.length; i++)
366
ServerInvokerMetadata data = metadata[i];
367
String[] subsystems = data.getSubSystems();
368
for (int z = 0; z < subsystems.length; z++)
370
if (subSystem.equalsIgnoreCase(subsystems[z]))
372
availableList.add(data);
378
//If alternative servers are found
379
if (availableList.size() > 0)
381
int index = loadBalancer.selectServer(availableList);
382
if (log.isDebugEnabled())
384
log.debug("Total of " + availableList.size() + " available servers found.");
385
log.debug("Using server number " + index);
387
//reconnect to the new server
388
ServerInvokerMetadata data = (ServerInvokerMetadata) availableList.get(index);
389
InvokerLocator newLocator = data.getInvokerLocator();
391
if (!remotingClient.getInvoker().getLocator().equals(newLocator))
395
remotingClient = new Client(newLocator);
396
remotingClient.connect();
401
log.warn("Problem connecting to newly found alternate target.", e);
413
* Converts the Class array supplied via the dynamic proxy to
414
* a String array of the respective class names, which is need by
415
* the NameBasedInvocation object.
420
private String[] createParamSignature(Class[] args)
422
if (args == null || args.length == 0)
424
return new String[]{};
426
String[] paramSig = new String[args.length];
427
for (int x = 0; x < args.length; x++)
429
paramSig[x] = args[x].getName();
434
static private MBeanServer createMBeanServer() throws Exception
436
if (SecurityUtility.skipAccessControl())
438
return MBeanServerFactory.createMBeanServer();
443
return (MBeanServer) AccessController.doPrivileged( new PrivilegedExceptionAction()
445
public Object run() throws Exception
447
return MBeanServerFactory.createMBeanServer();
451
catch (PrivilegedActionException e)
453
throw (Exception) e.getCause();
b'\\ No newline at end of file'