/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration),
* All rights reserved
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
package alma.acs.container;
import java.io.IOException;
import java.util.logging.Level;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.Servant;
import com.cosylab.CDB.DAL;
import si.ijs.maci.ComponentInfo;
import alma.ACS.ComponentStates;
import alma.JavaContainerError.wrappers.AcsJContainerEx;
import alma.JavaContainerError.wrappers.AcsJContainerServicesEx;
import alma.acs.classloading.AcsComponentClassLoader;
import alma.acs.component.ComponentLifecycle;
import alma.acs.component.ComponentLifecycleException;
import alma.acs.container.corba.AcsCorba;
import alma.acs.logging.AcsLogger;
import alma.maciErrType.ComponentDeactivationUncleanEx;
import alma.maciErrType.wrappers.AcsJComponentDeactivationFailedEx;
import alma.maciErrType.wrappers.AcsJComponentDeactivationUncleanEx;
/**
* Adapter between the container on the one side and a component with all its child objects on the other.
* For the component, ComponentAdapter
is the container,
* since it calls the ComponentLifecycle
methods.
* For the container, it represents the component with its meta data.
*
* @author hsommer Nov 6, 2002 2:48:13 PM
*/
public class ComponentAdapter
{
// fields from si.ijs.maci.ComponentInfo
private String m_type;
private String m_code;
private org.omg.CORBA.Object m_reference; // the corba object
private String m_compInstanceName;
private int[] m_clients;
private String m_containerName;
private int m_compHandle;
private int m_access;
private String[] m_interfaces;
// other fields
private AcsLogger m_containerLogger;
// the component itself and its XML translator proxy, if any
private ComponentLifecycle m_component;
// the tie skeleton that receives ORB calls
private Servant m_servant;
// the POA to be used for this component
private POA m_componentPOA;
// the servant manager for this component POA
private ComponentServantManager compServantManager;
private final AcsCorba acsCorba;
private final AcsManagerProxy m_managerProxy;
private final ClassLoader m_componentClassLoader;
private final ComponentStateManagerImpl m_componentStateManager;
private final ContainerServicesImpl m_containerServices;
private final CleaningDaemonThreadFactory m_threadFactory;
/**
* Method ComponentAdapter.
* @param compName component instance name (curl)
* @param type IDL type
* @param code Java impl class of the component helper (subclass of {@link ComponentHelper});
* @param compHandle component handle assigned by the manager
* @param containerName
* @param component the instance of the component implementation class
* @param managerProxy the shared manager proxy object
* @param componentClassLoader the classloader to be used as the currentThread-ClassLoader when component lifecycle methods are invoked.
* @param logger logger to be used by this class (not by the component though)
* @param acsCorba
* @throws AcsJContainerServicesEx
*/
ComponentAdapter(String compName, String type, String code,
int compHandle, String containerName,
ComponentLifecycle component,
AcsManagerProxy managerProxy, DAL cdb,
ClassLoader componentClassLoader,
AcsLogger logger,
AcsCorba acsCorba)
throws AcsJContainerEx
{
// store params
m_compInstanceName = compName;
m_type = type;
m_code = code;
m_compHandle = compHandle;
m_containerName = containerName;
m_component = component;
m_componentClassLoader = componentClassLoader;
m_containerLogger = logger;
this.acsCorba = acsCorba;
// init arrays to avoid nullpointer trouble
m_interfaces = new String[0];
m_clients = new int[0];
m_componentPOA = acsCorba.createPOAForComponent(m_compInstanceName);
m_componentStateManager = new ComponentStateManagerImpl(m_compInstanceName, m_containerLogger);
m_threadFactory = new CleaningDaemonThreadFactory(compName, m_containerLogger);
m_threadFactory.setNewThreadContextClassLoader(m_componentClassLoader);
m_managerProxy = managerProxy;
m_containerServices =
new ContainerServicesImpl(managerProxy, cdb, m_componentPOA, acsCorba, m_containerLogger,
m_compHandle, m_compInstanceName, m_componentStateManager, m_threadFactory);
}
void setComponentXmlTranslatorProxy(Object xmlTranslatorProxy) {
m_containerServices.setComponentXmlTranslatorProxy(xmlTranslatorProxy);
}
ContainerServicesImpl getContainerServices() {
return m_containerServices;
}
void activateComponent(Servant servant)
throws AcsJContainerEx
{
if (m_containerLogger.isLoggable(Level.FINER)) {
m_containerLogger.finer("entering ComponentAdapter#activateComponent for " + m_compInstanceName);
}
m_servant = servant;
try {
compServantManager = acsCorba.setServantManagerOnComponentPOA(m_componentPOA);
m_reference = acsCorba.activateComponent(servant, m_compInstanceName, m_componentPOA);
}
catch (Throwable thr) {
String msg = "failed to activate component " + m_compInstanceName + " of type " + m_component.getClass().getName();
AcsJContainerEx ex = new AcsJContainerEx(thr);
ex.setContextInfo(msg);
throw ex;
}
m_interfaces = _getInterfaces();
}
void initializeComponent() throws ComponentLifecycleException {
ClassLoader contCL = Thread.currentThread().getContextClassLoader();
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_INITIALIZING);
Throwable thr = null;
Thread.currentThread().setContextClassLoader(m_componentClassLoader);
try {
m_component.initialize(m_containerServices);
} catch (Throwable t) {
thr = t;
} finally {
Thread.currentThread().setContextClassLoader(contCL);
}
if (thr != null) {
if (thr instanceof ComponentLifecycleException) {
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_ERROR);
throw (ComponentLifecycleException) thr;
}
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_ERROR);
throw new ComponentLifecycleException(thr);
}
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_INITIALIZED);
}
void executeComponent() throws ComponentLifecycleException {
ClassLoader contCL = Thread.currentThread().getContextClassLoader();
Throwable thr = null;
Thread.currentThread().setContextClassLoader(m_componentClassLoader);
try {
m_component.execute();
} catch (Throwable t) {
thr = t;
} finally {
Thread.currentThread().setContextClassLoader(contCL);
}
if (thr != null) {
if (thr instanceof ComponentLifecycleException) {
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_ERROR);
throw (ComponentLifecycleException) thr;
}
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_ERROR);
throw new ComponentLifecycleException(thr);
}
m_componentStateManager.setStateByContainer(ComponentStates.COMPSTATE_OPERATIONAL);
}
private String[] _getInterfaces()
{
String[] interfaces = null;
try
{
interfaces = m_servant._all_interfaces(m_componentPOA, m_compInstanceName.getBytes());
if (m_containerLogger.isLoggable(Level.FINE)) {
StringBuffer buff = new StringBuffer("");
for (int i = 0; i < interfaces.length; i++)
{
buff.append(interfaces[i]);
}
m_containerLogger.fine("interfaces of component '" + m_compInstanceName + "': " + buff.toString());
}
}
catch (Exception ex)
{
m_containerLogger.info("failed to retrieve interface information for component " +
m_compInstanceName);
}
if (interfaces == null)
{
interfaces = new String[1];
interfaces[0] = "IDL:omg.org/CORBA/Object:1.0";
}
return interfaces;
}
/**
* Deactivates a component.
*
Runnable
that can abort the component in the following way.
* ABORTING
* DEFUNCT
* killComponentPOA==true
, destroys the POA for this component;
* ComponentStateManager
that gives acces to the state.
*/
ComponentStateManagerImpl getComponentStateManager()
{
return m_componentStateManager;
}
// @TODO
// /**
// * @return true if the component managed by this adapter declares itself to be stateless.
// */
// boolean isStatelessComponent() {
// return ( m_component instanceof StatelessComponentLifecycle );
// }
protected void finalize() throws Throwable {
if (m_containerLogger.isLoggable(Level.FINEST)) {
m_containerLogger.finest("finalize() called by JVM for impl classes of component " + getName() + '(' + getHandle() + ')');
}
super.finalize();
}
/**
* With this optional call, automatic invocation logging for certain component methods can be disabled.
* (Data will just be forwarded to containerServices)
* @param excludedMethods
* @see ComponentHelper#getComponentMethodsExcludedFromInvocationLogging()
*/
void setMethodsExcludedFromInvocationLogging(String[] excludedMethods) {
m_containerServices.setMethodsExcludedFromInvocationLogging(excludedMethods);
}
}