jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/webserver Main.java,NONE,1.1 PureJavaMain.java,NONE,1.1

Leo Simons <[email protected]>
Newsgroups gmane.comp.java.jicarilla.cvs
Message-ID <[email protected]>
Update of /cvsroot/jicarilla/jicarilla-sandbox/platform/components/http/impl/src/java/org/jicarilla/webserver
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv20979/platform/components/http/impl/src/java/org/jicarilla/webserver

Added Files:
	Main.java PureJavaMain.java 
Log Message:
seperate plumbing material from the basic HTTP logic, and work on solidifying the I/O code.

--- NEW FILE: PureJavaMain.java ---
/* ====================================================================
The Jicarilla Software License

Copyright (c) 2003 Leo Simons.
All rights reserved.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
==================================================================== */
package org.jicarilla.webserver;

import EDU.oswego.cs.dl.util.concurrent.Executor;
import EDU.oswego.cs.dl.util.concurrent.PooledExecutor;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.PosixParser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.SimpleLog;
import org.apache.commons.pool.impl.SoftReferenceObjectPool;
import org.jicarilla.container.Resolver;
import org.jicarilla.container.builder.Builder;
import org.jicarilla.container.builder.CustomComponent;
import org.jicarilla.container.builder.DefaultBuilder;
import org.jicarilla.container.selectors.ClassSelector;
import org.jicarilla.http.MessageFactory;
import org.jicarilla.lang.Active;
import org.jicarilla.lang.ExceptionListener;
import org.jicarilla.lang.LifecycleUtil;
import org.jicarilla.lang.NoopExceptionListener;
import org.jicarilla.lang.OrSelector;
import org.jicarilla.lang.Selector;
import org.jicarilla.net.EventFactory;
import org.jicarilla.net.SocketServer;
import org.jicarilla.net.SocketServerConfig;
import org.jicarilla.net.SocketServerImpl;
import org.jicarilla.plumbing.NoopSink;
import org.jicarilla.webserver.plumbing.BeanshellHTTPChannelFactory;
import org.jicarilla.webserver.plumbing.JettyChannelFactory;
import org.mortbay.http.HttpContext;
import org.mortbay.http.HttpServer;
import org.mortbay.http.handler.ResourceHandler;
import org.mortbay.util.MultiException;
import org.picocontainer.Parameter;
import org.picocontainer.defaults.CachingComponentAdapter;
import org.picocontainer.defaults.ComponentParameter;
import org.picocontainer.defaults.ConstantParameter;
import org.picocontainer.defaults.ConstructorComponentAdapter;

import java.net.InetAddress;
import java.net.UnknownHostException;

/**
 * This version of main not only uses a Jicarilla Container instead of a
 * PicoContainer, it also doesn't use BeanShell but hardwires things.
 *
 * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
 * @version $Id: PureJavaMain.java,v 1.1 2004/03/31 12:11:00 lsimons Exp $
 */
public class PureJavaMain implements Active
{
    public final static double MILLISECONDS_IN_A_SECOND = 1000.0;

    // default configuration
    public final static int DEFAULT_PORT = 8080;
    public final static int DEFAULT_BACKLOG = 500;
    public final static String DEFAULT_ADDRESS = "127.0.0.1";
    public final static int DEFAULT_THREADS = 5;
    public final static int DEFAULT_LOG_LEVEL = SimpleLog.LOG_LEVEL_WARN;
    public final static String DEFAULT_DIRECTORY =
            "/var/www/html";
    //public final static Class DEFAULT_SERVER_CLASS =
    //        SocketServerImpl.class;
    public final static int DEFAULT_INITIAL_POOL_SIZE = 20;

    // configuration
    protected int m_port = DEFAULT_PORT;
    protected int m_backlog = DEFAULT_BACKLOG;
    protected String m_address = DEFAULT_ADDRESS;
    protected int m_threads = DEFAULT_THREADS;
    protected int m_logLevel = DEFAULT_LOG_LEVEL;
    protected String m_directory = DEFAULT_DIRECTORY;
    protected int m_initialPoolSize = DEFAULT_INITIAL_POOL_SIZE;
    //protected Class m_serverClass;

    // helpers
    protected Object m_config;
    protected Log m_log;
    protected Object m_server;
    protected Resolver m_resolver;
    protected String[] m_args;
    protected CommandLine m_options;

    // instrumentation
    protected long startTime = System.currentTimeMillis();

    protected PureJavaMain( final String[] args ) throws Exception
    {
        m_args = args;
        setupCommandLine();
        setupConfig();
        setupLog();
        setupContainer();
    }
    
    public void initialize() throws Throwable
    {
        m_server = (SocketServer)m_resolver.get( SocketServer.class );

        m_log.info( "Starting Jicarilla server: " + m_address + ":" + m_port );

        // todo: move to container!
        LifecycleUtil.initialize( m_server );

        m_log.debug( "Up in " +
                (System.currentTimeMillis()-startTime)/MILLISECONDS_IN_A_SECOND +
                " seconds." );
    }

    public void dispose() throws Throwable
    {
        // todo: move to container!
        LifecycleUtil.dispose( m_server );
        m_resolver.releaseInstance( m_server );
    }

    public static void main( final String[] args )
    {
        Active main = null;
        try
        {
            main = new PureJavaMain( args );
            main.initialize();
        }
        catch( Throwable th )
        {
            printError( "Error initializing the server: ",
                    "Please try again. If the problem persists, contact your administrator.",
                    th, true
            );

            try
            {
                if( main != null )
                    main.dispose();
            }
            catch( Throwable t )
            {
                printError( "Error attempting a graceful shutdown: ",
                        "This is probably not a big problem.", t, true );
            }
        }
    }

    // ----------------------------------------------------------------------
    //  Setup Helpers
    // ----------------------------------------------------------------------
    protected void setupCommandLine()
    {
        final Options o = new Options();

        OptionBuilder.withArgName( "string" );
        OptionBuilder.withLongOpt( "base-directory" );
        OptionBuilder.withDescription(
                "the base directory from which to serve files" );
        OptionBuilder.withValueSeparator( '=' );
        OptionBuilder.hasArg();
        o.addOption( OptionBuilder.create( 'd' ) );

        OptionBuilder.withArgName( "number" );
        OptionBuilder.withLongOpt( "port" );
        OptionBuilder.withDescription(
                "the port on which to listen for requests" );
        OptionBuilder.withValueSeparator( '=' );
        OptionBuilder.hasArg();
        o.addOption( OptionBuilder.create( 'p' ) );

        OptionBuilder.withArgName( "number" );
        OptionBuilder.withLongOpt( "backlog" );
        OptionBuilder.withDescription(
                "the maximum size of the queue for the server socket" );
        OptionBuilder.withValueSeparator( '=' );
        OptionBuilder.hasArg();
        o.addOption( OptionBuilder.create( 'b' ) );

        OptionBuilder.withArgName( "string" );
        OptionBuilder.withLongOpt( "address" );
        OptionBuilder.withDescription(
                "the address on which to listen for requests" );
        OptionBuilder.withValueSeparator( '=' );
        OptionBuilder.hasArg();
        o.addOption( OptionBuilder.create( 'a' ) );

        OptionBuilder.withArgName( "number" );
        OptionBuilder.withLongOpt( "threads" );
        OptionBuilder.withDescription(
                "the number of base worker threads to create" );
        OptionBuilder.withValueSeparator( '=' );
        OptionBuilder.hasArg();
        o.addOption( OptionBuilder.create( 't' ) );

        //OptionBuilder.withArgName( "string" );
        //OptionBuilder.withLongOpt( "serverClass" );
        //OptionBuilder.withDescription(
        //        "the class to use as the central active server" );
        //OptionBuilder.withValueSeparator( '=' );
        //OptionBuilder.hasArg();
        //o.addOption( OptionBuilder.create( 'c' ) );

        OptionBuilder.withLongOpt( "debug" );
        OptionBuilder.withDescription( "be more verbose" );
        o.addOption( OptionBuilder.create( 'd' ) );

        OptionBuilder.withLongOpt( "quiet" );
        OptionBuilder.withDescription( "be less verbose" );
        OptionBuilder.withValueSeparator( '=' );
        o.addOption( OptionBuilder.create( 'q' ) );

        //OptionBuilder.withArgName( "number" );
        //OptionBuilder.withLongOpt( "bsh-port" );
        //OptionBuilder.withDescription(
        //        "the port on which to run the telnet BeanShell server" );
        //OptionBuilder.withValueSeparator( '=' );
        //OptionBuilder.hasArg();
        //o.addOption( OptionBuilder.create() );

        try
        {
            final PosixParser parser = new PosixParser();
            //parser = new GnuParser();
            m_options = parser.parse( o, m_args );
        }
        catch( Exception e )
        {
            final HelpFormatter formatter = new HelpFormatter();
            System.out.println( e.getMessage() );
            System.out.println(
                    "--------------------------------------------------" );
            formatter.printHelp( "java org.jicarilla.webserver.Main [OPTIONS]",
                    "\nStart the Jicarilla Server. Available options are:", o,
                    "" );
            System.exit( 1 );
        }
    }

    protected void setupContainer() throws Exception
    {
        final Builder builder = DefaultBuilder.newInstance()
            .addComponent( m_log )
            .addComponent( m_config );
        m_resolver = builder.getResolver();

        // todo move jetty support elsewhere
        //populate( builder );
        populateWithJetty( builder );

        builder.create();
    }

    protected void setupConfig() throws ClassNotFoundException
    {
        if( m_options.hasOption("port") )
            m_port = new Integer(m_options.getOptionValue("port")).intValue();

        m_backlog = m_options.hasOption("backlog")?
                new Integer(m_options.getOptionValue("backlog")).intValue() :
                DEFAULT_BACKLOG;

        m_address = m_options.hasOption("address")?
                m_options.getOptionValue("address") :
                DEFAULT_ADDRESS;

        m_directory = m_options.hasOption("directory")?
                m_options.getOptionValue("directory") : DEFAULT_DIRECTORY;

        m_threads = m_options.hasOption("threads")?
                new Integer(m_options.getOptionValue("threads")).intValue() :
                DEFAULT_THREADS;

        //m_serverClass = m_options.hasOption("server")?
        //        Class.forName( m_options.getOptionValue("server") ) :
        //        DEFAULT_SERVER_CLASS;

        m_logLevel = m_options.hasOption("quiet")?
                SimpleLog.LOG_LEVEL_WARN : SimpleLog.LOG_LEVEL_INFO;
        if( m_options.hasOption("debug") )
            m_logLevel = SimpleLog.LOG_LEVEL_DEBUG;

        m_config = new SocketServerConfig(
                m_address, m_port, m_backlog, m_threads );
    }

    protected void setupLog()
    {
        final SimpleLog log = new SimpleLog( m_address );
        log.setLevel( m_logLevel );
        m_log = log;
    }

    protected void populate( final Builder builder )
    {
        builder.addComponent(
                ExceptionListener.class,
                NoopExceptionListener.class
        );
        builder.addComponent(
                new OrSelector(
                        new Selector[] {
                            new ClassSelector(Executor.class),
                            new ClassSelector(PooledExecutor.class)
                        }
                ),
                PooledExecutor.class
        );

        // HTTP component
        /*builder.addComponent(
                MessageReceivedListener.class,
                NoopMessageReceivedListener.class
        );*/
        builder.addComponent(
                "message-pool",
                new SoftReferenceObjectPool( new MessageFactory() )
        );
        /*builder.addComponent(
                new OrSelector(
                        new Selector[] {
                            new ClassSelector(HTTPHandler.class),
                            new ClassSelector(HTTPErrorHandler.class)
                        }
                ),
                new CachingComponentAdapter(
                        new ConstructorComponentAdapter(
                                HTTPHandler.class,
                                HTTPMessageGenerator.class,
                                new Parameter[] {
                                    new ComponentParameter( ExceptionListener.class ),
                                    new ComponentParameter( MessageReceivedListener.class ),
                                    new ComponentParameter( "message-pool" )
                                }
                        )
                )
        );*/
        /*builder.addComponent(
                HTTPParser.class,
                HTTPParserImpl.class
        );*/

        // event pipeline
        builder.addComponent(
                "pipeline-factory",
                new BeanshellHTTPChannelFactory() );
        builder.addComponent(
                "pipeline-pool",
                new CachingComponentAdapter(
                        new ConstructorComponentAdapter(
                                "pipeline-pool",
                                SoftReferenceObjectPool.class,
                                new Parameter[] {
                                    new ComponentParameter( "pipeline-factory" ),
                                    new ConstantParameter(
                                            new Integer( m_initialPoolSize ) )
                                }
                        )
                )
        );

        // Socket Server
        builder.addComponent(
                "event-pool",
                new SoftReferenceObjectPool( new EventFactory() )
        );
        builder.addComponent(
                "error-handler",
                new NoopSink()
        );
        
        /*DefaultCustomizableResolver customResolver =
                new DefaultCustomizableResolver( m_resolver )
                .redirectCall( 3, "event-pool" )
                .redirectCall( 4, "pipeline-pool" )
                .redirectCall( 5, "error-handler" );
        Type3Factory factory = new Type3Factory( customResolver,
                SocketServerImpl.class.getName() );
        SingletonAdapter adapter = new SingletonAdapter( factory );
        
        builder.addComponent(
                SocketServer.class,
                adapter
        );*/
        
        builder.addComponent(
                SocketServer.class,
                new CustomComponent( SocketServerImpl.class )
                    .redirectCall( 3, "event-pool" )
                    .redirectCall( 4, "pipeline-pool" )
                    .redirectCall( 5, "error-handler" )
        );
        
        /*builder.addComponent(
                SocketServer.class,
                new CachingComponentAdapter(
                        new ConstructorComponentAdapter(
                                SocketServer.class,
                                SocketServerImpl.class,
                                new Parameter[] {
                                    new ComponentParameter( SocketServerConfig.class ),
                                    new ComponentParameter( ExceptionListener.class ),
                                    new ComponentParameter( "event-pool" ),
                                    new ComponentParameter( "pipeline-pool" ),
                                    new ComponentParameter( "error-handler" ),
                                    new ComponentParameter( PooledExecutor.class )
                                }
                        )
                )
        );*/
    }

    // ----------------------------------------------------------------------
    //  Error Printing Helpers
    // ----------------------------------------------------------------------
    protected static void printError( final String prefix, final String postfix,
            final Throwable t, final boolean recurse )
    {
        System.err.println( prefix + t.getMessage() );
        if( recurse )
        {
            System.err.println( "A stack trace follows:" );
            System.err.println(
                    "-----------------------------------------------------" );
            t.printStackTrace();
            //printRecursiveMessages( t.getCause(), 4 );
            //if( t instanceof EvalError )
            //{
            //    System.err.println( ((EvalError)t).getScriptStackTrace() );
            //}
            System.err.println(
                    "-----------------------------------------------------" );
        }
        System.err.println( postfix );
    }

    protected static void printRecursiveMessages( final Throwable t, final int indent )
    {
        if( t == null )
            return;

        for( int i = 0; i < indent; i++ )
        {
            System.err.print( ' ' );
        }

        System.err.print( friendlyClassName( t ) + ": " + t.getMessage() );
        System.err.println();

        printRecursiveMessages( t.getCause(), indent + 4 );
    }

    protected static String friendlyClassName( final Object o )
    {
        final String fqn = o.getClass().getName();
        final String last = fqn.substring( fqn.lastIndexOf( '.' ) );
        return last;
    }

    // ----------------------------------------------------------------------
    //  Jetty Integration
    // ----------------------------------------------------------------------

    protected void populateWithJetty( final Builder builder ) throws UnknownHostException, MultiException
    {
        builder.addComponent(
                ExceptionListener.class,
                NoopExceptionListener.class
        );
        builder.addComponent(
                new OrSelector(
                        new Selector[] {
                            new ClassSelector(Executor.class),
                            new ClassSelector(PooledExecutor.class)
                        }
                ),
                PooledExecutor.class
        );
        builder.addComponent(
                "message-pool",
                new SoftReferenceObjectPool( new MessageFactory() )
        );

        // Jetty
        builder.addComponent(
                "pipeline-factory",
                new JettyChannelFactory(
                        createJettyServer(),
                        createInetAddress()
                ) );
        builder.addComponent(
                "pipeline-pool",
                new CachingComponentAdapter(
                        new ConstructorComponentAdapter(
                                "pipeline-pool",
                                SoftReferenceObjectPool.class,
                                new Parameter[] {
                                    new ComponentParameter( "pipeline-factory" ),
                                    new ConstantParameter(
                                            new Integer( m_initialPoolSize ) )
                                }
                        )
                )
        );

        // Socket Server
        builder.addComponent(
                "event-pool",
                new SoftReferenceObjectPool( new EventFactory() )
        );
        builder.addComponent(
                "error-handler",
                new NoopSink()
        );
        builder.addComponent(
                SocketServer.class,
                new CustomComponent( SocketServerImpl.class )
                    .redirectCall( 3, "event-pool" )
                    .redirectCall( 4, "pipeline-pool" )
                    .redirectCall( 5, "error-handler" )
        );
    }

    protected InetAddress createInetAddress() throws UnknownHostException
    {
        return InetAddress.getByName( m_address );
    }

    protected HttpServer createJettyServer() throws MultiException
    {
        final HttpServer jetty = new HttpServer();

        configureJetty( jetty );

        return jetty;
    }

    protected void configureJetty( final HttpServer server ) throws MultiException
    {
        final HttpContext context = new HttpContext();
        context.setContextPath( "/" );
        context.setResourceBase( m_directory );
        context.addHandler( new ResourceHandler() );
        server.addContext( context );

        server.start();
    }
}

--- NEW FILE: Main.java ---
/* ====================================================================
 The Jicarilla Software License

 Copyright (c) 2003 Leo Simons.
 All rights reserved.

 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
 "Software"), to deal in the Software without restriction, including
 without limitation the rights to use, copy, modify, merge, publish,
 distribute, sublicense, and/or sell copies of the Software, and to
 permit persons to whom the Software is furnished to do so, subject to
 the following conditions:

 The above copyright notice and this permission notice shall be
 included in all copies or substantial portions of the Software.

 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
==================================================================== */
package org.jicarilla.webserver;

import bsh.EvalError;
import bsh.Interpreter;
import org.apache.commons.logging.Log;
import org.jicarilla.lang.LifecycleUtil;
import org.jicarilla.net.SocketServer;
import org.picocontainer.PicoContainer;

import java.io.FileNotFoundException;
import java.io.IOException;

/**
 * this is a basic CLI wrapper that calls the
 * BeanShell startup script.
 *
 * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
 * @version $Id: Main.java,v 1.1 2004/03/31 12:11:00 lsimons Exp $
 */
public class Main
{
    public final static int SHUTDOWN_DELAY_IN_MILLISECONDS = 1000;

    public static void main( final String[] args )
    {
        Log log = null;
        SocketServer server = null;
        PicoContainer container = null;

        final Interpreter i = new Interpreter();
        try { i.set( "args", args ); }
        catch( EvalError e ) {
            printError( "The server experienced a strange internal error: ",
                    "Please contact your support department.", e, true ); }

        try { i.source( "startup.bsh" ); }
        catch( FileNotFoundException fnfe ) {
            printError( "Cannot find the configuration file: ",
                    "Please try putting startup.bsh in the correct location.", fnfe, true ); }
        catch( IOException ioe ) {
            printError( "Error reading the configuration file: ",
                    "Please try again. If the problem persists, contact your administrator.", ioe, true ); }
        catch( EvalError ee ) {
            final int line = ee.getErrorLineNumber();
            printError( "Error in configuration file on line "+line+": ",
                    "", ee, true ); }
        try
        {

            log = (Log)i.get( "log" );
            server = (SocketServer)i.get( "server" );
            container = (PicoContainer)i.get( "container" );
        }

        catch( Exception e )
        {
            printError( "Error parsing the configuration file: ",
                    "Please examine the stack trace to find the cause of the problem and fix it.", e, false );

            if( log != null )
            {
                log.error( "An exception occured during startup", e );
                log.error( "Exiting on error..." );
            }

            try
            {
                LifecycleUtil.dispose( server );
                LifecycleUtil.dispose( container );
                Thread.sleep( SHUTDOWN_DELAY_IN_MILLISECONDS );
            }
            catch( Throwable t )
            {
                printError( "Error attempting a graceful shutdown: ",
                        "This is probably not a big problem.", e, true );
            }
        }
    }

    protected static void printError( final String prefix, final String postfix, final Throwable t, final boolean recurse )
    {
        System.err.println( prefix + t.getMessage() );
        if(recurse)
        {
            System.err.println( "A stack trace follows:" );
            System.err.println( "-----------------------------------------------------" );
            printRecursiveMessages( t.getCause(), 4 );
            if(t instanceof EvalError )
            {
                t.printStackTrace();
                System.err.println( ((EvalError)t).getScriptStackTrace() );
            }
            System.err.println( "-----------------------------------------------------" );
        }
        System.err.println( postfix );
    }

    protected static void printRecursiveMessages( final Throwable t, final int indent )
    {
        if( t == null )
            return;

        for( int i = 0; i < indent; i++ )
            System.err.print(' ');

        System.err.print( friendlyClassName( t ) + ": " + t.getMessage() );
        System.err.println();

        printRecursiveMessages( t.getCause(), indent+4 );
    }

    protected static String friendlyClassName( final Object o )
    {
        final String fqn = o.getClass().getName();
        final String last = fqn.substring( fqn.lastIndexOf('.') );
        return last;
    }
}



-------------------------------------------------------
This SF.Net email is sponsored by: IBM Linux Tutorials
Free Linux tutorial presented by Daniel Robbins, President and CEO of
GenToo technologies. Learn everything from fundamentals to system
administration.http://ads.osdn.com/?ad_id=1470&alloc_id=3638&op=click
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.