Package org.apache.axis.transport.http

Source Code of org.apache.axis.transport.http.SimpleAxisWorker

/*
* 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.description.ServiceDesc;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.encoding.Base64;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPFault;
import org.apache.axis.server.AxisServer;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.XMLUtils;

import org.apache.axis.components.logger.LogFactory;
import org.apache.commons.logging.Log;

import org.w3c.dom.Document;

import java.io.OutputStream;
import java.net.Socket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Iterator;
import java.util.ArrayList;


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");

                // !!! Fix string concatenation
                String url = "http://" + getLocalHost() + ":" +
                        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;
                        }
                    }

                    StringBuffer sb = new StringBuffer();
                    sb.append("<h2>And now... Some Services</h2>\n");
                    Iterator i = engine.getConfig().getDeployedServices();
                    out.write("<ul>\n".getBytes());
                    while (i.hasNext()) {
                        ServiceDesc sd = (ServiceDesc)i.next();
                        sb.append("<li>\n");
                        sb.append(sd.getName());
                        sb.append(" <a href=\"../services/");
                        sb.append(sd.getName());
                        sb.append("?wsdl\"><i>(wsdl)</i></a></li>\n");
                        ArrayList operations = sd.getOperations();
                        if (!operations.isEmpty()) {
                            sb.append("<ul>\n");
                            for (Iterator it = operations.iterator(); it.hasNext();) {
                                OperationDesc desc = (OperationDesc) it.next();
                                sb.append("<li>" + desc.getName());
                            }
                            sb.append("</ul>\n");
                        }
                    }
                    sb.append("</ul>\n");

                    byte [] bytes = sb.toString().getBytes();

                    out.write(HTML_MIME_STUFF);
                    putInt(buf, out, bytes.length);
                    out.write(SEPARATOR);
                    out.write(bytes);
                    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 SOAPFault((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(msgContext.getSOAPConstants())).getBytes());
            // Writing the length causes the entire message to be decoded twice.
            //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();
        } catch (Exception e) {
            log.debug(JavaUtils.getMessage("exception00"), e);
        } finally {
            try {
                if (socket != null) socket.close();
            } catch (Exception e) {
            }
        }
        if (msgContext.getProperty(msgContext.QUIT_REQUESTED) != null) {
            // why then, quit!
            try {
                server.stop();
            } 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;
    }

    /**
     * One method for all host name lookups.
     */
    public static String getLocalHost() {
        // FIXME
        // This doesn't return anything but 0.0.0.0
        //  String hostname = serverSocket.getInetAddress().getHostAddress();
        // And this returns the hostname of the host on the other
        // end of the socket:
        //  String hostname = socket.getInetAddress().getHostName();
        // This works for 99% of the uses of SimpleAxisServer,
        // but is very stupid
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException uhe){
            return "localhost";
        }
    }
}
TOP

Related Classes of org.apache.axis.transport.http.SimpleAxisWorker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.