KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mq > il > oil2 > OIL2ServerILService


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.mq.il.oil2;
8
9 import java.io.BufferedInputStream JavaDoc;
10 import java.io.BufferedOutputStream JavaDoc;
11 import java.io.IOException JavaDoc;
12 import java.io.ObjectInputStream JavaDoc;
13 import java.io.ObjectOutputStream JavaDoc;
14 import java.lang.reflect.Method JavaDoc;
15 import java.net.InetAddress JavaDoc;
16 import java.net.ServerSocket JavaDoc;
17 import java.net.Socket JavaDoc;
18 import java.net.SocketException JavaDoc;
19 import java.net.UnknownHostException JavaDoc;
20 import java.rmi.RemoteException JavaDoc;
21 import java.util.Properties JavaDoc;
22
23 import javax.jms.Destination JavaDoc;
24 import javax.jms.JMSException JavaDoc;
25 import javax.naming.InitialContext JavaDoc;
26 import javax.net.ServerSocketFactory;
27
28 import org.jboss.logging.Logger;
29 import org.jboss.mq.AcknowledgementRequest;
30 import org.jboss.mq.ConnectionToken;
31 import org.jboss.mq.DurableSubscriptionID;
32 import org.jboss.mq.SpyDestination;
33 import org.jboss.mq.SpyMessage;
34 import org.jboss.mq.Subscription;
35 import org.jboss.mq.TransactionRequest;
36 import org.jboss.mq.il.Invoker;
37 import org.jboss.mq.il.ServerIL;
38 import org.jboss.security.SecurityDomain;
39
40 /**
41  * Implements the ServerILJMXService which is used to manage the OIL2 IL.
42  *
43  * @author <a HREF="mailto:hiram.chirino@jboss.org">Hiram Chirino</a>
44  * @version $Revision: 1.22 $
45  * @jmx:mbean extends="org.jboss.mq.il.ServerILJMXServiceMBean"
46  */

47 public final class OIL2ServerILService
48    extends org.jboss.mq.il.ServerILJMXService
49    implements java.lang.Runnable JavaDoc, OIL2ServerILServiceMBean
50 {
51    /**
52     * logger instance.
53     */

54    final static private Logger log = Logger.getLogger(OIL2ServerILService.class);
55
56    /**
57     * The default timeout for the server socket. This is
58     * set so the socket will periodically return to check
59     * the running flag.
60     */

61    private final static int SO_TIMEOUT = 5000;
62
63    /**
64     * The JMS server where requests are forwarded to.
65     */

66    //private static JMSServerInvoker server;
67
private Invoker server;
68
69    /**
70     * If the TcpNoDelay option should be used on the socket.
71     */

72    private boolean enableTcpNoDelay = false;
73
74    /** The security domain name to use with SSL aware socket factories.
75     */

76    private String JavaDoc securityDomain;
77
78    /* The javax.net.SocketFactory implementation class to use on the client.
79     */

80    private String JavaDoc clientSocketFactoryName;
81    /** The socket factory used to obtain the server socket.
82     */

83    private ServerSocketFactory serverSocketFactory;
84    /**
85     * The listening socket that receives incomming connections
86     * for servicing.
87     */

88    private ServerSocket JavaDoc serverSocket;
89
90    /**
91     * The managed serverIL.
92     */

93    private OIL2ServerIL serverIL;
94
95    /**
96     * The running flag that all worker and server
97     * threads check to determine if the service should
98     * be stopped.
99     */

100    private volatile boolean running;
101
102    /**
103     * The server port to bind to.
104     */

105    private int serverBindPort = 0;
106
107    /**
108     * The internet address to bind to by
109     * default.
110     */

111    private InetAddress JavaDoc bindAddress = null;
112
113    /**
114     * The connection properties passed to the client to connect to this IL
115     */

116    private Properties JavaDoc connectionProperties;
117
118    public class RequestListner implements OIL2RequestListner
119    {
120
121       Socket JavaDoc socket;
122       ObjectInputStream JavaDoc in;
123       ObjectOutputStream JavaDoc out;
124       OIL2SocketHandler socketHandler;
125       ConnectionToken connectionToken;
126       boolean closing = false;
127
128       RequestListner(Socket JavaDoc socket) throws IOException JavaDoc
129       {
130          socket.setSoTimeout(0);
131          socket.setTcpNoDelay(enableTcpNoDelay);
132          out = new ObjectOutputStream JavaDoc(new BufferedOutputStream JavaDoc(socket.getOutputStream()));
133          out.flush();
134          in = new ObjectInputStream JavaDoc(new BufferedInputStream JavaDoc(socket.getInputStream()));
135       }
136
137       public void handleRequest(OIL2Request request)
138       {
139          // if( log.isTraceEnabled() )
140
// log.trace("RequestListner handing request: "+request);
141

142          if (closing)
143          {
144             log.trace("A connection that is closing received another request. Droping request.");
145             return;
146          }
147
148          Object JavaDoc result = null;
149          Exception JavaDoc resultException = null;
150
151          // now based upon the input directive, preform the
152
// requested action. Any exceptions are processed
153
// and potentially returned to the client.
154
//
155
try
156          {
157             switch (request.operation)
158             {
159                case OIL2Constants.SERVER_SET_SPY_DISTRIBUTED_CONNECTION :
160                   connectionToken = (ConnectionToken) request.arguments[0];
161                   // Make the client IL aware of us since he will be using our requestHander
162
// To make requests.
163
((OIL2ClientIL) connectionToken.clientIL).setRequestListner(this);
164                   break;
165
166                case OIL2Constants.SERVER_ACKNOWLEDGE :
167                   server.acknowledge(connectionToken, (AcknowledgementRequest) request.arguments[0]);
168                   break;
169
170                case OIL2Constants.SERVER_ADD_MESSAGE :
171                   server.addMessage(connectionToken, (SpyMessage) request.arguments[0]);
172                   break;
173
174                case OIL2Constants.SERVER_BROWSE :
175                   result =
176                      server.browse(connectionToken, (Destination JavaDoc) request.arguments[0], (String JavaDoc) request.arguments[1]);
177                   break;
178
179                case OIL2Constants.SERVER_CHECK_ID :
180                   server.checkID((String JavaDoc) request.arguments[0]);
181                   if (connectionToken != null)
182                      connectionToken.setClientID((String JavaDoc) request.arguments[0]);
183                   break;
184
185                case OIL2Constants.SERVER_CONNECTION_CLOSING :
186                   beginClose();
187                   break;
188
189                case OIL2Constants.SERVER_CREATE_QUEUE :
190                   result = server.createQueue(connectionToken, (String JavaDoc) request.arguments[0]);
191                   break;
192
193                case OIL2Constants.SERVER_CREATE_TOPIC :
194                   result = server.createTopic(connectionToken, (String JavaDoc) request.arguments[0]);
195                   break;
196
197                case OIL2Constants.SERVER_DELETE_TEMPORARY_DESTINATION :
198                   server.deleteTemporaryDestination(connectionToken, (SpyDestination) request.arguments[0]);
199                   break;
200
201                case OIL2Constants.SERVER_GET_ID :
202                   result = server.getID();
203                   if (connectionToken != null)
204                      connectionToken.setClientID((String JavaDoc) result);
205                   break;
206
207                case OIL2Constants.SERVER_GET_TEMPORARY_QUEUE :
208                   result = server.getTemporaryQueue(connectionToken);
209                   break;
210
211                case OIL2Constants.SERVER_GET_TEMPORARY_TOPIC :
212                   result = server.getTemporaryTopic(connectionToken);
213                   break;
214
215                case OIL2Constants.SERVER_RECEIVE :
216                   result =
217                      server.receive(
218                         connectionToken,
219                         ((Integer JavaDoc) request.arguments[0]).intValue(),
220                         ((Long JavaDoc) request.arguments[1]).longValue());
221                   break;
222
223                case OIL2Constants.SERVER_SET_ENABLED :
224                   server.setEnabled(connectionToken, ((Boolean JavaDoc) request.arguments[0]).booleanValue());
225                   break;
226
227                case OIL2Constants.SERVER_SUBSCRIBE :
228                   server.subscribe(connectionToken, (Subscription) request.arguments[0]);
229                   break;
230
231                case OIL2Constants.SERVER_TRANSACT :
232                   server.transact(connectionToken, (TransactionRequest) request.arguments[0]);
233                   break;
234
235                case OIL2Constants.SERVER_UNSUBSCRIBE :
236                   server.unsubscribe(connectionToken, ((Integer JavaDoc) request.arguments[0]).intValue());
237                   break;
238
239                case OIL2Constants.SERVER_DESTROY_SUBSCRIPTION :
240                   server.destroySubscription(connectionToken, (DurableSubscriptionID) request.arguments[0]);
241                   break;
242
243                case OIL2Constants.SERVER_CHECK_USER :
244                   result = server.checkUser((String JavaDoc) request.arguments[0], (String JavaDoc) request.arguments[1]);
245                   break;
246
247                case OIL2Constants.SERVER_PING :
248                   server.ping(connectionToken, ((Long JavaDoc) request.arguments[0]).longValue());
249                   break;
250
251                case OIL2Constants.SERVER_AUTHENTICATE :
252                   result = server.authenticate((String JavaDoc) request.arguments[0], (String JavaDoc) request.arguments[1]);
253                   break;
254
255                default :
256                   throw new RemoteException JavaDoc("Bad method code !");
257             } // switch
258
}
259          catch (Exception JavaDoc e)
260          {
261             resultException = e;
262          } // try
263

264          try
265          {
266             OIL2Response response = new OIL2Response(request);
267             response.result = result;
268             response.exception = resultException;
269             socketHandler.sendResponse(response);
270          }
271          catch (IOException JavaDoc e)
272          {
273             handleConnectionException(e);
274          }
275       }
276
277       public void handleConnectionException(Exception JavaDoc e)
278       {
279          if (!closing)
280             log.info("Client Disconnected: " + e);
281          beginClose();
282       }
283
284       void beginClose()
285       {
286          closing = true;
287          try
288          {
289             if (connectionToken != null)
290                server.connectionClosing(connectionToken);
291          }
292          catch (JMSException JavaDoc ignore)
293          {
294          }
295          finally
296          {
297             close();
298          }
299       }
300
301       void close()
302       {
303          try
304          {
305             if (socket != null)
306             {
307                socketHandler.stop();
308                in.close();
309                out.close();
310                socket.close();
311                socket = null;
312             }
313          }
314          catch (IOException JavaDoc e)
315          {
316             log.debug("Exception occured while closing opened resources: ", e);
317          }
318       }
319
320       public OIL2SocketHandler getSocketHandler()
321       {
322          return socketHandler;
323       }
324
325    }
326
327    /**
328     * Used to construct the GenericConnectionFactory (bindJNDIReferences()
329     * builds it) Sets up the connection properties need by a client to use this
330     * IL
331     *
332     * @return The ClientConnectionProperties value
333     */

334    public java.util.Properties JavaDoc getClientConnectionProperties()
335    {
336       return connectionProperties;
337    }
338
339    /**
340     * Gives this JMX service a name.
341     *
342     * @return The Name value
343     */

344    public String JavaDoc getName()
345    {
346       return "JBossMQ-OILServerIL";
347    }
348
349    /**
350     * Used to construct the GenericConnectionFactory (bindJNDIReferences()
351     * builds it)
352     *
353     * @return The ServerIL value
354     * @returns ServerIL the instance of this IL
355     */

356    public ServerIL getServerIL()
357    {
358       return serverIL;
359    }
360
361    /**
362     * Main processing method for the OILServerILService object
363     */

364    public void run()
365    {
366       try
367       {
368          while (running)
369          {
370             Socket JavaDoc socket = null;
371             try
372             {
373                socket = serverSocket.accept();
374                if (log.isTraceEnabled())
375                   log.trace("Accepted connection: " + socket);
376             }
377             catch (java.io.InterruptedIOException JavaDoc e)
378             {
379                // It's ok, this is due to the SO_TIME_OUT
380
continue;
381             }
382
383             // it's possible that the service is no longer
384
// running but it got a connection, no point in
385
// starting up a thread!
386
//
387
if (!running)
388             {
389                if (socket != null)
390                {
391                   try
392                   {
393                      socket.close();
394                   }
395                   catch (Exception JavaDoc ignore)
396                   {
397                   }
398                }
399                return;
400             }
401
402             try
403             {
404
405                if (log.isTraceEnabled())
406                   log.trace("Initializing RequestListner for socket: " + socket);
407                RequestListner requestListner = new RequestListner(socket);
408                OIL2SocketHandler socketHandler =
409                   new OIL2SocketHandler(requestListner.in, requestListner.out, Thread.currentThread().getThreadGroup());
410                requestListner.socketHandler = socketHandler;
411                socketHandler.setRequestListner(requestListner);
412                socketHandler.start();
413
414             }
415             catch (IOException JavaDoc ie)
416             {
417                log.debug("Client connection could not be accepted: ", ie);
418             }
419          }
420       }
421       catch (SocketException JavaDoc e)
422       {
423          // There is no easy way (other than string comparison) to
424
// determine if the socket exception is caused by connection
425
// reset by peer. In this case, it's okay to ignore both
426
// SocketException and IOException.
427
if (running)
428             log.warn("SocketException occured (Connection reset by peer?). Cannot initialize the OIL2ServerILService.");
429       }
430       catch (IOException JavaDoc e)
431       {
432          if (running)
433             log.warn("IOException occured. Cannot initialize the OIL2ServerILService.");
434       }
435       catch (Throwable JavaDoc t)
436       {
437          log.warn("Unexpected error occured. Cannot initialize the OIL2ServerILService.", t);
438       }
439       try
440       {
441          serverSocket.close();
442       }
443       catch (Exception JavaDoc e)
444       {
445          log.debug("error closing server socket", e);
446       }
447       return;
448    }
449
450    /**
451     * Starts this IL, and binds it to JNDI
452     *
453     * @exception Exception Description of Exception
454     */

455    public void startService() throws Exception JavaDoc
456    {
457       super.startService();
458
459       running = true;
460       this.server = lookupJMSServer();
461
462       // Use the default javax.net.ServerSocketFactory if none was set
463
if (serverSocketFactory == null)
464          serverSocketFactory = ServerSocketFactory.getDefault();
465
466       /* See if the server socket supports setSecurityDomain(SecurityDomain)
467       if an securityDomain was specified
468       */

469       if (securityDomain != null)
470       {
471          try
472          {
473             InitialContext JavaDoc ctx = new InitialContext JavaDoc();
474             Class JavaDoc ssfClass = serverSocketFactory.getClass();
475             SecurityDomain domain = (SecurityDomain) ctx.lookup(securityDomain);
476             Class JavaDoc[] parameterTypes = { SecurityDomain.class };
477             Method JavaDoc m = ssfClass.getMethod("setSecurityDomain", parameterTypes);
478             Object JavaDoc[] args = { domain };
479             m.invoke(serverSocketFactory, args);
480          }
481          catch (NoSuchMethodException JavaDoc e)
482          {
483             log.error("Socket factory does not support setSecurityDomain(SecurityDomain)");
484          }
485          catch (Exception JavaDoc e)
486          {
487             log.error("Failed to setSecurityDomain=" + securityDomain + " on socket factory");
488          }
489       }
490
491       // Create the server socket using the socket factory
492
serverSocket = serverSocketFactory.createServerSocket(serverBindPort, 50, bindAddress);
493       serverSocket.setSoTimeout(SO_TIMEOUT);
494
495       InetAddress JavaDoc socketAddress = serverSocket.getInetAddress();
496       log.info("JBossMQ OIL2 service available at : " + socketAddress + ":" + serverSocket.getLocalPort());
497
498       new Thread JavaDoc(server.getThreadGroup(), this, "OIL2 Worker Server").start();
499       /* We need to check the socketAddress against "0.0.0.0/0.0.0.0"
500          because this is not a valid address on Win32 while it is for
501          *NIX. See BugParade bug #4343286.
502          */

503       if (socketAddress.toString().equals("0.0.0.0/0.0.0.0"))
504          socketAddress = InetAddress.getLocalHost();
505
506       serverIL =
507          new OIL2ServerIL(
508             socketAddress.getHostAddress(),
509             serverSocket.getLocalPort(),
510             clientSocketFactoryName,
511             enableTcpNoDelay);
512
513       // Initialize the connection poperties using the base class.
514
connectionProperties = super.getClientConnectionProperties();
515       connectionProperties.setProperty(
516          OIL2ServerILFactory.CLIENT_IL_SERVICE_KEY,
517          "org.jboss.mq.il.oil2.OIL2ClientILService");
518       connectionProperties.setProperty(OIL2ServerILFactory.OIL2_PORT_KEY, "" + serverSocket.getLocalPort());
519       connectionProperties.setProperty(OIL2ServerILFactory.OIL2_ADDRESS_KEY, "" + socketAddress.getHostAddress());
520       connectionProperties.setProperty(OIL2ServerILFactory.OIL2_TCPNODELAY_KEY, enableTcpNoDelay ? "yes" : "no");
521
522       bindJNDIReferences();
523
524    }
525
526    /**
527     * Stops this IL, and unbinds it from JNDI.
528     */

529    public void stopService()
530    {
531       try
532       {
533          unbindJNDIReferences();
534       }
535       catch (Exception JavaDoc e)
536       {
537          log.error("Exception unbinding from JNDI", e);
538       }
539       try
540       {
541          running = false;
542          if (serverSocket != null)
543             serverSocket.close();
544       }
545       catch (Exception JavaDoc e)
546       {
547          log.debug("Exception stopping server thread", e);
548       }
549    }
550
551    /**
552     * Getter for property serverBindPort.
553     *
554     * @return Value of property serverBindPort.
555     * @jmx:managed-attribute
556     */

557    public int getServerBindPort()
558    {
559       return serverBindPort;
560    }
561
562    /**
563     * Setter for property serverBindPort.
564     *
565     * @param serverBindPort New value of property serverBindPort.
566     * @jmx:managed-attribute
567     */

568    public void setServerBindPort(int serverBindPort)
569    {
570       this.serverBindPort = serverBindPort;
571    }
572
573    /**
574     * Get the interface address the OIL server bind its listening port on.
575     *
576     * @return The hostname or dotted decimal address that the service is
577     * bound to.
578     * @jmx:managed-attribute
579     */

580    public String JavaDoc getBindAddress()
581    {
582       String JavaDoc addr = "0.0.0.0";
583       if (bindAddress != null)
584          addr = bindAddress.getHostName();
585       return addr;
586    }
587    /**
588     * Set the interface address the OIL server bind its listening port on.
589     *
590     * @param host The host address to bind to, if any.
591     *
592     * @throws java.net.UnknownHostException Thrown if the hostname cannot
593     * be resolved to an InetAddress object.
594     * @jmx:managed-attribute
595     */

596    public void setBindAddress(String JavaDoc host) throws UnknownHostException JavaDoc
597    {
598       // If host is null or empty use any address
599
if (host == null || host.length() == 0)
600          bindAddress = null;
601       else
602          bindAddress = InetAddress.getByName(host);
603    }
604
605    /**
606     * Gets the enableTcpNoDelay.
607     * @return Returns a boolean
608     * @jmx:managed-attribute
609     */

610    public boolean getEnableTcpNoDelay()
611    {
612       return enableTcpNoDelay;
613    }
614
615    /**
616     * Sets the enableTcpNoDelay.
617     * @param enableTcpNoDelay The enableTcpNoDelay to set
618     * @jmx:managed-attribute
619     */

620    public void setEnableTcpNoDelay(boolean enableTcpNoDelay)
621    {
622       this.enableTcpNoDelay = enableTcpNoDelay;
623    }
624
625    /** Get the javax.net.SocketFactory implementation class to use on the
626     *client.
627     * @jmx:managed-attribute
628     */

629    public String JavaDoc getClientSocketFactory()
630    {
631       return clientSocketFactoryName;
632    }
633    /** Set the javax.net.SocketFactory implementation class to use on the
634     *client.
635     * @jmx:managed-attribute
636     */

637    public void setClientSocketFactory(String JavaDoc name)
638    {
639       this.clientSocketFactoryName = name;
640    }
641
642    /** Set the javax.net.ServerSocketFactory implementation class to use to
643     *create the service SocketFactory.
644     *@jmx:managed-attribute
645     */

646    public void setServerSocketFactory(String JavaDoc name) throws Exception JavaDoc
647    {
648       ClassLoader JavaDoc loader = Thread.currentThread().getContextClassLoader();
649       Class JavaDoc ssfClass = loader.loadClass(name);
650       serverSocketFactory = (ServerSocketFactory) ssfClass.newInstance();
651    }
652    /** Get the javax.net.ServerSocketFactory implementation class to use to
653     *create the service SocketFactory.
654     *@jmx:managed-attribute
655     */

656    public String JavaDoc getServerSocketFactory()
657    {
658       String JavaDoc name = null;
659       if (serverSocketFactory != null)
660          name = serverSocketFactory.getClass().getName();
661       return name;
662    }
663
664    /** Set the security domain name to use with SSL aware socket factories
665     *@jmx:managed-attribute
666     */

667    public void setSecurityDomain(String JavaDoc domainName)
668    {
669       this.securityDomain = domainName;
670    }
671    /** Get the security domain name to use with SSL aware socket factories
672     *@jmx:managed-attribute
673     */

674    public String JavaDoc getSecurityDomain()
675    {
676       return this.securityDomain;
677    }
678 }
679 // vim:expandtab:tabstop=3:shiftwidth=3
680
Popular Tags