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]>

Reply via email to