/*************************************************** * * * Mobicents: The Open Source VoIP Platform * * * * Distributable under LGPL license. * * See terms of license at gnu.org. * * * ***************************************************/ package org.mobicents.slee.container.deployment.interceptors; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.LinkedList; import javax.slee.TransactionRolledbackLocalException; import org.apache.log4j.Logger; import org.mobicents.slee.container.SleeContainer; import org.mobicents.slee.container.SleeContainerUtils; import org.mobicents.slee.container.component.deployment.jaxb.descriptors.SbbDescriptorImpl; import org.mobicents.slee.runtime.eventrouter.routingtask.EventRoutingTransactionData; import org.mobicents.slee.runtime.sbb.SbbConcrete; import org.mobicents.slee.runtime.sbb.SbbLocalObjectConcrete; /** * An invoker for the sbb local object. * * @author M. Ranganathan * @author Ivelin Ivanov */ public class SbbLocalObjectInterceptor { private static Logger logger = Logger .getLogger(SbbLocalObjectInterceptor.class); private ClassLoader myClassLoader; private boolean setRollbackOnly; public SbbLocalObjectInterceptor(SbbLocalObjectConcrete sbbLocalObject) { this.myClassLoader = sbbLocalObject.getContextClassLoader(); if (logger.isDebugEnabled()) { logger.debug("myClassLoader " + myClassLoader); } } public Object invokeAndReturnObject(final Object proxy, String methodName, final Object[] args, Class[] types) throws Exception { if (this.setRollbackOnly) { throw new TransactionRolledbackLocalException( "Previous invocation caused rollback"); } final ClassLoader oldClassLoader = SleeContainerUtils .getCurrentThreadClassLoader(); SleeContainer sleeContainer = SleeContainer.lookupFromJndi(); if (System.getSecurityManager()!=null) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { Thread.currentThread().setContextClassLoader(myClassLoader); return null; } }); else Thread.currentThread().setContextClassLoader(myClassLoader); SbbConcrete sbbConcrete = (SbbConcrete) proxy; String sbbEntityId = sbbConcrete.getSbbEntity().getSbbEntityId(); LinkedList<String> invokedsbbEntities = EventRoutingTransactionData.getFromTransactionContext().getInvokedSbbEntities(); try { final Method meth = proxy.getClass().getMethod(methodName, types); invokedsbbEntities.add(sbbEntityId); SbbDescriptorImpl descriptor = sbbConcrete.getSbbEntity().getSbbComponent().getDescriptor(); boolean isolateSecurityPermissions = descriptor.getSbbLocalInterface()==null?false:descriptor.getSbbLocalInterface().isIsolateSecurityPermissions(); if(!isolateSecurityPermissions) { return meth.invoke(proxy, args); }else { //This try catch is akward inside, but its simpler than copying parts of this code try { //This is required. Since domain chain may indicate RA for instance, or SLEE deployer. If we dont do that test: tests/runtime/security/Test1112012Test.xml and second one, w //will fail because domain of SLEE tck ra is too restrictive (or we have bad desgin taht allows this to happen?) Object result =AccessController.doPrivileged(new PrivilegedExceptionAction(){ public Object run() throws IllegalAccessException, InvocationTargetException{ return meth.invoke(proxy, args); }}); return result; } catch(PrivilegedActionException pae) { Throwable cause = pae.getException(); if(cause instanceof IllegalAccessException) { throw new RuntimeException(cause); } else if(cause instanceof InvocationTargetException ) { // Remember the actual exception is hidden inside the // InvocationTarget exception when you use reflection! Throwable realException = cause.getCause(); if (realException instanceof RuntimeException) { RuntimeException re = (RuntimeException) realException; throw re; } else if (realException instanceof Error) { Error re = (Error) realException; throw re; } else if (realException instanceof Exception) { Exception re = (Exception) realException; throw re; } }else { throw pae.getException(); } //FIXME: why this is required? return null; } } } catch (InvocationTargetException ex) { if (logger.isDebugEnabled()) logger.debug("Invocation resulted in exception: " + ex.getMessage()); if(ex.getCause() instanceof RuntimeException){ sleeContainer.getTransactionManager().setRollbackOnly(); this.setRollbackOnly = true; throw new TransactionRolledbackLocalException( "Invocation resulted in exception ! ", ex.getCause()); } else { if(ex.getCause() instanceof Exception) { throw (Exception) ex.getCause(); }else { throw new Exception(ex.getCause()); } } } catch (Exception ex) { if (logger.isDebugEnabled()) logger.error(ex.getMessage(), ex); throw ex; } finally { // FIXME remove the equals test once this model is bug proof if (!invokedsbbEntities.removeLast().equals(sbbEntityId)) { logger.error("last sbb entity id removed from event routing tx data was not the expected"); } if (System.getSecurityManager()!=null) AccessController.doPrivileged(new PrivilegedAction() { public Object run() { Thread.currentThread().setContextClassLoader( oldClassLoader); return null; } }); else Thread.currentThread().setContextClassLoader(oldClassLoader); } } // Invokers for the simple types public void invokeAndReturnvoid(Object proxy, String methodName, Object[] args, Class[] argTypes) throws Exception { invokeAndReturnObject(proxy, methodName, args, argTypes); } public boolean invokeAndReturnboolean(Object proxy, String methodName, Object[] args, Class[] argTypes) throws Exception { Object retval = invokeAndReturnObject(proxy, methodName, args, argTypes); logger.debug("invokeAndReturnboolean : returned = " + retval); return ((Boolean) retval).booleanValue(); } public int invokeAndReturnint(Object proxy, String methodName, Object[] args, Class[] types) throws Exception { Object retval = invokeAndReturnObject(proxy, methodName, args, types); if (logger.isDebugEnabled()) { logger.debug("invokeAndReturnint : returned = " + retval); } return ((Integer) retval).intValue(); } public long invokeAndReturnlong(Object proxy, String methodName, Object[] args, Class[] types) throws Exception { Object retval = invokeAndReturnObject(proxy, methodName, args, types); logger.debug("invokeAndReturnlong : returned = " + retval); return ((Long) retval).longValue(); } public double invokeAndReturndouble(Object proxy, String methodName, Object[] args, Class[] types) throws Exception { Object retval = invokeAndReturnObject(proxy, methodName, args, types); if (logger.isDebugEnabled()) { logger.debug("invokeAndReturndouble : returned = " + retval); } return ((Double) retval).doubleValue(); } public char invokeAndReturnchar(Object proxy, String methodName, Object[] args, Class[] types) throws Exception { Object retval = invokeAndReturnObject(proxy, methodName, args, types); logger.debug("invokeAndReturnchar : returned = " + retval); return ((Character) retval).charValue(); } public float invokeAndReturnfloat(Object proxy, String methodName, Object[] args, Class[] types) throws Exception { Object retval = invokeAndReturnObject(proxy, methodName, args, types); if (logger.isDebugEnabled()) { logger.debug("invokeAndReturnchar : returned = " + retval); } return ((Float) retval).floatValue(); } public float invokeAndReturnshort(Object proxy, String methodName, Object[] args, Class[] types) throws Exception { Object retval = invokeAndReturnObject(proxy, methodName, args, types); logger.debug("invokeAndReturnchar : returned = " + retval); return ((Short) retval).shortValue(); } }