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

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

The newest version!
/*
 * $Id: AbstractCAPI.java,v 1.82 2012/03/03 21:23:44 agoubard Exp $
 *
 * See the COPYRIGHT file for redistribution and use restrictions.
 */
package org.xins.client;

import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.xins.common.MandatoryArgumentChecker;

import org.xins.common.collections.InvalidPropertyValueException;
import org.xins.common.collections.MissingRequiredPropertyException;

import org.xins.common.http.HTTPCallException;

import org.xins.common.service.Descriptor;
import org.xins.common.service.DescriptorBuilder;
import org.xins.common.service.GenericCallException;
import org.xins.common.service.TargetDescriptor;
import org.xins.common.service.UnsupportedProtocolException;

import org.xins.common.spec.APISpec;
import org.xins.common.spec.InvalidSpecificationException;

import org.xins.common.text.TextUtils;

/**
 * Base class for generated Client-side Application Programming Interface
 * (CAPI) classes.
 *
 * 

This class should not be derived from manually. This class is only * intended to be used as a superclass of CAPI classes generated * by the XINS framework. * *

The constructors of this class are considered internal to XINS and * should not be used directly. The behavior of the constructors may be * changed in later releases of XINS or they may even be removed. * * @version $Revision: 1.82 $ $Date: 2012/03/03 21:23:44 $ * @author Ernst de Haan * @author Anthony Goubard * * @since XINS 1.0.0 */ public abstract class AbstractCAPI { /** * Set of all CAPI classes for which the XINS version at build-time has * already been checked against the XINS version at run-time. Never * null. */ private static final Set> VERSION_COMPARISIONS_DONE = new HashSet>(); /** * The name of the API. This field cannot be null. */ private final String _apiName; /** * The XINS service caller to use. This field cannot be null. */ private final XINSServiceCaller _caller; /** * The API specification. This field is lazily initialized by * {@link #getAPISpecification()}. */ private APISpec _apiSpecification; /** * Creates a new AbstractCAPI object, using the specified * XINSServiceCaller. * *

This constructor is considered internal to XINS. Do not use it * directly. * * @param descriptor * the descriptor for the service(s), cannot be null. * * @param callConfig * fallback configuration for the calls, or null if a * default should be used. * * @throws IllegalArgumentException * if descriptor == null. * * @throws UnsupportedProtocolException * if any of the target descriptors in descriptor specifies * an unsupported protocol. * * @since XINS 1.1.0 */ protected AbstractCAPI(Descriptor descriptor, XINSCallConfig callConfig) throws IllegalArgumentException, UnsupportedProtocolException { // Check preconditions MandatoryArgumentChecker.check("descriptor", descriptor); // Create and store service caller _caller = new XINSServiceCaller(descriptor, callConfig); _caller.setCAPI(this); // Determine the API name _apiName = determineAPIName(); // Compare the XINS version at build- and run-time checkXINSVersion(); } /** * Creates a new AbstractCAPI object, using the specified * service descriptor. * *

A default XINS call configuration will be used. * *

This constructor is considered internal to XINS. Do not use it * directly. * * @param descriptor * the descriptor for the service(s), cannot be null. * * @throws IllegalArgumentException * if descriptor == null. * * @throws UnsupportedProtocolException * if any of the target descriptors in descriptor specifies * an unsupported protocol (since XINS 1.1.0). */ protected AbstractCAPI(Descriptor descriptor) throws IllegalArgumentException, UnsupportedProtocolException { this(descriptor, null); } /** * Creates a new AbstractCAPI object based on the specified * set of properties and the specified name. * *

A default XINS call configuration will be used. * *

This constructor is considered internal to XINS. Do not use it * directly. * * @param properties * the properties to read from, cannot be null. * * @param apiName * the name of the API, cannot be null and must be a valid * API name. * * @throws IllegalArgumentException * if properties == null || apiName == null or if * apiName is not considered to be a valid API name. * * @throws MissingRequiredPropertyException * if a required property is missing in the specified properties set. * * @throws InvalidPropertyValueException * if one of the properties in the specified properties set is used to * create a CAPI instance but its value is considered * invalid. * * @since XINS 1.2.0 */ protected AbstractCAPI(Map properties, String apiName) throws IllegalArgumentException, MissingRequiredPropertyException, InvalidPropertyValueException { // Check arguments MandatoryArgumentChecker.check("properties", properties, "apiName", apiName); // Determine property name String propName = "capis." + apiName; // Construct a XINS caller object _caller = new XINSServiceCaller(); // Build a descriptor from the properties Descriptor descriptor = DescriptorBuilder.build(_caller, properties, propName); // Associate caller with descriptor _caller.setDescriptor(descriptor); // Associate caller with this CAPI object _caller.setCAPI(this); // Determine the API name _apiName = determineAPIName(); // Compare the XINS version at build- and run-time checkXINSVersion(); } /** * Retrieves the name of the API (wrapper method). * * @return * the name of the API, or null if the name cannot be * determined. * * @since XINS 1.2.0 */ private String determineAPIName() { String apiName = getAPINameImpl(); if (! TextUtils.isEmpty(apiName)) { return apiName; } // Subclass did not return anything, determine based on package name String className = getClass().getName(); int index = className.lastIndexOf(".capi."); if (index > 0) { String s = className.substring(0, index); index = s.lastIndexOf('.'); s = s.substring(index + 1); if (! TextUtils.isEmpty(s)) { return s; } } return null; } /** * Determines the name of the API. * * @return * the name of the API, or a special indication (e.g. * "<unknown>") if the name cannot be determined; * never null. * * @since XINS 1.2.0 */ public final String getAPIName() { if (_apiName == null) { return ""; } else { return _apiName; } } /** * Returns true of the error code is a functional error code. * If unknown, false is returned. * * @param errorCode * the error code to check, cannot be null. * * @return * true if the error code is functional, false * if the error code is technical. */ protected boolean isFunctionalError(String errorCode) { return false; } /** * Retrieves the name of the API (implementation method). * *

The implementation of this method in class AbstractCAPI * returns null. * * @return * the name of the API, or null if unknown. * * @since XINS 1.2.0 */ protected String getAPINameImpl() { // NOTE: This method is not abstract, since that would make this class // incompatible with CAPI classes generated with older versions of // XINS (before 1.2.0) return null; } /** * Get the specification of the API. * * @return * the {@link APISpec} specification object. * * @throws InvalidSpecificationException * if the specification cannot be found or is invalid. * * @since XINS 1.3.0 */ public final APISpec getAPISpecification() throws InvalidSpecificationException { // Lazily initialize _apiSpecification if (_apiSpecification == null) { URL specsURL; CodeSource source = getClass().getProtectionDomain().getCodeSource(); if (source != null) { URL sourceURL = source.getLocation(); try { if (sourceURL.getPath().endsWith(".jar")) { specsURL = new URL("jar:" + sourceURL.toExternalForm() + "!/specs/"); } else { specsURL = new URL(sourceURL.toExternalForm() + "/specs/"); } } catch (MalformedURLException murlex) { Log.log_2116(murlex, getAPIName()); specsURL = getClass().getResource("/specs/"); } } else { specsURL = getClass().getResource("/specs/"); } _apiSpecification = new APISpec(getClass(), specsURL.toExternalForm()); } return _apiSpecification; } /** * Assigns the specified call configuration to this CAPI object. * * @param config * the call configuration to apply when executing a call with this CAPI * object, or null if no specific call configuration should be * associated with CAPI object; note that the call configuration can be * overridden by the request, see * {@link AbstractCAPICallRequest#configure(XINSCallConfig)}. * * @since XINS 1.2.0 */ public final void setXINSCallConfig(XINSCallConfig config) { _caller.setXINSCallConfig(config); } /** * Retrieves the call configuration currently associated with this CAPI * object. * * @return * the call configuration currently associated with this CAPI object, or * null if no specific call configuration is associated * with this cAPI object; note that the call configuration can be * overridden by the request, see * {@link AbstractCAPICallRequest#configuration()}. * * @since XINS 1.2.0 */ public final XINSCallConfig getXINSCallConfig() { return _caller.getXINSCallConfig(); } /** * Returns the XINS service caller to use. * *

This method is considered internal to XINS. It should not be * called directly, nor overridden. * *

This method is expected to be marked final in XINS * 2.0. This is not done yet to remain fully compatible with XINS 1.x. * * @return * the {@link XINSServiceCaller} to use, never null. */ protected final XINSServiceCaller getCaller() { return _caller; } /** * Checks if the XINS version used to build this CAPI class equals the * current XINS version. If not, a warning is logged. */ private void checkXINSVersion() { Class clazz = getClass(); if (! VERSION_COMPARISIONS_DONE.contains(clazz)) { // Compare build- and run-time version of XINS String buildVersion = getXINSVersion(); String runtimeVersion = Library.getVersion(); if (! buildVersion.equals(runtimeVersion)) { Log.log_2114(_apiName, buildVersion, runtimeVersion); } // Never check this CAPI class again VERSION_COMPARISIONS_DONE.add(clazz); } } /** * Returns the version of XINS used to build this CAPI class. * * @return * the version as a {@link String}, cannot be null. */ public abstract String getXINSVersion(); /** * Executes the specified call request. * *

This method is provided for CAPI subclasses. * * @param request * the call request to execute, cannot be null. * * @return * the result, not null. * * @throws IllegalArgumentException * if request == null. * * @throws UnacceptableRequestException * if the request is considered to be unacceptable; this is determined * by calling * request.{@link AbstractCAPICallRequest#checkParameters() checkParameters()}. * * @throws GenericCallException * if the first call attempt failed due to a generic reason and all the * other call attempts (if any) failed as well. * * @throws HTTPCallException * if the first call attempt failed due to an HTTP-related reason and * all the other call attempts (if any) failed as well. * * @throws XINSCallException * if the first call attempt failed due to a XINS-related reason and * all the other call attempts (if any) failed as well. * * @since XINS 1.2.0 */ protected final XINSCallResult callImpl(AbstractCAPICallRequest request) throws IllegalArgumentException, UnacceptableRequestException, GenericCallException, HTTPCallException, XINSCallException { // Check preconditions MandatoryArgumentChecker.check("request", request); // Check whether request is acceptable UnacceptableRequestException unacceptable = request.checkParameters(); if (unacceptable != null) { throw unacceptable; } // Execute the call request return _caller.call(request.xinsCallRequest()); } /** * Creates an AbstractCAPIErrorCodeException for the specified * error code. If the specified error code is not recognized, then * null is returned. * * @param request * the original request, should not be null. * * @param target * descriptor for the target that was attempted to be called, should not * be null. * * @param duration * the call duration in milliseconds, should be >= 0. * * @param resultData * the result data, should not be null and should have an * error code set. * * @return * if the error code is recognized, then a matching * {@link AbstractCAPIErrorCodeException} instance, otherwise * null. * * @throws IllegalArgumentException * if request == null * || target == null * || duration < 0 * || resultData == null * || resultData.getErrorCode() == null. * * @throws UnacceptableErrorCodeXINSCallException * if the specified error code is recognized but is considered * unacceptable for the function specified in the request. * * @since XINS 1.2.0 */ protected AbstractCAPIErrorCodeException createErrorCodeException(XINSCallRequest request, TargetDescriptor target, long duration, XINSCallResultData resultData) throws IllegalArgumentException, UnacceptableErrorCodeXINSCallException { // By default return nothing return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy