jeeves.utils.XmlRequest.java Source code

Java tutorial

Introduction

Here is the source code for jeeves.utils.XmlRequest.java

Source

//=============================================================================
//===   Copyright (C) 2001-2005 Food and Agriculture Organization of the
//===   United Nations (FAO-UN), United Nations World Food Programme (WFP)
//===   and United Nations Environment Programme (UNEP)
//===
//===   This program is free software; you can redistribute it and/or modify
//===   it under the terms of the GNU General Public License as published by
//===   the Free Software Foundation; either version 2 of the License, or (at
//===   your option) any later version.
//===
//===   This program is distributed in the hope that it will be useful, but
//===   WITHOUT ANY WARRANTY; without even the implied warranty of
//===   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
//===   General Public License for more details.
//===
//===   You should have received a copy of the GNU General Public License
//===   along with this program; if not, write to the Free Software
//===   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//===
//===   Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
//===   Rome - Italy. email: GeoNetwork@fao.org
//==============================================================================

package jeeves.utils;

import jeeves.exceptions.BadSoapResponseEx;
import jeeves.exceptions.BadXmlResponseEx;
import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HostConfiguration;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.HttpState;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthPolicy;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.protocol.Protocol;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

//=============================================================================

public class XmlRequest {
    public enum Method {
        GET, POST
    }

    //---------------------------------------------------------------------------
    //---
    //--- Constructor
    //---
    //---------------------------------------------------------------------------

    public XmlRequest() {
        this(null, 80);
    }

    //---------------------------------------------------------------------------

    public XmlRequest(String host) {
        this(host, 80);
    }

    //---------------------------------------------------------------------------

    public XmlRequest(String host, int port) {
        this(host, port, "http");
    }

    public XmlRequest(String host, int port, String protocol) {
        this.host = host;
        this.port = port;
        this.protocol = protocol;

        setMethod(Method.GET);
        state.addCookie(cookie);
        client.setState(state);
        client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
        client.setHostConfiguration(config);
        List<String> authPrefs = new ArrayList<String>(2);
        authPrefs.add(AuthPolicy.DIGEST);
        authPrefs.add(AuthPolicy.BASIC);
        // This will exclude the NTLM authentication scheme 
        client.getParams().setParameter(AuthPolicy.AUTH_SCHEME_PRIORITY, authPrefs);
    }

    //---------------------------------------------------------------------------

    public XmlRequest(URL url) {
        this(url.getHost(), url.getPort() == -1 ? url.getDefaultPort() : url.getPort(), url.getProtocol());

        address = url.getPath();
        query = url.getQuery();
    }

    //---------------------------------------------------------------------------
    //---
    //--- API methods
    //---
    //---------------------------------------------------------------------------

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    public String getAddress() {
        return address;
    }

    public Method getMethod() {
        return method;
    }

    public String getSentData() {
        return sentData;
    }

    public String getReceivedData() {
        return receivedData;
    }

    //---------------------------------------------------------------------------

    public void setHost(String host) {
        this.host = host;
    }

    //---------------------------------------------------------------------------

    public void setPort(int port) {
        this.port = port;
    }

    //---------------------------------------------------------------------------

    public void setAddress(String address) {
        this.address = address;
    }

    //---------------------------------------------------------------------------

    public void setUrl(URL url) {
        host = url.getHost();
        port = (url.getPort() == -1) ? url.getDefaultPort() : url.getPort();
        protocol = url.getProtocol();
        address = url.getPath();
        query = url.getQuery();
    }

    //---------------------------------------------------------------------------

    public void setMethod(Method m) {
        method = m;
    }

    //---------------------------------------------------------------------------

    public void setUseSOAP(boolean yesno) {
        useSOAP = yesno;
    }

    //---------------------------------------------------------------------------

    public void setUseProxy(boolean yesno) {
        useProxy = yesno;
    }

    //---------------------------------------------------------------------------

    public void setProxyHost(String host) {
        proxyHost = host;
    }

    //---------------------------------------------------------------------------

    public void setProxyPort(int port) {
        proxyPort = port;
    }

    //---------------------------------------------------------------------------

    public void setProxyCredentials(String username, String password) {
        if (username == null || username.trim().length() == 0)
            return;

        Credentials cred = new UsernamePasswordCredentials(username, password);
        AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM);

        client.getState().setProxyCredentials(scope, cred);

        proxyAuthent = true;
    }

    //---------------------------------------------------------------------------

    public void clearParams() {
        alSimpleParams.clear();
        postParams = null;
    }

    //--------------------------------------------------------------------------

    public void addParam(String name, Object value) {
        if (value != null)
            alSimpleParams.add(new NameValuePair(name, value.toString()));

        method = Method.GET;
    }

    //---------------------------------------------------------------------------

    public void setRequest(Element request) {
        postParams = (Element) request.detach();
        method = Method.POST;
    }

    //---------------------------------------------------------------------------
    /** Sends an xml request and obtains an xml response */

    public Element execute(Element request) throws IOException, BadXmlResponseEx, BadSoapResponseEx {
        setRequest(request);
        return execute();
    }

    //---------------------------------------------------------------------------
    /** Sends a request and obtains an xml response. The request can be a GET or a
      * POST depending on the method used to set parameters. Calls to the 'addParam'
      * method set a GET request while the setRequest method sets a POST/xml request.
      */

    public Element execute() throws IOException, BadXmlResponseEx, BadSoapResponseEx {
        HttpMethodBase httpMethod = setupHttpMethod();

        Element response = doExecute(httpMethod);

        if (useSOAP)
            response = soapUnembed(response);

        return response;
    }

    //---------------------------------------------------------------------------
    /** Sends a request (using GET or POST) and save the content to a file. This
      * method does not store received data.
      */

    public void executeLarge(File outFile) throws IOException {
        HttpMethodBase httpMethod = setupHttpMethod();

        doExecuteLarge(httpMethod, outFile);
    }

    //---------------------------------------------------------------------------
    /** Sends the content of a file using a POST request and gets the response in
      * xml format.
      */

    public Element send(String name, File inFile) throws IOException, BadXmlResponseEx, BadSoapResponseEx {
        Part[] parts = new Part[alSimpleParams.size() + 1];

        int partsIndex = 0;

        parts[partsIndex] = new FilePart(name, inFile);

        for (NameValuePair nv : alSimpleParams)
            parts[++partsIndex] = new StringPart(nv.getName(), nv.getValue());

        PostMethod post = new PostMethod();
        post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
        post.addRequestHeader("Accept", !useSOAP ? "application/xml" : "application/soap+xml");
        post.setPath(address);
        post.setDoAuthentication(useAuthent());

        //--- execute request

        Element response = doExecute(post);

        if (useSOAP)
            response = soapUnembed(response);

        return response;
    }

    //---------------------------------------------------------------------------

    public void setCredentials(String username, String password) {
        Credentials cred = new UsernamePasswordCredentials(username, password);
        AuthScope scope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT, AuthScope.ANY_REALM);

        client.getState().setCredentials(scope, cred);
        client.getParams().setAuthenticationPreemptive(true);
        serverAuthent = true;
    }

    //---------------------------------------------------------------------------
    //---
    //--- Private methods
    //---
    //---------------------------------------------------------------------------

    private Element doExecute(HttpMethodBase httpMethod) throws IOException, BadXmlResponseEx {
        config.setHost(host, port, Protocol.getProtocol(protocol));

        if (useProxy)
            config.setProxy(proxyHost, proxyPort);

        byte[] data = null;

        try {
            client.executeMethod(httpMethod);
            data = httpMethod.getResponseBody();

            // HttpClient is unable to automatically handle redirects of entity
            // enclosing methods such as POST and PUT.
            // Get the location header and run the request against it.
            String redirectLocation;
            Header locationHeader = httpMethod.getResponseHeader("location");
            if (locationHeader != null) {
                redirectLocation = locationHeader.getValue();
                httpMethod.setPath(redirectLocation);
                client.executeMethod(httpMethod);
                data = httpMethod.getResponseBody();
            }
            return Xml.loadStream(new ByteArrayInputStream(data));
        }

        catch (JDOMException e) {
            throw new BadXmlResponseEx(new String(data, "UTF8"));
        }

        finally {
            httpMethod.releaseConnection();

            sentData = getSentData(httpMethod);
            receivedData = getReceivedData(httpMethod, data);
        }
    }

    //---------------------------------------------------------------------------

    private File doExecuteLarge(HttpMethodBase httpMethod, File outFile) throws IOException {
        config.setHost(host, port, Protocol.getProtocol(protocol));

        if (useProxy)
            config.setProxy(proxyHost, proxyPort);

        InputStream is = null;
        OutputStream os = null;

        try {
            client.executeMethod(httpMethod);

            is = httpMethod.getResponseBodyAsStream();
            os = new FileOutputStream(outFile);

            BinaryFile.copy(is, os, true, true);

            is.close();
            os.close();

            return outFile;
        } finally {
            if (is != null)
                is.close();

            if (os != null)
                os.close();

            httpMethod.releaseConnection();

            sentData = getSentData(httpMethod);

            //--- we do not save received data because it can be very large
        }
    }

    //---------------------------------------------------------------------------

    private HttpMethodBase setupHttpMethod() throws UnsupportedEncodingException {
        HttpMethodBase httpMethod;

        if (method == Method.GET) {
            httpMethod = new GetMethod();

            if (query != null && !query.equals(""))
                httpMethod.setQueryString(query);

            else if (alSimpleParams.size() != 0)
                httpMethod.setQueryString(alSimpleParams.toArray(new NameValuePair[alSimpleParams.size()]));

            httpMethod.addRequestHeader("Accept", !useSOAP ? "application/xml" : "application/soap+xml");
            httpMethod.setFollowRedirects(true);
        } else {
            PostMethod post = new PostMethod();

            if (!useSOAP) {
                postData = (postParams == null) ? "" : Xml.getString(new Document(postParams));
                post.setRequestEntity(new StringRequestEntity(postData, "application/xml", "UTF8"));
            } else {
                postData = Xml.getString(new Document(soapEmbed(postParams)));
                post.setRequestEntity(new StringRequestEntity(postData, "application/soap+xml", "UTF8"));
            }

            httpMethod = post;
        }

        httpMethod.setPath(address);
        httpMethod.setDoAuthentication(useAuthent());

        return httpMethod;
    }

    //---------------------------------------------------------------------------

    private String getSentData(HttpMethodBase httpMethod) {
        StringBuilder sentData = new StringBuilder(httpMethod.getName()).append(" ").append(httpMethod.getPath());

        if (httpMethod.getQueryString() != null) {
            sentData.append("?" + httpMethod.getQueryString());
        }

        sentData.append("\r\n");

        for (Header h : httpMethod.getRequestHeaders()) {
            sentData.append(h);
        }

        sentData.append("\r\n");

        if (httpMethod instanceof PostMethod) {
            sentData.append(postData);
        }

        return sentData.toString();
    }

    //---------------------------------------------------------------------------

    private String getReceivedData(HttpMethodBase httpMethod, byte[] response) {
        StringBuilder receivedData = new StringBuilder();

        try {
            //--- if there is a connection error (the server is unreachable) this
            //--- call causes a NullPointerEx

            receivedData.append(httpMethod.getStatusText()).append("\r\r");

            for (Header h : httpMethod.getResponseHeaders()) {
                receivedData.append(h);
            }

            receivedData.append("\r\n");

            if (response != null) {
                receivedData.append(new String(response, "UTF8"));
            }
        } catch (Exception e) {
            receivedData.setLength(0);
        }

        return receivedData.toString();
    }

    //---------------------------------------------------------------------------

    private Element soapEmbed(Element elem) {
        Element envl = new Element("Envelope", SOAPUtil.NAMESPACE_ENV);
        Element body = new Element("Body", SOAPUtil.NAMESPACE_ENV);

        envl.addContent(body);
        body.addContent(elem);

        return envl;
    }

    //---------------------------------------------------------------------------

    @SuppressWarnings("unchecked")
    private Element soapUnembed(Element envelope) throws BadSoapResponseEx {
        Namespace ns = envelope.getNamespace();
        Element body = envelope.getChild("Body", ns);

        if (body == null)
            throw new BadSoapResponseEx(envelope);

        List<Element> list = body.getChildren();

        if (list.size() == 0)
            throw new BadSoapResponseEx(envelope);

        return list.get(0);
    }

    //---------------------------------------------------------------------------

    private boolean useAuthent() {
        return proxyAuthent || serverAuthent;
    }

    //---------------------------------------------------------------------------
    //---
    //--- Variables
    //---
    //---------------------------------------------------------------------------

    private String host;
    private int port;
    private String protocol;
    private String address;
    private boolean serverAuthent;
    private String query;
    private Method method;
    private boolean useSOAP;
    private Element postParams;
    private boolean useProxy;
    private String proxyHost;
    private int proxyPort;
    private boolean proxyAuthent;

    private HttpClient client = new HttpClient();
    private HttpState state = new HttpState();
    private Cookie cookie = new Cookie();

    private HostConfiguration config = new HostConfiguration();

    private ArrayList<NameValuePair> alSimpleParams = new ArrayList<NameValuePair>();

    //--- transient vars

    private String sentData;
    private String receivedData;
    private String postData;
}

//=============================================================================