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

com.oracle.bedrock.runtime.concurrent.callable.RemoteMethodInvocation Maven / Gradle / Ivy

Go to download

Interfaces, classes and resources to construct, inspect and manage runtime processes.

There is a newer version: 7.0.5
Show newest version
/*
 * File: RemoteMethodInvocation.java
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * The contents of this file are subject to the terms and conditions of 
 * the Common Development and Distribution License 1.0 (the "License").
 *
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the License by consulting the LICENSE.txt file
 * distributed with this file, or by consulting https://oss.oracle.com/licenses/CDDL
 *
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file LICENSE.txt.
 *
 * MODIFICATIONS:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 */

package com.oracle.bedrock.runtime.concurrent.callable;

import com.oracle.bedrock.runtime.concurrent.RemoteCallable;
import com.oracle.bedrock.util.ReflectionHelper;

import java.io.Serializable;
import java.lang.reflect.Method;

/**
 * A {@link RemoteCallable} representing a remote method invocation against
 * a remote instance (also represented by a {@link RemoteCallable}.
 * 

* Copyright (c) 2014. All Rights Reserved. Oracle Corporation.
* Oracle is a registered trademark of Oracle Corporation and/or its affiliates. * * @author Brian Oliver * * @param the type of the instance on which the method will be invoked */ public class RemoteMethodInvocation implements RemoteCallable { /** * The {@link RemoteCallable} that will produce the instance on which * to invoke the specified method. */ private RemoteCallable instanceProducer; /** * The name of the method to invoke on the instance. */ private String methodName; /** * The arguments for the method invocation. */ private Object[] arguments; /** * The optional (may be null) {@link Interceptor} to use * for intercepting {@link Method} invocations. */ private Interceptor interceptor; /** * Constructs a {@link RemoteMethodInvocation}. * * @param instanceProducer the {@link RemoteCallable} that produces the instance * on which the method should be invoked * @param methodName the name of the method to invoke * @param arguments the arguments to the instance * @param interceptor the optional (may be null) {@link Interceptor} */ public RemoteMethodInvocation(RemoteCallable instanceProducer, String methodName, Object[] arguments, Interceptor interceptor) { this.instanceProducer = instanceProducer; this.methodName = methodName; this.arguments = arguments; this.interceptor = interceptor; } /** * Obtain the {@link Interceptor} for the {@link RemoteMethodInvocation}. * * @return the {@link Interceptor} or null if not defined */ public Interceptor getInterceptor() { return interceptor; } @Override public Object call() throws Exception { T instance = instanceProducer.call(); if (instance == null) { throw new NullPointerException("Remote Instance is null"); } else { // find the compatible method on the instance Method method = ReflectionHelper.getCompatibleMethod(instance.getClass(), methodName, arguments); if (method == null) { throw new NoSuchMethodException(methodName); } else { // make the method accessible so we can call it method.setAccessible(true); if (interceptor != null) { interceptor.onBeforeInvocation(instance, method, arguments); } // invoke the method try { Object result = method.invoke(instance, arguments); // transform the result (if we have a transformer) if (interceptor != null) { result = interceptor.onAfterInvocation(instance, method, arguments, result); } return result; } catch (Exception e) { if (interceptor == null) { // rethrow if there's no interception happening throw e; } else { throw interceptor.onInvocationException(instance, method, arguments, e); } } } } } /** * Provides the ability to intercept remote {@link Method} invocations * so that arguments, results and exceptions may be transformed. */ public static interface Interceptor extends Serializable { /** * Called before the {@link Method} invocation occurs and the arguments * are serialized for dispatching remotely (to allow transforming * arguments prior to execution). *

* By implementing this {@link Method}, developers may change the * arguments submitted to the remote {@link Method}. Furthermore developers * may choose to throw unsupported exceptions should analysis of the * planned invocation prove to be unsupported, for example if one or more * arguments aren't serializable. * * @param method the {@link Method} to be invoked * @param arguments the supplied arguments to the {@link Method} * (these may be changed if necessary) */ public void onBeforeRemoteInvocation(Method method, Object[] arguments); /** * Called after the {@link Method} invocation has occurred and the resulting * result has deserialized but before the result has been returned locally * (to allow returning an alternative result). *

* By implementing this {@link Method}, developers may change the * returned result of the {@link Method}. Furthermore developers * may choose to throw various runtime time exceptions should analysis of the * invocation result prove to be unsupported or invalid. * * @param method the {@link Method} that was invoked * @param arguments the arguments supplied to the {@link Method} * @param result the returned result * * @return the result that should be returned */ public Object onAfterRemoteInvocation(Method method, Object[] arguments, Object result); /** * Called after the {@link Method} invocation has occurred and the * resulting {@link Exception} has been deserialized and before the * {@link Exception} has been raised locally (to allow throwing an * alternative {@link Exception}). *

* By implementing this {@link Method}, developers may change the * returned result of the {@link Method}. Furthermore developers * may choose to throw various runtime time exceptions should analysis the * invocation result prove to be unsupported or invalid. * * @param method the {@link Method} that was invoked * @param arguments the arguments supplied to the {@link Method} * @param exception the {@link Exception} that occurred * * @return the {@link Exception} to throw */ public Exception onRemoteInvocationException(Method method, Object[] arguments, Exception exception); /** * Called before the invocation of the {@link Method} on the provided * instance to allow transforming arguments prior to execution. * * @param instance the instance on which the {@link Method} will be invoked * (null when using static methods) * @param method the {@link Method} to be invoked * @param arguments the arguments supplied to the {@link Method} */ public void onBeforeInvocation(Object instance, Method method, Object[] arguments); /** * Called after the invocation of the {@link Method} on the provided * instance (to allow returning an alternative result). * * @param instance the instance on which the {@link Method} was invoked * (null when using static methods) * @param method the {@link Method} that was invoked * @param arguments the arguments supplied to the {@link Method} * @param result the returned result * * @return the result that should be returned */ public Object onAfterInvocation(Object instance, Method method, Object[] arguments, Object result); /** * Called after the invocation of the {@link Method} has produced an * {@link Exception} (to allow throwing an alternative {@link Exception}). * * @param instance the instance on which the {@link Method} was invoked * (null when using static methods) * @param method the {@link Method} that was invoked * @param arguments the arguments supplied to the {@link Method} * @param exception the {@link Exception} that occurred * * @return the {@link Exception} to be thrown */ public Exception onInvocationException(Object instance, Method method, Object[] arguments, Exception exception); } }