You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@avalon.apache.org by pr...@apache.org on 2002/08/01 22:42:08 UTC

cvs commit: jakarta-avalon-apps/phyre/src/java/org/apache/avalon/phyre/block HttpConnectionHandler.java HttpConstants.java PhyreWebStartLoader-schema.xml PhyreWebStartLoader.java

proyal      2002/08/01 13:42:08

  Added:       phyre/src/java/org/apache/avalon/phyre/block
                        HttpConnectionHandler.java HttpConstants.java
                        PhyreWebStartLoader-schema.xml
                        PhyreWebStartLoader.java
  Log:
  Block with mini webserver for Web Start support
  
  Revision  Changes    Path
  1.1                  jakarta-avalon-apps/phyre/src/java/org/apache/avalon/phyre/block/HttpConnectionHandler.java
  
  Index: HttpConnectionHandler.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.txt file.
   */
  package org.apache.avalon.phyre.block;
  
  import java.io.BufferedInputStream;
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.PrintStream;
  import java.net.ProtocolException;
  import java.net.Socket;
  import java.util.Date;
  import java.util.HashMap;
  import java.util.Map;
  
  import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
  import org.apache.avalon.excalibur.io.IOUtil;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  
  /**
   * @author <a href="mailto:proyal@apache.org">Peter Royal</a>
   */
  class HttpConnectionHandler extends AbstractLogEnabled
      implements ConnectionHandler, Configurable, Contextualizable, HttpConstants
  {
      /* mapping of file extensions to content-types */
      private static final Map CONTENT_TYPE_MAP = new HashMap();
      private static final int BUF_SIZE = 2048;
      private static final byte[] EOL = {( byte ) '\r', ( byte ) '\n'};
  
      private File m_homeDir;
      private File m_subDir;
      private File m_jnlp;
  
      private int m_timeout;
  
      static
      {
          fillMap();
      }
  
      public void contextualize( Context context )
          throws ContextException
      {
          m_homeDir = ( File ) context.get( "app.home" );
      }
  
      public void configure( Configuration configuration )
          throws ConfigurationException
      {
          m_subDir = new File( m_homeDir, configuration.getChild( "data-directory" ).getValue() );
  
          if( !m_subDir.exists() )
          {
              throw new ConfigurationException( "invalid data-directory" );
          }
  
          m_jnlp = new File( m_subDir,
                             configuration.getChild( "jnlp-file" ).getValue( "phyre.jnlp" ) );
  
          if( !m_jnlp.exists() )
          {
              throw new ConfigurationException( "invalid jnlp-file" );
          }
  
          m_timeout = configuration.getAttributeAsInteger( "timeout", 0 );
      }
  
      public void handleConnection( Socket connection )
          throws IOException, ProtocolException
      {
          final byte[] buffer = new byte[BUF_SIZE];
          final InputStream is = new BufferedInputStream( connection.getInputStream() );
          final PrintStream ps = new PrintStream( connection.getOutputStream() );
  
          connection.setSoTimeout( m_timeout );
          connection.setTcpNoDelay( true );
  
          int nread = 0;
          int r = 0;
  
          outerloop: while( nread < BUF_SIZE )
          {
              r = is.read( buffer, nread, BUF_SIZE - nread );
  
              if( -1 == r )
              {
                  return;
              }
  
              int i = nread;
  
              nread += r;
  
              for( ; i < nread; i++ )
              {
                  if( buffer[i] == ( byte ) '\n' || buffer[i] == ( byte ) '\r' )
                  {
                      /* read one line */
                      break outerloop;
                  }
              }
          }
  
          boolean get = false;
          int index;
  
          if( isGet( buffer ) )
          {
              get = true;
              index = 4;
          }
          else if( isHead( buffer ) )
          {
              index = 5;
          }
          else
          {
              /* we don't support this method */
              ps.print( "HTTP/1.0 " + HTTP_BAD_METHOD + " unsupported method type: " );
              ps.write( buffer, 0, 5 );
              ps.write( EOL );
              ps.flush();
  
              return;
          }
  
          int i = 0;
          /* find the file name, from:
           * GET /foo/bar.html HTTP/1.0
           * extract "/foo/bar.html"
           */
          for( i = index; i < nread; i++ )
          {
              if( buffer[i] == ( byte ) ' ' )
              {
                  break;
              }
          }
  
          String fname = new String( buffer, 0, index, i - index ).replace( '/', File.separatorChar );
          File target;
  
          if( fname.startsWith( File.separator ) )
          {
              fname = fname.substring( 1 );
          }
  
          if( 0 == fname.length() )
          {
              target = m_jnlp;
          }
          else
          {
              target = new File( m_subDir, fname );
          }
  
          boolean OK = printHeaders( target, ps );
  
          if( get )
          {
              if( OK )
              {
                  sendFile( target, ps );
              }
              else
              {
                  send404( ps );
              }
          }
      }
  
      private void send404( PrintStream ps ) throws IOException
      {
          ps.write( EOL );
          ps.write( EOL );
          ps.println( "Not Found\n\n" + "The requested resource was not found.\n" );
      }
  
      private void sendFile( File targ, PrintStream ps ) throws IOException
      {
          InputStream is = new FileInputStream( targ.getAbsolutePath() );
  
          ps.write( EOL );
  
          try
          {
              IOUtil.copy( is, ps );
          }
          finally
          {
              is.close();
          }
      }
  
      private boolean printHeaders( File target, PrintStream ps ) throws IOException
      {
          boolean ret = false;
          int rCode = 0;
  
          if( !target.exists() )
          {
              rCode = HTTP_NOT_FOUND;
              ps.print( "HTTP/1.0 " + HTTP_NOT_FOUND + " not found" );
              ps.write( EOL );
              ret = false;
          }
          else if( target.isDirectory() )
          {
              rCode = HTTP_FORBIDDEN;
              ps.print( "HTTP/1.0 " + HTTP_FORBIDDEN + " Directory listing forbidden" );
              ps.write( EOL );
              ret = false;
          }
          else
          {
              rCode = HTTP_OK;
              ps.print( "HTTP/1.0 " + HTTP_OK + " OK" );
              ps.write( EOL );
              ret = true;
          }
  
          ps.print( "Server: Phoenix Phyre JNLP Loaded" );
          ps.write( EOL );
          ps.print( "Date: " + new Date() );
          ps.write( EOL );
  
          if( ret )
          {
              ps.print( "Content-length: " + target.length() );
              ps.write( EOL );
              ps.print( "Last Modified: " + new Date( target.lastModified() ) );
              ps.write( EOL );
  
              String name = target.getName();
  
              int ind = name.lastIndexOf( '.' );
              String ct = null;
  
              if( ind > 0 )
              {
                  ct = ( String ) CONTENT_TYPE_MAP.get( name.substring( ind ) );
              }
              if( ct == null )
              {
                  ct = "unknown/unknown";
              }
  
              ps.print( "Content-type: " + ct );
              ps.write( EOL );
          }
  
          return ret;
      }
  
      private boolean isHead( final byte[] buffer )
      {
          return buffer[0] == ( byte ) 'H'
              && buffer[1] == ( byte ) 'E'
              && buffer[2] == ( byte ) 'A'
              && buffer[3] == ( byte ) 'D'
              && buffer[4] == ( byte ) ' ';
      }
  
      private boolean isGet( final byte[] buffer )
      {
          return buffer[0] == ( byte ) 'G'
              && buffer[1] == ( byte ) 'E'
              && buffer[2] == ( byte ) 'T'
              && buffer[3] == ( byte ) ' ';
      }
  
      private static void setSuffix( String k, String v )
      {
          CONTENT_TYPE_MAP.put( k, v );
      }
  
      private static void fillMap()
      {
          setSuffix( "", "content/unknown" );
          setSuffix( ".jar", "application/x-jar" );
          setSuffix( ".gif", "image/gif" );
          setSuffix( ".jpg", "image/jpeg" );
          setSuffix( ".jpeg", "image/jpeg" );
          setSuffix( ".htm", "text/html" );
          setSuffix( ".html", "text/html" );
          setSuffix( ".jnlp", "application/x-java-jnlp-file" );
      }
  }
  
  
  
  1.1                  jakarta-avalon-apps/phyre/src/java/org/apache/avalon/phyre/block/HttpConstants.java
  
  Index: HttpConstants.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.txt file.
   */
  package org.apache.avalon.phyre.block;
  
  /**
   * @author <a href="mailto:proyal@apache.org">Peter Royal</a>
   */
  interface HttpConstants
  {
      /** 2XX: generally "OK" */
      int HTTP_OK = 200;
      int HTTP_CREATED = 201;
      int HTTP_ACCEPTED = 202;
      int HTTP_NOT_AUTHORITATIVE = 203;
      int HTTP_NO_CONTENT = 204;
      int HTTP_RESET = 205;
      int HTTP_PARTIAL = 206;
  
      /** 3XX: relocation/redirect */
      int HTTP_MULT_CHOICE = 300;
      int HTTP_MOVED_PERM = 301;
      int HTTP_MOVED_TEMP = 302;
      int HTTP_SEE_OTHER = 303;
      int HTTP_NOT_MODIFIED = 304;
      int HTTP_USE_PROXY = 305;
  
      /** 4XX: client error */
      int HTTP_BAD_REQUEST = 400;
      int HTTP_UNAUTHORIZED = 401;
      int HTTP_PAYMENT_REQUIRED = 402;
      int HTTP_FORBIDDEN = 403;
      int HTTP_NOT_FOUND = 404;
      int HTTP_BAD_METHOD = 405;
      int HTTP_NOT_ACCEPTABLE = 406;
      int HTTP_PROXY_AUTH = 407;
      int HTTP_CLIENT_TIMEOUT = 408;
      int HTTP_CONFLICT = 409;
      int HTTP_GONE = 410;
      int HTTP_LENGTH_REQUIRED = 411;
      int HTTP_PRECON_FAILED = 412;
      int HTTP_ENTITY_TOO_LARGE = 413;
      int HTTP_REQ_TOO_LONG = 414;
      int HTTP_UNSUPPORTED_TYPE = 415;
  
      /** 5XX: server error */
      int HTTP_SERVER_ERROR = 500;
      int HTTP_INTERNAL_ERROR = 501;
      int HTTP_BAD_GATEWAY = 502;
      int HTTP_UNAVAILABLE = 503;
      int HTTP_GATEWAY_TIMEOUT = 504;
      int HTTP_VERSION = 505;
  }
  
  
  
  1.1                  jakarta-avalon-apps/phyre/src/java/org/apache/avalon/phyre/block/PhyreWebStartLoader-schema.xml
  
  Index: PhyreWebStartLoader-schema.xml
  ===================================================================
  <?xml version="1.0"?>
  <element name="root"
      xmlns="http://relaxng.org/ns/structure/1.0"
      datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes" >
      <interleave>
          <element name="bind"><text/></element>
          <optional>
              <element name="port">
                  <data type="integer"/>
              </element>
          </optional>
          <element name="handler">
              <element name="data-directory"><text/></element>
              <optional>
                  <element name="jnlp-file"><text/></element>
              </optional>
              <optional>
                  <element name="timeout">
                      <data type="integer"/>
                  </element>
              </optional>
          </element>
      </interleave>
  </element>
  
  
  
  1.1                  jakarta-avalon-apps/phyre/src/java/org/apache/avalon/phyre/block/PhyreWebStartLoader.java
  
  Index: PhyreWebStartLoader.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.txt file.
   */
  package org.apache.avalon.phyre.block;
  
  import java.net.InetAddress;
  import java.net.ServerSocket;
  import java.net.UnknownHostException;
  
  import org.apache.avalon.cornerstone.services.connection.AbstractHandlerFactory;
  import org.apache.avalon.cornerstone.services.connection.ConnectionHandler;
  import org.apache.avalon.cornerstone.services.connection.ConnectionHandlerFactory;
  import org.apache.avalon.cornerstone.services.connection.ConnectionManager;
  import org.apache.avalon.cornerstone.services.sockets.ServerSocketFactory;
  import org.apache.avalon.cornerstone.services.sockets.SocketManager;
  import org.apache.avalon.framework.activity.Startable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.service.ServiceException;
  import org.apache.avalon.framework.service.ServiceManager;
  
  /**
   * @author <a href="mailto:proyal@apache.org">Peter Royal</a>
   * @phoenix:block
   */
  public class PhyreWebStartLoader extends AbstractHandlerFactory
      implements Startable, ConnectionHandlerFactory
  {
      private static final String CONNECTION_NAME = "PhyreWebStartLoader";
  
      private SocketManager m_socketManager;
      private ConnectionManager m_connectionManager;
  
      private ServerSocket m_serverSocket;
  
      private int m_port;
      private InetAddress m_bindTo;
  
      /**
       * @phoenix:configuration-schema type="relax-ng"
       */
      public void configure( final Configuration configuration )
          throws ConfigurationException
      {
          super.configure( configuration.getChild( "handler" ) );
  
          m_port = configuration.getChild( "port" ).getValueAsInteger( 8008 );
  
          try
          {
              final String bindAddress = configuration.getChild( "bind" ).getValue();
              m_bindTo = InetAddress.getByName( bindAddress );
          }
          catch( final UnknownHostException unhe )
          {
              throw new ConfigurationException( "Malformed bind parameter", unhe );
          }
      }
  
      /**
       * @phoenix:dependency name="org.apache.avalon.cornerstone.services.sockets.SocketManager"
       * @phoenix:dependency name="org.apache.avalon.cornerstone.services.connection.ConnectionManager"
       */
      public void service( final ServiceManager serviceManager )
          throws ServiceException
      {
          super.service( serviceManager );
  
          m_socketManager = ( SocketManager ) serviceManager.lookup( SocketManager.ROLE );
          m_connectionManager = ( ConnectionManager ) serviceManager.lookup( ConnectionManager.ROLE );
      }
  
      public void start()
          throws Exception
      {
          final ServerSocketFactory factory = m_socketManager.getServerSocketFactory( "plain" );
  
          m_serverSocket = factory.createServerSocket( m_port, 5, m_bindTo );
          m_connectionManager.connect( CONNECTION_NAME, m_serverSocket, this );
      }
  
      public void stop() throws Exception
      {
          m_connectionManager.disconnect( CONNECTION_NAME );
          m_serverSocket.close();
      }
  
      protected ConnectionHandler newHandler()
          throws Exception
      {
          return new HttpConnectionHandler();
      }
  }
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>