Author: costin Date: Sat Feb 11 12:42:42 2006 New Revision: 377051 URL: http://svn.apache.org/viewcvs?rev=377051&view=rev Log: A couple of small improvements to the 'embeded' tomcat sandbox. Now it can work with only web.xml - or no xml files at all.
Added: tomcat/sandbox/java/org/apache/tomcat/standalone/ETomcat.java tomcat/sandbox/java/org/apache/tomcat/standalone/Main.java tomcat/sandbox/java/org/apache/tomcat/standalone/WebappsMain.java - copied, changed from r375161, tomcat/sandbox/java/org/apache/tomcat/standalone/Tomcat.java Removed: tomcat/sandbox/java/org/apache/tomcat/standalone/Tomcat.java Modified: tomcat/sandbox/.classpath tomcat/sandbox/build.xml tomcat/sandbox/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java tomcat/sandbox/resources/runtime.MF Modified: tomcat/sandbox/.classpath URL: http://svn.apache.org/viewcvs/tomcat/sandbox/.classpath?rev=377051&r1=377050&r2=377051&view=diff ============================================================================== --- tomcat/sandbox/.classpath (original) +++ tomcat/sandbox/.classpath Sat Feb 11 12:42:42 2006 @@ -2,11 +2,13 @@ <classpath> <classpathentry kind="src" path="java"/> <classpathentry kind="src" path="test"/> - <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> + <classpathentry combineaccessrules="false" kind="src" path="/container"/> <classpathentry combineaccessrules="false" kind="src" path="/connectors"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> <classpathentry kind="var" path="TOMCAT_LIBS_BASE/rhino1_6R2/js.jar"/> <classpathentry kind="var" path="TOMCAT_LIBS_BASE/junit3.8.1/junit.jar"/> <classpathentry kind="var" path="TOMCAT_LIBS_BASE/servlet-api-2.4/lib/servlet-api.jar"/> <classpathentry kind="var" path="TOMCAT_LIBS_BASE/commons-modeler-1.1/commons-modeler.jar"/> + <classpathentry kind="var" path="TOMCAT_LIBS_BASE/commons-el-1.0/commons-el.jar"/> <classpathentry kind="output" path="classes"/> </classpath> Modified: tomcat/sandbox/build.xml URL: http://svn.apache.org/viewcvs/tomcat/sandbox/build.xml?rev=377051&r1=377050&r2=377051&view=diff ============================================================================== --- tomcat/sandbox/build.xml (original) +++ tomcat/sandbox/build.xml Sat Feb 11 12:42:42 2006 @@ -11,8 +11,8 @@ <property name="tc55xbase" location=".." /> <!-- Source dependencies --> - <property name="target.vm" value="1.4"/> - <property name="source.vm" value="1.4"/> + <property name="target.vm" value="1.5"/> + <property name="source.vm" value="1.5"/> <property name="api.home" value="${tc55xbase}/servletapi"/> <property name="container.home" value="${tc55xbase}/container"/> <property name="jasper.home" value="${tc55xbase}/jasper"/> @@ -141,13 +141,14 @@ </target> <target name="compile-sandbox"> - <mkdir dir="${sandbox.home}/bin" /> + <mkdir dir="${sandbox.home}/classes" /> <javac destdir="${sandbox.home}/classes" source="${source.vm}" target="${target.vm}" deprecation="false" debug="false" > <src path="${sandbox.home}/java" /> <classpath> <path refid="runtime-deps" /> - <pathelement location="${connectors.home}/bin"/> + <pathelement location="${connectors.home}/bin"/> + <pathelement location="${container.home}/bin"/> </classpath> </javac> <copy todir="${sandbox.home}/classes" > @@ -195,24 +196,29 @@ </target> <target name="compile" - depends="compile-connectors,compile-sandbox,compile-container,compile-jasper"/> + depends="compile-connectors,compile-container,compile-sandbox,compile-jasper"/> <target name="clean-compile"> <delete dir="${container.home}/bin" includes="**"/> - <delete dir="${sandbox.home}/bin" includes="**"/> + <delete dir="${sandbox.home}/classes" includes="**"/> <delete dir="${connectors.home}/bin" includes="**"/> <delete dir="${jasper.home}/bin" includes="**"/> </target> - <target name="runtime" - description="Build single jar tomcat" depends="compile"> + <target name="tomcat-runtime.jar" + description="Build single jar tomcat" depends="compile,pack_tomcat-runtime.jar"> + </target> + + + <target name="pack_tomcat-runtime.jar" + description="Pack single jar tomcat" > <mkdir dir="runtime" /> <jar jarfile="runtime/tomcat-runtime.jar" manifest="resources/runtime.MF"> <fileset dir="${container.home}/bin" > <exclude name="org/apache/tomcat/util/buf/**"/> </fileset> - <fileset dir="${sandbox.home}/bin" > + <fileset dir="${sandbox.home}/classes" > <exclude name="org/apache/tomcat/util/net/Leader**"/> <exclude name="org/apache/tomcat/util/net/Master**"/> <exclude name="org/apache/tomcat/util/net/SSL**"/> @@ -221,6 +227,7 @@ <exclude name="org/apache/tomcat/util/net/Default**"/> </fileset> <fileset dir="${connectors.home}/bin" > + <exclude name="org/apache/coyote/http11/*"/> <exclude name="org/apache/tomcat/util/buf/**"/> <exclude name="org/apache/tomcat/util/net/jsse/**"/> <exclude name="org/apache/tomcat/util/threads/Expirer**"/> @@ -352,7 +359,7 @@ </target> - <target name="all" depends="tomcat-http11,runtime,runtime-all" /> + <target name="all" depends="tomcat-http11,tomcat-runtime.jar,runtime-all" /> <!-- ============ Download targets for deps ================ --> Modified: tomcat/sandbox/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java?rev=377051&r1=377050&r2=377051&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java (original) +++ tomcat/sandbox/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java Sat Feb 11 12:42:42 2006 @@ -5,6 +5,7 @@ import java.util.Vector; import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; @@ -14,7 +15,12 @@ * * If jasper is not found - i.e. runtime without jasper compiler - it'll * compute the mangled class name ( same code as jasper ) - * and invoke the jsp servlet directly. + * and invoke the jsp servlet directly. If the class is not found, it'll execute + * "jspc" and try again. + * + * + * + * TODO: test jspc, generate files in or out web-inf dir, modify web.xml * * @author Costin Manolache */ @@ -64,11 +70,33 @@ Class sC=Class.forName( mangledClass ); jsp=(HttpServlet)sC.newInstance(); } catch( Throwable t ) { + } + } + if(jsp == null) { + + } + // try again + if( jsp == null ) { + try { + Class sC=Class.forName( mangledClass ); + jsp=(HttpServlet)sC.newInstance(); + } catch( Throwable t ) { t.printStackTrace(); arg1.setStatus(404); } } jsp.service( req, arg1); + } + + private void compileJsp(ServletContext ctx, String jspPath) { + // Params to pass to jspc: + // classpath + + // webapp base dir + String baseDir = ctx.getRealPath("/"); + // jsp path ( rel. base dir ) + + } public void init(ServletConfig arg0) throws ServletException { Added: tomcat/sandbox/java/org/apache/tomcat/standalone/ETomcat.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/standalone/ETomcat.java?rev=377051&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/standalone/ETomcat.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/standalone/ETomcat.java Sat Feb 11 12:42:42 2006 @@ -0,0 +1,302 @@ +/* + */ +package org.apache.tomcat.standalone; + +import java.io.File; +import java.io.IOException; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; + +import org.apache.catalina.Context; +import org.apache.catalina.Lifecycle; +import org.apache.catalina.LifecycleEvent; +import org.apache.catalina.LifecycleListener; +import org.apache.catalina.connector.Connector; +import org.apache.catalina.core.StandardContext; +import org.apache.catalina.core.StandardEngine; +import org.apache.catalina.core.StandardHost; +import org.apache.catalina.core.StandardServer; +import org.apache.catalina.core.StandardService; +import org.apache.catalina.core.StandardWrapper; +import org.apache.catalina.deploy.LoginConfig; +import org.apache.catalina.session.StandardManager; + +/** + * Minimal tomcat starter for embedding. + * + * Tomcat supports multiple styles of configuration. + * + * 1. Classical server.xml, web.xml - see the Tomcat superclass. + * 2. Minimal tomcat, programatically configured, using regular webapps and web.xml + * 3. For apps that only need basic servlets, or have their own deployment mechanism - + * you can start tomcat without using web.xml + * + * Before people start screaming 'violation of the spec' - please read again the + * spec, web.xml is a mechanism for _deployment_. If you ship or deploy a webapp, it + * must have web.xml and all the war format. However the spec doesn't require the + * container to store the files in the same format or use the web.xml file - they + * added a lot of pain to the spec to make sure files could be stored in a database + * for example. + * + * In particular, storing the web.xml in a pre-parsed form, like a .ser file or + * a generated java class is (IMO) perfectly fine. One particular case of this is + * a hand-generated configurator - which is a good fit for apps that want to + * provide a HTTP interface and use servlets, but don't need all dynamic deployment + * and reconfiguration. + * + * In fact - if you don't use jsps or use precompiled jsps, you can leave most of the + * xml parsing overhead out of your app, and have a more minimal http server. + * + * This is provided as a base class and as an example - you can extend it, or just + * cut&paste or reuse methods. + * + * @author Costin Manolache + */ +public class ETomcat { + + protected StandardServer server; + protected StandardService service; + protected StandardEngine eng; + protected StandardHost host; + protected StandardContext ctx; + + /** Example main. You should extend ETomcat and call start() your own way. + */ + public static void main( String args[] ) { + try { + ETomcat etomcat = new ETomcat(); + + etomcat.initServer(null); + etomcat.initConnector(8000); + etomcat.initHost("localhost"); + etomcat.initWebapp("/", "."); + etomcat.initWebappDefaults(); + + etomcat.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void start() throws Exception { + server.initialize(); + server.start(); + } + + public StandardServer initServer(String baseDir) { + initHome(baseDir); + System.setProperty("catalina.useNaming", "false"); + + server = new StandardServer(); + server.setPort( -1 ); + + //ServerLifecycleListener jmxLoader = new ServerLifecycleListener(); + //server.addLifecycleListener(jmxLoader); + + service = new StandardService(); + server.addService( service ); + return server; + } + + /** Add a default http connector. + * + * Alternatively, you can construct a Connector and set any params, + * then call addConnector(Connector) + */ + public Connector initConnector(int port) throws Exception { + Connector connector = new Connector("HTTP/1.1"); + connector.setPort(port); + service.addConnector( connector ); + return connector; + } + + public void addConnector( Connector connector ) { + service.addConnector( connector ); + } + + /** Create a host. First host will be the default. + */ + public StandardHost initHost(String hostname) { + if(eng == null ) { + eng = new StandardEngine(); + eng.setName( "default" ); + eng.setDefaultHost(hostname); + service.setContainer(eng); + } + + + host = new StandardHost(); + host.setName(hostname); + + eng.addChild( host ); + return host; + } + + /** Initialize a webapp. + * + * You can customize the return value to support different web.xml features: + * + * context-param + * ctx.addParameter("name", "value"); + * + * + * error-page + * ErrorPage ep = new ErrorPage(); + * ep.setErrorCode(500); + * ep.setLocation("/error.html"); + * ctx.addErrorPage(ep); + * + * ctx.addMimeMapping("ext", "type"); + * + */ + public StandardContext initWebapp(String path, String dir) { + ctx = new StandardContext(); + ctx.setPath( path ); + ctx.setDocBase(dir); + + ctx.addLifecycleListener(new FixContextListener()); + + host.addChild(ctx); + return ctx; + } + + public void addWebapp(StandardContext ctx) { + this.ctx = ctx; + + ctx.addLifecycleListener(new FixContextListener()); + + host.addChild(ctx); + + } + + public void initWebappDefaults() { + // Default servlet + StandardWrapper defaultServletW = + initServlet("default", "org.apache.catalina.servlets.DefaultServlet"); + defaultServletW.addInitParameter("listings", "true"); + + initServlet("invoker", "org.apache.catalina.servlets.InvokerServlet"); + + initServlet("jsp", "org.apache.tomcat.servlets.jsp.JspProxyServlet"); + + ctx.addServletMapping("/", "default"); + ctx.addServletMapping("*.jsp", "jsp"); + ctx.addServletMapping("*.jspx", "jsp"); + ctx.addServletMapping("/servlet/*", "invoker"); + + + // Mime mappings: should read from /etc/mime.types on linux, or some + // resource + + + ctx.addWelcomeFile("index.html"); + ctx.addWelcomeFile("index.htm"); + ctx.addWelcomeFile("index.jsp"); + + ctx.setLoginConfig( new LoginConfig("NONE", null, null, null)); + + ctx.setManager( new StandardManager()); + } + + /** + * You can customize the returned servlet, ex: + * + * wrapper.addInitParameter("name", "value"); + */ + public StandardWrapper initServlet(String servletName, String servletClass) { + // will do class for name and set init params + StandardWrapper sw = (StandardWrapper)ctx.createWrapper(); + sw.setServletClass(servletClass); + sw.setName(servletName); + ctx.addChild(sw); + + return sw; + } + + /** Use an existing servlet, no class.forName or initialization will be + * performed + */ + public StandardWrapper initServlet(String servletName, Servlet servlet) { + // will do class for name and set init params + StandardWrapper sw = new ExistingStandardWrapper(servlet); + sw.setName(servletName); + ctx.addChild(sw); + + return sw; + } + + /** Init expected tomcat env. This is used as a base for the work directory. + * TODO: disable work dir if not needed ( no jsp, etc ). + * + * Also used as a base for webapps/ and config dirs, when used. + */ + private void initHome(String basedir) { + if( basedir != null ) { + System.setProperty("catalina.home", basedir); + System.setProperty("catalina.base", basedir); + } + String catalinaHome = System.getProperty("catalina.home"); + if(catalinaHome==null) { + catalinaHome=System.getProperty("user.dir"); + File home = new File(catalinaHome); + if (!home.isAbsolute()) { + try { + catalinaHome = home.getCanonicalPath(); + } catch (IOException e) { + catalinaHome = home.getAbsolutePath(); + } + } + System.setProperty("catalina.home", catalinaHome); + } + + if( System.getProperty("catalina.base") == null ) { + System.setProperty("catalina.base", catalinaHome); + } + } + + /** Fix startup sequence - required if you don't use web.xml. + * + * The start() method in context will set 'configured' to false - and + * expects a listener to set it back to true. + * + * @author Costin Manolache + */ + public static class FixContextListener implements LifecycleListener { + + public void lifecycleEvent(LifecycleEvent event) { + try { + Context context = (Context) event.getLifecycle(); + if (event.getType().equals(Lifecycle.START_EVENT)) { + context.setConfigured(true); + } + } catch (ClassCastException e) { + return; + } + } + + } + + /** Helper class for wrapping existing servlets. This disables servlet + * lifecycle and normal reloading, but also reduces overhead and provide + * more direct control over the servlet. + * + * @author Costin Manolache + */ + public static class ExistingStandardWrapper extends StandardWrapper { + private Servlet existing; + public ExistingStandardWrapper( Servlet existing ) { + this.existing = existing; + } + public synchronized Servlet loadServlet() throws ServletException { + return existing; + + } + public long getAvailable() { + return 0; + } + public boolean isUnavailable() { + return false; + } + } +} Added: tomcat/sandbox/java/org/apache/tomcat/standalone/Main.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/standalone/Main.java?rev=377051&view=auto ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/standalone/Main.java (added) +++ tomcat/sandbox/java/org/apache/tomcat/standalone/Main.java Sat Feb 11 12:42:42 2006 @@ -0,0 +1,52 @@ +/* + */ +package org.apache.tomcat.standalone; + +import java.lang.reflect.Method; + +/** Process CLI args and dispatch to the right launcher. + * + * First argument may be: + * + * -webapps - no server.xml or conf/ is used, you just need a webapps/ dir + * -app - no server.xml or webapps/ - you only need individual app dirs, only process + * web.xml. + * -etomcat - deeply embeded, no config file is used. Instead of web.xml it'll + * use programmatic settings. Experimental. + * -coyote - just the http adapter - will use Adapters. + * [ none of the above ] - old style Bootstrap, using server.xml + * + * Last 2 modes are for example - the typical use will be to cut&paste the start + * lines in your app and add the classes to your app jar(s). + * + * @author Costin Manolache + */ +public class Main { + + public static String HELP=""; + + public static void main(String args[]) { + if( args.length == 0 ) { + System.err.println(HELP); + return; + } + String dispatch = args[0]; + String launcher = "org.apache.catalina.startup.Bootstrap"; + if( "-webapps".equals(dispatch) ) { + launcher = "org.apache.tomcat.standalone.WebappsMain"; + } else if("-app".equals(dispatch)) { + launcher = "org.apache.tomcat.standalone.SimpleAppsMain"; + } else if("-etomcat".equals(dispatch)) { + launcher = "org.apache.tomcat.standalone.ETomcat"; + } else if("-coyote".equals(dispatch)) { + launcher = "org.apache.coyote.standalone.Main"; + } + try { + Class launcherClass = Class.forName(launcher); + Method main = launcherClass.getMethod("main", new Class[] { args.getClass() }); + main.invoke(null, new Object[] {args} ); + } catch( Throwable t ) { + t.printStackTrace(); + } + } +} Copied: tomcat/sandbox/java/org/apache/tomcat/standalone/WebappsMain.java (from r375161, tomcat/sandbox/java/org/apache/tomcat/standalone/Tomcat.java) URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/standalone/WebappsMain.java?p2=tomcat/sandbox/java/org/apache/tomcat/standalone/WebappsMain.java&p1=tomcat/sandbox/java/org/apache/tomcat/standalone/Tomcat.java&r1=375161&r2=377051&rev=377051&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/standalone/Tomcat.java (original) +++ tomcat/sandbox/java/org/apache/tomcat/standalone/WebappsMain.java Sat Feb 11 12:42:42 2006 @@ -2,73 +2,45 @@ */ package org.apache.tomcat.standalone; -import java.io.File; -import java.io.IOException; - -import org.apache.catalina.connector.Connector; -import org.apache.catalina.core.StandardEngine; import org.apache.catalina.core.StandardHost; -import org.apache.catalina.core.StandardServer; -import org.apache.catalina.core.StandardService; import org.apache.catalina.startup.HostConfig; -public class Tomcat { +/** + * Start tomcat using server.xml and web.xml and regular config files + * + * @author Costin Manolache + */ +public class WebappsMain extends ETomcat { public static void main( String args[] ) { try { - startTomcat(); + WebappsMain etomcat = new WebappsMain(); + + etomcat.initServer(null); + etomcat.initConnector(8000); + + // This will load all webapps, context configs, etc + etomcat.initAutoconfHost("localhost", "webapps"); + + etomcat.start(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } - private static void startTomcat() throws Exception { - String catalinaHome = System.getProperty("catalina.home"); - if(catalinaHome==null) { - catalinaHome=System.getProperty("user.dir"); - File home = new File(catalinaHome); - if (!home.isAbsolute()) { - try { - catalinaHome = home.getCanonicalPath(); - } catch (IOException e) { - catalinaHome = home.getAbsolutePath(); - } - } - System.setProperty("catalina.home", catalinaHome); - } - - if( System.getProperty("catalina.base") == null ) { - System.setProperty("catalina.base", catalinaHome); - } - System.setProperty("catalina.useNaming", "false"); - - StandardServer server = new StandardServer(); - server.setPort( -1 ); - //tc.setServer( server ); - - StandardService service = new StandardService(); - server.addService( service ); + public StandardHost initAutoconfHost(String hostName, String webappsBase) + { + host = new StandardHost(); + host.setName(hostName); - Connector connector = new Connector("HTTP/1.1"); - service.addConnector( connector ); - connector.setPort( 8000 ); - - StandardEngine eng = new StandardEngine(); - eng.setName( "default" ); - eng.setDefaultHost("localhost"); - service.setContainer(eng); - - StandardHost host = new StandardHost(); - host.setName( "localhost"); - host.setAppBase("webapps"); HostConfig hconfig = new HostConfig(); host.addLifecycleListener( hconfig ); - - eng.addChild( host ); - server.initialize(); - - server.start(); + host.setAppBase(webappsBase); + + eng.addChild(host); + return host; } + } Modified: tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java?rev=377051&r1=377050&r2=377051&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java (original) +++ tomcat/sandbox/java/org/apache/tomcat/util/buf/ByteChunk.java Sat Feb 11 12:42:42 2006 @@ -34,28 +34,37 @@ * to be able to parse the request without converting to string. */ -// TODO: This class could either extend ByteBuffer, or better a ByteBuffer inside -// this way it could provide the search/etc on ByteBuffer, as a helper. - /** * This class is used to represent a chunk of bytes, and - * utilities to manipulate byte[]. + * utilities to manipulate bytes. * * The buffer can be modified and used for both input and output. * - * There are 2 modes: The chunk can be associated with a sink - ByteInputChannel or ByteOutputChannel, - * which will be used when the buffer is empty ( on input ) or filled ( on output ). - * For output, it can also grow. This operating mode is selected by calling setLimit() or - * allocate(initial, limit) with limit != -1. + * There are 3 modes: + * + * 1. Wrapping a chunk from another buffer. This was the original use and is the + * most common use - for example in headers. Typically there is an associated + * CharChunk and MessageBytes for the char[] representation - but many buffers + * will not be converted or will be converted just before use. + * + * 2. For input, associated with a ByteInputChannel ( or ReadableByteChannel ), + * which will be called automatically when the buffer is emtpy. This is used for + * the input stream and for the header buffer ( which will be later wrapped in many + * ByteChunks ) + * + * 3. For output, associated ( or not ) with a ByteOutputChannel. The buffer + * can grow up to a limit ( and will stay allocated to that limit ). When the limit + * is reached, the channel is used. * * Various search and append method are defined - similar with String and StringBuffer, but * operating on bytes. + * + * In addition, append and substract are used in 2 and 3. * * This is important because it allows processing the http headers directly on the received bytes, * without converting to chars and Strings until the strings are needed. In addition, the charset * is determined later, from headers or user code. * - * * @author [EMAIL PROTECTED] * @author James Todd [EMAIL PROTECTED] * @author Costin Manolache @@ -66,6 +75,7 @@ /** Input interface, used when the buffer is emptiy * * Same as java.nio.channel.ReadableByteChannel + * @deprecated */ public static interface ByteInputChannel { /** @@ -78,6 +88,7 @@ } /** Same as java.nio.channel.WrittableByteChannel. + * @deprecated */ public static interface ByteOutputChannel { /** @@ -95,38 +106,83 @@ 8859_1, and this object is used mostly for servlets. */ public static final String DEFAULT_CHARACTER_ENCODING="ISO-8859-1"; - - // byte[] - //private byte[] buff; + + // By default in read mode - there are fewer uses of ByteChunk for output. + // (In most cases it's wrapping existing data) + // + // So start == 0, end == limit. Position is not used. + // + // if isOutout==true - the buffer is used for output. It must be released(). private ByteBuffer bb; + private boolean isSet=false; // == ! isNull + - private int start=0; - private int end; + private int start=0; // used as ByteBuffer.offset and position + private int end; // used as limit + // not sure it's good to have it here, MessageBytes should deal with this private String enc; - private boolean isSet=false; // XXX - - // How much can it grow, when data is added - private int limit=-1; + // Probably not needed if callers respect the rules - but good to debug. + private boolean inUse = false; // direct access to bb + private boolean isOutput=false; // byte buffer in output mode + private int mode = 0; + //private boolean optimizedWrite=true; + + // How much can it grow, when data is added. Different from the bb limit, + // this is how much we can resize the bb before flushing. + private int growLimit=-1; + // maybe a single in/out channel would be better. private ByteInputChannel in = null; private ByteOutputChannel out = null; - private boolean isOutput=false; - private boolean optimizedWrite=true; - + /* + + // experiment: specific structure for 2. and 3. + static class ByteData { + Channel channel; // or in, out + + int growLimit = -1; + String enc; // no need to have it in wrapped buffers + + } + private ByteData byteData; + */ /** * Creates a new, uninitialized ByteChunk object. */ public ByteChunk() { } - public ByteChunk( int initial ) { - allocate( initial, -1 ); - } - //-------------------- + + public ByteBuffer getBuffer(boolean forWrite) { + inUse = true; + if( forWrite ) { + isOutput = true; + // all methods except append should throw exceptions ! + // start - end are existing data, end is growing on append + // also, start is supposed to be 0 ( or offeset ? ) + bb.position(end); + bb.limit(bb.capacity()); + } + return bb; + } + + public void releaseBuffer() { + if( isOutput ) { + isOutput = false; + // start remain the same ( probably 0 ) + end = bb.position(); + // flip bb for reading + bb.limit(bb.position()); + bb.position(0); + } + inUse = false; + } + + public ByteChunk getClone() { try { return (ByteChunk)this.clone(); @@ -136,18 +192,21 @@ } public boolean isNull() { - return ! isSet; // buff==null; + return ! isSet; } /** * Resets the message buff to an uninitialized state. */ public void recycle() { - // buff = null; enc=null; start=0; end=0; isSet=false; + if( bb != null) bb.clear(); + inUse = false; + // mode remains - it shouldn't change + isOutput = false; } public void reset() { @@ -156,20 +215,41 @@ // -------------------- Setup -------------------- + /** + * Prealocate a buffer. + * Called by C2B, BufferedInputFilter ( mode 2 ), catalina InputBuffer + * and OutputBuffe, + * + * @param initial + */ + public ByteChunk( int initial ) { + allocate( initial, -1 ); + } + + /** Used for 2. and 3. - allocate the buffer. + * + * Called by InternalOutputBuffer, C2B ( for out ). + * + * Called by MessageBytes ( out mode ) to hold decoded uri, other temp + * storages for request ( long, etc ) + */ public void allocate( int initial, int limit ) { isOutput=true; if( bb==null || bb.capacity() < initial ) { //buff=new byte[initial]; bb=ByteBuffer.allocate(initial); } - this.limit=limit; + this.growLimit=limit; start=0; end=0; isSet=true; + mode = 4; // will set to 2 or 3 on first op. + //new Throwable().printStackTrace(); } /** * Sets the message bytes to the specified subarray of bytes. + * Used for 1. * * @param b the ascii bytes * @param off the start offset of the bytes @@ -178,18 +258,27 @@ public void setBytes(byte[] b, int off, int len) { //buff = b; bb=ByteBuffer.wrap( b, off, len ); - start = off; + start = off; // also offset in bb. + // bb.arrayOffset() == off == start; end = start+ len; isSet=true; + if( mode > 1 ) { + System.err.println("Old mode: " + mode); + new Throwable().printStackTrace(); + } + mode = 1; } - public void setOptimizedWrite(boolean optimizedWrite) { - this.optimizedWrite = optimizedWrite; - } + // -------------------------------------- + // Doesn't seem to be used - and it shouldn't be + //public void setOptimizedWrite(boolean optimizedWrite) { + // this.optimizedWrite = optimizedWrite; + //} public void setEncoding( String enc ) { this.enc=enc; } + public String getEncoding() { if (enc == null) enc=DEFAULT_CHARACTER_ENCODING; @@ -243,11 +332,11 @@ * or throw exception. */ public void setLimit(int limit) { - this.limit=limit; + this.growLimit=limit; } public int getLimit() { - return limit; + return growLimit; } /** @@ -275,6 +364,8 @@ } // -------------------- Adding data to the buffer -------------------- + // this is mode 3. + /** Append a char, by casting it to byte. This IS NOT intended for unicode. * * @param c @@ -292,11 +383,11 @@ makeSpace( 1 ); // couldn't make space - if( limit >0 && end >= limit ) { + if( growLimit >0 && end >= growLimit ) { flushBuffer(); } //buff[end++]=b; - bb.put(end++, b); + bb.array()[end++] = b; } public void append( ByteChunk src ) @@ -314,7 +405,7 @@ makeSpace( len ); // if we don't have limit: makeSpace can grow as it wants - if( limit < 0 ) { + if( growLimit < 0 ) { // assert: makeSpace made enough space System.arraycopy( src, off, bb.array(), end, len ); end+=len; @@ -325,12 +416,12 @@ // If the buffer is empty and the source is going to fill up all the // space in buffer, may as well write it directly to the output, // and avoid an extra copy - if ( optimizedWrite && len == limit && end == start) { + if ( /*optimizedWrite &&*/ len == growLimit && end == start) { out.realWriteBytes( src, off, len ); return; } // if we have limit and we're below - if( len <= limit - end ) { + if( len <= growLimit - end ) { // makeSpace will grow the buffer to the limit, // so we have space System.arraycopy( src, off, bb.array(), end, len ); @@ -346,7 +437,7 @@ // We chunk the data into slices fitting in the buffer limit, although // if the data is written directly if it doesn't fit - int avail=limit-end; + int avail=growLimit-end; System.arraycopy(src, off, bb.array(), end, avail); end += avail; @@ -354,9 +445,9 @@ int remain = len - avail; - while (remain > (limit - end)) { - out.realWriteBytes( src, (off + len) - remain, limit - end ); - remain = remain - (limit - end); + while (remain > (growLimit - end)) { + out.realWriteBytes( src, (off + len) - remain, growLimit - end ); + remain = remain - (growLimit - end); } System.arraycopy(src, (off + len) - remain, bb.array(), end, remain); @@ -364,12 +455,96 @@ } + /** Send the buffer to the sink. Called by append() when the limit is reached. + * You can also call it explicitely to force the data to be written. + * + * @throws IOException + */ + public void flushBuffer() + throws IOException + { + //assert out!=null + if( out==null ) { + throw new IOException( "Buffer overflow, no sink " + growLimit + " " + + bb.capacity() ); + } + out.realWriteBytes( bb.array(), start, end-start ); + end=start; + } + - // -------------------- Removing data from the buffer -------------------- + /** Make space for len chars. If len is small, allocate + * a reserve space too. Never grow bigger than limit. + */ + private void makeSpace(int count) + { + // all appends call make space + if( mode != 3 ) { + if( mode == 4 ) { + mode = 3; + } else { // mode change + new Throwable().printStackTrace(); + } + + } + + ByteBuffer tmp = null; + + int newSize; + int desiredSize=end + count; + + // Can't grow above the limit + if( growLimit > 0 && + desiredSize > growLimit) { + desiredSize=growLimit; + } + + if( bb==null ) { + if( desiredSize < 256 ) desiredSize=256; // take a minimum + bb=ByteBuffer.allocate(desiredSize); + } + + // limit < buf.length ( the buffer is already big ) + // or we already have space XXX + if( desiredSize <= bb.capacity() ) { + return; + } + // grow in larger chunks + if( desiredSize < 2 * bb.capacity() ) { + newSize= bb.capacity() * 2; + if( growLimit >0 && + newSize > growLimit ) newSize=growLimit; + } else { + newSize= bb.capacity() * 2 + count ; + if( growLimit > 0 && + newSize > growLimit ) newSize=growLimit; + } + tmp=ByteBuffer.allocate(newSize); + + System.arraycopy(bb.array(), start, tmp.array(), 0, end-start); + bb = tmp; + tmp = null; + end=end-start; + start=0; + } + // -------------------- Removing data from the buffer -------------------- + // mode 2. + private void checkMode2() { + if( mode != 2 ) { + if( mode == 4 ) { + System.err.println("Mode 2 buffer"); + mode = 2; + } else { // mode change + new Throwable().printStackTrace(); + } + } + } + public int substract() throws IOException { + checkMode2(); if ((end - start) == 0) { if (in == null) return -1; @@ -378,13 +553,14 @@ return -1; } - return (bb.get(start++) & 0xFF); + return (bb.array()[start++] & 0xFF); } public int substract(ByteChunk src) throws IOException { + checkMode2(); if ((end - start) == 0) { if (in == null) return -1; @@ -403,6 +579,7 @@ public int substract( byte src[], int off, int len ) throws IOException { + checkMode2(); if ((end - start) == 0) { if (in == null) return -1; @@ -418,74 +595,12 @@ System.arraycopy(bb.array(), start, src, off, n); start += n; return n; - - } - - - /** Send the buffer to the sink. Called by append() when the limit is reached. - * You can also call it explicitely to force the data to be written. - * - * @throws IOException - */ - public void flushBuffer() - throws IOException - { - //assert out!=null - if( out==null ) { - throw new IOException( "Buffer overflow, no sink " + limit + " " + - bb.capacity() ); - } - out.realWriteBytes( bb.array(), start, end-start ); - end=start; } - /** Make space for len chars. If len is small, allocate - * a reserve space too. Never grow bigger than limit. - */ - private void makeSpace(int count) - { - ByteBuffer tmp = null; - - int newSize; - int desiredSize=end + count; - - // Can't grow above the limit - if( limit > 0 && - desiredSize > limit) { - desiredSize=limit; - } - - if( bb==null ) { - if( desiredSize < 256 ) desiredSize=256; // take a minimum - bb=ByteBuffer.allocate(desiredSize); - } - - // limit < buf.length ( the buffer is already big ) - // or we already have space XXX - if( desiredSize <= bb.capacity() ) { - return; - } - // grow in larger chunks - if( desiredSize < 2 * bb.capacity() ) { - newSize= bb.capacity() * 2; - if( limit >0 && - newSize > limit ) newSize=limit; - } else { - newSize= bb.capacity() * 2 + count ; - if( limit > 0 && - newSize > limit ) newSize=limit; - } - tmp=ByteBuffer.allocate(newSize); - - System.arraycopy(bb.array(), start, tmp.array(), 0, end-start); - bb = tmp; - tmp = null; - end=end-start; - start=0; - } // -------------------- Conversion and getters -------------------- - + // all modes + public String toString() { if (null == bb.array()) { return null; @@ -685,7 +800,7 @@ int srcEnd = srcOff + srcLen; for( int i=myOff+start; i <= (end - srcLen); i++ ) { - if( bb.get(i) != first ) continue; + if( bb.array()[i] != first ) continue; // found first char, now look for a match int myPos=i+1; @@ -694,15 +809,11 @@ break; } - try { - for( int srcPos=srcOff + 1; srcPos< srcEnd; ) { - if( bb.get(myPos++) != src.charAt( srcPos++ )) + for( int srcPos=srcOff + 1; srcPos< srcEnd; ) { + if( bb.array()[myPos++] != src.charAt( srcPos++ )) break; if( srcPos==srcEnd ) return i-start; // found it } - } catch( Throwable t ) { - t.printStackTrace(); - } } return -1; } Modified: tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java URL: http://svn.apache.org/viewcvs/tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java?rev=377051&r1=377050&r2=377051&view=diff ============================================================================== --- tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java (original) +++ tomcat/sandbox/java/org/apache/tomcat/util/net/SimpleEndpoint.java Sat Feb 11 12:42:42 2006 @@ -170,33 +170,6 @@ serverSocket = null; } - protected void unlockAccept() { - Socket s = null; - try { - // Need to create a connection to unlock the accept(); - if (inet == null) { - s = new Socket("127.0.0.1", port); - } else { - s = new Socket(inet, port); - // setting soLinger to a small value will help shutdown the - // connection quicker - s.setSoLinger(true, 0); - } - } catch(Exception e) { - if (log.isDebugEnabled()) { - log.debug(sm.getString("endpoint.debug.unlock", "" + port), e); - } - } finally { - if (s != null) { - try { - s.close(); - } catch (Exception e) { - // Ignore - } - } - } - } - // -------------------- Private methods Socket acceptSocket() { Modified: tomcat/sandbox/resources/runtime.MF URL: http://svn.apache.org/viewcvs/tomcat/sandbox/resources/runtime.MF?rev=377051&r1=377050&r2=377051&view=diff ============================================================================== --- tomcat/sandbox/resources/runtime.MF (original) +++ tomcat/sandbox/resources/runtime.MF Sat Feb 11 12:42:42 2006 @@ -1,5 +1,3 @@ -Manifest-Version: 1.0 -Ant-Version: Apache Ant 1.6.2 -Created-By: 1.5.0-b64 (Sun Microsystems Inc.) -Main-Class: org.apache.catalina.startup.Bootstrap - +Manifest-Version: 1.0 +Main-Class: org.apache.tomcat.standalone.Main + --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]