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

« back to all changes in this revision

Viewing changes to src/org/jboss/remoting/InvokerLocator.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
 
/*
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;
24
 
 
25
 
import java.io.Serializable;
26
 
import java.net.InetAddress;
27
 
import java.net.MalformedURLException;
28
 
import java.net.URI;
29
 
import java.net.URISyntaxException;
30
 
import java.net.UnknownHostException;
31
 
import java.security.AccessController;
32
 
import java.security.PrivilegedActionException;
33
 
import java.security.PrivilegedExceptionAction;
34
 
import java.util.ArrayList;
35
 
import java.util.Collection;
36
 
import java.util.Iterator;
37
 
import java.util.List;
38
 
import java.util.Map;
39
 
import java.util.StringTokenizer;
40
 
import java.util.TreeMap;
41
 
 
42
 
import org.jboss.logging.Logger;
43
 
import org.jboss.remoting.serialization.SerializationStreamFactory;
44
 
import org.jboss.remoting.transport.ClientInvoker;
45
 
import org.jboss.remoting.util.SecurityUtility;
46
 
 
47
 
/**
48
 
 * InvokerLocator is an object that indentifies a specific Invoker on the network, via a unique
49
 
 * locator URI. The locator URI is in the format: <P>
50
 
 * <p/>
51
 
 * <tt>protocol://host[:port][/path[?param=value&param2=value2]]</tt>     <P>
52
 
 * <p/>
53
 
 * For example, a http based locator might be: <P>
54
 
 * <p/>
55
 
 * <tt>http://192.168.10.1:8081</tt>  <P>
56
 
 * <p/>
57
 
 * An example Socket based locator might be: <P>
58
 
 * <p/>
59
 
 * <tt>socket://192.168.10.1:9999</tt>  <P>
60
 
 * <p/>
61
 
 * An example RMI based locator might be: <P>
62
 
 * <p/>
63
 
 * <tt>rmi://localhost</tt>  <P>
64
 
 * <p/>
65
 
 * NOTE: If no hostname is given (e.g., "socket://:5555"), then the hostname will
66
 
 * automatically be resolved to the outside IP address of the local machine.  
67
 
 * If the given hostname is 0.0.0.0 and the system
68
 
 * property "jboss.bind.address" is set, then the hostname will be replaced by the value
69
 
 * associated with 'jboss.bind.address".
70
 
 *
71
 
 * @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
72
 
 * @author <a href="mailto:telrod@e2technologies.net">Tom Elrod</a>
73
 
 * @version $Revision: 4993 $
74
 
 */
75
 
public class InvokerLocator implements Serializable
76
 
{
77
 
   static final long serialVersionUID;
78
 
   protected static Logger log = Logger.getLogger(InvokerLocator.class); 
79
 
   protected static Boolean legacyParsingFlag;
80
 
 
81
 
   protected String protocol;
82
 
   protected String host;
83
 
   protected ArrayList connectHomes = new ArrayList();
84
 
   protected ArrayList homes = new ArrayList();
85
 
   protected int port;
86
 
   protected String path;
87
 
   protected String query;
88
 
   protected Map parameters;
89
 
   private String uri;
90
 
   private String originalURL;
91
 
   private Home homeInUse;
92
 
 
93
 
 
94
 
   static
95
 
   {
96
 
      if(Version.getDefaultVersion() == Version.VERSION_1)
97
 
      {
98
 
         serialVersionUID = -2909329895029296248L;
99
 
      }
100
 
      else
101
 
      {
102
 
         serialVersionUID = -4977622166779282521L;
103
 
      }
104
 
   }
105
 
   
106
 
   public static boolean getUseLegacyParsing()
107
 
   {
108
 
      if (legacyParsingFlag == null)
109
 
         return false;
110
 
      return legacyParsingFlag.booleanValue();
111
 
   }
112
 
   
113
 
   public static void setUseLegacyParsing(boolean flag)
114
 
   {
115
 
      legacyParsingFlag = new Boolean(flag);
116
 
   }
117
 
 
118
 
   /**
119
 
    * Indicates should address binding to all network interfaces (i.e. 0.0.0.0)
120
 
    */
121
 
   public static final String ANY = "0.0.0.0";
122
 
   /**
123
 
    * Constant value for server bind address system property.  Value is 'jboss.bind.address'.
124
 
    */
125
 
   private static final String SERVER_BIND_ADDRESS = "jboss.bind.address";
126
 
 
127
 
   /**
128
 
    * Public key to use when want to specify that locator look up local address by
129
 
    * IP or host name.
130
 
    */
131
 
   public static final String BIND_BY_HOST = "remoting.bind_by_host";
132
 
 
133
 
 
134
 
   /**
135
 
    * Constant to define the param name to be used when defining the data type.
136
 
    */
137
 
   public static final String DATATYPE = "datatype";
138
 
   public static final String DATATYPE_CASED = "dataType";
139
 
 
140
 
   /**
141
 
    * Constant to define the param name to be used when defining the serialization type.
142
 
    */
143
 
   public static final String SERIALIZATIONTYPE = "serializationtype";
144
 
   public static final String SERIALIZATIONTYPE_CASED = "serializationType";
145
 
 
146
 
   /**
147
 
    * Constant to define the param name to be used when defining the marshaller fully qualified classname
148
 
    */
149
 
   public static final String MARSHALLER = "marshaller";
150
 
   /**
151
 
    * Constant to define the param name to be used when defining the unmarshaller fully qualified classname
152
 
    */
153
 
   public static final String UNMARSHALLER = "unmarshaller";
154
 
 
155
 
   /**
156
 
    * Constant to define what port the marshalling loader port resides on.
157
 
    */
158
 
   public static final String LOADER_PORT = "loaderport";
159
 
 
160
 
   /**
161
 
    * Constant to define the param name to be used when defining if marshalling should be by value,
162
 
    * which means will be using local client invoker with cloning of payload value.
163
 
    */
164
 
   public static final String BYVALUE = "byvalue";
165
 
 
166
 
   /**
167
 
    * Constant to define the param name to be used when defining if marshalling should use
168
 
    * remote client invoker instead of using local client invoker (even though both client and
169
 
    * server invokers are within same JVM).
170
 
    */
171
 
   public static final String FORCE_REMOTE = "force_remote";   
172
 
 
173
 
   /**
174
 
    * Constant to define if client should try to automatically establish a
175
 
    * lease with the server.  Value for this parameter key should be either 'true' or 'false'.
176
 
    */
177
 
   public static final String CLIENT_LEASE = "leasing";
178
 
 
179
 
   /**
180
 
    * Constant to define what the client lease period should be in the case that
181
 
    * server side leasing is turned on.  Value for this parameter key should be the number
182
 
    * of milliseconds to wait before each client lease renewal and must be greater than zero
183
 
    * in order to be recognized.
184
 
    */
185
 
   public static final String CLIENT_LEASE_PERIOD = "lease_period";
186
 
 
187
 
   
188
 
   /**
189
 
    * Constant to define if InvokerLocator should use the old (ad hoc) parsing
190
 
    * algorithm instead of the new, URI based, parsing algorithm.
191
 
    */
192
 
   public static final String LEGACY_PARSING = "legacyParsing";
193
 
   
194
 
   /**
195
 
    * Serves as placeholder in host position when multiple hosts are given in the
196
 
    * query part by way of the parameter "hosts".  E.g.
197
 
    * <p>
198
 
    * socket://multihome:8888/?hosts=host1.jboss.org:host2.jboss.org
199
 
    */
200
 
   public static final String MULTIHOME = "multihome";
201
 
   
202
 
   /**
203
 
    * Parameter key used for specifying multiple homes to connect to.  E.g.
204
 
    * <p>
205
 
    * socket://multihome/?connecthomes=host1.jboss.org:7777!host2.jboss.org:8888
206
 
    */
207
 
   public static final String CONNECT_HOMES_KEY = "connecthomes";
208
 
   
209
 
   /**
210
 
    * Parameter key used for specifying multiple binding homes.  E.g.
211
 
    * <p>
212
 
    * socket://multihome/?homes=a.org:66!b.org:77&homes=c.org:88!d.org:99
213
 
    */
214
 
   public static final String HOMES_KEY = "homes";
215
 
   
216
 
   /**
217
 
    * Parameter key used for specifying default connecting port for
218
 
    * multihome InvokerLocator.
219
 
    */
220
 
   public static final String DEFAULT_CONNECT_PORT = "defaultConnectPort";
221
 
   
222
 
   /**
223
 
    * Parameter key used for specifying default server bind port for
224
 
    * multihme InvokerLocator.
225
 
    */
226
 
   public static final String DEFAULT_PORT = "defaultPort";
227
 
   
228
 
   
229
 
   /**
230
 
    * InvokerLocator leaves address 0.0.0.0 unchanged.  Once serverBindAddress has been
231
 
    * extracted from the InvokerLocator, it is necessary to transform 0.0.0.0 into an
232
 
    * address that contacted over the network.  See JBREM-687.
233
 
    */
234
 
   public static InvokerLocator validateLocator(InvokerLocator locator) throws MalformedURLException
235
 
   {
236
 
      InvokerLocator externalLocator = locator;
237
 
 
238
 
      String host = locator.getHost();
239
 
      String newHost = null;
240
 
      if(host == null || InvokerLocator.ANY.equals(host))
241
 
      {
242
 
         // now need to get some external bindable address
243
 
         try
244
 
         {
245
 
            newHost = (String)AccessController.doPrivileged( new PrivilegedExceptionAction()
246
 
            {
247
 
               public Object run() throws Exception
248
 
               {
249
 
                  String bindByHost = System.getProperty(InvokerLocator.BIND_BY_HOST, "True");
250
 
                  boolean byHost = Boolean.valueOf(bindByHost).booleanValue();
251
 
                  if(byHost)
252
 
                  {
253
 
                     return InetAddress.getLocalHost().getHostName();
254
 
                  }
255
 
                  else
256
 
                  {
257
 
                     return InetAddress.getLocalHost().getHostAddress();
258
 
                  }
259
 
               }
260
 
            });
261
 
         }
262
 
         catch (PrivilegedActionException e)
263
 
         {
264
 
            log.debug("Could not get host by name or address.", e.getCause());
265
 
         }
266
 
 
267
 
         if(newHost == null)
268
 
         {
269
 
            // now what?  step through network interfaces?
270
 
            throw new RuntimeException("Can not determine bindable address for locator (" + locator + ")");
271
 
         }
272
 
         
273
 
         externalLocator = new InvokerLocator(locator.protocol, newHost, locator.port,
274
 
                                              locator.getPath(), locator.getParameters());
275
 
      }
276
 
 
277
 
      return externalLocator;
278
 
   }
279
 
   
280
 
   
281
 
   public static void extractHomes(String homeList, List list, int defaultPort)
282
 
   {
283
 
      StringTokenizer tok = new StringTokenizer(homeList, "!");  
284
 
      while(tok.hasMoreTokens())
285
 
      {
286
 
         String h = null;
287
 
         int p = -1;
288
 
         String token = tok.nextToken();
289
 
         boolean isIPv6 = token.indexOf('[') >= 0;
290
 
         int boundary;
291
 
 
292
 
         if (isIPv6)
293
 
         {
294
 
            int pos = token.indexOf(']');
295
 
            if (pos + 1 == token.length())
296
 
               boundary = -1;
297
 
            else
298
 
               boundary = token.indexOf(']') + 1;
299
 
            
300
 
         }
301
 
         else
302
 
         {
303
 
            boundary = token.lastIndexOf(':');
304
 
         }
305
 
 
306
 
         if (boundary > -1)
307
 
         {
308
 
            h = token.substring(0, boundary);
309
 
 
310
 
            try
311
 
            {
312
 
               p = Integer.valueOf(token.substring(boundary + 1)).intValue();
313
 
            }
314
 
            catch (NumberFormatException  e)
315
 
            {
316
 
               log.warn("invalid port value: " + token.substring(boundary + 1));
317
 
            }
318
 
         }
319
 
         else
320
 
         {
321
 
            h = token;
322
 
         }
323
 
 
324
 
         if (p == -1)
325
 
            p = defaultPort;
326
 
 
327
 
         list.add(new Home(h, p));
328
 
      }
329
 
   }
330
 
   
331
 
   
332
 
   public static String convertHomesListToString(List homes)
333
 
   {
334
 
      if (homes == null || homes.size() == 0)
335
 
         return "";
336
 
      
337
 
      Iterator it = homes.iterator();
338
 
      StringBuffer b = new StringBuffer(((Home) it.next()).toString());
339
 
      while (it.hasNext())
340
 
      {
341
 
         b.append("!").append(it.next());
342
 
      }
343
 
      return b.toString();
344
 
   }
345
 
   
346
 
   
347
 
   /**
348
 
    * Constructs the object used to identify a remoting server via simple uri format string (e.g. socket://myhost:7000).
349
 
    * Note: the uri passed may not always be the one returned via call to getLocatorURI() as may need to change if
350
 
    * port not specified, host is 0.0.0.0, etc.  If need original uri that is passed to this constructor, need to
351
 
    * call getOriginalURI().
352
 
    * @param uri
353
 
    * @throws MalformedURLException
354
 
    */
355
 
   public InvokerLocator(String uri)
356
 
         throws MalformedURLException
357
 
   {
358
 
      originalURL = uri;
359
 
      parse(originalURL);
360
 
   }
361
 
   
362
 
   
363
 
   private void parse(String uriString) throws MalformedURLException
364
 
   {
365
 
      boolean doLegacyParsing = false;
366
 
      if (legacyParsingFlag != null)
367
 
      {
368
 
         doLegacyParsing = legacyParsingFlag.booleanValue();
369
 
      }
370
 
      else 
371
 
      {
372
 
         String s = getSystemProperty(LEGACY_PARSING);
373
 
         doLegacyParsing = "true".equalsIgnoreCase(s);
374
 
      }
375
 
 
376
 
      if (doLegacyParsing)
377
 
      {
378
 
         log.warn("using deprecated legacy URL parsing routine");
379
 
         legacyParse(uriString);
380
 
      }
381
 
      else
382
 
      {
383
 
         URIParse(uriString);
384
 
      }
385
 
      
386
 
      if (query != null)
387
 
      {
388
 
         StringTokenizer tok = new StringTokenizer(query, "&");
389
 
         parameters = new TreeMap();
390
 
         while(tok.hasMoreTokens())
391
 
         {
392
 
            String token = tok.nextToken();
393
 
            int eq = token.indexOf("=");
394
 
            String name = (eq > -1) ? token.substring(0, eq) : token;
395
 
            String value = (eq > -1) ? token.substring(eq + 1) : "";
396
 
            parameters.put(name, value);
397
 
         }
398
 
      }
399
 
 
400
 
      if (!MULTIHOME.equals(host) && parameters != null)
401
 
      {
402
 
         // Use "host:port" to connect.
403
 
         String s = (String) parameters.remove(CONNECT_HOMES_KEY);
404
 
         if (s != null) log.warn("host != " + MULTIHOME + ": " + CONNECT_HOMES_KEY + " will be ignored");
405
 
      }
406
 
 
407
 
      if (parameters != null)
408
 
      {
409
 
         String homesString = (String) parameters.remove(HOMES_KEY);
410
 
         String connectHomesString = (String) parameters.remove(CONNECT_HOMES_KEY);
411
 
         createHomeLists(parameters, homesString, connectHomesString);
412
 
      }
413
 
 
414
 
//    rebuild it, since the host probably got resolved and the port changed
415
 
      rebuildLocatorURI();
416
 
      
417
 
      if (!MULTIHOME.equals(host))
418
 
      {
419
 
         homeInUse = new Home(host, port);
420
 
         connectHomes.add(homeInUse);
421
 
         if (homes.isEmpty())
422
 
            homes.add(homeInUse);
423
 
      }
424
 
   }
425
 
 
426
 
   private void URIParse(String uriString) throws MalformedURLException
427
 
   {
428
 
      try
429
 
      {
430
 
         URI uri = new URI(encodePercent(uriString));
431
 
         protocol = uri.getScheme();
432
 
         host = decodePercent(resolveHost(uri.getHost()));
433
 
         port = uri.getPort();
434
 
         path = uri.getPath();
435
 
         query = decodePercent(uri.getQuery());
436
 
      }
437
 
      catch (URISyntaxException e)
438
 
      {
439
 
         throw new MalformedURLException(e.getMessage());
440
 
      }
441
 
   }
442
 
   
443
 
   private void legacyParse(String uri) throws MalformedURLException
444
 
   {
445
 
      log.warn("Legacy InvokerLocator parsing is deprecated");
446
 
      int i = uri.indexOf("://");
447
 
      if(i < 0)
448
 
      {
449
 
         throw new MalformedURLException("Invalid url " + uri);
450
 
      }
451
 
      String tmp = uri.substring(i + 3);
452
 
      this.protocol = uri.substring(0, i);
453
 
      i = tmp.indexOf("/");
454
 
      int p = tmp.indexOf(":");
455
 
      if(i != -1)
456
 
      {
457
 
         p = (p < i ? p : -1);
458
 
      }
459
 
      if(p != -1)
460
 
      {
461
 
         host = resolveHost(tmp.substring(0, p).trim());
462
 
         if(i > -1)
463
 
         {
464
 
            port = Integer.parseInt(tmp.substring(p + 1, i));
465
 
         }
466
 
         else
467
 
         {
468
 
            port = Integer.parseInt(tmp.substring(p + 1));
469
 
         }
470
 
      }
471
 
      else
472
 
      {
473
 
         if(i > -1)
474
 
         {
475
 
            host = resolveHost(tmp.substring(0, i).trim());
476
 
         }
477
 
         else
478
 
         {
479
 
            host = resolveHost(tmp.substring(0).trim());
480
 
         }
481
 
         port = -1;
482
 
      }
483
 
 
484
 
      // now look for any path
485
 
      p = tmp.indexOf("?");
486
 
      if(p != -1)
487
 
      {
488
 
         path = tmp.substring(i + 1, p);
489
 
         query = tmp.substring(p + 1);
490
 
      }
491
 
      else
492
 
      {
493
 
         p = tmp.indexOf("/");
494
 
         if(p != -1)
495
 
         {
496
 
            path = tmp.substring(p + 1);
497
 
         }
498
 
         else
499
 
         {
500
 
            path = "";
501
 
         }
502
 
         query = null;
503
 
      }
504
 
   }
505
 
 
506
 
   private static final String resolveHost(String host)
507
 
   {
508
 
      if (host == null)
509
 
      {
510
 
         host = fixRemoteAddress(host);
511
 
      }
512
 
      else if(host.indexOf("0.0.0.0") != -1)
513
 
      {
514
 
         String bindAddress = getSystemProperty(SERVER_BIND_ADDRESS, "0.0.0.0");         
515
 
         if(bindAddress.equals("0.0.0.0"))
516
 
         {
517
 
            host = fixRemoteAddress(host);
518
 
         }
519
 
         else
520
 
         {
521
 
            host = host.replaceAll("0\\.0\\.0\\.0", getSystemProperty(SERVER_BIND_ADDRESS));
522
 
         }
523
 
      }
524
 
      return host;
525
 
   }
526
 
 
527
 
   private static String fixRemoteAddress(String address)
528
 
   {
529
 
      if(address == null)
530
 
      {
531
 
         try
532
 
         {
533
 
            address = (String)AccessController.doPrivileged( new PrivilegedExceptionAction()
534
 
            {
535
 
               public Object run() throws UnknownHostException
536
 
               {
537
 
                  String bindByHost = System.getProperty(BIND_BY_HOST, "True");
538
 
                  boolean byHost = Boolean.valueOf(bindByHost).booleanValue();
539
 
 
540
 
                  if(byHost)
541
 
                  {
542
 
                     return InetAddress.getLocalHost().getHostName();
543
 
                  }
544
 
                  else
545
 
                  {
546
 
                     return InetAddress.getLocalHost().getHostAddress();
547
 
                  }
548
 
               }
549
 
            });
550
 
         }
551
 
         catch (PrivilegedActionException e)
552
 
         {
553
 
            log.debug("error", e.getCause());
554
 
         }
555
 
      }
556
 
 
557
 
      return address;
558
 
   }
559
 
  
560
 
 
561
 
   private void createHomeLists(Map parameters, String homesString, String connectHomesString)
562
 
   {
563
 
      // DEFAULT_PORT value takes precedence, followed by port value.
564
 
      int defaultPort = port; 
565
 
      String s = (String) parameters.get(DEFAULT_PORT);
566
 
      if (s != null && s != "")
567
 
      {
568
 
         try
569
 
         {
570
 
            defaultPort = Integer.parseInt(s);
571
 
         }
572
 
         catch (Exception e)
573
 
         {
574
 
            log.warn("invalid value for " + DEFAULT_PORT + ": " + s);
575
 
         }
576
 
      }
577
 
      
578
 
      if (homesString != null)
579
 
      {
580
 
         extractHomes(homesString, homes, defaultPort);
581
 
      }
582
 
      
583
 
      // DEFAULT_CONNECT_PORT value takes precedence, followed by 
584
 
      // DEFAULT_PORT value and then port value.
585
 
      s = (String) parameters.get(DEFAULT_CONNECT_PORT);
586
 
      if (s != null && s != "")
587
 
      {
588
 
         try
589
 
         {
590
 
            defaultPort = Integer.parseInt(s);
591
 
         }
592
 
         catch (Exception e)
593
 
         {
594
 
            log.warn("invalid value for " + DEFAULT_CONNECT_PORT + ": " + s);
595
 
         }
596
 
      }
597
 
 
598
 
      if (connectHomesString != null)
599
 
      {
600
 
         extractHomes(connectHomesString, connectHomes, defaultPort);
601
 
      }
602
 
   }
603
 
   
604
 
   
605
 
   /**
606
 
    * Constructs the object used to identify a remoting server.
607
 
    * @param protocol
608
 
    * @param host
609
 
    * @param port
610
 
    * @param path
611
 
    * @param parameters
612
 
    */
613
 
   public InvokerLocator(String protocol, String host, int port, String path, Map parameters)
614
 
   {
615
 
      this.protocol = protocol;
616
 
      this.host = resolveHost(host);
617
 
      this.port = port;
618
 
      this.path = path == null ? "" : path;
619
 
      this.parameters = parameters == null ? new TreeMap() : new TreeMap(parameters);
620
 
     
621
 
      if (this.parameters != null)
622
 
      {
623
 
         String homesString = (String) this.parameters.remove(HOMES_KEY);
624
 
         String connectHomesString = (String) this.parameters.remove(CONNECT_HOMES_KEY);
625
 
         createHomeLists(this.parameters, homesString, connectHomesString);
626
 
      }
627
 
      
628
 
      rebuildLocatorURI();
629
 
      originalURL = uri;
630
 
      
631
 
      if (!MULTIHOME.equals(host))
632
 
      {
633
 
         homeInUse = new Home(host, port);
634
 
         homes.add(homeInUse);
635
 
         connectHomes.add(homeInUse);
636
 
 
637
 
         if (parameters != null)
638
 
         {
639
 
            // Use "host:port" to connect.
640
 
            String s = (String) parameters.remove(CONNECT_HOMES_KEY);
641
 
            if (s != null) log.warn("host != " + MULTIHOME + ": " + CONNECT_HOMES_KEY + " will be ignored");
642
 
         }
643
 
      }
644
 
   }
645
 
 
646
 
   public int hashCode()
647
 
   {
648
 
      return uri.hashCode();
649
 
   }
650
 
 
651
 
   /**
652
 
    * Compares to see if Object passed is of type InvokerLocator and
653
 
    * it's internal locator uri hashcode is same as this one.  Note, this
654
 
    * means is testing to see if not only the host, protocol, and port are the
655
 
    * same, but the path and parameters as well.  Therefore 'socket://localhost:9000'
656
 
    * and 'socket://localhost:9000/foobar' would NOT be considered equal.
657
 
    * @param obj
658
 
    * @return
659
 
    */
660
 
   public boolean equals(Object obj)
661
 
   {
662
 
      return obj != null && obj instanceof InvokerLocator && uri.equals(((InvokerLocator)obj).getLocatorURI());
663
 
   }
664
 
 
665
 
   /**
666
 
    * Compares to see if InvokerLocator passed represents the same physical remoting server
667
 
    * endpoint as this one.  Unlike the equals() method, this just tests to see if protocol, host,
668
 
    * and port are the same and ignores the path and parameters.
669
 
    * @param compareMe
670
 
    * @return
671
 
    */
672
 
   public boolean isSameEndpoint(InvokerLocator compareMe)
673
 
   {
674
 
      return compareMe != null && getProtocol().equalsIgnoreCase(compareMe.getProtocol()) &&
675
 
             getHost().equalsIgnoreCase(compareMe.getHost()) && getPort() == compareMe.getPort();
676
 
   }
677
 
   
678
 
   public boolean isCompatibleWith(InvokerLocator other)
679
 
   {
680
 
      if (other == null)
681
 
         return false;
682
 
      
683
 
      // If this or other comes from pre-2.4.0 Remoting.
684
 
      if (homes == null || other.homes == null)
685
 
         return false;
686
 
      
687
 
      boolean result1 = getProtocol().equalsIgnoreCase(other.getProtocol()) &&
688
 
                        path.equals(other.getPath()) &&
689
 
                        parameters.equals(other.getParameters());
690
 
      
691
 
      ArrayList tempHomes = connectHomes.isEmpty() ? homes : connectHomes;
692
 
      boolean result2 = intersects(tempHomes, other.getConnectHomeList()) || 
693
 
                        intersects(tempHomes, other.getHomeList());
694
 
      
695
 
      return result1 && result2;
696
 
   }
697
 
 
698
 
   /**
699
 
    * return the locator URI, in the format: <P>
700
 
    * <p/>
701
 
    * <tt>protocol://host[:port][/path[?param=value&param2=value2]]</tt>
702
 
    * Note, this may not be the same as the original uri passed as parameter to the constructor.
703
 
    * @return
704
 
    */
705
 
   public String getLocatorURI()
706
 
   {
707
 
      return uri;
708
 
   }
709
 
 
710
 
   public String getProtocol()
711
 
   {
712
 
      return protocol;
713
 
   }
714
 
 
715
 
   public String getHost()
716
 
   {
717
 
      if (host.equals(MULTIHOME) && homeInUse != null)
718
 
         return homeInUse.host;
719
 
      
720
 
      return host;
721
 
   }
722
 
   
723
 
   public String getActualHost()
724
 
   {
725
 
      return host;
726
 
   }
727
 
   
728
 
   public boolean isMultihome()
729
 
   {
730
 
      return MULTIHOME.equals(host);
731
 
   }
732
 
   
733
 
   public String getConnectHomes()
734
 
   {
735
 
      return convertHomesListToString(connectHomes);
736
 
   }
737
 
   
738
 
   public List getConnectHomeList()
739
 
   {
740
 
      if (connectHomes == null)
741
 
      {
742
 
         ArrayList list = new ArrayList();
743
 
         list.add(new Home(host, port));
744
 
         return list;
745
 
      }
746
 
      
747
 
      return new ArrayList(connectHomes);
748
 
   }
749
 
   
750
 
   public void setConnectHomeList(List connectHomes)
751
 
   {
752
 
      if (connectHomes == null)
753
 
         this.connectHomes = new ArrayList();
754
 
      else
755
 
         this.connectHomes = new ArrayList(connectHomes);
756
 
      
757
 
      rebuildLocatorURI();
758
 
   }
759
 
   
760
 
   public Home getHomeInUse()
761
 
   {
762
 
      if (homeInUse != null || isMultihome())
763
 
         return homeInUse;
764
 
      
765
 
      return new Home(host, port);
766
 
   }
767
 
   
768
 
   public void setHomeInUse(Home homeInUse)
769
 
   {
770
 
      this.homeInUse = homeInUse;
771
 
   }
772
 
   
773
 
   public String getHomes()
774
 
   {  
775
 
      return convertHomesListToString(homes);
776
 
   }
777
 
   
778
 
   public List getHomeList()
779
 
   {
780
 
      if (homes == null)
781
 
      {
782
 
         ArrayList list = new ArrayList();
783
 
         list.add(new Home(host, port));
784
 
         return new ArrayList();
785
 
      }
786
 
      
787
 
      return new ArrayList(homes);
788
 
   }
789
 
 
790
 
   public void setHomeList(List homes)
791
 
   {
792
 
      if (homes == null)
793
 
         this.homes = new ArrayList();
794
 
      else
795
 
         this.homes = new ArrayList(homes);
796
 
      
797
 
      rebuildLocatorURI();
798
 
   }
799
 
   
800
 
   public int getPort()
801
 
   {
802
 
      if (host.equals(MULTIHOME) && homeInUse != null)
803
 
         return homeInUse.port;
804
 
      
805
 
      return port;
806
 
   }
807
 
   
808
 
   public int getActualPort()
809
 
   {
810
 
      return port;
811
 
   }
812
 
 
813
 
   public String getPath()
814
 
   {
815
 
      return path;
816
 
   }
817
 
 
818
 
   public Map getParameters()
819
 
   {
820
 
      if (parameters == null)
821
 
      {
822
 
         parameters = new TreeMap();
823
 
      }
824
 
      return parameters;
825
 
   }
826
 
 
827
 
   public String toString()
828
 
   {
829
 
      return "InvokerLocator [" + uri + "]";
830
 
   }
831
 
 
832
 
   /**
833
 
    * Gets the original uri passed to constructor (if there was one).
834
 
    * @return
835
 
    */
836
 
   public String getOriginalURI()
837
 
   {
838
 
      return originalURL;
839
 
   }
840
 
 
841
 
   /**
842
 
    * narrow this invoker to a specific RemoteClientInvoker instance
843
 
    *
844
 
    * @return
845
 
    * @throws Exception
846
 
    */
847
 
   public ClientInvoker narrow() throws Exception
848
 
   {
849
 
      return InvokerRegistry.createClientInvoker(this);
850
 
   }
851
 
 
852
 
 
853
 
   public String findSerializationType()
854
 
   {
855
 
      String serializationTypeLocal = SerializationStreamFactory.JAVA;
856
 
      if(parameters != null)
857
 
      {
858
 
         serializationTypeLocal = (String) parameters.get(SERIALIZATIONTYPE);
859
 
         if(serializationTypeLocal == null)
860
 
         {
861
 
            serializationTypeLocal = (String) parameters.get(InvokerLocator.SERIALIZATIONTYPE_CASED);
862
 
            if(serializationTypeLocal == null)
863
 
            {
864
 
               serializationTypeLocal = SerializationStreamFactory.JAVA;
865
 
            }
866
 
         }
867
 
      }
868
 
 
869
 
      return serializationTypeLocal;
870
 
   }
871
 
 
872
 
   protected boolean intersects(Collection c1, Collection c2)
873
 
   {
874
 
      Iterator it = c1.iterator();
875
 
      while (it.hasNext())
876
 
      {
877
 
         if (c2.contains(it.next()))
878
 
            return true;
879
 
      }
880
 
      return false;
881
 
   }
882
 
   
883
 
   protected void rebuildLocatorURI()
884
 
   {  
885
 
      String portPart = (port > -1) ? (":" + port) : "";
886
 
      String divider = path.startsWith("/") ? "" : "/";
887
 
      String parametersPart = (parameters != null) ? "?" : "";
888
 
      uri = protocol + "://" + host + portPart + divider + path + parametersPart;
889
 
      
890
 
      if(parameters != null)
891
 
      {
892
 
         if (!homes.isEmpty())
893
 
            parameters.put(HOMES_KEY, convertHomesListToString(homes));
894
 
         if (!connectHomes.isEmpty())
895
 
            parameters.put(CONNECT_HOMES_KEY, convertHomesListToString(connectHomes));
896
 
         
897
 
         Iterator iter = parameters.keySet().iterator();
898
 
         while(iter.hasNext())
899
 
         {
900
 
            String key = (String) iter.next();
901
 
            String val = (String) parameters.get(key);
902
 
            uri += key + "=" + val;
903
 
            if(iter.hasNext())
904
 
            {
905
 
               uri += "&";
906
 
            }
907
 
         }
908
 
         
909
 
         parameters.remove(HOMES_KEY);
910
 
         parameters.remove(CONNECT_HOMES_KEY);
911
 
      }
912
 
   }
913
 
   
914
 
   protected static String encodePercent(String s)
915
 
   {
916
 
      if (s == null) return null;
917
 
      StringTokenizer st = new StringTokenizer(s, "%");
918
 
      StringBuffer sb = new StringBuffer();
919
 
      int limit = st.countTokens() - 1;
920
 
      for (int i = 0; i < limit; i++)
921
 
      {
922
 
         String token = st.nextToken();
923
 
         sb.append(token).append("%25");
924
 
      }
925
 
      sb.append(st.nextToken());
926
 
      return sb.toString();
927
 
   }
928
 
   
929
 
   protected static String decodePercent(String s)
930
 
   {
931
 
      if (s == null) return null;
932
 
      StringBuffer sb = new StringBuffer();
933
 
      int fromIndex = 0;
934
 
      int index = s.indexOf("%25", fromIndex);
935
 
      while (index >= 0)
936
 
      {
937
 
         sb.append(s.substring(fromIndex, index)).append('%');
938
 
         fromIndex = index + 3;
939
 
         index = s.indexOf("%25", fromIndex);
940
 
      }
941
 
      sb.append(s.substring(fromIndex));
942
 
      return sb.toString();
943
 
   }
944
 
   
945
 
   static private String getSystemProperty(final String name, final String defaultValue)
946
 
   {
947
 
      if (SecurityUtility.skipAccessControl())
948
 
         return System.getProperty(name, defaultValue);
949
 
         
950
 
      String value = null;
951
 
      try
952
 
      {
953
 
         value = (String)AccessController.doPrivileged( new PrivilegedExceptionAction()
954
 
         {
955
 
            public Object run() throws Exception
956
 
            {
957
 
               return System.getProperty(name, defaultValue);
958
 
            }
959
 
         });
960
 
      }
961
 
      catch (PrivilegedActionException e)
962
 
      {
963
 
         throw (RuntimeException) e.getCause();
964
 
      }
965
 
      
966
 
      return value;
967
 
   }
968
 
   
969
 
   static private String getSystemProperty(final String name)
970
 
   {
971
 
      if (SecurityUtility.skipAccessControl())
972
 
         return System.getProperty(name);
973
 
      
974
 
      String value = null;
975
 
      try
976
 
      {
977
 
         value = (String)AccessController.doPrivileged( new PrivilegedExceptionAction()
978
 
         {
979
 
            public Object run() throws Exception
980
 
            {
981
 
               return System.getProperty(name);
982
 
            }
983
 
         });
984
 
      }
985
 
      catch (PrivilegedActionException e)
986
 
      {
987
 
         throw (RuntimeException) e.getCause();
988
 
      }
989
 
      
990
 
      return value;
991
 
   }
992
 
}