dims        2002/06/07 11:31:58

  Modified:    java/test/wsdl/multithread MultithreadTestCase.java
               java/src/org/apache/axis/transport/http
                        SimpleAxisServer.java
  Added:       java/src/org/apache/axis/transport/http
                        SimpleAxisWorker.java
  Log:
  Objectives:
  Improve performance of SimpleAxisServer for more stringent testing in a 
multi-threaded environment.
  
  Steps:
  - Start a new thread in SimpleAxisServer for each client socket.
  - Extract code from SimpleAxisServer into SimpleAxisWorker
  
  Note:
  The success ratio of MultithreadTestCase jumped from ~205/400 to ~320/400 on both 
JDK13 and JDK14
  
  Revision  Changes    Path
  1.8       +10 -11    xml-axis/java/test/wsdl/multithread/MultithreadTestCase.java
  
  Index: MultithreadTestCase.java
  ===================================================================
  RCS file: /home/cvs/xml-axis/java/test/wsdl/multithread/MultithreadTestCase.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- MultithreadTestCase.java  1 Apr 2002 20:12:17 -0000       1.7
  +++ MultithreadTestCase.java  7 Jun 2002 18:31:58 -0000       1.8
  @@ -1,26 +1,20 @@
   package test.wsdl.multithread;
   
  -import java.net.ConnectException;
  -
  -import java.rmi.RemoteException;
  -
  -import javax.xml.rpc.ServiceException;
  -
   import junit.framework.AssertionFailedError;
   import junit.framework.TestCase;
  -
   import org.apache.axis.AxisFault;
  -
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
  -
  +import samples.addr.Address;
   import samples.addr.AddressBook;
  -import samples.addr.AddressBookServiceLocator;
   import samples.addr.AddressBookSOAPBindingStub;
  -import samples.addr.Address;
  +import samples.addr.AddressBookServiceLocator;
   import samples.addr.Phone;
   import samples.addr.StateType;
   
  +import javax.xml.rpc.ServiceException;
  +import java.net.ConnectException;
  +
   /**
   * This test calls the stub multiple times from multiple threads.  Before the
   * stub was made threadsafe, there was a good chance this test would fail with an
  @@ -141,5 +135,10 @@
               throw error;
           }
       } // testMultithreading
  +
  +    public static void main(String[] args) {
  +        MultithreadTestCase testCase = new 
MultithreadTestCase("MultithreadTestCase");
  +        testCase.testMultithreading();
  +    }
   } // class MultithreadTestCase
   
  
  
  
  1.61      +43 -655   
xml-axis/java/src/org/apache/axis/transport/http/SimpleAxisServer.java
  
  Index: SimpleAxisServer.java
  ===================================================================
  RCS file: 
/home/cvs/xml-axis/java/src/org/apache/axis/transport/http/SimpleAxisServer.java,v
  retrieving revision 1.60
  retrieving revision 1.61
  diff -u -r1.60 -r1.61
  --- SimpleAxisServer.java     4 Jun 2002 01:19:46 -0000       1.60
  +++ SimpleAxisServer.java     7 Jun 2002 18:31:58 -0000       1.61
  @@ -53,31 +53,16 @@
    * <http://www.apache.org/>.
    */
   
  -package org.apache.axis.transport.http ;
  +package org.apache.axis.transport.http;
   
  -import org.apache.axis.AxisFault;
  -import org.apache.axis.Constants;
  -import org.apache.axis.Message;
  -import org.apache.axis.MessageContext;
  -import org.apache.axis.encoding.Base64;
  -import org.apache.axis.message.SOAPEnvelope;
  -import org.apache.axis.message.SOAPFaultElement;
   import org.apache.axis.server.AxisServer;
   import org.apache.axis.session.Session;
   import org.apache.axis.session.SimpleSession;
  -import org.apache.axis.utils.Options;
   import org.apache.axis.utils.JavaUtils;
  -import org.apache.axis.utils.XMLUtils;
  -
  +import org.apache.axis.utils.Options;
   import org.apache.commons.logging.Log;
   import org.apache.commons.logging.LogFactory;
   
  -import org.w3c.dom.Document;
  -
  -import java.io.IOException;
  -import java.io.InputStream;
  -import java.io.InterruptedIOException;
  -import java.io.OutputStream;
   import java.net.MalformedURLException;
   import java.net.ServerSocket;
   import java.net.Socket;
  @@ -94,8 +79,7 @@
    */
   public class SimpleAxisServer implements Runnable {
       protected static Log log =
  -        LogFactory.getLog(SimpleAxisServer.class.getName());
  -
  +            LogFactory.getLog(SimpleAxisServer.class.getName());
   
       // session state.
       // This table maps session keys (random numbers) to SimpleAxisSession objects.
  @@ -110,7 +94,26 @@
   
       // Are we doing sessions?
       // Set this to false if you don't want any session overhead.
  -    public static boolean doSessions = true;
  +    private static boolean doSessions = true;
  +
  +    protected boolean isSessionUsed() {
  +        return doSessions;
  +    }
  +
  +    protected Session createSession(String cooky) {
  +        // is there a session already?
  +        Session session = null;
  +        if (sessions.containsKey(cooky)) {
  +            session = (Session) sessions.get(cooky);
  +        } else {
  +            // no session for this cooky, bummer
  +            session = new SimpleSession();
  +
  +            // ADD CLEANUP LOGIC HERE if needed
  +            sessions.put(cooky, session);
  +        }
  +        return session;
  +    }
   
       // What is our current session index?
       // This is a monotonically increasing, non-thread-safe integer
  @@ -119,663 +122,44 @@
   
       // Axis server (shared between instances)
       private static AxisServer myAxisServer = null;
  -    private static synchronized AxisServer getAxisServer() {
  +
  +    protected static synchronized AxisServer getAxisServer() {
           if (myAxisServer == null) {
               myAxisServer = new AxisServer();
           }
           return myAxisServer;
       }
   
  -    // HTTP prefix
  -    private static byte HTTP[]   = "HTTP/1.0 ".getBytes();
  -
  -    // HTTP status codes
  -    private static byte OK[]     = ("200 " + 
JavaUtils.getMessage("ok00")).getBytes();
  -    private static byte UNAUTH[] = ("401 " + 
JavaUtils.getMessage("unauth00")).getBytes();
  -    private static byte ISE[]    = ("500 " + 
JavaUtils.getMessage("internalError01")).getBytes();
  -
  -    // Standard MIME headers for XML payload
  -    private static byte XML_MIME_STUFF[] =
  -        ( "\r\nContent-Type: text/xml; charset=utf-8\r\n" +
  -          "Content-Length: ").getBytes();
  -
  -    // Standard MIME headers for HTML payload
  -    private static byte HTML_MIME_STUFF[] =
  -        ( "\r\nContent-Type: text/html; charset=utf-8\r\n" +
  -          "Content-Length: ").getBytes();
  -
  -    // Mime/Content separator
  -    private static byte SEPARATOR[] = "\r\n\r\n".getBytes();
  -
  -    // Tiddly little response
  -    private static final String responseStr =
  -            "<html><head><title>SimpleAxisServer</title></head>" +
  -            "<body><h1>SimpleAxisServer</h1>" +
  -            JavaUtils.getMessage("reachedServer00") +
  -            "</html>";
  -    private static byte cannedHTMLResponse[] = responseStr.getBytes();
  -
  -    // Axis specific constants
  -    private static String transportName = "SimpleHTTP";
  -
       // are we stopped?
       // latch to true if stop() is called
       private boolean stopped = false;
   
       /**
  -     * The main workhorse method.
  -     *
        * Accept requests from a given TCP port and send them through the
        * Axis engine for processing.
        */
       public void run() {
  -        log.info(JavaUtils.getMessage("start00", "SimpleAxisServer", 
  -                  new Integer(getServerSocket().getLocalPort()).toString()));
  -
  -        // create an Axis server
  -        AxisServer engine = getAxisServer();
  -        //engine.init();
  -
  -        // create and initialize a message context
  -        MessageContext msgContext = new MessageContext(engine);
  -        Message        requestMsg;
  -
  -        // Reusuable, buffered, content length controlled, InputStream
  -        NonBlockingBufferedInputStream is =
  -            new NonBlockingBufferedInputStream();
  -
  -        // buffers for the headers we care about
  -        StringBuffer soapAction = new StringBuffer();
  -        StringBuffer httpRequest = new StringBuffer();
  -        StringBuffer fileName = new StringBuffer();
  -        StringBuffer cookie = new StringBuffer();
  -        StringBuffer cookie2 = new StringBuffer();
  -        StringBuffer authInfo = new StringBuffer();
  -        StringBuffer contentType= new StringBuffer();
  -        StringBuffer contentLocation= new StringBuffer();
  -        
  -        Message responseMsg = null;
  +        log.info(JavaUtils.getMessage("start00", "SimpleAxisServer",
  +                new Integer(getServerSocket().getLocalPort()).toString()));
   
           // Accept and process requests from the socket
           while (!stopped) {
               Socket socket = null;
  -
  -            // prepare request (do as much as possible while waiting for the
  -            // next connection).  Note the next two statements are commented
  -            // out.  Uncomment them if you experience any problems with not
  -            // resetting state between requests:
  -            //   msgContext = new MessageContext();
  -            //   requestMsg = new Message("", "String");
               try {
  -                msgContext.setTargetService(null);
  -            } catch (AxisFault fault) {
  -            }
  -            msgContext.setResponseMessage(null);
  -            msgContext.reset();
  -            //msgContext.setProperty("transport", "HTTPTransport");
  -            msgContext.setTransportName(transportName);
  -            
  -            responseMsg = null;
  -
  -            try {
  -                try {
  -                    socket = serverSocket.accept();
  -                } catch (IOException ioe) {
  -                    break;
  -                }
  -
  -                // assume the best
  -                byte[] status = OK;
  -
  -                // assume we're not getting WSDL
  -                boolean doWsdl = false;
  -
  -                // cookie for this session, if any
  -                String cooky = null;
  -
  -                try {
  -                    // wipe cookies if we're doing sessions
  -                    if (doSessions) {
  -                        cookie.delete(0, cookie.length());
  -                        cookie2.delete(0, cookie2.length());
  -                    }
  -                    authInfo.delete(0, authInfo.length());
  -
  -                    // read headers
  -                    is.setInputStream(socket.getInputStream());
  -                    // parse all headers into hashtable
  -                    int contentLength = parseHeaders(is, contentType,
  -                                                     contentLocation, soapAction,
  -                                                     httpRequest, fileName,
  -                                                     cookie, cookie2, authInfo);
  -                    is.setContentLength(contentLength);
  -
  -                    int paramIdx = fileName.toString().indexOf('?');
  -                    if (paramIdx != -1) {
  -                        // Got params
  -                        String params = fileName.substring(paramIdx + 1);
  -                        fileName.setLength(paramIdx);
  -
  -                        log.debug(JavaUtils.getMessage("filename00",
  -                                                       fileName.toString()));
  -                        log.debug(JavaUtils.getMessage("params00",
  -                                                       params));
  -
  -                        if ("wsdl".equalsIgnoreCase(params))
  -                            doWsdl = true;
  -                    }
  -
  -                    // Real and relative paths are the same for the
  -                    // SimpleAxisServer
  -                    msgContext.setProperty(Constants.MC_REALPATH,
  -                                           fileName.toString());
  -                    msgContext.setProperty(Constants.MC_RELATIVE_PATH,
  -                                           fileName.toString());
  -                    msgContext.setProperty(Constants.MC_JWS_CLASSDIR,
  -                                           "jwsClasses");
  -
  -                    String hostname = socket.getInetAddress().getHostName();
  -                    // !!! Fix string concatenation
  -                    String url = "http://"; + hostname + ":" +
  -                            this.getServerSocket().getLocalPort() + "/" +
  -                            fileName.toString();
  -                    msgContext.setProperty(MessageContext.TRANS_URL, url);
  -
  -                    String filePart = fileName.toString();
  -                    if (filePart.startsWith("axis/services/")) {
  -                        msgContext.setTargetService(filePart.substring(14));
  -                    }
  -
  -                    if (authInfo.length() > 0) {
  -                        // Process authentication info
  -                        //authInfo = new StringBuffer("dXNlcjE6cGFzczE=");
  -                        byte [] decoded = Base64.decode(authInfo.toString());
  -                        StringBuffer userBuf = new StringBuffer();
  -                        StringBuffer pwBuf = new StringBuffer();
  -                        StringBuffer authBuf = userBuf;
  -                        for (int i = 0; i < decoded.length; i++) {
  -                            if ((char)(decoded[i] & 0x7f) == ':') {
  -                                authBuf = pwBuf;
  -                                continue;
  -                            }
  -                            authBuf.append((char)(decoded[i] & 0x7f));
  -                        }
  -
  -                        if (log.isDebugEnabled()) {
  -                            log.debug(JavaUtils.getMessage("user00",
  -                                                           userBuf.toString()));
  -                        }
  -
  -                        msgContext.setUsername(userBuf.toString());
  -                        msgContext.setPassword(pwBuf.toString());
  -                    }
  -
  -                    // if get, then return simpleton document as response
  -                    if (httpRequest.toString().equals("GET")) {
  -                        OutputStream out = socket.getOutputStream();
  -                        out.write(HTTP);
  -                        out.write(status);
  -
  -                        if (doWsdl) {
  -                            engine.generateWSDL(msgContext);
  -
  -                            Document doc = (Document)msgContext.getProperty("WSDL");
  -
  -                            if (doc != null) {
  -                                String response = XMLUtils.DocumentToString(doc);
  -                                byte [] respBytes = response.getBytes();
  -
  -                                out.write(XML_MIME_STUFF);
  -                                putInt(out, respBytes.length);
  -                                out.write(SEPARATOR);
  -                                out.write(respBytes);
  -                                out.flush();
  -                                continue;
  -                            }
  -                        }
  -
  -                        out.write(HTML_MIME_STUFF);
  -                        putInt(out, cannedHTMLResponse.length);
  -                        out.write(SEPARATOR);
  -                        out.write(cannedHTMLResponse);
  -                        out.flush();
  -                        continue;
  -                    }
  -
  -                    // this may be "" if either SOAPAction: "" or if no SOAPAction 
at all.
  -                    // for now, do not complain if no SOAPAction at all
  -                    String soapActionString = soapAction.toString();
  -                    if (soapActionString != null) {
  -                        msgContext.setUseSOAPAction(true);
  -                        msgContext.setSOAPActionURI(soapActionString);
  -                    }
  -                    requestMsg = new Message(is,
  -                                             false,
  -                                             contentType.toString(),
  -                                             contentLocation.toString()
  -                                            );
  -                    msgContext.setRequestMessage(requestMsg);
  -
  -                    // set up session, if any
  -                    if (doSessions) {
  -                        // did we get a cookie?
  -                        if (cookie.length() > 0) {
  -                            cooky = cookie.toString().trim();
  -                        } else if (cookie2.length() > 0) {
  -                            cooky = cookie2.toString().trim();
  -                        }
  -
  -                        // if cooky is null, cook up a cooky
  -                        if (cooky == null) {
  -                            // fake one up!
  -                            // make it be an arbitrarily increasing number
  -                            // (no this is not thread safe because ++ isn't atomic)
  -                            int i = sessionIndex++;
  -                            cooky = "" + i;
  -                        }
  -
  -                        // is there a session already?
  -                        Session session = null;
  -                        if (sessions.containsKey(cooky)) {
  -                            session = (Session)sessions.get(cooky);
  -                        } else {
  -                            // no session for this cooky, bummer
  -                            session = new SimpleSession();
  -
  -                            // ADD CLEANUP LOGIC HERE if needed
  -                            sessions.put(cooky, session);
  -                        }
  -
  -                        msgContext.setSession(session);
  -                    }
  -
  -                    // invoke the Axis engine
  -                    engine.invoke(msgContext);
  -                    
  -                    // Retrieve the response from Axis
  -                    responseMsg = msgContext.getResponseMessage();
  -                    if (responseMsg == null) {
  -                        throw new AxisFault(JavaUtils.getMessage("nullResponse00"));
  -                    }
  -
  -                } catch( Exception e ) {
  -                    AxisFault af;
  -                    if (e instanceof AxisFault) {
  -                        af = (AxisFault)e;
  -                        log.debug(JavaUtils.getMessage("serverFault00"), af);
  -
  -                        if ("Server.Unauthorized".equals(af.getFaultCode())) {
  -                            status = UNAUTH; // SC_UNAUTHORIZED
  -                        } else {
  -                            status = ISE; // SC_INTERNAL_SERVER_ERROR
  -                        }
  -                    } else {
  -                        status = ISE; // SC_INTERNAL_SERVER_ERROR
  -                        af = AxisFault.makeFault(e);
  -                    }
  -
  -                    // There may be headers we want to preserve in the
  -                    // response message - so if it's there, just add the
  -                    // FaultElement to it.  Otherwise, make a new one.
  -                    responseMsg = msgContext.getResponseMessage();
  -                    if (responseMsg == null) {
  -                        responseMsg = new Message(af);
  -                    } else {
  -                        try {
  -                            SOAPEnvelope env = responseMsg.getSOAPEnvelope();
  -                            env.clearBody();
  -                            env.addBodyElement(new SOAPFaultElement((AxisFault)e));
  -                        } catch (AxisFault fault) {
  -                            // Should never reach here!
  -                        }
  -                    }
  -                }
  -
  -//                byte[] response = (byte[]) responseMsg.getSOAPPartAsBytes();
  -
  -                // Send it on its way...
  -                OutputStream out = socket.getOutputStream();
  -                out.write(HTTP);
  -                out.write(status);
  -                //out.write(XML_MIME_STUFF);
  -                out.write(("\r\n" + HTTPConstants.HEADER_CONTENT_TYPE + ": " + 
responseMsg.getContentType()).getBytes()); 
  -                out.write(("\r\n" + HTTPConstants.HEADER_CONTENT_LENGTH + ": " + 
responseMsg.getContentLength()).getBytes()); 
  -                // putInt(out, response.length);
  -
  -                if (doSessions && null != cooky && 0 != cooky.trim().length()) {
  -                    // write cookie headers, if any
  -                    // don't sweat efficiency *too* badly
  -                    // optimize at will
  -                    StringBuffer cookieOut = new StringBuffer();
  -                    cookieOut.append("\r\nSet-Cookie: ")
  -                        .append(cooky)
  -                        .append("\r\nSet-Cookie2: ")
  -                        .append(cooky);
  -                    // OH, THE HUMILITY!  yes this is inefficient.
  -                    out.write(cookieOut.toString().getBytes());
  -                }
  -
  -                out.write(SEPARATOR);
  -                responseMsg.writeTo(out);
  -               // out.write(response);
  -                out.flush();
  -
  -                if (msgContext.getProperty(msgContext.QUIT_REQUESTED) != null) {
  -                    // why then, quit!
  -                    this.stop();
  -                }
  -
  -            } catch (InterruptedIOException iie) {
  -                break;
  +                socket = serverSocket.accept();
  +            } catch (java.io.InterruptedIOException iie) {
               } catch (Exception e) {
                   log.debug(JavaUtils.getMessage("exception00"), e);
  -            } finally {
  -                try {
  -                    if (socket!=null) socket.close();
  -                } catch (Exception e) {
  -                }
  -            }
  -        }
  -
  -        log.info(JavaUtils.getMessage("quit00", "SimpleAxisServer"));
  -    }
  -
  -    // ASCII character mapping to lower case
  -    private static final byte[] toLower = new byte[256];
  -
  -    static {
  -        for (int i = 0; i < 256; i++) {
  -            toLower[i] = (byte)i;
  -        }
  -
  -        for (int lc = 'a'; lc <= 'z'; lc++) {
  -            toLower[lc + 'A' - 'a']=(byte)lc;
  -        }
  -    }
  -
  -    // mime header for content length
  -    private static final byte lenHeader[] = "content-length: ".getBytes();
  -    private static final int lenLen = lenHeader.length;
  -
  -    // mime header for content type
  -    private static final byte typeHeader[] = 
(HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase() +": ").getBytes();
  -    private static final int typeLen = typeHeader.length;
  -
  -    // mime header for content location
  -    private static final byte locationHeader[] = 
(HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase()+": ").getBytes();
  -    private static final int locationLen = locationHeader.length;
  -
  -    // mime header for soap action
  -    private static final byte actionHeader[] = "soapaction: ".getBytes();
  -    private static final int actionLen = actionHeader.length;
  -
  -    // mime header for cookie
  -    private static final byte cookieHeader[] = "cookie: ".getBytes();
  -    private static final int cookieLen = cookieHeader.length;
  -
  -    // mime header for cookie2
  -    private static final byte cookie2Header[] = "cookie2: ".getBytes();
  -    private static final int cookie2Len = cookie2Header.length;
  -
  -    // HTTP header for authentication
  -    private static final byte authHeader[] = "authorization: ".getBytes();
  -    private static final int authLen = authHeader.length;
  -
  -    // mime header for GET
  -    private static final byte getHeader[] = "GET".getBytes();
  -
  -    // mime header for POST
  -    private static final byte postHeader[] = "POST".getBytes();
  -
  -    // header ender
  -    private static final byte headerEnder[] = ": ".getBytes();
  -
  -    // buffer for IO
  -    private static final int BUFSIZ = 4096;
  -    private byte buf[] = new byte[BUFSIZ];
  -
  -    // "Basic" auth string
  -    private static final byte basicAuth[] = "basic ".getBytes();
  -
  -    /**
  -     * Read a single line from the input stream
  -     * @param is        inputstream to read from
  -     * @param b         byte array to read into
  -     * @param off       starting offset into the byte array
  -     * @param len       maximum number of bytes to read
  -     */
  -    private int readLine(NonBlockingBufferedInputStream is, byte[] b, int off, int 
len)
  -        throws IOException
  -    {
  -        int count = 0, c;
  -
  -        while ((c = is.read()) != -1) {
  -            if(c != '\n' && c != '\r'){
  -              b[off++] = (byte)c;
  -              count++;
  -            }
  -            if (count == len) break;
  -            if( '\n' == c ){
  -              int peek= is.peek(); //If the next line begins with tab or space then 
this is a continuation.
  -              if(peek != ' ' && peek != '\t') break;
  -            }
  -        }
  -        return count > 0 ? count : -1;
  -    }
  -
  -    /**
  -     * Read all mime headers, returning the value of Content-Length and
  -     * SOAPAction.
  -     * @param is         InputStream to read from
  -     * @param contentType The content type. 
  -     * @param contentLocation The content location
  -     * @param soapAction StringBuffer to return the soapAction into
  -     * @param httpRequest StringBuffer for GET / POST
  -     * @param cookie first cookie header (if doSessions)
  -     * @param cookie2 second cookie header (if doSessions)
  -     * @return Content-Length
  -     */
  -    private int parseHeaders(NonBlockingBufferedInputStream is,
  -                             StringBuffer contentType,
  -                             StringBuffer contentLocation,
  -                             StringBuffer soapAction,
  -                             StringBuffer httpRequest,
  -                             StringBuffer fileName,
  -                             StringBuffer cookie,
  -                             StringBuffer cookie2,
  -                             StringBuffer authInfo)
  -      throws IOException
  -    {
  -        int n;
  -        int len = 0;
  -
  -        // parse first line as GET or POST
  -        n=this.readLine(is, buf, 0, buf.length);
  -        if (n < 0) {
  -            // nothing!
  -            throw new IOException(JavaUtils.getMessage("unexpectedEOS00"));
  -        }
  -
  -        // which does it begin with?
  -        httpRequest.delete(0, httpRequest.length());
  -        fileName.delete(0, fileName.length());
  -        contentType.delete(0, contentType.length());
  -        contentLocation.delete(0, contentLocation.length());
  -
  -        if (buf[0] == getHeader[0]) {
  -            httpRequest.append("GET");
  -            for (int i = 0; i < n - 5; i++) {
  -                char c = (char)(buf[i + 5] & 0x7f);
  -                if (c == ' ')
  -                    break;
  -                fileName.append(c);
  -            }
  -            log.debug( JavaUtils.getMessage("filename01", "SimpleAxisServer", 
fileName.toString()));
  -            return 0;
  -        } else if (buf[0] == postHeader[0]) {
  -            httpRequest.append("POST");
  -            for (int i = 0; i < n - 6; i++) {
  -                char c = (char)(buf[i + 6] & 0x7f);
  -                if (c == ' ')
  -                    break;
  -                fileName.append(c);
  -            }
  -            log.debug( JavaUtils.getMessage("filename01", "SimpleAxisServer", 
fileName.toString()));
  -        } else {
  -            throw new IOException(JavaUtils.getMessage("badRequest00"));
  -        }
  -
  -        while ((n=readLine(is,buf,0,buf.length)) > 0) {
  -
  -            if ((n<=2) && (buf[0]=='\n'||buf[0]=='\r') && (len>0)) break;
  -
  -            // RobJ gutted the previous logic; it was too hard to extend for more 
headers.
  -            // Now, all it does is search forwards for ": " in the buf,
  -            // then do a length / byte compare.
  -            // Hopefully this is still somewhat efficient (Sam is watching!).
  -
  -            // First, search forwards for ": "
  -            int endHeaderIndex = 0;
  -            while (endHeaderIndex < n && toLower[buf[endHeaderIndex]] != 
headerEnder[0]) {
  -                endHeaderIndex++;
  -            }
  -            endHeaderIndex += 2;
  -            // endHeaderIndex now points _just past_ the ": ", and is
  -            // comparable to the various lenLen, actionLen, etc. values
  -
  -            // convenience; i gets pre-incremented, so initialize it to one less
  -            int i = endHeaderIndex - 1;
  -
  -            // which header did we find?
  -            if (endHeaderIndex == lenLen && matches(buf, lenHeader)) {
  -                // parse content length
  -
  -                while ((++i<n) && (buf[i]>='0') && (buf[i]<='9')) {
  -                    len = (len*10) + (buf[i]-'0');
  -                }
  -
  -            }
  -            else if (endHeaderIndex == actionLen
  -                       && matches(buf, actionHeader))
  -            {
  -
  -                soapAction.delete(0,soapAction.length());
  -                // skip initial '"'
  -                i++;
  -                while ((++i<n) && (buf[i]!='"')) {
  -                    soapAction.append((char)(buf[i] & 0x7f));
  -                }
  -
  -            }
  -            else if (doSessions && endHeaderIndex == cookieLen
  -                       && matches(buf, cookieHeader))
  -            {
  -
  -                // keep everything up to first ;
  -                while ((++i<n) && (buf[i]!=';') && (buf[i]!='\r') && 
(buf[i]!='\n')) {
  -                    cookie.append((char)(buf[i] & 0x7f));
  -                }
  -
  -            }
  -            else if (doSessions && endHeaderIndex == cookie2Len
  -                       && matches(buf, cookie2Header))
  -            {
  -
  -                // keep everything up to first ;
  -                while ((++i<n) && (buf[i]!=';') && (buf[i]!='\r') && 
(buf[i]!='\n')) {
  -                    cookie2.append((char)(buf[i] & 0x7f));
  -                }
  -
  -            }
  -            else if (endHeaderIndex == authLen && matches(buf, authHeader)) {
  -                if (matches(buf, endHeaderIndex, basicAuth)) {
  -                    i += basicAuth.length;
  -                    while (++i<n && (buf[i]!='\r') && (buf[i]!='\n')) {
  -                        if (buf[i]==' ') continue;
  -                        authInfo.append((char)(buf[i] & 0x7f));
  -                    }
  -                } else {
  -                    throw new IOException(
  -                            JavaUtils.getMessage("badAuth00"));
  -                }
  -            }
  -            else if (endHeaderIndex == locationLen && matches(buf, locationHeader)) 
{
  -                    while (++i<n && (buf[i]!='\r') && (buf[i]!='\n')) {
  -                        if (buf[i]==' ') continue;
  -                        contentLocation.append((char)(buf[i] & 0x7f));
  -                    }
  -            }
  -            else if (endHeaderIndex == typeLen&& matches(buf, typeHeader)) {
  -                    while (++i<n && (buf[i]!='\r') && (buf[i]!='\n')) {
  -                        if (buf[i]==' ') continue;
  -                        contentType.append((char)(buf[i] & 0x7f));
  -                    }
  -            }
  -
  -        }
  -        return len;
  -    }
  -
  -
  -    /**
  -     * does tolower[buf] match the target byte array, up to the target's length?
  -     */
  -    public boolean matches (byte[] buf, byte[] target) {
  -        for (int i = 0; i < target.length; i++) {
  -            if (toLower[buf[i]] != target[i]) {
  -                return false;
  +                break;
               }
  -        }
  -        return true;
  -    }
  -
  -    /**
  -     * Case-insensitive match of a target byte [] to a source byte [],
  -     * starting from a particular offset into the source.
  -     */
  -    public boolean matches (byte[] buf, int bufIdx, byte[] target) {
  -        for (int i = 0; i < target.length; i++) {
  -            if (toLower[buf[bufIdx + i]] != target[i]) {
  -                return false;
  +            if (socket != null) {
  +                SimpleAxisWorker worker = new SimpleAxisWorker(this, socket);
  +                Thread thread = new Thread(worker);
  +                thread.setDaemon(true);
  +                thread.start();
               }
           }
  -        return true;
  -    }
  -
  -
  -    /**
  -     * output an integer into the output stream
  -     * @param out       OutputStream to be written to
  -     * @param value     Integer value to be written.
  -     */
  -    private void putInt(OutputStream out, int value)
  -        throws IOException
  -    {
  -        int len = 0;
  -        int offset=buf.length;
  -
  -        // negative numbers
  -        if (value < 0) {
  -            buf[--offset] = (byte) '-';
  -            value=-value;
  -            len++;
  -        }
  -
  -        // zero
  -        if (value == 0) {
  -            buf[--offset] = (byte) '0';
  -            len++;
  -        }
  -
  -        // positive numbers
  -        while (value > 0) {
  -            buf[--offset] = (byte)(value%10 + '0');
  -            value=value/10;
  -            len++;
  -        }
  -
  -        // write the result
  -        out.write(buf, offset, len);
  +        log.info(JavaUtils.getMessage("quit00", "SimpleAxisServer"));
       }
   
       // per thread socket information
  @@ -825,6 +209,11 @@
        */
       public void stop() throws Exception {
           stopped = true;
  +        try {
  +            serverSocket.close();
  +        } catch (Exception e) {
  +            e.printStackTrace();
  +        }
           if (worker != null) worker.interrupt();
       }
   
  @@ -848,12 +237,11 @@
               int port = opts.getPort();
               ServerSocket ss = new ServerSocket(port);
               sas.setServerSocket(ss);
  -            sas.run();
  +            sas.start();
           } catch (Exception e) {
               log.error(JavaUtils.getMessage("exception00"), e);
               return;
           }
   
  -     }
  -
  +    }
   }
  
  
  
  1.1                  
xml-axis/java/src/org/apache/axis/transport/http/SimpleAxisWorker.java
  
  Index: SimpleAxisWorker.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   *
   * Copyright (c) 2001 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 acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Axis" 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 name, without prior written
   *    permission of the Apache Software Foundation.
   *
   * 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/>.
   */
  
  package org.apache.axis.transport.http;
  
  import org.apache.axis.AxisFault;
  import org.apache.axis.Constants;
  import org.apache.axis.Message;
  import org.apache.axis.MessageContext;
  import org.apache.axis.encoding.Base64;
  import org.apache.axis.message.SOAPEnvelope;
  import org.apache.axis.message.SOAPFaultElement;
  import org.apache.axis.server.AxisServer;
  import org.apache.axis.utils.JavaUtils;
  import org.apache.axis.utils.XMLUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  import org.w3c.dom.Document;
  
  import java.io.OutputStream;
  import java.net.Socket;
  
  public class SimpleAxisWorker implements Runnable {
      protected static Log log =
              LogFactory.getLog(SimpleAxisWorker.class.getName());
  
      private SimpleAxisServer server;
      private Socket socket;
  
      // Axis specific constants
      private static String transportName = "SimpleHTTP";
  
      // HTTP status codes
      private static byte OK[] = ("200 " + JavaUtils.getMessage("ok00")).getBytes();
      private static byte UNAUTH[] = ("401 " + 
JavaUtils.getMessage("unauth00")).getBytes();
      private static byte ISE[] = ("500 " + 
JavaUtils.getMessage("internalError01")).getBytes();
  
      // HTTP prefix
      private static byte HTTP[] = "HTTP/1.0 ".getBytes();
  
      // Standard MIME headers for XML payload
      private static byte XML_MIME_STUFF[] =
              ("\r\nContent-Type: text/xml; charset=utf-8\r\n" +
              "Content-Length: ").getBytes();
  
      // Standard MIME headers for HTML payload
      private static byte HTML_MIME_STUFF[] =
              ("\r\nContent-Type: text/html; charset=utf-8\r\n" +
              "Content-Length: ").getBytes();
  
      // Mime/Content separator
      private static byte SEPARATOR[] = "\r\n\r\n".getBytes();
  
      // Tiddly little response
      private static final String responseStr =
              "<html><head><title>SimpleAxisServer</title></head>" +
              "<body><h1>SimpleAxisServer</h1>" +
              JavaUtils.getMessage("reachedServer00") +
              "</html>";
      private static byte cannedHTMLResponse[] = responseStr.getBytes();
  
      // ASCII character mapping to lower case
      private static final byte[] toLower = new byte[256];
  
      static {
          for (int i = 0; i < 256; i++) {
              toLower[i] = (byte) i;
          }
  
          for (int lc = 'a'; lc <= 'z'; lc++) {
              toLower[lc + 'A' - 'a'] = (byte) lc;
          }
      }
  
      // buffer for IO
      private static final int BUFSIZ = 4096;
  
      // mime header for content length
      private static final byte lenHeader[] = "content-length: ".getBytes();
      private static final int lenLen = lenHeader.length;
  
      // mime header for content type
      private static final byte typeHeader[] = 
(HTTPConstants.HEADER_CONTENT_TYPE.toLowerCase() + ": ").getBytes();
      private static final int typeLen = typeHeader.length;
  
      // mime header for content location
      private static final byte locationHeader[] = 
(HTTPConstants.HEADER_CONTENT_LOCATION.toLowerCase() + ": ").getBytes();
      private static final int locationLen = locationHeader.length;
  
      // mime header for soap action
      private static final byte actionHeader[] = "soapaction: ".getBytes();
      private static final int actionLen = actionHeader.length;
  
      // mime header for cookie
      private static final byte cookieHeader[] = "cookie: ".getBytes();
      private static final int cookieLen = cookieHeader.length;
  
      // mime header for cookie2
      private static final byte cookie2Header[] = "cookie2: ".getBytes();
      private static final int cookie2Len = cookie2Header.length;
  
      // HTTP header for authentication
      private static final byte authHeader[] = "authorization: ".getBytes();
      private static final int authLen = authHeader.length;
  
      // mime header for GET
      private static final byte getHeader[] = "GET".getBytes();
  
      // mime header for POST
      private static final byte postHeader[] = "POST".getBytes();
  
      // header ender
      private static final byte headerEnder[] = ": ".getBytes();
  
      // "Basic" auth string
      private static final byte basicAuth[] = "basic ".getBytes();
  
      public SimpleAxisWorker(SimpleAxisServer server, Socket socket) {
          this.server = server;
          this.socket = socket;
      }
  
      /**
       * The main workhorse method.
       */
      public void run() {
          byte buf[] = new byte[BUFSIZ];
          // create an Axis server
          AxisServer engine = server.getAxisServer();
  
          // create and initialize a message context
          MessageContext msgContext = new MessageContext(engine);
          Message requestMsg;
  
          // Reusuable, buffered, content length controlled, InputStream
          NonBlockingBufferedInputStream is =
                  new NonBlockingBufferedInputStream();
  
          // buffers for the headers we care about
          StringBuffer soapAction = new StringBuffer();
          StringBuffer httpRequest = new StringBuffer();
          StringBuffer fileName = new StringBuffer();
          StringBuffer cookie = new StringBuffer();
          StringBuffer cookie2 = new StringBuffer();
          StringBuffer authInfo = new StringBuffer();
          StringBuffer contentType = new StringBuffer();
          StringBuffer contentLocation = new StringBuffer();
  
          Message responseMsg = null;
  
          // prepare request (do as much as possible while waiting for the
          // next connection).  Note the next two statements are commented
          // out.  Uncomment them if you experience any problems with not
          // resetting state between requests:
          //   msgContext = new MessageContext();
          //   requestMsg = new Message("", "String");
          try {
              msgContext.setTargetService(null);
          } catch (AxisFault fault) {
          }
          msgContext.setResponseMessage(null);
          msgContext.reset();
          //msgContext.setProperty("transport", "HTTPTransport");
          msgContext.setTransportName(transportName);
  
          responseMsg = null;
  
          try {
              // assume the best
              byte[] status = OK;
  
              // assume we're not getting WSDL
              boolean doWsdl = false;
  
              // cookie for this session, if any
              String cooky = null;
  
              try {
                  // wipe cookies if we're doing sessions
                  if (server.isSessionUsed()) {
                      cookie.delete(0, cookie.length());
                      cookie2.delete(0, cookie2.length());
                  }
                  authInfo.delete(0, authInfo.length());
  
                  // read headers
                  is.setInputStream(socket.getInputStream());
                  // parse all headers into hashtable
                  int contentLength = parseHeaders(is, buf, contentType,
                          contentLocation, soapAction,
                          httpRequest, fileName,
                          cookie, cookie2, authInfo);
                  is.setContentLength(contentLength);
  
                  int paramIdx = fileName.toString().indexOf('?');
                  if (paramIdx != -1) {
                      // Got params
                      String params = fileName.substring(paramIdx + 1);
                      fileName.setLength(paramIdx);
  
                      log.debug(JavaUtils.getMessage("filename00",
                              fileName.toString()));
                      log.debug(JavaUtils.getMessage("params00",
                              params));
  
                      if ("wsdl".equalsIgnoreCase(params))
                          doWsdl = true;
                  }
  
                  // Real and relative paths are the same for the
                  // SimpleAxisServer
                  msgContext.setProperty(Constants.MC_REALPATH,
                          fileName.toString());
                  msgContext.setProperty(Constants.MC_RELATIVE_PATH,
                          fileName.toString());
                  msgContext.setProperty(Constants.MC_JWS_CLASSDIR,
                          "jwsClasses");
  
                  String hostname = socket.getInetAddress().getHostName();
                  // !!! Fix string concatenation
                  String url = "http://"; + hostname + ":" +
                          server.getServerSocket().getLocalPort() + "/" +
                          fileName.toString();
                  msgContext.setProperty(MessageContext.TRANS_URL, url);
  
                  String filePart = fileName.toString();
                  if (filePart.startsWith("axis/services/")) {
                      msgContext.setTargetService(filePart.substring(14));
                  }
  
                  if (authInfo.length() > 0) {
                      // Process authentication info
                      //authInfo = new StringBuffer("dXNlcjE6cGFzczE=");
                      byte[] decoded = Base64.decode(authInfo.toString());
                      StringBuffer userBuf = new StringBuffer();
                      StringBuffer pwBuf = new StringBuffer();
                      StringBuffer authBuf = userBuf;
                      for (int i = 0; i < decoded.length; i++) {
                          if ((char) (decoded[i] & 0x7f) == ':') {
                              authBuf = pwBuf;
                              continue;
                          }
                          authBuf.append((char) (decoded[i] & 0x7f));
                      }
  
                      if (log.isDebugEnabled()) {
                          log.debug(JavaUtils.getMessage("user00",
                                  userBuf.toString()));
                      }
  
                      msgContext.setUsername(userBuf.toString());
                      msgContext.setPassword(pwBuf.toString());
                  }
  
                  // if get, then return simpleton document as response
                  if (httpRequest.toString().equals("GET")) {
                      OutputStream out = socket.getOutputStream();
                      out.write(HTTP);
                      out.write(status);
  
                      if (doWsdl) {
                          engine.generateWSDL(msgContext);
  
                          Document doc = (Document) msgContext.getProperty("WSDL");
                          if (doc != null) {
                              String response = XMLUtils.DocumentToString(doc);
                              byte[] respBytes = response.getBytes();
  
                              out.write(XML_MIME_STUFF);
                              putInt(buf, out, respBytes.length);
                              out.write(SEPARATOR);
                              out.write(respBytes);
                              out.flush();
                              return;
                          }
                      }
  
                      out.write(HTML_MIME_STUFF);
                      putInt(buf, out, cannedHTMLResponse.length);
                      out.write(SEPARATOR);
                      out.write(cannedHTMLResponse);
                      out.flush();
                      return;
                  }
  
                  // this may be "" if either SOAPAction: "" or if no SOAPAction at 
all.
                  // for now, do not complain if no SOAPAction at all
                  String soapActionString = soapAction.toString();
                  if (soapActionString != null) {
                      msgContext.setUseSOAPAction(true);
                      msgContext.setSOAPActionURI(soapActionString);
                  }
                  requestMsg = new Message(is,
                          false,
                          contentType.toString(),
                          contentLocation.toString()
                  );
                  msgContext.setRequestMessage(requestMsg);
  
                  // set up session, if any
                  if (server.isSessionUsed()) {
                      // did we get a cookie?
                      if (cookie.length() > 0) {
                          cooky = cookie.toString().trim();
                      } else if (cookie2.length() > 0) {
                          cooky = cookie2.toString().trim();
                      }
  
                      // if cooky is null, cook up a cooky
                      if (cooky == null) {
                          // fake one up!
                          // make it be an arbitrarily increasing number
                          // (no this is not thread safe because ++ isn't atomic)
                          int i = server.sessionIndex++;
                          cooky = "" + i;
                      }
  
                      msgContext.setSession(server.createSession(cooky));
                  }
  
                  // invoke the Axis engine
                  engine.invoke(msgContext);
  
                  // Retrieve the response from Axis
                  responseMsg = msgContext.getResponseMessage();
                  if (responseMsg == null) {
                      throw new AxisFault(JavaUtils.getMessage("nullResponse00"));
                  }
  
              } catch (Exception e) {
                  AxisFault af;
                  if (e instanceof AxisFault) {
                      af = (AxisFault) e;
                      log.debug(JavaUtils.getMessage("serverFault00"), af);
  
                      if ("Server.Unauthorized".equals(af.getFaultCode())) {
                          status = UNAUTH; // SC_UNAUTHORIZED
                      } else {
                          status = ISE; // SC_INTERNAL_SERVER_ERROR
                      }
                  } else {
                      status = ISE; // SC_INTERNAL_SERVER_ERROR
                      af = AxisFault.makeFault(e);
                  }
  
                  // There may be headers we want to preserve in the
                  // response message - so if it's there, just add the
                  // FaultElement to it.  Otherwise, make a new one.
                  responseMsg = msgContext.getResponseMessage();
                  if (responseMsg == null) {
                      responseMsg = new Message(af);
                  } else {
                      try {
                          SOAPEnvelope env = responseMsg.getSOAPEnvelope();
                          env.clearBody();
                          env.addBodyElement(new SOAPFaultElement((AxisFault) e));
                      } catch (AxisFault fault) {
                          // Should never reach here!
                      }
                  }
              }
  
              // Send it on its way...
              OutputStream out = socket.getOutputStream();
              out.write(HTTP);
              out.write(status);
              //out.write(XML_MIME_STUFF);
              out.write(("\r\n" + HTTPConstants.HEADER_CONTENT_TYPE + ": " + 
responseMsg.getContentType()).getBytes());
              out.write(("\r\n" + HTTPConstants.HEADER_CONTENT_LENGTH + ": " + 
responseMsg.getContentLength()).getBytes());
              // putInt(out, response.length);
  
              if (server.isSessionUsed() && null != cooky && 0 != 
cooky.trim().length()) {
                  // write cookie headers, if any
                  // don't sweat efficiency *too* badly
                  // optimize at will
                  StringBuffer cookieOut = new StringBuffer();
                  cookieOut.append("\r\nSet-Cookie: ")
                          .append(cooky)
                          .append("\r\nSet-Cookie2: ")
                          .append(cooky);
                  // OH, THE HUMILITY!  yes this is inefficient.
                  out.write(cookieOut.toString().getBytes());
              }
  
              out.write(SEPARATOR);
              responseMsg.writeTo(out);
              // out.write(response);
              out.flush();
  
              if (msgContext.getProperty(msgContext.QUIT_REQUESTED) != null) {
                  // why then, quit!
                  server.stop();
              }
          } catch (Exception e) {
              log.debug(JavaUtils.getMessage("exception00"), e);
          } finally {
              try {
                  if (socket != null) socket.close();
              } catch (Exception e) {
              }
          }
      }
  
      /**
       * Read all mime headers, returning the value of Content-Length and
       * SOAPAction.
       * @param is         InputStream to read from
       * @param contentType The content type.
       * @param contentLocation The content location
       * @param soapAction StringBuffer to return the soapAction into
       * @param httpRequest StringBuffer for GET / POST
       * @param cookie first cookie header (if doSessions)
       * @param cookie2 second cookie header (if doSessions)
       * @return Content-Length
       */
      private int parseHeaders(NonBlockingBufferedInputStream is,
                               byte buf[],
                               StringBuffer contentType,
                               StringBuffer contentLocation,
                               StringBuffer soapAction,
                               StringBuffer httpRequest,
                               StringBuffer fileName,
                               StringBuffer cookie,
                               StringBuffer cookie2,
                               StringBuffer authInfo)
              throws java.io.IOException {
          int n;
          int len = 0;
  
          // parse first line as GET or POST
          n = this.readLine(is, buf, 0, buf.length);
          if (n < 0) {
              // nothing!
              throw new java.io.IOException(JavaUtils.getMessage("unexpectedEOS00"));
          }
  
          // which does it begin with?
          httpRequest.delete(0, httpRequest.length());
          fileName.delete(0, fileName.length());
          contentType.delete(0, contentType.length());
          contentLocation.delete(0, contentLocation.length());
  
          if (buf[0] == getHeader[0]) {
              httpRequest.append("GET");
              for (int i = 0; i < n - 5; i++) {
                  char c = (char) (buf[i + 5] & 0x7f);
                  if (c == ' ')
                      break;
                  fileName.append(c);
              }
              log.debug(JavaUtils.getMessage("filename01", "SimpleAxisServer", 
fileName.toString()));
              return 0;
          } else if (buf[0] == postHeader[0]) {
              httpRequest.append("POST");
              for (int i = 0; i < n - 6; i++) {
                  char c = (char) (buf[i + 6] & 0x7f);
                  if (c == ' ')
                      break;
                  fileName.append(c);
              }
              log.debug(JavaUtils.getMessage("filename01", "SimpleAxisServer", 
fileName.toString()));
          } else {
              throw new java.io.IOException(JavaUtils.getMessage("badRequest00"));
          }
  
          while ((n = readLine(is, buf, 0, buf.length)) > 0) {
  
              if ((n <= 2) && (buf[0] == '\n' || buf[0] == '\r') && (len > 0)) break;
  
              // RobJ gutted the previous logic; it was too hard to extend for more 
headers.
              // Now, all it does is search forwards for ": " in the buf,
              // then do a length / byte compare.
              // Hopefully this is still somewhat efficient (Sam is watching!).
  
              // First, search forwards for ": "
              int endHeaderIndex = 0;
              while (endHeaderIndex < n && toLower[buf[endHeaderIndex]] != 
headerEnder[0]) {
                  endHeaderIndex++;
              }
              endHeaderIndex += 2;
              // endHeaderIndex now points _just past_ the ": ", and is
              // comparable to the various lenLen, actionLen, etc. values
  
              // convenience; i gets pre-incremented, so initialize it to one less
              int i = endHeaderIndex - 1;
  
              // which header did we find?
              if (endHeaderIndex == lenLen && matches(buf, lenHeader)) {
                  // parse content length
  
                  while ((++i < n) && (buf[i] >= '0') && (buf[i] <= '9')) {
                      len = (len * 10) + (buf[i] - '0');
                  }
  
              } else if (endHeaderIndex == actionLen
                      && matches(buf, actionHeader)) {
  
                  soapAction.delete(0, soapAction.length());
                  // skip initial '"'
                  i++;
                  while ((++i < n) && (buf[i] != '"')) {
                      soapAction.append((char) (buf[i] & 0x7f));
                  }
  
              } else if (server.isSessionUsed() && endHeaderIndex == cookieLen
                      && matches(buf, cookieHeader)) {
  
                  // keep everything up to first ;
                  while ((++i < n) && (buf[i] != ';') && (buf[i] != '\r') && (buf[i] 
!= '\n')) {
                      cookie.append((char) (buf[i] & 0x7f));
                  }
  
              } else if (server.isSessionUsed() && endHeaderIndex == cookie2Len
                      && matches(buf, cookie2Header)) {
  
                  // keep everything up to first ;
                  while ((++i < n) && (buf[i] != ';') && (buf[i] != '\r') && (buf[i] 
!= '\n')) {
                      cookie2.append((char) (buf[i] & 0x7f));
                  }
  
              } else if (endHeaderIndex == authLen && matches(buf, authHeader)) {
                  if (matches(buf, endHeaderIndex, basicAuth)) {
                      i += basicAuth.length;
                      while (++i < n && (buf[i] != '\r') && (buf[i] != '\n')) {
                          if (buf[i] == ' ') continue;
                          authInfo.append((char) (buf[i] & 0x7f));
                      }
                  } else {
                      throw new java.io.IOException(
                              JavaUtils.getMessage("badAuth00"));
                  }
              } else if (endHeaderIndex == locationLen && matches(buf, 
locationHeader)) {
                  while (++i < n && (buf[i] != '\r') && (buf[i] != '\n')) {
                      if (buf[i] == ' ') continue;
                      contentLocation.append((char) (buf[i] & 0x7f));
                  }
              } else if (endHeaderIndex == typeLen && matches(buf, typeHeader)) {
                  while (++i < n && (buf[i] != '\r') && (buf[i] != '\n')) {
                      if (buf[i] == ' ') continue;
                      contentType.append((char) (buf[i] & 0x7f));
                  }
              }
  
          }
          return len;
      }
  
      /**
       * does tolower[buf] match the target byte array, up to the target's length?
       */
      public boolean matches(byte[] buf, byte[] target) {
          for (int i = 0; i < target.length; i++) {
              if (toLower[buf[i]] != target[i]) {
                  return false;
              }
          }
          return true;
      }
  
      /**
       * Case-insensitive match of a target byte [] to a source byte [],
       * starting from a particular offset into the source.
       */
      public boolean matches(byte[] buf, int bufIdx, byte[] target) {
          for (int i = 0; i < target.length; i++) {
              if (toLower[buf[bufIdx + i]] != target[i]) {
                  return false;
              }
          }
          return true;
      }
  
      /**
       * output an integer into the output stream
       * @param out       OutputStream to be written to
       * @param value     Integer value to be written.
       */
      private void putInt(byte buf[], OutputStream out, int value)
              throws java.io.IOException {
          int len = 0;
          int offset = buf.length;
  
          // negative numbers
          if (value < 0) {
              buf[--offset] = (byte) '-';
              value = -value;
              len++;
          }
  
          // zero
          if (value == 0) {
              buf[--offset] = (byte) '0';
              len++;
          }
  
          // positive numbers
          while (value > 0) {
              buf[--offset] = (byte) (value % 10 + '0');
              value = value / 10;
              len++;
          }
  
          // write the result
          out.write(buf, offset, len);
      }
  
      /**
       * Read a single line from the input stream
       * @param is        inputstream to read from
       * @param b         byte array to read into
       * @param off       starting offset into the byte array
       * @param len       maximum number of bytes to read
       */
      private int readLine(NonBlockingBufferedInputStream is, byte[] b, int off, int 
len)
              throws java.io.IOException {
          int count = 0, c;
  
          while ((c = is.read()) != -1) {
              if (c != '\n' && c != '\r') {
                  b[off++] = (byte) c;
                  count++;
              }
              if (count == len) break;
              if ('\n' == c) {
                  int peek = is.peek(); //If the next line begins with tab or space 
then this is a continuation.
                  if (peek != ' ' && peek != '\t') break;
              }
          }
          return count > 0 ? count : -1;
      }
  }
  
  
  


Reply via email to