org.fao.geonet.csw.common.requests.CatalogRequest.java Source code

Java tutorial

Introduction

Here is the source code for org.fao.geonet.csw.common.requests.CatalogRequest.java

Source

//=============================================================================
//===   Copyright (C) 2001-2007 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
//===
//===   Contact: Jeroen Ticheler - FAO - Viale delle Terme di Caracalla 2,
//===   Rome - Italy. email: geonetwork@osgeo.org
//==============================================================================

package org.fao.geonet.csw.common.requests;

import jeeves.server.context.ServiceContext;
import jeeves.utils.Log;
import jeeves.utils.Util;

import org.apache.commons.httpclient.Cookie;
import org.apache.commons.httpclient.Credentials;
import org.apache.commons.httpclient.Header;
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.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.lang.StringUtils;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.csw.common.Csw;
import org.fao.geonet.csw.common.exceptions.CatalogException;
import org.fao.geonet.csw.common.util.Xml;
import org.fao.geonet.lib.Lib;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

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

public abstract class CatalogRequest {
    public enum Method {
        GET, POST
    }

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

    public CatalogRequest() {
        this(null, null);
    }

    public CatalogRequest(ServiceContext context) {
        this(context, null);
    }

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

    public CatalogRequest(ServiceContext context, String host) {
        this(context, host, 80);
    }

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

    public CatalogRequest(ServiceContext context, String host, int port) {
        this(context, host, port, "http");
    }

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

    public CatalogRequest(ServiceContext context, String host, int port, String protocol) {
        this.host = host;
        this.port = port;
        this.protocol = protocol;

        setMethod(Method.POST);
        Cookie cookie = new Cookie();
        HttpState state = new HttpState();
        state.addCookie(cookie);
        client.setState(state);
        client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);

        if (context != null)
            Lib.net.setupProxy(context, client);
    }

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

    public String getHost() {
        return host;
    }

    public int getPort() {
        return port;
    }

    public String getProtocol() {
        return protocol;
    }

    public String getAddress() {
        return address;
    }

    public Method getMethod() {
        return method;
    }

    public String getSentData() {
        return sentData;
    }

    public String getReceivedData() {
        return receivedData;
    }

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

    public String getOutputSchema() {
        return outputSchema;
    }

    public void setOutputSchema(String outputSchema) {
        this.outputSchema = outputSchema;
    }

    public String getServerVersion() {
        return serverVersion;
    }

    public void setServerVersion(String serverVersion) {
        this.serverVersion = serverVersion;
    }

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

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

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

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

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

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

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

    //---------------------------------------------------------------------------
    /**
     * Set request URL host, port, address and path.
     * If URL contains query string parameters, those parameters are
     * preserved (and {@link CatalogRequest#excludedParameters} are
     * excluded). A complete GetCapabilities URL may be used for initialization.
     */
    public void setUrl(URL url) {
        this.host = url.getHost();
        this.port = url.getPort();
        this.protocol = url.getProtocol();
        this.address = url.toString();
        this.path = url.getPath();

        alSetupGetParams = new ArrayList<NameValuePair>();
        String query = url.getQuery();

        if (StringUtils.isNotEmpty(query)) {
            String[] params = query.split("&");
            for (String param : params) {
                String[] kvp = param.split("=");
                if (!excludedParameters.contains(kvp[0].toLowerCase())) {
                    this.alSetupGetParams.add(new NameValuePair(kvp[0], kvp[1]));
                }
            }
        }

        if (this.port == -1) {
            this.port = url.getDefaultPort();
        }
    }

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

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

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

    public void setLoginAddress(String address) {
        loginAddr = address;
    }

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

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

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

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

    public Element execute() throws Exception {
        HttpMethodBase httpMethod = setupHttpMethod();

        Element response = doExecute(httpMethod);

        if (useSOAP)
            response = soapUnembed(response);

        //--- raises an exception if the case
        CatalogException.unmarshal(response);

        return response;
    }

    public boolean login(String username, String password) throws Exception

    {
        Element request = new Element("request").addContent(new Element("username").setText(username))
                .addContent(new Element("password").setText(password));

        PostMethod post = new PostMethod();

        postData = Xml.getString(new Document(request));

        post.setRequestEntity(new StringRequestEntity(postData, "application/xml", "UTF8"));
        //      post.setFollowRedirects(true);
        post.setPath(loginAddr);

        Element response = doExecute(post);

        if (Csw.NAMESPACE_ENV.getURI().equals(response.getNamespace().getURI()))
            response = soapUnembed(response);

        return response.getName().equals("ok");
    }

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

    public void setCredentials(String username, String password) {
        this.useAuthent = true;
        this.username = username;
        this.password = password;
    }

    //---------------------------------------------------------------------------
    //---
    //--- Abstract methods
    //---
    //---------------------------------------------------------------------------

    protected abstract String getRequestName();

    protected abstract void setupGetParams();

    protected abstract Element getPostParams();

    //---------------------------------------------------------------------------
    //---
    //--- Protected methods
    //---
    //---------------------------------------------------------------------------

    //---------------------------------------------------------------------------
    //--- GET fill methods
    //---------------------------------------------------------------------------

    protected void fill(String param, Iterable iter) {
        fill(param, iter, "");
    }

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

    protected void fill(String param, Iterable iter, String prefix) {
        Iterator i = iter.iterator();

        if (!i.hasNext())
            return;

        StringBuffer sb = new StringBuffer();

        while (i.hasNext()) {
            sb.append(prefix);
            sb.append(i.next());

            if (i.hasNext())
                sb.append(',');
        }

        addParam(param, sb.toString());
    }

    //---------------------------------------------------------------------------
    //--- POST fill methods
    //---------------------------------------------------------------------------

    protected void fill(Element root, String parentName, String childName, Iterable iter, Namespace ns) {
        Iterator i = iter.iterator();

        if (!i.hasNext())
            return;

        Element parent = new Element(parentName, ns);

        while (i.hasNext()) {
            Element el = new Element(childName, ns);
            el.setText(i.next().toString());

            parent.addContent(el);
        }

        root.addContent(parent);
    }

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

    protected void fill(Element root, String childName, Iterable iter) {
        Iterator i = iter.iterator();

        if (!i.hasNext())
            return;

        while (i.hasNext()) {
            Element el = new Element(childName, root.getNamespace());
            el.setText(i.next().toString());

            root.addContent(el);
        }
    }

    //---------------------------------------------------------------------------
    //--- Attribute facilities
    //---------------------------------------------------------------------------

    protected void setAttrib(Element el, String name, Object value) {
        setAttrib(el, name, value, "");
    }

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

    protected void setAttrib(Element el, String name, Object value, String prefix) {
        if (value != null)
            el.setAttribute(name, prefix + value.toString());
    }

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

    protected void setAttrib(Element el, String name, Iterable iter, String prefix) {
        Iterator i = iter.iterator();

        if (!i.hasNext())
            return;

        StringBuffer sb = new StringBuffer();

        while (i.hasNext()) {
            sb.append(prefix);
            sb.append(i.next().toString());

            if (i.hasNext())
                sb.append(" ");
        }

        el.setAttribute(name, sb.toString());
    }

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

    protected void setAttribComma(Element el, String name, Iterable iter, String prefix) {
        Iterator i = iter.iterator();

        if (!i.hasNext())
            return;

        StringBuffer sb = new StringBuffer();

        while (i.hasNext()) {
            Object value = i.next();

            sb.append(prefix);
            sb.append(value.toString());

            if (i.hasNext())
                sb.append(',');
        }

        el.setAttribute(name, sb.toString());
    }
    //--------------------------------------------------------------------------
    //--- Parameters facilities (POST)
    //---------------------------------------------------------------------------

    protected void addParam(Element root, String name, Object value) {
        if (value != null)
            root.addContent(new Element(name, Csw.NAMESPACE_CSW).setText(value.toString()));
    }

    //---------------------------------------------------------------------------
    //--- Parameters facilities (GET)
    //--------------------------------------------------------------------------

    protected void addParam(String name, Object value) {
        addParam(name, value, "");
    }

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

    protected void addParam(String name, Object value, String prefix) {
        if (value != null)
            alGetParams.add(new NameValuePair(name, prefix + value.toString()));
    }

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

    private Element doExecute(HttpMethodBase httpMethod) throws IOException, JDOMException {
        client.getHostConfiguration().setHost(host, port, protocol);

        byte[] data = null;

        try {
            client.executeMethod(httpMethod);

            ///data = httpMethod.getResponseBody();
            // If server return HTTP Error 500 Server error 
            // when retrieving the data return null
            if (httpMethod.getStatusCode() == 500) {
                System.out.println("  Status code: " + httpMethod.getStatusCode());
                return null;
            } else {
                return Xml.loadStream(httpMethod.getResponseBodyAsStream());
            }
        } finally {
            httpMethod.releaseConnection();
            try {
                setupSentData(httpMethod);
                setupReceivedData(httpMethod, data);
            } catch (Throwable e) {
                Log.warning(Geonet.HARVESTER,
                        "Exception was raised during cleanup of a CSW request : " + Util.getStackTrace(e));
            }
        }
    }

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

    private HttpMethodBase setupHttpMethod() throws UnsupportedEncodingException {
        HttpMethodBase httpMethod;

        if (method == Method.GET) {
            alGetParams = new ArrayList<NameValuePair>();

            if (alSetupGetParams.size() != 0) {
                alGetParams.addAll(alSetupGetParams);
            }

            setupGetParams();
            httpMethod = new GetMethod();
            httpMethod.setPath(path);
            httpMethod.setQueryString(alGetParams.toArray(new NameValuePair[1]));
            System.out.println("GET params:" + httpMethod.getQueryString());
            if (useSOAP)
                httpMethod.addRequestHeader("Accept", "application/soap+xml");
        } else {
            Element params = getPostParams();
            PostMethod post = new PostMethod();
            if (!useSOAP) {
                postData = Xml.getString(new Document(params));
                post.setRequestEntity(new StringRequestEntity(postData, "application/xml", "UTF8"));
            } else {
                postData = Xml.getString(new Document(soapEmbed(params)));
                post.setRequestEntity(new StringRequestEntity(postData, "application/soap+xml", "UTF8"));
            }
            System.out.println("POST params:" + Xml.getString(params));
            httpMethod = post;
            httpMethod.setPath(path);
        }

        //      httpMethod.setFollowRedirects(true);

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

            client.getState().setCredentials(scope, cred);
            httpMethod.setDoAuthentication(true);
        }

        return httpMethod;
    }

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

    private void setupSentData(HttpMethodBase httpMethod) {
        sentData = httpMethod.getName() + " " + httpMethod.getPath();

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

        sentData += "\r\n";

        for (Header h : httpMethod.getRequestHeaders())
            sentData += h;

        sentData += "\r\n";

        if (httpMethod instanceof PostMethod)
            sentData += postData;
    }

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

    private void setupReceivedData(HttpMethodBase httpMethod, byte[] response) {
        receivedData = httpMethod.getStatusText() + "\r\r";

        for (Header h : httpMethod.getResponseHeaders())
            receivedData += h;

        receivedData += "\r\n";

        try {
            if (response != null)
                receivedData += new String(response, "UTF8");
        } catch (UnsupportedEncodingException e) {
            // TODO what's this ?
        }
    }

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

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

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

        return envl;
    }

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

    private Element soapUnembed(Element envelope) throws Exception {
        Namespace ns = envelope.getNamespace();
        Element body = envelope.getChild("Body", ns);

        if (body == null)
            throw new Exception("Bad SOAP response");

        List list = body.getChildren();

        if (list.size() == 0)
            throw new Exception("Bas SOAP response");

        return (Element) list.get(0);
    }

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

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    private String host;
    private int port;
    private String protocol;
    private String address;
    private String path;
    private String loginAddr;
    private Method method;
    private boolean useSOAP;
    private boolean useAuthent;
    private String username;
    private String password;
    protected String outputSchema;

    protected String serverVersion = Csw.CSW_VERSION; // Sets default value

    private HttpClient client = new HttpClient();

    private ArrayList<NameValuePair> alGetParams;
    private ArrayList<NameValuePair> alSetupGetParams;

    // Parameters to not take into account in GetRequest
    private static final List<String> excludedParameters = Arrays.asList("", "request", "version", "service");

    //--- transient vars

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

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