All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.arjuna.ats.internal.arjuna.recovery.Listener Maven / Gradle / Ivy

/*
 * JBoss, Home of Professional Open Source
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
 * as indicated by the @author tags. 
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors. 
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License, v. 2.1.
 * This program is distributed in the hope that it will be useful, but WITHOUT A 
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License,
 * v.2.1 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
 * MA  02110-1301, USA.
 * 
 * (C) 2005-2006,
 * @author JBoss Inc.
 */
/*
 * Copyright (C) 1999-2001 by HP Bluestone Software, Inc. All rights Reserved.
 *
 * HP Arjuna Labs,
 * Newcastle upon Tyne,
 * Tyne and Wear,
 * UK.
 *
 * $Id: Listener.java 2342 2006-03-30 13:06:17Z  $
 */
 
package com.arjuna.ats.internal.arjuna.recovery;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.LinkedList;
import java.util.List;

import com.arjuna.ats.arjuna.common.recoveryPropertyManager;
import com.arjuna.ats.arjuna.logging.tsLogger;
import com.arjuna.ats.arjuna.recovery.Service;

public class Listener extends Thread
{
   /**
    * Creates a listener thread on the specified port
    * for the specified service to run.
    */

   public Listener( int port, Service service )
      throws IOException
   {
      super( "Listener:" + port );

      _listener_port = port;
      _listener_service = service;

      _listener_socket = new ServerSocket( _listener_port );

      if (Listener.setTimeout)
	  _listener_socket.setSoTimeout( _listener_socket_timeout_in_msecs );

       connections = new LinkedList();
   }
   
   /**
    * Creates a listener thread on the specified server socket
    * for the specified service to run.
    */

   public Listener( ServerSocket serverSocket, Service service )
      throws IOException
   {
      super( "Listener:" + serverSocket.getLocalPort() );

      _listener_port = serverSocket.getLocalPort();
      _listener_service = service;

      _listener_socket = serverSocket;

      if (Listener.setTimeout)
	  _listener_socket.setSoTimeout( _listener_socket_timeout_in_msecs );

      connections = new LinkedList();
   }

   /*
    * Close down the socket.
    *
    * this is pointless because this instance is a thread so never gets garbage collected until it has stopped running.
    * but that means shutdown will have been called making the call to close in this method redundant.

   public void finalize()
   {
      stopListener();

      try
      {
         _listener_socket.close();
      }
      catch ( IOException ex )
      {
	  tsLogger.arjLoggerI18N.warn("com.arjuna.ats.internal.arjuna.recovery.Listener_1");
      }
   }      
    */

   /**
    * Loops waiting for connection requests from client,
    * creates a new Connection object for each connection.
    */

   public void run()
   {
      while ( !stopRequested() )
      {
         try
         {
            final Socket conn = _listener_socket.accept();
             // n.b. add may not occur because a shutdown was requested
            if (addConnection(conn)) {
                // ok the connection is in the list -- ensure it clears itself out
            Connection.Callback callback = new Connection.Callback() {
                private Socket _conn = conn;
                public void run() {
                    removeConnection(_conn);
                }
            };

            Connection new_conn = new Connection( conn, _listener_service, callback );

     	    if (tsLogger.logger.isDebugEnabled()) {
                 tsLogger.logger.debug("Connected to " + conn.getInetAddress().getHostAddress() +
                         " on port " + conn.getPort() + " on listener port " +
                         conn.getLocalPort() + " for service " +
                         _listener_service.getClass().getName());
             }

            new_conn.start();
            }
         }
         catch ( final InterruptedIOException ex )
         {
            // timeout on the listener socket expired.
         }
         catch (final SocketException ex)
         {
             // we get this if the socket is closed under a call to shutdown
             if (tsLogger.logger.isDebugEnabled()) {
                 tsLogger.logger.debug("Recovery listener existing " +
                         _listener_service.getClass().getName());
             }
         }
         catch ( final IOException ex )
         {
	     if (tsLogger.logger.isDebugEnabled())
		 tsLogger.logger.debug("Listener - IOException"+" "+ex);
         }
         catch (final Exception ex)
         {
         }
      }
   }

    public synchronized boolean addConnection(Socket conn)
    {
        if (!_stop_listener) {
            connections.add(conn);
            return true;
        } else {
            // a close down request got in between the connection create and the
            // call to this method. it will have closed all the other connections
            // and will be waiting on this (listener) thread. so close this connection
            // before returning false
            try {
                conn.close();
            } catch (Exception e) {
                // ignore
            }
            return false;
        }
    }

    public synchronized void removeConnection(Socket conn)
    {
        connections.remove(conn);
        notifyAll();
    }

   /**
    * Halts running of the listener thread.
    */

   public synchronized void stopListener()
   {
      _stop_listener = true;

       try
       {
           _listener_socket.close();  // in case we're still in accept
       }
       catch (final Exception ex)
       {
       }
      // there is no need for this as the close will interrupt any i/o that is in progress
      // this.interrupt();

       // ok, closing a connection socket will cause the connection thread to remove it from the list as it
       // exits so we keep on closing them and waiting until the list is empty

       while(connections.size() > 0) {
           Socket conn = connections.get(0);
           try {
               conn.close();
           } catch (Exception e) {
               // ignore
           }
           try {
               wait();
           } catch (InterruptedException e) {
               // ignore
           }
       }
      
       // make sure this listener thread has exited before we return

       try {
           this.join();
       } catch (InterruptedException ie) {
       }
   }

   private synchronized boolean stopRequested()
   {
       return _stop_listener;
   }
    
   // Socket & port which client(RecoveryManager) connects to.
   private ServerSocket _listener_socket;
   private int          _listener_port;

   // Flag to indicate when to shutdown the listener thread.
   private boolean _stop_listener = false;
   
   // Timeout used on for accept.
   private int _listener_socket_timeout_in_msecs = 1500;
   
   // The work item to execute.
   private Service _listener_service;

    private List connections;

    private static boolean setTimeout = false;
    
    static
    {
    	setTimeout = recoveryPropertyManager.getRecoveryEnvironmentBean().isTimeoutSocket();
    }
    
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy