org.ksoap2.transport.HttpTransportSE2.java Source code

Java tutorial

Introduction

Here is the source code for org.ksoap2.transport.HttpTransportSE2.java

Source

/**
 *  Copyright (c) 2003,2004, Stefan Haustein, Oberhausen, Rhld., Germany
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The  above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE. 
 *
 * Contributor(s): John D. Beatty, Dave Dash, F. Hunter, Alexander Krebs, 
 *                 Lars Mehrmann, Sean McDaniel, Thomas Strang, Renaud Tognelli 
 * */
package org.ksoap2.transport;

import android.util.Base64;
import android.util.Base64InputStream;

import org.apache.commons.io.IOUtils;
import org.ksoap2.HeaderProperty;
import org.ksoap2.SoapEnvelope;
import org.ksoap2.serialization.SoapSerializationEnvelope;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xmlpull.v1.XmlPullParserException;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import ru.profi1c.engine.Dbg;
import ru.profi1c.engine.util.IOHelper;

/**
 *   HttpTransport, ?  ?    
 */
public class HttpTransportSE2 extends Transport {
    private static final String TAG = HttpTransportSE2.class.getSimpleName();

    private ServiceConnection mConnection;

    /**
     * Creates instance of HttpTransportSE2 with set url
     *
     * @param url the destination to POST SOAP data
     */
    public HttpTransportSE2(String url) {
        super(null, url);
    }

    /**
     * Creates instance of HttpTransportSE2 with set url and defines a
     * proxy server to use to access it
     *
     * @param proxy Proxy information or <code>null</code> for direct access
     * @param url   The destination to POST SOAP data
     */
    public HttpTransportSE2(Proxy proxy, String url) {
        super(proxy, url);
    }

    /**
     * Creates instance of HttpTransportSE2 with set url
     *
     * @param url     the destination to POST SOAP data
     * @param timeout timeout for mConnection and Read Timeouts (milliseconds)
     */
    public HttpTransportSE2(String url, int timeout) {
        super(url, timeout);
    }

    public HttpTransportSE2(Proxy proxy, String url, int timeout) {
        super(proxy, url, timeout);
    }

    /**
     * set the desired soapAction header field
     *
     * @param soapAction the desired soapAction
     * @param envelope   the envelope containing the information for the soap call.
     * @throws IOException
     * @throws XmlPullParserException
     */
    public void call(String soapAction, SoapEnvelope envelope) throws IOException, XmlPullParserException {
        call(soapAction, envelope, null);
    }

    /**
     *   web-??    ? ( 2 )
     *   base64.
     *
     * @param soapAction  soapAction
     * @param envelope   , ?  ?  soap.
     * @param file          ??  ???? 
     * @return ??   ?   ? ?  null
     * @throws IOException
     */
    public boolean callLarge(String soapAction, SoapEnvelope envelope, File file) throws IOException {

        boolean isOk = false;

        if (soapAction == null) {
            soapAction = "\"\"";
        }

        byte[] requestData = createRequestData(envelope);

        mConnection = getServiceConnection();
        mConnection.setRequestProperty("User-Agent", USER_AGENT);
        // SOAPAction is not a valid header for VER12 so do not add
        // it
        // @see "http://code.google.com/p/ksoap2-android/issues/detail?id=67
        if (envelope.version != SoapSerializationEnvelope.VER12) {
            mConnection.setRequestProperty("SOAPAction", soapAction);
        }

        if (envelope.version == SoapSerializationEnvelope.VER12) {
            mConnection.setRequestProperty("Content-Type", CONTENT_TYPE_SOAP_XML_CHARSET_UTF_8);
        } else {
            mConnection.setRequestProperty("Content-Type", CONTENT_TYPE_XML_CHARSET_UTF_8);
        }

        mConnection.setRequestProperty("Connection", "close");
        mConnection.setRequestProperty("Content-Length", "" + requestData.length);

        mConnection.setRequestMethod("POST");
        mConnection.connect();

        OutputStream os = mConnection.openOutputStream();

        os.write(requestData, 0, requestData.length);
        os.flush();
        os.close();
        InputStream is = null;

        try {
            mConnection.connect();
            is = mConnection.openInputStream();
            isOk = parseXml(is, file);
        } catch (IOException e) {
            is = mConnection.getErrorStream();

            if (is == null) {
                mConnection.disconnect();
                throw (e);
            }
        } finally {
            IOHelper.close(is);
        }
        return isOk;
    }

    /**
     * ? ?    web-??
     *
     * @param is
     * @param file
     * @return
     */
    private boolean parseXml(InputStream is, File file) {
        boolean complete = false;
        try {
            SAXParserFactory factory = SAXParserFactory.newInstance();

            SAXParser parser = factory.newSAXParser();
            SaxHandler saxHandler = new SaxHandler(file);

            parser.parse(is, saxHandler);
            complete = saxHandler.isComplete();

        } catch (ParserConfigurationException e) {
            Dbg.printStackTrace(e);
        } catch (SAXException e) {
            Dbg.printStackTrace(e);
        } catch (IOException e) {
            Dbg.printStackTrace(e);
        }
        return complete;
    }

    /**
     * set the desired soapAction header field
     *
     * @param soapAction the desired soapAction
     * @param envelope   the envelope containing the information for the soap call.
     * @param headers    a list of HeaderProperties to be http header properties when establishing the mConnection
     * @return <code>CookieJar</code> with any cookies sent by the server
     * @throws IOException
     * @throws XmlPullParserException
     */
    @SuppressWarnings("unchecked")
    public List call(String soapAction, SoapEnvelope envelope, List headers)
            throws IOException, XmlPullParserException {

        if (soapAction == null) {
            soapAction = "\"\"";
        }

        byte[] requestData = createRequestData(envelope);

        requestDump = debug ? new String(requestData) : null;
        responseDump = null;

        mConnection = getServiceConnection();

        mConnection.setRequestProperty("User-Agent", USER_AGENT);
        // SOAPAction is not a valid header for VER12 so do not add
        // it
        // @see "http://code.google.com/p/ksoap2-android/issues/detail?id=67
        if (envelope.version != SoapSerializationEnvelope.VER12) {
            mConnection.setRequestProperty("SOAPAction", soapAction);
        }

        if (envelope.version == SoapSerializationEnvelope.VER12) {
            mConnection.setRequestProperty("Content-Type", CONTENT_TYPE_SOAP_XML_CHARSET_UTF_8);
        } else {
            mConnection.setRequestProperty("Content-Type", CONTENT_TYPE_XML_CHARSET_UTF_8);
        }

        mConnection.setRequestProperty("Connection", "close");
        mConnection.setRequestProperty("Content-Length", "" + requestData.length);

        // Pass the headers provided by the user along with the call
        if (headers != null) {
            for (int i = 0; i < headers.size(); i++) {
                HeaderProperty hp = (HeaderProperty) headers.get(i);
                mConnection.setRequestProperty(hp.getKey(), hp.getValue());
            }
        }

        mConnection.setRequestMethod("POST");
        mConnection.connect();

        OutputStream os = mConnection.openOutputStream();

        os.write(requestData, 0, requestData.length);
        os.flush();
        os.close();
        InputStream is;
        List retHeaders = null;

        try {
            mConnection.connect();
            is = mConnection.openInputStream();
            retHeaders = mConnection.getResponseProperties();
        } catch (IOException e) {
            is = mConnection.getErrorStream();

            if (is == null) {
                mConnection.disconnect();
                throw (e);
            }
        }

        if (debug) {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] buf = new byte[256];

            while (true) {
                int rd = is.read(buf, 0, 256);
                if (rd == -1) {
                    break;
                }
                bos.write(buf, 0, rd);
            }

            bos.flush();
            buf = bos.toByteArray();
            responseDump = new String(buf);
            is.close();
            is = new ByteArrayInputStream(buf);
        }

        parseResponse(envelope, is);
        return retHeaders;
    }

    public ServiceConnection getConnection() {
        return (ServiceConnectionSE) mConnection;
    }

    protected ServiceConnection getServiceConnection() throws IOException {
        return new ServiceConnectionSE(proxy, url, timeout);
    }

    public String getHost() {

        String retVal = null;

        try {
            retVal = new URL(url).getHost();
        } catch (MalformedURLException e) {
            Dbg.printStackTrace(e);
        }

        return retVal;
    }

    public int getPort() {

        int retVal = -1;

        try {
            retVal = new URL(url).getPort();
        } catch (MalformedURLException e) {
            Dbg.printStackTrace(e);
        }

        return retVal;
    }

    public String getPath() {

        String retVal = null;

        try {
            retVal = new URL(url).getPath();
        } catch (MalformedURLException e) {
            Dbg.printStackTrace(e);
        }

        return retVal;
    }

    /**
     *  ?  xml 
     */
    private static class SaxHandler extends DefaultHandler {
        private static final boolean DEBUG = Dbg.DEBUG;

        public static final String DECODING_TMP_FILE_NAME = "decoding.tmp";
        private static final String TAG_NAME = "return";
        public static final int INFORM_WRITE_SIZE = 10240;

        private final File mOutFile;
        private final File mTmpFile;

        private FileOutputStream mFOut;
        private boolean mReading, mComplete;

        private int mTotalWrite;

        public SaxHandler(File outFile) {
            this.mOutFile = outFile;

            mTmpFile = new File(outFile.getParentFile(), DECODING_TMP_FILE_NAME);
            if (mTmpFile.exists()) {
                mTmpFile.delete();
            }
        }

        public void startDocument() throws SAXException {
            if (DEBUG) {
                Dbg.d(TAG, "SaxHandler, start parsing document");
            }
        }

        public void endDocument() throws SAXException {
            if (DEBUG) {
                Dbg.d(TAG, "SaxHandler, end parsing document");
            }
        }

        public void startElement(String uri, String localName, String qName, Attributes attributes)
                throws SAXException {

            if (TAG_NAME.equals(localName)) {
                if (DEBUG) {
                    Dbg.d(TAG, "SaxHandler, start element: " + qName);
                }
                try {
                    mFOut = new FileOutputStream(mTmpFile);
                    mReading = true;
                    mTotalWrite = 0;
                } catch (FileNotFoundException e) {
                    Dbg.printStackTrace(e);
                }
            }
        }

        public void endElement(String uri, String localName, String qName) throws SAXException {

            if (TAG_NAME.equals(localName)) {
                if (DEBUG) {
                    Dbg.d(TAG, "SaxHandler, end element: " + qName);
                }
                mReading = false;

                if (mFOut != null) {
                    try {
                        mFOut.close();
                    } catch (IOException e) {
                        Dbg.printStackTrace(e);
                    }
                    if (mTmpFile.exists()) {
                        if (mTmpFile.length() > 0) {
                            mComplete = decodeStream();
                        }
                        mTmpFile.delete();
                    }

                }
            }
        }

        public void characters(char ch[], int start, int length) throws SAXException {

            if (mReading) {
                String str = new String(ch, start, length);
                try {
                    mFOut.write(str.getBytes());
                    mTotalWrite += length;

                    if (DEBUG) {
                        // 10  - 
                        if (mTotalWrite % INFORM_WRITE_SIZE == 0) {
                            Dbg.d(TAG, "SaxHandler, write to outfile length: " + mTotalWrite);
                        }
                    }

                } catch (IOException e) {
                    Dbg.printStackTrace(e);
                }
            }
        }

        /**
         *   base64
         *
         * @return
         */
        public boolean decodeStream() {
            boolean isOk = false;

            if (mOutFile.exists()) {

            }
            FileInputStream fis = null;
            FileOutputStream fos = null;
            try {
                fis = new FileInputStream(mTmpFile);
                fos = new FileOutputStream(mOutFile);

                Base64InputStream base64Is = new Base64InputStream(fis, Base64.NO_WRAP);
                IOUtils.copy(base64Is, fos);

                isOk = true;
            } catch (FileNotFoundException e) {
                Dbg.printStackTrace(e);
            } catch (IOException e) {
                Dbg.printStackTrace(e);
            } finally {
                IOHelper.close(fis);
                IOHelper.close(fos);
            }
            return isOk;
        }

        public boolean isComplete() {
            return mComplete;
        }

    }
}