fr.openwide.talendalfresco.rest.client.ClientCommandBase.java Source code

Java tutorial

Introduction

Here is the source code for fr.openwide.talendalfresco.rest.client.ClientCommandBase.java

Source

/*
 * Copyright (C) 2008-2012 Open Wide SA
 *  
 * This library is free software; you can redistribute 
 * it and/or modify it under the terms of version 2.1 of 
 * the GNU Lesser General Public License as published by  
 * the Free Software Foundation.
 * 
 * This library 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 Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General 
 * Public License along with this library; if not, write to the 
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
 * Boston, MA  02111-1307  USA
 * 
 * More information at http://knowledge.openwide.fr/bin/view/Main/AlfrescoETLConnector/
 */

package fr.openwide.talendalfresco.rest.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpMethodBase;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.EntityEnclosingMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.params.HttpMethodParams;

import fr.openwide.talendalfresco.rest.RestConstants;

/**
 * Base for client-side REST commands.
 * 
 * @author Marc Dutoo - Open Wide SA
 *
 */
public abstract class ClientCommandBase implements ClientCommand {

    enum HttpMType {
        GET, POST
    }

    protected HashSet<String> defaultResultElementSet = new HashSet<String>(
            Arrays.asList(new String[] { RestConstants.TAG_COMMAND, RestConstants.TAG_CODE, RestConstants.TAG_ERROR,
                    RestConstants.TAG_MESSAGE }));
    protected HashMap<String, String> elementValueMap = new HashMap<String, String>(6);

    protected String name;
    private HttpMType methodType;
    protected ArrayList<NameValuePair> params = new ArrayList<NameValuePair>(3);
    protected HashMap<String, NameValuePair> paramMap = new HashMap<String, NameValuePair>(3);
    protected RequestEntity requestEntity = null;

    protected String resultCode = null;
    protected String resultError = null;
    protected String resultMessage = null;

    // state vars used in result parsing :
    protected boolean isInCommandResponseContent = false;
    protected int commandResponseContentDepth = 0;
    protected StringBuffer singleLevelTextBuf = null;

    public ClientCommandBase(String name, HttpMType httpMethod) {
        this.name = name;
        this.methodType = httpMethod;
        //this.params.add("paramName", "paramValue");
        //this.defaultResultElementSet.add("myelt");
    }

    public String getName() {
        return this.name;
    }

    public HttpMType getMethodType() {
        return this.methodType;
    }

    public List<NameValuePair> getParams() {
        return params;
    }

    protected NameValuePair getParam(String paramName) {
        return paramMap.get(paramName);
    }

    protected void setParam(NameValuePair paramValue) {
        if (paramValue == null) {
            return;
        }
        NameValuePair oldValue = paramMap.put(paramValue.getName(), paramValue);
        int oldValueIndex = params.indexOf(oldValue);
        oldValueIndex = (oldValueIndex == -1) ? params.size() : oldValueIndex;
        params.add(oldValueIndex, paramValue);
    }

    /**
     * Can be overriden to tune the default behaviour,
     * check or build parameters...
     * The client should set the params (query string) itself.
     */
    public HttpMethodBase createMethod() throws RestClientException {
        // instantiating a new method and configuring it
        HttpMethodBase method;
        switch (this.getMethodType()) {
        case POST:
            //case PUT:
            method = new PostMethod();
            break;
        case GET:
        default:
            method = new GetMethod();
            method.setFollowRedirects(true);
        }
        method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
                new DefaultHttpMethodRetryHandler(3, false));
        //method.setQueryString(params.toArray(new NameValuePair[0])); // done in client
        //method.getParams().setContentCharset(this.restEncoding); // done in client

        // set request entity (allow to fill method body for posts) :
        if (requestEntity != null && method instanceof EntityEnclosingMethod) {
            ((EntityEnclosingMethod) method).setRequestEntity(requestEntity);
        }

        return method;
    }

    public String getResultCode() {
        return resultCode;
    }

    public String getResultError() {
        return resultError;
    }

    public String getResultMessage() {
        return resultMessage;
    }

    /**
     * Override if needed with any command specific behaviour.
     * Default is same as top level.
     * @param event
     */
    protected void handleResponseContentEvent(XMLEvent event) {
        handleResponseTopLevelEvent(event);
    }

    public final void handleResponse(XMLEventReader xmlReader) throws XMLStreamException {
        // Read the response body and parse it
        while (xmlReader.hasNext()) {
            XMLEvent event = xmlReader.nextEvent();

            if (isInCommandResponseContent) {

                // within command content tag case
                switch (event.getEventType()) {
                case XMLEvent.END_ELEMENT:
                    commandResponseContentDepth--;
                    if (commandResponseContentDepth == -1) {
                        // means the content tag has been closed
                        isInCommandResponseContent = false;
                    }
                    break;
                case XMLEvent.START_ELEMENT:
                    commandResponseContentDepth++;
                }
                // delegate impl of command content tag case
                handleResponseContentEvent(event);

            } else {

                // outside command content tag case
                handleResponseTopLevelEvent(event);
            }
        }

        resultCode = elementValueMap.get(RestConstants.TAG_CODE);
        resultError = elementValueMap.get(RestConstants.TAG_ERROR);
        resultMessage = elementValueMap.get(RestConstants.TAG_MESSAGE);
    }

    protected void handleResponseTopLevelEvent(XMLEvent event) {
        switch (event.getEventType()) {
        case XMLEvent.CHARACTERS:
        case XMLEvent.CDATA:
            if (singleLevelTextBuf != null) {
                singleLevelTextBuf.append(event.asCharacters().getData());
            } // else element not meaningful
            break;
        case XMLEvent.START_ELEMENT:
            StartElement startElement = event.asStartElement();
            String elementName = startElement.getName().getLocalPart();
            if (defaultResultElementSet.contains(elementName)) {
                // reinit buffer at start of meaningful elements
                singleLevelTextBuf = new StringBuffer();
            } else if (RestConstants.TAG_CONTENT.equals(elementName)) {
                // switch to content mode
                isInCommandResponseContent = true;
            } else {
                singleLevelTextBuf = null; // not useful
            }
            break;
        case XMLEvent.END_ELEMENT:
            if (singleLevelTextBuf == null) {
                break; // element not meaningful
            }

            // TODO or merely put it in the map since the element has been tested at start
            EndElement endElement = event.asEndElement();
            elementName = endElement.getName().getLocalPart();
            if (defaultResultElementSet.contains(elementName)) {
                String value = singleLevelTextBuf.toString();
                elementValueMap.put(elementName, value);
                // TODO test if it is code and it is not OK, break to error handling
            }
            // singleLevelTextBuf = new StringBuffer(); // no ! in start
            break;
        }
    }

    @SuppressWarnings("unchecked")
    public String toString() {
        StringBuffer sbuf = new StringBuffer();
        sbuf.append("Command ");
        sbuf.append(name);
        sbuf.append(" with parameters ");
        sbuf.append(String.valueOf(Arrays.asList(params)));
        sbuf.append(" and resultCode ");
        sbuf.append(resultCode);
        return sbuf.toString();
    }

}