You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@avalon.apache.org by do...@apache.org on 2001/02/22 08:52:17 UTC
cvs commit: jakarta-avalon-cornerstone/src/java/org/apache/cornerstone/blocks/sockets DefaultServerSocketFactory.java DefaultSocketFactory.java DefaultSocketManager.java DefaultSocketManager.xinfo TLSServerSocketFactory.java
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 <fe...@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 <fe...@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 <fe...@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 <fe...@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 <fe...@apache.org>
* @author Charles Benett <ch...@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 );
}
}