/* * ALMA - Atacama Large Millimiter Array * (c) European Southern Observatory, 2011 * Copyright by ESO (in the framework of the ALMA collaboration), * and Cosylab * 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.alarmsystem.corbaservice; import java.util.concurrent.ThreadFactory; import java.util.logging.Level; import org.omg.CORBA.ORB; import org.omg.CORBA.Policy; import org.omg.CORBA.portable.IDLEntity; import org.omg.CosNaming.NamingContext; import org.omg.PortableServer.IdAssignmentPolicyValue; import org.omg.PortableServer.LifespanPolicyValue; import org.omg.PortableServer.POA; import org.omg.PortableServer.RequestProcessingPolicyValue; import org.omg.PortableServer.Servant; import org.omg.PortableServer.ServantRetentionPolicyValue; import org.omg.PortableServer.POAPackage.AdapterAlreadyExists; import org.omg.PortableServer.POAPackage.AdapterNonExistent; import org.omg.PortableServer.POAPackage.InvalidPolicy; import com.cosylab.CDB.DAL; import com.cosylab.CDB.DALHelper; import alma.ACS.OffShoot; import alma.ACS.OffShootHelper; import alma.ACS.OffShootOperations; import alma.ACSErrTypeCommon.wrappers.AcsJBadParameterEx; import alma.ACSErrTypeCommon.wrappers.AcsJUnexpectedExceptionEx; import alma.JavaContainerError.wrappers.AcsJContainerEx; import alma.JavaContainerError.wrappers.AcsJContainerServicesEx; import alma.acs.alarmsystem.corbaservice.AlarmSystemCorbaServer; import alma.acs.container.AdvancedContainerServices; import alma.acs.container.CleaningDaemonThreadFactory; import alma.acs.container.ContainerServicesBase; import alma.acs.logging.AcsLogLevel; import alma.acs.logging.AcsLogger; import alma.acs.nc.AcsEventPublisher; import alma.acs.nc.AcsEventSubscriber; import alma.acs.nc.Helper; import alma.acs.nc.NCPublisher; import alma.acs.nc.NCSubscriber; public class AlarmSystemContainerServices implements ContainerServicesBase { /** * The CORBA ORB */ private final ORB orb; /** * The logger */ private final AcsLogger logger; /** * Thread factory. * @TODO: During service shutdown, {@link CleaningDaemonThreadFactory#cleanUp()} should be called. */ private final CleaningDaemonThreadFactory threadFactory; /** * The CORBA server for the alarm system */ private AlarmSystemCorbaServer alSysCorbaServer; /** * The name returned by <code>getName()</code>. */ private static final String name = "AlarmService"; /** * The implementation of the {@link AdvancedContainerServices} */ private final AlarmSystemAdvancedContainerServices advancedContainerServices; /** * Constructor * * @param theOrb The ORB * @param theLogger The logger */ public AlarmSystemContainerServices(AlarmSystemCorbaServer alSysCorbaServer, AcsLogger theLogger) { if (alSysCorbaServer==null) { throw new IllegalArgumentException("The AlarmSystemCorbaServer can't be null"); } if (theLogger==null) { throw new IllegalArgumentException("The logger can't be null"); } threadFactory = new CleaningDaemonThreadFactory(name, theLogger); this.alSysCorbaServer=alSysCorbaServer; this.orb=alSysCorbaServer.getORB(); logger=theLogger; advancedContainerServices= new AlarmSystemAdvancedContainerServices(this); } @Override public <T extends Servant & OffShootOperations> OffShoot activateOffShoot(T cbServant) throws AcsJContainerServicesEx { if (cbServant == null) { String msg = "activateOffShoot called with missing parameter."; AcsJContainerServicesEx ex = new AcsJContainerServicesEx(); ex.setContextInfo(msg); throw ex; } POA offshootPoa; try { offshootPoa = getPOAForOffshoots(alSysCorbaServer.getRootPOA()); } catch (Exception e) { AcsJContainerServicesEx ex = new AcsJContainerServicesEx(e); throw ex; } org.omg.CORBA.Object actObj = null; try { offshootPoa.activate_object(cbServant); actObj = offshootPoa.servant_to_reference(cbServant); actObj._hash(Integer.MAX_VALUE); // just to provoke an exc. if // something is wrong with our // new object logger.finer("offshoot of type '" + cbServant.getClass().getName() + "' activated as a CORBA object."); } catch (Throwable thr) { AcsJContainerServicesEx ex = new AcsJContainerServicesEx(thr); ex.setContextInfo("failed to activate offshoot of type '" + cbServant.getClass().getName()); throw ex; } return OffShootHelper.narrow(actObj); } @Override public <T> AcsEventPublisher<T> createNotificationChannelPublisher(String channelName, Class<T> eventType) throws AcsJContainerServicesEx { return createNotificationChannelPublisher(channelName, null, eventType); } @Override public <T> AcsEventPublisher<T> createNotificationChannelPublisher( String channelName, String channelNotifyServiceDomainName, Class<T> eventType) throws AcsJContainerServicesEx { AcsEventPublisher<T> publisher = null; try { // TODO: try to get the naming service ref in a nicer way (from ORB etc) NamingContext namingService = Helper.getNamingServiceInitial(this); publisher = new NCPublisher<T>(channelName, channelNotifyServiceDomainName, this, namingService); } catch(Throwable e) { logger.log(AcsLogLevel.ERROR, "Unexpected error while creating new AcsEventPublisher object", e); AcsJContainerServicesEx ex = new AcsJContainerServicesEx(e); throw ex; } // m_publishers.put( (channelNotifyServiceDomainName == null ? "" : channelNotifyServiceDomainName) + "/" + channelName, publisher); return publisher; } @Override public <T> AcsEventSubscriber<T> createNotificationChannelSubscriber(String channelName, Class<T> eventType) throws AcsJContainerServicesEx { return createNotificationChannelSubscriber(channelName, null, eventType); } @Override public <T> AcsEventSubscriber<T> createNotificationChannelSubscriber( String channelName, String channelNotifyServiceDomainName, Class<T> eventType) throws AcsJContainerServicesEx { if (eventType == null || !IDLEntity.class.isAssignableFrom(eventType)) { throw new IllegalArgumentException("With Corba-NC based pub-sub, the event must be an instance of IDLEntity."); } AcsEventSubscriber<T> subscriber = null; try { // TODO: try to get the naming service ref in a nicer way (from ORB etc) NamingContext namingService = Helper.getNamingServiceInitial(this); // This is dirty omitting of <T> because NCSubscriber needs something like "<U extends T & IDLEntity>" // Note that this problem does not exist in the ContainerServicesImpl because there we instantiate via reflection. subscriber = new NCSubscriber(channelName, channelNotifyServiceDomainName, this, namingService, this.getName(), eventType); } catch (Throwable e) { logger.log(AcsLogLevel.ERROR, "Unexpected error while creating new AcsEventSubscriber object", e); AcsJContainerServicesEx ex = new AcsJContainerServicesEx(e); throw ex; } // m_subscribers.put( (channelNotifyServiceDomainName == null ? "" : channelNotifyServiceDomainName) + "/" + channelName, subscriber); return subscriber; } private Policy[] m_offshootPolicies; public POA getPOAForOffshoots(POA componentPOA) throws AcsJContainerEx, AcsJUnexpectedExceptionEx { final String offshootPoaName = "offshootPoa"; POA offshootPoa = null; synchronized (componentPOA) { try { // can we reuse it? offshootPoa = componentPOA.find_POA(offshootPoaName, false); } catch (AdapterNonExistent e) { logger.finest("will have to create offshoot POA"); if (m_offshootPolicies == null) { m_offshootPolicies = new Policy[4]; m_offshootPolicies[0] = componentPOA .create_id_assignment_policy(IdAssignmentPolicyValue.SYSTEM_ID); m_offshootPolicies[1] = componentPOA .create_lifespan_policy(LifespanPolicyValue.TRANSIENT); m_offshootPolicies[2] = componentPOA .create_request_processing_policy(RequestProcessingPolicyValue.USE_ACTIVE_OBJECT_MAP_ONLY); m_offshootPolicies[3] = componentPOA .create_servant_retention_policy(ServantRetentionPolicyValue.RETAIN); } try { offshootPoa = componentPOA.create_POA(offshootPoaName, alSysCorbaServer.getRootPOA().the_POAManager(), m_offshootPolicies); logger.finest("successfully created offshoot POA"); } catch (InvalidPolicy ex) { AcsJContainerEx ex2 = new AcsJContainerEx(ex); ex2 .setContextInfo("Attempted to create offshoot POA with invalid policies."); throw ex2; } catch (AdapterAlreadyExists ex) { // we sync on componentPOA, so this should never happen throw new AcsJUnexpectedExceptionEx(ex); } } } return offshootPoa; } @Override public AdvancedContainerServices getAdvancedContainerServices() { return advancedContainerServices; } @Override public AcsLogger getLogger() { return logger; } @Override public String getName() { return name; } @Override public ThreadFactory getThreadFactory() { return threadFactory; } @Override public DAL getCDB() throws AcsJContainerServicesEx { try { org.omg.CORBA.Object dalObj = alSysCorbaServer.getServiceFromNameServer("CDB"); DAL dal = DALHelper.narrow(dalObj); return dal; } catch (Throwable thr) { String msg = "Unexpectedly failed to get the CDB reference!"; logger.log(Level.FINE, msg, thr); AcsJContainerServicesEx ex = new AcsJContainerServicesEx(thr); ex.setContextInfo(msg); throw ex; } } /** * * @return The Orb */ public ORB getOrb() { return orb; } @Override public void deactivateOffShoot(Object offshootImpl) throws AcsJContainerServicesEx { if( offshootImpl instanceof Servant ) { Servant cbServant = (Servant)offshootImpl; try { checkOffShootServant(cbServant); POA rootPOA = alSysCorbaServer.getRootPOA(); if (cbServant == null || rootPOA == null) { String msg = "deactivateOffShoot called with missing parameter."; AcsJContainerEx ex = new AcsJContainerEx(); ex.setContextInfo(msg); throw ex; } byte[] id = null; try { POA offshootPoa = getPOAForOffshoots(rootPOA); id = offshootPoa.servant_to_id(cbServant); offshootPoa.deactivate_object(id); } catch (AcsJContainerEx e) { throw e; } catch (Throwable thr) { String msg = "failed to deactivate offshoot of type '" + cbServant.getClass().getName() + "' (ID=" + String.valueOf(id) + ")"; logger.log(Level.WARNING, msg, thr); AcsJContainerEx ex = new AcsJContainerEx(thr); ex.setContextInfo(msg); throw ex; } } catch (AcsJContainerEx ex) { throw new AcsJContainerServicesEx(ex); } } else { AcsJContainerServicesEx ex = new AcsJContainerServicesEx(); ex.setContextInfo("Not yet implemented"); throw ex; } } private void checkOffShootServant(Servant servant) throws AcsJContainerServicesEx { if (servant == null) { AcsJBadParameterEx cause = new AcsJBadParameterEx(); cause.setParameter("servant"); cause.setParameterValue("null"); throw new AcsJContainerServicesEx(cause); } if (!(servant instanceof OffShootOperations)) { String msg = "invalid offshoot servant provided. Must implement " + OffShootOperations.class.getName(); logger.fine(msg); AcsJContainerServicesEx ex = new AcsJContainerServicesEx(); ex.setContextInfo(msg); throw ex; } } }