PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/projects/jboss-5.1.0/cluster/src/main/org/jboss/ha/jndi/DetachedHANamingService.java

https://gitlab.com/essere.lab.public/qualitas.class-corpus
Java | 883 lines | 622 code | 92 blank | 169 comment | 76 complexity | b07c2cab11d18d3c52f77e5335e6b31b MD5 | raw file
  1. /*
  2. * JBoss, Home of Professional Open Source.
  3. * Copyright 2008, Red Hat Middleware LLC, and individual contributors
  4. * as indicated by the @author tags. See the copyright.txt file in the
  5. * distribution for a 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. package org.jboss.ha.jndi;
  23. import java.io.IOException;
  24. import java.io.ObjectOutputStream;
  25. import java.io.OutputStream;
  26. import java.lang.reflect.InvocationTargetException;
  27. import java.lang.reflect.Method;
  28. import java.lang.reflect.UndeclaredThrowableException;
  29. import java.net.DatagramPacket;
  30. import java.net.Inet4Address;
  31. import java.net.InetAddress;
  32. import java.net.InetSocketAddress;
  33. import java.net.MulticastSocket;
  34. import java.net.ServerSocket;
  35. import java.net.Socket;
  36. import java.net.SocketAddress;
  37. import java.net.UnknownHostException;
  38. import java.rmi.MarshalledObject;
  39. import java.security.AccessController;
  40. import java.security.PrivilegedAction;
  41. import java.util.Collections;
  42. import java.util.HashMap;
  43. import java.util.Map;
  44. import javax.management.ObjectName;
  45. import javax.net.ServerSocketFactory;
  46. import org.jboss.ha.framework.interfaces.HAPartition;
  47. import org.jboss.ha.jndi.spi.DistributedTreeManager;
  48. import org.jboss.invocation.Invocation;
  49. import org.jboss.invocation.MarshalledInvocation;
  50. import org.jboss.logging.Logger;
  51. import org.jboss.system.ServiceMBeanSupport;
  52. import org.jboss.util.threadpool.BasicThreadPool;
  53. import org.jboss.util.threadpool.BasicThreadPoolMBean;
  54. import org.jboss.util.threadpool.ThreadPool;
  55. import org.jnp.interfaces.Naming;
  56. import org.jnp.interfaces.NamingContext;
  57. /**
  58. * Management Bean for the protocol independent HA-JNDI service. This allows the
  59. * naming service transport layer to be provided by a detached invoker service
  60. * like JRMPInvokerHA + ProxyFactoryHA.
  61. * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
  62. * @author <a href="mailto:sacha.labourey@cogito-info.ch">Sacha Labourey</a>
  63. * @author Scott.Stark@jboss.org
  64. * @version $Revision: 80406 $
  65. */
  66. public class DetachedHANamingService
  67. extends ServiceMBeanSupport
  68. implements DetachedHANamingServiceMBean
  69. {
  70. // Constants -----------------------------------------------------
  71. // Attributes ----------------------------------------------------
  72. /**
  73. * The jnp server socket through which the HAJNDI stub is vended
  74. */
  75. ServerSocket bootstrapSocket;
  76. /**
  77. * The Naming interface server implementation
  78. */
  79. HAJNDI theServer;
  80. /**
  81. * The mapping from the long method hash to the Naming Method
  82. */
  83. private Map<Long, Method> marshalledInvocationMapping;
  84. /**
  85. * The protocol stub returned to clients by the bootstrap lookup
  86. */
  87. Naming stub;
  88. /**
  89. * The HAPartition
  90. */
  91. protected HAPartition clusterPartition;
  92. /**
  93. * The manager of our distributed bindings
  94. */
  95. private DistributedTreeManager distributedTreeManager;
  96. /**
  97. * The proxy factory service that generates the Naming stub
  98. */
  99. private ObjectName proxyFactory;
  100. /**
  101. * The local (non-HA) Naming instance.
  102. */
  103. private Naming localNamingInstance;
  104. /**
  105. * The interface to bind to. This is useful for multi-homed hosts that want
  106. * control over which interfaces accept connections.
  107. */
  108. InetAddress bindAddress;
  109. /**
  110. * The bootstrapSocket listen queue depth
  111. */
  112. private int backlog = 50;
  113. /**
  114. * The jnp protocol listening port. The default is 1100, the same as the RMI
  115. * registry default port.
  116. */
  117. int port = 1100;
  118. /**
  119. * The autodiscovery multicast group
  120. */
  121. String adGroupAddress = NamingContext.DEFAULT_DISCOVERY_GROUP_ADDRESS;
  122. /**
  123. * The autodiscovery port
  124. */
  125. int adGroupPort = NamingContext.DEFAULT_DISCOVERY_GROUP_PORT;
  126. /**
  127. * The interface to bind the Multicast socket for autodiscovery to
  128. */
  129. InetAddress discoveryBindAddress;
  130. /** The runable task for discovery request packets */
  131. private AutomaticDiscovery autoDiscovery = null;
  132. /** A flag indicating if autodiscovery should be disabled */
  133. private boolean discoveryDisabled = false;
  134. /** The autodiscovery Multicast reply TTL */
  135. int autoDiscoveryTTL = 16;
  136. /**
  137. * An optional custom server socket factory for the bootstrap lookup
  138. */
  139. private ServerSocketFactory jnpServerSocketFactory;
  140. /**
  141. * The class name of the optional custom JNP server socket factory
  142. */
  143. private String jnpServerSocketFactoryName;
  144. /**
  145. * The thread pool used to handle jnp stub lookup requests
  146. */
  147. ThreadPool lookupPool;
  148. // Public --------------------------------------------------------
  149. public DetachedHANamingService()
  150. {
  151. // for JMX
  152. }
  153. /**
  154. * Expose the Naming service interface mapping as a read-only attribute
  155. * @return A Map<Long hash, Method> of the Naming interface
  156. * @jmx:managed-attribute
  157. */
  158. public Map<Long, Method> getMethodMap()
  159. {
  160. return this.marshalledInvocationMapping;
  161. }
  162. public String getPartitionName()
  163. {
  164. return this.clusterPartition.getPartitionName();
  165. }
  166. public HAPartition getHAPartition()
  167. {
  168. return this.clusterPartition;
  169. }
  170. public void setHAPartition(HAPartition clusterPartition)
  171. {
  172. this.clusterPartition = clusterPartition;
  173. }
  174. public DistributedTreeManager getDistributedTreeManager ()
  175. {
  176. return this.distributedTreeManager;
  177. }
  178. public void setDistributedTreeManager (DistributedTreeManager distributedTreeManager )
  179. {
  180. this.distributedTreeManager = distributedTreeManager;
  181. }
  182. public Naming getLocalNamingInstance()
  183. {
  184. return localNamingInstance;
  185. }
  186. public void setLocalNamingInstance(Naming localNamingInstance)
  187. {
  188. this.localNamingInstance = localNamingInstance;
  189. }
  190. public ObjectName getProxyFactoryObjectName()
  191. {
  192. return this.proxyFactory;
  193. }
  194. public void setProxyFactoryObjectName(ObjectName proxyFactory)
  195. {
  196. this.proxyFactory = proxyFactory;
  197. }
  198. public void setPort(int p)
  199. {
  200. this.port = p;
  201. }
  202. public int getPort()
  203. {
  204. return this.port;
  205. }
  206. public String getBindAddress()
  207. {
  208. String address = null;
  209. if (this.bindAddress != null)
  210. {
  211. address = this.bindAddress.getHostAddress();
  212. }
  213. return address;
  214. }
  215. public void setBindAddress(String host) throws java.net.UnknownHostException
  216. {
  217. this.bindAddress = InetAddress.getByName(host);
  218. }
  219. public int getBacklog()
  220. {
  221. return this.backlog;
  222. }
  223. public void setBacklog(int backlog)
  224. {
  225. if (backlog <= 0)
  226. {
  227. backlog = 50;
  228. }
  229. this.backlog = backlog;
  230. }
  231. public void setDiscoveryDisabled(boolean disable)
  232. {
  233. this.discoveryDisabled = disable;
  234. }
  235. public boolean getDiscoveryDisabled()
  236. {
  237. return this.discoveryDisabled;
  238. }
  239. public String getAutoDiscoveryAddress()
  240. {
  241. return this.adGroupAddress;
  242. }
  243. public void setAutoDiscoveryAddress(String adAddress)
  244. {
  245. this.adGroupAddress = adAddress;
  246. }
  247. public int getAutoDiscoveryGroup()
  248. {
  249. return this.adGroupPort;
  250. }
  251. public void setAutoDiscoveryGroup(int adGroup)
  252. {
  253. this.adGroupPort = adGroup;
  254. }
  255. public String getAutoDiscoveryBindAddress()
  256. {
  257. return (this.discoveryBindAddress != null) ? this.discoveryBindAddress.getHostAddress() : null;
  258. }
  259. public void setAutoDiscoveryBindAddress(String address) throws UnknownHostException
  260. {
  261. this.discoveryBindAddress = InetAddress.getByName(address);
  262. }
  263. public int getAutoDiscoveryTTL()
  264. {
  265. return this.autoDiscoveryTTL;
  266. }
  267. public void setAutoDiscoveryTTL(int ttl)
  268. {
  269. this.autoDiscoveryTTL = ttl;
  270. }
  271. public void setJNPServerSocketFactory(String factoryClassName) throws ClassNotFoundException, InstantiationException, IllegalAccessException
  272. {
  273. this.jnpServerSocketFactoryName = factoryClassName;
  274. ClassLoader loader = Thread.currentThread().getContextClassLoader();
  275. Class<?> clazz = loader.loadClass(this.jnpServerSocketFactoryName);
  276. this.jnpServerSocketFactory = (ServerSocketFactory) clazz.newInstance();
  277. }
  278. public void setLookupPool(BasicThreadPoolMBean poolMBean)
  279. {
  280. this.lookupPool = poolMBean.getInstance();
  281. }
  282. /*
  283. public void startService(HAPartition haPartition)
  284. throws Exception
  285. {
  286. this.startService();
  287. }
  288. */
  289. @Override
  290. protected void createService() throws Exception
  291. {
  292. if (this.clusterPartition == null)
  293. {
  294. throw new IllegalStateException("HAPartition property must be set before starting HAJNDI service");
  295. }
  296. if (this.distributedTreeManager == null)
  297. {
  298. throw new IllegalStateException("DistributedTreeManager property must be set before starting HAJNDI service");
  299. }
  300. this.log.debug("Initializing HAJNDI server on partition: " + this.clusterPartition.getPartitionName());
  301. // Start HAJNDI service
  302. this.theServer = new HAJNDI(this.clusterPartition, this.distributedTreeManager, localNamingInstance);
  303. // Build the Naming interface method map
  304. Map<Long, Method> map = new HashMap<Long, Method>(13);
  305. Method[] methods = Naming.class.getMethods();
  306. for (Method method: methods)
  307. {
  308. Long hash = new Long(MarshalledInvocation.calculateHash(method));
  309. map.put(hash, method);
  310. }
  311. this.marshalledInvocationMapping = Collections.unmodifiableMap(map);
  312. // share instance for in-vm discovery
  313. NamingContext.setHANamingServerForPartition(this.clusterPartition.getPartitionName(), this.theServer);
  314. }
  315. @Override
  316. protected void startService()
  317. throws Exception
  318. {
  319. this.log.debug("Obtaining the HAJNDI transport proxy");
  320. this.stub = this.getNamingProxy();
  321. this.distributedTreeManager.setHAStub(this.stub);
  322. if (this.port >= 0)
  323. {
  324. this.log.debug("Starting HAJNDI bootstrap listener");
  325. this.initBootstrapListener();
  326. }
  327. // Automatic Discovery for unconfigured clients
  328. if (this.adGroupAddress != null && this.discoveryDisabled == false)
  329. {
  330. try
  331. {
  332. this.autoDiscovery = new AutomaticDiscovery();
  333. this.autoDiscovery.start();
  334. this.lookupPool.run(this.autoDiscovery);
  335. }
  336. catch (Exception e)
  337. {
  338. this.log.warn("Failed to start AutomaticDiscovery", e);
  339. }
  340. }
  341. this.log.debug("initializing HAJNDI");
  342. this.theServer.init();
  343. }
  344. @Override
  345. protected void stopService() throws Exception
  346. {
  347. // un-share instance for in-vm discovery
  348. NamingContext.removeHANamingServerForPartition(this.clusterPartition.getPartitionName());
  349. // Stop listener
  350. ServerSocket s = this.bootstrapSocket;
  351. this.bootstrapSocket = null;
  352. if (s != null)
  353. {
  354. this.log.debug("Closing the HAJNDI bootstrap listener");
  355. s.close();
  356. }
  357. // Stop HAJNDI service
  358. this.log.debug("Stopping the HAJNDI service");
  359. this.theServer.shutdown();
  360. this.log.debug("Stopping AutomaticDiscovery");
  361. if (this.autoDiscovery != null && this.discoveryDisabled == false)
  362. {
  363. this.autoDiscovery.stop();
  364. }
  365. }
  366. @Override
  367. protected void destroyService() throws Exception
  368. {
  369. this.log.debug("Destroying the HAJNDI service");
  370. }
  371. /**
  372. * Expose the Naming service via JMX to invokers.
  373. * @param invocation A pointer to the invocation object
  374. * @return Return value of method invocation.
  375. * @throws Exception Failed to invoke method.
  376. * @jmx:managed-operation
  377. */
  378. public Object invoke(Invocation invocation) throws Exception
  379. {
  380. // Set the method hash to Method mapping
  381. if (invocation instanceof MarshalledInvocation)
  382. {
  383. MarshalledInvocation mi = (MarshalledInvocation) invocation;
  384. mi.setMethodMap(this.marshalledInvocationMapping);
  385. }
  386. // Invoke the Naming method via reflection
  387. Method method = invocation.getMethod();
  388. Object[] args = invocation.getArguments();
  389. Object value = null;
  390. try
  391. {
  392. value = method.invoke(this.theServer, args);
  393. }
  394. catch (InvocationTargetException e)
  395. {
  396. Throwable t = e.getTargetException();
  397. if (t instanceof Exception)
  398. {
  399. throw (Exception) t;
  400. }
  401. throw new UndeclaredThrowableException(t, method.toString());
  402. }
  403. return value;
  404. }
  405. /**
  406. * Bring up the bootstrap lookup port for obtaining the naming service proxy
  407. */
  408. protected void initBootstrapListener()
  409. {
  410. // Start listener
  411. try
  412. {
  413. // Get the default ServerSocketFactory is one was not specified
  414. if (this.jnpServerSocketFactory == null)
  415. {
  416. this.jnpServerSocketFactory = ServerSocketFactory.getDefault();
  417. }
  418. this.bootstrapSocket = this.jnpServerSocketFactory.createServerSocket(this.port, this.backlog, this.bindAddress);
  419. // If an anonymous port was specified get the actual port used
  420. if (this.port == 0)
  421. {
  422. this.port = this.bootstrapSocket.getLocalPort();
  423. }
  424. String msg = "Started HAJNDI bootstrap; jnpPort=" + this.port
  425. + ", backlog=" + this.backlog + ", bindAddress=" + this.bindAddress;
  426. this.log.info(msg);
  427. }
  428. catch (IOException e)
  429. {
  430. this.log.error("Could not start HAJNDI bootstrap listener on port " + this.port, e);
  431. }
  432. if (this.lookupPool == null)
  433. {
  434. this.lookupPool = new BasicThreadPool("HANamingBootstrap Pool");
  435. }
  436. AcceptHandler handler = new AcceptHandler();
  437. this.lookupPool.run(handler);
  438. }
  439. // Protected -----------------------------------------------------
  440. /**
  441. * Get the Naming proxy for the transport. This version looks up the
  442. * proxyFactory service Proxy attribute. Subclasses can override this to set
  443. * the proxy another way.
  444. * @return The Naming proxy for the protocol used with the HAJNDI service
  445. */
  446. protected Naming getNamingProxy() throws Exception
  447. {
  448. return (Naming) this.server.getAttribute(this.proxyFactory, "Proxy");
  449. }
  450. // Private -------------------------------------------------------
  451. private class AutomaticDiscovery
  452. implements Runnable
  453. {
  454. private Logger log = Logger.getLogger(AutomaticDiscovery.class);
  455. /** The socket for auto discovery requests */
  456. private MulticastSocket socket = null;
  457. /** The ha-jndi addres + ':' + port string */
  458. private byte[] ipAddress = null;
  459. /** The multicast group address */
  460. private InetAddress group = null;
  461. private volatile boolean stopping = false;
  462. // Thread that is executing the run() method
  463. private volatile Thread receiverThread = null;
  464. private volatile boolean receiverStopped = true;
  465. public AutomaticDiscovery() throws Exception
  466. {
  467. }
  468. public void start() throws Exception
  469. {
  470. this.stopping = false;
  471. // Set up the multicast socket on which we listen for discovery requests
  472. this.group = InetAddress.getByName(DetachedHANamingService.this.adGroupAddress);
  473. // On Linux, we avoid cross-talk problem by binding the MulticastSocket
  474. // to the multicast address. See https://jira.jboss.org/jira/browse/JGRP-777
  475. if(checkForPresence("os.name", "linux"))
  476. {
  477. this.socket = createMulticastSocket(group, DetachedHANamingService.this.adGroupPort);
  478. }
  479. else
  480. {
  481. this.socket = new MulticastSocket(DetachedHANamingService.this.adGroupPort);
  482. }
  483. // If there is a valid bind address, set the socket interface to it
  484. // Use the jndi bind address if there is no discovery address
  485. if (DetachedHANamingService.this.discoveryBindAddress == null)
  486. {
  487. DetachedHANamingService.this.discoveryBindAddress = DetachedHANamingService.this.bindAddress;
  488. }
  489. if (DetachedHANamingService.this.discoveryBindAddress != null
  490. && DetachedHANamingService.this.discoveryBindAddress.isAnyLocalAddress() == false)
  491. {
  492. this.socket.setInterface(DetachedHANamingService.this.discoveryBindAddress);
  493. }
  494. this.socket.setTimeToLive(DetachedHANamingService.this.autoDiscoveryTTL);
  495. this.socket.joinGroup(this.group);
  496. // Determine the hostname:port string we will return to discovery requests
  497. String address = DetachedHANamingService.this.getBindAddress();
  498. /* An INADDR_ANY (0.0.0.0 || null) address is useless as the value
  499. sent to a remote client so check for this and use the local host
  500. address instead.
  501. */
  502. if (address == null || address.equals("0.0.0.0"))
  503. {
  504. address = InetAddress.getLocalHost().getHostAddress();
  505. }
  506. this.ipAddress = (address + ":" + DetachedHANamingService.this.port).getBytes();
  507. this.log.info("Listening on " + this.socket.getInterface() + ":" + this.socket.getLocalPort()
  508. + ", group=" + DetachedHANamingService.this.adGroupAddress
  509. + ", HA-JNDI address=" + new String(this.ipAddress));
  510. }
  511. public void stop()
  512. {
  513. try
  514. {
  515. this.stopping = true;
  516. // JBAS-2834 -- try to stop the receiverThread
  517. if (this.receiverThread != null
  518. && this.receiverThread != Thread.currentThread()
  519. && this.receiverThread.isInterrupted() == false)
  520. {
  521. // Give it a moment to die on its own (unlikely)
  522. this.receiverThread.join(5);
  523. if (!this.receiverStopped)
  524. {
  525. this.receiverThread.interrupt(); // kill it
  526. }
  527. }
  528. this.socket.leaveGroup(this.group);
  529. this.socket.close();
  530. }
  531. catch (Exception ex)
  532. {
  533. this.log.error("Stopping AutomaticDiscovery failed", ex);
  534. }
  535. }
  536. public void run()
  537. {
  538. boolean trace = this.log.isTraceEnabled();
  539. this.log.debug("Discovery request thread begin");
  540. // JBAS-2834 Cache a reference to this thread so stop()
  541. // can interrupt it if necessary
  542. this.receiverThread = Thread.currentThread();
  543. this.receiverStopped = false;
  544. // Wait for a datagram
  545. while (true)
  546. {
  547. // Stopped by normal means
  548. if (this.stopping)
  549. {
  550. break;
  551. }
  552. try
  553. {
  554. if (trace)
  555. {
  556. this.log.trace("HA-JNDI AutomaticDiscovery waiting for queries...");
  557. }
  558. byte[] buf = new byte[256];
  559. DatagramPacket packet = new DatagramPacket(buf, buf.length);
  560. this.socket.receive(packet);
  561. if (trace)
  562. {
  563. this.log.trace("HA-JNDI AutomaticDiscovery Packet received.");
  564. }
  565. // Queue the response to the thread pool
  566. DiscoveryRequestHandler handler = new DiscoveryRequestHandler(this.log,
  567. packet, this.socket, this.ipAddress);
  568. DetachedHANamingService.this.lookupPool.run(handler);
  569. if (trace)
  570. {
  571. this.log.trace("Queued DiscoveryRequestHandler");
  572. }
  573. }
  574. catch (Throwable t)
  575. {
  576. if (this.stopping == false)
  577. {
  578. this.log.warn("Ignored error while processing HAJNDI discovery request:", t);
  579. }
  580. }
  581. }
  582. this.receiverStopped = true;
  583. this.log.debug("Discovery request thread end");
  584. }
  585. private boolean checkForPresence(final String key, String value)
  586. {
  587. try
  588. {
  589. String tmp = null;
  590. if (System.getSecurityManager() == null)
  591. {
  592. tmp = System.getProperty(key);
  593. }
  594. else
  595. {
  596. // Use a different local var to limit scope of @SuppressWarnings
  597. @SuppressWarnings("unchecked")
  598. String prop = (String) AccessController.doPrivileged(new PrivilegedAction()
  599. {
  600. public Object run()
  601. {
  602. return System.getProperty(key);
  603. }
  604. });
  605. tmp = prop;
  606. }
  607. return tmp != null && tmp.trim().toLowerCase().startsWith(value);
  608. }
  609. catch (Throwable t)
  610. {
  611. return false;
  612. }
  613. }
  614. private MulticastSocket createMulticastSocket(InetAddress mcast_addr, int port) throws IOException
  615. {
  616. if(mcast_addr != null && !mcast_addr.isMulticastAddress()) {
  617. log.warn("mcast_addr (" + mcast_addr + ") is not a multicast address, will be ignored");
  618. return new MulticastSocket(port);
  619. }
  620. SocketAddress saddr=new InetSocketAddress(mcast_addr, port);
  621. MulticastSocket retval=null;
  622. try {
  623. retval=new MulticastSocket(saddr);
  624. }
  625. catch(IOException ex) {
  626. StringBuilder sb=new StringBuilder();
  627. String type=mcast_addr != null ? mcast_addr instanceof Inet4Address? "IPv4" : "IPv6" : "n/a";
  628. sb.append("could not bind to " + mcast_addr + " (" + type + " address)");
  629. sb.append("; make sure your mcast_addr is of the same type as the IP stack (IPv4 or IPv6).");
  630. sb.append("\nWill ignore mcast_addr, but this may lead to cross talking " +
  631. "(see http://www.jboss.com/wiki/Edit.jsp?page=CrossTalking for details). ");
  632. sb.append("\nException was: " + ex);
  633. log.warn(sb);
  634. }
  635. if(retval == null)
  636. {
  637. retval=new MulticastSocket(port);
  638. }
  639. return retval;
  640. }
  641. }
  642. /**
  643. * The class used as the runnable for writing the bootstrap stub
  644. */
  645. private class DiscoveryRequestHandler implements Runnable
  646. {
  647. private Logger log;
  648. private MulticastSocket socket;
  649. private DatagramPacket packet;
  650. private byte[] ipAddress;
  651. DiscoveryRequestHandler(Logger log, DatagramPacket packet,
  652. MulticastSocket socket, byte[] ipAddress)
  653. {
  654. this.log = log;
  655. this.packet = packet;
  656. this.socket = socket;
  657. this.ipAddress = ipAddress;
  658. }
  659. public void run()
  660. {
  661. boolean trace = this.log.isTraceEnabled();
  662. if( trace )
  663. {
  664. this.log.trace("DiscoveryRequestHandler begin");
  665. }
  666. // Return the naming server IP address and port to the client
  667. try
  668. {
  669. // See if the discovery is restricted to a particular parition
  670. String requestData = new String(this.packet.getData()).trim();
  671. if( trace )
  672. {
  673. this.log.trace("RequestData: "+requestData);
  674. }
  675. int colon = requestData.indexOf(':');
  676. if (colon > 0)
  677. {
  678. // Check the partition name
  679. String name = requestData.substring(colon + 1);
  680. if (name.equals(DetachedHANamingService.this.clusterPartition.getPartitionName()) == false)
  681. {
  682. this.log.debug("Ignoring discovery request for partition: " + name);
  683. if( trace )
  684. {
  685. this.log.trace("DiscoveryRequestHandler end");
  686. }
  687. return;
  688. }
  689. }
  690. DatagramPacket p = new DatagramPacket(this.ipAddress, this.ipAddress.length,
  691. this.packet.getAddress(), this.packet.getPort());
  692. if (trace)
  693. {
  694. this.log.trace("Sending AutomaticDiscovery answer: " + new String(this.ipAddress) +
  695. " to " + this.packet.getAddress() + ":" + this.packet.getPort());
  696. }
  697. this.socket.send(p);
  698. if (trace)
  699. {
  700. this.log.trace("AutomaticDiscovery answer sent.");
  701. }
  702. }
  703. catch (IOException ex)
  704. {
  705. this.log.error("Error writing response", ex);
  706. }
  707. if( trace )
  708. {
  709. this.log.trace("DiscoveryRequestHandler end");
  710. }
  711. }
  712. }
  713. /**
  714. * The class used as the runnable for the bootstrap lookup thread pool.
  715. */
  716. private class AcceptHandler implements Runnable
  717. {
  718. AcceptHandler()
  719. {
  720. }
  721. public void run()
  722. {
  723. boolean trace = DetachedHANamingService.this.log.isTraceEnabled();
  724. while (DetachedHANamingService.this.bootstrapSocket != null)
  725. {
  726. Socket socket = null;
  727. // Accept a connection
  728. try
  729. {
  730. socket = DetachedHANamingService.this.bootstrapSocket.accept();
  731. if (trace)
  732. {
  733. DetachedHANamingService.this.log.trace("Accepted bootstrap client: "+socket);
  734. }
  735. BootstrapRequestHandler handler = new BootstrapRequestHandler(socket);
  736. DetachedHANamingService.this.lookupPool.run(handler);
  737. }
  738. catch (IOException e)
  739. {
  740. // Stopped by normal means
  741. if (DetachedHANamingService.this.bootstrapSocket == null)
  742. {
  743. return;
  744. }
  745. DetachedHANamingService.this.log.error("Naming accept handler stopping", e);
  746. }
  747. catch(Throwable e)
  748. {
  749. DetachedHANamingService.this.log.error("Unexpected exception during accept", e);
  750. }
  751. }
  752. }
  753. }
  754. /**
  755. * The class used as the runnable for writing the bootstrap stub
  756. */
  757. private class BootstrapRequestHandler implements Runnable
  758. {
  759. private Socket socket;
  760. BootstrapRequestHandler(Socket socket)
  761. {
  762. this.socket = socket;
  763. }
  764. public void run()
  765. {
  766. // Return the naming server stub
  767. try
  768. {
  769. OutputStream os = this.socket.getOutputStream();
  770. ObjectOutputStream out = new ObjectOutputStream(os);
  771. MarshalledObject replyStub = new MarshalledObject(DetachedHANamingService.this.stub);
  772. out.writeObject(replyStub);
  773. out.close();
  774. }
  775. catch (IOException ex)
  776. {
  777. DetachedHANamingService.this.log.debug("Error writing response to " + this.socket, ex);
  778. }
  779. finally
  780. {
  781. try
  782. {
  783. this.socket.close();
  784. }
  785. catch (IOException e)
  786. {
  787. }
  788. }
  789. }
  790. }
  791. }