/******************************************************************************* * Copyright (c) 2016 Composent, Inc. and others. All rights reserved. This * program and the accompanying materials are made available under the terms of * the Eclipse Public License v1.0 which accompanies this distribution, and is * available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Composent, Inc. - initial API and implementation ******************************************************************************/ package org.eclipse.ecf.remoteservice.client; import java.lang.reflect.Method; import org.eclipse.ecf.core.util.ECFException; import org.eclipse.ecf.remoteservice.IRemoteCall; import org.eclipse.ecf.remoteservice.RemoteCall; import org.osgi.framework.ServiceException; /** * Abstract client remote service instance. This class should be overridden to implement the abstract * invokeAsync, and invokeSync methods, which will be called when the proxy created is called by clients. * * @since 8.9 */ public abstract class AbstractRSAClientService extends AbstractClientService { public static class RSARemoteCall extends RemoteCall { private final Object proxy; private final Method reflectMethod; public RSARemoteCall(Object proxy, Method method, String methodName, Object[] parameters, long timeout) { super(methodName, parameters, timeout); this.reflectMethod = method; this.proxy = proxy; } public Method getReflectMethod() { return reflectMethod; } public Object getProxy() { return proxy; } } /** * @param call the remote call to invoke * @param callable the remote callable to invoke * @return Object result of remote call * @throws ECFException if invoke fails */ @Override protected Object invokeRemoteCall(IRemoteCall call, IRemoteCallable callable) throws ECFException { return null; } public AbstractRSAClientService(AbstractClientContainer container, RemoteServiceClientRegistration registration) { super(container, registration); } /** * Invoke a remote call asynchronously. This method should not block and should return either a {@link org.eclipse.equinox.concurrent.future.IFuture}, {@link java.util.concurrent.Future}, or {@link java.util.concurrent.CompletableFuture} * or a * CompletableFuture based upon the return type defined in the asynchronous service interface. * * @param remoteCall the RSARemoteCall to use to make the asynchronous remote call. Will not be <code>null</code>. * @return Object. Should return a non-null instance of {@link org.eclipse.equinox.concurrent.future.IFuture}, {@link java.util.concurrent.Future}, or {@link java.util.concurrent.CompletableFuture} * @throws ECFException if async cannot be invoked */ protected abstract Object invokeAsync(RSARemoteCall remoteCall) throws ECFException; /** * Invoke a remote call synchronously. This method should block until a value may be returned, or the remote * call has failed or timed out. * * @param remoteCall the RSARemoteCall to synchronously invoke. Will not be <code>null</code>. * @return the result (of appropriate type) * @throws ECFException if some exception occurred during invocation */ protected abstract Object invokeSync(RSARemoteCall remoteCall) throws ECFException; protected RSARemoteCall createRemoteCall(Object proxy, Method method, String methodName, Object[] parameters, long timeout) { return new RSARemoteCall(proxy, method, methodName, parameters, timeout); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { Object resultObject = invokeObject(proxy, method, args); if (resultObject != null) return resultObject; if (isAsync(proxy, method, args)) return invokeAsync(createRemoteCall(proxy, method, getAsyncInvokeMethodName(method), args, IRemoteCall.DEFAULT_TIMEOUT)); final String callMethod = getCallMethodNameForProxyInvoke(method, args); final Object[] callParameters = getCallParametersForProxyInvoke(callMethod, method, args); final long callTimeout = getCallTimeoutForProxyInvoke(callMethod, method, args); return invokeSync(createRemoteCall(proxy, method, callMethod, callParameters, callTimeout)); } catch (Throwable t) { if (t instanceof ServiceException) throw t; // rethrow as service exception throw new ServiceException("Service exception on remote service proxy rsid=" + getRemoteServiceID(), ServiceException.REMOTE, t); //$NON-NLS-1$ } } }