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

« back to all changes in this revision

Viewing changes to src/org/jboss/remoting/MicroRemoteClientInvoker.java

  • Committer: Package Import Robot
  • Author(s): Torsten Werner
  • Date: 2011-09-09 14:01:03 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: package-import@ubuntu.com-20110909140103-hqokx61534tas9rg
Tags: 2.5.3.SP1-1
* Newer but not newest upstream release. Do not build samples.
* Change debian/watch to upstream's svn repo.
* Add patch to fix compile error caused by tomcat update.
  (Closes: #628303)
* Switch to source format 3.0.
* Switch to debhelper level 7.
* Remove useless Depends.
* Update Standards-Version: 3.9.2.
* Update README.source.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package org.jboss.remoting;
2
 
 
3
 
import org.jboss.logging.Logger;
4
 
import org.jboss.remoting.loading.ClassByteClassLoader;
5
 
import org.jboss.remoting.loading.RemotingClassLoader;
6
 
import org.jboss.remoting.marshal.InvalidMarshallingResource;
7
 
import org.jboss.remoting.marshal.MarshalFactory;
8
 
import org.jboss.remoting.marshal.Marshaller;
9
 
import org.jboss.remoting.marshal.UnMarshaller;
10
 
import org.jboss.remoting.marshal.UpdateableClassloaderUnMarshaller;
11
 
import org.jboss.remoting.transport.ClientInvoker;
12
 
import org.jboss.remoting.util.SecurityUtility;
13
 
import org.jboss.util.id.GUID;
14
 
 
15
 
import java.io.IOException;
16
 
import java.security.AccessController;
17
 
import java.security.PrivilegedAction;
18
 
import java.security.PrivilegedActionException;
19
 
import java.security.PrivilegedExceptionAction;
20
 
import java.util.HashMap;
21
 
import java.util.List;
22
 
import java.util.Map;
23
 
import java.util.WeakHashMap;
24
 
 
25
 
/**
26
 
 * MicroRemoteClientInvoker is an abstract client part handler that implements the bulk of the heavy
27
 
 * lifting to process a remote method and dispatch it to a remote ServerInvoker and handle the result. <P>
28
 
 * <p/>
29
 
 * Specialized Client/Server Invokers might add additional functionality as part of the invocation - such as
30
 
 * delivering queued notifcations from a remote server by adding the notification objects during each invocation
31
 
 * to the invocation result payload and then having the client re-dispatch the notifications locally upon
32
 
 * receiving the return invocation result.
33
 
 *
34
 
 * The reason for the name micro is that this class contains only api that can be run within a J2ME envrionment.
35
 
 *
36
 
 * @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
37
 
 * @author <a href="mailto:telrod@e2technologies.net">Tom Elrod</a>
38
 
 * @version $Revision: 5265 $
39
 
 */
40
 
public abstract class MicroRemoteClientInvoker extends AbstractInvoker implements ClientInvoker
41
 
{
42
 
   private static final Logger log = Logger.getLogger(MicroRemoteClientInvoker.class);
43
 
   private boolean trace = log.isTraceEnabled();
44
 
 
45
 
   protected boolean connected = false;
46
 
   private Marshaller marshaller;
47
 
   private Map unmarshallers = new WeakHashMap();
48
 
   private String dataType;
49
 
   private final Object clientLeaseLock = new Object();
50
 
   private LeasePinger leasePinger = null;
51
 
   private String invokerSessionID = new GUID().toString();
52
 
   protected boolean parentFirstClassLoading = true;
53
 
   private boolean changeInvalidStateToCannotConnect = false;
54
 
   
55
 
   protected List connectHomes;
56
 
 
57
 
   public MicroRemoteClientInvoker(InvokerLocator locator)
58
 
   {
59
 
      super(locator);
60
 
      init();
61
 
   }
62
 
 
63
 
   public MicroRemoteClientInvoker(InvokerLocator locator, Map configuration)
64
 
   {
65
 
      super(locator, configuration);
66
 
      init();
67
 
   }
68
 
 
69
 
   /**
70
 
    * Transport a request against a remote ServerInvoker.
71
 
    */
72
 
   public Object invoke(InvocationRequest invocationReq) throws Throwable
73
 
   {
74
 
      Object returnValue = null;
75
 
      int invokeCount = 0;
76
 
 
77
 
      if (trace) { log.trace(this + "(" + (++invokeCount) + ") invoking " + invocationReq); }
78
 
 
79
 
      // Set up marshaller and unmarshaller.
80
 
      Marshaller marshaller = null;
81
 
      UnMarshaller unmarshaller = null;
82
 
      RemotingClassLoader rcl = null;
83
 
      synchronized (MicroRemoteClientInvoker.class)
84
 
      {
85
 
         marshaller = getMarshaller();
86
 
         if (marshaller == null)
87
 
         {
88
 
            // try by locator (in case marshaller class name specified)
89
 
            Map map = passConfigMapToMarshalFactory ? configuration : null;
90
 
            marshaller = MarshalFactory.getMarshaller(getLocator(), getClassLoader(), map);
91
 
            if (marshaller == null)
92
 
            {
93
 
               // need to have a marshaller, so create a default one
94
 
               marshaller = MarshalFactory.getMarshaller(getDataType(), getSerializationType());
95
 
               if (marshaller == null)
96
 
               {
97
 
                  // went as far as possible to find a marshaller, will have to give up
98
 
                  throw new InvalidMarshallingResource(
99
 
                        "Can not find a valid marshaller for data type: " + getDataType());
100
 
               }
101
 
            }
102
 
            setMarshaller(marshaller);
103
 
         }
104
 
         
105
 
         unmarshaller = getUnMarshaller();
106
 
         if (unmarshaller == null)
107
 
         {
108
 
            // try by locator (in case unmarshaller class name specified)
109
 
            Map map = passConfigMapToMarshalFactory ? configuration : null;
110
 
            unmarshaller = MarshalFactory.getUnMarshaller(getLocator(), getClassLoader(), map);
111
 
            if (unmarshaller == null)
112
 
            {
113
 
               unmarshaller = MarshalFactory.getUnMarshaller(getDataType(), getSerializationType());
114
 
               if (unmarshaller == null)
115
 
               {
116
 
                  // went as far as possible to find a unmarshaller, will have to give up
117
 
                  throw new InvalidMarshallingResource(
118
 
                        "Can not find a valid unmarshaller for data type: " + getDataType());
119
 
               }
120
 
            }
121
 
            setUnMarshaller(unmarshaller);
122
 
         }
123
 
 
124
 
         // Each unmarshaller gets a RemotingClassloader classloader containing the 
125
 
         // remoting class loader (for remote classloading) and the current thread's
126
 
         // class loader.  This allows to load remoting classes as well as user's
127
 
         // classes.  If possible, will simply reset context classloader on existing
128
 
         // RemotingClassLoader.
129
 
         final ClassLoader contextClassLoader = getContextClassLoader(Thread.currentThread());
130
 
         if (unmarshaller instanceof UpdateableClassloaderUnMarshaller)
131
 
         {
132
 
            UpdateableClassloaderUnMarshaller uclum = (UpdateableClassloaderUnMarshaller) unmarshaller;
133
 
            ClassLoader cl = uclum.getClassLoader();
134
 
            if (cl instanceof RemotingClassLoader)
135
 
            {
136
 
               rcl = (RemotingClassLoader) cl;
137
 
               rcl.setUserClassLoader(contextClassLoader);
138
 
            }
139
 
            else
140
 
            {
141
 
               rcl = createRemotingClassLoader(getClassLoader(), contextClassLoader, parentFirstClassLoading);
142
 
               unmarshaller.setClassLoader(rcl);
143
 
            }
144
 
         }
145
 
         else
146
 
         {
147
 
            rcl = createRemotingClassLoader(getClassLoader(), contextClassLoader, parentFirstClassLoading);
148
 
            unmarshaller.setClassLoader(rcl);  
149
 
         }
150
 
      }
151
 
 
152
 
      // if raw, then send only param of invocation request
153
 
      Object payload = null;
154
 
      Map metadata = invocationReq.getRequestPayload();
155
 
      if (metadata != null && metadata.get(Client.RAW) != null)
156
 
      {
157
 
         payload = invocationReq.getParameter();
158
 
      }
159
 
      else
160
 
      {
161
 
         payload = invocationReq;
162
 
      }
163
 
 
164
 
      try
165
 
      {
166
 
         String sessionId = invocationReq.getSessionId();
167
 
         returnValue = transport(sessionId, payload, metadata, marshaller, unmarshaller);
168
 
      }
169
 
      finally
170
 
      {
171
 
         // Delete reference to current thread's context classloader.
172
 
         rcl.unsetUserClassLoader();
173
 
      }
174
 
      
175
 
      // Now check if is remoting response and process
176
 
      if (returnValue instanceof InvocationResponse)
177
 
      {
178
 
         InvocationResponse response = (InvocationResponse)returnValue;
179
 
         returnValue = response.getResult();
180
 
 
181
 
         // if is a server side exception, throw it
182
 
         if (response.isException())
183
 
         {
184
 
            Throwable e = (Throwable)returnValue;
185
 
 
186
 
            if (trace) { log.trace(this + " received a server-side exception as response to the invocation: " + e); }
187
 
 
188
 
            StackTraceElement[] serverStackTrace;
189
 
            if (e.getCause() != null)
190
 
            {
191
 
               serverStackTrace = e.getCause().getStackTrace();
192
 
               if (serverStackTrace == null || serverStackTrace.length == 0)
193
 
               {
194
 
                  serverStackTrace = e.getStackTrace();
195
 
               }
196
 
            }
197
 
            else
198
 
            {
199
 
               serverStackTrace = e.getStackTrace();
200
 
            }
201
 
 
202
 
            // need to check that there is a server stack trace.  If there is not, need to log
203
 
            // warning here so caller knows that error happened on server side and to look there,
204
 
            // as stack trace is just going to lead them to here, giving the impression that is
205
 
            // a client side exception from this point within remoting client.
206
 
            if (serverStackTrace == null || serverStackTrace.length == 0)
207
 
            {
208
 
               log.warn("An exception occurred on the server side when making remote invocation.  " +
209
 
                        "The exception returned from server does not include a stack trace.  " +
210
 
                        "Original server side exception message is " + e.getMessage(), e);
211
 
            }
212
 
 
213
 
            Exception clientException = new Exception();
214
 
            StackTraceElement[] clientStackTrace = clientException.getStackTrace();
215
 
            StackTraceElement[] completeStackTrace = new StackTraceElement[serverStackTrace.length + clientStackTrace.length];
216
 
            System.arraycopy(serverStackTrace, 0, completeStackTrace, 0, serverStackTrace.length);
217
 
            System.arraycopy(clientStackTrace, 0, completeStackTrace, serverStackTrace.length, clientStackTrace.length);
218
 
 
219
 
            Throwable responseException = null;
220
 
            if (e instanceof ServerInvoker.InvalidStateException && changeInvalidStateToCannotConnect)
221
 
            {
222
 
               responseException = new CannotConnectException(e.getMessage(), e.getCause());
223
 
            }
224
 
            else
225
 
            {
226
 
               responseException = e;
227
 
            }
228
 
            
229
 
            if (e.getCause() != null)
230
 
            {
231
 
               responseException.getCause().setStackTrace(completeStackTrace);
232
 
            }
233
 
            else
234
 
            {
235
 
               responseException.setStackTrace(completeStackTrace);
236
 
            }
237
 
 
238
 
            throw responseException;
239
 
         }
240
 
 
241
 
         if (trace) { log.trace(this + " received InvocationResponse so going to return response's return value of " + returnValue);}
242
 
 
243
 
      }
244
 
 
245
 
      return returnValue;
246
 
   }
247
 
 
248
 
   /**
249
 
    * this method is called prior to making the remote invocation to allow the subclass the ability
250
 
    * to provide additional data or modify the invocation
251
 
    *
252
 
    * @param sessionId
253
 
    * @param param
254
 
    * @param sendPayload
255
 
    * @param receivedPayload
256
 
    */
257
 
   protected void preProcess(String sessionId, Object param, Map sendPayload, Map receivedPayload)
258
 
   {
259
 
   }
260
 
 
261
 
   /**
262
 
    * this method is called prior to returning the result for the invocation to allow the subclass the ability
263
 
    * to modify the result result
264
 
    *
265
 
    * @param sessionId
266
 
    * @param param
267
 
    * @param sendPayload
268
 
    * @param receivedPayload
269
 
    */
270
 
   protected void postProcess(String sessionId, Object param, Map sendPayload,
271
 
                              Map receivedPayload)
272
 
   {
273
 
 
274
 
   }
275
 
 
276
 
   protected abstract Object transport(String sessionId, Object invocation, Map metadata,
277
 
                                       Marshaller marshaller, UnMarshaller unmarshaller)
278
 
      throws IOException, ConnectionFailedException, ClassNotFoundException;
279
 
 
280
 
   /**
281
 
    * Subclasses must provide this method to return true if their remote connection is connected and
282
 
    * false if disconnected.  in some transports, such as SOAP, this method may always return true,
283
 
    * since the remote connectivity is done on demand and not kept persistent like other transports
284
 
    * (such as socket-based transport).
285
 
    *
286
 
    * @return boolean true if connected, false if not
287
 
    */
288
 
   public boolean isConnected()
289
 
   {
290
 
      return connected;
291
 
   }
292
 
 
293
 
   /**
294
 
    * Connect to the remote invoker.
295
 
    */
296
 
   public synchronized void connect() throws ConnectionFailedException
297
 
   {
298
 
      if (!connected)
299
 
      {
300
 
         log.debug(this + " connecting");
301
 
         
302
 
         // In single home case, locator's connect homes list consists
303
 
         // locator's host:port.  In multihome case, connect homes list 
304
 
         // is empty unless explicitly defined.
305
 
         connectHomes = locator.getConnectHomeList();
306
 
         if (locator.isMultihome() && connectHomes.isEmpty())
307
 
         {
308
 
            connectHomes = locator.getHomeList();
309
 
         }
310
 
 
311
 
         handleConnect();
312
 
         connected = true;
313
 
 
314
 
         log.debug(this + " connected");
315
 
      }
316
 
   }
317
 
 
318
 
   /**
319
 
    * Subclasses must implement this method to provide a hook to connect to the remote server, if
320
 
    * this applies to the specific transport. However, in some transport implementations, this may
321
 
    * not make must difference since the connection is not persistent among invocations, such as
322
 
    * SOAP.  In these cases, the method should silently return without any processing.
323
 
    *
324
 
    * @throws ConnectionFailedException
325
 
    *
326
 
    */
327
 
   protected abstract void handleConnect() throws ConnectionFailedException;
328
 
 
329
 
   /**
330
 
    * Subclasses must implement this method to provide a hook to disconnect from the remote server,
331
 
    * if this applies to the specific transport. However, in some transport implementations, this
332
 
    * may not make must difference since the connection is not persistent among invocations, such as
333
 
    * SOAP. In these cases, the method should silently return without any processing.
334
 
    */
335
 
   protected abstract void handleDisconnect();
336
 
 
337
 
   /**
338
 
    * disconnect from the remote invokere
339
 
    */
340
 
   public synchronized void disconnect()
341
 
   {
342
 
      if (trace) { log.trace(this + " disconnecting ..."); }
343
 
 
344
 
      if (connected)
345
 
      {
346
 
         connected = false;
347
 
         handleDisconnect();
348
 
         ClassLoader classLoader = getClassLoader();
349
 
         if (classLoader != null && classLoader instanceof ClassByteClassLoader)
350
 
         {
351
 
            ((ClassByteClassLoader) classbyteloader).destroy();
352
 
         }
353
 
         if (trace) { log.trace(this + " disconnected"); }
354
 
      }
355
 
      else
356
 
      {
357
 
         if (trace) { log.trace(this + " is not connected!"); }
358
 
      }
359
 
   }
360
 
 
361
 
   public void setMarshaller(Marshaller marshaller)
362
 
   {
363
 
      this.marshaller = marshaller;
364
 
   }
365
 
 
366
 
   public Marshaller getMarshaller()
367
 
   {
368
 
      return this.marshaller;
369
 
   }
370
 
 
371
 
   public void setUnMarshaller(UnMarshaller unmarshaller)
372
 
   {
373
 
      ClassLoader classLoader = getContextClassLoader(Thread.currentThread());
374
 
      unmarshallers.put(classLoader, unmarshaller);
375
 
   }
376
 
 
377
 
   public UnMarshaller getUnMarshaller()
378
 
   {
379
 
      ClassLoader classLoader = getContextClassLoader(Thread.currentThread());
380
 
      return (UnMarshaller)unmarshallers.get(classLoader);
381
 
   }
382
 
   
383
 
   public String getSessionId()
384
 
   {
385
 
      return this.invokerSessionID;
386
 
   }
387
 
 
388
 
   public void terminateLease(String sessionId, int disconnectTimeout)
389
 
   {
390
 
      terminateLease(sessionId, disconnectTimeout, null);
391
 
   }
392
 
   
393
 
   public void terminateLease(String sessionId, int disconnectTimeout, LeasePinger passedLeasePinger)
394
 
   {
395
 
      synchronized(clientLeaseLock)
396
 
      {
397
 
         if (passedLeasePinger != null && passedLeasePinger != leasePinger)
398
 
         {
399
 
            if (trace) log.trace(this + ": " + passedLeasePinger + " != " + leasePinger);
400
 
            return;
401
 
         }
402
 
         if (trace) log.trace(this + " entering terminateLease() for " + leasePinger);
403
 
         if(leasePinger != null)
404
 
         {
405
 
            leasePinger.setDisconnectTimeout(disconnectTimeout);
406
 
            
407
 
            if (sessionId == null)
408
 
            {
409
 
               if (trace) log.trace(this + " shutting down LeasePinger: " + leasePinger);
410
 
               // Independent of any particular Client - force LeasePinger shutdown.
411
 
               // Should be called only if there is a reasonable belief that the lease
412
 
               // has already stopped on the server side.
413
 
               try
414
 
               {
415
 
                  leasePinger.stopPing();
416
 
               }
417
 
               catch (Exception e)
418
 
               {
419
 
                  log.debug("error shutting down lease pinger" + e.getMessage());
420
 
                  log.trace("error shutting down lease pinger", e);
421
 
               }
422
 
               leasePinger = null;
423
 
            }
424
 
            else
425
 
            {
426
 
               // Remove a particular Client.
427
 
               if (trace) log.trace(this + " removing client " + sessionId + " from LeasePinger: " + leasePinger);
428
 
               boolean isLastClientLease = leasePinger.removeClient(sessionId);
429
 
               if(isLastClientLease)
430
 
               {
431
 
                  if (trace) log.trace(this + " shutting down LeasePinger, " + sessionId + " was last client lease: " + leasePinger);
432
 
                  try
433
 
                  {
434
 
                     leasePinger.stopPing();
435
 
                  }
436
 
                  catch (Exception e)
437
 
                  {
438
 
                     log.debug("error shutting down lease pinger");
439
 
                  }
440
 
                  leasePinger = null;
441
 
               }
442
 
            }
443
 
         }
444
 
         else
445
 
         {
446
 
            if (trace) log.trace(this + " leasePinger is null: must have been shut down already");
447
 
         }
448
 
         if (trace) log.trace(this + " leaving terminateLease() for " + leasePinger);
449
 
      }
450
 
   }
451
 
 
452
 
   public long getLeasePeriod(String sessionID)
453
 
   {
454
 
      synchronized(clientLeaseLock)
455
 
      {
456
 
         if(leasePinger == null)
457
 
         {
458
 
            return -1;
459
 
         }
460
 
 
461
 
         return leasePinger.getLeasePeriod(sessionID);
462
 
      }
463
 
   }
464
 
 
465
 
   public void establishLease(String clientSessionID, Map configuration, long leasePeriod)
466
 
      throws Throwable
467
 
   {
468
 
      Client client = (Client) configuration.get(Client.CLIENT);
469
 
      ConnectionListener listener = (ConnectionListener) configuration.remove(Client.CONNECTION_LISTENER);
470
 
      boolean useClientConnectionIdentity = false;
471
 
      if (configuration != null)
472
 
      {
473
 
         Object o = configuration.get(Remoting.USE_CLIENT_CONNECTION_IDENTITY);
474
 
         if (o instanceof String)
475
 
         {
476
 
            useClientConnectionIdentity = Boolean.valueOf((String) o).booleanValue();
477
 
         }
478
 
         else if (o != null)
479
 
         {
480
 
            log.warn("value of " + Remoting.USE_CLIENT_CONNECTION_IDENTITY + " must be a String: " + o); 
481
 
         }
482
 
      }
483
 
       
484
 
      synchronized (clientLeaseLock)
485
 
      {
486
 
         // if already have a lease pinger, then already have a client with an established
487
 
         // lease and just need to update the lease pinger
488
 
         if (leasePinger != null)
489
 
         {
490
 
            leasePinger.addClient(clientSessionID, configuration, leasePeriod);
491
 
            if (trace) log.trace(this + " added client with session ID " + clientSessionID + " to " + leasePinger);
492
 
         }
493
 
         else
494
 
         {
495
 
            try
496
 
            {
497
 
               if(trace) { log.trace(this + " sending initial lease ping to server to determine if server has leasing enabled."); }
498
 
 
499
 
               // configuration should NOT be passed as want ping to be specific to client invoker
500
 
               // and NOT to the client.
501
 
 
502
 
               String leasePingerId = new GUID().toString();
503
 
               Map requestMap = new HashMap();
504
 
               requestMap.put(LeasePinger.LEASE_PINGER_ID, leasePingerId);
505
 
               requestMap.put(LeasePinger.TIME_STAMP, Long.toString(System.currentTimeMillis()));
506
 
               if (trace) log.trace(this + " initiating lease for leasePingerId " + leasePingerId);
507
 
               InvocationRequest ir = new InvocationRequest(invokerSessionID, null, "$PING$", requestMap, new HashMap(), null);
508
 
 
509
 
               Object ret = invoke(ir);
510
 
 
511
 
               if (ret instanceof InvocationResponse)
512
 
               {
513
 
                  InvocationResponse resp = (InvocationResponse) ret;
514
 
                  Boolean shouldLease = (Boolean)resp.getResult();
515
 
 
516
 
                  if (shouldLease.booleanValue())
517
 
                  {
518
 
                     long defaultLeasePeriod = LeasePinger.DEFAULT_LEASE_PERIOD;
519
 
                     Map respMap = resp.getPayload();
520
 
 
521
 
                     if (respMap != null)
522
 
                     {
523
 
                        Long leaseTimeoutValue = (Long)respMap.get("clientLeasePeriod");
524
 
                        long serverDefaultLeasePeriod = leaseTimeoutValue.longValue();
525
 
                        if(serverDefaultLeasePeriod > 0)
526
 
                        {
527
 
                           defaultLeasePeriod = serverDefaultLeasePeriod;
528
 
                        }
529
 
                     }
530
 
 
531
 
                     if(trace) { log.trace("server does have leasing enabled (with default lease period of " + defaultLeasePeriod + ") and will start a new lease pinger."); }
532
 
 
533
 
                     leasePinger = new LeasePinger(this, invokerSessionID, defaultLeasePeriod, configuration);
534
 
                     leasePinger.setLeasePingerId(leasePingerId);
535
 
                     leasePinger.setUseClientConnectionIdentity(useClientConnectionIdentity);
536
 
                     leasePinger.addClient(clientSessionID, configuration, leasePeriod);
537
 
                     leasePinger.startPing();
538
 
                  }
539
 
               }
540
 
            }
541
 
            catch (Throwable throwable)
542
 
            {
543
 
               Exception e = new Exception("Error setting up client lease");
544
 
               e.initCause(throwable);
545
 
               throw e;
546
 
            }
547
 
         }
548
 
 
549
 
         if (trace) log.trace(this + ": client = " + client + ", listener = " + listener);
550
 
         if (client != null && listener != null)
551
 
         {
552
 
            client.addConnectionListener(listener, configuration);
553
 
         }
554
 
      }
555
 
   }
556
 
 
557
 
   /**
558
 
    * Will get the data type for the marshaller factory so know which marshaller to
559
 
    * get to marshal the data.  Will first check the locator uri for a 'datatype'
560
 
    * parameter and take that value if it exists.  Otherwise, will use the
561
 
    * default datatype for the client invoker, based on transport.
562
 
    */
563
 
   private String getDataType()
564
 
   {
565
 
      if (dataType == null)
566
 
      {
567
 
         String localDataType = getDataType(getLocator());
568
 
         if (localDataType == null)
569
 
         {
570
 
            localDataType = getDefaultDataType();
571
 
         }
572
 
         dataType = localDataType;
573
 
      }
574
 
      return dataType;
575
 
   }
576
 
 
577
 
   private String getDataType(InvokerLocator locator)
578
 
   {
579
 
      String type = null;
580
 
 
581
 
      if (locator != null)
582
 
      {
583
 
         Map params = locator.getParameters();
584
 
         if (params != null)
585
 
         {
586
 
            type = (String) params.get(InvokerLocator.DATATYPE);
587
 
            if (type == null)
588
 
            {
589
 
               type = (String) params.get(InvokerLocator.DATATYPE_CASED);
590
 
            }
591
 
         }
592
 
      }
593
 
      return type;
594
 
   }
595
 
   
596
 
   protected void init()
597
 
   {
598
 
      // Get the parent delegation order flag, default is parent first
599
 
      Object flag = super.getConfiguration().get(Remoting.CLASSLOADING_PARENT_FIRST_DELEGATION);
600
 
      if(flag == null)
601
 
      {
602
 
         // Fallback to the system property
603
 
         flag = getSystemProperty(Remoting.CLASSLOADING_PARENT_FIRST_DELEGATION_PROP);
604
 
      }
605
 
      boolean parentFirst = true;
606
 
      if (flag != null)
607
 
      {
608
 
         String sflag = flag.toString();
609
 
         parentFirst = Boolean.valueOf(sflag).booleanValue();
610
 
      }
611
 
      parentFirstClassLoading = parentFirst;
612
 
      
613
 
      flag = configuration.get(Remoting.CHANGE_INVALID_STATE_TO_CANNOT_CONNECT);
614
 
      if (flag != null)
615
 
      {
616
 
         String sflag = flag.toString();
617
 
         changeInvalidStateToCannotConnect = Boolean.valueOf(sflag).booleanValue();
618
 
      }
619
 
   }
620
 
 
621
 
   /**
622
 
    * Each implementation of the remote client invoker should have
623
 
    * a default data type that is uses in the case it is not specified
624
 
    * in the invoker locator uri.
625
 
    */
626
 
   protected abstract String getDefaultDataType();
627
 
 
628
 
   
629
 
   protected List getConnectHomes()
630
 
   {
631
 
      return connectHomes;
632
 
   }
633
 
 
634
 
   /**
635
 
    * Called by the garbage collector on an object when garbage collection
636
 
    * determines that there are no more references to the object.
637
 
    * A subclass overrides the <code>finalize</code> method to dispose of
638
 
    * system resources or to perform other cleanup.
639
 
    * <p/>
640
 
    * The general contract of <tt>finalize</tt> is that it is invoked
641
 
    * if and when the Java<font size="-2"><sup>TM</sup></font> virtual
642
 
    * machine has determined that there is no longer any
643
 
    * means by which this object can be accessed by any thread that has
644
 
    * not yet died, except as a result of an action taken by the
645
 
    * finalization of some other object or class which is ready to be
646
 
    * finalized. The <tt>finalize</tt> method may take any action, including
647
 
    * making this object available again to other threads; the usual purpose
648
 
    * of <tt>finalize</tt>, however, is to perform cleanup actions before
649
 
    * the object is irrevocably discarded. For example, the finalize method
650
 
    * for an object that represents an input/output connection might perform
651
 
    * explicit I/O transactions to break the connection before the object is
652
 
    * permanently discarded.
653
 
    * <p/>
654
 
    * The <tt>finalize</tt> method of class <tt>Object</tt> performs no
655
 
    * special action; it simply returns normally. Subclasses of
656
 
    * <tt>Object</tt> may override this definition.
657
 
    * <p/>
658
 
    * The Java programming language does not guarantee which thread will
659
 
    * transport the <tt>finalize</tt> method for any given object. It is
660
 
    * guaranteed, however, that the thread that invokes finalize will not
661
 
    * be holding any user-visible synchronization locks when finalize is
662
 
    * invoked. If an uncaught exception is thrown by the finalize method,
663
 
    * the exception is ignored and finalization of that object terminates.
664
 
    * <p/>
665
 
    * After the <tt>finalize</tt> method has been invoked for an object, no
666
 
    * further action is taken until the Java virtual machine has again
667
 
    * determined that there is no longer any means by which this object can
668
 
    * be accessed by any thread that has not yet died, including possible
669
 
    * actions by other objects or classes which are ready to be finalized,
670
 
    * at which point the object may be discarded.
671
 
    * <p/>
672
 
    * The <tt>finalize</tt> method is never invoked more than once by a Java
673
 
    * virtual machine for any given object.
674
 
    * <p/>
675
 
    * Any exception thrown by the <code>finalize</code> method causes
676
 
    * the finalization of this object to be halted, but is otherwise
677
 
    * ignored.
678
 
    *
679
 
    * @throws Throwable the <code>Exception</code> raised by this method
680
 
    */
681
 
   protected void finalize() throws Throwable
682
 
   {
683
 
      disconnect();
684
 
      super.finalize();
685
 
   }
686
 
   
687
 
   protected LeasePinger getLeasePinger()
688
 
   {
689
 
      synchronized(clientLeaseLock)
690
 
      {
691
 
         return leasePinger;
692
 
      }
693
 
   }
694
 
   
695
 
   static private String getSystemProperty(final String name)
696
 
   {
697
 
      if (SecurityUtility.skipAccessControl())
698
 
         return System.getProperty(name);
699
 
      
700
 
      String value = null;
701
 
      try
702
 
      {
703
 
         value = (String)AccessController.doPrivileged( new PrivilegedExceptionAction()
704
 
         {
705
 
            public Object run() throws Exception
706
 
            {
707
 
               return System.getProperty(name);
708
 
            }
709
 
         });
710
 
      }
711
 
      catch (PrivilegedActionException e)
712
 
      {
713
 
         throw (RuntimeException) e.getCause();
714
 
      }
715
 
      
716
 
      return value;
717
 
   }
718
 
   
719
 
   static private RemotingClassLoader createRemotingClassLoader(final ClassLoader remotingClassLoader,
720
 
         final ClassLoader userClassLoader, final boolean parentFirstDelegation)
721
 
   {
722
 
      if (SecurityUtility.skipAccessControl())
723
 
      {
724
 
         return new RemotingClassLoader(remotingClassLoader, userClassLoader, parentFirstDelegation);
725
 
      }
726
 
 
727
 
      return (RemotingClassLoader)AccessController.doPrivileged( new PrivilegedAction()
728
 
      {
729
 
         public Object run()
730
 
         {
731
 
            return new RemotingClassLoader(remotingClassLoader, userClassLoader, parentFirstDelegation);
732
 
         }
733
 
      });
734
 
   }
735
 
   
736
 
   static private ClassLoader getContextClassLoader(final Thread thread)
737
 
   {
738
 
      if (SecurityUtility.skipAccessControl())
739
 
      {
740
 
         return thread.getContextClassLoader();
741
 
      }
742
 
 
743
 
      return (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
744
 
      {
745
 
         public Object run()
746
 
         {
747
 
            return thread.getContextClassLoader();
748
 
         }
749
 
      });
750
 
   }
751
 
}