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

org.xins.server.Function Maven / Gradle / Ivy

There is a newer version: 3.0
Show newest version
/*
 * $Id: Function.java,v 1.159 2011/02/12 17:59:13 agoubard Exp $
 *
 * See the COPYRIGHT file for redistribution and use restrictions.
 */
package org.xins.server;

import org.xins.common.FormattedParameters;
import org.xins.common.MandatoryArgumentChecker;
import org.xins.common.manageable.Manageable;

/**
 * Base class for function implementation classes.
 *
 * 

A function can be enabled or disabled using the * {@link #setEnabled(boolean)} method. A function that is enabled can be * invoked, while a function that is disabled cannot. By default a function * is enabled. * * @version $Revision: 1.159 $ $Date: 2011/02/12 17:59:13 $ * @author Ernst de Haan * * @since XINS 1.0.0 */ public abstract class Function extends Manageable { /** * Call result to be returned when a function is currently disabled. See * {@link #isEnabled()}. */ private static final FunctionResult DISABLED_FUNCTION_RESULT = new FunctionResult("_DisabledFunction"); /** * The API implementation this function is part of. This field cannot be * null. */ private final API _api; /** * The name of this function. This field cannot be null. */ private final String _name; /** * The version of the specification this function implements. This field * cannot be null. */ private final String _version; /** * Flag that indicates if this function is currently accessible. */ private boolean _enabled; /** * Lock object for _callCount. This field cannot be * null. */ private final Object _callCountLock = new Object(); /** * The total number of calls executed up until now. */ private int _callCount; /** * Statistics object linked to this function. This field cannot be * null. */ private final FunctionStatistics _statistics; /** * Constructs a new Function. * * @param api * the API to which this function belongs, not null. * * @param name * the name, not null. * * @param version * the version of the specification this function implements, not * null. * * @throws IllegalArgumentException * if api == null || name == null || version == null. */ protected Function(API api, String name, String version) throws IllegalArgumentException { // Check arguments MandatoryArgumentChecker.check("api", api, "name", name, "version", version); // Initialize fields _statistics = new FunctionStatistics(); _api = api; _name = name; _version = version; _enabled = true; // Notify the API that a Function has been added _api.functionAdded(this); } /** * Returns the API that contains this function. * * @return * the {@link API}, not null. */ public final API getAPI() { return _api; } /** * Returns the name of this function. * * @return * the name, not null. * * @since XINS 1.5.0. */ public final String getName() { return _name; } /** * Returns the specification version for this function. * * @return * the version, not null. */ final String getVersion() { return _version; } /** * Checks if this function is currently accessible. * * @return * true if this function is currently accessible, * false otherwise. * * @see #setEnabled(boolean) */ public final boolean isEnabled() { return _enabled; } /** * Sets if this function is currently accessible. * * @param enabled * true if this function should be accessible, * false if not. * * @see #isEnabled() */ public final void setEnabled(boolean enabled) { _enabled = enabled; } /** * Returns the call statistics for this function. * * @return * the statistics, never null. */ final FunctionStatistics getStatistics() { return _statistics; } /** * Assigns a new call ID for the caller. Every call to this method will * return an increasing number. * * @return * the assigned call ID, >= 0. */ final int assignCallID() { int callID; synchronized (_callCountLock) { callID = _callCount++; } return callID; } /** * Handles a call to this function (wrapper method). This method will call * {@link #handleCall(CallContext context)}. * * @param start * the start time of the call, as milliseconds since the * UNIX Epoch. * * @param functionRequest * the request, never null. * * @param ip * the IP address of the requester, never null. * * @return * the call result, never null. * * @throws IllegalStateException * if this object is currently not initialized. */ FunctionResult handleCall(long start, FunctionRequest functionRequest) throws IllegalStateException { // Check state first assertUsable(); // Assign a call ID int callID = assignCallID(); // Check if this function is enabled if (! _enabled) { performedCall(functionRequest, start, DISABLED_FUNCTION_RESULT); return DISABLED_FUNCTION_RESULT; } // Skipped the function call if asked to if (functionRequest.shouldSkipFunctionCall()) { Object inParams = new FormattedParameters(functionRequest.getParameters(), functionRequest.getDataElement()); Log.log_3516(functionRequest.getFunctionName(), inParams); performedCall(functionRequest, start, API.SUCCESSFUL_RESULT); return API.SUCCESSFUL_RESULT; } // Construct a CallContext object CallContext context = new CallContext(functionRequest, start, this, callID); FunctionResult result; try { // Handle the call result = handleCall(context); // Make sure the result is valid InvalidResponseResult invalidResponse = result.checkOutputParameters(); if (invalidResponse != null) { result = invalidResponse; String details = invalidResponse.toString(); Log.log_3501(functionRequest.getFunctionName(), callID, details); } } catch (Throwable exception) { result = _api.handleFunctionException(start, functionRequest, callID, exception); } // Update function statistics // We assume that this method will never throw any exception performedCall(functionRequest, start, result); return result; } /** * Handles a call to this function. * * @param context * the context for this call, never null. * * @return * the result of the call, never null. * * @throws Throwable * if anything goes wrong. */ protected abstract FunctionResult handleCall(CallContext context) throws Throwable; /** * Callback method that should be called after a call to this function. * This method will update the statistics for this funciton and perform * transaction logging. * *

This method should never throw any * {@link RuntimeException}. If it does, then that should be considered a * serious bug. * * @param functionRequest * the request, should not be null. * * @param ip * the ip of the requester, should not be null. * * @param start * the start time, as a number of milliseconds since the * UNIX Epoch. * * @param result * the call result, should not be null. * * @throws NullPointerException * if parameters == null || result == null. */ private final void performedCall(FunctionRequest functionRequest, long start, FunctionResult result) throws NullPointerException { // NOTE: Since XINS 1.0.0-beta11, callID is ignored. // Get the error code String code = result.getErrorCode(); // Update statistics and determine the duration of the call boolean isSuccess = code == null; long duration = _statistics.recordCall(start, isSuccess, code); Engine.logTransaction(functionRequest, result, start, duration); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy