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

« back to all changes in this revision

Viewing changes to src/main/org/jboss/remoting/transport/Connector.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.transport;
 
24
 
 
25
import org.jboss.logging.Logger;
 
26
import org.jboss.remoting.ConnectionListener;
 
27
import org.jboss.remoting.InvokerLocator;
 
28
import org.jboss.remoting.InvokerRegistry;
 
29
import org.jboss.remoting.Remoting;
 
30
import org.jboss.remoting.ServerConfiguration;
 
31
import org.jboss.remoting.ServerInvocationHandler;
 
32
import org.jboss.remoting.ServerInvocationHandlerWrapper;
 
33
import org.jboss.remoting.ServerInvoker;
 
34
import org.jboss.remoting.marshal.MarshalFactory;
 
35
import org.jboss.remoting.marshal.MarshallLoaderFactory;
 
36
import org.jboss.remoting.serialization.ClassLoaderUtility;
 
37
import org.jboss.remoting.util.SecurityUtility;
 
38
import org.w3c.dom.Element;
 
39
import org.w3c.dom.NamedNodeMap;
 
40
import org.w3c.dom.Node;
 
41
import org.w3c.dom.NodeList;
 
42
 
 
43
import javax.management.MBeanRegistration;
 
44
import javax.management.MBeanServer;
 
45
import javax.management.MBeanServerInvocationHandler;
 
46
import javax.management.MalformedObjectNameException;
 
47
import javax.management.ObjectName;
 
48
import javax.net.ServerSocketFactory;
 
49
import javax.net.SocketFactory;
 
50
 
 
51
import java.io.IOException;
 
52
import java.net.InetAddress;
 
53
import java.net.UnknownHostException;
 
54
import java.security.AccessController;
 
55
import java.security.PrivilegedAction;
 
56
import java.security.PrivilegedActionException;
 
57
import java.security.PrivilegedExceptionAction;
 
58
import java.util.ArrayList;
 
59
import java.util.HashMap;
 
60
import java.util.Iterator;
 
61
import java.util.List;
 
62
import java.util.Map;
 
63
import java.util.StringTokenizer;
 
64
 
 
65
/**
 
66
 * Connector is an implementation of the ConnectorMBean interface.
 
67
 * <p/>
 
68
 * The Connector is root component for the remoting server.  It binds the server transport, marshaller,
 
69
 * and handler together to form the remoting server instance.
 
70
 * <p/>
 
71
 * A transport connector is configured via *-service.xml such as:
 
72
 * <code>
 
73
 * <?xml version="1.0" encoding="UTF-8"?>
 
74
 * <!DOCTYPE server>
 
75
 * <server>
 
76
 * <!-- NOTE: set this up to the path where your libraries are -->
 
77
 * <classpath codebase="lib" archives="*"/>
 
78
 * <mbean code="org.jboss.remoting.network.NetworkRegistry"
 
79
 * name="jboss.remoting:service=NetworkRegistry"/>
 
80
 * <p/>
 
81
 * <mbean code="org.jboss.remoting.transport.Connector"
 
82
 * name="jboss.remoting:service=Connector,transport=Socket"
 
83
 * display-name="Socket transport Connector">
 
84
 * <p/>
 
85
 * <!-- Can either just specify the InvokerLocator attribute and not the invoker element in the -->
 
86
 * <!-- Configuration attribute, or do the full invoker configuration in the in invoker element -->
 
87
 * <!-- of the Configuration attribute. -->
 
88
 * <!-- Remember that if you do use more than one param on the uri, will have to include as a CDATA, -->
 
89
 * <!-- otherwise, parser will complain. -->
 
90
 * <!-- <attribute name="InvokerLocator"><![CDATA[socket://${jboss.bind.address}:8084/?enableTcpNoDelay=false&clientMaxPoolSize=30]]></attribute>-->
 
91
 * <attribute name="Configuration">
 
92
 * <config>
 
93
 * <invoker transport="socket">
 
94
 * <attribute name="numAcceptThreads">1</attribute>
 
95
 * <attribute name="maxPoolSize">303</attribute>
 
96
 * <attribute name="clientMaxPoolSize" isParam="true">304</attribute>
 
97
 * <attribute name="socketTimeout">60000</attribute>
 
98
 * <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
 
99
 * <attribute name="serverBindPort">6666</attribute>
 
100
 * <!--  <attribute name="clientConnectAddress">216.23.33.2</attribute> -->
 
101
 * <!--  <attribute name="clientConnectPort">7777</attribute> -->
 
102
 * <attribute name="enableTcpNoDelay" isParam="true">false</attribute>
 
103
 * <attribute name="backlog">200</attribute>
 
104
 * </invoker>
 
105
 * <handlers>
 
106
 * <handler subsystem="mock">org.jboss.remoting.transport.mock.MockServerInvocationHandler</handler>
 
107
 * </handlers>
 
108
 * </config>
 
109
 * </attribute>
 
110
 * </mbean>
 
111
 * <p/>
 
112
 * <mbean code="org.jboss.remoting.detection.multicast.MulticastDetector"
 
113
 * name="jboss.remoting:service=Detector,transport=multicast">
 
114
 * <!-- you can specifically bind the detector to a specific IP address here -->
 
115
 * <!--  <attribute name="BindAddress">${jboss.bind.address}</attribute> -->
 
116
 * <attribute name="Port">2410</attribute>
 
117
 * </mbean>
 
118
 * <p/>
 
119
 * </server>
 
120
 * </code>
 
121
 *
 
122
 * @author <a href="mailto:jhaynie@vocalocity.net">Jeff Haynie</a>
 
123
 * @author <a href="mailto:adrian.brock@happeningtimes.com">Adrian Brock</a>
 
124
 * @author <a href="mailto:d_jencks@users.sourceforge.net">David Jencks</a>
 
125
 * @author <a href="mailto:juha@jboss.org">Juha Lindfors</a>
 
126
 * @author <a href="mailto:tom@jboss.org">Tom Elrod</a>
 
127
 * @version $Revision: 5925 $
 
128
 * @jmx.mbean description = "An MBean wrapper around a ServerInvoker."
 
129
 * @jboss.xmbean
 
130
 */
 
131
public class Connector implements MBeanRegistration, ConnectorMBean
 
132
{
 
133
   protected ServerInvoker invoker;
 
134
 
 
135
   private String locatorURI;
 
136
 
 
137
   private Element xml;
 
138
   private ServerConfiguration serverConfiguration;
 
139
   
 
140
   private Map configuration = new HashMap();
 
141
 
 
142
   private MBeanServer server;
 
143
 
 
144
   private ServerSocketFactory svrSocketFactory;
 
145
   private SocketFactory socketFactory;
 
146
 
 
147
   private Connector marshallerLoaderConnector = null;
 
148
   private boolean isMarshallerLoader = false;
 
149
   private List remoteClassLoaders;
 
150
 
 
151
   private boolean isStarted = false;
 
152
   private boolean isCreated = false;
 
153
 
 
154
   protected static final Logger log = Logger.getLogger(Connector.class);
 
155
   private static final InetAddress LOCAL_HOST;
 
156
 
 
157
   static
 
158
   {
 
159
      try
 
160
      {
 
161
         LOCAL_HOST = (InetAddress) AccessController.doPrivileged( new PrivilegedExceptionAction()
 
162
         {
 
163
            public Object run() throws UnknownHostException
 
164
            {
 
165
               try
 
166
               {
 
167
                  return InetAddress.getLocalHost();
 
168
               }
 
169
               catch (UnknownHostException e)
 
170
               {
 
171
                  return InetAddress.getByName("127.0.0.1");
 
172
               }
 
173
            }
 
174
         });
 
175
      }
 
176
      catch (PrivilegedActionException e)
 
177
      {
 
178
         log.debug(Connector.class.getName() + " unable to get local host address", e.getCause());
 
179
         throw new ExceptionInInitializerError(e.getCause());
 
180
      }
 
181
      catch (SecurityException e)
 
182
      {
 
183
         log.debug(Connector.class.getName() + " unable to get local host address", e);
 
184
         throw e;
 
185
      }
 
186
   }
 
187
   
 
188
   /**
 
189
    * Empty constructor.
 
190
    */
 
191
   public Connector()
 
192
   {
 
193
 
 
194
   }
 
195
 
 
196
   /**
 
197
    * Creates Connector with specified locator.
 
198
    *
 
199
    * @param locatorURI
 
200
    */
 
201
   public Connector(String locatorURI)
 
202
   {
 
203
      this.locatorURI = locatorURI;
 
204
   }
 
205
 
 
206
   /**
 
207
    * Creates Connector with specified locator.
 
208
    *
 
209
    * @param locator
 
210
    */
 
211
   public Connector(InvokerLocator locator)
 
212
   {
 
213
      if (locator != null)
 
214
      {
 
215
         this.locatorURI = locator.getLocatorURI();
 
216
      }
 
217
   }
 
218
 
 
219
   /**
 
220
    * Constructs connector and populates configuration information.
 
221
    *
 
222
    * @param configuration
 
223
    */
 
224
   public Connector(Map configuration)
 
225
   {
 
226
      this.configuration.putAll(configuration);
 
227
   }
 
228
 
 
229
   /**
 
230
    * Constructs connector for given locator and configuration.
 
231
    *
 
232
    * @param locatorURI
 
233
    * @param configuration
 
234
    */
 
235
   public Connector(String locatorURI, Map configuration)
 
236
   {
 
237
      this.locatorURI = locatorURI;
 
238
      this.configuration.putAll(configuration);
 
239
   }
 
240
 
 
241
   /**
 
242
    * Constructs connector for given locator and configuration.
 
243
    *
 
244
    * @param locator
 
245
    * @param configuration
 
246
    */
 
247
   public Connector(InvokerLocator locator, Map configuration)
 
248
   {
 
249
      if (locator != null)
 
250
      {
 
251
         this.locatorURI = locator.getLocatorURI();
 
252
      }
 
253
 
 
254
      if (configuration != null)
 
255
      {
 
256
         this.configuration.putAll(configuration);
 
257
      }
 
258
   }
 
259
 
 
260
   protected Connector(boolean isMarshallerConnector)
 
261
   {
 
262
      this();
 
263
      this.isMarshallerLoader = isMarshallerConnector;
 
264
   }
 
265
 
 
266
   /**
 
267
    * Indicates if the connector has been started yet.
 
268
    *
 
269
    * @return
 
270
    */
 
271
   public boolean isStarted()
 
272
   {
 
273
      return isStarted;
 
274
   }
 
275
 
 
276
   /**
 
277
    * This method is called by the MBeanServer before registration takes
 
278
    * place. The MBean is passed a reference of the MBeanServer it is
 
279
    * about to be registered with. The MBean must return the ObjectName it
 
280
    * will be registered with. The MBeanServer can pass a suggested object
 
281
    * depending upon how the MBean is registered.<p>
 
282
    * <p/>
 
283
    * The MBean can stop the registration by throwing an exception.The
 
284
    * exception is forwarded to the invoker wrapped in an
 
285
    * MBeanRegistrationException.
 
286
    *
 
287
    * @param server the MBeanServer the MBean is about to be
 
288
    *               registered with.
 
289
    * @param name   the suggested ObjectName supplied by the
 
290
    *               MBeanServer.
 
291
    * @return the actual ObjectName to register this MBean with.
 
292
    * @throws Exception for any error, the MBean is not registered.
 
293
    */
 
294
   public ObjectName preRegister(MBeanServer server, ObjectName name)
 
295
         throws Exception
 
296
   {
 
297
      this.server = server;
 
298
      return name;
 
299
   }
 
300
 
 
301
   /**
 
302
    * This method is called by the MBeanServer after registration takes
 
303
    * place or when registration fails.
 
304
    *
 
305
    * @param registrationDone the MBeanServer passes true when the
 
306
    *                         MBean was registered, false otherwise.
 
307
    */
 
308
   public void postRegister(Boolean registrationDone)
 
309
   {
 
310
   }
 
311
 
 
312
   /**
 
313
    * This method is called by the MBeanServer before deregistration takes
 
314
    * place.<p>
 
315
    * <p/>
 
316
    * The MBean can throw an exception, this will stop the deregistration.
 
317
    * The exception is forwarded to the invoker wrapped in
 
318
    * an MBeanRegistrationException.
 
319
    */
 
320
   public void preDeregister()
 
321
         throws Exception
 
322
   {
 
323
   }
 
324
 
 
325
   /**
 
326
    * This method is called by the MBeanServer after deregistration takes
 
327
    * place.
 
328
    */
 
329
   public void postDeregister()
 
330
   {
 
331
   }
 
332
 
 
333
   /**
 
334
    * Starts the connector.  This is when configuration will be applied and server invoker created.
 
335
    *
 
336
    * @jmx.managed-operation description = "Start sets up the ServerInvoker we are wrapping."
 
337
    * impact      = "ACTION"
 
338
    */
 
339
   public void start() throws Exception
 
340
   {
 
341
      if (!isStarted)
 
342
      {
 
343
 
 
344
         // doing this for those who use remoting outside of jboss container
 
345
         // so don't have to call create() and then start()
 
346
         if (!isCreated)
 
347
         {
 
348
            create();
 
349
         }
 
350
 
 
351
         // want to have handlers registered before starting, so if someone makes invocation,
 
352
         // there is something to handle it.
 
353
         if (serverConfiguration != null)
 
354
         {
 
355
            configureHandlersFromServerConfiguration();
 
356
         }
 
357
         else if (xml != null)
 
358
         {
 
359
            configureHandlersFromXML();
 
360
         }
 
361
 
 
362
         // if marshaller loader not started, start it
 
363
         if (!isMarshallerLoader)
 
364
         {
 
365
            if (marshallerLoaderConnector != null && !marshallerLoaderConnector.isStarted())
 
366
            {
 
367
               marshallerLoaderConnector.start();
 
368
            }
 
369
         }
 
370
 
 
371
         // if invoker not started, start it
 
372
         if (invoker.isStarted() == false)
 
373
         {
 
374
            try
 
375
            {
 
376
               invoker.start();
 
377
            }
 
378
            catch (Exception e)
 
379
            {
 
380
               if (marshallerLoaderConnector != null)
 
381
               {
 
382
                  marshallerLoaderConnector.stop();
 
383
               }
 
384
               log.debug("Error starting connector.", e);
 
385
               throw e;
 
386
            }
 
387
         }
 
388
         isStarted = true;
 
389
 
 
390
         log.debug(this + " started");
 
391
      }
 
392
 
 
393
   }
 
394
 
 
395
   /**
 
396
    * Starts the connector.
 
397
    *
 
398
    * @param runAsNewThread indicates if should be started on new thread or the current one.  If
 
399
    *                       runAsNewThread is true, new thread will not be daemon thread.
 
400
    * @throws Exception
 
401
    */
 
402
   public void start(boolean runAsNewThread) throws Exception
 
403
   {
 
404
 
 
405
      Runnable r = new Runnable()
 
406
      {
 
407
         public void run()
 
408
         {
 
409
            try
 
410
            {
 
411
               start();
 
412
            }
 
413
            catch (Exception e)
 
414
            {
 
415
               log.error("Error starting Connector.", e);
 
416
            }
 
417
         }
 
418
      };
 
419
      Thread t = new Thread(r);
 
420
      t.setDaemon(false);
 
421
      t.start();
 
422
   }
 
423
 
 
424
   private void init()
 
425
         throws Exception
 
426
   {
 
427
      Map invokerConfig = new HashMap();
 
428
 
 
429
      if (locatorURI == null)
 
430
      {
 
431
         // InvokerLocator attribute not set; check to see if serverConfiguration is set.
 
432
         if (serverConfiguration != null)
 
433
         {
 
434
            getInvokerConfigFromServerConfiguration(invokerConfig);
 
435
         }
 
436
         // Check to see if Configuration attribute is set.
 
437
         else if (xml != null)
 
438
         {
 
439
            getInvokerConfigFromXML(invokerConfig);
 
440
         }
 
441
 
 
442
         configuration.putAll(invokerConfig);
 
443
      }
 
444
 
 
445
      if (locatorURI == null)
 
446
      {
 
447
         throw new IllegalStateException("Connector not configured with LocatorURI.");
 
448
      }
 
449
 
 
450
      final InvokerLocator locator = new InvokerLocator(locatorURI);
 
451
 
 
452
      if (invoker == null)
 
453
      {
 
454
         // create the server invoker
 
455
         try
 
456
         {
 
457
            invoker = (ServerInvoker) AccessController.doPrivileged( new PrivilegedExceptionAction()
 
458
            {
 
459
               public Object run() throws Exception
 
460
               {
 
461
                  return  InvokerRegistry.createServerInvoker(locator, configuration);
 
462
               }
 
463
            });
 
464
         }
 
465
         catch (PrivilegedActionException pae)
 
466
         {
 
467
            throw pae.getException();
 
468
         }
 
469
         
 
470
         invoker.setMBeanServer(server);
 
471
 
 
472
         // set the server socket factory if has been already set on the connector
 
473
         invoker.setServerSocketFactory(svrSocketFactory);
 
474
         // seting to null as don't want to keep reference in connector, but the server invoker
 
475
         // see JBREM-367
 
476
         this.svrSocketFactory = null;
 
477
 
 
478
         // set the socket factory if has been already set on the connector
 
479
         invoker.setSocketFactory(socketFactory);
 
480
         this.socketFactory = null;
 
481
 
 
482
         invoker.create();
 
483
         
 
484
         // this will set the mbean server on the invoker and register it with mbean server
 
485
         if (server != null)
 
486
         {
 
487
            try
 
488
            {
 
489
               final ObjectName objName = new ObjectName(invoker.getMBeanObjectName());
 
490
 
 
491
               try
 
492
               {
 
493
                  AccessController.doPrivileged( new PrivilegedExceptionAction()
 
494
                  {
 
495
                     public Object run() throws Exception
 
496
                     {
 
497
                        if (!server.isRegistered(objName))
 
498
                        {
 
499
                           server.registerMBean(invoker, objName);
 
500
                        }
 
501
                        else
 
502
                        {
 
503
                           log.warn(objName + " is already registered with MBeanServer");
 
504
                        }
 
505
                        return null;
 
506
                     }
 
507
                  });
 
508
               }
 
509
               catch (PrivilegedActionException e)
 
510
               {
 
511
                  throw (Exception) e.getCause();
 
512
               }
 
513
 
 
514
            }
 
515
            catch (Throwable e)
 
516
            {
 
517
               log.warn("Error registering invoker " + invoker + " with MBeanServer.", e);
 
518
            }
 
519
         }
 
520
      }
 
521
 
 
522
      // if using a generic locator (such as socket://localhost:0), the locator may change so
 
523
      // keep the local cache in synch
 
524
      locatorURI = invoker.getLocator().getLocatorURI();
 
525
 
 
526
      if (remoteClassLoaders == null)
 
527
      {
 
528
         Object o = configuration.get(Remoting.REMOTE_CLASS_LOADERS);
 
529
         if (o instanceof List)
 
530
         {
 
531
            setRemoteClassLoaders((List) o);
 
532
         }
 
533
         else if (o != null)
 
534
         {
 
535
            log.warn("value of " + Remoting.REMOTE_CLASS_LOADERS + " must be a List");
 
536
         }
 
537
      }
 
538
 
 
539
      if (!isMarshallerLoader)
 
540
      {
 
541
         // need to check if should create a marshaller loader on the server side
 
542
         if (marshallerLoaderConnector == null)
 
543
         {
 
544
            marshallerLoaderConnector = createMarshallerLoader(invoker.getLocator());
 
545
         }
 
546
      }
 
547
 
 
548
   }
 
549
 
 
550
   private Connector createMarshallerLoader(InvokerLocator locator)
 
551
   {
 
552
      /**
 
553
       * This is a bit of a hack, but have to bootstrap the marshaller/unmarshaller here because
 
554
       * need them loaded and added to the MarshalFactory now, because is possible the first client
 
555
       * to make a call on this connector may not have the marshaller/unmarshaller.  Therefore, when
 
556
       * the MarshallerLoaderHandler goes to load them for the client (MarshallerLoaderClient), they
 
557
       * have to be there.  Otherwise, would not be loaded until first client actually reaches the
 
558
       * target server invoker, where they would otherwise be loaded.
 
559
       */
 
560
      ClassLoader classLoader = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
 
561
      {
 
562
         public Object run()
 
563
         {
 
564
            return Connector.class.getClassLoader();
 
565
         }
 
566
      });
 
567
      
 
568
      MarshalFactory.getMarshaller(locator, classLoader, configuration);
 
569
 
 
570
      Connector marshallerLoader = null;
 
571
      InvokerLocator loaderLocator = MarshallLoaderFactory.convertLocator(locator);
 
572
      // if loaderLocator is null, then probably not defined to have loader service (i.e. no loader port specified)
 
573
      if (loaderLocator != null)
 
574
      {
 
575
         marshallerLoader = MarshallLoaderFactory.createMarshallLoader(loaderLocator, remoteClassLoaders, server);
 
576
      }
 
577
      return marshallerLoader;
 
578
   }
 
579
 
 
580
   private void getInvokerConfigFromXML(Map invokerConfig)
 
581
   {
 
582
      try
 
583
      {
 
584
         NodeList invokerNodes = xml.getElementsByTagName("invoker");
 
585
 
 
586
         if (invokerNodes != null && invokerNodes.getLength() >= 1)
 
587
         {
 
588
            // only accept on invoker per connector at present
 
589
            Node invokerNode = invokerNodes.item(0);
 
590
 
 
591
            NamedNodeMap attributes = invokerNode.getAttributes();
 
592
            Node transportNode = attributes.getNamedItem("transport");
 
593
 
 
594
            if (transportNode != null)
 
595
            {
 
596
               String transport = transportNode.getNodeValue();
 
597
 
 
598
               // need to log warning if there are more than one invoker elements
 
599
               if (invokerNodes.getLength() > 1)
 
600
               {
 
601
                  log.warn("Found more than one invokers defined in configuration.  " +
 
602
                           "Will only be using the first one - " + transport);
 
603
               }
 
604
 
 
605
               // now create a map for all the sub attributes
 
606
               Map paramConfig = new HashMap();
 
607
               
 
608
               // In case of a multihome configuration.
 
609
               List homes = new ArrayList();
 
610
               List connectHomes = new ArrayList();
 
611
    
 
612
               NodeList invokerAttributes = invokerNode.getChildNodes();
 
613
               int len = invokerAttributes.getLength();
 
614
               for (int x = 0; x < len; x++)
 
615
               {
 
616
                  Node attr = invokerAttributes.item(x);
 
617
                  if ("attribute".equals(attr.getNodeName()))
 
618
                  {
 
619
                     String name = attr.getAttributes().getNamedItem("name").getNodeValue();
 
620
                     String value = attr.getFirstChild().getNodeValue();
 
621
                     if ("homes".equals(name))
 
622
                     {
 
623
                        processHomes(attr, "home", homes);
 
624
                     }
 
625
                     else if ("connecthomes".equals(name))
 
626
                     {
 
627
                        processHomes(attr, "connecthome", connectHomes);
 
628
                     }
 
629
                     else
 
630
                     {
 
631
                        invokerConfig.put(name, value);
 
632
                     }
 
633
                     Node isParamAttribute = attr.getAttributes().getNamedItem("isParam");
 
634
                     if (isParamAttribute != null && Boolean.valueOf(isParamAttribute.getNodeValue()).booleanValue())
 
635
                     {
 
636
                        paramConfig.put(name, value);
 
637
                     }
 
638
                  }
 
639
               }
 
640
               
 
641
               if (homes.isEmpty() && !connectHomes.isEmpty())
 
642
               {
 
643
                  throw new Exception("Configuration has a " + InvokerLocator.CONNECT_HOMES_KEY +
 
644
                                      " without a " + InvokerLocator.HOMES_KEY);
 
645
               }
 
646
 
 
647
               // should now have my map with all my attributes, now need to look for
 
648
               // specific attributes that will impact the locator uri.
 
649
 
 
650
               String clientConnectAddress = (String) invokerConfig.get("clientConnectAddress");
 
651
               String clientConnectPort = (String) invokerConfig.get("clientConnectPort");
 
652
               String serverBindAddress = (String) invokerConfig.get("serverBindAddress");
 
653
               String serverBindPort = (String) invokerConfig.get("serverBindPort");
 
654
               String localHostAddress = getLocalHost().getHostAddress();              
 
655
               
 
656
               String tempURI = null;
 
657
               String path = (String) invokerConfig.get("path");
 
658
               PortUtil.updateRange(invokerConfig);
 
659
               
 
660
               if (homes.isEmpty() && connectHomes.isEmpty())
 
661
               {
 
662
                  int port = clientConnectPort != null
 
663
                                ? Integer.parseInt(clientConnectPort)
 
664
                                : serverBindPort != null
 
665
                                   ? Integer.parseInt(serverBindPort)
 
666
                                   : PortUtil.findFreePort(serverBindAddress != null
 
667
                                                              ? serverBindAddress
 
668
                                                               : localHostAddress);
 
669
                  String host = clientConnectAddress != null
 
670
                                   ? clientConnectAddress
 
671
                                   : serverBindAddress != null
 
672
                                      ? serverBindAddress
 
673
                                      : localHostAddress;
 
674
   
 
675
                  // finally, let's build the invoker uri
 
676
                  tempURI = transport + "://" + fixHostnameForURL(host) + ":" + port;
 
677
                  if (path != null)
 
678
                  {
 
679
                     tempURI += "/" + path;
 
680
                  }
 
681
               }
 
682
               else
 
683
               {
 
684
                  String port = clientConnectPort != null
 
685
                                   ? ":" + clientConnectPort
 
686
                                   : serverBindPort != null
 
687
                                      ? ":" + serverBindPort
 
688
                                      : "";
 
689
                  tempURI = transport + "://multihome" + port;
 
690
                  if (path != null)
 
691
                  {
 
692
                     tempURI += "/" + path;
 
693
                  }
 
694
                  tempURI += "/?";
 
695
                  
 
696
                  Iterator it = homes.iterator();
 
697
                  tempURI += "homes=" + it.next();
 
698
                  while (it.hasNext())
 
699
                  {
 
700
                     tempURI += "!" + it.next();
 
701
                  }
 
702
                  
 
703
                  if (!connectHomes.isEmpty())
 
704
                  {
 
705
                     tempURI += "&connecthomes=";
 
706
                     it = connectHomes.iterator();
 
707
                     tempURI += it.next();
 
708
                     while (it.hasNext())
 
709
                     {
 
710
                        tempURI += "!" + it.next();
 
711
                     }  
 
712
                  }
 
713
               }
 
714
 
 
715
               // any params to add to the uri?
 
716
               if (paramConfig.size() > 0)
 
717
               {
 
718
                  if (tempURI.indexOf("/?") < 0)
 
719
                     tempURI += "/?";
 
720
                  else
 
721
                     tempURI += "&";
 
722
                  Iterator keyItr = paramConfig.keySet().iterator();
 
723
                  if (keyItr.hasNext())
 
724
                  {
 
725
                     Object name = keyItr.next();
 
726
                     Object value = paramConfig.get(name);
 
727
                     tempURI += name + "=" + value;
 
728
                  }
 
729
                  while (keyItr.hasNext())
 
730
                  {
 
731
                     tempURI += "&";
 
732
                     Object name = keyItr.next();
 
733
                     Object value = paramConfig.get(name);
 
734
                     tempURI += name + "=" + value;
 
735
                  }
 
736
               }
 
737
               locatorURI = tempURI;
 
738
            }
 
739
            else
 
740
            {
 
741
               log.error("Invoker element within Configuration attribute does not contain a transport attribute.");
 
742
            }
 
743
         }
 
744
      }
 
745
      catch (Exception e)
 
746
      {
 
747
         log.error("Error configuring invoker for connector: " + e.getMessage());
 
748
         log.debug("Error configuring invoker for connector.", e);
 
749
         throw new IllegalStateException("Error configuring invoker for connector.  Can not continue without invoker.");
 
750
      }
 
751
   }
 
752
   
 
753
   private void processHomes(Node node, String homeType, List homes)
 
754
   {
 
755
      NodeList nodes = node.getChildNodes();
 
756
      for (int i = 0; i < nodes.getLength(); i++)
 
757
      {
 
758
         Node child = nodes.item(i);
 
759
         if (Node.ELEMENT_NODE == child.getNodeType())
 
760
         {
 
761
            if (homeType.equals(child.getNodeName()))
 
762
            {
 
763
               NodeList children = child.getChildNodes();
 
764
               for (int k = 0; k < children.getLength(); k++)
 
765
               {
 
766
                  Node grandchild = children.item(k);
 
767
                  if (Node.TEXT_NODE == grandchild.getNodeType())
 
768
                  {
 
769
                     homes.add(grandchild.getNodeValue());
 
770
                  } 
 
771
               }
 
772
            }
 
773
         }
 
774
      }
 
775
   }
 
776
 
 
777
   private void getInvokerConfigFromServerConfiguration(Map invokerConfig) throws Exception
 
778
   {
 
779
      try
 
780
      {
 
781
         String transport = serverConfiguration.getTransport();
 
782
         
 
783
         if (transport == null)
 
784
         {
 
785
            log.error("ServerConfiguration must contain a non-null transport attribute.");
 
786
            return;
 
787
         }
 
788
         
 
789
         Map locatorParameters = serverConfiguration.getInvokerLocatorParameters();
 
790
         Map serverParameters = serverConfiguration.getServerParameters();
 
791
         
 
792
         // Remove single home elements meant to be ignored.
 
793
         String temp = (String) serverParameters.remove("clientConnectAddress");
 
794
         if (temp != null) log.warn("clientConnectAddress in server parameters will be ignored");
 
795
         temp = (String) serverParameters.remove("clientConnectPort");
 
796
         if (temp != null) log.warn("clientConnectPort in server parameters will be ignored");
 
797
         temp = (String) serverParameters.get("serverBindAddress");
 
798
         if (temp != null)
 
799
         {
 
800
            locatorParameters.remove("serverBindAddress");
 
801
            log.warn("serverBindAddress in locator parameters will be ignored");
 
802
         }
 
803
         temp = (String) serverParameters.get("serverBindPort");
 
804
         if (temp != null)
 
805
         {
 
806
            locatorParameters.remove("serverBindPort");
 
807
            log.warn("serverBindPort in locator parameters will be ignored");
 
808
         }
 
809
 
 
810
         // Adjust multihome elements.
 
811
         temp = (String) serverParameters.remove(InvokerLocator.CONNECT_HOMES_KEY);
 
812
         if (temp != null) log.warn(InvokerLocator.CONNECT_HOMES_KEY + " in server parameters will be ignored");
 
813
         temp = (String) serverParameters.remove(InvokerLocator.HOMES_KEY);
 
814
         if (temp != null)
 
815
         {
 
816
            if (locatorParameters.get(InvokerLocator.HOMES_KEY) == null)
 
817
               locatorParameters.put(InvokerLocator.HOMES_KEY, temp);
 
818
            else
 
819
               log.warn(InvokerLocator.HOMES_KEY + " in server parameters will be ignored");
 
820
         }
 
821
 
 
822
         // If there is a connect homes value, then there must be a homes value.
 
823
         if (locatorParameters.get(InvokerLocator.CONNECT_HOMES_KEY) != null &&
 
824
             locatorParameters.get(InvokerLocator.HOMES_KEY) == null)
 
825
         {
 
826
            throw new Exception("Configuration has a " + InvokerLocator.CONNECT_HOMES_KEY +
 
827
                                " without a " + InvokerLocator.HOMES_KEY);
 
828
         }
 
829
         
 
830
         // Get multihome parameters.
 
831
         String connectHomes = (String) locatorParameters.remove(InvokerLocator.CONNECT_HOMES_KEY);
 
832
         String homes = (String) serverParameters.remove(InvokerLocator.HOMES_KEY);
 
833
         temp = (String) locatorParameters.remove(InvokerLocator.HOMES_KEY);
 
834
         if (homes == null) homes = temp;
 
835
         
 
836
         locatorParameters = new HashMap(serverConfiguration.getInvokerLocatorParameters());
 
837
         serverParameters = new HashMap(serverConfiguration.getServerParameters());
 
838
         
 
839
         // Get single home parameters.
 
840
         String clientConnectAddress = (String) locatorParameters.remove("clientConnectAddress");
 
841
         String clientConnectPort = (String) locatorParameters.remove("clientConnectPort");
 
842
         String serverBindAddress = (String) serverParameters.get("serverBindAddress");
 
843
         String defaultPortString = (String) serverParameters.get("serverBindPort");
 
844
         temp = (String) locatorParameters.remove("serverBindAddress");
 
845
         if (serverBindAddress == null) serverBindAddress = temp;
 
846
         temp = (String) locatorParameters.remove("serverBindPort");
 
847
         if (defaultPortString == null) defaultPortString = temp;
 
848
         
 
849
         String path = (String) locatorParameters.remove("path");
 
850
         PortUtil.updateRange(invokerConfig);
 
851
         
 
852
         String tempURI = null;
 
853
         boolean parametersStarted = false;
 
854
         if (connectHomes == null && homes == null)
 
855
         {
 
856
            String localHostAddress = getLocalHost().getHostAddress();
 
857
            
 
858
            // A single home configuration.
 
859
            String host = clientConnectAddress != null 
 
860
                             ? clientConnectAddress
 
861
                             : serverBindAddress != null
 
862
                                ? serverBindAddress
 
863
                                : localHostAddress;
 
864
 
 
865
            int port = clientConnectPort != null
 
866
                          ? Integer.parseInt(clientConnectPort)
 
867
                          : defaultPortString != null
 
868
                             ? Integer.parseInt(defaultPortString)
 
869
                             : PortUtil.findFreePort(serverBindAddress != null
 
870
                                                        ? serverBindAddress
 
871
                                                        : localHostAddress);
 
872
 
 
873
            tempURI = transport + "://" + fixHostnameForURL(host) + ":" + port + ((path != null) ? ("/" + path) : "");
 
874
         }
 
875
         else
 
876
         {
 
877
            // A multihome configuration.
 
878
            tempURI = transport + "://multihome" + ((path != null) ? ("/" + path) : "");
 
879
            parametersStarted = true;
 
880
            tempURI += "/?";
 
881
            if (connectHomes != null)
 
882
            {
 
883
               tempURI += InvokerLocator.CONNECT_HOMES_KEY + "=" + connectHomes;
 
884
               if (homes != null)
 
885
                  tempURI += "&" + InvokerLocator.HOMES_KEY + "=" + homes;
 
886
            }
 
887
            else if (homes != null)
 
888
               tempURI += InvokerLocator.HOMES_KEY + "=" + homes;
 
889
         }
 
890
         
 
891
         // any params to add to the uri?
 
892
         if (locatorParameters.size() > 0)
 
893
         {
 
894
            if (!parametersStarted)
 
895
               tempURI += "/?";
 
896
            else
 
897
               tempURI += "&";
 
898
            Iterator keyItr = locatorParameters.keySet().iterator();
 
899
            if (keyItr.hasNext())
 
900
            {
 
901
               Object name = keyItr.next();
 
902
               Object value = locatorParameters.get(name);
 
903
               tempURI += name + "=" + value;
 
904
            }
 
905
            while (keyItr.hasNext())
 
906
            {
 
907
               tempURI += "&";
 
908
               Object name = keyItr.next();
 
909
               Object value = locatorParameters.get(name);
 
910
               tempURI += name + "=" + value;
 
911
            }
 
912
         }
 
913
         
 
914
         locatorURI = tempURI;
 
915
         
 
916
         invokerConfig.putAll(serverConfiguration.getServerParameters());
 
917
         invokerConfig.putAll((serverConfiguration.getInvokerLocatorParameters()));
 
918
      }
 
919
      catch (Exception e)
 
920
      {
 
921
         log.error("Error configuring invoker for connector: " + e.getMessage());
 
922
         log.debug("Error configuring invoker for connector.", e);
 
923
         throw new IllegalStateException("Error configuring invoker from configuration POJO.  Can not continue without invoker.");
 
924
      }
 
925
   }
 
926
   
 
927
   // adds enclosing brackets if an IPv6 literal address
 
928
   private String fixHostnameForURL(String address)
 
929
   {
 
930
      if (address == null) 
 
931
         return address ;
 
932
 
 
933
      if (address.indexOf(':') != -1 && address.indexOf("[") == -1)
 
934
         return "[" + address + "]" ;
 
935
      else 
 
936
         return address ;
 
937
   }
 
938
   
 
939
   private void configureHandlersFromServerConfiguration() throws Exception
 
940
   {
 
941
      Map handlerMap = serverConfiguration.getInvocationHandlers();
 
942
      if (handlerMap.size() == 0 &&
 
943
            (getInvocationHandlers() == null || getInvocationHandlers().length == 0))
 
944
      {
 
945
         throw new IllegalArgumentException("invocationHandlers list empty and are no registered handlers found.");
 
946
      }
 
947
 
 
948
 
 
949
      Iterator it = handlerMap.keySet().iterator();
 
950
      while (it.hasNext())
 
951
      {
 
952
         String subsystems = (String) it.next();
 
953
         Object value = handlerMap.get(subsystems);
 
954
         ServerInvocationHandler handler = null;
 
955
         
 
956
         if (value instanceof ServerInvocationHandler)
 
957
         {
 
958
            handler = (ServerInvocationHandler) value;
 
959
         }
 
960
         else if (value instanceof String)
 
961
         {
 
962
            //first check to see if this is an ObjectName
 
963
            String valueString = (String) value;
 
964
            boolean isObjName = false;
 
965
            try
 
966
            {
 
967
               ObjectName objName = new ObjectName(valueString);
 
968
               handler = createHandlerProxy(objName);
 
969
               isObjName = true;
 
970
            }
 
971
            catch (MalformedObjectNameException e)
 
972
            {
 
973
               log.debug("Handler supplied is not an object name.");
 
974
            }
 
975
 
 
976
            if (!isObjName)
 
977
            {
 
978
               Class serverInvocationHandlerClass = ClassLoaderUtility.loadClass(valueString, Connector.class);
 
979
               handler = (ServerInvocationHandler) serverInvocationHandlerClass.newInstance();
 
980
            }
 
981
         }
 
982
         else
 
983
         {
 
984
            throw new IllegalArgumentException("handler has invalid type: " + value);
 
985
         }
 
986
 
 
987
         StringTokenizer tok = new StringTokenizer(subsystems, ",");
 
988
 
 
989
         while (tok.hasMoreTokens())
 
990
         {
 
991
            String subsystem = tok.nextToken();
 
992
            addInvocationHandler(subsystem, handler);
 
993
         }
 
994
      }
 
995
   }
 
996
   
 
997
   private void configureHandlersFromXML() throws Exception
 
998
   {
 
999
      NodeList handlersNodes = xml.getElementsByTagName("handler");
 
1000
 
 
1001
      if ((handlersNodes == null || handlersNodes.getLength() <= 0) &&
 
1002
            (getInvocationHandlers() == null || getInvocationHandlers().length == 0))
 
1003
      {
 
1004
         throw new IllegalArgumentException("required 'handler' element not found and are no registered handlers found.");
 
1005
      }
 
1006
 
 
1007
      int len = handlersNodes.getLength();
 
1008
 
 
1009
      for (int c = 0; c < len; c++)
 
1010
      {
 
1011
         Node node = handlersNodes.item(c);
 
1012
         Node subNode = node.getAttributes().getNamedItem("subsystem");
 
1013
 
 
1014
         if (subNode == null)
 
1015
         {
 
1016
            throw new IllegalArgumentException("Required 'subsystem' attribute on 'handler' element");
 
1017
         }
 
1018
 
 
1019
         String handlerClass = node.getFirstChild().getNodeValue();
 
1020
 
 
1021
         boolean isObjName = false;
 
1022
         ServerInvocationHandler handler = null;
 
1023
 
 
1024
         //first check to see if this is an ObjectName
 
1025
         try
 
1026
         {
 
1027
            ObjectName objName = new ObjectName(handlerClass);
 
1028
            handler = createHandlerProxy(objName);
 
1029
            isObjName = true;
 
1030
         }
 
1031
         catch (MalformedObjectNameException e)
 
1032
         {
 
1033
            log.debug("Handler supplied is not an object name.");
 
1034
         }
 
1035
 
 
1036
         if (!isObjName)
 
1037
         {
 
1038
            Class serverInvocationHandlerClass = ClassLoaderUtility.loadClass(handlerClass, Connector.class);
 
1039
            handler = (ServerInvocationHandler) serverInvocationHandlerClass.newInstance();
 
1040
//          handler = (ServerInvocationHandler) cl.loadClass(handlerClass).newInstance();
 
1041
         }
 
1042
 
 
1043
         StringTokenizer tok = new StringTokenizer(subNode.getNodeValue(), ",");
 
1044
 
 
1045
         while (tok.hasMoreTokens())
 
1046
         {
 
1047
            String subsystem = tok.nextToken();
 
1048
            addInvocationHandler(subsystem, handler);
 
1049
         }
 
1050
      }
 
1051
   }
 
1052
 
 
1053
   private ServerInvocationHandler createHandlerProxy(ObjectName objName)
 
1054
   {
 
1055
      ServerInvocationHandler handler;
 
1056
      if (server != null)
 
1057
      {
 
1058
         handler = (ServerInvocationHandler)
 
1059
               MBeanServerInvocationHandler.newProxyInstance(server,
 
1060
                                                             objName,
 
1061
                                                             ServerInvocationHandler.class,
 
1062
                                                             false);
 
1063
         handler = new ServerInvocationHandlerWrapper(handler);
 
1064
      }
 
1065
      else
 
1066
      {
 
1067
         throw new RuntimeException("Can not register MBean invocation handler as the Connector has not been registered with a MBeanServer.");
 
1068
      }
 
1069
      return handler;
 
1070
   }
 
1071
 
 
1072
   /**
 
1073
    * Adds a connection listener to receive notification when a client connection
 
1074
    * is lost or disconnected.  Will only be triggered for notifications when
 
1075
    * leasing is turned on (via the lease period attribute being set to > 0).
 
1076
    *
 
1077
    * @param listener
 
1078
    * @jmx.managed-operation description = "Add a connection listener to call when detect that a client has
 
1079
    * failed or disconnected."
 
1080
    * impact      = "ACTION"
 
1081
    * @jmx.managed-parameter name        = "listener"
 
1082
    * type        = "org.jboss.remoting.ConnectionListener"
 
1083
    * description = "The connection listener to register"
 
1084
    */
 
1085
   public void addConnectionListener(ConnectionListener listener)
 
1086
   {
 
1087
      if (invoker != null)
 
1088
      {
 
1089
         invoker.addConnectionListener(listener);
 
1090
      }
 
1091
   }
 
1092
 
 
1093
   /**
 
1094
    * Removes connection listener from receiving client connection lost/disconnected
 
1095
    * notifications.
 
1096
    *
 
1097
    * @param listener
 
1098
    * @jmx.managed-operation description = "Remove a client connection listener."
 
1099
    * impact      = "ACTION"
 
1100
    * @jmx.managed-parameter name        = "listener"
 
1101
    * type        = "org.jboss.remoting.ConnectionListener"
 
1102
    * description = "The client connection listener to remove."
 
1103
    */
 
1104
   public void removeConnectionListener(ConnectionListener listener)
 
1105
   {
 
1106
      if (invoker != null)
 
1107
      {
 
1108
         invoker.removeConnectionListener(listener);
 
1109
      }
 
1110
   }
 
1111
 
 
1112
   /**
 
1113
    * Sets the lease period for client connections.
 
1114
    * Value is in milliseconds.
 
1115
    *
 
1116
    * @param leasePeriodValue
 
1117
    * @jmx.managed-attribute description = "The number of milliseconds that should be used
 
1118
    * when establishing the client lease period (meaning client will need to update its lease
 
1119
    * within this amount of time or will be considered dead)."
 
1120
    * access     = "read-write"
 
1121
    */
 
1122
   public void setLeasePeriod(long leasePeriodValue)
 
1123
   {
 
1124
      if (invoker != null)
 
1125
      {
 
1126
         invoker.setLeasePeriod(leasePeriodValue);
 
1127
      }
 
1128
   }
 
1129
 
 
1130
   /**
 
1131
    * Gets the lease period for client connections.
 
1132
    * Value in milliseconds.
 
1133
    *
 
1134
    * @return
 
1135
    * @jmx.managed-attribute
 
1136
    */
 
1137
   public long getLeasePeriod()
 
1138
   {
 
1139
      if (invoker != null)
 
1140
      {
 
1141
         return invoker.getLeasePeriod();
 
1142
      }
 
1143
      else
 
1144
      {
 
1145
         return -1;
 
1146
      }
 
1147
   }
 
1148
 
 
1149
 
 
1150
   /**
 
1151
    * Stops the connector.  Will also stop and destroy server invoker (transport)
 
1152
    *
 
1153
    * @jmx.managed-operation description = "Stop tears down the ServerInvoker we are wrapping."
 
1154
    * impact      = "ACTION"
 
1155
    */
 
1156
   public void stop()
 
1157
   {
 
1158
      if (isStarted)
 
1159
      {
 
1160
         if (invoker != null)
 
1161
         {
 
1162
            if (server != null)
 
1163
            {
 
1164
               try
 
1165
               {
 
1166
                  ObjectName objName = new ObjectName(invoker.getMBeanObjectName());
 
1167
                  unregisterMBean(server, objName);
 
1168
               }
 
1169
               catch (Exception e)
 
1170
               {
 
1171
                  log.error("invalid Object Name", e);
 
1172
               }  
 
1173
            }
 
1174
            log.trace(this + " shutting down server invoker");
 
1175
            invoker.stop();
 
1176
            invoker.destroy();
 
1177
            
 
1178
            AccessController.doPrivileged( new PrivilegedAction()
 
1179
            {
 
1180
               public Object run()
 
1181
               {
 
1182
                  InvokerRegistry.destroyServerInvoker(invoker);
 
1183
                  return null;
 
1184
               }
 
1185
            });
 
1186
            
 
1187
            invoker = null;
 
1188
         }
 
1189
         if (marshallerLoaderConnector != null && marshallerLoaderConnector.isStarted)
 
1190
         {
 
1191
            marshallerLoaderConnector.stop();
 
1192
            marshallerLoaderConnector = null;
 
1193
         }
 
1194
         isStarted = false;
 
1195
      }
 
1196
      
 
1197
      log.trace(this + " is stopped");
 
1198
   }
 
1199
 
 
1200
   /**
 
1201
    * Creates the connector.
 
1202
    *
 
1203
    * @jmx.managed-operation
 
1204
    */
 
1205
   public void create()
 
1206
         throws Exception
 
1207
   {
 
1208
      if (!isCreated)
 
1209
      {
 
1210
         try
 
1211
         {
 
1212
            init();
 
1213
            isCreated = true;
 
1214
         }
 
1215
         catch (Exception e)
 
1216
         {
 
1217
            // unwind create process
 
1218
            if (invoker != null)
 
1219
            {
 
1220
               invoker.stop();
 
1221
               invoker.destroy();
 
1222
               
 
1223
               AccessController.doPrivileged( new PrivilegedAction()
 
1224
               {
 
1225
                  public Object run()
 
1226
                  {
 
1227
                     InvokerRegistry.destroyServerInvoker(invoker);
 
1228
                     return null;
 
1229
                  }
 
1230
               });
 
1231
               
 
1232
               invoker = null;
 
1233
            }
 
1234
            isCreated = false;
 
1235
            throw e;
 
1236
         }
 
1237
      }
 
1238
   }
 
1239
 
 
1240
   /**
 
1241
    * Destroys the connector.
 
1242
    *
 
1243
    * @jmx.managed-operation
 
1244
    */
 
1245
   public void destroy()
 
1246
   {
 
1247
      if (isStarted)
 
1248
      {
 
1249
         stop();
 
1250
      }
 
1251
      if (invoker != null)
 
1252
      {
 
1253
         invoker.stop();
 
1254
         invoker.destroy();
 
1255
         
 
1256
         AccessController.doPrivileged( new PrivilegedAction()
 
1257
         {
 
1258
            public Object run()
 
1259
            {
 
1260
               InvokerRegistry.destroyServerInvoker(invoker);
 
1261
               return null;
 
1262
            }
 
1263
         });
 
1264
         
 
1265
         invoker = null;
 
1266
      }
 
1267
      isCreated = false;
 
1268
   }
 
1269
 
 
1270
   public ServerInvoker getServerInvoker()
 
1271
   {
 
1272
      return invoker;
 
1273
   }
 
1274
 
 
1275
   /**
 
1276
    * Will get array of all the handlers registered with the connector's server invoker.
 
1277
    *
 
1278
    * @return
 
1279
    */
 
1280
   public ServerInvocationHandler[] getInvocationHandlers()
 
1281
   {
 
1282
      ServerInvocationHandler[] handlers = null;
 
1283
      if (invoker != null)
 
1284
      {
 
1285
         handlers = invoker.getInvocationHandlers();
 
1286
      }
 
1287
 
 
1288
      return handlers;
 
1289
   }
 
1290
 
 
1291
   /**
 
1292
    * Returns the locator to the connector. Locator is the actual InvokerLocator
 
1293
    * object used to identify and get the ServerInvoker we are wrapping.
 
1294
    *
 
1295
    * @jmx.managed-attribute description = "Locator is the actual InvokerLocator object used to
 
1296
    * identify and get the ServerInvoker we are wrapping."
 
1297
    * access      = "read-only"
 
1298
    */
 
1299
   public InvokerLocator getLocator()
 
1300
   {
 
1301
      return invoker.getLocator();
 
1302
   }
 
1303
 
 
1304
   /**
 
1305
    * Sets the invoker locator. InvokerLocator is the string URI representation
 
1306
    * of the InvokerLocator used to get and identify the ServerInvoker
 
1307
    * we are wrapping.
 
1308
    *
 
1309
    * @jmx.managed-attribute description = "InvokerLocator is the string URI representation of the
 
1310
    * InvokerLocator used to get and identify the ServerInvoker
 
1311
    * we are wrapping."
 
1312
    * access     = "read-write"
 
1313
    */
 
1314
   public void setInvokerLocator(String locator)
 
1315
         throws Exception
 
1316
   {
 
1317
      if (!isCreated)
 
1318
      {
 
1319
         locatorURI = locator;
 
1320
      }
 
1321
      else
 
1322
      {
 
1323
         throw new RuntimeException("Can not set the invoker locator on this Connector " +
 
1324
                                    "as has already been created with a different locator.");
 
1325
      }
 
1326
   }
 
1327
 
 
1328
 
 
1329
   /**
 
1330
    * Returns the invoker locator. InvokerLocator is the string URI representation
 
1331
    * of the InvokerLocator used to get and identify the ServerInvoker
 
1332
    * we are wrapping.
 
1333
    *
 
1334
    * @jmx.managed-attribute
 
1335
    */
 
1336
   public String getInvokerLocator() throws Exception
 
1337
   {
 
1338
      return locatorURI;
 
1339
   }
 
1340
 
 
1341
   /**
 
1342
    * Configuration is an xml element indicating subsystems to be registered
 
1343
    * with the ServerInvoker we wrap. Using mbean subsystems that call
 
1344
    * registerSubsystem is more flexible.
 
1345
    *
 
1346
    * @jmx.managed-attribute description = "Configuration is an xml element indicating subsystems
 
1347
    * to be registered with the ServerInvoker we wrap. Using
 
1348
    * mbean subsystems that call registerSubsystem is more
 
1349
    * flexible."
 
1350
    * access     = "read-write"
 
1351
    */
 
1352
   public void setConfiguration(Element xml)
 
1353
         throws Exception
 
1354
   {
 
1355
      this.xml = xml;
 
1356
   }
 
1357
 
 
1358
   /**
 
1359
    * Configuration is an xml element indicating subsystems to be registered
 
1360
    * with the ServerInvoker we wrap. Using mbean subsystems that call
 
1361
    * registerSubsystem is more flexible.
 
1362
    *
 
1363
    * @jmx.managed-attribute
 
1364
    */
 
1365
   public Element getConfiguration()
 
1366
   {
 
1367
      return xml;
 
1368
   }
 
1369
 
 
1370
   /**
 
1371
    * Adds a handler to the connector via OjbectName.  This will create a mbean proxy of
 
1372
    * type of ServerInvocationHandler for the MBean specified by object name passed (so has
 
1373
    * to implement ServerInvocationHandler interface).
 
1374
    *
 
1375
    * @param subsystem
 
1376
    * @param handlerObjectName
 
1377
    * @return Previous ServerInvocatioHandler with the same subsystem value (case insensitive) or null if one did not previously exist.
 
1378
    * @throws Exception
 
1379
    * @jmx.managed-operation description = "Add a subsystem invocation handler to the ServerInvoker
 
1380
    * we wrap, identified by the subsystem parameter."
 
1381
    * impact      = "ACTION"
 
1382
    * @jmx.managed-parameter name        = "subsystem"
 
1383
    * type        = "java.lang.String"
 
1384
    * description = "The subsystem this handler is for."
 
1385
    * @jmx.managed-parameter name        = "handlerObjectName"
 
1386
    * type        = "javax.management.ObjectName"
 
1387
    * description = "The ServerInvocationHandler MBean we are registering
 
1388
    * for the subsystem"
 
1389
    */
 
1390
   public ServerInvocationHandler addInvocationHandler(String subsystem, ObjectName handlerObjectName) throws Exception
 
1391
   {
 
1392
      ServerInvocationHandler invocationHandler = createHandlerProxy(handlerObjectName);
 
1393
      return addInvocationHandler(subsystem, invocationHandler);
 
1394
   }
 
1395
 
 
1396
   /**
 
1397
    * Adds an invocation handler for the named subsystem to the invoker we
 
1398
    * manage, and sets the mbean server on the invocation handler.
 
1399
    *
 
1400
    * @return Previous ServerInvocatioHandler with the same subsystem value (case insensitive) or null if one did not previously exist.
 
1401
    * @jmx.managed-operation description = "Add a subsystem invocation handler to the ServerInvoker
 
1402
    * we wrap, identified by the subsystem parameter."
 
1403
    * impact      = "ACTION"
 
1404
    * @jmx.managed-parameter name        = "subsystem"
 
1405
    * type        = "java.lang.String"
 
1406
    * description = "The subsystem this handler is for."
 
1407
    * @jmx.managed-parameter name        = "handler"
 
1408
    * type        = "org.jboss.remoting.ServerInvocationHandler"
 
1409
    * description = "The ServerInvocationHandler we are registering
 
1410
    * for the subsystem"
 
1411
    */
 
1412
   public ServerInvocationHandler addInvocationHandler(String subsystem, final ServerInvocationHandler handler)
 
1413
         throws Exception
 
1414
   {
 
1415
      if (invoker == null)
 
1416
      {
 
1417
         throw new IllegalStateException("You may only add handlers once the Connector is created (via create() method).");
 
1418
      }
 
1419
 
 
1420
      // In case handler is an MBean.
 
1421
      AccessController.doPrivileged( new PrivilegedAction()
 
1422
      {
 
1423
         public Object run()
 
1424
         {
 
1425
            handler.setMBeanServer(server);
 
1426
            return null;
 
1427
         }
 
1428
      });
 
1429
      return invoker.addInvocationHandler(subsystem, handler);
 
1430
   }
 
1431
 
 
1432
   /**
 
1433
    * Removes an invocation handler for the supplied subsystem from the invoker
 
1434
    * we manage, and unsets the MBeanServer on the handler.
 
1435
    *
 
1436
    * @jmx.managed-operation description = "Remove a subsystem invocation handler to the
 
1437
    * ServerInvoker we wrap, identified by the subsystem
 
1438
    * parameter."
 
1439
    * impact      = "ACTION"
 
1440
    * @jmx.managed-parameter name        = "subsystem"
 
1441
    * type        = "java.lang.String"
 
1442
    * description = "The subsystem this handler is for."
 
1443
    */
 
1444
   public void removeInvocationHandler(String subsystem) throws Exception
 
1445
   {
 
1446
      ServerInvocationHandler handler = invoker.removeInvocationHandler(subsystem);
 
1447
 
 
1448
      if (handler != null)
 
1449
      {
 
1450
         handler.setMBeanServer(null);
 
1451
      }
 
1452
   }
 
1453
 
 
1454
   /**
 
1455
    * The server socket factory can only be set on the Connector before the create() method
 
1456
    * has been called.  Otherwise, a runtime exception will be thrown.
 
1457
    * @param serverSocketFactory
 
1458
    */
 
1459
   public void setServerSocketFactory(ServerSocketFactory serverSocketFactory)
 
1460
   {
 
1461
      if(isCreated)
 
1462
      {
 
1463
         throw new RuntimeException("Can not set server socket factory on Connector after the create() method has been called.");
 
1464
      }
 
1465
 
 
1466
      if (invoker != null)
 
1467
      {
 
1468
         invoker.setServerSocketFactory(serverSocketFactory);
 
1469
      }
 
1470
      else
 
1471
      {
 
1472
         this.svrSocketFactory = serverSocketFactory;
 
1473
      }
 
1474
   }
 
1475
 
 
1476
   public ServerSocketFactory getServerSocketFactory()
 
1477
   {
 
1478
      if (invoker != null)
 
1479
      {
 
1480
         return invoker.getServerSocketFactory();
 
1481
      }
 
1482
      else
 
1483
      {
 
1484
         return svrSocketFactory;
 
1485
      }
 
1486
   }
 
1487
 
 
1488
   /**
 
1489
    * The socket factory (for callbacks) can only be set on the Connector before the
 
1490
    * create() method has been called.  Otherwise, a runtime exception will be thrown.
 
1491
    * @param socketFactory
 
1492
    */
 
1493
   public void setSocketFactory(SocketFactory socketFactory)
 
1494
   {
 
1495
      if(isCreated)
 
1496
      {
 
1497
         throw new RuntimeException("Can not set socket factory on Connector after the create() method has been called.");
 
1498
      }
 
1499
 
 
1500
      if (invoker != null)
 
1501
      {
 
1502
         invoker.setSocketFactory(socketFactory);
 
1503
      }
 
1504
      else
 
1505
      {
 
1506
         this.socketFactory = socketFactory;
 
1507
      }
 
1508
   }
 
1509
 
 
1510
   public SocketFactory getSocketFactory()
 
1511
   {
 
1512
      if (invoker != null)
 
1513
      {
 
1514
         return invoker.getSocketFactory();
 
1515
      }
 
1516
      else
 
1517
      {
 
1518
         return socketFactory;
 
1519
      }
 
1520
   }
 
1521
 
 
1522
   public ServerConfiguration getServerConfiguration()
 
1523
   {
 
1524
      return serverConfiguration;
 
1525
   }
 
1526
 
 
1527
   public void setServerConfiguration(ServerConfiguration serverConfig)
 
1528
   {
 
1529
      this.serverConfiguration = serverConfig;
 
1530
   }
 
1531
   
 
1532
   public void setRemoteClassLoaders(List classLoaders)
 
1533
   {
 
1534
      if (classLoaders == null)
 
1535
         return;
 
1536
 
 
1537
      SecurityManager sm = System.getSecurityManager();
 
1538
      if (sm != null)
 
1539
      {
 
1540
         sm.checkPermission(new RuntimePermission("setContextClassLoader"));
 
1541
      }
 
1542
      this.remoteClassLoaders = classLoaders;
 
1543
   }
 
1544
   
 
1545
   static private void unregisterMBean(final MBeanServer server, final ObjectName name)
 
1546
   throws Exception
 
1547
   {
 
1548
      if (SecurityUtility.skipAccessControl())
 
1549
      {
 
1550
         server.unregisterMBean(name);
 
1551
         return;
 
1552
      }
 
1553
      
 
1554
      try
 
1555
      {
 
1556
         AccessController.doPrivileged( new PrivilegedExceptionAction()
 
1557
         {
 
1558
            public Object run() throws Exception
 
1559
            {
 
1560
               server.unregisterMBean(name);
 
1561
               return null;
 
1562
            }
 
1563
         });
 
1564
      }
 
1565
      catch (PrivilegedActionException e)
 
1566
      {
 
1567
         throw (Exception) e.getCause();
 
1568
      }
 
1569
   }
 
1570
   
 
1571
   static private InetAddress getLocalHost() throws UnknownHostException
 
1572
   {
 
1573
      if (SecurityUtility.skipAccessControl())
 
1574
      {
 
1575
         return doGetLocalHost();
 
1576
      }
 
1577
 
 
1578
      try
 
1579
      {
 
1580
         return (InetAddress) AccessController.doPrivileged( new PrivilegedExceptionAction()
 
1581
         {
 
1582
            public Object run() throws UnknownHostException
 
1583
            {
 
1584
               return doGetLocalHost();
 
1585
            }
 
1586
         });
 
1587
      }
 
1588
      catch (PrivilegedActionException e)
 
1589
      {
 
1590
         throw (UnknownHostException) e.getCause();
 
1591
      }
 
1592
   }
 
1593
   
 
1594
   static private InetAddress doGetLocalHost() throws UnknownHostException
 
1595
   {
 
1596
      if (LOCAL_HOST != null)
 
1597
      {
 
1598
         return LOCAL_HOST;
 
1599
      }
 
1600
 
 
1601
      try
 
1602
      {
 
1603
         return InetAddress.getLocalHost();
 
1604
      }
 
1605
      catch (UnknownHostException e)
 
1606
      {
 
1607
         return InetAddress.getByName("127.0.0.1");
 
1608
      }
 
1609
   }
 
1610
}