costin 02/01/11 20:10:14 Added: jk/java/org/apache/jk/server/tomcat40 JkConnector.java JkRequest40.java JkResponse40.java Worker40.java Log: Jk2-style connector for 4.0. I couldn't find any way to make it work as a servlet ( class loader is a nightmare ), so JkConnector must be added to server.xml and the jar files must be copied. However we do use the JkServlet and web.xml for all the config - so configuration will be identical and more importanly standard webapp tools ( and knowledge ) can be used. Of course, there are other options as well - server.xml settings, workers.properties ( I'll try this later - it would be a nice idea to jave a single file for both C and java, and set things like port only there ). Webapp features like reloading ( or hot update, etc ) will probably not work with 4.0 ( probably not very usefull for most people anyway ). Revision Changes Path 1.1 jakarta-tomcat-connectors/jk/java/org/apache/jk/server/tomcat40/JkConnector.java Index: JkConnector.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.jk.server.tomcat40; import java.io.*; import java.net.*; import java.security.*; import java.util.*; import org.apache.catalina.*; import org.apache.catalina.core.*; import org.apache.catalina.net.DefaultServerSocketFactory; import org.apache.catalina.net.ServerSocketFactory; import org.apache.catalina.util.LifecycleSupport; import org.apache.catalina.util.StringManager; import org.apache.jk.server.*; import org.apache.catalina.jk.*; /** * Implementation of an Jk connector. * * @author Kevin Seguin * @author Costin Manolache */ public final class JkConnector implements Connector, Lifecycle { /** * The Container used for processing requests received by this Connector. */ protected Container container = null; protected LifecycleSupport lifecycle = new LifecycleSupport(this); private boolean started = false; private boolean stopped = false; private Service service = null; // ------------------------------------------------------------- Properties /** * Return the Container used for processing requests received by this * Connector. */ public Container getContainer() { return container; } /** * Set the Container used for processing requests received by this * Connector. * * @param container The new Container to use */ public void setContainer(Container container) { this.container = container; } /** * Return descriptive information about this Connector implementation. */ public String getInfo() { return "JkConnector/2.0dev"; } /** * Returns the <code>Service</code> with which we are associated. */ public Service getService() { return service; } /** * Set the <code>Service</code> with which we are associated. */ public void setService(Service service) { this.service = service; } // --------------------------------------------------------- Public Methods /** * Invoke a pre-startup initialization. This is used to allow connectors * to bind to restricted ports under Unix operating environments. * ServerSocket (we start as root and change user? or I miss something?). */ public void initialize() throws LifecycleException { } // ------------------------------------------------------ Lifecycle Methods /** * Add a lifecycle event listener to this component. * * @param listener The listener to add */ public void addLifecycleListener(LifecycleListener listener) { lifecycle.addLifecycleListener(listener); } /** * Get the lifecycle listeners associated with this lifecycle. If this * Lifecycle has no listeners registered, a zero-length array is returned. */ public LifecycleListener[] findLifecycleListeners() { return null; // FIXME: lifecycle.findLifecycleListeners(); } /** * Remove a lifecycle event listener from this component. * * @param listener The listener to add */ public void removeLifecycleListener(LifecycleListener listener) { lifecycle.removeLifecycleListener(listener); } Properties props=new Properties(); /** * Begin processing requests via this Connector. * * @exception LifecycleException if a fatal startup error occurs */ public void start() throws LifecycleException { JkConfig40 config=new JkConfig40(); lifecycle.fireLifecycleEvent(START_EVENT, null); if( dL > 0 ) d( "Start " + container + " " + service ); Worker40 worker=new Worker40(); Container ct=service.getContainer(); worker.setContainer( ct ); ((ContainerBase)ct).addLifecycleListener(config); config.loadExisting( ct ); JkMain jkMain=new JkMain(); jkMain.setProperties( props ); jkMain.setDefaultWorker( worker ); String catalinaHome=System.getProperty("catalina.home"); File f=new File( catalinaHome ); File jkHomeF=new File( f, "webapps/jk" ); d("Setting jkHome " + jkHomeF ); jkMain.setJkHome( jkHomeF.getAbsolutePath() ); try { jkMain.start(); } catch( Exception ex ) { ex.printStackTrace(); } } /** * Terminate processing requests via this Connector. * * @exception LifecycleException if a fatal shutdown error occurs */ public void stop() throws LifecycleException { lifecycle.fireLifecycleEvent(STOP_EVENT, null); } private static final int dL=10; private static void d(String s ) { System.err.println( "JkConnector: " + s ); } // -------------------- Not used -------------------- public void setConnectionTimeout(int connectionTimeout) {} public boolean getEnableLookups() { return false;} public void setEnableLookups(boolean enableLookups) {} public org.apache.catalina.net.ServerSocketFactory getFactory() { return null; } public void setFactory(org.apache.catalina.net.ServerSocketFactory s) {} public int getRedirectPort() { return -1; } public void setRedirectPort(int i ) {} public java.lang.String getScheme() { return null; } public void setScheme(java.lang.String s ) {} public boolean getSecure() { return false; } public void setSecure(boolean b) {} public org.apache.catalina.Request createRequest() { return null; } public org.apache.catalina.Response createResponse() { return null; } } 1.1 jakarta-tomcat-connectors/jk/java/org/apache/jk/server/tomcat40/JkRequest40.java Index: JkRequest40.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.jk.server.tomcat40; import java.io.*; import java.util.List; import java.util.Iterator; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.Cookie; import org.apache.catalina.connector.*; import org.apache.catalina.*; import org.apache.catalina.util.RequestUtil; import org.apache.tomcat.util.buf.MessageBytes; import org.apache.tomcat.util.http.Cookies; import org.apache.tomcat.util.http.ServerCookie; import org.apache.tomcat.util.http.BaseRequest; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.jk.core.*; import org.apache.jk.common.*; public class JkRequest40 extends HttpRequestBase { private static final String match = ";" + Globals.SESSION_PARAMETER_NAME + "="; private static int id = 1; Channel ch; Endpoint ep; public JkRequest40() { super(); } public void recycle() { // save response - we're a pair Response res=response; super.recycle(); response=res; } public void setEndpoint( Channel ch, Endpoint ep ) { this.ch=ch; this.ep=ep; } void setBaseRequest(BaseRequest ajp) throws UnsupportedEncodingException { // XXX make this guy wrap AjpRequest so // we're more efficient (that's the whole point of // all of the MessageBytes in AjpRequest) setMethod(ajp.method().toString()); setProtocol(ajp.protocol().toString()); setRequestURI(ajp.requestURI().toString()); setRemoteAddr(ajp.remoteAddr().toString()); setRemoteHost(ajp.remoteHost().toString()); setServerName(ajp.serverName().toString()); setServerPort(ajp.getServerPort()); String remoteUser = ajp.remoteUser().toString(); if (remoteUser != null) { setUserPrincipal(new Ajp13Principal(remoteUser)); } setAuthType(ajp.authType().toString()); setQueryString(ajp.queryString().toString()); setScheme(ajp.getScheme()); setSecure(ajp.getSecure()); setContentLength(ajp.getContentLength()); String contentType = ajp.contentType().toString(); if (contentType != null) { setContentType(contentType); } MimeHeaders mheaders = ajp.headers(); int nheaders = mheaders.size(); for (int i = 0; i < nheaders; ++i) { MessageBytes name = mheaders.getName(i); MessageBytes value = mheaders.getValue(i); addHeader(name.toString(), value.toString()); } Iterator itr = ajp.getAttributeNames(); while (itr.hasNext()) { String name = (String)itr.next(); setAttribute(name, ajp.getAttribute(name)); } addCookies(ajp.cookies()); } // public Object getAttribute(String name) { // return ajp.getAttribute(name); // } // public Enumeration getAttributeNames() { // return new Enumerator(ajp.getAttributeNames()); // } public void setRequestURI(String uri) { int semicolon = uri.indexOf(match); if (semicolon >= 0) { String rest = uri.substring(semicolon + match.length()); int semicolon2 = rest.indexOf(";"); if (semicolon2 >= 0) { setRequestedSessionId(rest.substring(0, semicolon2)); rest = rest.substring(semicolon2); } else { setRequestedSessionId(rest); rest = ""; } setRequestedSessionURL(true); uri = uri.substring(0, semicolon) + rest; if (dL > 0) d(" Requested URL session id is " + ((HttpServletRequest) getRequest()) .getRequestedSessionId()); } else { setRequestedSessionId(null); setRequestedSessionURL(false); } super.setRequestURI(uri); } private void addCookies(Cookies cookies) { int ncookies = cookies.getCookieCount(); for (int j = 0; j < ncookies; j++) { ServerCookie scookie = cookies.getCookie(j); Cookie cookie = new Cookie(scookie.getName().toString(), scookie.getValue().toString()); if (cookie.getName().equals(Globals.SESSION_COOKIE_NAME)) { // Override anything requested in the URL if (!isRequestedSessionIdFromCookie()) { // Accept only the first session id cookie setRequestedSessionId(cookie.getValue()); setRequestedSessionCookie(true); setRequestedSessionURL(false); if (dL > 0) d(" Requested cookie session id is " + ((HttpServletRequest) getRequest()) .getRequestedSessionId()); } } if (dL > 0) { d(" Adding cookie " + cookie.getName() + "=" + cookie.getValue()); } addCookie(cookie); } } public ServletInputStream createInputStream() throws IOException { return (ServletInputStream)getStream(); } private static final int dL=0; private static void d(String s ) { System.err.println( "JkRequest40: " + s ); } } class Ajp13Principal implements java.security.Principal { String user; Ajp13Principal(String user) { this.user = user; } public boolean equals(Object o) { if (o == null) { return false; } else if (!(o instanceof Ajp13Principal)) { return false; } else if (o == this) { return true; } else if (this.user == null && ((Ajp13Principal)o).user == null) { return true; } else if (user != null) { return user.equals( ((Ajp13Principal)o).user); } else { return false; } } public String getName() { return user; } public int hashCode() { if (user == null) return 0; else return user.hashCode(); } public String toString() { return getName(); } } class JkInputStream extends InputStream { JkInputStream() { } public int available() throws IOException { return 0; } public void close() throws IOException { } public void mark(int readLimit) { } public boolean markSupported() { return false; } public void reset() throws IOException { throw new IOException("reset() not supported"); } byte singleRead[]=new byte[1]; public int read() throws IOException { int rc=read( singleRead, 0, 1 ); if( rc== 1 ) return singleRead[0]; return -1; } public int read(byte[] b, int off, int len) throws IOException { return -1;// ajp13.doRead(b, off, len); } public long skip(long n) throws IOException { if (n > Integer.MAX_VALUE) { throw new IOException("can't skip than many: " + n); } // XXX if n is big, split this in multiple reads byte[] b = new byte[(int)n]; return read(b, 0, b.length); } } 1.1 jakarta-tomcat-connectors/jk/java/org/apache/jk/server/tomcat40/JkResponse40.java Index: JkResponse40.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.jk.server.tomcat40; import java.io.*; import java.util.Iterator; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.apache.catalina.connector.HttpResponseBase; import org.apache.catalina.*; import org.apache.catalina.util.CookieTools; import org.apache.jk.core.*; import org.apache.jk.common.*; import org.apache.tomcat.util.http.MimeHeaders; public class JkResponse40 extends HttpResponseBase { private boolean finished = false; private boolean headersSent = false; private MimeHeaders headers = new MimeHeaders(); private StringBuffer cookieValue = new StringBuffer(); Channel ch; Endpoint ep; int headersMsgNote; int utfC2bNote; public JkResponse40(WorkerEnv we) { super(); headersMsgNote=we.getNoteId( WorkerEnv.ENDPOINT_NOTE, "headerMsg" ); utfC2bNote=we.getNoteId( WorkerEnv.ENDPOINT_NOTE, "utfC2B" ); } String getStatusMessage() { return getStatusMessage(getStatus()); } public void recycle() { // We're a pair - preserve Request req=request; super.recycle(); request=req; this.finished = false; this.headersSent = false; this.stream=null; this.headers.recycle(); } protected void sendHeaders() throws IOException { if( dL>0 ) d("sendHeaders " + headersSent); if (headersSent) { // don't send headers twice return; } headersSent = true; int numHeaders = 0; if (getContentType() != null) { numHeaders++; } if (getContentLength() >= 0) { numHeaders++; } // Add the session ID cookie if necessary HttpServletRequest hreq = (HttpServletRequest)request.getRequest(); HttpSession session = hreq.getSession(false); if ((session != null) && session.isNew() && (getContext() != null) && getContext().getCookies()) { Cookie cookie = new Cookie(Globals.SESSION_COOKIE_NAME, session.getId()); cookie.setMaxAge(-1); String contextPath = null; if (context != null) contextPath = context.getPath(); if ((contextPath != null) && (contextPath.length() > 0)) cookie.setPath(contextPath); else cookie.setPath("/"); if (hreq.isSecure()) cookie.setSecure(true); addCookie(cookie); } // Send all specified cookies (if any) synchronized (cookies) { Iterator items = cookies.iterator(); while (items.hasNext()) { Cookie cookie = (Cookie) items.next(); cookieValue.delete(0, cookieValue.length()); CookieTools.getCookieHeaderValue(cookie, cookieValue); addHeader(CookieTools.getCookieHeaderName(cookie), cookieValue.toString()); } } // figure out how many headers... // can have multiple headers of the same name... // need to loop through headers once to get total // count, once to add header to outBuf String[] hnames = getHeaderNames(); Object[] hvalues = new Object[hnames.length]; int i; for (i = 0; i < hnames.length; ++i) { String[] tmp = getHeaderValues(hnames[i]); numHeaders += tmp.length; hvalues[i] = tmp; } C2B c2b=(C2B)ep.getNote( utfC2bNote ); if( c2b==null ) { c2b=new C2B( "UTF8" ); ep.setNote( utfC2bNote, c2b ); } if( dL>0 ) d("sendHeaders " + numHeaders ); MsgAjp msg=(MsgAjp)ep.getNote( headersMsgNote ); msg.reset(); msg.appendByte(HandlerRequest.JK_AJP13_SEND_HEADERS); msg.appendInt( getStatus() ); c2b.convert( getStatusMessage(getStatus())); c2b.flushBuffer(); msg.appendByteChunk(c2b.getByteChunk()); c2b.recycle(); String contentType=getContentType(); int cl=getContentLength(); msg.appendInt(numHeaders); if ( contentType != null) { sendHeader(msg, c2b, "Content-Type", contentType ); } if ( cl >= 0) { sendHeader(msg, c2b, "Content-Length", String.valueOf(cl)); } // XXX do we need this ? If so, we need to adjust numHeaders // and avoid duplication for (i = 0; i < hnames.length; ++i) { String name = hnames[i]; String[] values = (String[])hvalues[i]; for (int j = 0; j < values.length; ++j) { sendHeader( msg, c2b, name, values[j] ); } } msg.send( ch, ep ); // The response is now committed committed = true; } private void sendHeader( Msg msg, C2B c2b, String n, String v ) throws IOException { if( dL > 0 ) d( "SendHeader " + n + " " + v ); c2b.convert( n ); c2b.flushBuffer(); msg.appendByteChunk(c2b.getByteChunk()); c2b.recycle(); c2b.convert( v ); c2b.flushBuffer(); msg.appendByteChunk(c2b.getByteChunk()); c2b.recycle(); } public void finishResponse() throws IOException { if( dL>0 ) d("finishResponse " + this.finished ); if(!this.finished) { super.finishResponse(); this.finished = true; // Avoid END_OF_RESPONSE sent 2 times MsgAjp msg=(MsgAjp)ep.getNote( headersMsgNote ); msg.reset(); msg.appendByte( HandlerRequest.JK_AJP13_END_RESPONSE ); msg.appendInt( 1 ); msg.send(ch, ep ); } } public void write(byte b[], int off, int len ) throws IOException { if( dL>0 ) d("write " + len); if( !headersSent ) sendHeaders(); MsgAjp msg=(MsgAjp)ep.getNote( headersMsgNote ); msg.reset(); msg.appendByte( HandlerRequest.JK_AJP13_SEND_BODY_CHUNK); msg.appendBytes( b, off, len ); msg.send( ch, ep ); } void setEndpoint(Channel ch, Endpoint ep) { this.ch=ch; this.ep=ep; MsgAjp msg=(MsgAjp)ep.getNote( headersMsgNote ); if( msg==null ) { msg=new MsgAjp(); ep.setNote( headersMsgNote, msg ); } setStream( new JkOutputStream( this )); } private static final int dL=10; private static void d(String s ) { System.err.println( "JkResponse40: " + s ); } } class JkOutputStream extends OutputStream { JkResponse40 resp; JkOutputStream(JkResponse40 resp) { this.resp=resp; } //XXX buffer byte singeByteWrite[]=new byte[1]; public void write(int b) throws IOException { singeByteWrite[0]=(byte)b; write(singeByteWrite, 0, 1); } public void write(byte[] b, int off, int len) throws IOException { resp.write( b, off, len ); } public void close() throws IOException { } public void flush() throws IOException { } } 1.1 jakarta-tomcat-connectors/jk/java/org/apache/jk/server/tomcat40/Worker40.java Index: Worker40.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * [Additional notices, if required by prior licensing conditions] * */ package org.apache.jk.server.tomcat40; import java.io.*; import java.net.*; import java.util.*; import org.apache.jk.*; import org.apache.tomcat.modules.server.PoolTcpConnector; import org.apache.tomcat.util.net.*; import org.apache.tomcat.util.buf.*; import org.apache.tomcat.util.log.*; import org.apache.tomcat.util.http.*; import org.apache.jk.core.*; import org.apache.catalina.*; /** Tomcat 40 worker * */ public class Worker40 extends Worker { private int reqNote; Container container; public Worker40() { super(); } public void setContainer( Container ct40 ) { this.container=ct40; } public void init(WorkerEnv we) throws IOException { reqNote=we.getNoteId( WorkerEnv.REQUEST_NOTE, "tomcat40Request" ); } public void service( BaseRequest req, Channel ch, Endpoint ep ) throws IOException { d("Incoming request " ); JkRequest40 treq=(JkRequest40)req.getNote( reqNote ); JkResponse40 tres; if( treq==null ) { treq=new JkRequest40(); req.setNote( reqNote, treq ); tres=new JkResponse40(we); treq.setResponse( tres ); tres.setRequest( treq ); } tres=(JkResponse40)treq.getResponse(); treq.setEndpoint( ch, ep ); treq.setBaseRequest( req ); tres.setEndpoint( ch, ep ); try { container.invoke( treq, tres ); } catch(Throwable ex ) { ex.printStackTrace(); } d("Finishing response"); tres.finishResponse(); treq.finishRequest(); treq.recycle(); tres.recycle(); } private static final int dL=0; private static void d(String s ) { System.err.println( "Worker40: " + s ); } // -------------------- Handler implementation -------------------- // /** Construct the request object, with probably unnecesary // sanity tests ( should work without thread pool - but that is // not supported in PoolTcpConnector, maybe in future ) // */ // private Ajp14Request initRequest(Object thData[] ) { // if( ajp14_note < 0 ) throw new RuntimeException( "assert: ajp14_note>0" ); // Ajp14Request req=null; // if( thData != null ) { // req=(Ajp14Request)thData[0]; // } // if( req != null ) { // Response res=req.getResponse(); // req.recycle(); // res.recycle(); // // make the note available to other modules // req.setNote( ajp14_note, req.ajp13); // return req; // } // // either thData==null or broken ( req==null) // Ajp13 ajp13=new Ajp13(reqHandler); // negHandler.init( ajp13 ); // negHandler.setContainerSignature( ContextManager.TOMCAT_NAME + // " v" + ContextManager.TOMCAT_VERSION); // if( password!= null ) { // negHandler.setPassword( password ); // ajp13.setBackward(false); // } // BaseRequest ajpreq=new BaseRequest(); // req=new Ajp14Request(ajp13, ajpreq); // Ajp14Response res=new Ajp14Response(ajp13); // cm.initRequest(req, res); // return req; // } // /** Called whenever a new TCP connection is received. The connection // is reused. // */ // public void processConnection(TcpConnection connection, Object thData[]) // { // try { // if( debug>0) // log( "Received ajp14 connection "); // Socket socket = connection.getSocket(); // // assert: socket!=null, connection!=null ( checked by PoolTcpEndpoint ) // socket.setSoLinger( true, 100); // Ajp14Request req=initRequest( thData ); // Ajp14Response res= (Ajp14Response)req.getResponse(); // Ajp13 ajp13=req.ajp13; // BaseRequest ajpReq=req.ajpReq; // ajp13.setSocket(socket); // // first request should be the loginit. // int status=ajp13.receiveNextRequest( ajpReq ); // if( status != 304 ) { // XXX use better codes // log( "Failure in logInit "); // return; // } // status=ajp13.receiveNextRequest( ajpReq ); // if( status != 304 ) { // XXX use better codes // log( "Failure in login "); // return; // } // boolean moreRequests = true; // while(moreRequests) { // status=ajp13.receiveNextRequest( ajpReq ); // if( status==-2) { // // special case - shutdown // // XXX need better communication, refactor it // if( !doShutdown(socket.getLocalAddress(), // socket.getInetAddress())) { // moreRequests = false; // continue; // } // } // if( status == 200) // cm.service(req, res); // else if (status == 500) { // log( "Invalid request received " + req ); // break; // } // req.recycle(); // res.recycle(); // } // if( debug > 0 ) log("Closing ajp14 connection"); // ajp13.close(); // socket.close(); // } catch (Exception e) { // log("Processing connection " + connection, e); // } // } // // We don't need to check isSameAddress if we authenticate !!! // protected boolean doShutdown(InetAddress serverAddr, // InetAddress clientAddr) // { // try { // // close the socket connection before handling any signal // // but get the addresses first so they are not corrupted // if(isSameAddress(serverAddr, clientAddr)) { // cm.stop(); // // same behavior as in past, because it seems that // // stopping everything doesn't work - need to figure // // out what happens with the threads ( XXX ) // // XXX It should work now - but will fail if servlets create // // threads // System.exit(0); // } // } catch(Exception ignored) { // log("Ignored " + ignored); // } // log("Shutdown command ignored"); // return false; // } // // legacy, should be removed // public void setServer(Object contextM) // { // this.cm=(ContextManager)contextM; // } }
-- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>