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

« back to all changes in this revision

Viewing changes to .pc/0001-convert-to-official-Java-concurrent-packages.patch/src/main/org/jboss/remoting/transport/socket/MicroSocketClientInvoker.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.transport.socket;
 
2
 
 
3
import org.jboss.logging.Logger;
 
4
import org.jboss.remoting.CannotConnectException;
 
5
import org.jboss.remoting.ConnectionFailedException;
 
6
import org.jboss.remoting.Home;
 
7
import org.jboss.remoting.InvocationFailureException;
 
8
import org.jboss.remoting.InvocationRequest;
 
9
import org.jboss.remoting.InvokerLocator;
 
10
import org.jboss.remoting.RemoteClientInvoker;
 
11
import org.jboss.remoting.ServerInvoker;
 
12
import org.jboss.remoting.Version;
 
13
import org.jboss.remoting.serialization.ClassLoaderUtility;
 
14
import org.jboss.remoting.util.SecurityUtility;
 
15
import org.jboss.remoting.invocation.OnewayInvocation;
 
16
import org.jboss.remoting.marshal.Marshaller;
 
17
import org.jboss.remoting.marshal.UnMarshaller;
 
18
import org.jboss.remoting.marshal.VersionedMarshaller;
 
19
import org.jboss.remoting.marshal.VersionedUnMarshaller;
 
20
import org.jboss.remoting.marshal.serializable.SerializableMarshaller;
 
21
import org.jboss.util.propertyeditor.PropertyEditors;
 
22
 
 
23
import java.beans.IntrospectionException;
 
24
import java.io.EOFException;
 
25
import java.io.IOException;
 
26
import java.io.InputStream;
 
27
import java.io.OutputStream;
 
28
import java.lang.reflect.Constructor;
 
29
import java.net.InetAddress;
 
30
import java.net.Socket;
 
31
import java.net.InetSocketAddress;
 
32
import java.net.SocketException;
 
33
import java.net.UnknownHostException;
 
34
import java.rmi.MarshalException;
 
35
import java.security.AccessController;
 
36
import java.security.PrivilegedActionException;
 
37
import java.security.PrivilegedExceptionAction;
 
38
import java.util.HashMap;
 
39
import java.util.Iterator;
 
40
import java.util.LinkedList;
 
41
import java.util.List;
 
42
import java.util.Map;
 
43
import java.util.Properties;
 
44
import java.util.regex.Pattern;
 
45
 
 
46
import EDU.oswego.cs.dl.util.concurrent.Semaphore;
 
47
 
 
48
/**
 
49
 * SocketClientInvoker uses Sockets to remotely connect to the a remote ServerInvoker, which must be
 
50
 * a SocketServerInvoker.
 
51
 *
 
52
 * @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
 
53
 * @author <a href="mailto:telrod@e2technologies.net">Tom Elrod</a>
 
54
 * @author <a href="mailto:ovidiu@jboss.org">Ovidiu Feodorov</a>
 
55
 *
 
56
 * @version $Revision: 5476 $
 
57
 */
 
58
public class MicroSocketClientInvoker extends RemoteClientInvoker
 
59
{
 
60
   // Constants ------------------------------------------------------------------------------------
 
61
 
 
62
   private static final Logger log = Logger.getLogger(MicroSocketClientInvoker.class);
 
63
 
 
64
   /**
 
65
    * Can be either true or false and will indicate if client socket should have TCP_NODELAY turned
 
66
    * on or off. TCP_NODELAY is for a specific purpose; to disable the Nagle buffering algorithm.
 
67
    * It should only be set for applications that send frequent small bursts of information without
 
68
    * getting an immediate response; where timely delivery of data is required (the canonical
 
69
    * example is mouse movements). The default is false.
 
70
    */
 
71
   public static final String TCP_NODELAY_FLAG = "enableTcpNoDelay";
 
72
 
 
73
   /**
 
74
    * The client side maximum number of threads. The default is MAX_POOL_SIZE.
 
75
    */
 
76
   public static final String MAX_POOL_SIZE_FLAG = "clientMaxPoolSize";
 
77
 
 
78
   /**
 
79
    * Specifies the fully qualified class name for the custom SocketWrapper implementation to use on
 
80
    * the client. Note, will need to make sure this is marked as a client parameter (using the
 
81
    * 'isParam' attribute). Making this change will not affect the marshaller/unmarshaller that is
 
82
    * used, which may also be a requirement.
 
83
    */
 
84
   public static final String CLIENT_SOCKET_CLASS_FLAG = "clientSocketClass";
 
85
   
 
86
   /** Key for setting timeout used by OnewayConnectionTask */
 
87
   public static final String ONEWAY_CONNECTION_TIMEOUT = "onewayConnectionTimeout";
 
88
   
 
89
   /** Key to determine if client side oneway invocations should wait to read version.
 
90
    *  See JBREM-706.
 
91
    */
 
92
   public static final String USE_ONEWAY_CONNECTION_TIMEOUT = "useOnewayConnectionTimeout";
 
93
 
 
94
   /** Key for setting time to wait to get permission to get a connection */
 
95
   public static final String CONNECTION_WAIT = "connectionWait";
 
96
   
 
97
   /** Key for setting socket write timeout */
 
98
   public static final String WRITE_TIMEOUT = "writeTimeout";
 
99
   
 
100
   /**
 
101
    * Default value for enable TCP nodelay. Value is false.
 
102
    */
 
103
   public static final boolean TCP_NODELAY_DEFAULT = false;
 
104
 
 
105
   /**
 
106
    * Default maximum number of times a invocation will be made when it gets a SocketException.
 
107
    * Default is 3.
 
108
    */
 
109
   public static final int MAX_CALL_RETRIES = 3;
 
110
 
 
111
   /**
 
112
    * Default maximum number of socket connections allowed at any point in time. Default is 50.
 
113
    */
 
114
   public static final int MAX_POOL_SIZE = 50;
 
115
 
 
116
   /** Default timeout value used by OnewayConnectionTask.  Value is 2 seconds. */
 
117
   public static final int ONEWAY_CONNECTION_TIMEOUT_DEFAULT = 2000;
 
118
   
 
119
   /** Default time to wait to get permission to get a connection */
 
120
   public static final int CONNECTION_WAIT_DEFAULT = 30000;
 
121
 
 
122
   // Static ---------------------------------------------------------------------------------------
 
123
 
 
124
   private static boolean trace = log.isTraceEnabled();
 
125
 
 
126
   /**
 
127
    * Used for debugging (tracing) connections leaks
 
128
    */
 
129
   static int counter = 0;
 
130
 
 
131
   protected static final Map connectionPools = new HashMap();
 
132
   
 
133
   protected static final Map semaphores = new HashMap();
 
134
 
 
135
   // Performance measurements
 
136
   public static long getSocketTime = 0;
 
137
   public static long readTime = 0;
 
138
   public static long writeTime = 0;
 
139
   public static long serializeTime = 0;
 
140
   public static long deserializeTime = 0;
 
141
   
 
142
   private static final String patternString = "^.*(?:connection.*reset|connection.*closed|broken.*pipe).*$";
 
143
   private static final Pattern RETRIABLE_ERROR_MESSAGE = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
 
144
   
 
145
   /**
 
146
    * Close all sockets in a specific pool.
 
147
    */
 
148
   public static void clearPool(LinkedList thepool)
 
149
   {
 
150
      try
 
151
      {
 
152
         if (thepool == null)
 
153
         {
 
154
            return;
 
155
         }
 
156
         synchronized (thepool)
 
157
         {
 
158
            int size = thepool.size();
 
159
            for (int i = 0; i < size; i++)
 
160
            {
 
161
               SocketWrapper socketWrapper = (SocketWrapper)thepool.removeFirst();
 
162
               try
 
163
               {
 
164
                  socketWrapper.close();
 
165
                  socketWrapper = null;
 
166
               }
 
167
               catch (Exception ignored)
 
168
               {
 
169
               }
 
170
            }
 
171
         }
 
172
      }
 
173
      catch (Exception ex)
 
174
      {
 
175
         log.debug("Failure", ex);
 
176
      }
 
177
   }
 
178
 
 
179
   /**
 
180
    * Close all sockets in all pools.
 
181
    */
 
182
   public static void clearPools()
 
183
   {
 
184
      synchronized (connectionPools)
 
185
      {
 
186
         for(Iterator i = connectionPools.keySet().iterator(); i.hasNext();)
 
187
         {
 
188
            ServerAddress sa = (ServerAddress) i.next();
 
189
 
 
190
            if (trace) { log.trace("clearing pool for " + sa); }
 
191
            clearPool((LinkedList) connectionPools.get(sa));
 
192
            i.remove();
 
193
         }
 
194
         semaphores.clear();
 
195
      }
 
196
   }
 
197
 
 
198
   // Attributes -----------------------------------------------------------------------------------
 
199
 
 
200
   private Constructor clientSocketConstructor;
 
201
   private boolean reuseAddress;
 
202
 
 
203
   protected InetAddress addr;
 
204
   protected int port;
 
205
 
 
206
   // flag being set on true by a disconnect request. If trying to create a connection goes on in a
 
207
   // loop and a disconnect request arrives, this flag will be used to sent this information into
 
208
   // the connect loop
 
209
   // private volatile boolean bailOut;
 
210
 
 
211
   /**
 
212
    * Indicates if will check the socket connection when getting from pool by sending byte over the
 
213
    * connection to validate is still good.
 
214
    */
 
215
   protected boolean shouldCheckConnection;
 
216
 
 
217
   /**
 
218
    * If the TcpNoDelay option should be used on the socket.
 
219
    */
 
220
   protected boolean enableTcpNoDelay;
 
221
 
 
222
   protected String clientSocketClassName;
 
223
   protected Class clientSocketClass;
 
224
   protected int numberOfCallRetries;
 
225
   protected int maxPoolSize;
 
226
   protected int onewayConnectionTimeout;
 
227
   protected boolean useOnewayConnectionTimeout = true;
 
228
   protected int connectionWait = CONNECTION_WAIT_DEFAULT;
 
229
 
 
230
   /**
 
231
    * Pool for this invoker. This is shared between all instances of proxies attached to a specific
 
232
    * invoker.
 
233
    */
 
234
   protected LinkedList pool;
 
235
   
 
236
   //Semaphore is also shared between all proxies - must 1-1 correspondence between pool and semaphore
 
237
   protected Semaphore semaphore;
 
238
   
 
239
 
 
240
   /**
 
241
    * connection information
 
242
    */
 
243
   protected ServerAddress address;
 
244
   protected Home home;
 
245
   
 
246
   /**
 
247
    * Socket configuration parameters.
 
248
    */
 
249
   protected boolean keepAlive;
 
250
   protected boolean keepAliveSet;
 
251
   protected boolean oOBInline;
 
252
   protected boolean oOBInlineSet;
 
253
   protected int receiveBufferSize = - 1;
 
254
   protected int sendBufferSize = -1;
 
255
   protected boolean soLinger;
 
256
   protected boolean soLingerSet;
 
257
   protected int soLingerDuration = -1;
 
258
   protected int trafficClass = -1;
 
259
   
 
260
   /**
 
261
    * If true, an IOException with message such as "Connection reset by peer: socket write error" will 
 
262
    * be treated like a SocketException.
 
263
    */
 
264
   protected boolean generalizeSocketException;
 
265
   
 
266
   protected int writeTimeout = -1;
 
267
 
 
268
   // Constructors ---------------------------------------------------------------------------------
 
269
 
 
270
   public MicroSocketClientInvoker(InvokerLocator locator)
 
271
   {
 
272
      this(locator, null);
 
273
   }
 
274
 
 
275
   public MicroSocketClientInvoker(InvokerLocator locator, Map configuration)
 
276
   {
 
277
      super(locator, configuration);
 
278
 
 
279
      clientSocketConstructor = null;
 
280
      reuseAddress = true;
 
281
      shouldCheckConnection = false;
 
282
      enableTcpNoDelay = TCP_NODELAY_DEFAULT;
 
283
      clientSocketClassName = ClientSocketWrapper.class.getName();
 
284
      clientSocketClass = null;
 
285
      numberOfCallRetries = MAX_CALL_RETRIES;
 
286
      pool = null;
 
287
      maxPoolSize = MAX_POOL_SIZE;
 
288
      onewayConnectionTimeout = ONEWAY_CONNECTION_TIMEOUT_DEFAULT;
 
289
 
 
290
      try
 
291
      {
 
292
         setup();
 
293
      }
 
294
      catch (Exception ex)
 
295
      {
 
296
         log.debug("Error setting up " + this, ex);
 
297
         throw new RuntimeException(ex.getMessage(), ex);
 
298
      }
 
299
 
 
300
      log.debug(this + " constructed");
 
301
   }
 
302
 
 
303
   // Public ---------------------------------------------------------------------------------------
 
304
 
 
305
   /**
 
306
    * Indicates if will check socket connection when returning from pool by sending byte to the
 
307
    * server. Default value will be false.
 
308
    */
 
309
   public boolean checkingConnection()
 
310
   {
 
311
      return shouldCheckConnection;
 
312
   }
 
313
 
 
314
   /**
 
315
    * Returns if newly created sockets will have SO_REUSEADDR enabled. Default is for this to be
 
316
    * true.
 
317
    */
 
318
   public boolean getReuseAddress()
 
319
   {
 
320
      return reuseAddress;
 
321
   }
 
322
 
 
323
   /**
 
324
    * Sets if newly created socket should have SO_REUSEADDR enable. Default is true.
 
325
    */
 
326
   public void setReuseAddress(boolean reuse)
 
327
   {
 
328
      reuseAddress = reuse;
 
329
   }
 
330
 
 
331
   public boolean isKeepAlive()
 
332
   {
 
333
      return keepAlive;
 
334
   }
 
335
 
 
336
   public void setKeepAlive(boolean keepAlive)
 
337
   {
 
338
      this.keepAlive = keepAlive;
 
339
      keepAliveSet = true;
 
340
   }
 
341
 
 
342
   public boolean isOOBInline()
 
343
   {
 
344
      return oOBInline;
 
345
   }
 
346
 
 
347
   public void setOOBInline(boolean inline)
 
348
   {
 
349
      oOBInline = inline;
 
350
      oOBInlineSet = true;
 
351
   }
 
352
 
 
353
   public int getReceiveBufferSize()
 
354
   {
 
355
      return receiveBufferSize;
 
356
   }
 
357
 
 
358
   public void setReceiveBufferSize(int receiveBufferSize)
 
359
   {
 
360
      this.receiveBufferSize = receiveBufferSize;
 
361
   }
 
362
 
 
363
   public int getSendBufferSize()
 
364
   {
 
365
      return sendBufferSize;
 
366
   }
 
367
 
 
368
   public void setSendBufferSize(int sendBufferSize)
 
369
   {
 
370
      this.sendBufferSize = sendBufferSize;
 
371
   }
 
372
 
 
373
   public boolean isSoLinger()
 
374
   {
 
375
      return soLinger;
 
376
   }
 
377
   
 
378
   public int getSoLingerDuration()
 
379
   {
 
380
      return soLingerDuration;
 
381
   }
 
382
 
 
383
   public void setSoLinger(boolean soLinger)
 
384
   {
 
385
      this.soLinger = soLinger;
 
386
      soLingerSet = true;
 
387
   }
 
388
 
 
389
   public void setSoLingerDuration(int soLingerDuration)
 
390
   {
 
391
      this.soLingerDuration = soLingerDuration;
 
392
   }
 
393
 
 
394
   public int getTrafficClass()
 
395
   {
 
396
      return trafficClass;
 
397
   }
 
398
 
 
399
   public void setTrafficClass(int trafficClass)
 
400
   {
 
401
      this.trafficClass = trafficClass;
 
402
   }
 
403
 
 
404
   public int getWriteTimeout()
 
405
   {
 
406
      return writeTimeout;
 
407
   }
 
408
 
 
409
   public void setWriteTimeout(int writeTimeout)
 
410
   {
 
411
      this.writeTimeout = writeTimeout;
 
412
   }
 
413
 
 
414
   public boolean isGeneralizeSocketException()
 
415
   {
 
416
      return generalizeSocketException;
 
417
   }
 
418
 
 
419
   public void setGeneralizeSocketException(boolean generalizeSocketException)
 
420
   {
 
421
      this.generalizeSocketException = generalizeSocketException;
 
422
   }
 
423
 
 
424
   public synchronized void disconnect()
 
425
   {
 
426
      log.debug(this + " disconnecting ...");
 
427
//      bailOut = true;
 
428
      super.disconnect();
 
429
   }
 
430
 
 
431
   public void flushConnectionPool()
 
432
   {
 
433
      synchronized (pool)
 
434
      {
 
435
         while (pool != null && pool.size() > 0)
 
436
         {
 
437
            SocketWrapper socketWrapper = (SocketWrapper)pool.removeFirst();
 
438
            try
 
439
            {
 
440
               socketWrapper.close();
 
441
            }
 
442
            catch (IOException e)
 
443
            {
 
444
               log.debug("Failed to close socket wrapper", e);
 
445
            }
 
446
         }
 
447
      }
 
448
   }
 
449
   
 
450
   public int getConnectionWait()
 
451
   {
 
452
      return connectionWait;
 
453
   }
 
454
 
 
455
   public void setConnectionWait(int connectionWait)
 
456
   {
 
457
      this.connectionWait = connectionWait;
 
458
   }
 
459
 
 
460
   public Home getHomeInUse()
 
461
   {
 
462
      return home;
 
463
   }
 
464
 
 
465
   /**
 
466
    * Sets the number of times an invocation will retry based on getting SocketException.
 
467
    */
 
468
   public void setNumberOfCallRetries(int numberOfCallRetries)
 
469
   {
 
470
      if (numberOfCallRetries < 1)
 
471
      {
 
472
         this.numberOfCallRetries = MAX_CALL_RETRIES;
 
473
      }
 
474
      else
 
475
      {
 
476
         this.numberOfCallRetries = numberOfCallRetries;
 
477
      }
 
478
   }
 
479
 
 
480
   public int getNumberOfCallRetries()
 
481
   {
 
482
      return numberOfCallRetries;
 
483
   }
 
484
 
 
485
   /**
 
486
    * Sets the number of retries to get a socket connection.
 
487
    *
 
488
    * @param numberOfRetries Must be a number greater than 0.
 
489
    */
 
490
   public void setNumberOfRetries(int numberOfRetries)
 
491
   {
 
492
      log.warn("numberOfRetries is no longer used");
 
493
   }
 
494
 
 
495
   public int getNumberOfRetries()
 
496
   {
 
497
      log.warn("numberOfRetries is no longer used");
 
498
      return -1;
 
499
   }
 
500
 
 
501
   /**
 
502
    * The name of of the server.
 
503
    */
 
504
   public String getServerHostName() throws Exception
 
505
   {
 
506
      return address.address;
 
507
   }
 
508
   
 
509
   public int getNumberOfUsedConnections()
 
510
   {
 
511
      if (semaphore == null)
 
512
         return 0;
 
513
      
 
514
      return maxPoolSize - (int) semaphore.permits();
 
515
   }
 
516
   
 
517
   public int getNumberOfAvailableConnections()
 
518
   {
 
519
      if (semaphore == null)
 
520
         return 0;
 
521
      
 
522
      return (int) semaphore.permits();
 
523
   }
 
524
 
 
525
   // Package protected ----------------------------------------------------------------------------
 
526
 
 
527
   // Protected ------------------------------------------------------------------------------------
 
528
 
 
529
   protected void setup() throws Exception
 
530
   {
 
531
      Properties props = new Properties();
 
532
      props.putAll(configuration);
 
533
      mapJavaBeanProperties(MicroSocketClientInvoker.this, props, false);
 
534
      configureParameters();
 
535
 
 
536
      if (!InvokerLocator.MULTIHOME.equals(locator.getHost()))
 
537
      {
 
538
         addr = getAddressByName(locator.getHost());
 
539
         port = locator.getPort();
 
540
         address = createServerAddress(addr, port);
 
541
      }
 
542
      else
 
543
      {
 
544
         List homes = locator.getConnectHomeList();
 
545
         if (homes.size() == 1)
 
546
         {
 
547
            // Treat as in non MULTIHOME case.
 
548
            Home home = (Home) homes.iterator().next();
 
549
            addr = getAddressByName(home.host);
 
550
            address = createServerAddress(addr, home.port);
 
551
         }
 
552
      }
 
553
   }
 
554
 
 
555
   protected void configureParameters()
 
556
   {
 
557
      Map params = configuration;
 
558
 
 
559
      if (params == null)
 
560
      {
 
561
         return;
 
562
      }
 
563
 
 
564
      // look for enableTcpNoDelay param
 
565
      Object val = params.get(TCP_NODELAY_FLAG);
 
566
      if (val != null)
 
567
      {
 
568
         try
 
569
         {
 
570
            enableTcpNoDelay = Boolean.valueOf((String)val).booleanValue();
 
571
            log.debug(this + " setting enableTcpNoDelay to " + enableTcpNoDelay);
 
572
         }
 
573
         catch (Exception e)
 
574
         {
 
575
            log.warn(this + " could not convert " + TCP_NODELAY_FLAG + " value of " +
 
576
                     val + " to a boolean value.");
 
577
         }
 
578
      }
 
579
 
 
580
      // look for maxPoolSize param
 
581
      val = params.get(MAX_POOL_SIZE_FLAG);
 
582
      if (val != null)
 
583
      {
 
584
         try
 
585
         {
 
586
            maxPoolSize = Integer.valueOf((String)val).intValue();
 
587
            log.debug(this + " setting maxPoolSize to " + maxPoolSize);
 
588
         }
 
589
         catch (Exception e)
 
590
         {
 
591
            log.warn(this + " could not convert " + MAX_POOL_SIZE_FLAG + " value of " +
 
592
                     val + " to a int value");
 
593
         }
 
594
      }
 
595
 
 
596
      // look for client socket class name
 
597
      val = params.get(CLIENT_SOCKET_CLASS_FLAG);
 
598
      if (val != null)
 
599
      {
 
600
         String value = (String)val;
 
601
         if (value.length() > 0)
 
602
         {
 
603
            clientSocketClassName = value;
 
604
            log.debug(this + " setting client socket wrapper class name to " + clientSocketClassName);
 
605
         }
 
606
      }
 
607
 
 
608
      val = params.get(SocketServerInvoker.CHECK_CONNECTION_KEY);
 
609
      if (val != null && ((String)val).length() > 0)
 
610
      {
 
611
         String value = (String) val;
 
612
         shouldCheckConnection = Boolean.valueOf(value).booleanValue();
 
613
         log.debug(this + " setting shouldCheckConnection to " + shouldCheckConnection);
 
614
      }
 
615
      else if (getVersion() == Version.VERSION_1)
 
616
      {
 
617
         shouldCheckConnection = true;
 
618
         log.debug(this + " setting shouldCheckConnection to " + shouldCheckConnection);
 
619
      }
 
620
      
 
621
      // look for onewayConnectionTimeout param
 
622
      val = params.get(ONEWAY_CONNECTION_TIMEOUT);
 
623
      if (val != null)
 
624
      {
 
625
         try
 
626
         {
 
627
            onewayConnectionTimeout = Integer.valueOf((String)val).intValue();
 
628
            log.debug(this + " setting onewayConnectionTimeout to " + onewayConnectionTimeout);
 
629
         }
 
630
         catch (Exception e)
 
631
         {
 
632
            log.warn(this + " could not convert " + ONEWAY_CONNECTION_TIMEOUT + " value of " +
 
633
                     val + " to an int value");
 
634
         }
 
635
      }
 
636
      
 
637
      // look for useOnewayConnectionTimeout param
 
638
      val = params.get(USE_ONEWAY_CONNECTION_TIMEOUT);
 
639
      if (val != null)
 
640
      {
 
641
         try
 
642
         {
 
643
            useOnewayConnectionTimeout = Boolean.valueOf((String)val).booleanValue();
 
644
            log.debug(this + " setting useOnewayConnectionTimeout to " + useOnewayConnectionTimeout);
 
645
         }
 
646
         catch (Exception e)
 
647
         {
 
648
            log.warn(this + " could not convert " + USE_ONEWAY_CONNECTION_TIMEOUT + " value of " +
 
649
                     val + " to a boolean value");
 
650
         }
 
651
      }
 
652
      
 
653
      // look for writeTimeout param
 
654
      val = params.get(WRITE_TIMEOUT);
 
655
      if (val != null)
 
656
      {
 
657
         try
 
658
         {
 
659
            writeTimeout = Integer.valueOf((String)val).intValue();
 
660
            log.debug(this + " setting writeTimeout to " + writeTimeout);
 
661
         }
 
662
         catch (Exception e)
 
663
         {
 
664
            log.warn(this + " could not convert " + WRITE_TIMEOUT + " value of " +
 
665
                     val + " to an int value");
 
666
         }
 
667
      }
 
668
   }
 
669
 
 
670
   protected ServerAddress createServerAddress(InetAddress addr, int port)
 
671
   {
 
672
      return new ServerAddress(addr.getHostAddress(), port, enableTcpNoDelay, -1, maxPoolSize);
 
673
   }
 
674
 
 
675
   protected void finalize() throws Throwable
 
676
   {
 
677
      disconnect();
 
678
      super.finalize();
 
679
   }
 
680
 
 
681
   protected synchronized void handleConnect() throws ConnectionFailedException
 
682
   {
 
683
      initPool();
 
684
      
 
685
      if (InvokerLocator.MULTIHOME.equals(locator.getHost()))
 
686
      {
 
687
         home = getUsableAddress(locator);
 
688
         if (home == null)
 
689
         {
 
690
            throw new ConnectionFailedException(this + " unable to find a usable address for: " + home);
 
691
         }
 
692
         locator.setHomeInUse(home);
 
693
      }
 
694
      else
 
695
      {
 
696
         home = new Home(locator.getHost(), locator.getPort());
 
697
      }
 
698
   }
 
699
 
 
700
   protected Home getUsableAddress(InvokerLocator locator)
 
701
   {
 
702
      List homes = getConnectHomes();
 
703
      Iterator it = homes.iterator();
 
704
      Home home = null;
 
705
      
 
706
      while (it.hasNext())
 
707
      {
 
708
         try
 
709
         {
 
710
            home = (Home) it.next();
 
711
            addr = getAddressByName(home.host);
 
712
            address = createServerAddress(addr, home.port);
 
713
            invoke(new InvocationRequest(null, null, ServerInvoker.ECHO, null, null, null));
 
714
            if (trace) log.trace(this + " able to contact server at: " + home);
 
715
            return home;
 
716
         }
 
717
         catch (Throwable e)
 
718
         {
 
719
            log.debug(this + " unable to contact server at: " + home);
 
720
         }
 
721
      }
 
722
   
 
723
      return null;
 
724
   }
 
725
 
 
726
   protected synchronized void handleDisconnect()
 
727
   {
 
728
      clearPools();
 
729
      clearPool(pool);
 
730
   }
 
731
 
 
732
   /**
 
733
    * Each implementation of the remote client invoker should have a default data type that is used
 
734
    * in the case it is not specified in the invoker locator URI.
 
735
    */
 
736
   protected String getDefaultDataType()
 
737
   {
 
738
      return SerializableMarshaller.DATATYPE;
 
739
   }
 
740
 
 
741
   protected Object transport(String sessionID, Object invocation, Map metadata,
 
742
                              Marshaller marshaller, UnMarshaller unmarshaller)
 
743
         throws IOException, ConnectionFailedException, ClassNotFoundException
 
744
   {
 
745
      SocketWrapper socketWrapper = null;
 
746
      Object response = null;
 
747
      boolean oneway = false;
 
748
 
 
749
      // tempTimeout < 0 will indicate there is no per invocation timeout.
 
750
      int tempTimeout = -1;
 
751
      int timeLeft = -1;
 
752
      int savedTimeout = -1;
 
753
      long start = -1;
 
754
 
 
755
      if(metadata != null)
 
756
      {
 
757
         // check to see if is one way invocation and return after writing invocation if is
 
758
         Object val = metadata.get(org.jboss.remoting.Client.ONEWAY_FLAG);
 
759
         if(val != null && val instanceof String && Boolean.valueOf((String)val).booleanValue())
 
760
         {
 
761
            oneway = true;
 
762
         }
 
763
 
 
764
         // look for temporary timeout values
 
765
         String tempTimeoutString = (String) metadata.get(ServerInvoker.TIMEOUT);
 
766
         {
 
767
            if (tempTimeoutString != null)
 
768
            {
 
769
               try
 
770
               {
 
771
                  tempTimeout = Integer.valueOf(tempTimeoutString).intValue();
 
772
                  log.debug(this + " setting timeout to " + tempTimeout + " for this invocation");
 
773
               }
 
774
               catch (Exception e)
 
775
               {
 
776
                  log.warn(this + " could not convert " + ServerInvoker.TIMEOUT + " value of " +
 
777
                           tempTimeoutString + " to an integer value.");
 
778
               }
 
779
            }
 
780
         }
 
781
      }
 
782
      
 
783
      if (tempTimeout >= 0)
 
784
      {
 
785
         start = System.currentTimeMillis();
 
786
      }
 
787
 
 
788
      boolean serverSideOneway = false;
 
789
      if (oneway && invocation instanceof InvocationRequest)
 
790
      {
 
791
         InvocationRequest ir = (InvocationRequest) invocation;
 
792
         if (ir.getParameter() instanceof OnewayInvocation)
 
793
            serverSideOneway = true;
 
794
      }
 
795
      
 
796
      int retryCount = 0;
 
797
      Exception sockEx = null;
 
798
 
 
799
      for (; retryCount < numberOfCallRetries; retryCount++)
 
800
      {
 
801
         if (trace) log.trace(this + " retryCount: " + retryCount);
 
802
         if (0 < tempTimeout)
 
803
         {
 
804
            // If a per invocation timeout has been set, the time spent retrying
 
805
            // should count toward the elapsed time.
 
806
            timeLeft = (int) (tempTimeout - (System.currentTimeMillis() - start));
 
807
            if (timeLeft <= 0)
 
808
               break;
 
809
         }
 
810
 
 
811
         try
 
812
         {
 
813
            boolean tryPool = retryCount < (numberOfCallRetries - 1)
 
814
                                 || maxPoolSize == 1
 
815
                                 || numberOfCallRetries == 1;
 
816
            socketWrapper = getConnection(marshaller, unmarshaller, tryPool, timeLeft);
 
817
            log.trace(this + " got socketWrapper: " + socketWrapper);
 
818
         }
 
819
         catch (InterruptedException e)
 
820
         {
 
821
            semaphore.release();
 
822
            if (trace) log.trace(this + " released semaphore: " + semaphore.permits(), e);
 
823
            throw new RuntimeException(e);
 
824
         }
 
825
         catch (Exception e)
 
826
         {
 
827
//            if (bailOut)
 
828
//               return null;
 
829
            semaphore.release();
 
830
            if (trace) log.trace(this + " released semaphore: " + semaphore.permits(), e);
 
831
            sockEx =  new CannotConnectException(
 
832
                  "Can not get connection to server. Problem establishing " +
 
833
                  "socket connection for " + locator, e);
 
834
            continue;
 
835
         }
 
836
 
 
837
         if (tempTimeout >= 0)
 
838
         {
 
839
            timeLeft = (int) (tempTimeout - (System.currentTimeMillis() - start));
 
840
            if (timeLeft <= 0)
 
841
               break;
 
842
            savedTimeout = socketWrapper.getTimeout();            
 
843
            socketWrapper.setTimeout(timeLeft);
 
844
         }
 
845
 
 
846
         try
 
847
         {
 
848
            int version = getVersion();
 
849
            boolean performVersioning = Version.performVersioning(version);
 
850
 
 
851
            OutputStream outputStream = socketWrapper.getOutputStream();
 
852
            log.trace(this + "got outputStream: " + outputStream);
 
853
            if (performVersioning)
 
854
            {
 
855
               log.trace(this + " writing version");
 
856
               writeVersion(outputStream, version);
 
857
               log.trace(this + " wrote version");
 
858
            }
 
859
 
 
860
            //TODO: -TME so this is messed up as now ties remoting versioning to using a marshaller type
 
861
            versionedWrite(outputStream, marshaller, invocation, version);
 
862
 
 
863
            if (serverSideOneway)
 
864
            {
 
865
               if(trace) { log.trace(this + " sent oneway invocation, so not waiting for response, returning null"); }
 
866
            }
 
867
            else if (oneway)
 
868
            {
 
869
               if (performVersioning && useOnewayConnectionTimeout)
 
870
               {
 
871
                  int onewaySavedTimeout = socketWrapper.getTimeout();
 
872
                  socketWrapper.setTimeout(onewayConnectionTimeout);
 
873
                  InputStream inputStream = socketWrapper.getInputStream();
 
874
                  version = readVersion(inputStream);
 
875
                  if (version == -1)
 
876
                  {
 
877
                     throw new EOFException("end of file");
 
878
                  }
 
879
                  if (version == SocketWrapper.CLOSING)
 
880
                  {
 
881
                     log.trace(this + " received version 254: treating as end of file");
 
882
                     throw new EOFException("end of file");
 
883
                  }
 
884
 
 
885
                  // Note that if an exception is thrown, the socket is thrown away,
 
886
                  // so there's no need to reset the timeout value.
 
887
                  socketWrapper.setTimeout(onewaySavedTimeout);
 
888
               }
 
889
            }
 
890
            else
 
891
            {
 
892
               InputStream inputStream = socketWrapper.getInputStream();
 
893
               if (performVersioning)
 
894
               {
 
895
                  version = readVersion(inputStream);
 
896
                  if (version == -1)
 
897
                  {
 
898
                     throw new EOFException("end of file");
 
899
                  }
 
900
                  if (version == SocketWrapper.CLOSING)
 
901
                  {
 
902
                     log.trace(this + " received version 254: treating as end of file");
 
903
                     throw new EOFException("end of file");
 
904
                  }
 
905
               }
 
906
 
 
907
               response = versionedRead(inputStream, unmarshaller, version);
 
908
            }
 
909
 
 
910
            // Note that resetting the timeout value after closing the socket results
 
911
            // in an exception, so the reset is not done in a finally clause.  However,
 
912
            // if a catch clause is ever added that does not close the socket, care
 
913
            // must be taken to reset the timeout in that case.
 
914
            if (tempTimeout >= 0)
 
915
            {
 
916
               socketWrapper.setTimeout(savedTimeout);
 
917
            }
 
918
         }
 
919
         catch (SocketException sex)
 
920
         {
 
921
            handleRetriableException(socketWrapper, sex, retryCount);
 
922
            sockEx = sex;
 
923
            continue;
 
924
         }
 
925
         catch (EOFException ex)
 
926
         {
 
927
            handleRetriableException(socketWrapper, ex, retryCount);
 
928
            sockEx = ex;
 
929
            continue;
 
930
         }
 
931
         catch (IOException e)
 
932
         {
 
933
            if (isGeneralizeSocketException() && e.getMessage() != null && RETRIABLE_ERROR_MESSAGE.matcher(e.getMessage()).matches())
 
934
            {
 
935
               handleRetriableException(socketWrapper, e, retryCount);
 
936
               sockEx = new SocketException(e.getMessage());
 
937
               continue;
 
938
            }
 
939
            else
 
940
            {
 
941
               return handleOtherException(e, semaphore, socketWrapper, oneway);
 
942
            }
 
943
         }
 
944
         catch (Exception ex)
 
945
         {
 
946
            return handleOtherException(ex, semaphore, socketWrapper, oneway);
 
947
         }
 
948
 
 
949
         // call worked, so no need to retry
 
950
         break;
 
951
      }
 
952
 
 
953
      // need to check if ran out of retries
 
954
      if (retryCount >= numberOfCallRetries)
 
955
      {
 
956
         handleException(sockEx, socketWrapper);
 
957
      }
 
958
      
 
959
      if (response == null && tempTimeout > 0 && timeLeft <= 0)
 
960
      {
 
961
         if (sockEx == null)
 
962
         {
 
963
            sockEx =  new CannotConnectException(
 
964
                         "Can not get connection to server. Timed out establishing " +
 
965
                         "socket connection for " + locator);
 
966
         }
 
967
         handleException(sockEx, socketWrapper);
 
968
      }
 
969
 
 
970
      // Put socket back in pool for reuse
 
971
      synchronized (pool)
 
972
      {
 
973
         if (pool.size() < maxPoolSize)
 
974
         {
 
975
            pool.add(socketWrapper);
 
976
            if (trace) { log.trace(this + " returned " + socketWrapper + " to pool"); }
 
977
         }
 
978
         else
 
979
         {
 
980
            if (trace) { log.trace(this + "'s pool is full, will close the connection"); }
 
981
            try
 
982
            {
 
983
               socketWrapper.close();
 
984
            }
 
985
            catch (Exception ignored)
 
986
            {
 
987
            }
 
988
         }         
 
989
         semaphore.release();
 
990
         if (trace) log.trace(this + " released semaphore: " + semaphore.permits());
 
991
      }
 
992
 
 
993
      if (trace && !oneway) { log.trace(this + " received response " + response);  }
 
994
      return response;
 
995
   }
 
996
 
 
997
   protected Object handleException(Exception ex, SocketWrapper socketWrapper)
 
998
      throws ClassNotFoundException, InvocationFailureException
 
999
   {
 
1000
      if (ex instanceof ClassNotFoundException)
 
1001
      {
 
1002
         //TODO: -TME Add better exception handling for class not found exception
 
1003
         log.debug("Error loading classes from remote call result.", ex);
 
1004
         throw (ClassNotFoundException)ex;
 
1005
      }
 
1006
      
 
1007
      if (ex instanceof CannotConnectException)
 
1008
      {
 
1009
         log.debug(this, ex);
 
1010
         throw (CannotConnectException) ex;
 
1011
      }
 
1012
      
 
1013
      if (ex instanceof InterruptedException)
 
1014
      {
 
1015
         log.debug(this, ex);
 
1016
         throw new RuntimeException(ex);
 
1017
      }
 
1018
 
 
1019
      throw new InvocationFailureException("Unable to perform invocation", ex);
 
1020
   }
 
1021
   
 
1022
   protected void handleRetriableException(SocketWrapper socketWrapper, Exception e, int retryCount)
 
1023
   {
 
1024
      if (trace) log.trace(this + "(" + socketWrapper + ") got Exception: " + e);
 
1025
 
 
1026
      try
 
1027
      {
 
1028
         semaphore.release();
 
1029
         if (trace) log.trace(this + " released semaphore: " + semaphore.permits());
 
1030
         socketWrapper.close();            
 
1031
      }
 
1032
      catch (Exception ex)
 
1033
      {
 
1034
         if (trace) { log.trace(this + " couldn't successfully close its socketWrapper", ex); }
 
1035
      }
 
1036
 
 
1037
      /**
 
1038
       * About to run out of retries and
 
1039
       * pool may be full of timed out sockets,
 
1040
       * so want to flush the pool and try with
 
1041
       * fresh socket as a last effort.
 
1042
       */
 
1043
      if (retryCount == (numberOfCallRetries - 2))
 
1044
      {
 
1045
         flushConnectionPool();
 
1046
      }
 
1047
      
 
1048
      if (trace)
 
1049
      {
 
1050
         if (retryCount < (numberOfCallRetries - 1))
 
1051
         {
 
1052
            log.trace(this + " will try again, retries: " + retryCount + " < " + numberOfCallRetries);
 
1053
         }
 
1054
         else
 
1055
         {
 
1056
            log.trace(this + " retries exhausted");               
 
1057
         }
 
1058
      }
 
1059
   }
 
1060
 
 
1061
   protected Object handleOtherException(Exception ex, Semaphore semaphore, SocketWrapper socketWrapper, boolean oneway)
 
1062
   throws ClassNotFoundException, InvocationFailureException
 
1063
   {
 
1064
      log.debug(this + " got exception: " + socketWrapper, ex);
 
1065
 
 
1066
      try
 
1067
      {
 
1068
         semaphore.release();
 
1069
         if (trace) log.trace(this + " released semaphore: " + semaphore.permits());
 
1070
         socketWrapper.close();
 
1071
      }
 
1072
      catch (Exception ignored)
 
1073
      {
 
1074
      }
 
1075
      
 
1076
      if (oneway)
 
1077
         return null;
 
1078
      else
 
1079
         return handleException(ex, socketWrapper);
 
1080
   }
 
1081
   
 
1082
   protected void initPool()
 
1083
   {
 
1084
      synchronized (connectionPools)
 
1085
      {
 
1086
         pool = (LinkedList)connectionPools.get(address);
 
1087
         semaphore = (Semaphore)semaphores.get(address);
 
1088
         if (pool == null)
 
1089
         {
 
1090
            pool = new LinkedList();
 
1091
            connectionPools.put(address, pool);
 
1092
            log.debug("Creating semaphore with size " + maxPoolSize);
 
1093
            semaphore = new Semaphore(maxPoolSize);
 
1094
            semaphores.put(address, semaphore);
 
1095
            
 
1096
            if (trace)
 
1097
            {
 
1098
               synchronized (pool)
 
1099
               {
 
1100
                  log.trace(this + " added new pool (" + pool + ") as " + address);
 
1101
               }
 
1102
            }
 
1103
         }
 
1104
         else
 
1105
         {
 
1106
            if (trace)
 
1107
            {
 
1108
               synchronized (pool)
 
1109
               {
 
1110
                  log.trace(this + " using pool (" + pool + ") already defined for " + address);
 
1111
               }
 
1112
            }
 
1113
         }
 
1114
      }
 
1115
   }
 
1116
   
 
1117
   protected SocketWrapper getConnection(Marshaller marshaller,
 
1118
                                         UnMarshaller unmarshaller,
 
1119
                                         boolean tryPool, int timeAllowed)
 
1120
      throws Exception
 
1121
   {
 
1122
      long start = System.currentTimeMillis();
 
1123
      long timeToWait = (timeAllowed > 0) ? timeAllowed : connectionWait;
 
1124
      boolean timedout = !semaphore.attempt(timeToWait);
 
1125
      if (trace) log.trace(this + " obtained semaphore: " + semaphore.permits());
 
1126
      
 
1127
      if (timedout)
 
1128
      {
 
1129
         throw new IllegalStateException("Timeout waiting for a free socket");
 
1130
      }
 
1131
      
 
1132
      SocketWrapper pooled = null;
 
1133
 
 
1134
      if (tryPool)
 
1135
      {
 
1136
         synchronized (pool)
 
1137
         {
 
1138
            // if connection within pool, use it
 
1139
            if (pool.size() > 0)
 
1140
            {
 
1141
               pooled = getPooledConnection();
 
1142
               if (trace) log.trace(this + " reusing pooled connection: " + pooled);
 
1143
            }
 
1144
         }
 
1145
      }
 
1146
      else
 
1147
      {
 
1148
         if (trace) log.trace(this + " avoiding connection pool, creating new socket");
 
1149
      }
 
1150
 
 
1151
      if (pooled == null)
 
1152
      {
 
1153
         //Need to create a new one  
 
1154
         Socket socket = null;
 
1155
 
 
1156
         if (trace) { log.trace(this + " creating socket "); }
 
1157
 
 
1158
         // timeAllowed < 0 indicates no per invocation timeout has been set.
 
1159
         int timeRemaining = -1;
 
1160
         if (0 <= timeAllowed)
 
1161
         {
 
1162
            timeRemaining = (int) (timeAllowed - (System.currentTimeMillis() - start));
 
1163
         }
 
1164
         
 
1165
         socket = createSocket(address.address, address.port, timeRemaining);
 
1166
         if (trace) log.trace(this + " created socket: " + socket);
 
1167
 
 
1168
         socket.setTcpNoDelay(address.enableTcpNoDelay);
 
1169
 
 
1170
         Map metadata = getLocator().getParameters();
 
1171
         if (metadata == null)
 
1172
         {
 
1173
            metadata = new HashMap(2);
 
1174
         }
 
1175
         else
 
1176
         {
 
1177
            metadata = new HashMap(metadata);
 
1178
         }
 
1179
         metadata.put(SocketWrapper.MARSHALLER, marshaller);
 
1180
         metadata.put(SocketWrapper.UNMARSHALLER, unmarshaller);
 
1181
         if (writeTimeout > 0)
 
1182
         {
 
1183
            metadata.put(SocketWrapper.WRITE_TIMEOUT, new Integer(writeTimeout));
 
1184
         }
 
1185
         if (timeAllowed > 0)
 
1186
         {
 
1187
            timeRemaining = (int) (timeAllowed - (System.currentTimeMillis() - start));
 
1188
            
 
1189
            if (timeRemaining <= 0)
 
1190
               throw new IllegalStateException("Timeout creating a new socket");
 
1191
            
 
1192
            metadata.put(SocketWrapper.TEMP_TIMEOUT, new Integer(timeRemaining));
 
1193
         }
 
1194
         
 
1195
         pooled = createClientSocket(socket, address.timeout, metadata);
 
1196
      }
 
1197
 
 
1198
      return pooled;
 
1199
   }
 
1200
 
 
1201
   protected SocketWrapper createClientSocket(Socket socket, int timeout, Map metadata)
 
1202
      throws Exception
 
1203
   {
 
1204
      if (clientSocketConstructor == null)
 
1205
      {
 
1206
         if(clientSocketClass == null)
 
1207
         {
 
1208
            clientSocketClass = ClassLoaderUtility.loadClass(clientSocketClassName, getClass());
 
1209
         }
 
1210
 
 
1211
         Class[] args = new Class[]{Socket.class, Map.class, Integer.class};
 
1212
         clientSocketConstructor = clientSocketClass.getConstructor(args);
 
1213
      }
 
1214
 
 
1215
      SocketWrapper clientSocketWrapper = null;
 
1216
      clientSocketWrapper = (SocketWrapper)clientSocketConstructor.
 
1217
         newInstance(new Object[]{socket, metadata, new Integer(timeout)});
 
1218
 
 
1219
      return clientSocketWrapper;
 
1220
   }
 
1221
 
 
1222
   protected Socket createSocket(String address, int port, int timeout) throws IOException
 
1223
   {
 
1224
      Socket s = new Socket();
 
1225
      configureSocket(s);
 
1226
      InetSocketAddress inetAddr = new InetSocketAddress(address, port);
 
1227
      connect(s, inetAddr);
 
1228
      return s;
 
1229
   }
 
1230
   
 
1231
   protected void configureSocket(Socket s) throws SocketException
 
1232
   {
 
1233
      s.setReuseAddress(getReuseAddress());
 
1234
      
 
1235
      if (keepAliveSet)           s.setKeepAlive(keepAlive);
 
1236
      if (oOBInlineSet)           s.setOOBInline(oOBInline);
 
1237
      if (receiveBufferSize > -1) s.setReceiveBufferSize(receiveBufferSize);
 
1238
      if (sendBufferSize > -1)    s.setSendBufferSize(sendBufferSize);
 
1239
      if (soLingerSet && 
 
1240
            soLingerDuration > 0) s.setSoLinger(soLinger, soLingerDuration);
 
1241
      if (trafficClass > -1)      s.setTrafficClass(trafficClass);
 
1242
   }
 
1243
 
 
1244
   protected SocketWrapper getPooledConnection()
 
1245
   {
 
1246
      SocketWrapper socketWrapper = null;
 
1247
      while (pool.size() > 0)
 
1248
      {
 
1249
         socketWrapper = (SocketWrapper)pool.removeFirst();
 
1250
         try
 
1251
         {
 
1252
            if (socketWrapper != null)
 
1253
            {
 
1254
               if (socketWrapper instanceof OpenConnectionChecker)
 
1255
               {
 
1256
                  ((OpenConnectionChecker) socketWrapper).checkOpenConnection();
 
1257
               }
 
1258
               if (shouldCheckConnection)
 
1259
               {
 
1260
                  socketWrapper.checkConnection();
 
1261
                  return socketWrapper;
 
1262
               }
 
1263
               else
 
1264
               {
 
1265
                  return socketWrapper;
 
1266
               }
 
1267
            }
 
1268
         }
 
1269
         catch (Exception ex)
 
1270
         {
 
1271
            if (trace) { log.trace(this + " couldn't reuse connection from pool"); }
 
1272
            try
 
1273
            {
 
1274
               socketWrapper.close();
 
1275
            }
 
1276
            catch (Exception e)
 
1277
            {
 
1278
               log.debug("Failed to close socket wrapper", e);
 
1279
            }
 
1280
         }
 
1281
      }
 
1282
      return null;
 
1283
   }
 
1284
 
 
1285
   // Private --------------------------------------------------------------------------------------
 
1286
 
 
1287
   private Object versionedRead(InputStream inputStream, UnMarshaller unmarshaller, int version)
 
1288
      throws IOException, ClassNotFoundException
 
1289
   {
 
1290
      //TODO: -TME - is switch required?
 
1291
      switch (version)
 
1292
      {
 
1293
         case Version.VERSION_1:
 
1294
         case Version.VERSION_2:
 
1295
         case Version.VERSION_2_2:
 
1296
         {
 
1297
            if (trace) { log.trace(this + " reading response from unmarshaller"); }
 
1298
            if (unmarshaller instanceof VersionedUnMarshaller)
 
1299
               return((VersionedUnMarshaller)unmarshaller).read(inputStream, null, version);
 
1300
            else
 
1301
               return unmarshaller.read(inputStream, null);
 
1302
         }
 
1303
         default:
 
1304
         {
 
1305
            throw new IOException("Can not read data for version " + version + ". " +
 
1306
               "Supported versions: " + Version.VERSION_1 + ", " + Version.VERSION_2 + ", " + Version.VERSION_2_2);
 
1307
         }
 
1308
      }
 
1309
   }
 
1310
 
 
1311
   private void versionedWrite(OutputStream outputStream, Marshaller marshaller,
 
1312
                               Object invocation, int version) throws IOException
 
1313
   {
 
1314
      //TODO: -TME Should I worry about checking the version here?  Only one way to do it at this point
 
1315
      switch (version)
 
1316
      {
 
1317
         case Version.VERSION_1:
 
1318
         case Version.VERSION_2:
 
1319
         case Version.VERSION_2_2:
 
1320
         {
 
1321
            if (trace) { log.trace(this + " writing invocation to marshaller"); }
 
1322
            if (marshaller instanceof VersionedMarshaller)
 
1323
               ((VersionedMarshaller) marshaller).write(invocation, outputStream, version);
 
1324
            else
 
1325
               marshaller.write(invocation, outputStream);
 
1326
            if (trace) { log.trace(this + " done writing invocation to marshaller"); }
 
1327
 
 
1328
            return;
 
1329
         }
 
1330
         default:
 
1331
         {
 
1332
            throw new IOException("Can not write data for version " + version + ".  " +
 
1333
               "Supported versions: " + Version.VERSION_1 + ", " + Version.VERSION_2 + ", " + Version.VERSION_2_2);
 
1334
         }
 
1335
      }
 
1336
   }
 
1337
 
 
1338
   //TODO: -TME Exact same method in ServerThread
 
1339
   private int readVersion(InputStream inputStream) throws IOException
 
1340
   {
 
1341
      if (trace) { log.trace(this + " reading version from input stream"); }
 
1342
      int version = inputStream.read();
 
1343
      if (trace) { log.trace(this + " read version " + version + " from input stream"); }
 
1344
      return version;
 
1345
   }
 
1346
 
 
1347
   //TODO: -TME Exact same method in ServerThread
 
1348
   private void writeVersion(OutputStream outputStream, int version) throws IOException
 
1349
   {
 
1350
      if (trace) { log.trace(this + " writing version " + version + " on output stream"); }
 
1351
      outputStream.write(version);
 
1352
   }
 
1353
   
 
1354
   static private void mapJavaBeanProperties(final Object o, final Properties props, final boolean isStrict)
 
1355
   throws IntrospectionException
 
1356
   {
 
1357
      if (SecurityUtility.skipAccessControl())
 
1358
      {
 
1359
         PropertyEditors.mapJavaBeanProperties(o, props, isStrict);
 
1360
         return;
 
1361
      }
 
1362
 
 
1363
      try
 
1364
      {
 
1365
         AccessController.doPrivileged( new PrivilegedExceptionAction()
 
1366
         {
 
1367
            public Object run() throws IntrospectionException
 
1368
            {
 
1369
               PropertyEditors.mapJavaBeanProperties(o, props, isStrict);
 
1370
               return null;
 
1371
            }
 
1372
         });
 
1373
      }
 
1374
      catch (PrivilegedActionException e)
 
1375
      {
 
1376
         throw (IntrospectionException) e.getCause();
 
1377
      }
 
1378
   }
 
1379
   
 
1380
   static private void connect(final Socket socket, final InetSocketAddress address)
 
1381
   throws IOException
 
1382
   {
 
1383
      if (SecurityUtility.skipAccessControl())
 
1384
      {
 
1385
         socket.connect(address);
 
1386
         return;
 
1387
      }
 
1388
      
 
1389
      try
 
1390
      {
 
1391
         AccessController.doPrivileged( new PrivilegedExceptionAction()
 
1392
         {
 
1393
            public Object run() throws Exception
 
1394
            {
 
1395
               socket.connect(address);
 
1396
               return null;
 
1397
            }
 
1398
         });
 
1399
      }
 
1400
      catch (PrivilegedActionException e)
 
1401
      {
 
1402
         throw (IOException) e.getCause();
 
1403
      }   
 
1404
   }
 
1405
   
 
1406
   static private InetAddress getAddressByName(final String host) throws UnknownHostException
 
1407
   {
 
1408
      if (SecurityUtility.skipAccessControl())
 
1409
      {
 
1410
         return InetAddress.getByName(host);
 
1411
      }
 
1412
      
 
1413
      try
 
1414
      {
 
1415
         return (InetAddress)AccessController.doPrivileged( new PrivilegedExceptionAction()
 
1416
         {
 
1417
            public Object run() throws IOException
 
1418
            {
 
1419
               return InetAddress.getByName(host);
 
1420
            }
 
1421
         });
 
1422
      }
 
1423
      catch (PrivilegedActionException e)
 
1424
      {
 
1425
         throw (UnknownHostException) e.getCause();
 
1426
      }
 
1427
   }
 
1428
   // Inner classes --------------------------------------------------------------------------------
 
1429
 
 
1430
}