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>