leosimons 01/04/05 12:10:13 Added: proposal/4.0/src/java/org/apache/phoenix Restart.java Shutdown.java Start.java proposal/4.0/src/java/org/apache/phoenix/applications Application.java ApplicationException.java ServerApplication.java proposal/4.0/src/java/org/apache/phoenix/core Block.java BlockContext.java Embeddor.java Kernel.java ServerKernel.java proposal/4.0/src/java/org/apache/phoenix/engine PhoenixEmbeddor.java PhoenixKernel.java proposal/4.0/src/java/org/apache/phoenix/engine/applications DefaultServerApplication.java ServerApplicationFactory.java proposal/4.0/src/java/org/apache/phoenix/engine/deployer DefaultSarDeployer.java proposal/4.0/src/java/org/apache/phoenix/engine/deployer/blocks BlockDAG.java BlockEntry.java BlockVisitor.java DefaultBlockContext.java DefaultBlockDeployer.java RoleEntry.java proposal/4.0/src/java/org/apache/phoenix/engine/facilities ApplicationManager.java ClassLoader.java ConfigurationManager.java LogManager.java SecurityManager.java ThreadManager.java proposal/4.0/src/java/org/apache/phoenix/engine/jmx Manager.java proposal/4.0/src/java/org/apache/phoenix/facilities Facility.java Log: Creating a proposal structure for version 4 of phoenix. Phoenix 4 is ment to work with version 4 of the framework, include jmx support, use an embeddor to talk with the environment as detailed in the JSF JSR and generally be a lot cleaner than the current setup. A detailed changes.txt will be written once the first version of this proposal stabilises. Revision Changes Path 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/Restart.java Index: Restart.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.phoenix; /** * Class to restart phoenix. Call to restart the server. * * @author <a href="[EMAIL PROTECTED]">Leo Simons</a> */ public class Restart { public Restart() { (new Start()).restart(); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/Shutdown.java Index: Shutdown.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.phoenix; /** * Class to exit phoenix. Call to shut down the server. * * @author <a href="[EMAIL PROTECTED]">Leo Simons</a> */ public class Shutdown { public Shutdown() { (new Start()).shutdown(); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/Start.java Index: Start.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.phoenix; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import javax.management.MBeanServer; import org.apache.framework.context.Context; import org.apache.framework.context.DefaultContext; import org.apache.framework.container.Entry; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.DefaultConfiguration; import org.apache.framework.configuration.ConfigurationException; import org.apache.framework.lifecycle.Disposable; import org.apache.avalon.component.DefaultComponentManager; import org.apache.phoenix.core.Embeddor; import org.apache.phoenix.engine.PhoenixEmbeddor; /** * Entry point to phoenix. Call to start the server. // TODO: list available arguments * * @author <a href="[EMAIL PROTECTED]">Leo Simons</a> * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> */ public class Start implements Disposable { // embeddor private static Embeddor embeddor; // embeddor configuration settings private static String embeddorClass; private static final String DEFAULT_EMBEDDOR_CLASS = "org.apache.phoenix.engine.PhoenixEmbeddor"; private static String deployerClass; private static final String DEFAULT_DEPLOYER_CLASS = "org.apache.phoenix.engine.DefaultSarDeployer"; private static String mBeanServerClass; private static final String DEFAULT_MBEANSERVER_CLASS = "org.apache.jmx.MBeanServerImpl"; private static String kernelClass; private static final String DEFAULT_KERNEL_CLASS = "org.apache.phoenix.engine.DefaultKernel"; private static String configurationSource; private static final String DEFAULT_CONFIGURATION_SOURCE = "../conf/server.xml"; // monitor these for status changes private static boolean singleton = false; private static boolean shutdown = false; private static boolean restart = false; // command line options private static final int DEBUG_LOG_OPT = 'd'; private static final int HELP_OPT = 'h'; private static final int LOG_FILE_OPT = 'l'; private static final int APPS_PATH_OPT = 'a'; /** * Entry-point into Phoenix. See the class description for a list of the possible * arguments. */ public void main( final String[] args ) { if( singleton ) { System.out.println( "Sorry, an instance of phoenix is already running. Phoenix cannot be run multiple times in the same VM." ); System.exit( 1 ); } singleton = true; final Start start = new Start(); try { start.execute( args ); } catch( final Throwable throwable ) { System.out.println( "There was an uncaught exception:" ); System.out.println( "---------------------------------------------------------" ); System.out.println( throwable.toString() ); System.out.println( "---------------------------------------------------------" ); System.out.println( "Please check the configuration files and restart phoenix." ); System.out.println( "If the problem persists, contact the Avalon project. See" ); System.out.println( "http://jakarta.apache.org/avalon for more information." ); System.exit( 1 ); } } ///////////////////////// /// LIFECYCLE METHODS /// ///////////////////////// /** * Shuts down and immediately restarts the server using the * same settings. */ public void restart() { this.restart = true; } /** * Shuts down the server. */ public void dispose() { this.shutdown = true; } ///////////////////////// /// EXECUTION METHODS /// ///////////////////////// private void execute( final String[] args ) throws Exception { try { final PrivilegedExceptionAction action = new PrivilegedExceptionAction() { public Object run() throws Exception { exec( args ); return null; } }; AccessController.doPrivileged( action ); } catch( final PrivilegedActionException pae ) { // only "checked" exceptions will be "wrapped" in a PrivilegedActionException. throw pae.getException(); } } private void exec( final String[] args ) throws Exception { this.parseCommandLineOptions( args ); this.createEmbeddor(); final DefaultContext ctx = new DefaultContext(); ctx.put( "kernel-class", this.kernelClass ); ctx.put( "deployer-class", this.deployerClass ); ctx.put( "mBeanServer-class", this.mBeanServerClass ); ctx.put( "kernel-configuration-source", this.configurationSource ); ctx.put( "log-destination", "../log/phoenix.log" ); final Configuration conf = new DefaultConfiguration("phoenix","localhost"); // run Embeddor lifecycle this.embeddor.contextualize(ctx); this.embeddor.configure(conf); this.embeddor.init(); while( !this.shutdown ) { while( !this.restart ) { this.embeddor.run(); } this.embeddor.restart(); this.restart = false; } embeddor.dispose(); System.exit( 0 ); } ////////////////////// /// HELPER METHODS /// ////////////////////// private void parseCommandLineOptions( final String[] args ) { // start with the defaults this.mBeanServerClass = this.DEFAULT_MBEANSERVER_CLASS; this.kernelClass = this.DEFAULT_KERNEL_CLASS; this.embeddorClass = this.DEFAULT_EMBEDDOR_CLASS; this.deployerClass = this.DEFAULT_DEPLOYER_CLASS; this.configurationSource = this.DEFAULT_CONFIGURATION_SOURCE; // TODO: update code below to set the code above // setup parser and get arguments final CLOptionDescriptor[] clOptionsDescriptor = createCommandLineOptions(); final CLArgsParser parser = new CLArgsParser( args, clOptionsDescriptor ); if( null != parser.getErrorString() ) { System.err.println( "Error: " + parser.getErrorString() ); return; } final List clOptions = parser.getArguments(); final int size = clOptions.size(); boolean debugLog = false; // parse options for( int i = 0; i < size; i++ ) { final CLOption option = (CLOption)clOptions.get( i ); switch( option.getId() ) { case 0: System.err.println( "Error: Unknown argument" + option.getArgument() ); //fall threw case HELP_OPT: usage(); return; case DEBUG_LOG_OPT: debugLog = true; break; case LOG_FILE_OPT: m_logFile = option.getArgument(); break; case APPS_PATH_OPT: m_appsPath = option.getArgument(); break; } } if( !debugLog ) LogKit.setGlobalPriority( Priority.DEBUG ); } protected CLOptionDescriptor[] createCommandLineOptions() { //TODO: localise final CLOptionDescriptor options[] = new CLOptionDescriptor[ 4 ]; options[0] = new CLOptionDescriptor( "help", CLOptionDescriptor.ARGUMENT_DISALLOWED, HELP_OPT, "display this help" ); options[1] = new CLOptionDescriptor( "log-file", CLOptionDescriptor.ARGUMENT_REQUIRED, LOG_FILE_OPT, "the name of log file." ); options[2] = new CLOptionDescriptor( "apps-path", CLOptionDescriptor.ARGUMENT_REQUIRED, APPS_PATH_OPT, "the path to apps/ directory that contains .sars" ); options[3] = new CLOptionDescriptor( "debug-init", CLOptionDescriptor.ARGUMENT_DISALLOWED, DEBUG_LOG_OPT, "use this option to specify enable debug " + "initialisation logs." ); return options; } protected void usage(List commandLineOptions) { System.out.println( "java " + getClass().getName() + " [options]" ); System.out.println( "\tAvailable options:"); System.out.println( CLUtil.describeOptions( commandLineOptions ) ); } private void createEmbeddor() throws ConfigurationException { try { Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); this.embeddor = (Embeddor)Class.forName( this.embeddorClass ).newInstance(); } catch( final Exception e ) { throw new ConfigurationException( "Failed to create Embeddor of class " + this.embeddorClass, e ); } } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/applications/Application.java Index: Application.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.phoenix.applications; import org.apache.framework.lifecycle.Disposable; import org.apache.framework.lifecycle.Initializable; import org.apache.framework.lifecycle.Startable; import org.apache.framework.lifecycle.Stoppable; import org.apache.avalon.camelot.Container; /** * The Application is a self-contained component that performs a specific * function. * * Example ServerApplications may be a Mail Server, File Server, Directory Server etc. * Example JesktopApplications may be a Spreadsheet program, browser, mail client * Example WebApplications may be a particular website or application within a website * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface Application extends Initializable, Startable, Stoppable, Disposable, Container { } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/applications/ApplicationException.java Index: ApplicationException.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.phoenix.applications; import org.apache.framework.CascadingException; /** * The ApplicationException is used to indicate problems with applications. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class ApplicationException extends CascadingException { public ApplicationException( final String message ) { this( message, null ); } public ApplicationException( final String message, final Throwable throwable ) { super( message, throwable ); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/applications/ServerApplication.java Index: ServerApplication.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.phoenix.applications; import org.apache.framework.context.Contextualizable; import org.apache.framework.configuration.Configurable; /** * The ServerApplication is a self-contained server component that performs a specific * user function. * * Example ServerApplications may be a Mail Server, File Server, Directory Server etc. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface ServerApplication extends Application, Contextualizable, Configurable { } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/core/Block.java Index: Block.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.phoenix.core; import org.apache.framework.component.Component; /** * The main interface to implement for building servers using Avalon patterns. * * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> */ public interface Block extends Component { } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/core/BlockContext.java Index: BlockContext.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.phoenix.core; import java.io.File; import org.apache.framework.context.Context; import org.apache.avalon.thread.ThreadPool; import org.apache.log.Logger; /** * Context via which Blocks communicate with container. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface BlockContext extends Context { String APP_NAME = "app.name"; String APP_HOME_DIR = "app.home"; String NAME = "block.name"; /** * Base directory of .sar application. * * @return the base directory */ File getBaseDirectory(); /** * Retrieve name of block. * * @return the name of block */ String getName(); /** * Retrieve thread pool by category. * ThreadPools are given names so that you can manage different thread * count to different components. * * @param category the category * @return the ThreadManager */ ThreadPool getThreadPool( String category ); /** * Retrieve default thread pool. * Equivelent to getThreadPool( "default" ); * * @return the default ThreadPool */ ThreadPool getDefaultThreadPool(); /** * Retrieve logger coresponding to root category of application. * * @return the base logger */ Logger getBaseLogger(); } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/core/Embeddor.java Index: Embeddor.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.phoenix.core; import java.lang.Runnable; import java.lang.UnsupportedOperationException; import org.apache.framework.context.Contextualizable; import org.apache.framework.configuration.Configurable; import org.apache.framework.lifecycle.Initializable; import org.apache.framework.lifecycle.Disposable; /** * * @author <a href="[EMAIL PROTECTED]">Leo Simons</a> */ public interface Embeddor extends Contextualizable, Configurable, Initializable, Runnable, Disposable { public void restart() throws UnsupportedOperationException; } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/core/Kernel.java Index: Kernel.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.phoenix.core; import org.apache.avalon.camelot.ContainerException; import org.apache.phoenix.applications.Application; /** * The Kernel is the core of any system. * The kernel is responsible for orchestrating low level services * such as loading, configuring and destroying applications. It also * gives access to basic facilities specific to that particular kernel. * A ServerKernel may offer scheduling, naming, security, classloading etc. * A JesktopKernel may offer inter-application drag-n-drop support. * A VEKernel may offer inter-VE transport for Avatars. * * Note that no facilities are available until after the Kernel has been initialized. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface Kernel extends Application, Runnable // and thus extends Initializable, Startable, Stoppable, Disposable, Container, Component { /** * Retrieve Application from container. * The Application that is returned must be initialized * and prepared for manipulation. * * @param name the name of application * @return the application * @exception ContainerException if an error occurs */ Application getApplication( String name ) throws ContainerException; } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/core/ServerKernel.java Index: ServerKernel.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.phoenix.core; import org.apache.framework.logger.Loggable; import org.apache.framework.context.Contextualizable; /** * The ServerKernel is the core of the Phoenix system. * The kernel is responsible for orchestrating low level services * such as loading, configuring and destroying blocks. It also * gives access to basic facilities such as scheduling sub-systems, * protected execution contexts, naming and directory services etc. * * Note that no facilities are available until after the Kernel has been * contextualized, configured and initialized. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface ServerKernel extends Loggable, Kernel, Contextualizable // and thus extends Application, Runnable, Initializable, Startable, // Stoppable, Disposable, Container, Component { } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/PhoenixEmbeddor.java Index: PhoenixEmbeddor.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.phoenix.engine; import javax.management.MBeanServer; import java.io.File; import org.apache.framework.configuration.Configurable; import org.apache.framework.context.Contextualizable; import org.apache.framework.container.Container; import org.apache.framework.component.Composer; import org.apache.framework.logger.Loggable; import org.apache.framework.container.Deployer; import org.apache.framework.lifecycle.Suspendable; import org.apache.framework.lifecycle.Resumable; import org.apache.framework.context.Context; import org.apache.framework.container.Entry; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.avalon.camelot.CamelotUtil; import org.apache.avalon.atlantis.Kernel; import org.apache.avalon.context.DefaultContext; import org.apache.avalon.component.DefaultComponentManager; import org.apache.avalon.configuration.DefaultConfigurationBuilder; import org.apache.phoenix.engine.facilities.Manager; import org.apache.log.format.AvalonLogFormatter; import org.apache.log.output.FileOutputLogTarget; import org.apache.log.Logger; import org.apache.log.LogKit; import org.apache.log.Priority; import org.apache.log.LogTarget; /** * * @author <a href="[EMAIL PROTECTED]">Leo Simons</a> * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> */ public class DefaultEmbeddor implements Embeddor { private Context context; private Logger logger; private Deployer deployer; private DefaultContext deployerContext; private Manager manager; private MBeanServer mBeanServer; private DefaultContext managerContext; private Kernel kernel; private Thread kernelThread; private DefaultContext kernelContext; private Configuration kernelConfiguration; private boolean kernelSupportsSuspend = false; // monitor these for status changes private boolean shutdown = false; private boolean restart = false; private boolean suspend = false; private boolean recontextualized = false; private boolean reconfigured = false; ///////////////////////// /// LIFECYCLE METHODS /// ///////////////////////// /** * Make sure to provide all the neccessary information through * this context. All information it needs consists of strings. * These are also indexed using strings. Neccessary are: * <ul> * <li><b>kernel-class</b>, the classname of the * org.apache.phoenix.core.Kernel to be used.</li> * <li><b>deployer-class</b>, the classname of the * org.apache.avalon.camelot.Deployer to be used.</li> * <li><b>mBeanServer-class</b>, the classname of the * javax.management.MBeanServer to be used.</li> * <li><b>kernel-configuration-source</b>, the location * of the configuration file to be used for configuring the * kernel.</li> * <li><b>log-destination</b>, the file to save log * messages in. If omitted, no logs are written.</li> * <li>TODO: <b>facilities-directory</b>, the directory in * which the facilities you wish to load into the kernel * are stored (in .far format).<br /> * When ommited, the default facilities are used.</li> * <li><b>applications-directory</b>, the directory in which * the applications to be loaded by the kernel are stored * (in .sar format).<br /> * When ommited, no applications are loaded.</li> * </ul> */ public void contextualize( Context context ) { this.context = context; } /** * Currently unused, but Embeddor extends it so call anyway * using a dummy configuration. */ void configure( Configuration configuration ) throws ConfigurationException; { // TODO } /** * Creates the core handlers - logger, deployer, Manager and * Kernel. Note that these are not set up properly until you have * called the <code>run()</code> method. */ public void init() throws Exception { this.createLogger(); try { this.createDeployer(); } catch( Exception e ) { logger.fatalError("Unable to create deployer!", e); throw new Exception(e); } try { this.createManager(); } catch( Exception e ) { logger.fatalError("Unable to create manager!", e); throw new Exception(e); } try { this.createKernel(); } catch( Exception e ) { logger.fatalError("Unable to create kernel!", e); throw new Exception(e); } } /** * This is the main method of the embeddor. It sets up the core * components, and then deploys the <code>Facilities</code>. These * are registered with the Kernel and the Manager. The same * happens for the <code>Applications</code>. * Now, the Kernel is taken through its lifecycle. When it is * finished, as well as all the applications running in it, it * is shut down, after which the PhoenixEmbeddor is as well. */ public void run() { this.setupLogger(); try { this.setupDeployer(); } catch( Exception e ) { logger.fatalError("Unable to setup deployer!", e); System.exit( 1 ); } try { this.setupManager(); } catch( Exception e ) { logger.fatalError("Unable to setup manager!", e); System.exit( 1 ); } try { this.setupKernel(); } catch( Exception e ) { logger.fatalError("Unable to setup kernel!", e); System.exit( 1 ); } try { kernel.start(); while( !this.shutdown ) { while( !this.restart && !this.suspend ) { kernel.run(); try { synchronized( this ) { wait(); } } catch (InterruptedException e) {} } if( this.restart ) { handleRestart(); } else if( this.suspend ) { handleSuspend(); } } handleDispose(); } catch ( Exception e ) { // whoops! this.logger.fatalError("There was a fatal error while running phoenix.", e ); System.exit( 1 ); } } /** * This stops and then restarts the Embeddor, * re-creating the logger, deployer, Manager * and Kernel in the process. */ public void restart() { this.restart = true; } /** * Shut down the Embeddor together with the * Logger, Deployer, Manager and Kernel. */ public void dispose() { this.shutdown = true; } /** * Suspend both the Embeddor and its Manager. * If the Kernel does not support suspend, * this shuts down the Kernel and all * Applications running in it. This is not * recommended! */ public void suspend() { this.suspend = true; } /** * Resume both the Embeddor and its Manager. * If the Kernel does not support suspend, it * has to be re-created and re-setup. This * happens now. */ public void resume() { try { if( this.kernelSupportsSuspend ) { if( kernel instanceof Resumable ) { manager.resume(); ((Resumable)kernel).resume(); this.suspend = false; synchronized( this ) { notifyAll(); } } else { // it's stupid if this happens // but let's handle it anyway... kernel.stop(); kernel.dispose(); kernel = null; this.createKernel(); this.setupKernel(); manager.resume(); kernel.start(); this.suspend = false; synchronized( this ) { notifyAll(); } } } else { this.createKernel(); this.setupKernel(); manager.resume(); kernel.start(); this.suspend = false; synchronized( this ) { notifyAll(); } } } catch( Exception e ) { // this is bad... logger.fatalError( "A fatal error occured while resuming. Phoenix will exit.", e ); System.exit( 1 ); } } ////////////////////// /// HELPER METHODS /// ////////////////////// private void createLogger() throws ConfigurationException { try { final FileOutputLogTarget logTarget = new FileOutputLogTarget( (String)this.context.get( "log-destination" ) ); final AvalonLogFormatter formatter = new AvalonLogFormatter(); formatter.setFormat( "%{time} [%7.7{priority}] <<%{category}>> " + "(%{context}): %{message}\\n%{throwable}" ); logTarget.setFormatter( formatter ); LogKit.addLogTarget( (String)this.context.get( "log-destination" ), logTarget ); this.logger = LogKit.createLogger( LogKit.createCategory( "Phoenix", Priority.DEBUG ), new LogTarget[] { logTarget } ); this.logger.info( "Loader started" ); } catch( final Exception e ) { throw new ConfigurationException( "Failed to create Logger", e ); } } private void setupLogger() {} private void createDeployer() throws ConfigurationException { try { Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); this.deployer = (Deployer)Class.forName( (String)this.context.get( "deployer-class" ) ).newInstance(); this.deployerContext = new DefaultContext(); } catch( final Exception e ) { throw new ConfigurationException( "Failed to create Deployer of class " + (String)this.context.get( "deployer-class" ), e ); } } private void setupDeployer() throws Exception { if( this.deployer instanceof Loggable ) { ((Loggable)this.deployer).setLogger( this.logger ); } if( this.deployer instanceof Contextualizable ) { ((Contextualizable)this.deployer).contextualize( (Context)this.deployerContext ); } if( this.deployer instanceof Composer ) { final DefaultComponentManager componentManager = new DefaultComponentManager(); componentManager.put( "org.apache.avalon.camelot.Container", (Container)this.kernel ); ((Composer)this.deployer).compose( componentManager ); } final File directory = new File( (String)this.context.get( "default-apps-location" ) ); CamelotUtil.deployFromDirectory( deployer, directory, ".sar" ); // TODO: load facilities from .fars // final File directory2 = new File( (String)this.context.get( "default-facilities-location" ) ); // CamelotUtil.deployFromDirectory( deployer, directory2, ".far" ); } private void createManager() throws ConfigurationException { try { Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); this.mBeanServer = (MBeanServer)Class.forName( (String)this.context.get( "mBeanServer-class" ) ).newInstance(); this.managerContext = new DefaultContext(); } catch( final Exception e ) { throw new ConfigurationException( "Failed to create MBean Server of class " + (String)this.context.get( "mBeanServer-class" ), e ); } } private void setupManager() { this.manager = new Manager( this.mBeanServer ); if( this.manager instanceof Loggable ) { ((Loggable)this.manager).setLogger( this.logger ); } if( this.manager instanceof Contextualizable ) { this.managerContext.put( "org.apache.framework.container.Deployer", this.deployer ); /* add references to default facilities so they will be loaded. TODO: put the facilities in .sars, make the deployer load those and remove this. */ this.managerContext.put( "org.apache.avalon.atlantis.Facility.ComponentBuilder", "org.apache.phoenix.engine.facilities.DefaultComponentBuilder" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.ComponentManager", "org.apache.phoenix.engine.facilities.DefaultComponentManager" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.ConfigurationRepository", "org.apache.phoenix.engine.facilities.DefaultConfigurationRepository" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.ContextBuilder", "org.apache.phoenix.engine.facilities.DefaultContextBuilder" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.LoggerBuilder", "org.apache.phoenix.engine.facilities.DefaultLoggerBuilder" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.LogManager", "org.apache.phoenix.engine.facilities.DefaultLogManager" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.DefaultPolicy", "org.apache.phoenix.engine.facilities.DefaultPolicy" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.ThreadManager", "org.apache.phoenix.engine.facilities.DefaultThreadManager" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.SarBlockFactory", "org.apache.phoenix.engine.facilities.SarBlockFactory" ); this.managerContext.put( "org.apache.avalon.atlantis.Facility.SarClassLoader", "org.apache.phoenix.engine.facilities.SarClassLoader" ); ((Contextualizable)this.manager).contextualize( (Context)this.managerContext ); } /* TODO add DynamicMBeans for the default kernel services here */ } private void createKernel() throws ConfigurationException { try { Thread.currentThread().setContextClassLoader( getClass().getClassLoader() ); this.kernel = (Kernel)Class.forName( (String)this.context.get( "kernel-class" ) ).newInstance(); this.kernelContext = new DefaultContext(); } catch( final Exception e ) { throw new ConfigurationException( "Failed to create Kernel of class " + (String)this.context.get( "kernel-class" ), e ); } } private void setupKernel() { if( this.kernel instanceof Loggable ) { ((Loggable)this.kernel).setLogger( this.logger ); } if( this.kernel instanceof Contextualizable ) { this.kernelContext.put( "org.apache.phoenix.facilities.Manager", this.manager ); ((Contextualizable)this.kernel).contextualize( (Context)this.kernelContext ); } if( this.kernel instanceof Configurable ) { try { this.kernelConfiguration = (new DefaultConfigurationBuilder()).build( (String)this.context.get( "kernel-configuration-source" ) ); ((Configurable)this.kernel).configure( this.kernelConfiguration ); } catch ( Exception se ) { // it's okay; we don't use this yet anyway... } } if( this.kernel instanceof Suspendable ) { this.kernelSupportsSuspend = true; } try { this.kernel.init(); } catch ( Exception e ) { this.logger.log( Priority.FATAL_ERROR, "There was a fatal error; phoenix could not be started", e ); System.exit( 1 ); } } private void handleRestart() { this.restart = false; kernel.stop(); kernel.dispose(); manager.stop(); manager.dispose(); logger = null; kernel = null; manager = null; mBeanServer = null; deployer = null; System.gc(); // make sure resources are released try { this.init(); this.setupLogger(); this.setupDeployer(); this.setupManager(); this.setupKernel(); } catch( Exception e ) { // this is bad... logger.fatalError( "A fatal error occured while restarting. Phoenix will exit.", e ); System.exit( 1 ); } kernel.start(); } private void handleSuspend() { //this.suspend = false; if( this.kernelSupportsSuspend ) { ((Suspendable)kernel).suspend(); } else { // the kernel does not support suspend, // thus, we must destroy and then // re-create it. kernel.stop(); kernel.dispose(); kernel = null; System.gc(); // make sure resources are released } // wait for resume try { synchronized( this ) { wait(); } } catch (InterruptedException e) {} } private void handleDispose() { kernel.stop(); kernel.dispose(); manager.stop(); manager.dispose(); kernel = null; manager = null; mBeanServer = null; deployer = null; System.gc(); // make sure resources are released } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/PhoenixKernel.java Index: PhoenixKernel.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.phoenix.engine; import org.apache.phoenix.applications.Application; import org.apache.framework.container.Entry; /** * This is the DefaultServerKernel for phoenix. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultServerKernel { public final static String BANNER = Constants.SOFTWARE + " " + Constants.VERSION; public DefaultServerKernel() { m_entryClass = ServerApplicationEntry.class; m_applicationClass = ServerApplication.class; } /** * Prepare an application before it is initialized. * Overide to provide functionality. * Usually used to setLogger(), contextualize, compose, configure. * * @param name the name of application * @param entry the application entry * @param application the application instance * @exception Exception if an error occurs */ protected void prepareApplication( final String name, final Entry entry, final Application application ) throws Exception { final ServerApplicationEntry saEntry = (ServerApplicationEntry)entry; final ServerApplication saApplication = (ServerApplication)application; setupLogger( saApplication, LogKit.getLoggerFor( name ) ); saApplication.contextualize( saEntry.getContext() ); if( saApplication instanceof Composer ) { ((Composer)saApplication).compose( saEntry.getComponentManager() ); } saApplication.configure( saEntry.getConfiguration() ); } protected void postAdd( final String name, final Entry entry ) { } public void init() throws Exception { System.out.println(); System.out.println( BANNER ); super.init(); } protected Application newApplication( final String name, final Entry entry ) throws Exception { //It is here where you could return new EASServerApplication() //if you wanted to host multiple different types of apps return new DefaultServerApplication(); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/applications/DefaultServerApplication.java Index: DefaultServerApplication.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.phoenix.engine; import java.security.Policy; import java.util.HashMap; import java.util.Iterator; import org.apache.framework.component.Component; import org.apache.framework.component.ComponentManager; import org.apache.framework.component.ComponentException; import org.apache.framework.component.Composer; import org.apache.framework.context.Context; import org.apache.framework.context.Contextualizable; import org.apache.avalon.component.DefaultComponentManager; import org.apache.avalon.context.DefaultContext; import org.apache.framework.lifecycle.Initializable; import org.apache.avalon.atlantis.ApplicationException; import org.apache.avalon.camelot.AbstractContainer; import org.apache.avalon.camelot.pipeline.AvalonState; import org.apache.framework.container.ContainerException; import org.apache.framework.container.Entry; import org.apache.framework.container.Factory; import org.apache.avalon.camelot.pipeline.ComponentBuilder; import org.apache.avalon.camelot.pipeline.ComponentManagerBuilder; import org.apache.avalon.camelot.pipeline.ConfigurationRepository; import org.apache.avalon.camelot.pipeline.ContextBuilder; import org.apache.avalon.camelot.pipeline.LoggerBuilder; import org.apache.avalon.camelot.pipeline.ShutdownPipeline; import org.apache.avalon.camelot.pipeline.StartupPipeline; import org.apache.framework.configuration.Configurable; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.framework.thread.ThreadManager; import org.apache.phoenix.engine.blocks.BlockDAG; import org.apache.phoenix.engine.blocks.BlockEntry; import org.apache.phoenix.engine.blocks.RoleEntry; import org.apache.phoenix.engine.facilities.DefaultComponentBuilder; import org.apache.phoenix.engine.facilities.DefaultComponentManagerBuilder; import org.apache.phoenix.engine.facilities.DefaultConfigurationRepository; import org.apache.phoenix.engine.facilities.DefaultContextBuilder; import org.apache.phoenix.engine.facilities.DefaultLogManager; import org.apache.phoenix.engine.facilities.DefaultLoggerBuilder; import org.apache.phoenix.engine.facilities.DefaultPolicy; import org.apache.phoenix.engine.facilities.DefaultThreadManager; import org.apache.phoenix.engine.facilities.SarClassLoader; import org.apache.phoenix.engine.phases.DefaultPhase; import org.apache.phoenix.engine.phases.Phase; import org.apache.phoenix.engine.phases.Traversal; import org.apache.phoenix.metainfo.DependencyInfo; /** * This is the basic container of blocks. A server application * represents an aggregation of blocks that act together to form * an application. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> */ public class DefaultServerApplication extends AbstractContainer implements ServerApplication { protected HashMap m_phases = new HashMap(); protected BlockDAG m_dag = new BlockDAG(); //the following are used for setting up facilities protected Context m_context; protected Configuration m_configuration; protected ComponentManager m_componentManager; protected DefaultLogManager m_logManager; protected ThreadManager m_threadManager; protected DefaultPolicy m_policy; protected SarClassLoader m_classLoader; //these are the facilities (internal components) of ServerApplication protected ComponentBuilder m_componentBuilder; protected LoggerBuilder m_loggerBuilder; protected ContextBuilder m_contextBuilder; protected ComponentManagerBuilder m_componentManagerBuilder; protected ConfigurationRepository m_configurationRepository; public DefaultServerApplication() { m_entryClass = BlockEntry.class; } public void contextualize( final Context context ) { //save it to contextualize policy/logManager/etc final DefaultContext newContext = new DefaultContext( context ); newContext.put( "name", context.get( SarContextResources.APP_NAME ) ); newContext.put( "directory", context.get( SarContextResources.APP_HOME_DIR ) ); m_context = newContext; } public void configure( final Configuration configuration ) throws ConfigurationException { m_configuration = configuration; } public void init() throws Exception { createComponents(); //setup the component manager m_componentManager = createComponentManager(); setupComponents(); initPhases(); setupPhases(); } protected void initPhases() throws ApplicationException { Phase phase = null; phase = new DefaultPhase( Phase.FORWARD, new StartupPipeline(), AvalonState.BASE, AvalonState.RUNNING ); m_phases.put( "startup", phase ); phase = new DefaultPhase( Phase.REVERSE, new ShutdownPipeline(), AvalonState.RUNNING, AvalonState.DISPOSED ); m_phases.put( "shutdown", phase ); } protected void setupPhases() throws Exception { final Iterator phases = m_phases.values().iterator(); while( phases.hasNext() ) { final Phase phase = (Phase)phases.next(); setupComponent( phase ); } } public void start() throws Exception { // load blocks try { getLogger().info( "Number of blocks to load: " + m_entries.size() ); final Phase phase = (Phase)m_phases.get( "startup" ); runPhase( phase ); } catch( final ApplicationException ae ) { getLogger().warn( "Error loading blocks: " + ae.getMessage(), ae ); throw ae; } } public void stop() throws Exception { } public void dispose() throws Exception { getLogger().info( "Number of blocks to unload: " + m_entries.size() ); final Phase phase = (Phase)m_phases.get( "shutdown" ); runPhase( phase ); m_entries.clear(); } /** * Create all required components. * * @exception Exception if an error occurs */ protected void createComponents() throws Exception { //TODO: Refactor logManager so it does more useful managing // possibly including setting up rolling etc m_logManager = new DefaultLogManager(); m_contextBuilder = new DefaultContextBuilder(); m_componentManagerBuilder = new DefaultComponentManagerBuilder(); m_configurationRepository = new DefaultConfigurationRepository(); m_loggerBuilder = new DefaultLoggerBuilder(); m_componentBuilder = new DefaultComponentBuilder(); m_classLoader = new SarClassLoader(); m_threadManager = new DefaultThreadManager(); m_policy = new DefaultPolicy(); } /** * Setup all the components. (ir run all required lifecycle methods). * * @exception Exception if an error occurs */ protected void setupComponents() throws Exception { Configuration configuration = null; configuration = m_configuration.getChild( "logs" ); setupComponent( m_logManager, "<core>.logs", configuration ); configuration = m_configuration.getChild( "threads" ); setupComponent( m_threadManager, "<core>.threads", configuration ); configuration = m_configuration.getChild( "policy" ); setupComponent( (Component)m_policy, "<policy>", configuration ); setupComponent( m_classLoader ); setupComponent( m_componentBuilder ); setupComponent( m_loggerBuilder ); setupComponent( m_contextBuilder ); setupComponent( m_componentManagerBuilder ); setupComponent( m_configurationRepository ); setupComponent( m_dag, "<core>.dag", null ); } protected void setupComponent( final Component object ) throws Exception { setupComponent( object, null, null ); } protected void setupComponent( final Component object, final String logName, final Configuration configuration ) throws Exception { setupLogger( object, logName ); if( object instanceof Contextualizable ) { ((Contextualizable)object).contextualize( m_context ); } if( object instanceof Composer ) { ((Composer)object).compose( m_componentManager ); } if( object instanceof Configurable ) { ((Configurable)object).configure( configuration ); } if( object instanceof Initializable ) { ((Initializable)object).init(); } } protected void runPhase( final Phase phase ) throws Exception { if( Phase.FORWARD == phase.getTraversal() ) { final Iterator entries = list(); while( entries.hasNext() ) { final String name = (String)entries.next(); m_dag.walkGraph( name, phase ); } } else if( Phase.REVERSE == phase.getTraversal() ) { //TODO: final Iterator entries = list(); while( entries.hasNext() ) { final String name = (String)entries.next(); //m_dag.reverseWalkGraph( name, phase ); } } else { //TODO: Does this make sense ???? final Iterator entries = list(); while( entries.hasNext() ) { final String name = (String)entries.next(); final BlockEntry entry = (BlockEntry)getEntry( name ); phase.visitBlock( name, entry ); } } } /** * This method is called before entry is added to give chance for * sub-class to veto addition. * * @param name the name of entry * @param entry the entry * @exception ContainerException to stop removal of entry */ protected void preAdd( final String name, final Entry entry ) throws ContainerException { final BlockEntry blockEntry = (BlockEntry)entry; verifyDependenciesMap( name, blockEntry ); } /** * Retrieve a list of RoleEntry objects that were specified * in configuration file and verify they were expected based * on BlockInfo file. Also verify that all entries specified * in BlockInfo file have been provided. * * @param entry the BlockEntry describing block * @return the list of RoleEntry objects */ protected void verifyDependenciesMap( final String name, final BlockEntry entry ) throws ContainerException { //Make sure all role entries specified in config file are valid final RoleEntry[] roleEntrys = entry.getRoleEntrys(); for( int i = 0; i < roleEntrys.length; i++ ) { final String role = roleEntrys[ i ].getRole(); final DependencyInfo info = entry.getBlockInfo().getDependency( role ); if( null == info ) { final String message = "Unknown dependency " + roleEntrys[ i ].getName() + " with role " + role + " declared for Block " + name; getLogger().warn( message ); throw new ContainerException( message ); } } //Make sure all dependencies in BlockInfo file are satisfied final DependencyInfo[] dependencies = entry.getBlockInfo().getDependencies(); for( int i = 0; i < dependencies.length; i++ ) { final RoleEntry roleEntry = entry.getRoleEntry( dependencies[ i ].getRole() ); if( null == roleEntry ) { final String message = "Dependency " + dependencies[ i ].getRole() + " not provided in configuration for Block " + name; getLogger().warn( message ); throw new ContainerException( message ); } } } /** * Create a ComponentManager containing all components in engine. * * @return the ComponentManager */ protected ComponentManager createComponentManager() { final DefaultComponentManager componentManager = new DefaultComponentManager(); componentManager.put( "org.apache.phoenix.engine.ServerApplication", this ); componentManager.put( "java.security.Policy", m_policy ); componentManager.put( "java.lang.ClassLoader", m_classLoader ); componentManager.put( "NOT_DONE_YET", m_logManager ); componentManager.put( "org.apache.avalon.util.thread.ThreadManager", m_threadManager ); componentManager.put( "org.apache.avalon.camelot.pipeline.ContextBuilder", m_contextBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.LoggerBuilder", m_loggerBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.ComponentBuilder", m_componentBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.ComponentManagerBuilder", m_componentManagerBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.ConfigurationRepository", m_configurationRepository ); return componentManager; } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/applications/ServerApplicationFactory.java Index: ServerApplicationFactory.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.phoenix.engine; import java.security.Policy; import java.util.HashMap; import java.util.Iterator; import org.apache.framework.component.Component; import org.apache.framework.component.ComponentManager; import org.apache.framework.component.ComponentException; import org.apache.framework.component.Composer; import org.apache.framework.context.Context; import org.apache.framework.context.Contextualizable; import org.apache.avalon.component.DefaultComponentManager; import org.apache.avalon.context.DefaultContext; import org.apache.framework.lifecycle.Initializable; import org.apache.avalon.atlantis.ApplicationException; import org.apache.avalon.camelot.AbstractContainer; import org.apache.avalon.camelot.pipeline.AvalonState; import org.apache.framework.container.ContainerException; import org.apache.framework.container.Entry; import org.apache.framework.container.Factory; import org.apache.avalon.camelot.pipeline.ComponentBuilder; import org.apache.avalon.camelot.pipeline.ComponentManagerBuilder; import org.apache.avalon.camelot.pipeline.ConfigurationRepository; import org.apache.avalon.camelot.pipeline.ContextBuilder; import org.apache.avalon.camelot.pipeline.LoggerBuilder; import org.apache.avalon.camelot.pipeline.ShutdownPipeline; import org.apache.avalon.camelot.pipeline.StartupPipeline; import org.apache.framework.configuration.Configurable; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.framework.thread.ThreadManager; import org.apache.phoenix.engine.blocks.BlockDAG; import org.apache.phoenix.engine.blocks.BlockEntry; import org.apache.phoenix.engine.blocks.RoleEntry; import org.apache.phoenix.engine.facilities.DefaultComponentBuilder; import org.apache.phoenix.engine.facilities.DefaultComponentManagerBuilder; import org.apache.phoenix.engine.facilities.DefaultConfigurationRepository; import org.apache.phoenix.engine.facilities.DefaultContextBuilder; import org.apache.phoenix.engine.facilities.DefaultLogManager; import org.apache.phoenix.engine.facilities.DefaultLoggerBuilder; import org.apache.phoenix.engine.facilities.DefaultPolicy; import org.apache.phoenix.engine.facilities.DefaultThreadManager; import org.apache.phoenix.engine.facilities.SarClassLoader; import org.apache.phoenix.engine.phases.DefaultPhase; import org.apache.phoenix.engine.phases.Phase; import org.apache.phoenix.engine.phases.Traversal; import org.apache.phoenix.metainfo.DependencyInfo; /** * This is the basic container of blocks. A server application * represents an aggregation of blocks that act together to form * an application. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> */ public class DefaultServerApplication extends AbstractContainer implements ServerApplication { protected HashMap m_phases = new HashMap(); protected BlockDAG m_dag = new BlockDAG(); //the following are used for setting up facilities protected Context m_context; protected Configuration m_configuration; protected ComponentManager m_componentManager; protected DefaultLogManager m_logManager; protected ThreadManager m_threadManager; protected DefaultPolicy m_policy; protected SarClassLoader m_classLoader; //these are the facilities (internal components) of ServerApplication protected ComponentBuilder m_componentBuilder; protected LoggerBuilder m_loggerBuilder; protected ContextBuilder m_contextBuilder; protected ComponentManagerBuilder m_componentManagerBuilder; protected ConfigurationRepository m_configurationRepository; public DefaultServerApplication() { m_entryClass = BlockEntry.class; } public void contextualize( final Context context ) { //save it to contextualize policy/logManager/etc final DefaultContext newContext = new DefaultContext( context ); newContext.put( "name", context.get( SarContextResources.APP_NAME ) ); newContext.put( "directory", context.get( SarContextResources.APP_HOME_DIR ) ); m_context = newContext; } public void configure( final Configuration configuration ) throws ConfigurationException { m_configuration = configuration; } public void init() throws Exception { createComponents(); //setup the component manager m_componentManager = createComponentManager(); setupComponents(); initPhases(); setupPhases(); } protected void initPhases() throws ApplicationException { Phase phase = null; phase = new DefaultPhase( Phase.FORWARD, new StartupPipeline(), AvalonState.BASE, AvalonState.RUNNING ); m_phases.put( "startup", phase ); phase = new DefaultPhase( Phase.REVERSE, new ShutdownPipeline(), AvalonState.RUNNING, AvalonState.DISPOSED ); m_phases.put( "shutdown", phase ); } protected void setupPhases() throws Exception { final Iterator phases = m_phases.values().iterator(); while( phases.hasNext() ) { final Phase phase = (Phase)phases.next(); setupComponent( phase ); } } public void start() throws Exception { // load blocks try { getLogger().info( "Number of blocks to load: " + m_entries.size() ); final Phase phase = (Phase)m_phases.get( "startup" ); runPhase( phase ); } catch( final ApplicationException ae ) { getLogger().warn( "Error loading blocks: " + ae.getMessage(), ae ); throw ae; } } public void stop() throws Exception { } public void dispose() throws Exception { getLogger().info( "Number of blocks to unload: " + m_entries.size() ); final Phase phase = (Phase)m_phases.get( "shutdown" ); runPhase( phase ); m_entries.clear(); } /** * Create all required components. * * @exception Exception if an error occurs */ protected void createComponents() throws Exception { //TODO: Refactor logManager so it does more useful managing // possibly including setting up rolling etc m_logManager = new DefaultLogManager(); m_contextBuilder = new DefaultContextBuilder(); m_componentManagerBuilder = new DefaultComponentManagerBuilder(); m_configurationRepository = new DefaultConfigurationRepository(); m_loggerBuilder = new DefaultLoggerBuilder(); m_componentBuilder = new DefaultComponentBuilder(); m_classLoader = new SarClassLoader(); m_threadManager = new DefaultThreadManager(); m_policy = new DefaultPolicy(); } /** * Setup all the components. (ir run all required lifecycle methods). * * @exception Exception if an error occurs */ protected void setupComponents() throws Exception { Configuration configuration = null; configuration = m_configuration.getChild( "logs" ); setupComponent( m_logManager, "<core>.logs", configuration ); configuration = m_configuration.getChild( "threads" ); setupComponent( m_threadManager, "<core>.threads", configuration ); configuration = m_configuration.getChild( "policy" ); setupComponent( (Component)m_policy, "<policy>", configuration ); setupComponent( m_classLoader ); setupComponent( m_componentBuilder ); setupComponent( m_loggerBuilder ); setupComponent( m_contextBuilder ); setupComponent( m_componentManagerBuilder ); setupComponent( m_configurationRepository ); setupComponent( m_dag, "<core>.dag", null ); } protected void setupComponent( final Component object ) throws Exception { setupComponent( object, null, null ); } protected void setupComponent( final Component object, final String logName, final Configuration configuration ) throws Exception { setupLogger( object, logName ); if( object instanceof Contextualizable ) { ((Contextualizable)object).contextualize( m_context ); } if( object instanceof Composer ) { ((Composer)object).compose( m_componentManager ); } if( object instanceof Configurable ) { ((Configurable)object).configure( configuration ); } if( object instanceof Initializable ) { ((Initializable)object).init(); } } protected void runPhase( final Phase phase ) throws Exception { if( Phase.FORWARD == phase.getTraversal() ) { final Iterator entries = list(); while( entries.hasNext() ) { final String name = (String)entries.next(); m_dag.walkGraph( name, phase ); } } else if( Phase.REVERSE == phase.getTraversal() ) { //TODO: final Iterator entries = list(); while( entries.hasNext() ) { final String name = (String)entries.next(); //m_dag.reverseWalkGraph( name, phase ); } } else { //TODO: Does this make sense ???? final Iterator entries = list(); while( entries.hasNext() ) { final String name = (String)entries.next(); final BlockEntry entry = (BlockEntry)getEntry( name ); phase.visitBlock( name, entry ); } } } /** * This method is called before entry is added to give chance for * sub-class to veto addition. * * @param name the name of entry * @param entry the entry * @exception ContainerException to stop removal of entry */ protected void preAdd( final String name, final Entry entry ) throws ContainerException { final BlockEntry blockEntry = (BlockEntry)entry; verifyDependenciesMap( name, blockEntry ); } /** * Retrieve a list of RoleEntry objects that were specified * in configuration file and verify they were expected based * on BlockInfo file. Also verify that all entries specified * in BlockInfo file have been provided. * * @param entry the BlockEntry describing block * @return the list of RoleEntry objects */ protected void verifyDependenciesMap( final String name, final BlockEntry entry ) throws ContainerException { //Make sure all role entries specified in config file are valid final RoleEntry[] roleEntrys = entry.getRoleEntrys(); for( int i = 0; i < roleEntrys.length; i++ ) { final String role = roleEntrys[ i ].getRole(); final DependencyInfo info = entry.getBlockInfo().getDependency( role ); if( null == info ) { final String message = "Unknown dependency " + roleEntrys[ i ].getName() + " with role " + role + " declared for Block " + name; getLogger().warn( message ); throw new ContainerException( message ); } } //Make sure all dependencies in BlockInfo file are satisfied final DependencyInfo[] dependencies = entry.getBlockInfo().getDependencies(); for( int i = 0; i < dependencies.length; i++ ) { final RoleEntry roleEntry = entry.getRoleEntry( dependencies[ i ].getRole() ); if( null == roleEntry ) { final String message = "Dependency " + dependencies[ i ].getRole() + " not provided in configuration for Block " + name; getLogger().warn( message ); throw new ContainerException( message ); } } } /** * Create a ComponentManager containing all components in engine. * * @return the ComponentManager */ protected ComponentManager createComponentManager() { final DefaultComponentManager componentManager = new DefaultComponentManager(); componentManager.put( "org.apache.phoenix.engine.ServerApplication", this ); componentManager.put( "java.security.Policy", m_policy ); componentManager.put( "java.lang.ClassLoader", m_classLoader ); componentManager.put( "NOT_DONE_YET", m_logManager ); componentManager.put( "org.apache.avalon.util.thread.ThreadManager", m_threadManager ); componentManager.put( "org.apache.avalon.camelot.pipeline.ContextBuilder", m_contextBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.LoggerBuilder", m_loggerBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.ComponentBuilder", m_componentBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.ComponentManagerBuilder", m_componentManagerBuilder ); componentManager.put( "org.apache.avalon.camelot.pipeline.ConfigurationRepository", m_configurationRepository ); return componentManager; } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/deployer/DefaultSarDeployer.java Index: DefaultSarDeployer.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.phoenix.engine; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.apache.avalon.ComponentManager; import org.apache.avalon.ComponentManagerException; import org.apache.framework.component.Composer; import org.apache.avalon.configuration.Configuration; import org.apache.avalon.configuration.ConfigurationException; import org.apache.avalon.DefaultComponentManager; import org.apache.avalon.configuration.DefaultConfigurationBuilder; import org.apache.avalon.DefaultContext; import org.apache.avalon.camelot.AbstractCamelotDeployer; import org.apache.avalon.camelot.CamelotUtil; import org.apache.avalon.camelot.ContainerException; import org.apache.avalon.camelot.DefaultLocatorRegistry; import org.apache.avalon.camelot.DefaultRegistry; import org.apache.avalon.camelot.Deployer; import org.apache.avalon.camelot.DeployerUtil; import org.apache.avalon.camelot.DeploymentException; import org.apache.avalon.camelot.Locator; import org.apache.avalon.camelot.LocatorRegistry; import org.apache.avalon.camelot.Registry; import org.apache.avalon.camelot.RegistryException; import org.apache.avalon.util.io.FileUtil; import org.apache.avalon.util.io.IOUtil; import org.apache.phoenix.BlockContext; import org.apache.phoenix.metainfo.BlockInfo; import org.apache.phoenix.engine.blocks.BlockEntry; import org.apache.phoenix.engine.blocks.RoleEntry; import org.apache.phoenix.engine.blocks.DefaultBlockDeployer; /** * This class deploys a .sar file. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultSarDeployer extends AbstractCamelotDeployer { protected File m_deployDirectory; /** * Default constructor. */ public DefaultSarDeployer() { m_deployToContainer = true; m_autoUndeploy = true; m_type = "Sar"; } protected void deployFromFile( final String name, final File file ) throws DeploymentException { if( file.isDirectory() ) { throw new DeploymentException( "Deploying directories is not supported" ); } else { final File destination = getDestinationFor( name, file ); expandTo( file, destination ); deployFromDirectory( file, name, destination ); } } protected void expandTo( final File file, final File directory ) throws DeploymentException { final ZipFile zipFile = DeployerUtil.getZipFileFor( file ); if( !needsExpanding( zipFile, directory ) ) { return; } directory.mkdirs(); final Enumeration entries = zipFile.entries(); while( entries.hasMoreElements() ) { final ZipEntry entry = (ZipEntry)entries.nextElement(); if( entry.isDirectory() ) continue; final String name = entry.getName().replace( '/', File.separatorChar ); if( !shouldExpandEntry( entry.getName() ) ) continue; final File destination = new File( directory, name ); InputStream input = null; OutputStream output = null; try { destination.getParentFile().mkdirs(); output = new FileOutputStream( destination ); input = zipFile.getInputStream( entry ); IOUtil.copy( input, output ); } catch( final IOException ioe ) { throw new DeploymentException( "Error extracting " + name, ioe ); } finally { IOUtil.shutdownStream( input ); IOUtil.shutdownStream( output ); } } } protected boolean shouldExpandEntry( final String name ) { if( name.startsWith( "META-INF" ) ) return false; else return true; } protected boolean needsExpanding( final ZipFile zipFile, final File directory ) { return !directory.exists(); } protected File getDestinationFor( final String location, final File file ) { final String name = FileUtil.removeExtention( FileUtil.removePath( file.getName() ) ); if( null != m_deployDirectory ) { return (new File( m_deployDirectory, name )).getAbsoluteFile(); } else { return (new File( file.getParentFile(), name )).getAbsoluteFile(); } } protected ServerKernel getKernel() throws DeploymentException { if( !(m_container instanceof ServerKernel) ) { throw new DeploymentException( "Can only deploy to a kernel container" ); } else { return (ServerKernel)m_container; } } protected void buildEntry( final String name, final ServerApplicationEntry entry, final File archive, final File directory ) throws DeploymentException { //final File file = new File( directory, "SAR-INF" + File.separator + "sar-inf.xml" ); //setup the ServerApplications context final DefaultContext context = new DefaultContext(); context.put( SarContextResources.APP_ARCHIVE, archive ); context.put( SarContextResources.APP_HOME_DIR, directory ); context.put( SarContextResources.APP_NAME, name ); entry.setContext( context ); //setup the ServerApplications component manager final DefaultComponentManager componentManager = new DefaultComponentManager(); componentManager.put( "org.apache.avalon.camelot.Registry", new DefaultRegistry( BlockInfo.class ) ); componentManager.put( "org.apache.avalon.camelot.LocatorRegistry", new DefaultLocatorRegistry() ); entry.setComponentManager( componentManager ); //setup the ServerApplications configuration manager final File file = new File( directory, "conf" + File.separator + "server.xml" ); final Configuration configuration = getConfigurationFor( file ); entry.setConfiguration( configuration ); } protected void deployFromDirectory( final File archive, final String name, final File directory ) throws DeploymentException { getLogger().info( "deploying from archive (" + archive + ") expanded into directory " + directory ); final ServerApplicationEntry entry = new ServerApplicationEntry(); buildEntry( name, entry, archive, directory ); addEntry( name, entry ); final ServerKernel kernel = getKernel(); ServerApplication serverApplication = null; try { serverApplication = (ServerApplication)kernel.getApplication( name ); } catch( final ContainerException ce ) { throw new DeploymentException( "Error preparingserver application", ce ); } //rework next bit so it grabs deployments from archive final Deployer deployer = getBlockDeployer( entry ); final File blocksDirectory = new File( directory, "blocks" ); CamelotUtil.deployFromDirectory( deployer, blocksDirectory, ".bar" ); final File file = new File( directory, "conf" + File.separator + "assembly.xml" ); try { final Configuration configuration = getConfigurationFor( file ); final Configuration[] blocks = configuration.getChildren( "block" ); handleBlocks( serverApplication, entry, blocks ); } catch( final ComponentManagerException cme ) { throw new DeploymentException( "Error setting up registries", cme ); } catch( final ConfigurationException ce ) { throw new DeploymentException( "Error in assembly.xml", ce ); } } protected Configuration getConfigurationFor( final File file ) throws DeploymentException { try { final FileInputStream input = new FileInputStream( file ); return DeployerUtil.buildConfiguration( input ); } catch( final IOException ioe ) { throw new DeploymentException( "Error reading " + file, ioe ); } } protected Deployer getBlockDeployer( final ServerApplicationEntry entry ) throws DeploymentException { final Deployer deployer = new DefaultBlockDeployer(); setupLogger( deployer ); if( deployer instanceof Composer ) { try { ((Composer)deployer).compose( entry.getComponentManager() ); } catch( final Exception e ) { throw new DeploymentException( "Error composing block deployer", e ); } } return deployer; } protected void handleBlocks( final ServerApplication serverApplication, final ServerApplicationEntry saEntry, final Configuration[] blocks ) throws ComponentManagerException, ConfigurationException, DeploymentException { final ComponentManager componentManager = saEntry.getComponentManager(); final Registry infoRegistry = (Registry)componentManager.lookup( "org.apache.avalon.camelot.Registry" ); final LocatorRegistry locatorRegistry = (LocatorRegistry)componentManager. lookup( "org.apache.avalon.camelot.LocatorRegistry" ); for( int i = 0; i < blocks.length; i++ ) { final Configuration block = blocks[ i ]; final String name = block.getAttribute("name"); final String className = block.getAttribute("class"); BlockInfo info = null; try { info = (BlockInfo)infoRegistry.getInfo( className ); } catch( final RegistryException re ) { throw new DeploymentException( "Failed to aquire BlockInfo for " + className, re ); } Locator locator = null; try { locator = locatorRegistry.getLocator( className ); } catch( final RegistryException re ) { throw new DeploymentException( "Failed to aquire Locator for " + className, re ); } final Configuration[] provides = block.getChildren( "provide" ); final ArrayList roleList = new ArrayList(); for( int j = 0; j < provides.length; j++ ) { final Configuration provide = provides[ j ]; final String requiredName = provide.getAttribute("name"); final String role = provide.getAttribute("role"); roleList.add( new RoleEntry( requiredName, role ) ); } final RoleEntry[] roles = (RoleEntry[]) roleList.toArray( new RoleEntry[ 0 ] ); final BlockEntry entry = new BlockEntry( locator, roles ); entry.setBlockInfo( info ); entry.setConfiguration( block.getChild( "configuration" ) ); try { serverApplication.add( name, entry ); } catch( final ContainerException ce ) { throw new DeploymentException( "Error adding component to container", ce ); } getLogger().debug( "Adding " + m_type + "Entry " + name + " as " + entry ); } } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/deployer/blocks/BlockDAG.java Index: BlockDAG.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.phoenix.engine.blocks; import java.util.Iterator; import org.apache.avalon.logger.AbstractLoggable; import org.apache.framework.component.ComponentManager; import org.apache.framework.component.ComponentException; import org.apache.framework.component.Composer; import org.apache.framework.container.ContainerException; import org.apache.phoenix.Block; import org.apache.phoenix.engine.ServerApplication; import org.apache.phoenix.metainfo.DependencyInfo; import org.apache.phoenix.metainfo.ServiceInfo; /** * This is the dependency graph for blocks. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class BlockDAG extends AbstractLoggable implements Composer { protected ServerApplication m_serverApplication; public void compose( final ComponentManager componentManager ) throws ComponentException { m_serverApplication = (ServerApplication)componentManager. lookup( "org.apache.phoenix.engine.ServerApplication" ); } public void walkGraph( final String root, final BlockVisitor visitor ) throws Exception { visitBlock( root, getBlockEntry( root ), visitor, true ); } public void reverseWalkGraph( final String root, final BlockVisitor visitor ) throws Exception { visitBlock( root, getBlockEntry( root ), visitor, false ); } protected BlockEntry getBlockEntry( final String name ) throws Exception { return (BlockEntry)m_serverApplication.getEntry( name ); //catch( final ContainerException ce ) } /** * Traverse dependencies of specified entry. * * @param name name of BlockEntry * @param entry the BlockEntry */ protected void visitDependencies( final String name, final BlockEntry entry, final BlockVisitor visitor ) throws Exception { getLogger().debug( "Traversing dependencies for " + name ); final DependencyInfo[] infos = entry.getBlockInfo().getDependencies(); for( int i = 0; i < infos.length; i++ ) { final ServiceInfo serviceInfo = infos[ i ].getService(); final String role = infos[ i ].getRole(); getLogger().debug( "Traversing dependency of " + name + " with role " + role + " to provide service " + serviceInfo.getName() ); //roleEntry should NEVER be null as it is checked when //entry is added to container final RoleEntry roleEntry = entry.getRoleEntry( role ); final String dependencyName = roleEntry.getName(); final BlockEntry dependency = getBlockEntry( dependencyName ); visitBlock( dependencyName, dependency, visitor, true ); } } /** * Traverse all reverse dependencies of specified entry. * A reverse dependency are those that dependend on entry. * * @param name name of BlockEntry * @param entry the BlockEntry */ protected void visitReverseDependencies( final String name, final BlockVisitor visitor ) throws Exception { getLogger().debug( "Traversing reverse dependencies for " + name ); final Iterator entries = m_serverApplication.list(); while( entries.hasNext() ) { final String blockName = (String)entries.next(); final BlockEntry entry = getBlockEntry( blockName ); final RoleEntry[] roles = entry.getRoleEntrys(); for( int i = 0; i < roles.length; i++ ) { final String depends = roles[ i ].getName(); if( depends.equals( name ) ) { getLogger().debug( "Attempting to unload block " + blockName + " as it depends on " + depends ); //finally try to traverse block visitBlock( blockName, entry, visitor, false ); } } } } protected void visitBlock( final String name, final BlockEntry entry, final BlockVisitor visitor, final boolean forward ) throws Exception { if( forward ) { visitDependencies( name, entry, visitor ); } else { visitReverseDependencies( name, visitor ); } visitor.visitBlock( name, entry ); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/deployer/blocks/BlockEntry.java Index: BlockEntry.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.phoenix.engine.blocks; import org.apache.avalon.camelot.Entry; import org.apache.framework.container.Locator; import org.apache.avalon.camelot.AvalonState; import org.apache.framework.configuration.Configuration; import org.apache.phoenix.Block; import org.apache.phoenix.metainfo.BlockInfo; /** * This is the structure describing each block before it is loaded. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class BlockEntry extends Entry { protected final Locator m_locator; protected final RoleEntry[] m_roleEntrys; //UGLY HACK should be stored in another server Facility (ie ConfigurationRepository) protected Configuration m_configuration; public BlockEntry( final Locator locator, final RoleEntry[] roleEntrys ) { setState( AvalonState.BASE ); m_locator = locator; m_roleEntrys = roleEntrys; } public Locator getLocator() { return m_locator; } public BlockInfo getBlockInfo() { return (BlockInfo)getInfo(); } public void setBlockInfo( final BlockInfo blockInfo ) { setInfo( blockInfo ); } /** * Get a RoleEntry from entry with a particular role. * * @param role the role of RoleEntry to look for * @return the matching deendency else null */ public RoleEntry getRoleEntry( final String role ) { for( int i = 0; i < m_roleEntrys.length; i++ ) { if( m_roleEntrys[ i ].getRole().equals( role ) ) { return m_roleEntrys[ i ]; } } return null; } public RoleEntry[] getRoleEntrys() { return m_roleEntrys; } public Configuration getConfiguration() { return m_configuration; } public void setConfiguration( final Configuration configuration ) { m_configuration = configuration; } public Block getBlock() { return (Block)getInstance(); } public void setBlock( final Block block ) { setInstance( block ); } public void setInfo( final BlockInfo info ) { //m_info = info; } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/deployer/blocks/BlockVisitor.java Index: BlockVisitor.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.phoenix.engine.blocks; import org.apache.avalon.atlantis.ApplicationException; /** * Visitor interface that objects implement to walk the DAG. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface BlockVisitor { /** * This is called when a block is reached whilst walking the tree. * * @param name the name of block * @param entry the BlockEntry * @exception ApplicationException if walking is to be stopped */ void visitBlock( String name, BlockEntry entry ) throws ApplicationException; } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/deployer/blocks/DefaultBlockContext.java Index: DefaultBlockContext.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.phoenix.engine.blocks; import java.io.File; import org.apache.framework.context.Context; import org.apache.avalon.context.DefaultContext; import org.apache.framework.thread.ThreadManager; import org.apache.framework.thread.ThreadPool; import org.apache.log.Logger; import org.apache.phoenix.BlockContext; /** * Context via which Blocks communicate with container. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultBlockContext extends DefaultContext implements BlockContext { protected ThreadManager m_threadManager; protected Logger m_baseLogger; public DefaultBlockContext( final Logger logger, final ThreadManager threadManager ) { this( logger, threadManager, null ); } public DefaultBlockContext( final Logger logger, final ThreadManager threadManager, final Context context ) { super( context ); m_baseLogger = logger; m_threadManager = threadManager; } /** * Base directory of .sar application. * * @return the base directory */ public File getBaseDirectory() { return (File)get( APP_HOME_DIR ); } /** * Retrieve name of block. * * @return the name of block */ public String getName() { return (String)get( NAME ); } /** * Retrieve thread manager by category. * ThreadManagers are given names so that you can manage different thread * count to different components. * * @param category the category * @return the ThreadManager */ public ThreadPool getThreadPool( final String category ) { return m_threadManager.getThreadPool( category ); } /** * Retrieve the default thread pool. * Equivelent to getThreadPool( "default" ); * @return the ThreadPool */ public ThreadPool getDefaultThreadPool() { return getThreadPool( "default" ); } /** * Retrieve logger coresponding to root category of application. * * @return the base logger */ public Logger getBaseLogger() { return m_baseLogger; } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/deployer/blocks/DefaultBlockDeployer.java Index: DefaultBlockDeployer.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.phoenix.engine.blocks; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Iterator; import java.util.Map; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.zip.ZipFile; import org.apache.avalon.camelot.AbstractZipDeployer; import org.apache.avalon.camelot.DeployerUtil; import org.apache.framework.container.DeploymentException; import org.apache.framework.container.LocatorRegistry; import org.apache.framework.container.Registry; import org.apache.framework.container.RegistryException; import org.apache.aut.io.IOUtil; import org.apache.phoenix.metainfo.BlockInfo; import org.apache.phoenix.metainfo.BlockInfoBuilder; /** * This class deploys a .bar file into a registry. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultBlockDeployer extends AbstractZipDeployer { protected BlockInfoBuilder m_builder; /** * Default constructor. */ public DefaultBlockDeployer() { m_builder = new BlockInfoBuilder(); //Indicate that this deployer should deploy to respective types m_deployToLocatorRegistry = true; m_deployToInfoRegistry = true; m_autoUndeploy = true; m_type = "Block"; } /** * Load resources from jar required to deploy file. * * @param zipFile the zipFile * @param location the location deploying to * @param url the URL * @exception DeploymentException if an error occurs */ protected void loadResources( final ZipFile zipFile, final String location, final URL url ) throws DeploymentException { handleBlocks( zipFile, DeployerUtil.loadManifest( zipFile ), url ); } /** * Create and register Infos for all blocks stored in deployment. * * @param properties the properties * @param url the url of deployment * @exception DeploymentException if an error occurs */ protected void handleBlocks( final ZipFile zipFile, final Manifest manifest, final URL url ) throws DeploymentException { final Map entries = manifest.getEntries(); final Iterator sections = entries.keySet().iterator(); //for every section (aka resource) // check to see if the attribute "Avalon-Block" is set to true while( sections.hasNext() ) { final String section = (String)sections.next(); final Attributes attributes = manifest.getAttributes( section ); final String blockValue = attributes.getValue( "Avalon-Block" ); final boolean isBlock = Boolean.valueOf( blockValue ).booleanValue(); if( isBlock ) { handleBlock( zipFile, section, url ); } } } /** * Handle the addition of a block from .bar file. * * @param zipFile the .bar zip * @param block the block filename * @param url the url of .bar file * @exception DeploymentException if an error occurs */ protected void handleBlock( final ZipFile zipFile, final String block, final URL url ) throws DeploymentException { final String classname = block.substring( 0, block.length() - 6 ).replace('/','.'); addLocator( classname, classname, url ); final BlockInfo info = loadBlockInfo( zipFile, classname, url ); addInfo( classname, info ); } /** * Create a blockinfo object by loading a .xinfo file. * * @param zipFile the zipFile to load it from * @param classname the name of the block class * @param url the url for zip * @return the created block info * @exception DeploymentException if an error occurs */ protected BlockInfo loadBlockInfo( final ZipFile zipFile, final String classname, final URL url ) throws DeploymentException { final String resource = classname.replace( '.', '/' ) + ".xinfo"; final InputStream inputStream = DeployerUtil.loadResourceStream( zipFile, resource ); try { return m_builder.build( inputStream ); } catch( final Exception e ) { throw new DeploymentException( "Failed to build BlockInfo for " + classname + " in location " + url, e ); } finally { IOUtil.shutdownStream( inputStream ); } } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/deployer/blocks/RoleEntry.java Index: RoleEntry.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.phoenix.engine.blocks; /** * This is the structure describing the instances of roles provided to each block. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class RoleEntry { protected final String m_name; protected final String m_role; public RoleEntry( final String name, final String role ) { m_name = name; m_role = role; } public String getRole() { return m_role; } public String getName() { return m_name; } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/facilities/ApplicationManager.java Index: ApplicationManager.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.phoenix.engine.loader; import java.io.File; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.security.AccessControlContext; import java.security.AccessController; import java.security.CodeSource; import java.security.PermissionCollection; import java.security.Permissions; import java.security.Policy; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; import java.security.Security; import java.util.ArrayList; import java.util.Enumeration; import java.util.StringTokenizer; /** * PhoenixLoader is the class that bootstraps and installs the security manager. * It also a default policy that gives all code all permssions. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public final class PhoenixLoader { protected final static boolean ENABLE_SECURITY_MANAGER = !Boolean.getBoolean("phoenix.insecure"); protected final static String RESTRICTED_PACKAGES = System.getProperty( "phoenix.restricted.packages", Security.getProperty("package.access") ); protected final static String MAIN_JAR = System.getProperty( "phoenix.mainJar", "phoenix-engine.jar" ); protected final static String MAIN_CLASS = System.getProperty( "phoenix.mainClass", "org.apache.phoenix.engine.Main" ); public final static void main( final String args[] ) throws Exception { //setup restricted packages Security.setProperty( "phoenix.access", RESTRICTED_PACKAGES ); //setup new Policy manager Policy.setPolicy( new FreeNEasyPolicy() ); final File loaderDir = findLoaderDir(); final String avalonHome = loaderDir.getAbsoluteFile().getParentFile() + File.separator; System.setProperty( "phoenix.home", avalonHome ); final File mainJar = new File( loaderDir, MAIN_JAR ); //load main jar final URL archive = mainJar.toURL(); final URLClassLoader classLoader = new URLClassLoader( new URL[] { archive } ); runSystem( classLoader, args ); } /** * load class and retrieve appropriate main method. */ protected static void runSystem( final ClassLoader classLoader, final String[] args ) { try { final Class clazz = classLoader.loadClass( MAIN_CLASS ); final Method method = clazz.getMethod( "main", new Class[] { args.getClass() } ); final Object instance = clazz.newInstance(); // Set security manager unless it has been disabled by system property if( ENABLE_SECURITY_MANAGER ) { System.setSecurityManager( new SecurityManager() ); } //kick the tires and light the fires.... try { final PrivilegedExceptionAction action = new PrivilegedExceptionAction() { public Object run() throws Exception { method.invoke( instance, new Object[] { args } ); return null; } }; AccessController.doPrivileged( action ); } catch( final PrivilegedActionException pae ) { // only "checked" exceptions will be "wrapped" in a PrivilegedActionException. throw pae.getException(); } } catch( final Exception throwable ) { throwable.printStackTrace( System.err ); } } /** * Finds the avalon-loader.jar file in the classpath. */ protected final static File findLoaderDir() throws Exception { final String classpath = System.getProperty( "java.class.path" ); final String pathSeparator = System.getProperty( "path.separator" ); final StringTokenizer tokenizer = new StringTokenizer( classpath, pathSeparator ); while( tokenizer.hasMoreTokens() ) { final String element = tokenizer.nextToken(); if( element.endsWith( "phoenix-loader.jar" ) ) { File file = (new File( element )).getCanonicalFile(); file = file.getParentFile(); return file; } } throw new Exception( "Unable to locate avalon-loader.jar in classpath" ); } /** * Default polic class to give every code base all permssions. * Will be replaced once the kernel loads. */ private static class FreeNEasyPolicy extends Policy { public PermissionCollection getPermissions( final CodeSource codeSource ) { final Permissions permissions = new Permissions(); permissions.add( new java.security.AllPermission() ); return permissions; } public void refresh() {} } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/facilities/ClassLoader.java Index: ClassLoader.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.phoenix.engine.facilities; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.security.Policy; import org.apache.framework.component.ComponentManager; import org.apache.framework.component.ComponentException; import org.apache.framework.component.Composer; import org.apache.framework.context.Context; import org.apache.framework.context.Contextualizable; import org.apache.framework.lifecycle.Initializable; import org.apache.avalon.atlantis.Facility; import org.apache.aut.io.ExtensionFileFilter; import org.apache.aut.security.PolicyClassLoader; import org.apache.phoenix.engine.SarContextResources; /** * This component creates blocks and blockInfos. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class SarClassLoader extends PolicyClassLoader implements Facility, Contextualizable, Composer, Initializable { protected File m_baseDirectory; public SarClassLoader() { super( new URL[ 0 ], Thread.currentThread().getContextClassLoader(), null ); } public void contextualize( final Context context ) { m_baseDirectory = (File)context.get( SarContextResources.APP_HOME_DIR ); } public void compose( final ComponentManager componentManager ) throws ComponentException { m_policy = (Policy)componentManager.lookup( "java.security.Policy" ); } public void init() throws Exception { final File blockDir = (new File( m_baseDirectory, "blocks" )).getAbsoluteFile(); final File libDir = (new File( m_baseDirectory, "lib" )).getAbsoluteFile(); addURLs( blockDir, new String[] { ".bar" } ); addURLs( libDir, new String[] { ".jar", ".zip" } ); } protected void addURLs( final File directory, final String[] extentions ) throws MalformedURLException { final ExtensionFileFilter filter = new ExtensionFileFilter( extentions ); final File[] files = directory.listFiles( filter ); if( null == files ) return; addURLs( files ); } protected void addURLs( final File[] files ) throws MalformedURLException { for( int i = 0; i < files.length; i++ ) { addURL( files[ i ].toURL() ); } } public String toString() { final StringBuffer sb = new StringBuffer(); sb.append( "ClassLoader[" ); final URL[] urls = getURLs(); for( int i = 0; i < urls.length; i++ ) { sb.append( ' ' ); sb.append( urls[ i ] ); } sb.append( " ]" ); return sb.toString(); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/facilities/ConfigurationManager.java Index: ConfigurationManager.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.phoenix.engine.facilities; import org.apache.avalon.atlantis.Facility; import org.apache.avalon.camelot.Entry; import org.apache.avalon.camelot.pipeline.ConfigurationRepository; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.phoenix.engine.blocks.BlockEntry; /** * Repository from which all configuration data is retrieved. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultConfigurationRepository implements Facility { public Configuration getConfiguration( String name, Entry entry ) throws ConfigurationException { final BlockEntry blockEntry = (BlockEntry)entry; return blockEntry.getConfiguration(); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/facilities/LogManager.java Index: LogManager.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.phoenix.engine.facilities; import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; import org.apache.avalon.logger.AbstractLoggable; import org.apache.framework.context.Context; import org.apache.framework.context.Contextualizable; import org.apache.avalon.atlantis.Facility; import org.apache.framework.configuration.Configurable; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.log.format.AvalonLogFormatter; import org.apache.log.Category; import org.apache.log.LogKit; import org.apache.log.LogTarget; import org.apache.log.output.FileOutputLogTarget; /** * Component responsible for managing logs. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultLogManager extends AbstractLoggable implements Facility, Contextualizable, Configurable { protected String m_baseName; protected File m_baseDirectory; public void contextualize( final Context context ) { m_baseName = (String)context.get( "name" ); if( null == m_baseName ) m_baseName = "<base>"; m_baseDirectory = (File)context.get( "directory" ); if( null == m_baseDirectory ) m_baseDirectory = new File( "." ); } public void configure( final Configuration configuration ) throws ConfigurationException { final Iterator targets = configuration.getChildren( "log-target" ); configureTargets( m_baseName, m_baseDirectory, targets ); final Iterator categories = configuration.getChildren( "category" ); configureCategories( m_baseName, categories ); /* final String logPriority = configuration.getChild( "global-priority" ).getValue(); final Priority.Enum priority = LogKit.getPriorityForName( logPriority ); LogKit.setGlobalPriority( priority ); */ } protected void configureTargets( final String baseName, final File baseDirectory, final Iterator targets ) throws ConfigurationException { while(targets.hasNext()) { final Configuration target = (Configuration)targets.next(); final String name = baseName + '.' + target.getAttribute( "name" ); String location = target.getAttribute( "location" ).trim(); final String format = target.getAttribute( "format", null ); if( '/' == location.charAt( 0 ) ) { location = location.substring( 1 ); } final File file = new File( baseDirectory, location ); final FileOutputLogTarget logTarget = new FileOutputLogTarget(); final AvalonLogFormatter formatter = new AvalonLogFormatter(); formatter.setFormat( "%{time} [%7.7{priority}] <<%{category}>> " + "(%{context}): %{message}\\n%{throwable}" ); logTarget.setFormatter( formatter ); try { logTarget.setFilename( file.getAbsolutePath() ); } catch( final IOException ioe ) { throw new ConfigurationException( "Error initializing log files", ioe ); } if( null != format ) { logTarget.setFormat( format ); } LogKit.addLogTarget( name, logTarget ); } } protected void configureCategories( final String baseName, final Iterator categories ) throws ConfigurationException { while(categories.hasNext()) { final Configuration category = (Configuration)categories.next(); String name = category.getAttribute( "name" ); final String target = baseName + '.' + category.getAttribute( "target" ); final String priority = category.getAttribute( "priority" ); if( name.trim().equals( "" ) ) { name = baseName; } else { name = baseName + '.' + name; } final Category logCategory = LogKit.createCategory( name, LogKit.getPriorityForName( priority ) ); final LogTarget logTarget = LogKit.getLogTarget( target ); LogTarget logTargets[] = null; if( null != target ) logTargets = new LogTarget[] { logTarget }; LogKit.createLogger( logCategory, logTargets ); } } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/facilities/SecurityManager.java Index: SecurityManager.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.phoenix.engine.facilities; import java.io.File; import java.io.InputStream; import java.lang.reflect.Constructor; import java.net.MalformedURLException; import java.net.URL; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.Permission; import java.security.PermissionCollection; import java.security.Permissions; import java.security.UnresolvedPermission; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; import java.util.PropertyPermission; import java.util.StringTokenizer; import org.apache.framework.component.Component; import org.apache.framework.context.Context; import org.apache.framework.context.Contextualizable; import org.apache.avalon.context.DefaultContext; import org.apache.framework.lifecycle.Initializable; import org.apache.avalon.atlantis.Facility; import org.apache.framework.configuration.Configurable; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.aut.PropertyException; import org.apache.aut.PropertyUtil; import org.apache.aut.security.AbstractPolicy; /** * Policy that extracts information from policy files. * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultPolicy extends AbstractPolicy implements Facility, Contextualizable, Configurable, Initializable { protected DefaultContext m_context; public void contextualize( final Context context ) { m_context = new DefaultContext( System.getProperties(), context ); m_context.put( "/", File.separator ); } public void configure( final Configuration configuration ) throws ConfigurationException { final Iterator it = configuration.getChildren( "keystore" ); final HashMap keyStores = configureKeyStores( it ); final Iterator grants = configuration.getChildren( "grant" ); configureGrants( grants, keyStores ); // final Configuration[] grants = configuration.getChildren( "grant" ); // configureGrants( grants, keyStores ); } public void init() throws Exception { //these properties straight out ot ${java.home}/lib/security/java.policy final Permissions permissions = createPermissionSetFor( "file:/-", null ); permissions.add( new PropertyPermission( "os.name", "read" ) ); permissions.add( new PropertyPermission( "os.arch", "read" ) ); permissions.add( new PropertyPermission( "os.version", "read" ) ); permissions.add( new PropertyPermission( "file.separator", "read" ) ); permissions.add( new PropertyPermission( "path.separator", "read" ) ); permissions.add( new PropertyPermission( "line.separator", "read" ) ); permissions.add( new PropertyPermission( "java.version", "read" ) ); permissions.add( new PropertyPermission( "java.vendor", "read" ) ); permissions.add( new PropertyPermission( "java.vendor.url", "read" ) ); permissions.add( new PropertyPermission( "java.class.version", "read" ) ); permissions.add( new PropertyPermission( "java.vm.version", "read" ) ); permissions.add( new PropertyPermission( "java.vm.vendor", "read" ) ); permissions.add( new PropertyPermission( "java.vm.name", "read" ) ); permissions.add( new PropertyPermission( "java.specification.version", "read" ) ); permissions.add( new PropertyPermission( "java.specification.vendor", "read" ) ); permissions.add( new PropertyPermission( "java.specification.name", "read" ) ); permissions.add( new PropertyPermission( "java.vm.specification.version", "read" ) ); permissions.add( new PropertyPermission( "java.vm.specification.vendor", "read" ) ); permissions.add( new PropertyPermission( "java.vm.specification.name", "read" ) ); } protected HashMap configureKeyStores( final Iterator it ) throws ConfigurationException { final HashMap keyStores = new HashMap(); while(it.hasNext()) { final Configuration configuration = (Configuration)it.next(); final String type = configuration.getAttribute( "type" ); final String location = configuration.getAttribute( "location" ); final String name = configuration.getAttribute( "name" ); try { final KeyStore keyStore = KeyStore.getInstance( type ); final URL url = new URL( location ); final InputStream ins = url.openStream(); keyStore.load( ins, null ); keyStores.put( name, keyStore ); } catch( final Exception e ) { throw new ConfigurationException( "Error configuring keystore " + name, e ); } } return keyStores; } protected void configureGrants( final Iterator it, final HashMap keyStores ) throws ConfigurationException { while(it.hasNext()) { configureGrant( (Configuration)it.next(), keyStores ); } } protected void configureGrant( final Configuration configuration, final HashMap keyStores ) throws ConfigurationException { //<grant signed-by="Fred" code-base="file:${sar.home}/blocks/*" key-store="foo-keystore"> //<permission class="java.io.FilePermission" target="/tmp/*" action="read,write" /> //</grant> final String signedBy = configuration.getAttribute( "signed-by", null ); final String keyStoreName = configuration.getAttribute( "key-store", null ); String codeBase = configuration.getAttribute( "code-base", null ); if( null != codeBase ) { codeBase = expand( codeBase ); } final Certificate[] signers = getSigners( signedBy, keyStoreName, keyStores ); Permissions permissions = null; try { permissions = createPermissionSetFor( codeBase, signers ); } catch( final MalformedURLException mue ) { throw new ConfigurationException( "Malformed code-base " + codeBase, mue ); } configurePermissions( configuration.getChildren( "permission" ), permissions, keyStores ); } protected void configurePermissions( final Iterator it, final Permissions permissions, final HashMap keyStores ) throws ConfigurationException { while(it.hasNext()) { configurePermission( (Configuration)it.next(), permissions, keyStores ); } } protected void configurePermission( final Configuration configuration, final Permissions permissions, final HashMap keyStores ) throws ConfigurationException { final String type = configuration.getAttribute( "class" ); final String actions = configuration.getAttribute( "actions", null ); final String signedBy = configuration.getAttribute( "signed-by", null ); final String keyStoreName = configuration.getAttribute( "key-store", null ); String target = configuration.getAttribute( "target", null ); if( null != target ) { target = expand( target ); } final Certificate[] signers = getSigners( signedBy, keyStoreName, keyStores ); final Permission permission = createPermission( type, target, actions, signers ); permissions.add( permission ); } protected String expand( final String value ) throws ConfigurationException { try { final Object resolvedValue = PropertyUtil.resolveProperty( value, m_context, false ); return resolvedValue.toString(); } catch( final PropertyException pe ) { throw new ConfigurationException( "Error resolving property " + value, pe ); } } protected Permission createPermission( final String type, final String target, final String actions, final Certificate[] signers ) throws ConfigurationException { if( null != signers ) { return createUnresolvedPermission( type, target, actions, signers ); } try { final Class c = Class.forName( type ); Class paramClasses[] = null; Object params[] = null; if( null == actions && null == target ) { paramClasses = new Class[ 0 ]; params = new Object[ 0 ]; } else if( null == actions ) { paramClasses = new Class[1]; paramClasses[0] = String.class; params = new Object[1]; params[0] = target; } else { paramClasses = new Class[2]; paramClasses[0] = String.class; paramClasses[1] = String.class; params = new Object[2]; params[0] = target; params[1] = actions; } final Constructor constructor = c.getConstructor( paramClasses ); final Object o = constructor.newInstance( params ); return (Permission)o; } catch( final ClassNotFoundException cnfe ) { return createUnresolvedPermission( type, target, actions, signers ); } catch( final Exception e ) { throw new ConfigurationException( "Failed to create permission " + type + " due to " + e, e ); } } protected Permission createUnresolvedPermission( final String type, final String target, final String actions, final Certificate[] signers ) { return new UnresolvedPermission( type, target, actions, signers ); } protected Certificate[] getSigners( final String signedBy, String keyStoreName, final HashMap keyStores ) throws ConfigurationException { if( null != signedBy && null == keyStoreName ) { keyStoreName = "default"; } Certificate[] signers = null; if( null != signedBy ) { signers = getCertificates( signedBy, keyStoreName, keyStores ); } return signers; } protected Certificate[] getCertificates( final String signedBy, final String keyStoreName, final HashMap keyStores ) throws ConfigurationException { final KeyStore keyStore = (KeyStore)keyStores.get( keyStoreName ); if( null == keyStore ) { throw new ConfigurationException( "Unable to aquire keyStore " + keyStoreName ); } final ArrayList certificateSet = new ArrayList(); final StringTokenizer tokenizer = new StringTokenizer( signedBy, "," ); while( tokenizer.hasMoreTokens() ) { final String alias = ((String)tokenizer.nextToken()).trim(); Certificate certificate = null; try { certificate = keyStore.getCertificate( alias ); } catch( final KeyStoreException kse ) { throw new ConfigurationException( "Error aquiring certificate " + alias, kse ); } if( null == certificate ) { throw new ConfigurationException( "Unable to locate alias " + alias + " in keystore named " + keyStoreName ); } if( !certificateSet.contains( certificate ) ) { if( DEBUG ) getLogger().debug( "Certificate " + certificate ); certificateSet.add( certificate ); } } return (Certificate[])certificateSet.toArray( new Certificate[ 0 ] ); } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/facilities/ThreadManager.java Index: ThreadManager.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.phoenix.engine.facilities; import java.util.Hashtable; import java.util.Iterator; import org.apache.avalon.logger.AbstractLoggable; import org.apache.avalon.atlantis.Facility; import org.apache.framework.configuration.Configurable; import org.apache.framework.configuration.Configuration; import org.apache.framework.configuration.ConfigurationException; import org.apache.avalon.thread.DefaultThreadPool; import org.apache.framework.thread.ThreadManager; import org.apache.framework.thread.ThreadPool; /** * * * @author <a href="mailto:[EMAIL PROTECTED]">Federico Barbieri</a> * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public class DefaultThreadManager extends AbstractLoggable implements Facility, ThreadManager, Configurable { protected final Hashtable m_pools = new Hashtable(); public void configure( final Configuration configuration ) throws ConfigurationException { final Iterator it = configuration.getChildren( "thread-group" ); while(it.hasNext()) { final Configuration group = (Configuration)it.next(); final String name = group.getChild( "name" ).getValue(); final int priority = group.getChild( "priority" ).getValueAsInt( 5 ); final boolean isDaemon = group.getChild( "is-daemon" ).getValueAsBoolean( false ); final int minThreads = group.getChild( "min-threads" ).getValueAsInt( 5 ); final int maxThreads = group.getChild( "max-threads" ).getValueAsInt( 10 ); final int minSpareThreads = group.getChild( "min-spare-threads" ). getValueAsInt( maxThreads - minThreads ); try { final DefaultThreadPool threadPool = new DefaultThreadPool( name, maxThreads ); threadPool.setDaemon( isDaemon ); //setupLogger( threadPool ); m_pools.put( name, threadPool ); } catch( final Exception e ) { throw new ConfigurationException( "Error creating thread pool " + name, e ); } } } public ThreadPool getDefaultThreadPool() { return getThreadPool( "default" ); } public ThreadPool getThreadPool( final String name ) { final ThreadPool threadPool = (ThreadPool)m_pools.get( name ); if( null == threadPool ) { //Should this be a ComponentNotFoundException ???? throw new IllegalArgumentException( "No such thread group " + name ); } return threadPool; } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/engine/jmx/Manager.java Index: Manager.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.phoenix.engine.facilities; import javax.management.MBeanServer; /** * * @author <a href="[EMAIL PROTECTED]">Leo Simons</a> */ public class AvalonMBeanServer { private MBeanServer server; public AvalonMBeanServer( MBeanServer server ) { this.server = server; } } 1.1 jakarta-avalon-phoenix/proposal/4.0/src/java/org/apache/phoenix/facilities/Facility.java Index: Facility.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.avalon.atlantis; import org.apache.avalon.Component; /** * A Facility is a horizontal cut through the kernel. * Unlike Components which offer a Service/Content interface, Facilitys * are used to facilitate the non-Service/Form interface or life-cycle orientated * methods of Components. See documentation for a clearer explanation. * * Example Facilities would be * <ul> * <li>ConfigurationRepository that stores configuration data for components</li> * <li>ThreadFacility that allows components to run in threads</li> * <li>ContextUtility that builds context information for components</li> * <li>ExportFacility that exports components to external users (perhaps via RMI)</li> * <li>NamingFacility that binds compoents to a name in a directory</li> * <li>ManagementFacility that manages components via JMX</li> * </ul> * * @author <a href="mailto:[EMAIL PROTECTED]">Peter Donald</a> */ public interface Facility extends Component { } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]