/* * @@COPYRIGHT@@ */ package com.cosylab.acs.maci.plug; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.util.HashMap; import java.util.Map; import java.util.logging.Logger; import org.omg.CORBA.NO_RESOURCES; import org.omg.CORBA.TIMEOUT; import org.omg.CORBA.UNKNOWN; import si.ijs.maci.CBComponentInfo; import si.ijs.maci.CBComponentInfoPOA; import alma.ACS.CBDescIn; import alma.ACS.CBDescOut; import alma.ACSErr.Completion; import alma.acs.exceptions.AcsJCompletion; import alma.acs.exceptions.AcsJException; import alma.acs.logging.AcsLogLevel; import alma.acs.logging.ClientLogManager; import alma.maciErrType.CannotActivateComponentEx; import alma.maciErrType.CannotDeactivateComponentEx; import alma.maciErrType.ComponentDeactivationFailedEx; import alma.maciErrType.ComponentDeactivationUncleanEx; import alma.maciErrType.wrappers.AcsJCannotActivateComponentEx; import alma.maciErrType.wrappers.AcsJCannotDeactivateComponentEx; import alma.maciErrType.wrappers.AcsJComponentDeactivationFailedEx; import alma.maciErrType.wrappers.AcsJComponentDeactivationUncleanEx; import com.cosylab.acs.maci.AccessRights; import com.cosylab.acs.maci.Component; import com.cosylab.acs.maci.ComponentInfo; import com.cosylab.acs.maci.Container; import com.cosylab.acs.maci.IntArray; import com.cosylab.acs.maci.RemoteException; import com.cosylab.acs.maci.TimeoutRemoteException; /** * CORBA Container Proxy. * * @author Matej Sekoranja (matej.sekoranja@cosylab.com) * @version @@VERSION@@ */ public class ContainerProxy extends ClientProxy implements Container { /** * Serial version UID. */ private static final long serialVersionUID = -7485420616224721204L; /** * CORBA reference. */ protected si.ijs.maci.Container container; protected static final Logger logger = ClientLogManager.getAcsLogManager().getLoggerForApplication("Manager-ContainerProxy", true); /** * Constructor for ContainerProxy. * @param container CORBA reference, non-<code>null</code>. */ public ContainerProxy(si.ijs.maci.Container container) { super(container); this.container = container; this.ior = serialize(container); activateCallback(); } @Override public int get_handle() { try { return container.get_handle(); } catch (TIMEOUT tex) { TimeoutRemoteException re = new TimeoutRemoteException("Timout occured while invoking 'get_handle()' method.", tex); throw re; } catch (Exception ex) { RemoteException re = new RemoteException("Failed to invoke 'get_handle()' method.", ex); throw re; } } /** * @see com.cosylab.acs.maci.Container#activate_component(int, long, String, String, String) */ public ComponentInfo activate_component(int handle, long executionId, String name, String exe, String type) throws AcsJCannotActivateComponentEx { try { ComponentInfo retVal = null; si.ijs.maci.ComponentInfo info; try { info = container.activate_component(handle, executionId, name, exe, type); } catch (CannotActivateComponentEx cannotActivateEx) { // we want to keep the ErrorTrace of the IDL-declared CannotActivateComponentEx when wrapping it with other exceptions, // and thus have to convert it to its JDK-style peer exception throw AcsJCannotActivateComponentEx.fromCannotActivateComponentEx(cannotActivateEx); } if (info != null) { retVal = new ComponentInfo(info.h, info.name, info.type, info.code, info.reference != null ? new ComponentProxy(info.name, info.reference) : null); retVal.setContainer(info.container); retVal.setContainerName(info.container_name); retVal.setAccessRights(inverseMapAccessRights(info.access)); retVal.setClients(new IntArray(info.clients)); retVal.setInterfaces(info.interfaces); } return retVal; } catch (TIMEOUT tex) { TimeoutRemoteException re = new TimeoutRemoteException("Timout occured while invoking 'activate_component()' method.", tex); throw re; } catch (org.omg.CORBA.MARSHAL marshalEx) { // see http://jira.alma.cl/browse/COMP-4371. Unclear if a parameter was null, or the returned struct was invalid. RemoteException re = new RemoteException("Failed to transform the paramters or return value of the container's 'activate_component' method " + "to/from the corba call, using parameters name=" + name + ", exe=" + exe + ", type=" + type, marshalEx); throw re; } catch (Exception ex) { RemoteException re = new RemoteException("Failed to invoke 'activate_component()' method.", ex); throw re; } } private CBComponentInfoImpl componentInfoCBServant; private CBComponentInfo componentInfoCB; void activateCallback() { componentInfoCBServant = new CBComponentInfoImpl(); componentInfoCB = componentInfoCBServant._this(getOrb()); } // TODO timeout class CBComponentInfoImpl extends CBComponentInfoPOA { private Map<Integer, ComponentInfoCompletionCallback> lookupTable = new HashMap<Integer, ComponentInfoCompletionCallback>(); private int id = 0; public CBDescIn register(ComponentInfoCompletionCallback cb) { synchronized (lookupTable) { // possible endless loop while (lookupTable.containsKey(++id)) ; lookupTable.put(id, cb); return new CBDescIn(0, 0, id); } } public ComponentInfoCompletionCallback unregister(int id) { synchronized (lookupTable) { return lookupTable.remove(id); } } @Override public void working(si.ijs.maci.ComponentInfo value, Completion c, CBDescOut desc) { // noop } @Override public void done(si.ijs.maci.ComponentInfo info, Completion c, CBDescOut desc) { logger.log(AcsLogLevel.DEBUG, "CBComponentInfo.done called with desc.id_tag = " + desc.id_tag); ComponentInfoCompletionCallback cb = null; try { cb = unregister(desc.id_tag); if (cb != null) { ComponentInfo retVal = null; if (info != null) { retVal = new ComponentInfo(info.h, info.name, info.type, info.code, info.reference != null ? new ComponentProxy(info.name, info.reference) : null); retVal.setContainer(info.container); retVal.setContainerName(info.container_name); retVal.setAccessRights(inverseMapAccessRights(info.access)); retVal.setClients(new IntArray(info.clients)); retVal.setInterfaces(info.interfaces); } AcsJException ex = AcsJCompletion.fromCorbaCompletion(c).getAcsJException(); if (ex == null) cb.done(retVal); else cb.failed(retVal, ex); } else { NO_RESOURCES nr = new NO_RESOURCES("Unknown 'desc.id_tag' (" + desc.id_tag + ") parameter for CBComponentInfo.done received."); logger.log(AcsLogLevel.WARNING, nr.getMessage(), nr); throw nr; } } catch (NO_RESOURCES nre) { // simply rethrow throw nre; } catch (Throwable thr) { // See AIV-9450, AIV-11149: We may fail to call "cb.done" if some unexpected exception gets thrown here... logger.log(AcsLogLevel.SEVERE, "Failed to process data about a freshly activated component.", thr); // best effort, to at least release the waiting requesting client. if (cb != null) { cb.failed(null, thr); } // report this back to the container throw new UNKNOWN("Unexpected exception caught while processing CBComponentInfo.done() callback."); } } @Override public boolean negotiate(long time_to_transmit, CBDescOut desc) { // not used return false; } } public void activate_component_async(int handle, long executionId, String name, String exe, String type, ComponentInfoCompletionCallback callback) { CBDescIn cbIn = componentInfoCBServant.register(callback); try { container.activate_component_async(handle, executionId, name, exe, type, componentInfoCB, cbIn ); } catch (TIMEOUT tex) { componentInfoCBServant.unregister(cbIn.id_tag); TimeoutRemoteException re = new TimeoutRemoteException("Timout occured while invoking 'activate_component()' method.", tex); throw re; } catch (org.omg.CORBA.MARSHAL marshalEx) { componentInfoCBServant.unregister(cbIn.id_tag); // see http://jira.alma.cl/browse/COMP-4371. Unclear if a parameter was null, or the returned struct was invalid. RemoteException re = new RemoteException("Failed to transform the paramters or return value of the container's 'activate_component' method " + "to/from the corba call, using parameters name=" + name + ", exe=" + exe + ", type=" + type, marshalEx); throw re; } catch (Exception ex) { componentInfoCBServant.unregister(cbIn.id_tag); RemoteException re = new RemoteException("Failed to invoke 'activate_component()' method.", ex); throw re; } } /** * @see com.cosylab.acs.maci.Container#deactivate_component(int) */ public void deactivate_component(int handle) throws AcsJCannotDeactivateComponentEx, AcsJComponentDeactivationUncleanEx,AcsJComponentDeactivationFailedEx { try { container.deactivate_component(handle); } catch (CannotDeactivateComponentEx cdce) { throw AcsJCannotDeactivateComponentEx.fromCannotDeactivateComponentEx(cdce); } catch (ComponentDeactivationUncleanEx cdue) { throw AcsJComponentDeactivationUncleanEx.fromComponentDeactivationUncleanEx(cdue); } catch (ComponentDeactivationFailedEx cdfe) { throw AcsJComponentDeactivationFailedEx.fromComponentDeactivationFailedEx(cdfe); } catch (Exception ex) { RemoteException re = new RemoteException("Failed to invoke 'deactivate_component()' method.", ex); throw re; } } /** * @see com.cosylab.acs.maci.Container#get_component_info(int[]) */ public ComponentInfo[] get_component_info(int[] handles) throws RemoteException { try { // returned value ComponentInfo[] retVal = null; // transform to CORBA specific si.ijs.maci.ComponentInfo[] infos = container.get_component_info(handles); if (infos != null) { retVal = new ComponentInfo[infos.length]; for (int i = 0; i < infos.length; i++) { ComponentInfo componentInfo = new ComponentInfo(infos[i].h, infos[i].name, infos[i].type, infos[i].code, new ComponentProxy(infos[i].name, infos[i].reference)); componentInfo.setContainer(infos[i].container); componentInfo.setContainerName(infos[i].container_name); componentInfo.setAccessRights(inverseMapAccessRights(infos[i].access)); componentInfo.setClients(new IntArray(infos[i].clients)); componentInfo.setInterfaces(infos[i].interfaces); retVal[i] = componentInfo; } } return retVal; } catch (Exception ex) { RemoteException re = new RemoteException("Failed to invoke 'get_component_info()' method.", ex); throw re; } } /** * @see com.cosylab.acs.maci.Container#restart_component(int) */ public Component restart_component(int handle) throws RemoteException { try { org.omg.CORBA.Object component = container.restart_component(handle); final String componentName = "unknown"; return new ComponentProxy(componentName, component); } catch (Exception ex) { RemoteException re = new RemoteException("Failed to invoke 'restart_component()' method.", ex); throw re; } } /** * @see com.cosylab.acs.maci.Container#shutdown(int) */ public void shutdown(int action) throws RemoteException { try { container.shutdown(action); } catch (Exception ex) { RemoteException re = new RemoteException("Failed to invoke 'shutdown()' method.", ex); throw re; } } /** * @see com.cosylab.acs.maci.Container#deactivate_components(int[]) */ public void set_component_shutdown_order(int[] handles) throws RemoteException { try { container.set_component_shutdown_order(handles); } catch (Exception ex) { RemoteException re = new RemoteException("Failed to invoke 'set_component_shutdown_order()' method.", ex); throw re; } } /** * Returns the client. * @return si.ijs.maci.Client */ public si.ijs.maci.Client getClient() { return container; } /** * Map CORBA specific codes to <code>AccessRights</code> status codes. * * @param accessRights CORBA specific codes * @return <code>AccessRights</code> status codes */ public static int inverseMapAccessRights(int accessRights) { int retVal = 0; if ((accessRights & si.ijs.maci.AccessRights.INTROSPECT_MANAGER.value) == si.ijs.maci.AccessRights.INTROSPECT_MANAGER.value) retVal |= AccessRights.INTROSPECT_MANAGER; if ((accessRights & si.ijs.maci.AccessRights.REGISTER_COMPONENT.value) == si.ijs.maci.AccessRights.REGISTER_COMPONENT.value) retVal |= AccessRights.REGISTER_COMPONENT; if ((accessRights & si.ijs.maci.AccessRights.SHUTDOWN_SYSTEM.value) == si.ijs.maci.AccessRights.SHUTDOWN_SYSTEM.value) retVal |= AccessRights.SHUTDOWN_SYSTEM; return retVal; } /** * Save the state of the <tt>ContainerProxy</tt> instance to a stream (that * is, serialize it). */ private void writeObject(ObjectOutputStream stream) throws IOException { stream.writeObject(ior); } /** * Reconstitute the <tt>ContainerProxy</tt> instance from a stream (that is, * deserialize it). */ private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException { try { ior = (String)stream.readObject(); container = si.ijs.maci.ContainerHelper.narrow(deserialize(ior)); } catch (Exception e) { // silent here and set reference to null. // An method after deserialization should clean such invalid reference container = null; ior = null; } activateCallback(); } /** * Returns a single-line rendition of this instance into text. * * @return internal state of this instance */ public String toString() { StringBuffer sbuff = new StringBuffer(); sbuff.append("ContainerProxy = { "); sbuff.append("container = '"); sbuff.append(container); sbuff.append("' }"); return new String(sbuff); } /** * @see java.lang.Object#equals(Object) */ public boolean equals(Object obj) { if (container == null) return (obj == null); else if (obj instanceof si.ijs.maci.Container) { try { // compare IORs (encoded host, port, object name, ...) return container.toString().equals(((si.ijs.maci.Container)obj).toString()); //return container._is_equivalent((si.ijs.maci.Container) obj); } catch (Exception ex) { return false; } } else if (obj instanceof ClientProxy) { try { // compare IORs (encoded host, port, object name, ...) return ior.equals(((ClientProxy)obj).ior); //return container._is_equivalent(((ClientProxy) obj).getClient()); } catch (Exception ex) { return false; } } else return false; } }