/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG 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: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.internal.communication.core.factory; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import javax.security.auth.Subject; import com.caucho.hessian.client.HessianRuntimeException; import com.caucho.hessian.io.HessianProtocolException; import org.eclipse.equinox.log.Logger; import org.eclipse.riena.communication.core.RemoteFailure; import org.eclipse.riena.communication.core.RemoteServiceDescription; import org.eclipse.riena.communication.core.hooks.AbstractHooksProxy; import org.eclipse.riena.communication.core.hooks.CallContext; import org.eclipse.riena.communication.core.hooks.ICallHook; import org.eclipse.riena.communication.core.hooks.ICallMessageContext; import org.eclipse.riena.communication.core.hooks.ICallMessageContextAccessor; import org.eclipse.riena.core.Log4r; import org.eclipse.riena.core.wire.InjectService; import org.eclipse.riena.core.wire.Wire; import org.eclipse.riena.internal.communication.core.Activator; public class CallHooksProxy extends AbstractHooksProxy { private final HashSet<ICallHook> callHooks = new HashSet<ICallHook>(); private RemoteServiceDescription rsd; private ICallMessageContextAccessor mca; private final static Logger LOGGER = Log4r.getLogger(Activator.getDefault(), CallHooksProxy.class); public CallHooksProxy(final Object proxiedInstance) { super(proxiedInstance); Wire.instance(this).andStart(Activator.getDefault().getContext()); } @Override public Object invoke(final Object proxy, final Method method, final Object[] args) throws Throwable { ICallMessageContext mc = null; if (mca != null) { mc = mca.createMessageContext(getProxiedInstance(), method.getName(), null); } final CallContext context = new CallContext(rsd, method.getName(), mc); if (callHooks.size() > 0) { // call before service hook for (final ICallHook callHook : callHooks) { callHook.beforeCall(context); } } final ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(rsd.getServiceClassLoader()); try { return super.invoke(proxy, method, args); } catch (final InvocationTargetException e) { Thread.currentThread().setContextClassLoader(oldClassLoader); // first check for specific Hessian exceptions if (e.getTargetException() instanceof HessianRuntimeException || e.getTargetException() instanceof HessianProtocolException) { Throwable cause = e.getTargetException(); while (cause.getCause() != null) { if (cause.getCause() instanceof RemoteFailure) { context.setRemoteFailure(true); throw cause.getCause(); } cause = cause.getCause(); } context.setRemoteFailure(true); throw new RemoteFailure("Error while invoking remote service", e.getTargetException()); //$NON-NLS-1$ } // if runtime exception throw it anyway if (e.getTargetException() instanceof RuntimeException) { throw e.getTargetException(); } // throw exception if it is in the method signature for (final Class<?> exceptionType : method.getExceptionTypes()) { if (exceptionType.isAssignableFrom(e.getTargetException().getClass())) { throw e.getTargetException(); } } // otherwise throw a remote failure context.setRemoteFailure(true); throw new RemoteFailure("Error while invoking remote service", e.getTargetException()); //$NON-NLS-1$ } finally { Thread.currentThread().setContextClassLoader(oldClassLoader); context.getMessageContext().fireEndCall(); // call hooks after the call if (callHooks.size() > 0) { for (final ICallHook callHook : callHooks) { callHook.afterCall(context); } } } } @InjectService public void bind(final ICallHook serviceHook) { callHooks.add(serviceHook); } public void unbind(final ICallHook serviceHook) { callHooks.remove(serviceHook); } public Object getCallProxy() { return getProxiedInstance(); } public void setRemoteServiceDescription(final RemoteServiceDescription rsd) { this.rsd = rsd; } public void setMessageContextAccessor(final ICallMessageContextAccessor mca) { this.mca = mca; } @Override public Subject getSubject() { return null; } }