avalon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dona...@apache.org
Subject cvs commit: jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/sockets DefaultServerSocketFactory.java DefaultSocketFactory.java DefaultSocketManager.java DefaultSocketManager.xinfo TLSServerSocketFactory.java
Date Thu, 22 Feb 2001 07:52:17 GMT
donaldp     01/02/21 23:52:17

  Added:       src/java/org/apache/cornerstone/blocks/connection
                        Connection.java DefaultConnectionManager.java
                        DefaultConnectionManager.xinfo
               src/java/org/apache/cornerstone/blocks/eventserver
                        EventServer.java EventServer.xinfo
               src/java/org/apache/cornerstone/blocks/masterstore
                        AbstractFileRepository.java
                        File_Persistent_Object_Repository.java
                        File_Persistent_Stream_Repository.java
                        RepositoryManager.java RepositoryManager.xinfo
               src/java/org/apache/cornerstone/blocks/scheduler
                        DefaultJobScheduler.java DefaultJobScheduler.xinfo
                        DefaultTimeScheduler.java
                        DefaultTimeScheduler.xinfo JobEntry.java
                        TimeScheduledEntry.java
               src/java/org/apache/cornerstone/blocks/security
                        DefaultRoleManager.java
               src/java/org/apache/cornerstone/blocks/serversocket
                        AuthenticatedServerSocketAcceptor.java
                        ServerSocketAcceptor.java SocketManager.java
                        SocketManager.xinfo TLSServerSocketAcceptor.java
               src/java/org/apache/cornerstone/blocks/sockets
                        DefaultServerSocketFactory.java
                        DefaultSocketFactory.java DefaultSocketManager.java
                        DefaultSocketManager.xinfo
                        TLSServerSocketFactory.java
  Log:
  Committing all the cornerstone blocks
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/connection/Connection.java
  
  Index: Connection.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.connection;
  
  import java.io.IOException;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.util.ArrayList;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Component;
  import org.apache.avalon.util.thread.ThreadPool;
  import org.apache.cornerstone.services.connection.ConnectionHandler;
  import org.apache.cornerstone.services.connection.ConnectionHandlerFactory;
  
  class Connection
      extends AbstractLoggable
      implements Component, Runnable
  {
      protected final ServerSocket               m_serverSocket;
      protected final ConnectionHandlerFactory   m_handlerFactory;
      protected final ThreadPool                 m_threadPool;
      protected final ArrayList                  m_runners          = new ArrayList();
  
      protected Thread                           m_thread;
  
      public Connection( final ServerSocket serverSocket, 
                         final ConnectionHandlerFactory handlerFactory,
                         final ThreadPool threadPool )
      {
          m_serverSocket = serverSocket;
          m_handlerFactory = handlerFactory;
          m_threadPool = threadPool;
      }
  
      public void dispose()
          throws Exception
      {
          m_threadPool.interrupt();
  
          if( null != m_thread )
          {
              m_thread.interrupt();
              m_thread.join( /* 1000 ??? */ );
              m_thread = null;
          }
  
          final Iterator runners = m_runners.iterator();
          while( runners.hasNext() )
          {
              final ConnectionRunner runner = (ConnectionRunner)runners.next();
              runner.dispose();
          }
  
          m_runners.clear();
      }
  
      public void run()
      {
          m_thread = Thread.currentThread();
  
          while( !Thread.interrupted() )
          {
              try
              {
                  final Socket socket = m_serverSocket.accept();
                  final ConnectionHandler handler = m_handlerFactory.createConnectionHandler();
                  final ConnectionRunner runner = 
                      new ConnectionRunner( socket, m_runners, handler );
                  setupLogger( runner );
                  m_threadPool.execute( runner );
              }
              catch( final IOException ioe )
              {
                  getLogger().error( "Exception accepting connection", ioe );
              }
              catch( final Exception e )
              {
                  getLogger().error( "Exception executing runner", e );
              }
          }
      }
  }
   
  class ConnectionRunner
      extends AbstractLoggable
      implements Runnable, Component
  {
      protected Socket             m_socket;
      protected Thread             m_thread;
      protected ArrayList          m_runners;
      protected ConnectionHandler  m_handler;
  
      ConnectionRunner( final Socket socket, 
                        final ArrayList runners, 
                        final ConnectionHandler handler )
      {
          m_socket = socket;
          m_runners = runners;
          m_handler = handler;
      }
  
      public void dispose()
          throws Exception
      {
          if( null != m_thread )
          {
              m_thread.interrupt();
              m_thread.join( /* 1000 ??? */ );
              m_thread = null;
          }
      }
          
      public void run()
      {
          try
          {
              m_thread = Thread.currentThread();
              m_runners.add( this );
  
              getLogger().debug( "Starting connection on " + m_socket );
              setupLogger( m_handler );
              m_handler.handleConnection( m_socket ); 
              getLogger().debug( "Ending connection on " + m_socket );
          }
          catch( final Exception e )
          {
              getLogger().warn( "Error handling connection", e );
          }
          finally
          {
              try { m_socket.close(); }
              catch( final IOException ioe ) 
              { 
                  getLogger().warn( "Error shutting down connection", ioe );
              }
                  
              m_runners.remove( this );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/connection/DefaultConnectionManager.java
  
  Index: DefaultConnectionManager.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.connection;
  
  import java.io.IOException;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.util.HashMap;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Context;
  import org.apache.avalon.Contextualizable;
  import org.apache.avalon.Disposable;
  import org.apache.phoenix.Block;
  import org.apache.phoenix.BlockContext;
  import org.apache.cornerstone.services.connection.ConnectionHandler;
  import org.apache.cornerstone.services.connection.ConnectionHandlerFactory;
  import org.apache.cornerstone.services.connection.ConnectionManager;
  import org.apache.avalon.util.thread.ThreadPool;
  
  /**
   * This is the service through which ConnectionManagement occurs.
   *
   * WARNING: This is very early ALPHA and the interface will most likely change.
   * 
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   */
  public class DefaultConnectionManager
      extends AbstractLoggable
      implements Block, ConnectionManager, Contextualizable, Disposable
  {
      protected BlockContext        m_context;
      protected HashMap             m_connections        = new HashMap();
  
      public void contextualize( final Context context )
      {
          m_context = (BlockContext)context;
      }
      
      public void dispose()
          throws Exception
      {
          final Iterator names = ((HashMap)m_connections.clone()).keySet().iterator();
          while( names.hasNext() )
          {
              final String name = (String)names.next();
              disconnect( name );
          }
      }
  
      /**
       * Start managing a connection.
       * Management involves accepting connections and farming them out to threads 
       * from pool to be handled.
       *
       * @param name the name of connection
       * @param socket the ServerSocket from which to 
       * @param handlerFactory the factory from which to aquire handlers
       * @param threadPool the thread pool to use
       * @exception Exception if an error occurs
       */
      public void connect( String name, 
                           ServerSocket socket,
                           ConnectionHandlerFactory handlerFactory,
                           ThreadPool threadPool )
          throws Exception
      {
          if( null != m_connections.get( name ) )
          {
              throw new IllegalArgumentException( "Connection already exists with name " + 
                                                  name );
          }
  
          final Connection runner = new Connection( socket, handlerFactory, threadPool );
          setupLogger( runner );
          m_connections.put( name, runner );
          threadPool.execute( runner );
      }
      
      /**
       * Start managing a connection. 
       * This is similar to other connect method except that it uses default thread pool.
       *
       * @param name the name of connection
       * @param socket the ServerSocket from which to 
       * @param handlerFactory the factory from which to aquire handlers
       * @exception Exception if an error occurs
       */
      public void connect( String name, 
                           ServerSocket socket, 
                           ConnectionHandlerFactory handlerFactory )
          throws Exception
      {
          connect( name, socket, handlerFactory, m_context.getDefaultThreadPool() );
      }
      
      /**
       * This shuts down all handlers and socket, waiting for each to gracefully shutdown.
       *
       * @param name the name of connection
       * @exception Exception if an error occurs
       */
      public void disconnect( final String name )
          throws Exception
      {
          disconnect( name, false );
      }
      
      /**
       * This shuts down all handlers and socket. 
       * If tearDown is true then it will forcefully shutdown all connections and try 
       * to return as soon as possible. Otherwise it will behave the same as 
       * void disconnect( String name );
       *
       * @param name the name of connection
       * @param tearDown if true will forcefully tear down all handlers
       * @exception Exception if an error occurs
       */
      public void disconnect( final String name, final boolean tearDown )
          throws Exception
      {
          final Connection connection = (Connection)m_connections.remove( name );
          if( null == connection )
          {
              throw new IllegalArgumentException( "No such connection with name " +
                                                  name );
          }
  
          //TODO: Stop ignoring tearDown
          connection.dispose();
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/connection/DefaultConnectionManager.xinfo
  
  Index: DefaultConnectionManager.xinfo
  ===================================================================
  <?xml version="1.0"?>
  
  <blockinfo>
  
    <meta>
  
      <contributors>
        <author name="Peter Donald" email="donaldp@apache.org"/>
        <author name="Federico Barbier" email="fede@apache.org"/>
      </contributors>
  
    </meta>
  
    <!-- services that are offered by this block -->
    <services>
      <service name="org.apache.cornerstone.services.connection.ConnectionManager" version="1.0" />
    </services>
  
  </blockinfo>
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/eventserver/EventServer.java
  
  Index: EventServer.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.eventserver;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Disposable;
  import org.apache.phoenix.Block;
  import org.apache.cornerstone.services.Scheduler;
  
  /**
   * The <code>EventServer</code> implements a service for setting
   * and receiving alarms within Avalon. The <code>EventServer</code> allows to set
   * a listener on a specific event.
   *
   * @deprecated This class is going to be merged with org.apache.cornerstone.blocks.scheduler.*
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   */
  public class EventServer
      extends AbstractLoggable
      implements Block, Scheduler, Disposable
  {
      protected HashMap           m_alarms         = new HashMap();
  
      public void setAlarm( final String name, 
                            final Scheduler.EventTrigger eventTrigger, 
                            final Scheduler.Target target )
      {
          eventTrigger.initialize( name, target, this );
          new Thread( eventTrigger ).start();
          m_alarms.put( name, eventTrigger );
      }
  
      /**
       * Removes an alarm by name.  If the alarm does not exist throws RuntimeException.
       *
       * @param name The name of the alarm
       */
      public void removeAlarm( final String name ) 
      {
          shutdownAlarm( name );
          m_alarms.remove( name );
      }
  
      public void shutdownAlarm( final String name ) 
      {
          try { getTrigger( name ).stop(); }
          catch( final Exception e )
          {
              getLogger().warn( "Error occured stopping trigger " + name, e );
          }
      }    
  
      /**
       * Resets a named alarm to restart the timer.
       */
      public void resetAlarm( final String name )
      {
          getTrigger( name ).reset();
      }
  
      public void dispose()
      {
          final Iterator e = m_alarms.keySet().iterator();
          while(e.hasNext()) 
          {
              shutdownAlarm( (String)e.next() );
          }
  
          m_alarms.clear();
      }
      
      private Scheduler.EventTrigger getTrigger( final String name ) 
      {
          final Scheduler.EventTrigger eventTrigger = 
              (Scheduler.EventTrigger)m_alarms.get( name );
  
          if( null == eventTrigger ) 
          {
              throw new IllegalArgumentException( "No alarm named " + name );
          }
  
          return eventTrigger;
      }
  }
  
  
  
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/eventserver/EventServer.xinfo
  
  Index: EventServer.xinfo
  ===================================================================
  <?xml version="1.0"?>
  
  <blockinfo>
  
    <meta>
  
      <contributors>
        <author name="Federico Barbieri" email="fede@apache.org"/>
        <author name="Berin Loritsch" email="bloritsch@apache.org"/>
      </contributors>
  
    </meta>
  
    <!-- services that are offered by this block -->
    <services>
      <service name="org.apache.cornerstone.services.Scheduler" version="1.0" />
    </services>
  
  </blockinfo>
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/masterstore/AbstractFileRepository.java
  
  Index: AbstractFileRepository.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.masterstore;
  
  import java.io.BufferedOutputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileOutputStream;
  import java.io.FilenameFilter;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.util.ArrayList;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.ComponentManager;
  import org.apache.avalon.ComponentManagerException;
  import org.apache.avalon.Composer;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.avalon.Context;
  import org.apache.avalon.Contextualizable;
  import org.apache.avalon.Initializable;
  import org.apache.phoenix.Block;
  import org.apache.phoenix.BlockContext;
  import org.apache.cornerstone.services.Store;
  import org.apache.avalon.util.io.ExtensionFileFilter;
  import org.apache.avalon.util.io.ResettableFileInputStream;
  
  /**
   * This an abstract class implementing functionality for creating a file-store.
   *
   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   */
  public abstract class AbstractFileRepository 
      extends AbstractLoggable  
      implements Block, Store.Repository, Contextualizable, Composer, Configurable, Initializable
  {
      protected static final boolean      DEBUG          = false;
  
      protected static final String       HANDLED_URL    = "file://";
      protected static final int          BYTE_MASK      = 0x0f;
      protected static final char[]       HEX_DIGITS     = 
      {
          '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
      };
      
      protected String                    m_path;
      protected String                    m_destination;
      protected String                    m_extension;
      protected String                    m_name;
      protected FilenameFilter            m_filter;
      protected File                      m_baseDirectory;
  
      protected ComponentManager          m_componentManager;
      protected BlockContext              m_context;
  
      protected abstract String getExtensionDecorator();
      
      public void contextualize( final Context context )
      {
          final BlockContext blockContext = (BlockContext)context;
          m_baseDirectory = blockContext.getBaseDirectory();        
      }
  
      public void compose( final ComponentManager componentManager )
          throws ComponentManagerException
      {
          m_componentManager = componentManager;
      }
  
      public void configure( final Configuration configuration )
          throws ConfigurationException
      {
          if( null == m_destination )
          {
              final String destination = configuration.getAttribute( "destinationURL" );
              setDestination( destination );
          }
      }
  
      public void init() 
          throws Exception
      {
          getLogger().info( "Init " + getClass().getName() + " Store" );
  
          m_name = RepositoryManager.getName();
          m_extension = "." + m_name + getExtensionDecorator();
          m_filter = new ExtensionFileFilter( m_extension );
   
          final File directory = new File( m_path );
          directory.mkdirs();
  
          getLogger().info( getClass().getName() + " opened in " + m_path );
      }
  
      protected void setDestination( final String destination )
          throws ConfigurationException
      {
          if( !destination.startsWith( HANDLED_URL ) )
          {
              throw new ConfigurationException( "cannot handle destination " + destination );
          }
  
          m_path = destination.substring( HANDLED_URL.length() );
  
          File directory = new File( m_baseDirectory, m_path );
          
          try { directory = directory.getCanonicalFile(); }
          catch( final IOException ioe )
          {
              throw new ConfigurationException( "Unable to form canonical representation of " + 
                                                directory );
          }
  
          m_path = directory.toString();
  
          m_destination = destination;
      }
  
      protected AbstractFileRepository createChildRepository()
          throws Exception
      {
          return (AbstractFileRepository)getClass().newInstance();
      }
  
      public Store.Repository getChildRepository( final String childName )
      {
          AbstractFileRepository child = null; 
          
          try { child = createChildRepository(); }
          catch( final Exception e )
          {
              throw new RuntimeException( "Cannot create child repository " + 
                                          childName + " : " + e );
          }
  
          try { child.compose( m_componentManager ); }
          catch( final ComponentManagerException cme )
          {
              throw new RuntimeException( "Cannot compose child " +
                                          "repository " + childName + 
                                          " : " + cme );
          }
  
          try 
          {
              child.setDestination( m_destination + File.pathSeparatorChar + 
                                    childName + File.pathSeparator );
          }
          catch( final ConfigurationException ce )
          {
              throw new RuntimeException( "Cannot set destination for child child " +
                                          "repository " + childName + 
                                          " : " + ce );
          }
          
          try { child.init(); } 
          catch( final Exception e )
          {
              throw new RuntimeException( "Cannot initialize child " +
                                          "repository " + childName + 
                                          " : " + e );
          }
  
          if( DEBUG ) 
          {
              getLogger().debug( "Child repository of " + m_name + " created in " + 
                                 m_destination + File.pathSeparatorChar + 
                                 childName + File.pathSeparator );
          }
  
          return child;
      }
  
      protected File getFile( final String key )
          throws IOException
      {
          return new File( encode( key ) );
      }
  
      protected InputStream getInputStream( final String key )
          throws IOException
      {
          return new FileInputStream( getFile( key ) );
      }
  
      protected OutputStream getOutputStream( final String key )
          throws IOException
      {
          return new FileOutputStream( getFile( key ) );
      }
  
      /**
       * Remove the object associated to the given key.
       */
      public synchronized void remove( final String key )
      {
          try
          {
              final File file = getFile( key );
              file.delete();
              if( DEBUG ) getLogger().debug( "removed key " + key );
          } 
          catch( final Exception e )
          {
              throw new RuntimeException( "Exception caught while removing" +
                                          " an object: " + e );
          }
      }
      
      /**
       * Indicates if the given key is associated to a contained object.
       */
      public synchronized boolean containsKey( final String key )
      {
          try
          {
              final File file = getFile( key );
              if( DEBUG ) getLogger().debug( "checking key " + key );
              return file.exists();
          } 
          catch( final Exception e )
          {
              throw new RuntimeException( "Exception caught while searching " +
                                          "an object: " + e );
          }
      }
  
      /**
       * Returns the list of used keys.
       */
      public Iterator list() 
      {
          final File storeDir = new File( m_path );
          final String[] names = storeDir.list( m_filter );
          final ArrayList list = new ArrayList();
  
          for( int i = 0; i < names.length; i++ )
          {
              list.add( decode( names[i] ) );
          }
  
          return list.iterator();
      }
  
      /**
       * Returns a String that uniquely identifies the object.
       * <b>Note:</b> since this method uses the Object.toString()
       * method, it's up to the caller to make sure that this method
       * doesn't change between different JVM executions (like
       * it may normally happen). For this reason, it's highly recommended
       * (even if not mandated) that Strings be used as keys.
       */
      protected String encode( final String key ) 
      {
          final byte[] bytes = key.getBytes();
          final char[] buffer = new char[ bytes.length << 1 ];
  
          for( int i = 0, j = 0; i < bytes.length; i++ )
          {
              final int k = bytes[ i ];
              buffer[ j++ ] = HEX_DIGITS[ ( k >>> 4 ) & BYTE_MASK ];
              buffer[ j++ ] = HEX_DIGITS[ k & BYTE_MASK ];
          }
  
          StringBuffer result = new StringBuffer();
          result.append( m_path );
          result.append( File.separator );
          result.append( buffer );
          result.append( m_extension );
          return result.toString();
      }
      
      /**
       * Inverse of encode exept it do not use path.
       * So decode(encode(s) - m_path) = s.
       * In other words it returns a String that can be used as key to retive 
       * the record contained in the 'filename' file.
       */
      protected String decode( String filename )
      {
          filename = filename.substring( 0, filename.length() - m_extension.length() );
          final int size = filename.length();
          final byte[] bytes = new byte[ size >>> 1 ];
  
          for( int i = 0, j = 0; i < size; j++ )
          {
              bytes[ j ] = Byte.parseByte( filename.substring( i, i + 2 ), 16 );
              i +=2;
          }
  
          return new String( bytes );
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/masterstore/File_Persistent_Object_Repository.java
  
  Index: File_Persistent_Object_Repository.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.masterstore;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.ObjectInputStream;
  import java.io.ObjectOutputStream;
  import java.io.ObjectStreamClass;
  import java.io.OutputStream;
  import java.util.ArrayList;
  import java.util.Iterator;
  import org.apache.cornerstone.services.Store;
  
  /**
   * This is a simple implementation of persistent object store using
   * object serialization on the file system.
   *
   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   * @author <a href="mailto:paul_hammant@yahoo.com">Paul Hammant</a>
   */
  public class File_Persistent_Object_Repository 
      extends AbstractFileRepository  
      implements Store.ObjectRepository
  {
      protected String getExtensionDecorator() 
      {
          return ".FileObjectStore";
      }
  
      /**
       * Get the object associated to the given unique key.
       */
      public synchronized Object get( final String key )
      {
          try
          {
              final InputStream inputStream = getInputStream( key );
  
              try
              {
                  final ObjectInputStream stream = new ObjectInputStream( inputStream );
                  final Object object = stream.readObject();
                  if( DEBUG ) 
                  {
                      getLogger().debug( "returning object " + object + " for key " + key );
                  }
                  return object;
              }
              finally
              {
                  inputStream.close();
              }
          } 
          catch( final Exception e )
          {
              throw new RuntimeException( "Exception caught while retrieving an object: " + e );
          }
      }
     
      /**
       * Store the given object and associates it to the given key
       */ 
      public synchronized void put( final String key, final Object value )
      {
          try
          {
              final OutputStream outputStream = getOutputStream( key );
  
              try
              {
                  final ObjectOutputStream stream = new ObjectOutputStream( outputStream );
                  stream.writeObject( value );
                  if( DEBUG ) getLogger().debug( "storing object " + value + " for key " + key );
              }
              finally
              {
                  outputStream.close();
              }
          } 
          catch( final Exception e )
          {
              throw new RuntimeException( "Exception caught while storing an object: " + e );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/masterstore/File_Persistent_Stream_Repository.java
  
  Index: File_Persistent_Stream_Repository.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.masterstore;
  
  import java.io.BufferedOutputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.OutputStream;
  import java.util.ArrayList;
  import java.util.HashMap;
  import org.apache.cornerstone.services.Store;
  import org.apache.avalon.util.io.ResettableFileInputStream;
  import org.apache.avalon.util.io.IOUtil;
  
  /**
   * Implementation of a StreamRepository to a File.
   * TODO: -retieve(String key) should return a FilterInputStream to allow 
   * mark and reset methods. (working not like BufferedInputStream!!!)
   *
   * @author  Federico Barbieri <fede@apache.org>
   */
  public class File_Persistent_Stream_Repository 
      extends AbstractFileRepository  
      implements Store.StreamRepository
  {
      protected final HashMap             m_inputs  = new HashMap();
      protected final HashMap             m_outputs = new HashMap();
  
      protected String getExtensionDecorator()
      {
          return ".FileStreamStore";
      }
  
      /**
       * Get the object associated to the given unique key.
       */
      public synchronized InputStream get( final String key )
      {
          try
          {
              final ResettableFileInputStream stream = 
                  new ResettableFileInputStream( getFile( key ) );
  
              final Object o = m_inputs.get( key );
              if( null == o ) 
              {
                  m_inputs.put( key, stream );
              }
              else if( o instanceof ArrayList )
              {
                  ((ArrayList)o).add( stream );
              }
              else
              {
                  final ArrayList list = new ArrayList();
                  list.add( o );
                  list.add( stream );
                  m_inputs.put( key, stream );
              }
  
              return stream;
          } 
          catch( final IOException ioe )
          {
              final String message = "Exception caught while retrieving a stream ";
              getLogger().warn( message, ioe );
              throw new RuntimeException( message+ ": " + ioe );
          }
      }
     
      /**
       * Store the given object and associates it to the given key
       */ 
      public synchronized OutputStream put( final String key )
      {
          try
          {
              final OutputStream outputStream = getOutputStream( key );
              final BufferedOutputStream stream = new BufferedOutputStream( outputStream );
  
              final Object o = m_outputs.get( key );
              if( null == o ) 
              {
                  m_outputs.put( key, stream );
              }
              else if( o instanceof ArrayList )
              {
                  ((ArrayList)o).add( stream );
              }
              else
              {
                  final ArrayList list = new ArrayList();
                  list.add( o );
                  list.add( stream );
                  m_outputs.put( key, stream );
              }
  
              return stream;
          } 
          catch( final IOException ioe )
          {
              final String message = "Exception caught while storing a stream ";
              getLogger().warn( message, ioe );
              throw new RuntimeException( message+ ": " + ioe );
          }
      }
      
      public void remove( final String key )
      {
          Object o = m_inputs.remove( key );
          if( null != o )
          {
              if( o instanceof InputStream )
              {
                  IOUtil.shutdownStream( (InputStream)o );
              }
              else
              {
                  final ArrayList list = (ArrayList)o;
                  final int size = list.size();
                  
                  for( int i = 0; i < size; i++ )
                  {
                      IOUtil.shutdownStream( (InputStream)list.get( i ) );
                  }
              }
          }
  
          o = m_outputs.remove( key );
          if( null != o )
          {
              if( o instanceof OutputStream )
              {
                  IOUtil.shutdownStream( (OutputStream)o );
              }
              else
              {
                  final ArrayList list = (ArrayList)o;
                  final int size = list.size();
                  
                  for( int i = 0; i < size; i++ )
                  {
                      IOUtil.shutdownStream( (OutputStream)list.get( 0 ) );
                  }
              }
          }
  
          super.remove( key );
      }
  }
  
      
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/masterstore/RepositoryManager.java
  
  Index: RepositoryManager.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.masterstore;
  
  import java.net.MalformedURLException;
  import java.net.URL;
  import java.util.HashMap;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Component;
  import org.apache.avalon.ComponentManager;
  import org.apache.avalon.ComponentManagerException;
  import org.apache.avalon.ComponentNotAccessibleException;
  import org.apache.avalon.ComponentNotFoundException;
  import org.apache.avalon.Composer;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.avalon.Context;
  import org.apache.avalon.Contextualizable;
  import org.apache.avalon.Initializable;
  import org.apache.phoenix.Block;
  import org.apache.cornerstone.services.Store;
  
  /**
   *
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   */
  public class RepositoryManager 
      extends AbstractLoggable 
      implements Block, Store, Contextualizable, Composer, Configurable
  {
      private static final String   REPOSITORY_NAME  = "Repository";
      private static long           id               = 0;
  
      protected HashMap             m_repositories        = new HashMap();
      protected HashMap             m_models              = new HashMap();
      protected HashMap             m_classes             = new HashMap();
      protected ComponentManager    m_componentManager;
      protected Context             m_context;
  
      public void contextualize( final Context context )
      {
          m_context = context;
      }
  
      public void compose( final ComponentManager componentManager )
          throws ComponentManagerException
      {
          m_componentManager = componentManager;
      }    
  
      public void configure( final Configuration configuration )
          throws ConfigurationException
      {
          final Configuration[] registeredClasses = 
              configuration.getChild( "repositories" ).getChildren( "repository" );
          
          for( int i = 0; i < registeredClasses.length; i++ )
          {
              registerRepository( registeredClasses[ i ] );
          }
      }
  
      public void registerRepository( final Configuration repConf ) 
          throws ConfigurationException
      {
          final String className = repConf.getAttribute( "class" );
          getLogger().info( "Registering Repository " + className );
  
          final Configuration[] protocols = 
              repConf.getChild( "protocols" ).getChildren( "protocol" );
          final Configuration[] types = repConf.getChild( "types" ).getChildren( "type" );
          final Configuration[] modelIterator = 
              repConf.getChild( "models" ).getChildren( "model" );
  
          for( int i = 0; i < protocols.length; i++ )
          {
              final String protocol = protocols[ i ].getValue();
  
              for( int j = 0; j < types.length; j++ )
              {
                  final String type = types[ j ].getValue();
  
                  for( int k = 0; k < modelIterator.length; k++ )
                  {
                      final String model = modelIterator[ k ].getValue();
                      m_classes.put( protocol + type + model, className );
                      getLogger().info( "   for " + protocol + "," + type + "," + model );
                  }
              }
          }
      }
  
      public Component select( Object hint ) 
          throws ComponentManagerException
      {
          Configuration repConf = null;
          try
          {
              repConf = (Configuration) hint;
          } 
          catch( final ClassCastException cce )
          {
              throw new ComponentNotAccessibleException( "Hint is of the wrong type. " + 
                                                         "Must be a Configuration", cce );
          }
          URL destination = null;
          try 
          {
              destination = new URL( repConf.getAttribute("destinationURL") );
          } 
          catch( final ConfigurationException ce )
          {
              throw new ComponentNotAccessibleException( "Malformed configuration has no " + 
                                                         "destinationURL attribute", ce );
          } 
          catch( final MalformedURLException mue )
          {
              throw new ComponentNotAccessibleException( "destination is malformed. " + 
                                                         "Must be a valid URL", mue );
          }
  
          try
          {
              final String type = repConf.getAttribute( "type" );
              final String repID = destination + type;
              Store.Repository reply = (Store.Repository)m_repositories.get( repID );
              final String model = (String)repConf.getAttribute( "model" );
  
              if( null != reply ) 
              {
                  if( m_models.get( repID ).equals( model ) )
                  {
                      return reply;
                  } 
                  else
                  {
                      final String message = "There is already another repository with the " +
                          "same destination and type but with different model";
                      throw new ComponentNotFoundException( message );
                  }
              } 
              else
              {
                  final String protocol = destination.getProtocol();
                  final String repClass = (String)m_classes.get( protocol + type + model );
  
                  getLogger().debug( "Need instance of " + repClass + " to handle: " + 
                                     protocol + type + model );
  
                  try 
                  {
                      reply = (Store.Repository)Class.forName( repClass ).newInstance();
                      setupLogger( reply, "repository" );
                      
                      if( reply instanceof Contextualizable )
                      {
                          ((Contextualizable)reply).contextualize( m_context );
                      }
  
                      if( reply instanceof Composer )
                      {
                          ((Composer)reply).compose( m_componentManager );
                      }
  
                      if( reply instanceof Configurable )
                      {
                          ((Configurable)reply).configure( repConf );
                      }
  
                      if( reply instanceof Initializable )
                      {
                          ((Initializable)reply).init();
                      }
  
                      m_repositories.put( repID, reply );
                      m_models.put( repID, model );
                      getLogger().info( "New instance of " + repClass + " created for " + 
                                        destination );
                      return reply;
                  } 
                  catch( final Exception e )
                  {
                      final String message = "Cannot find or init repository: " + e.getMessage();
                      getLogger().warn( message, e );
                      
                      throw new ComponentNotAccessibleException( message, e );
                  }
              }
          } 
          catch( final ConfigurationException ce ) 
          {
              throw new ComponentNotAccessibleException( "Malformed configuration", ce );
          }
      }
          
      public static final String getName() 
      {
          return REPOSITORY_NAME + id++;
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/masterstore/RepositoryManager.xinfo
  
  Index: RepositoryManager.xinfo
  ===================================================================
  <?xml version="1.0"?>
  
  <blockinfo>
  
    <meta>
  
      <contributors>
        <author name="Federico Barbier" email="fede@apache.org"/>
      </contributors>
  
    </meta>
  
    <!-- services that are offered by this block -->
    <services>
      <service name="org.apache.cornerstone.services.Store" version="1.0" />
    </services>
  
  </blockinfo>
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/scheduler/DefaultJobScheduler.java
  
  Index: DefaultJobScheduler.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.scheduler;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Disposable;
  import org.apache.avalon.Initializable;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.phoenix.Block;
  import org.apache.cornerstone.services.scheduler.Job;
  import org.apache.cornerstone.services.scheduler.JobScheduler;
  import org.apache.avalon.util.BinaryHeap;
  import org.apache.avalon.util.lang.ThreadManager;
  
  /**
   * Default implementation of JobScheduling service.
   *
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   * @deprecated This class is going to be merged with org.apache.cornerstone.blocks.eventserver.*
   */
  public class DefaultJobScheduler
      extends AbstractLoggable
      implements Block, JobScheduler, Initializable, Runnable
  {
      protected final class JobRunner
          extends AbstractLoggable
          implements Runnable
      {
          protected final String              m_name;
          protected final Runnable            m_runnable;
  
          private JobRunner( final String name, final Runnable runnable )
          {
              m_name = name;
              m_runnable = runnable;
          }
  
          public void run()
          {
              try
              {
                  if( m_runnable instanceof Initializable )
                  {
                      ((Initializable)m_runnable).init();
                  }
                      
                  m_runnable.run();
  
                  if( m_runnable instanceof Disposable )
                  {
                      ((Disposable)m_runnable).dispose();
                  }
              }
              catch( final Throwable throwable )
              {
                  this.getLogger().warn( "Error occured executing scheduled task " + m_name,
                                         throwable );
              }
          }
          
      }
      protected final Object               MONITOR      = new Object();
  
      protected boolean                    m_running;
      protected HashMap                    m_jobs;
      protected BinaryHeap                 m_priorityQueue;
      
      public void init()
      {
          m_jobs = new HashMap();
          m_priorityQueue = new BinaryHeap();
      }
  
      public void destroy()
      {
          m_running = false;
          synchronized( MONITOR ) { MONITOR.notify(); }
          m_jobs = null;
          m_priorityQueue = null;
      }
  
      public void addJob( final String name, final Job job )
      {
          removeJob( name );
  
          final JobEntry jobEntry = new JobEntry( name, job );
          m_jobs.put( name, job );
          m_priorityQueue.insert( jobEntry );
  
          if( job == m_priorityQueue.peek() )
          {
              synchronized( MONITOR ) { MONITOR.notify(); }
          }
      }
  
      public void removeJob( final String name )
      {
          //use the kill-o-matic against any job with same name
          final JobEntry jobEntry = (JobEntry)m_jobs.get( name );
          if( null != jobEntry ) jobEntry.invalidate();
      }
  
      public Job getJob( final String name )
      {
          final JobEntry jobEntry = (JobEntry)m_jobs.get( name );
  
          if( null != jobEntry ) return jobEntry.getJob();
          else return null;
      }    
  
      /**
       * Helper method to configure a task if it is required.
       *
       * @param name the name of job
       * @param runnable the task
       * @param configuration the configuration (can be null if no configuration available)
       */
      protected void doConfigure( final String name, 
                                  final Runnable runnable, 
                                  final Configuration configuration )
          throws ConfigurationException
      {
          if( runnable instanceof Configurable )
          {
              if( null == configuration )
              {
                  getLogger().warn( "Configurable task " + name + " has no configuration." );
              }
              else
              {
                  ((Configurable)runnable).configure( configuration );
              }
          }
          else if( null != configuration )
          {
              getLogger().warn( "Non-configurable task " + name + " has a configuration." );
          }
      }
  
      /**
       * Actually run a job.
       *
       * @param jobEntry the jobEntry to run
       */
      protected void runJob( final JobEntry jobEntry )
      {
          final Job job = jobEntry.getJob();
          final Runnable runnable = job.getRunnable();
          final Configuration configuration = job.getConfiguration();
          
          try
          {
              doConfigure( jobEntry.getName(), runnable, configuration );
          }
          catch( final ConfigurationException ce )
          {
              getLogger().warn( "Failed to configure job " + jobEntry.getName(), ce );
              return;
          }
          
          try
          {
              final JobRunner runner = new JobRunner( jobEntry.getName(), runnable );
              runner.setLogger( getLogger() );
              ThreadManager.getWorkerPool("job-scheduler").execute( runner );
          }
          catch( final Exception e )
          {
              getLogger().warn( "Execution occured while running job " + jobEntry.getName(), e );
          }
      }
  
      /**
       * Main execution loop the detects when a job is to run 
       * and starts it appropriate times.
       */
      public void run()
      {
          m_running = true;
  
          while( m_running )
          {
              long duration = 0;
  
              if( !m_priorityQueue.isEmpty() )
              {
                  final JobEntry jobEntry = 
                      (JobEntry)m_priorityQueue.peek();
                  duration = jobEntry.getNextTime() - System.currentTimeMillis();
  
                  if( duration < 0 )
                  {
                      //time to run job so remove it from priority queue
                      //and run it
                      m_priorityQueue.pop();
  
                      //if job has been invalidated then remove it and continue
                      if( !jobEntry.isValid() ) continue;
  
                      runJob( jobEntry );
  
                      //reschedule if appropriate
                      final long next = 
                          jobEntry.getJob().getTimeAfter( System.currentTimeMillis() );
  
                      if( 0 < next )
                      {
                          jobEntry.setNextTime( next );
                          m_priorityQueue.insert( jobEntry );
                      }
  
                      continue;
                  }
              }
  
              //wait/sleep until monitor is signalled which occurs when 
              //next jobs is likely to occur or when a new job gets added to 
              //top of heap
              try { synchronized( MONITOR ) { MONITOR.wait( duration ); } }
              catch( final InterruptedException ie ) { }
          }
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/scheduler/DefaultJobScheduler.xinfo
  
  Index: DefaultJobScheduler.xinfo
  ===================================================================
  <?xml version="1.0"?> 
   
  <blockinfo> 
   
    <meta> 
   
      <contributors> 
        <author name="Peter Donald" email="donaldp@mad.scientist.com"/> 
      </contributors> 
   
    </meta> 
   
    <!-- services that are offered by this block --> 
    <services> 
      <service name="org.apache.cornerstone.services.scheduler.JobScheduler" version="1.0" /> 
    </services> 
   
  </blockinfo> 
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/scheduler/DefaultTimeScheduler.java
  
  Index: DefaultTimeScheduler.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.scheduler;
  
  import java.util.Hashtable;
  import java.util.NoSuchElementException;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Disposable;
  import org.apache.avalon.Initializable;
  import org.apache.phoenix.Block;
  import org.apache.cornerstone.services.scheduler.TimeScheduler;
  import org.apache.cornerstone.services.scheduler.TimeTrigger;
  import org.apache.cornerstone.services.scheduler.Target;
  import org.apache.avalon.util.BinaryHeap;
  import org.apache.avalon.util.thread.ThreadContext;
  import org.apache.log.Logger;
  
  /**
   * Default implementation of TimeScheduler service.
   *
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   */
  public class DefaultTimeScheduler
      extends AbstractLoggable
      implements Block, TimeScheduler, Initializable, Disposable, Runnable
  {
      protected final Object               m_monitor         = new Object();
  
      protected boolean                    m_running;
      protected Hashtable                  m_entries;
      protected BinaryHeap                 m_priorityQueue;
      
      public void init()
      {
          m_entries = new Hashtable();
          m_priorityQueue = new BinaryHeap();
      }
  
      public void dispose()
      {
          m_running = false;
          synchronized( m_monitor ) { m_monitor.notify(); }
          m_entries = null;
          m_priorityQueue = null;
      }
  
      /**
       * Schedule a time based trigger.
       * Note that if a TimeTrigger already has same name then it is removed.
       *
       * @param name the name of the trigger
       * @param trigger the trigger
       * @param target the target
       */
      public void addTrigger( final String name, 
                              final TimeTrigger trigger, 
                              final Target target )
      {
          try { removeTrigger( name ); }
          catch( final NoSuchElementException nse ) {}
  
          final TimeScheduledEntry entry = new TimeScheduledEntry( name, trigger, target );
          m_entries.put( name, entry );
          rescheduleEntry( entry, false );
  
          if( entry == m_priorityQueue.peek() )
          {
              synchronized( m_monitor ) { m_monitor.notify(); }
          }
      }
  
      /**
       * Remove a scheduled trigger by name.
       *
       * @param name the name of the trigger
       * @exception NoSuchElementException if no trigger exists with that name
       */
      public void removeTrigger( String name )
          throws NoSuchElementException
      {
          //use the kill-o-matic against any entry with same name
           final TimeScheduledEntry entry = getEntry( name );
           entry.invalidate();
      }
  
      /**
       * Force a trigger time to be recalculated.
       *
       * @param name the name of the trigger
       * @exception NoSuchElementException if no trigger exists with that name
       */
      public void resetTrigger( String name )
          throws NoSuchElementException
      {
          final TimeScheduledEntry entry = getEntry( name );
          rescheduleEntry( entry, true );
      }    
  
      /**
       * Reschedule an entry.
       * if clone is true then invalidate old version and create a new entry to 
       * insert into queue.
       *
       * @param timeEntry the entry
       * @param clone true if new entry is to be created
       */
      protected void rescheduleEntry( final TimeScheduledEntry timeEntry, final boolean clone )
      {
          TimeScheduledEntry entry = timeEntry;
  
          if( clone )
          {
              entry = new TimeScheduledEntry( timeEntry.getName(),
                                              timeEntry.getTimeTrigger(),
                                              timeEntry.getTarget() );
              timeEntry.invalidate();
          }
  
          //reschedule if appropriate
          final long next = entry.getTimeTrigger().getTimeAfter( System.currentTimeMillis() );
  
          if( 0 < next )
          {
              entry.setNextTime( next );
              m_priorityQueue.insert( entry );
  
              if( entry == m_priorityQueue.peek() )
              {
                  synchronized( m_monitor ) { m_monitor.notify(); }
              }
          }
      }
  
      /**
       * Retrieve entry from set.
       *
       * @param name the name of entry
       * @return the entry
       * @exception NoSuchElementException if no entry is found with that name
       */
      protected TimeScheduledEntry getEntry( final String name )
          throws NoSuchElementException
      {
          //use the kill-o-matic against any entry with same name
           final TimeScheduledEntry entry = (TimeScheduledEntry)m_entries.get( name );
          if( null != entry ) 
          {
              return entry;
          }
          else
          {
              throw new NoSuchElementException();
          }
      }
  
      protected void runEntry( final TimeScheduledEntry entry )
      {
          final Logger logger = getLogger();
          final Runnable runnable = new Runnable()
          {
              public void run()
              {
                  try { entry.getTarget().targetTriggered( entry.getName() ); }
                  catch( final Throwable t )
                  {
                      logger.warn( "Error occured executin trigger " + entry.getName(), t );
                  }
              }
          };
         
          //this should suck threads from a named pool
          try { ThreadContext.getCurrentThreadPool().execute( runnable ); }
          catch( final Exception e )
          {
              getLogger().warn( "Error executing trigger " + entry.getName(), e );
          }
      }
  
      public void run()
      {
          m_running = true;
  
          while( m_running )
          {
              long duration = 0;
  
              if( !m_priorityQueue.isEmpty() )
              {
                  final TimeScheduledEntry entry = 
                      (TimeScheduledEntry)m_priorityQueue.peek();
                  duration = entry.getNextTime() - System.currentTimeMillis();
  
                  if( 0 == duration )
                  {
                      //give a short duration that will sleep
                      // so that next loop will definetly be below 0.
                      //Can not act on zero else multiple runs could go through 
                      //at once
                      duration = 1;
                  }
                  else if( duration < 0 )
                  {
                      //time to run job so remove it from priority queue
                      //and run it
                      m_priorityQueue.pop();
  
                      //if job has been invalidated then remove it and continue
                      if( !entry.isValid() ) continue;
  
                      runEntry( entry );
  
                      rescheduleEntry( entry, false );
                      continue;
                  }
              }
  
              //wait/sleep until m_monitor is signalled which occurs when 
              //next jobs is likely to occur or when a new job gets added to 
              //top of heap
              try { synchronized( m_monitor ) { m_monitor.wait( duration ); } }
              catch( final InterruptedException ie ) { }
          }
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/scheduler/DefaultTimeScheduler.xinfo
  
  Index: DefaultTimeScheduler.xinfo
  ===================================================================
  <?xml version="1.0"?> 
   
  <blockinfo> 
   
    <meta> 
   
      <contributors> 
        <author name="Peter Donald" email="donaldp@apache.org"/> 
      </contributors> 
   
    </meta> 
   
    <!-- services that are offered by this block --> 
    <services> 
      <service name="org.apache.cornerstone.services.scheduler.TimeScheduler" version="1.0" /> 
    </services> 
   
  </blockinfo> 
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/scheduler/JobEntry.java
  
  Index: JobEntry.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.scheduler;
  
  import org.apache.cornerstone.services.scheduler.Job;
  
  /**
   * Class use internally to package to hold job entries.
   *
   * @author <a href="mailto:donaldp@mad.scientist.com">Peter Donald</a>
   */
  final class JobEntry
      implements Comparable
  {
      protected final String   m_name;
      protected final Job      m_job;
  
      //cached version of time from Job class
      protected long           m_time;
      protected boolean        m_isValid;
  
      /**
       * Constructor that constructs a JobEntry with a name and a job to do.
       *
       * @param name the name of Job
       * @param job the job
       */
      JobEntry( final String name, final Job job )
      {
          m_name = name;
          m_job = job;
          m_time = job.getTimeAfter( System.currentTimeMillis() );
          m_isValid = true;
      }
  
      /**
       * Return name of job.
       *
       * @return the name of job
       */
      public String getName()
      {
          return m_name;
      }
  
      /**
       * Return the job indicated by this entry.
       *
       * @return the Job
       */
      public Job getJob()
      {
          return m_job;
      }
  
      /**
       * Determine if this entry is valid
       *
       * @return true if job is valid, false otherwise
       */
      public boolean isValid()
      {
          return m_isValid;
      }
  
      /**
       * Invalidate job
       */
      public void invalidate()
      {
          m_isValid = false;
      }
  
      /**
       * Retrieve cached time when job should run next.
       *
       * @return the time in milliseconds when job should run
       */
      public long getNextTime()
      {
          return m_time;
      }
  
      /**
       * Set cached time in milliseconds when job should run
       *
       * @param time the time
       */
      public void setNextTime( long time )
      {
          m_time = time;
      }
  
      /**
       * Implement comparable interface used to help sort jobs.
       * Jobs are compared based on next time to run
       *
       * @param object the other job
       * @return -'ve value if other job occurs before this job
       */
      public int compareTo( final Object object )
      {
          final JobEntry other = (JobEntry)object;
          return (int)(other.m_time - m_time);
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/scheduler/TimeScheduledEntry.java
  
  Index: TimeScheduledEntry.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.scheduler;
  
  import org.apache.cornerstone.services.scheduler.TimeTrigger;
  import org.apache.cornerstone.services.scheduler.Target;
  
  /**
   * Class use internally to package to hold scheduled time entries.
   *
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   */
  final class TimeScheduledEntry
      implements Comparable
  {
      protected final String       m_name;
      protected final TimeTrigger  m_trigger;
      protected final Target       m_target;
  
      //cached version of time from TimeTrigger class
      protected long               m_time;
      protected boolean            m_isValid;
  
      public TimeScheduledEntry( String name, TimeTrigger trigger, Target target )
      {
          m_name = name;
          m_trigger = trigger;
          m_target = target;
          //m_time = m_trigger.getTimeAfter( System.currentTimeMillis() );
          m_isValid = true;
      }
  
      /**
       * Return name of trigger.
       *
       * @return the name of trigger
       */
      public String getName()
      {
          return m_name;
      }
  
      public Target getTarget()
      {
          return m_target;
      }
  
      public TimeTrigger getTimeTrigger()
      {
          return m_trigger;
      }
  
      /**
       * Determine if this entry is valid
       *
       * @return true if trigger is valid, false otherwise
       */
      public boolean isValid()
      {
          return m_isValid;
      }
  
      /**
       * Invalidate trigger
       */
      public void invalidate()
      {
          m_isValid = false;
      }
  
      /**
       * Retrieve cached time when trigger should run next.
       *
       * @return the time in milliseconds when trigger should run
       */
      public long getNextTime()
      {
          return m_time;
      }
  
      /**
       * Set cached time in milliseconds when trigger should run
       *
       * @param time the time
       */
      public void setNextTime( long time )
      {
          m_time = time;
      }
  
      /**
       * Implement comparable interface used to help sort triggers.
       * Triggers are compared based on next time to run
       *
       * @param object the other trigger
       * @return -'ve value if other trigger occurs before this trigger
       */
      public int compareTo( final Object object )
      {
          final TimeScheduledEntry other = (TimeScheduledEntry)object;
          return (int)-(other.m_time - m_time);
      }
  
      public String toString()
      {
          return "TimeEntry[ name=" + m_name + " valid=" + m_isValid + " time=" + m_time;
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/security/DefaultRoleManager.java
  
  Index: DefaultRoleManager.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.security;
  
  import java.security.Principal;
  import java.util.Hashtable;
  import org.apache.cornerstone.services.security.RoleManager;
  import org.apache.phoenix.Block;
  
  /**
   * Service to manager the role mappings for principals.
   * 
   * This currently assumes principal is the prime dimension 
   * which could be wrong. It could be that roles are a primary
   * aspect and 
   *
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   */
  public class DefaultRoleManager 
      implements Block, RoleManager
  {
      protected Hashtable          m_principals   = new Hashtable();
  
      public void removeRoleMapping( final Principal principal )
      {
          checkPrincipal();
          final String name = principal.getName();
          m_principals.remove( name );
      }
  
      public void addRoleMapping( final Principal principal, final String[] roles )
      {
          checkPrincipal();
          final String name = principal.getName();
          m_principals.put( name, roles );
      }
  
      public boolean isPrincipalInRole( final Principal principal, final String role )
      {
          checkPrincipal();
          final String name = principal.getName();
          final String[] roles = (String[])m_principals.get( name );
  
          if( null != roles )
          {
              for( int i = 0; i < roles.length; i++ )
              {
                  if( roles[ i ].equals( role ) )
                  {
                      return true;
                  }
              }
          }
  
          return false;
      }
  
      protected void checkPrincipal()
      {
          //TOTO: verify that Principal is valid ....
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/serversocket/AuthenticatedServerSocketAcceptor.java
  
  Index: AuthenticatedServerSocketAcceptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.serversocket;
  
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.Socket;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Disposable;
  import org.apache.cornerstone.services.SocketServer;
  
  /**
   * This is an implementation example of a socket acceptor. A socket acceptor
   * waits on a defined (in its confs) socket for request. On a request it calls
   * the method parseRequest(Socket s) in the SocketHandler interface. The
   * specific implementation of the SocketHandler is defined again in confs.
   * Definitivly this class listen on the specific port and then call the
   * specific handler to parse the request on that socket. You must start an
   * acceptor for each port or other "request generator" you want to listen to.
   *
   * @author  Federico Barbieri <fede@apache.org>
   */
  public class AuthenticatedServerSocketAcceptor
      extends AbstractLoggable
      implements SocketServer.Listener, Disposable
  {
      protected ServerSocket               m_serverSocket;
      protected int                        m_port;
      protected SocketServer.SocketHandler m_handler;
  
      public void listen( final int port,
                          final SocketServer.SocketHandler handler,
                          final InetAddress bind )
      {
          m_handler = handler;
          m_port = port;
  
          try
          {
              m_serverSocket = new ServerSocket( m_port, 50, bind );
          }
          catch( final IOException ioe )
          {
              getLogger().error( "Cannot open AuthenticatedServerSocketAcceptor on port " +
                                 m_port + ": ", ioe );
              throw new
                  RuntimeException( "Cannot open AuthenticatedServerSocketAcceptor on port " +
                                    m_port );
          }
  
          getLogger().info( "AuthenticatedServerSocketAcceptor on port " + m_port + " ready" );
      }
  
      /**
       * This is the actual work of an acceptor.
       * In particular a ServerSocketAcceptor will accept() on the specified port.
       */
      public void run()
      {
          getLogger().info( "AuthenticatedServerSocketAcceptor on port " +
                            m_port + ": running" );
  
          try
          {
              while( true )
              {
                  final Socket socket = m_serverSocket.accept();
                  getLogger().info( "AuthenticatedServerSocketAcceptor on port " +
                                    m_port + ": request arrived" );
                  m_handler.parseRequest( socket );
              }
          }
          catch( final Exception e )
          {
              getLogger().error( "Exception on port " + m_port + ": ", e );
          }
      }
  
      public void dispose()
          throws Exception
      {
          try
          {
              m_serverSocket.close();
          }
          catch( final Exception e )
          {
              getLogger().error( "Exception while destroing AuthenticatedServerSocketAcceptor " +
                                 "on port " + m_port + ": ", e );
          }
  
          getLogger().info( "AuthenticatedServerSocketAcceptor on port " + m_port + " disposed" );
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/serversocket/ServerSocketAcceptor.java
  
  Index: ServerSocketAcceptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.serversocket;
  
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.Socket;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Disposable;
  import org.apache.cornerstone.services.SocketServer;
  import org.apache.log.Logger;
  
  /**
   * This is an implementation example of a socket acceptor. A socket acceptor
   * waits on a defined (in its confs) socket for request. On a request it calls
   * the method parseRequest(Socket s) in the SocketHandler interface. The
   * specific implementation of the SocketHandler is defined again in confs.
   * Definitivly this class listen on the specific port and then call the
   * specific handler to parse the request on that socket. You must start an
   * acceptor for each port or other "request generator" you want to listen to.
   *
   * @author  Federico Barbieri <fede@apache.org>
   */
  public class ServerSocketAcceptor 
      extends AbstractLoggable
      implements SocketServer.Listener, Disposable
  {
      protected ServerSocket                m_serverSocket;
      protected int                         m_port;
      protected SocketServer.SocketHandler  m_handler;
      
      public void listen( final int port, 
                          final SocketServer.SocketHandler handler, 
                          final InetAddress bind ) 
      {
          m_handler = handler;
          m_port = port;
  
          try
          {
              m_serverSocket = new ServerSocket( m_port, 50, bind );
          } 
          catch( final IOException ioe )
          {
              final String message = "Cannot open ServerSocketAcceptor on port " + m_port;
              getLogger().error( message , ioe );
              throw new RuntimeException( message );
          }
          
          getLogger().info( "ServerSocketAcceptor on port " + m_port + " ready" );
      }
      
  
      /**
       * This is the actual work of an acceptor.
       * In particular a ServerSocketAcceptor will accept() on the specified port.
       */
      public void run() 
      {
          getLogger().info( "ServerSocketAcceptor on port " + m_port + ": running" );
  
          try 
          {
              while( true )
              {
                  final Socket socket = m_serverSocket.accept();
                  getLogger().info( "ServerSocketAcceptor on port " + m_port + 
                                    ": request arrived" );
                  m_handler.parseRequest( socket );
              }
          }
          catch( final Exception e ) 
          {
              getLogger().error( "Exception on port " + m_port + ": ", e );
          }
      }
      
      public void dispose()
          throws Exception
      {
          try
          {
              m_serverSocket.close();
          } 
          catch( final Exception e )
          {
              getLogger().error( "Exception while destroing ServerSocketAcceptor on port " + 
                                 m_port + ": ", e );
          }
  
          getLogger().info( "ServerSocketAcceptor on port " + m_port + " disposed" );
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/serversocket/SocketManager.java
  
  Index: SocketManager.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.serversocket;
  
  import java.net.InetAddress;
  import java.util.HashMap;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.ComponentManager;
  import org.apache.avalon.Composer;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.avalon.DefaultComponentManager;
  import org.apache.avalon.Disposable;
  import org.apache.avalon.Initializable;
  import org.apache.avalon.Loggable;
  import org.apache.phoenix.Block;
  import org.apache.cornerstone.services.SocketServer;
  import org.apache.avalon.util.ObjectUtil;
  import org.apache.avalon.util.StringUtil;
  import org.apache.avalon.util.lang.ThreadManager;
  
  /**
   * This is an implementation example of a socket acceptor. A socket acceptor
   * waits on a defined (in its confs) socket for request. On a request it calls
   * the method parseRequest(Socket s) in the SocketHandler interface. The
   * specific implementation of the SocketHandler is defined again in confs.
   * Definitivly this class listen on the specific port and then call the
   * specific handler to parse the request on that socket. You must start an
   * acceptor for each port or other "request generator" you want to listen to.
   *
   * @author Federico Barbieri <fede@apache.org>
   * @deprecated This class is deprecated in favour of org.apache.cornerstone.blocks.sockets.* and org.apache.cornerstone.blocks.connection.*. This still has bugs with respect to closing connections at shutdown time and it also exhibits scalability problems.
   */
  public class SocketManager 
      extends AbstractLoggable
      implements Block, SocketServer, Configurable, Disposable
  {
      protected final HashMap              m_listeners         = new HashMap();
      protected final ComponentManager     m_componentManager  = new DefaultComponentManager();
      protected Configuration              m_configuration;
      
      public void configure( final Configuration configuration ) 
      {
          m_configuration = configuration;
      }
      
      public void dispose() 
          throws Exception
      {
          final Iterator openListener = m_listeners.values().iterator();
          
          while( openListener.hasNext() )
          {
              shutdownListener( (SocketServer.Listener)openListener.next() );
          }
  
          m_listeners.clear();
      }
  
      public void openListener( final String name, 
                                final String type,
                                final int port,
                                final SocketServer.SocketHandler handler ) 
      {
          openListener( name, type, port, null, handler );
      }
  
      public void openListener( final String name, 
                                final String type, 
                                final int port, 
                                final InetAddress bind, 
                                final SocketServer.SocketHandler handler ) 
      {
          getLogger().info( "Instantiating Listener " + name + " (" + 
                            type + ") on port " + port);
  
          try 
          {
              final Configuration[] listeners = 
                  m_configuration.getChild("listenerDefinition").getChildren("listener");
                  
              for( int i = 0; i < listeners.length; i++ )
              {
                  final Configuration element = listeners[ i ];
                  final String elementType = element.getAttribute("type");
                          
                  if( -1 != elementType.indexOf( type ) ) 
                  {
                      final ClassLoader classLoader = getClass().getClassLoader();
                      final String classname = element.getAttribute( "class" );
                      final SocketServer.Listener acceptor = (SocketServer.Listener)
                          ObjectUtil.createObject( classLoader, classname );
  
                      setupLogger( acceptor );
  
                      if( acceptor instanceof Composer )
                      {
                          ((Composer)acceptor).compose( m_componentManager );
                      }                    
              
                      if( acceptor instanceof Configurable )
                      {
                          ((Configurable)acceptor).configure( element );
                      }
  
                      if( acceptor instanceof Initializable )
                      {
                          ((Initializable)acceptor).init();
                      }
                                  
                      acceptor.listen( port, handler, bind );
                      ThreadManager.getWorkerPool("default").execute( acceptor );
                      m_listeners.put( name, acceptor );
                      return;
                  }
              }
                  
              throw new RuntimeException( "Cannot find any listener like " + type );
          } 
          catch( final ConfigurationException ce ) 
          {
              throw new RuntimeException( "Cannot open new listener (" + type + ") on port " + 
                                          port + ": " + ce.getMessage());
          } 
          catch( final InstantiationException ie ) 
          {
              throw new RuntimeException( "Cannot open new listener (" + type + ") on port " + 
                                          port + ": " + ie.getMessage());
          } 
          catch( final IllegalAccessException iae ) 
          {
              throw new RuntimeException( "Cannot open new listener (" + type + ") on port " + 
                                          port + ": " + iae.getMessage());
          } 
          catch( final ClassNotFoundException cnfe ) 
          {
              throw new RuntimeException( "Cannot open new listener (" + type + ") on port " + 
                                          port + ": " + cnfe.getMessage());
          } 
          catch( final Exception e ) 
          {
              throw new RuntimeException( "Cannot open new listener (" + type + ") on port " + 
                                          port + ": " + StringUtil.printStackTrace( e, true ) );
          }
      }
  
      public void closeListener( final String name ) 
      {
          final SocketServer.Listener listener = (SocketServer.Listener) m_listeners.get( name );
          if( null == listener ) return;
          m_listeners.remove( name );
          shutdownListener( listener );
      }
  
      protected void shutdownListener( final SocketServer.Listener listener ) 
      {
          try
          {
              if( listener instanceof Disposable )
              {
                  ((Disposable)listener).dispose();
              }
          } 
          catch( final Exception e ) {}
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/serversocket/SocketManager.xinfo
  
  Index: SocketManager.xinfo
  ===================================================================
  <?xml version="1.0"?>
  
  <blockinfo>
  
    <meta>
  
      <contributors>
        <author name="Federico Barbier" email="fede@apache.org"/>
      </contributors>
  
    </meta>
  
    <!-- services that are offered by this block -->
    <services>
      <service name="org.apache.cornerstone.services.SocketServer" version="1.0" />
    </services>
  
  </blockinfo>
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/serversocket/TLSServerSocketAcceptor.java
  
  Index: TLSServerSocketAcceptor.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.serversocket;
  
  import com.sun.net.ssl.KeyManagerFactory;
  import com.sun.net.ssl.SSLContext;
  import java.io.FileInputStream;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.Socket;
  import java.security.KeyStore;
  import javax.net.ServerSocketFactory;
  import javax.net.ssl.SSLServerSocketFactory;
  import javax.security.cert.X509Certificate;
  import org.apache.avalon.ComponentManager;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.avalon.Disposable;
  import org.apache.avalon.Initializable;
  import org.apache.cornerstone.services.SocketServer;
  import org.apache.avalon.AbstractLoggable;
  
  /**
   * This is an implementation example of a secure socket acceptor. A socket acceptor
   * waits on a defined (in its confs) socket for request. On a request it calls
   * the method parseRequest(Socket s) in the SocketHandler interface. The 
   * specific implementation of the SocketHandler is defined again in confs.
   * Definitivly this class listen on the specific port and then call the 
   * specific handler to parse the request on that socket. You must start an 
   * acceptor for each port or other "request generator" you want to listen to.
   *
   * This socket acceptor implements Transport Layer Security (TLS) using  the JSSE extension.
   * It currently supports the Sun SSL provider shipped with JSSE. Support for other
   * crypto providers may be added in due course.
   *
   * @author  Federico Barbieri <fede@apache.org>
   * @author  Charles Benett <charles@benett1.demon.co.uk>
   */
  public class TLSServerSocketAcceptor 
      extends AbstractLoggable
      implements SocketServer.Listener, Configurable, Initializable, Disposable
  {
      protected Configuration                  m_configuration;
      protected ServerSocket                   m_serverSocket;
      protected int                            m_port;
      protected SocketServer.SocketHandler     m_handler;
      protected KeyStore                       m_keyStore;
      protected String                         m_keyStoreFile;
      protected char[]                         m_passphrase;
      
      public void configure( final Configuration configuration ) 
          throws ConfigurationException
      {
          m_keyStoreFile = configuration.getChild("serverKeysFile").getValue();
  
          // Get passphrase for access to keys.
          // TBD: Replace with console interaction
          m_passphrase = "passphrase".toCharArray();
      }
  
      public void init() throws Exception 
      {
          try
          {
              m_keyStore = KeyStore.getInstance("JKS");
              m_keyStore.load( new FileInputStream( "../conf/" + m_keyStoreFile ), m_passphrase );
          } 
          catch( final Exception e ) 
          {
              getLogger().error("Exception loading keystore from: " + m_keyStoreFile, e);
          }
          
          getLogger().info("Keystore loaded from: " + m_keyStoreFile);
      }
      
      public void listen( final int port, 
                          final SocketServer.SocketHandler handler, 
                          final InetAddress bind ) 
      {
          m_handler = handler;
          m_port = port;
  
          try
          {
              // set up key manager to do server authentication
              final SSLContext sslContext = SSLContext.getInstance("TLS");
              final KeyManagerFactory keyManagerFactory = 
                  KeyManagerFactory.getInstance("SunX509");
              keyManagerFactory.init( m_keyStore, m_passphrase );
              sslContext.init( keyManagerFactory.getKeyManagers(), null, null );
                  
              // Create TLS socket
              final SSLServerSocketFactory sslServerSocketFactory = 
                  sslContext.getServerSocketFactory();
              m_serverSocket = sslServerSocketFactory.createServerSocket( m_port, 50, bind );
                  
          } 
          catch( final Exception e ) 
          {
              getLogger().error( "Cannot open TLSServerSocketAcceptor on port " + m_port, e );
              throw new 
                  RuntimeException( "Cannot open TLSServerSocketAcceptor on port " + m_port );
          }
         
          getLogger().info( "TLSServerSocketAcceptor on port " + m_port + " ready" );
      }
      
      /**
       * This is the actual work of an acceptor.
       * In particular a ServerSocketAcceptor will accept() on the specified m_port.
       */
      public void run() 
      {
          getLogger().info( "TLSServerSocketAcceptor on port " + m_port + ": running" );
          try 
          {
              while( true ) 
              {
                  final Socket socket = m_serverSocket.accept();
                  getLogger().info( "TLSServerSocketAcceptor on port " + m_port + 
                               ": request arrived" );
  
                  m_handler.parseRequest( socket );
              }
          } 
          catch( final Exception e ) 
          {
              getLogger().error( "Exception on port " + m_port, e );
          }
      }
      
      public void dispose() throws Exception 
      {
          try
          {
              m_serverSocket.close();
          } 
          catch( final Exception e ) 
          {
              getLogger().error( "Exception while destroing TLSServerSocketAcceptor on port " + 
                            m_port, e );
          }
                  
          getLogger().info( "TLSServerSocketAcceptor on port " + m_port + " disposed" );
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/sockets/DefaultServerSocketFactory.java
  
  Index: DefaultServerSocketFactory.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.sockets;
  
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import org.apache.avalon.Component;
  import org.apache.cornerstone.services.sockets.ServerSocketFactory;
  
  /**
   * Factory implementation for vanilla TCP sockets.
   *
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   */
  public class DefaultServerSocketFactory
      implements ServerSocketFactory, Component
  {
      /**
       * Creates a socket on specified port.
       *
       * @param port the port
       * @return the created ServerSocket
       * @exception IOException if an error occurs
       */
      public ServerSocket createServerSocket( final int port )
          throws IOException
      {
          return new ServerSocket( port );
      }
  
      /**
       * Creates a socket on specified port with a specified backLog.
       *
       * @param port the port
       * @param backLog the backLog
       * @return the created ServerSocket
       * @exception IOException if an error occurs
       */
      public ServerSocket createServerSocket( int port, int backLog )
          throws IOException
      {
          return new ServerSocket( port, backLog );
      }
  
      /**
       * Creates a socket on a particular network interface on specified port 
       * with a specified backLog.
       *
       * @param port the port
       * @param backLog the backLog
       * @param bindAddress the network interface to bind to.
       * @return the created ServerSocket
       * @exception IOException if an error occurs
       */
      public ServerSocket createServerSocket( int port, int backLog, InetAddress bindAddress )
          throws IOException
      {
          return new ServerSocket( port, backLog, bindAddress );
      }
  }
  
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/sockets/DefaultSocketFactory.java
  
  Index: DefaultSocketFactory.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.sockets;
  
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.Socket;
  import org.apache.cornerstone.services.sockets.SocketFactory;
  
  /**
   * The vanilla implementation of SocketFactory.
   *
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   */
  public class DefaultSocketFactory
      implements SocketFactory
  {
      /**
       * Create a socket and connect to remote address specified.
       *
       * @param address the remote address
       * @param port the remote port
       * @return the socket
       * @exception IOException if an error occurs
       */
      public Socket createSocket( final InetAddress address, final int port )
          throws IOException
      {
          return new Socket( address, port );
      }
  
      /**
       * Create a socket and connect to remote address specified 
       * originating from specified local address.
       *
       * @param address the remote address
       * @param port the remote port
       * @param localAddress the local address
       * @param localPort the local port
       * @return the socket
       * @exception IOException if an error occurs
       */
      public Socket createSocket( final InetAddress address, final int port, 
                                  final InetAddress localAddress, final int localPort )
          throws IOException
      {
          return new Socket( address, port, localAddress, localPort );
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/sockets/DefaultSocketManager.java
  
  Index: DefaultSocketManager.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included  with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.sockets;
  
  import java.util.HashMap;
  import java.util.Iterator;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Component;
  import org.apache.avalon.ComponentNotAccessibleException;
  import org.apache.avalon.ComponentNotFoundException;
  import org.apache.avalon.Context;
  import org.apache.avalon.Contextualizable;
  import org.apache.avalon.Initializable;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.avalon.util.ObjectUtil;
  import org.apache.cornerstone.services.sockets.ServerSocketFactory;
  import org.apache.cornerstone.services.sockets.SocketFactory;
  import org.apache.cornerstone.services.sockets.SocketManager;
  import org.apache.phoenix.Block;
  
  /**
   * Implementation of SocketManager.
   * 
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   */
  public class DefaultSocketManager 
      extends AbstractLoggable
      implements SocketManager, Block, Contextualizable, Configurable, Initializable
  {
      protected final HashMap              m_serverSockets   = new HashMap();
      protected final HashMap              m_sockets         = new HashMap();
  
      protected Context                    m_context;
      protected Configuration              m_configuration;
  
      public void contextualize( final Context context )
      {
          m_context = context;
      }
  
      /**
       * Configure the SocketManager.
       *
       * @param configuration the Configuration
       * @exception ConfigurationException if an error occurs
       */
      public void configure( final Configuration configuration )
          throws ConfigurationException
      {
          m_configuration = configuration;
      }
      
      public void init() 
          throws Exception 
      {
          final Configuration[] serverSockets = 
              m_configuration.getChild( "server-sockets" ).getChildren( "factory" );
  
          for( int i = 0; i < serverSockets.length; i++ )
          {
              final Configuration element = serverSockets[ i ];
              final String name = element.getAttribute( "name" );
              final String className = element.getAttribute( "class" );
  
              setupServerSocketFactory( name, className, element );
          }
  
          final Configuration[] clientSockets = 
              m_configuration.getChild( "client-sockets" ).getChildren( "factory" );
          
          for( int i = 0; i < clientSockets.length; i++ )
          {
              final Configuration element = clientSockets[ i ];
              final String name = element.getAttribute( "name" );
              final String className = element.getAttribute( "class" );
              
              setupClientSocketFactory( name, className, element );
          }
      }
  
      protected void setupServerSocketFactory( final String name, 
                                               final String className,
                                               final Configuration configuration )
          throws Exception
      {
          final Object object = createFactory( name, className, configuration );
  
          if( !(object instanceof ServerSocketFactory) )
          {
              throw new ComponentNotAccessibleException( "Error creating factory " + name + 
                                                         " with class " + className + " as " +
                                                         "it does not implement the correct " + 
                                                         "interface (ServerSocketFactory)" );
          }
  
          m_serverSockets.put( name, object );
      }
  
      
      protected void setupClientSocketFactory( final String name, 
                                               final String className,
                                               final Configuration configuration )
          throws Exception
      {
          final Object object = createFactory( name, className, configuration );
          
          if( !(object instanceof SocketFactory) )
          {
              throw new ComponentNotAccessibleException( "Error creating factory " + name + 
                                                         " with class " + className + " as " +
                                                         "it does not implement the correct " + 
                                                         "interface (SocketFactory)" );
          }
          
          m_sockets.put( name, object );
      }
      
      protected Component createFactory( final String name, 
                                         final String className,
                                         final Configuration configuration )
          throws Exception
      {
          Component factory = null;
          
          try
          {
              final ClassLoader classLoader = 
                  (ClassLoader)Thread.currentThread().getContextClassLoader();
              factory = (Component)ObjectUtil.createObject( classLoader, className ); 
          }
          catch( final Exception e )
          {
              throw new ComponentNotAccessibleException( "Error creating factory with class " + 
                                                         className, e );
          }
          
          setupLogger( factory );
          
          if( factory instanceof Contextualizable )
          {
              ((Contextualizable)factory).contextualize( m_context );
          }
          
          if( factory instanceof Configurable )
          {
              ((Configurable)factory).configure( configuration );
          }
          
          if( factory instanceof Initializable )
          {
              ((Initializable)factory).init();
          }
  
          return factory;
      }
  
      /**
       * Retrieve a server socket factory by name.
       *
       * @param name the name of server socket factory
       * @return the ServerSocketFactory
       * @exception ComponentNotFoundException if server socket factory is not available
       */
      public ServerSocketFactory getServerSocketFactory( String name )
          throws ComponentNotFoundException
      {
          final ServerSocketFactory factory = (ServerSocketFactory)m_serverSockets.get( name );
  
          if( null != factory )
          {
              return factory;
          }
          else
          {
              throw new ComponentNotFoundException( "Unable to locate server socket factory " +
                                                    "named " + name );
          }
      }
      
      /**
       * Retrieve a client socket factory by name.
       *
       * @param name the name of client socket factory
       * @return the SocketFactory
       * @exception ComponentNotFoundException if socket factory is not available
       */
      public SocketFactory getSocketFactory( final String name )
          throws ComponentNotFoundException
      {
          final SocketFactory factory = (SocketFactory)m_sockets.get( name );
          
          if( null != factory )
          {
              return factory;
          }
          else
          {
              throw new ComponentNotFoundException( "Unable to locate client socket factory " +
                                                    "named " + name );
          }
      }
  }
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/sockets/DefaultSocketManager.xinfo
  
  Index: DefaultSocketManager.xinfo
  ===================================================================
  <?xml version="1.0"?>
  
  <blockinfo>
  
    <meta>
  
      <contributors>
        <author name="Peter Donald" email="donaldp@apache.org"/>
        <author name="Federico Barbier" email="fede@apache.org"/>
      </contributors>
  
    </meta>
  
    <!-- services that are offered by this block -->
    <services>
      <service name="org.apache.cornerstone.services.sockets.SocketManager" version="1.0" />
    </services>
  
  </blockinfo>
  
  
  
  1.1                  jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/sockets/TLSServerSocketFactory.java
  
  Index: TLSServerSocketFactory.java
  ===================================================================
  /*
   * Copyright (C) The Apache Software Foundation. All rights reserved.
   *
   * This software is published under the terms of the Apache Software License
   * version 1.1, a copy of which has been included with this distribution in
   * the LICENSE file.
   */
  package org.apache.cornerstone.blocks.sockets;
  
  import com.sun.net.ssl.KeyManagerFactory;
  import com.sun.net.ssl.SSLContext;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.security.KeyStore;
  import javax.net.ssl.SSLServerSocket;
  import javax.net.ssl.SSLServerSocketFactory;
  import javax.security.cert.X509Certificate;
  import org.apache.avalon.AbstractLoggable;
  import org.apache.avalon.Component;
  import org.apache.avalon.Context;
  import org.apache.avalon.Contextualizable;
  import org.apache.avalon.Initializable;
  import org.apache.avalon.configuration.Configurable;
  import org.apache.avalon.configuration.Configuration;
  import org.apache.avalon.configuration.ConfigurationException;
  import org.apache.cornerstone.services.sockets.ServerSocketFactory;
  import org.apache.phoenix.BlockContext;
  
  /**
   * Factory implementation for vanilla TCP sockets.
   *
   * @author <a href="mailto:donaldp@apache.org">Peter Donald</a>
   * @author <a href="mailto:fede@apache.org">Federico Barbieri</a>
   * @author <a href="mailto:charles@benett1.demon.co.uk">Charles Benett</a>
   * @author <a href="mailto:">Harish Prabandham</a>
   * @author <a href="mailto:">Costin Manolache</a>
   * @author <a href="mailto:">Craig McClanahan</a>
   */
  public class TLSServerSocketFactory
      extends AbstractLoggable
      implements ServerSocketFactory, Component, Contextualizable, Configurable, Initializable
  {
      protected SSLServerSocketFactory   m_factory;
      protected File                     m_baseDirectory;
  
      protected String                   m_keyStoreFile;
      protected String                   m_keyStorePassword;
      protected String                   m_keyStoreType; 
      protected String                   m_keyStoreProtocol; 
      protected String                   m_keyStoreAlgorithm; 
      protected boolean                  m_keyStoreAuthenticateClients;
  
      public void contextualize( final Context context )
      {
          final BlockContext blockContext = (BlockContext)context;
          m_baseDirectory = blockContext.getBaseDirectory();        
      }
  
      /**
       * Configure factory. Sample config is
       *
       * <keystore>
       *  <file>conf/keystore</file> <!-- location of keystore relative to .sar base directory -->
       *  <password></password> <!-- Password for the Key Store file -->
       *  <type>JKS</type> <!-- Type of the Key Store file -->
       *  <protocol>TLS</protocol> <!-- SSL protocol to use -->
       *  <algorithm>SunX509</algorithm> <!-- Certificate encoding algorithm -->
       *  <authenticate-client>false</authenticate-client> <!-- Require client authentication? -->
       * <keystore>
       *
       * @param configuration the Configuration
       * @exception ConfigurationException if an error occurs
       */
      public void configure( final Configuration configuration )
          throws ConfigurationException
      {
          final Configuration keyStore = configuration.getChild( "keystore" );
          m_keyStoreFile = keyStore.getChild( "file" ).getValue( "conf/keystore" );
          m_keyStorePassword = keyStore.getChild( "password" ).getValue();
          m_keyStoreType = keyStore.getChild( "type" ).getValue( "JKS" );
          m_keyStoreProtocol = keyStore.getChild( "protocol" ).getValue( "TLS" );
          m_keyStoreAlgorithm = keyStore.getChild( "algorithm" ).getValue( "SunX509" );
          m_keyStoreAuthenticateClients = 
              keyStore.getChild( "authenticate-client" ).getValueAsBoolean( false );
      }
  
      public void init() 
          throws Exception 
      {
          final KeyStore keyStore = initKeyStore();
          initSSLFactory( keyStore );
      }
  
      protected KeyStore initKeyStore() 
          throws Exception 
      {
          try
          {
              final KeyStore keyStore = KeyStore.getInstance( m_keyStoreType );
              final File keyStoreFile = new File( m_baseDirectory, m_keyStoreFile ); 
              final FileInputStream input = new FileInputStream( keyStoreFile );
  
              keyStore.load( input, m_keyStorePassword.toCharArray() );
              getLogger().info( "Keystore loaded from: " + keyStoreFile );
              
              return keyStore;
          } 
          catch( final Exception e ) 
          {
              getLogger().error( "Exception loading keystore from: " + m_keyStoreFile, e );
              throw e;
          }
      }
  
      protected void initSSLFactory( final KeyStore keyStore ) 
          throws Exception
      {
          /*
            java.security.Security.addProvider( new sun.security.provider.Sun() );
            java.security.Security.addProvider( new com.sun.net.ssl.internal.ssl.Provider() );
            // */
  
          // set up key manager to do server authentication
          final SSLContext sslContext = SSLContext.getInstance( m_keyStoreProtocol );
          final KeyManagerFactory keyManagerFactory = 
              KeyManagerFactory.getInstance( m_keyStoreAlgorithm );
  
          keyManagerFactory.init( keyStore, m_keyStorePassword.toCharArray() );
  
          sslContext.init( keyManagerFactory.getKeyManagers(), 
                           null, 
                           new java.security.SecureRandom() );
                  
          // Create socket factory
          m_factory = sslContext.getServerSocketFactory();
      }
      
      /**
       * Creates a socket on specified port.
       *
       * @param port the port
       * @return the created ServerSocket
       * @exception IOException if an error occurs
       */
      public ServerSocket createServerSocket( final int port )
          throws IOException
      {
          final ServerSocket serverSocket = m_factory.createServerSocket( port );
          initServerSocket( serverSocket );
          return serverSocket;
      }
  
      /**
       * Creates a socket on specified port with a specified backLog.
       *
       * @param port the port
       * @param backLog the backLog
       * @return the created ServerSocket
       * @exception IOException if an error occurs
       */
      public ServerSocket createServerSocket( int port, int backLog )
          throws IOException
      {
          final ServerSocket serverSocket = m_factory.createServerSocket( port, backLog );
          initServerSocket( serverSocket );
          return serverSocket;
      }
  
      /**
       * Creates a socket on a particular network interface on specified port 
       * with a specified backLog.
       *
       * @param port the port
       * @param backLog the backLog
       * @param bindAddress the network interface to bind to.
       * @return the created ServerSocket
       * @exception IOException if an error occurs
       */
      public ServerSocket createServerSocket( int port, int backLog, InetAddress bindAddress )
          throws IOException
      {
          final ServerSocket serverSocket = 
              m_factory.createServerSocket( port, backLog, bindAddress );
          initServerSocket( serverSocket );
          return serverSocket;
      }
  
      protected void initServerSocket( final ServerSocket serverSocket ) 
      {
          final SSLServerSocket socket = (SSLServerSocket)serverSocket;
          
          // Enable all available cipher suites when the socket is connected
          final String[] cipherSuites = socket.getSupportedCipherSuites();
          socket.setEnabledCipherSuites( cipherSuites );
  
          // Set client authentication if necessary
          socket.setNeedClientAuth( m_keyStoreAuthenticateClients );
      }
  }
  
  
  
  

Mime
View raw message