axis-java-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Glen Daniels <gdani...@macromedia.com>
Subject RE: cvs commit: xml-axis/java/src/org/apache/axis/transport/http SimpleAxisWorker.java SimpleAxisServer.java
Date Fri, 07 Jun 2002 20:20:30 GMT

*applause* :)

> -----Original Message-----
> From: dims@apache.org [mailto:dims@apache.org]
> Sent: Friday, June 07, 2002 2:32 PM
> To: xml-axis-cvs@apache.org
> Subject: cvs commit: xml-axis/java/src/org/apache/axis/transport/http
> SimpleAxisWorker.java SimpleAxisServer.java
> 
> 
> 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/MultithreadTestC
> ase.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/Sim
> pleAxisServer.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 apache@apache.org.
>    *
>    * 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;
>       }
>   }
>   
>   
>   
> 

Mime
View raw message