~ubuntu-branches/ubuntu/raring/libjboss-remoting-java/raring

« back to all changes in this revision

Viewing changes to src/org/jboss/remoting/transporter/TransporterClient.java

  • Committer: Package Import Robot
  • Author(s): Torsten Werner
  • Date: 2011-09-09 14:01:03 UTC
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: package-import@ubuntu.com-20110909140103-o8ucrolqt5g25k57
Tags: upstream-2.5.3.SP1
ImportĀ upstreamĀ versionĀ 2.5.3.SP1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
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.
6
 
*
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.
11
 
*
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.
16
 
*
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.
21
 
*/
22
 
 
23
 
package org.jboss.remoting.transporter;
24
 
 
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;
35
 
 
36
 
import javax.management.MBeanServer;
37
 
import javax.management.MBeanServerFactory;
38
 
 
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;
49
 
 
50
 
/**
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.
54
 
 *
55
 
 * @author <a href="mailto:tom.elrod@jboss.com">Tom Elrod</a>
56
 
 */
57
 
public class TransporterClient implements InvocationHandler, Serializable
58
 
{
59
 
   private Client remotingClient = null;
60
 
   private boolean isClustered = false;
61
 
   private String subSystem = null;
62
 
 
63
 
   private LoadBalancer loadBalancer = new DefaultLoadBalancer();
64
 
 
65
 
   private final Logger log = Logger.getLogger(TransporterClient.class);
66
 
   private static final long serialVersionUID = 7418567482011657189L;
67
 
 
68
 
   /**
69
 
    * Creates the remoting client to server POJO.
70
 
    * Is not clustered.
71
 
    *
72
 
    * @param locator
73
 
    * @throws Exception
74
 
    */
75
 
   private TransporterClient(InvokerLocator locator) throws Exception
76
 
   {
77
 
      remotingClient = new Client(locator);
78
 
      remotingClient.connect();
79
 
   }
80
 
 
81
 
   /**
82
 
    * Creates the remoting client to server POJO.
83
 
    * Is clustered
84
 
    *
85
 
    * @param locator
86
 
    * @param targetSubsystem
87
 
    * @throws Exception
88
 
    */
89
 
   private TransporterClient(InvokerLocator locator, String targetSubsystem) throws Exception
90
 
   {
91
 
      remotingClient = new Client(locator, targetSubsystem);
92
 
      remotingClient.connect();
93
 
      this.isClustered = true;
94
 
      this.subSystem = targetSubsystem;
95
 
   }
96
 
 
97
 
   /**
98
 
    * Creates the remoting client to server POJO.
99
 
    * Is clustered
100
 
    *
101
 
    * @param locator
102
 
    * @param targetSubsystem
103
 
    * @param loadbalancer    policy
104
 
    * @throws Exception
105
 
    */
106
 
   private TransporterClient(InvokerLocator locator, String targetSubsystem, LoadBalancer loadbalancer) throws Exception
107
 
   {
108
 
      this.loadBalancer = loadbalancer;
109
 
      remotingClient = new Client(locator, targetSubsystem);
110
 
      remotingClient.connect();
111
 
      this.isClustered = true;
112
 
      this.subSystem = targetSubsystem;
113
 
   }
114
 
 
115
 
   /**
116
 
    * Disconnects the remoting client
117
 
    */
118
 
   private void disconnect()
119
 
   {
120
 
      if (remotingClient != null)
121
 
      {
122
 
         remotingClient.disconnect();
123
 
      }
124
 
   }
125
 
 
126
 
   /**
127
 
    * Will set up network registry and detector for clustering (to identify other
128
 
    * remoting servers running on network).
129
 
    *
130
 
    * @throws Exception
131
 
    */
132
 
   private static void setupDetector() throws Exception
133
 
   {
134
 
      InternalTransporterServices services = InternalTransporterServices.getInstance();
135
 
 
136
 
      // if no one has setup our internal services yet, let's do it now
137
 
      if (!services.isSetup())
138
 
      {
139
 
         // we need an MBeanServer to store our network registry and multicast detector services
140
 
         MBeanServer server = createMBeanServer();
141
 
 
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);
146
 
         detector.start();
147
 
      }
148
 
      else
149
 
      {
150
 
         // the internal services singleton is already setup, but make sure it has the services we need
151
 
         if (services.getDetector() == null)
152
 
         {
153
 
            MulticastDetector detector = new MulticastDetector();
154
 
            services.assignDetector(detector, null, true);
155
 
            detector.start();
156
 
         }
157
 
 
158
 
         if (services.getNetworkRegistry() == null)
159
 
         {
160
 
            NetworkRegistry registry = NetworkRegistry.getInstance();
161
 
            services.assignNetworkRegistry(registry, null, true);
162
 
         }
163
 
      }
164
 
 
165
 
      return;
166
 
   }
167
 
 
168
 
   /**
169
 
    * Create a remote proxy to a POJO on a remote server.
170
 
    *
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.
177
 
    * @throws Exception
178
 
    */
179
 
   public static Object createTransporterClient(String locatorURI, Class targetClass, boolean clustered) throws Exception
180
 
   {
181
 
      if (!clustered)
182
 
      {
183
 
         return createTransporterClient(locatorURI, targetClass);
184
 
      }
185
 
      else
186
 
      {
187
 
         if (InternalTransporterServices.getInstance().getNetworkRegistry() == null)
188
 
         {
189
 
            setupDetector();
190
 
         }
191
 
         InvokerLocator locator = new InvokerLocator(locatorURI);
192
 
         TransporterClient client = new TransporterClient(locator, targetClass.getName());
193
 
         ClassLoader tcl = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
194
 
         {
195
 
            public Object run()
196
 
            {
197
 
               return Thread.currentThread().getContextClassLoader();
198
 
            }
199
 
         });
200
 
         return Proxy.newProxyInstance(tcl, new Class[]{targetClass}, client);
201
 
      }
202
 
   }
203
 
 
204
 
   /**
205
 
    * Create a remote proxy to a POJO on a remote server.
206
 
    *
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.
211
 
    * @throws Exception
212
 
    */
213
 
   public static Object createTransporterClient(String locatorURI, Class targetClass, LoadBalancer loadBalancer) throws Exception
214
 
   {
215
 
         if (InternalTransporterServices.getInstance().getNetworkRegistry() == null)
216
 
         {
217
 
            setupDetector();
218
 
         }
219
 
         InvokerLocator locator = new InvokerLocator(locatorURI);
220
 
         TransporterClient client = new TransporterClient(locator, targetClass.getName(), loadBalancer);
221
 
         ClassLoader tcl = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
222
 
         {
223
 
            public Object run()
224
 
            {
225
 
               return Thread.currentThread().getContextClassLoader();
226
 
            }
227
 
         });
228
 
         return Proxy.newProxyInstance(tcl, new Class[]{targetClass}, client);
229
 
   }
230
 
 
231
 
   /**
232
 
    * Create a remote proxy to a POJO on a remote server.
233
 
    *
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.
237
 
    * @throws Exception
238
 
    */
239
 
   public static Object createTransporterClient(String locatorURI, Class targetClass) throws Exception
240
 
   {
241
 
      InvokerLocator locator = new InvokerLocator(locatorURI);
242
 
      return createTransporterClient(locator, targetClass);
243
 
   }
244
 
 
245
 
   /**
246
 
    * Create a remote proxy to a POJO on a remote server.
247
 
    *
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.
251
 
    * @throws Exception
252
 
    */
253
 
   public static Object createTransporterClient(InvokerLocator locator, Class targetClass) throws Exception
254
 
   {
255
 
      TransporterClient client = new TransporterClient(locator, targetClass.getName());
256
 
      ClassLoader tcl = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
257
 
      {
258
 
         public Object run()
259
 
         {
260
 
            return Thread.currentThread().getContextClassLoader();
261
 
         }
262
 
      });
263
 
      return Proxy.newProxyInstance(tcl, new Class[]{targetClass}, client);
264
 
   }
265
 
 
266
 
   /**
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.
269
 
    *
270
 
    * @param transporterClient
271
 
    */
272
 
   public static void destroyTransporterClient(Object transporterClient)
273
 
   {
274
 
      if (transporterClient instanceof Proxy)
275
 
      {
276
 
         InvocationHandler handler = Proxy.getInvocationHandler(transporterClient);
277
 
         if (handler instanceof TransporterClient)
278
 
         {
279
 
            TransporterClient client = (TransporterClient) handler;
280
 
            client.disconnect();
281
 
         }
282
 
         else
283
 
         {
284
 
            throw new IllegalArgumentException("Object is not a transporter client.");
285
 
         }
286
 
      }
287
 
      else
288
 
      {
289
 
         throw new IllegalArgumentException("Object is not a transporter client.");
290
 
      }
291
 
   }
292
 
 
293
 
   /**
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).
297
 
    *
298
 
    * @param proxy
299
 
    * @param method
300
 
    * @param args
301
 
    * @return
302
 
    * @throws Throwable
303
 
    */
304
 
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
305
 
   {
306
 
      String methodName = method.getName();
307
 
      String[] paramSig = createParamSignature(method.getParameterTypes());
308
 
 
309
 
      NameBasedInvocation request = new NameBasedInvocation(methodName,
310
 
                                                            args,
311
 
                                                            paramSig);
312
 
      Object response = null;
313
 
 
314
 
      boolean failOver = false;
315
 
 
316
 
      do
317
 
      {
318
 
         try
319
 
         {
320
 
            failOver = false;
321
 
            response = remotingClient.invoke(request);
322
 
         }
323
 
         catch (CannotConnectException cnc)
324
 
         {
325
 
            failOver = findAlternativeTarget();
326
 
            if (!failOver)
327
 
            {
328
 
               throw cnc;
329
 
            }
330
 
         }
331
 
         catch (InvocationTargetException itex)
332
 
         {
333
 
            Throwable rootEx = itex.getCause();
334
 
            throw rootEx;
335
 
         }
336
 
      }
337
 
      while (failOver);
338
 
 
339
 
      return response;
340
 
   }
341
 
 
342
 
   /**
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.
347
 
    *
348
 
    * @return
349
 
    */
350
 
   private boolean findAlternativeTarget()
351
 
   {
352
 
      boolean failover = false;
353
 
      ArrayList availableList = new ArrayList();
354
 
      NetworkRegistry registry = InternalTransporterServices.getInstance().getNetworkRegistry();
355
 
      if (registry != null)
356
 
      {
357
 
         NetworkInstance[] instances = registry.getServers();
358
 
         if (instances != null)
359
 
         {
360
 
            for (int x = 0; x < instances.length; x++)
361
 
            {
362
 
               NetworkInstance netInstance = instances[x];
363
 
               ServerInvokerMetadata[] metadata = netInstance.getServerInvokers();
364
 
               for (int i = 0; i < metadata.length; i++)
365
 
               {
366
 
                  ServerInvokerMetadata data = metadata[i];
367
 
                  String[] subsystems = data.getSubSystems();
368
 
                  for (int z = 0; z < subsystems.length; z++)
369
 
                  {
370
 
                     if (subSystem.equalsIgnoreCase(subsystems[z]))
371
 
                     {
372
 
                        availableList.add(data);
373
 
 
374
 
                     }
375
 
                  }
376
 
               }
377
 
            }
378
 
            //If alternative servers are found
379
 
            if (availableList.size() > 0)
380
 
            {
381
 
               int index = loadBalancer.selectServer(availableList);
382
 
               if (log.isDebugEnabled())
383
 
               {
384
 
                  log.debug("Total of " + availableList.size() + " available servers found.");
385
 
                  log.debug("Using server number " + index);
386
 
               }
387
 
               //reconnect to the new server
388
 
               ServerInvokerMetadata data = (ServerInvokerMetadata) availableList.get(index);
389
 
               InvokerLocator newLocator = data.getInvokerLocator();
390
 
 
391
 
               if (!remotingClient.getInvoker().getLocator().equals(newLocator))
392
 
               {
393
 
                  try
394
 
                  {
395
 
                     remotingClient = new Client(newLocator);
396
 
                     remotingClient.connect();
397
 
                     return true;
398
 
                  }
399
 
                  catch (Exception e)
400
 
                  {
401
 
                     log.warn("Problem connecting to newly found alternate target.", e);
402
 
                  }
403
 
               }
404
 
 
405
 
            }
406
 
         }
407
 
      }
408
 
      return failover;
409
 
 
410
 
   }
411
 
 
412
 
   /**
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.
416
 
    *
417
 
    * @param args
418
 
    * @return
419
 
    */
420
 
   private String[] createParamSignature(Class[] args)
421
 
   {
422
 
      if (args == null || args.length == 0)
423
 
      {
424
 
         return new String[]{};
425
 
      }
426
 
      String[] paramSig = new String[args.length];
427
 
      for (int x = 0; x < args.length; x++)
428
 
      {
429
 
         paramSig[x] = args[x].getName();
430
 
      }
431
 
      return paramSig;
432
 
   }
433
 
 
434
 
   static private MBeanServer createMBeanServer() throws Exception
435
 
   {
436
 
      if (SecurityUtility.skipAccessControl())
437
 
      {
438
 
         return MBeanServerFactory.createMBeanServer();
439
 
      }
440
 
      
441
 
      try
442
 
      {
443
 
         return (MBeanServer) AccessController.doPrivileged( new PrivilegedExceptionAction()
444
 
         {
445
 
            public Object run() throws Exception
446
 
            {
447
 
               return MBeanServerFactory.createMBeanServer();
448
 
            }
449
 
         });
450
 
      }
451
 
      catch (PrivilegedActionException e)
452
 
      {
453
 
         throw (Exception) e.getCause();
454
 
      }   
455
 
   }
456
 
}
 
 
b'\\ No newline at end of file'