Search in sources :

Example 1 with ComponentInvocationHandler

use of alma.acs.component.dynwrapper.ComponentInvocationHandler in project ACS by ACS-Community.

the class ContainerServicesImpl method activateOffShoot.

/**
	 * @see alma.acs.container.ContainerServices#activateOffShoot(org.omg.PortableServer.Servant)
	 */
@Override
public <T extends OffShootOperations> OffShoot activateOffShoot(T offshootImpl, Class<T> idlOpInterface) throws AcsJContainerServicesEx {
    Servant servant = null;
    boolean isTie = false;
    boolean haveToInject = false;
    // Checks
    checkOffShoot(offshootImpl);
    // and set the offshoot implementation as the final delegate
    if (!(offshootImpl instanceof Servant)) {
        if (idlOpInterface == null)
            throw new AcsJContainerServicesEx(new NullPointerException("Received null idlOpInterface when asking to activate XML offshoot"));
        if (!idlOpInterface.isAssignableFrom(offshootImpl.getClass())) {
            AcsJContainerServicesEx ex = new AcsJContainerServicesEx();
            ex.setContextInfo("Received OffShoot of type '" + offshootImpl.getClass().getName() + "' does not inherits from '" + idlOpInterface.getName() + "'");
            throw ex;
        }
        // Guess the name of the xyzPOATie class, build it, and delegate
        String poaTieClassName = null;
        try {
            m_logger.fine("Creating POATie servant for offshoot '" + offshootImpl.getClass().getName() + "'");
            // Get the POATie class and the expected xyzOperations interface
            String baseClassName = idlOpInterface.getName().substring(0, idlOpInterface.getName().length() - 1);
            poaTieClassName = baseClassName + "POATie";
            Class<?> poaTieClazz = Class.forName(poaTieClassName);
            Method implGetter = poaTieClazz.getMethod("_delegate", (Class[]) null);
            Class<?> operationsIF = implGetter.getReturnType();
            // Create the dynamic XML entities wrapper
            Object proxy = DynamicProxyFactory.getDynamicProxyFactory(m_logger).createServerProxy(operationsIF, offshootImpl, idlOpInterface);
            // Create the POATie object, give it the proxy, and set it as our servant
            Constructor<?> c = poaTieClazz.getConstructor(new Class[] { operationsIF });
            servant = (Servant) c.newInstance(proxy);
            if (m_componentXmlTranslatorProxy != null)
                haveToInject = true;
        } catch (ClassNotFoundException e) {
            String msg = "Failed to create servant for offshoot " + offshootImpl.getClass().getName() + ": class '" + poaTieClassName + "' cannot be found";
            m_logger.log(AcsLogLevel.ERROR, msg, e);
            AcsJContainerServicesEx ex = new AcsJContainerServicesEx();
            ex.setContextInfo(msg);
            throw ex;
        } catch (Exception e) {
            throw new AcsJContainerServicesEx(e);
        }
    } else {
        m_logger.fine("Don't need to create servant for offshoot '" + offshootImpl.getClass().getName() + "'");
        servant = (Servant) offshootImpl;
    }
    // check if the servant is the Tie variant, which allows proxy-based call interception by the container
    String servantName = servant.getClass().getName();
    if (servantName.endsWith("POATie")) {
        try {
            // the _delegate getter method is mandated by the IDL-to-Java mapping spec
            Method implGetter = servant.getClass().getMethod("_delegate", (Class[]) null);
            isTie = true;
            Class<?> operationsIF = implGetter.getReturnType();
            java.lang.Object offshootTiedImpl = implGetter.invoke(servant, (java.lang.Object[]) null);
            // now we insert the interceptor between the tie skeleton and the impl.
            // Offshoots have no name, so we construct one from the component name and the offshoot interface name
            // 
            String qualOffshootName = getName() + "/" + operationsIF.getName().substring(0, operationsIF.getName().length() - "Operations".length());
            java.lang.Object interceptingOffshootImpl = ContainerSealant.createContainerSealant(operationsIF, offshootTiedImpl, qualOffshootName, true, m_logger, Thread.currentThread().getContextClassLoader(), methodsExcludedFromInvocationLogging);
            Method implSetter = servant.getClass().getMethod("_delegate", new Class[] { operationsIF });
            implSetter.invoke(servant, new java.lang.Object[] { interceptingOffshootImpl });
            m_logger.fine("created sealant for offshoot " + qualOffshootName);
        } catch (NoSuchMethodException e) {
        // so this was not a Tie skeleton, even though its name ends misleadingly with "POATie"
        } catch (Exception e) {
            m_logger.log(Level.WARNING, "Failed to create interceptor for offshoot " + servantName, e);
        }
    }
    if (!isTie) {
    // TODO: perhaps require tie offshoots with ACS 5.0, and enable this warning log			
    //			m_logger.warning("Offshoot servant '" + servantName + "' from component '" + getName() + 
    //					"' does not follow the tie approach. Calls can thus not be intercepted by the container.");
    }
    OffShoot shoot = null;
    try {
        org.omg.CORBA.Object obj = acsCorba.activateOffShoot(servant, m_clientPOA);
        m_activatedOffshootsMap.put(offshootImpl, servant);
        shoot = OffShootHelper.narrow(obj);
    } catch (Throwable thr) {
        String msg = "failed to activate offshoot object of type '" + servant.getClass().getName() + "' for client '" + m_clientName + "'. ";
        // flatten the exception chain by one level if possible
        if (thr instanceof AcsJContainerServicesEx && thr.getCause() != null) {
            msg += "(" + thr.getMessage() + ")";
            thr = thr.getCause();
        }
        m_logger.log(Level.FINE, msg, thr);
        AcsJContainerServicesEx ex = new AcsJContainerServicesEx(thr);
        throw ex;
    }
    // so when requesting an offshoot into the component, we return the corresponding CORBA object
    if (haveToInject) {
        m_logger.fine("Injecting offshoot '" + offshootImpl.getClass().getName() + "' to '" + m_clientName + "' component XML binder");
        ComponentInvocationHandler handler = (ComponentInvocationHandler) Proxy.getInvocationHandler(m_componentXmlTranslatorProxy);
        handler.addOffshoot(offshootImpl, shoot);
    }
    m_logger.fine("successfully activated offshoot of type " + offshootImpl.getClass().getName());
    return shoot;
}
Also used : Method(java.lang.reflect.Method) AcsJContainerServicesEx(alma.JavaContainerError.wrappers.AcsJContainerServicesEx) Servant(org.omg.PortableServer.Servant) InvocationTargetException(java.lang.reflect.InvocationTargetException) AcsJException(alma.acs.exceptions.AcsJException) OffShoot(alma.ACS.OffShoot) ComponentInvocationHandler(alma.acs.component.dynwrapper.ComponentInvocationHandler)

Aggregations

OffShoot (alma.ACS.OffShoot)1 AcsJContainerServicesEx (alma.JavaContainerError.wrappers.AcsJContainerServicesEx)1 ComponentInvocationHandler (alma.acs.component.dynwrapper.ComponentInvocationHandler)1 AcsJException (alma.acs.exceptions.AcsJException)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1 Method (java.lang.reflect.Method)1 Servant (org.omg.PortableServer.Servant)1