All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.xins.client.FileServiceCaller Maven / Gradle / Ivy

The newest version!
/*
 * $Id: FileServiceCaller.java,v 1.25 2012/04/16 19:40:39 agoubard Exp $
 *
 * See the COPYRIGHT file for redistribution and use restrictions.
 */
package org.xins.client;


import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import org.xins.common.FormattedParameters;

import org.xins.common.MandatoryArgumentChecker;
import org.xins.common.Utils;
import org.xins.common.http.HTTPCallConfig;
import org.xins.common.http.HTTPCallException;
import org.xins.common.http.HTTPCallRequest;
import org.xins.common.http.HTTPCallResult;
import org.xins.common.http.HTTPCallResultData;
import org.xins.common.http.HTTPStatusCodeVerifier;
import org.xins.common.http.StatusCodeHTTPCallException;
import org.xins.common.service.CallConfig;
import org.xins.common.service.CallException;
import org.xins.common.service.CallRequest;
import org.xins.common.service.CallResult;
import org.xins.common.service.Descriptor;
import org.xins.common.service.GenericCallException;
import org.xins.common.service.IOCallException;
import org.xins.common.service.ServiceCaller;
import org.xins.common.service.TargetDescriptor;
import org.xins.common.service.UnsupportedProtocolException;
import org.xins.common.servlet.container.LocalServletHandler;
import org.xins.common.servlet.container.XINSServletResponse;
import org.xins.common.text.URLEncoding;

/**
 * Call a XINS API using the internal Servlet container. This service caller
 * doesn't send data over the network but directly invoke the Servlet method.
 *
 * @version $Revision: 1.25 $ $Date: 2012/04/16 19:40:39 $
 * @author Anthony Goubard
 *
 * @since XINS 1.5.0
 */
class FileServiceCaller extends ServiceCaller {

   /**
    * The pool of the loaded XINS APIs. The key is the location of the WAR
    * file, as a {@link TargetDescriptor}, the value is the {@link LocalServletHandler}.
    */
   private static HashMap SERVLETS = new HashMap();

   /**
    * Constructs a new HTTPServiceCaller object with the
    * specified descriptor and call configuration.
    *
    * @param descriptor
    *    the descriptor of the service, cannot be null.
    *
    * @param callConfig
    *    the call configuration, or null if a default one should
    *    be used.
    *
    * @throws IllegalArgumentException
    *    if descriptor == null.
    *
    * @throws UnsupportedProtocolException
    *    if descriptor is or contains a {@link TargetDescriptor}
    *    with an unsupported protocol.
    */
   public FileServiceCaller(Descriptor     descriptor,
                            HTTPCallConfig callConfig)
   throws IllegalArgumentException, UnsupportedProtocolException {

      // Call superclass constructor
      super(descriptor, callConfig);
   }

   /**
    * Constructs a new FileServiceCaller object with the
    * specified descriptor and call configuration.
    *
    * @param descriptor
    *    the descriptor of the service, cannot be null.
    *
    * @throws IllegalArgumentException
    *    if descriptor == null.
    *
    * @throws UnsupportedProtocolException
    *    if descriptor is or contains a {@link TargetDescriptor}
    *    with an unsupported protocol.
    */
   public FileServiceCaller(Descriptor descriptor)
   throws IllegalArgumentException, UnsupportedProtocolException {

      this(descriptor, (HTTPCallConfig) null);
   }

   /**
    * Returns a default CallConfig object. This method is called
    * by the ServiceCaller constructor if no
    * CallConfig object was given.
    *
    * 

The implementation of this method in class {@link FileServiceCaller} * returns a standard {@link HTTPCallConfig}. * * @return * a new {@link HTTPCallConfig} instance, never null. */ protected CallConfig getDefaultCallConfig() { return new HTTPCallConfig(); } protected CallResult createCallResult(CallRequest request, TargetDescriptor succeededTarget, long duration, List exceptions, Object result) throws ClassCastException { return new HTTPCallResult((HTTPCallRequest) request, succeededTarget, duration, exceptions, (HTTPCallResultData) result); } protected boolean isProtocolSupportedImpl(String protocol) { return "file".equalsIgnoreCase(protocol); } /** * Executes a request towards the specified target. If the call succeeds, * then a {@link HTTPCallResult} object is returned, otherwise a * {@link CallException} is thrown. * *

The implementation of this method in class * HTTPServiceCaller delegates to * {@link #call(HTTPCallRequest,HTTPCallConfig)}. * * @param request * the call request to be executed, must be an instance of class * {@link HTTPCallRequest}, cannot be null. * * @param callConfig * the call configuration, never null and should always be * an instance of class {@link HTTPCallConfig}. * * @param target * the target to call, cannot be null. * * @return * the result, if and only if the call succeeded, always an instance of * class {@link HTTPCallResult}, never null. * * @throws ClassCastException * if the specified request object is not null * and not an instance of class {@link HTTPCallRequest}. * * @throws IllegalArgumentException * if target == null || request == null. * * @throws CallException * if the call to the specified target failed. */ public Object doCallImpl(CallRequest request, CallConfig callConfig, TargetDescriptor target) throws ClassCastException, IllegalArgumentException, CallException { long start = System.currentTimeMillis(); long duration; LocalServletHandler servletHandler = SERVLETS.get(target); if (servletHandler == null) { String fileLocation = target.getURL(); try { File warFile = new File(new URI(fileLocation)); servletHandler = new LocalServletHandler(warFile); SERVLETS.put(target, servletHandler); } catch (URISyntaxException usex) { Log.log_2117(usex); } catch (ServletException sex) { Log.log_2117(sex); } } Map parameters = ((HTTPCallRequest) request).getParameters(); // Get the parameters for logging FormattedParameters params = new FormattedParameters(parameters, null, "", "?", 160); // Get URL value String url = target.getURL(); // Loop through the parameters StringBuffer query = new StringBuffer(255); query.append("/?"); for (Map.Entry parameter : parameters.entrySet()) { String key = parameter.getKey(); String value = parameter.getValue(); if (value == null) { value = ""; } // Add this parameter key/value combination. if (key != null) { if (query.length() > 2) { query.append("&"); } query.append(URLEncoding.encode(key)); query.append("="); query.append(URLEncoding.encode(value)); } } XINSServletResponse response; try { response = servletHandler.query(query.toString()); } catch (IOException exception) { duration = System.currentTimeMillis() - start; org.xins.common.Log.log_1109(exception, url, params, duration); throw new IOCallException(request, target, duration, exception); } // Retrieve the data returned from the call HTTPCallResultData data; try { String result = response.getResult(); byte[] resultData = null; if (result != null) { resultData = result.getBytes(response.getCharacterEncoding()); } data = new HTTPCallResultDataHandler(response.getStatus(), resultData); } catch (UnsupportedEncodingException ueex) { throw Utils.logProgrammingError(ueex); } // Determine the HTTP status code int code = data.getStatusCode(); duration = System.currentTimeMillis() - start; HTTPStatusCodeVerifier verifier = ((HTTPCallRequest)request).getStatusCodeVerifier(); // Status code is considered acceptable if (verifier == null || verifier.isAcceptable(code)) { org.xins.common.Log.log_1107(url, params, duration, code); // Status code is considered unacceptable } else { org.xins.common.Log.log_1108(url, params, duration, code); throw new StatusCodeHTTPCallException((HTTPCallRequest) request, target, duration, code); } return new HTTPCallResult((HTTPCallRequest) request, target, duration, null, data); } /** * Performs the specified request towards the HTTP service. If the call * succeeds with one of the targets, then a {@link HTTPCallResult} object * is returned, that combines the HTTP status code and the data returned. * Otherwise, if none of the targets could successfully be called, a * {@link CallException} is thrown. * * @param request * the call request, not null. * * @param callConfig * the call configuration to use, or null. * * @return * the result of the call, cannot be null. * * @throws IllegalArgumentException * if request == null. * * @throws GenericCallException * if the first call attempt failed due to a generic reason and all the * other call attempts failed as well. * * @throws HTTPCallException * if the first call attempt failed due to an HTTP-related reason and * all the other call attempts failed as well. */ public HTTPCallResult call(HTTPCallRequest request, HTTPCallConfig callConfig) throws IllegalArgumentException, GenericCallException, HTTPCallException { // Check preconditions MandatoryArgumentChecker.check("request", request); // Perform the call CallResult callResult; try { callResult = doCall(request, callConfig); // Allow GenericCallException, HTTPCallException and Error to proceed, // but block other kinds of exceptions and throw an Error instead. } catch (GenericCallException exception) { throw exception; } catch (HTTPCallException exception) { throw exception; } catch (Exception exception) { throw Utils.logProgrammingError(exception); } return (HTTPCallResult) callResult; } /** * Performs the specified request towards the HTTP service. If the call * succeeds with one of the targets, then a {@link HTTPCallResult} object * is returned, that combines the HTTP status code and the data returned. * Otherwise, if none of the targets could successfully be called, a * {@link CallException} is thrown. * * @param request * the call request, not null. * * @return * the result of the call, cannot be null. * * @throws IllegalArgumentException * if request == null. * * @throws GenericCallException * if the first call attempt failed due to a generic reason and all the * other call attempts failed as well. * * @throws HTTPCallException * if the first call attempt failed due to an HTTP-related reason and * all the other call attempts failed as well. */ public HTTPCallResult call(HTTPCallRequest request) throws IllegalArgumentException, GenericCallException, HTTPCallException { return call(request, (HTTPCallConfig) null); } /** * Container of the data part of an HTTP call result. * * @version $Revision: 1.25 $ $Date: 2012/04/16 19:40:39 $ * @author Anthony Goubard * * @since XINS 1.5.0 */ private static final class HTTPCallResultDataHandler implements HTTPCallResultData { /** * The HTTP status code. */ private final int _code; /** * The data returned. */ private final byte[] _data; /** * Constructs a new HTTPCallResultDataHandler object. * * @param code * the HTTP status code. * * @param data * the data returned from the call, as a set of bytes. */ HTTPCallResultDataHandler(int code, byte[] data) { _code = code; _data = data; } /** * Returns the HTTP status code. * * @return * the HTTP status code. */ public int getStatusCode() { return _code; } /** * Returns the result data as a byte array. Note that this is not a copy or * clone of the internal data structure, but it is a link to the actual * data structure itself. * * @return * a byte array of the result data, never null. */ public byte[] getData() { return _data; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy