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.
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.
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.
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.
23
package org.jboss.remoting.transport;
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;
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;
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;
63
import java.util.StringTokenizer;
66
* Connector is an implementation of the ConnectorMBean interface.
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.
71
* A transport connector is configured via *-service.xml such as:
73
* <?xml version="1.0" encoding="UTF-8"?>
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"/>
81
* <mbean code="org.jboss.remoting.transport.Connector"
82
* name="jboss.remoting:service=Connector,transport=Socket"
83
* display-name="Socket transport Connector">
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">
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>
106
* <handler subsystem="mock">org.jboss.remoting.transport.mock.MockServerInvocationHandler</handler>
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>
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."
131
public class Connector implements MBeanRegistration, ConnectorMBean
133
protected ServerInvoker invoker;
135
private String locatorURI;
138
private ServerConfiguration serverConfiguration;
140
private Map configuration = new HashMap();
142
private MBeanServer server;
144
private ServerSocketFactory svrSocketFactory;
145
private SocketFactory socketFactory;
147
private Connector marshallerLoaderConnector = null;
148
private boolean isMarshallerLoader = false;
149
private List remoteClassLoaders;
151
private boolean isStarted = false;
152
private boolean isCreated = false;
154
protected static final Logger log = Logger.getLogger(Connector.class);
155
private static final InetAddress LOCAL_HOST;
161
LOCAL_HOST = (InetAddress) AccessController.doPrivileged( new PrivilegedExceptionAction()
163
public Object run() throws UnknownHostException
167
return InetAddress.getLocalHost();
169
catch (UnknownHostException e)
171
return InetAddress.getByName("127.0.0.1");
176
catch (PrivilegedActionException e)
178
log.debug(Connector.class.getName() + " unable to get local host address", e.getCause());
179
throw new ExceptionInInitializerError(e.getCause());
181
catch (SecurityException e)
183
log.debug(Connector.class.getName() + " unable to get local host address", e);
197
* Creates Connector with specified locator.
201
public Connector(String locatorURI)
203
this.locatorURI = locatorURI;
207
* Creates Connector with specified locator.
211
public Connector(InvokerLocator locator)
215
this.locatorURI = locator.getLocatorURI();
220
* Constructs connector and populates configuration information.
222
* @param configuration
224
public Connector(Map configuration)
226
this.configuration.putAll(configuration);
230
* Constructs connector for given locator and configuration.
233
* @param configuration
235
public Connector(String locatorURI, Map configuration)
237
this.locatorURI = locatorURI;
238
this.configuration.putAll(configuration);
242
* Constructs connector for given locator and configuration.
245
* @param configuration
247
public Connector(InvokerLocator locator, Map configuration)
251
this.locatorURI = locator.getLocatorURI();
254
if (configuration != null)
256
this.configuration.putAll(configuration);
260
protected Connector(boolean isMarshallerConnector)
263
this.isMarshallerLoader = isMarshallerConnector;
267
* Indicates if the connector has been started yet.
271
public boolean isStarted()
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>
283
* The MBean can stop the registration by throwing an exception.The
284
* exception is forwarded to the invoker wrapped in an
285
* MBeanRegistrationException.
287
* @param server the MBeanServer the MBean is about to be
289
* @param name the suggested ObjectName supplied by the
291
* @return the actual ObjectName to register this MBean with.
292
* @throws Exception for any error, the MBean is not registered.
294
public ObjectName preRegister(MBeanServer server, ObjectName name)
297
this.server = server;
302
* This method is called by the MBeanServer after registration takes
303
* place or when registration fails.
305
* @param registrationDone the MBeanServer passes true when the
306
* MBean was registered, false otherwise.
308
public void postRegister(Boolean registrationDone)
313
* This method is called by the MBeanServer before deregistration takes
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.
320
public void preDeregister()
326
* This method is called by the MBeanServer after deregistration takes
329
public void postDeregister()
334
* Starts the connector. This is when configuration will be applied and server invoker created.
336
* @jmx.managed-operation description = "Start sets up the ServerInvoker we are wrapping."
339
public void start() throws Exception
344
// doing this for those who use remoting outside of jboss container
345
// so don't have to call create() and then start()
351
// want to have handlers registered before starting, so if someone makes invocation,
352
// there is something to handle it.
353
if (serverConfiguration != null)
355
configureHandlersFromServerConfiguration();
357
else if (xml != null)
359
configureHandlersFromXML();
362
// if marshaller loader not started, start it
363
if (!isMarshallerLoader)
365
if (marshallerLoaderConnector != null && !marshallerLoaderConnector.isStarted())
367
marshallerLoaderConnector.start();
371
// if invoker not started, start it
372
if (invoker.isStarted() == false)
380
if (marshallerLoaderConnector != null)
382
marshallerLoaderConnector.stop();
384
log.debug("Error starting connector.", e);
390
log.debug(this + " started");
396
* Starts the connector.
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.
402
public void start(boolean runAsNewThread) throws Exception
405
Runnable r = new Runnable()
415
log.error("Error starting Connector.", e);
419
Thread t = new Thread(r);
427
Map invokerConfig = new HashMap();
429
if (locatorURI == null)
431
// InvokerLocator attribute not set; check to see if serverConfiguration is set.
432
if (serverConfiguration != null)
434
getInvokerConfigFromServerConfiguration(invokerConfig);
436
// Check to see if Configuration attribute is set.
437
else if (xml != null)
439
getInvokerConfigFromXML(invokerConfig);
442
configuration.putAll(invokerConfig);
445
if (locatorURI == null)
447
throw new IllegalStateException("Connector not configured with LocatorURI.");
450
final InvokerLocator locator = new InvokerLocator(locatorURI);
454
// create the server invoker
457
invoker = (ServerInvoker) AccessController.doPrivileged( new PrivilegedExceptionAction()
459
public Object run() throws Exception
461
return InvokerRegistry.createServerInvoker(locator, configuration);
465
catch (PrivilegedActionException pae)
467
throw pae.getException();
470
invoker.setMBeanServer(server);
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
476
this.svrSocketFactory = null;
478
// set the socket factory if has been already set on the connector
479
invoker.setSocketFactory(socketFactory);
480
this.socketFactory = null;
484
// this will set the mbean server on the invoker and register it with mbean server
489
final ObjectName objName = new ObjectName(invoker.getMBeanObjectName());
493
AccessController.doPrivileged( new PrivilegedExceptionAction()
495
public Object run() throws Exception
497
if (!server.isRegistered(objName))
499
server.registerMBean(invoker, objName);
503
log.warn(objName + " is already registered with MBeanServer");
509
catch (PrivilegedActionException e)
511
throw (Exception) e.getCause();
517
log.warn("Error registering invoker " + invoker + " with MBeanServer.", e);
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();
526
if (remoteClassLoaders == null)
528
Object o = configuration.get(Remoting.REMOTE_CLASS_LOADERS);
529
if (o instanceof List)
531
setRemoteClassLoaders((List) o);
535
log.warn("value of " + Remoting.REMOTE_CLASS_LOADERS + " must be a List");
539
if (!isMarshallerLoader)
541
// need to check if should create a marshaller loader on the server side
542
if (marshallerLoaderConnector == null)
544
marshallerLoaderConnector = createMarshallerLoader(invoker.getLocator());
550
private Connector createMarshallerLoader(InvokerLocator locator)
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.
560
ClassLoader classLoader = (ClassLoader) AccessController.doPrivileged( new PrivilegedAction()
564
return Connector.class.getClassLoader();
568
MarshalFactory.getMarshaller(locator, classLoader, configuration);
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)
575
marshallerLoader = MarshallLoaderFactory.createMarshallLoader(loaderLocator, remoteClassLoaders, server);
577
return marshallerLoader;
580
private void getInvokerConfigFromXML(Map invokerConfig)
584
NodeList invokerNodes = xml.getElementsByTagName("invoker");
586
if (invokerNodes != null && invokerNodes.getLength() >= 1)
588
// only accept on invoker per connector at present
589
Node invokerNode = invokerNodes.item(0);
591
NamedNodeMap attributes = invokerNode.getAttributes();
592
Node transportNode = attributes.getNamedItem("transport");
594
if (transportNode != null)
596
String transport = transportNode.getNodeValue();
598
// need to log warning if there are more than one invoker elements
599
if (invokerNodes.getLength() > 1)
601
log.warn("Found more than one invokers defined in configuration. " +
602
"Will only be using the first one - " + transport);
605
// now create a map for all the sub attributes
606
Map paramConfig = new HashMap();
608
// In case of a multihome configuration.
609
List homes = new ArrayList();
610
List connectHomes = new ArrayList();
612
NodeList invokerAttributes = invokerNode.getChildNodes();
613
int len = invokerAttributes.getLength();
614
for (int x = 0; x < len; x++)
616
Node attr = invokerAttributes.item(x);
617
if ("attribute".equals(attr.getNodeName()))
619
String name = attr.getAttributes().getNamedItem("name").getNodeValue();
620
String value = attr.getFirstChild().getNodeValue();
621
if ("homes".equals(name))
623
processHomes(attr, "home", homes);
625
else if ("connecthomes".equals(name))
627
processHomes(attr, "connecthome", connectHomes);
631
invokerConfig.put(name, value);
633
Node isParamAttribute = attr.getAttributes().getNamedItem("isParam");
634
if (isParamAttribute != null && Boolean.valueOf(isParamAttribute.getNodeValue()).booleanValue())
636
paramConfig.put(name, value);
641
if (homes.isEmpty() && !connectHomes.isEmpty())
643
throw new Exception("Configuration has a " + InvokerLocator.CONNECT_HOMES_KEY +
644
" without a " + InvokerLocator.HOMES_KEY);
647
// should now have my map with all my attributes, now need to look for
648
// specific attributes that will impact the locator uri.
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();
656
String tempURI = null;
657
String path = (String) invokerConfig.get("path");
658
PortUtil.updateRange(invokerConfig);
660
if (homes.isEmpty() && connectHomes.isEmpty())
662
int port = clientConnectPort != null
663
? Integer.parseInt(clientConnectPort)
664
: serverBindPort != null
665
? Integer.parseInt(serverBindPort)
666
: PortUtil.findFreePort(serverBindAddress != null
669
String host = clientConnectAddress != null
670
? clientConnectAddress
671
: serverBindAddress != null
675
// finally, let's build the invoker uri
676
tempURI = transport + "://" + fixHostnameForURL(host) + ":" + port;
679
tempURI += "/" + path;
684
String port = clientConnectPort != null
685
? ":" + clientConnectPort
686
: serverBindPort != null
687
? ":" + serverBindPort
689
tempURI = transport + "://multihome" + port;
692
tempURI += "/" + path;
696
Iterator it = homes.iterator();
697
tempURI += "homes=" + it.next();
700
tempURI += "!" + it.next();
703
if (!connectHomes.isEmpty())
705
tempURI += "&connecthomes=";
706
it = connectHomes.iterator();
707
tempURI += it.next();
710
tempURI += "!" + it.next();
715
// any params to add to the uri?
716
if (paramConfig.size() > 0)
718
if (tempURI.indexOf("/?") < 0)
722
Iterator keyItr = paramConfig.keySet().iterator();
723
if (keyItr.hasNext())
725
Object name = keyItr.next();
726
Object value = paramConfig.get(name);
727
tempURI += name + "=" + value;
729
while (keyItr.hasNext())
732
Object name = keyItr.next();
733
Object value = paramConfig.get(name);
734
tempURI += name + "=" + value;
737
locatorURI = tempURI;
741
log.error("Invoker element within Configuration attribute does not contain a transport attribute.");
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.");
753
private void processHomes(Node node, String homeType, List homes)
755
NodeList nodes = node.getChildNodes();
756
for (int i = 0; i < nodes.getLength(); i++)
758
Node child = nodes.item(i);
759
if (Node.ELEMENT_NODE == child.getNodeType())
761
if (homeType.equals(child.getNodeName()))
763
NodeList children = child.getChildNodes();
764
for (int k = 0; k < children.getLength(); k++)
766
Node grandchild = children.item(k);
767
if (Node.TEXT_NODE == grandchild.getNodeType())
769
homes.add(grandchild.getNodeValue());
777
private void getInvokerConfigFromServerConfiguration(Map invokerConfig) throws Exception
781
String transport = serverConfiguration.getTransport();
783
if (transport == null)
785
log.error("ServerConfiguration must contain a non-null transport attribute.");
789
Map locatorParameters = serverConfiguration.getInvokerLocatorParameters();
790
Map serverParameters = serverConfiguration.getServerParameters();
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");
800
locatorParameters.remove("serverBindAddress");
801
log.warn("serverBindAddress in locator parameters will be ignored");
803
temp = (String) serverParameters.get("serverBindPort");
806
locatorParameters.remove("serverBindPort");
807
log.warn("serverBindPort in locator parameters will be ignored");
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);
816
if (locatorParameters.get(InvokerLocator.HOMES_KEY) == null)
817
locatorParameters.put(InvokerLocator.HOMES_KEY, temp);
819
log.warn(InvokerLocator.HOMES_KEY + " in server parameters will be ignored");
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)
826
throw new Exception("Configuration has a " + InvokerLocator.CONNECT_HOMES_KEY +
827
" without a " + InvokerLocator.HOMES_KEY);
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;
836
locatorParameters = new HashMap(serverConfiguration.getInvokerLocatorParameters());
837
serverParameters = new HashMap(serverConfiguration.getServerParameters());
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;
849
String path = (String) locatorParameters.remove("path");
850
PortUtil.updateRange(invokerConfig);
852
String tempURI = null;
853
boolean parametersStarted = false;
854
if (connectHomes == null && homes == null)
856
String localHostAddress = getLocalHost().getHostAddress();
858
// A single home configuration.
859
String host = clientConnectAddress != null
860
? clientConnectAddress
861
: serverBindAddress != null
865
int port = clientConnectPort != null
866
? Integer.parseInt(clientConnectPort)
867
: defaultPortString != null
868
? Integer.parseInt(defaultPortString)
869
: PortUtil.findFreePort(serverBindAddress != null
873
tempURI = transport + "://" + fixHostnameForURL(host) + ":" + port + ((path != null) ? ("/" + path) : "");
877
// A multihome configuration.
878
tempURI = transport + "://multihome" + ((path != null) ? ("/" + path) : "");
879
parametersStarted = true;
881
if (connectHomes != null)
883
tempURI += InvokerLocator.CONNECT_HOMES_KEY + "=" + connectHomes;
885
tempURI += "&" + InvokerLocator.HOMES_KEY + "=" + homes;
887
else if (homes != null)
888
tempURI += InvokerLocator.HOMES_KEY + "=" + homes;
891
// any params to add to the uri?
892
if (locatorParameters.size() > 0)
894
if (!parametersStarted)
898
Iterator keyItr = locatorParameters.keySet().iterator();
899
if (keyItr.hasNext())
901
Object name = keyItr.next();
902
Object value = locatorParameters.get(name);
903
tempURI += name + "=" + value;
905
while (keyItr.hasNext())
908
Object name = keyItr.next();
909
Object value = locatorParameters.get(name);
910
tempURI += name + "=" + value;
914
locatorURI = tempURI;
916
invokerConfig.putAll(serverConfiguration.getServerParameters());
917
invokerConfig.putAll((serverConfiguration.getInvokerLocatorParameters()));
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.");
927
// adds enclosing brackets if an IPv6 literal address
928
private String fixHostnameForURL(String address)
933
if (address.indexOf(':') != -1 && address.indexOf("[") == -1)
934
return "[" + address + "]" ;
939
private void configureHandlersFromServerConfiguration() throws Exception
941
Map handlerMap = serverConfiguration.getInvocationHandlers();
942
if (handlerMap.size() == 0 &&
943
(getInvocationHandlers() == null || getInvocationHandlers().length == 0))
945
throw new IllegalArgumentException("invocationHandlers list empty and are no registered handlers found.");
949
Iterator it = handlerMap.keySet().iterator();
952
String subsystems = (String) it.next();
953
Object value = handlerMap.get(subsystems);
954
ServerInvocationHandler handler = null;
956
if (value instanceof ServerInvocationHandler)
958
handler = (ServerInvocationHandler) value;
960
else if (value instanceof String)
962
//first check to see if this is an ObjectName
963
String valueString = (String) value;
964
boolean isObjName = false;
967
ObjectName objName = new ObjectName(valueString);
968
handler = createHandlerProxy(objName);
971
catch (MalformedObjectNameException e)
973
log.debug("Handler supplied is not an object name.");
978
Class serverInvocationHandlerClass = ClassLoaderUtility.loadClass(valueString, Connector.class);
979
handler = (ServerInvocationHandler) serverInvocationHandlerClass.newInstance();
984
throw new IllegalArgumentException("handler has invalid type: " + value);
987
StringTokenizer tok = new StringTokenizer(subsystems, ",");
989
while (tok.hasMoreTokens())
991
String subsystem = tok.nextToken();
992
addInvocationHandler(subsystem, handler);
997
private void configureHandlersFromXML() throws Exception
999
NodeList handlersNodes = xml.getElementsByTagName("handler");
1001
if ((handlersNodes == null || handlersNodes.getLength() <= 0) &&
1002
(getInvocationHandlers() == null || getInvocationHandlers().length == 0))
1004
throw new IllegalArgumentException("required 'handler' element not found and are no registered handlers found.");
1007
int len = handlersNodes.getLength();
1009
for (int c = 0; c < len; c++)
1011
Node node = handlersNodes.item(c);
1012
Node subNode = node.getAttributes().getNamedItem("subsystem");
1014
if (subNode == null)
1016
throw new IllegalArgumentException("Required 'subsystem' attribute on 'handler' element");
1019
String handlerClass = node.getFirstChild().getNodeValue();
1021
boolean isObjName = false;
1022
ServerInvocationHandler handler = null;
1024
//first check to see if this is an ObjectName
1027
ObjectName objName = new ObjectName(handlerClass);
1028
handler = createHandlerProxy(objName);
1031
catch (MalformedObjectNameException e)
1033
log.debug("Handler supplied is not an object name.");
1038
Class serverInvocationHandlerClass = ClassLoaderUtility.loadClass(handlerClass, Connector.class);
1039
handler = (ServerInvocationHandler) serverInvocationHandlerClass.newInstance();
1040
// handler = (ServerInvocationHandler) cl.loadClass(handlerClass).newInstance();
1043
StringTokenizer tok = new StringTokenizer(subNode.getNodeValue(), ",");
1045
while (tok.hasMoreTokens())
1047
String subsystem = tok.nextToken();
1048
addInvocationHandler(subsystem, handler);
1053
private ServerInvocationHandler createHandlerProxy(ObjectName objName)
1055
ServerInvocationHandler handler;
1058
handler = (ServerInvocationHandler)
1059
MBeanServerInvocationHandler.newProxyInstance(server,
1061
ServerInvocationHandler.class,
1063
handler = new ServerInvocationHandlerWrapper(handler);
1067
throw new RuntimeException("Can not register MBean invocation handler as the Connector has not been registered with a MBeanServer.");
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).
1078
* @jmx.managed-operation description = "Add a connection listener to call when detect that a client has
1079
* failed or disconnected."
1081
* @jmx.managed-parameter name = "listener"
1082
* type = "org.jboss.remoting.ConnectionListener"
1083
* description = "The connection listener to register"
1085
public void addConnectionListener(ConnectionListener listener)
1087
if (invoker != null)
1089
invoker.addConnectionListener(listener);
1094
* Removes connection listener from receiving client connection lost/disconnected
1098
* @jmx.managed-operation description = "Remove a client connection listener."
1100
* @jmx.managed-parameter name = "listener"
1101
* type = "org.jboss.remoting.ConnectionListener"
1102
* description = "The client connection listener to remove."
1104
public void removeConnectionListener(ConnectionListener listener)
1106
if (invoker != null)
1108
invoker.removeConnectionListener(listener);
1113
* Sets the lease period for client connections.
1114
* Value is in milliseconds.
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"
1122
public void setLeasePeriod(long leasePeriodValue)
1124
if (invoker != null)
1126
invoker.setLeasePeriod(leasePeriodValue);
1131
* Gets the lease period for client connections.
1132
* Value in milliseconds.
1135
* @jmx.managed-attribute
1137
public long getLeasePeriod()
1139
if (invoker != null)
1141
return invoker.getLeasePeriod();
1151
* Stops the connector. Will also stop and destroy server invoker (transport)
1153
* @jmx.managed-operation description = "Stop tears down the ServerInvoker we are wrapping."
1160
if (invoker != null)
1166
ObjectName objName = new ObjectName(invoker.getMBeanObjectName());
1167
unregisterMBean(server, objName);
1171
log.error("invalid Object Name", e);
1174
log.trace(this + " shutting down server invoker");
1178
AccessController.doPrivileged( new PrivilegedAction()
1182
InvokerRegistry.destroyServerInvoker(invoker);
1189
if (marshallerLoaderConnector != null && marshallerLoaderConnector.isStarted)
1191
marshallerLoaderConnector.stop();
1192
marshallerLoaderConnector = null;
1197
log.trace(this + " is stopped");
1201
* Creates the connector.
1203
* @jmx.managed-operation
1205
public void create()
1217
// unwind create process
1218
if (invoker != null)
1223
AccessController.doPrivileged( new PrivilegedAction()
1227
InvokerRegistry.destroyServerInvoker(invoker);
1241
* Destroys the connector.
1243
* @jmx.managed-operation
1245
public void destroy()
1251
if (invoker != null)
1256
AccessController.doPrivileged( new PrivilegedAction()
1260
InvokerRegistry.destroyServerInvoker(invoker);
1270
public ServerInvoker getServerInvoker()
1276
* Will get array of all the handlers registered with the connector's server invoker.
1280
public ServerInvocationHandler[] getInvocationHandlers()
1282
ServerInvocationHandler[] handlers = null;
1283
if (invoker != null)
1285
handlers = invoker.getInvocationHandlers();
1292
* Returns the locator to the connector. Locator is the actual InvokerLocator
1293
* object used to identify and get the ServerInvoker we are wrapping.
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"
1299
public InvokerLocator getLocator()
1301
return invoker.getLocator();
1305
* Sets the invoker locator. InvokerLocator is the string URI representation
1306
* of the InvokerLocator used to get and identify the ServerInvoker
1309
* @jmx.managed-attribute description = "InvokerLocator is the string URI representation of the
1310
* InvokerLocator used to get and identify the ServerInvoker
1312
* access = "read-write"
1314
public void setInvokerLocator(String locator)
1319
locatorURI = locator;
1323
throw new RuntimeException("Can not set the invoker locator on this Connector " +
1324
"as has already been created with a different locator.");
1330
* Returns the invoker locator. InvokerLocator is the string URI representation
1331
* of the InvokerLocator used to get and identify the ServerInvoker
1334
* @jmx.managed-attribute
1336
public String getInvokerLocator() throws Exception
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.
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
1350
* access = "read-write"
1352
public void setConfiguration(Element xml)
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.
1363
* @jmx.managed-attribute
1365
public Element getConfiguration()
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).
1376
* @param handlerObjectName
1377
* @return Previous ServerInvocatioHandler with the same subsystem value (case insensitive) or null if one did not previously exist.
1379
* @jmx.managed-operation description = "Add a subsystem invocation handler to the ServerInvoker
1380
* we wrap, identified by the subsystem parameter."
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"
1390
public ServerInvocationHandler addInvocationHandler(String subsystem, ObjectName handlerObjectName) throws Exception
1392
ServerInvocationHandler invocationHandler = createHandlerProxy(handlerObjectName);
1393
return addInvocationHandler(subsystem, invocationHandler);
1397
* Adds an invocation handler for the named subsystem to the invoker we
1398
* manage, and sets the mbean server on the invocation handler.
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."
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"
1412
public ServerInvocationHandler addInvocationHandler(String subsystem, final ServerInvocationHandler handler)
1415
if (invoker == null)
1417
throw new IllegalStateException("You may only add handlers once the Connector is created (via create() method).");
1420
// In case handler is an MBean.
1421
AccessController.doPrivileged( new PrivilegedAction()
1425
handler.setMBeanServer(server);
1429
return invoker.addInvocationHandler(subsystem, handler);
1433
* Removes an invocation handler for the supplied subsystem from the invoker
1434
* we manage, and unsets the MBeanServer on the handler.
1436
* @jmx.managed-operation description = "Remove a subsystem invocation handler to the
1437
* ServerInvoker we wrap, identified by the subsystem
1440
* @jmx.managed-parameter name = "subsystem"
1441
* type = "java.lang.String"
1442
* description = "The subsystem this handler is for."
1444
public void removeInvocationHandler(String subsystem) throws Exception
1446
ServerInvocationHandler handler = invoker.removeInvocationHandler(subsystem);
1448
if (handler != null)
1450
handler.setMBeanServer(null);
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
1459
public void setServerSocketFactory(ServerSocketFactory serverSocketFactory)
1463
throw new RuntimeException("Can not set server socket factory on Connector after the create() method has been called.");
1466
if (invoker != null)
1468
invoker.setServerSocketFactory(serverSocketFactory);
1472
this.svrSocketFactory = serverSocketFactory;
1476
public ServerSocketFactory getServerSocketFactory()
1478
if (invoker != null)
1480
return invoker.getServerSocketFactory();
1484
return svrSocketFactory;
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
1493
public void setSocketFactory(SocketFactory socketFactory)
1497
throw new RuntimeException("Can not set socket factory on Connector after the create() method has been called.");
1500
if (invoker != null)
1502
invoker.setSocketFactory(socketFactory);
1506
this.socketFactory = socketFactory;
1510
public SocketFactory getSocketFactory()
1512
if (invoker != null)
1514
return invoker.getSocketFactory();
1518
return socketFactory;
1522
public ServerConfiguration getServerConfiguration()
1524
return serverConfiguration;
1527
public void setServerConfiguration(ServerConfiguration serverConfig)
1529
this.serverConfiguration = serverConfig;
1532
public void setRemoteClassLoaders(List classLoaders)
1534
if (classLoaders == null)
1537
SecurityManager sm = System.getSecurityManager();
1540
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
1542
this.remoteClassLoaders = classLoaders;
1545
static private void unregisterMBean(final MBeanServer server, final ObjectName name)
1548
if (SecurityUtility.skipAccessControl())
1550
server.unregisterMBean(name);
1556
AccessController.doPrivileged( new PrivilegedExceptionAction()
1558
public Object run() throws Exception
1560
server.unregisterMBean(name);
1565
catch (PrivilegedActionException e)
1567
throw (Exception) e.getCause();
1571
static private InetAddress getLocalHost() throws UnknownHostException
1573
if (SecurityUtility.skipAccessControl())
1575
return doGetLocalHost();
1580
return (InetAddress) AccessController.doPrivileged( new PrivilegedExceptionAction()
1582
public Object run() throws UnknownHostException
1584
return doGetLocalHost();
1588
catch (PrivilegedActionException e)
1590
throw (UnknownHostException) e.getCause();
1594
static private InetAddress doGetLocalHost() throws UnknownHostException
1596
if (LOCAL_HOST != null)
1603
return InetAddress.getLocalHost();
1605
catch (UnknownHostException e)
1607
return InetAddress.getByName("127.0.0.1");