/* * 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.util.concurrent.ThreadFactory; import org.omg.PortableServer.Servant; import alma.ACS.OffShoot; import alma.ACS.OffShootOperations; import alma.JavaContainerError.wrappers.AcsJContainerServicesEx; import alma.acs.logging.AcsLogger; import alma.acs.nc.AcsEventPublisher; import alma.acs.nc.AcsEventSubscriber; import com.cosylab.CDB.DAL; /** * Through this interface, the container offers services to its hosted components. * The component must call these methods explicitly; in this respect, * <code>ContainerServices</code> is different from the other services that the container * provides without the component implementation knowing about it. * It can be thought of as a callback handle or a library. * <p> * Currently, methods are added to this interface as the functionality becomes available. * At some point we will have to declutter the interface by introducing 2nd-level interfaces * that harbor cohesive functionality. For example, instead of calling * <code>myContainerServices.getComponent(...)</code>, the new call will then be something like * <code>myContainerServices.communication().getComponent(...)</code>. * <p> * created on Oct 24, 2002 12:56:36 PM * @author hsommer */ public interface ContainerServicesBase { ///////////////////////////////////////////////////////////// // basic needs ///////////////////////////////////////////////////////////// /** * Delivers the unique instance name for the component. * The name must have been specified at deployment time in the CDB * (for static components like the famous "LAMP1" example), * or must have been given to the manager at runtime by the client who creates * a dynamic component (or was invented by the manager if none was given). * @return the unique component instance name */ public String getName(); /** * Gets a <code>Logger</code> object that the component should use for logging. * <p> * The <code>Logger</code> will be set up with a namespace specific to the component * that uses this <code>ContainerServices</code> instance. * <p> * Specific logger extensions that only apply to certain subsystems can be used * by wrapping this logger with a class such as {@link alma.acs.logging.domainspecific.AntennaContextLogger}. * * @return Logger */ public AcsLogger getLogger(); /** * Convenience method for accessing the Configuration Database. * <p> * Currently more than a convenience, given that the CDB is not yet a Java component, * but a separate service... * * @return the CDB interface * @throws ContainerException */ public DAL getCDB() throws AcsJContainerServicesEx; ///////////////////////////////////////////////////////////// // advanced stuff, only for special cases ///////////////////////////////////////////////////////////// /** * Activates a CORBA servant that implements alma.ACS.OffShoot. * The purpose of the OffShoot marker interface is to crack down on uncontrolled * activation of just any CORBA services by Java components, * while allowing this for selected subtypes of OffShoot, like * {@link alma.ACS.Callback}. * <p> * The OffShoot servant can be either a subclass of the xyzPOA skeleton, or a xyzPOATie instance * (delegation model). * Since ACS 4.1.2, a tie servant is detected, and interception code gets inserted between the * POATie skeleton and the offshoot implementation class. This way, the container * can intercept (and log) calls to offshoots in the same way as it does for calls to components. * <b>It is therefore recommended to use the tie approach for all offshoot servants, * unless there is a reason to avoid container interception.</b> * <p> * Note that since ACS 9.0 we are using generics to express that the offshoot impl object must * be both a corba servant and implement OffShootOperations. * * @param cbServant the CORBA-generated servant, e.g. CBdoublePOA; * must implement <code>alma.ACS.OffShootOperations</code>. * @return The corba-activated offshoot object, which needs a narrow-cast to the subtype, like * <code>CBdouble myCBdouble = alma.ACS.CBdoubleHelper.narrow(...)</code>. * @throws ContainerException if anything goes wrong, * especially if <code>cbServant</code> is not an OffShoot. */ public <T extends Servant & OffShootOperations> OffShoot activateOffShoot(T cbServant) throws AcsJContainerServicesEx; /** * Deactivates the offshoot object previously activated through the {@link #activateOffShoot(Object, Class)} method. * Caution: this method returns immediately, while the underlying * {@link org.omg.PortableServer.POAOperations#deactivate_object(byte[])} still * works on the deactivation. If {@link #activateOffShoot(Servant)} is called too shortly * after deactivation, an exception will be thrown. TODO: find a remedy * * @param offshootImpl the offshoot object implementation * @throws AcsJContainerServicesEx if something goes wrong, e.g., if the corresponding offshoot servant was not active. */ public void deactivateOffShoot(Object offshootImpl) throws AcsJContainerServicesEx; /** * More specialized methods are available from the <code>AdvancedContainerServices</code>. */ public AdvancedContainerServices getAdvancedContainerServices(); ///////////////////////////////////////////////////////////// // other ///////////////////////////////////////////////////////////// /** * Gets a <code>ThreadFactory</code>, to be used as input for other classes from the concurrent library * (such as <code>ThreadPoolExecutor</code>), or simply to create new <code>Thread</code>s. * <p> * All user-created threads should come from the factory returned here, so "<code>new Thread(...)</code>" should * not appear anywhere in component code. * <p> * The returned thread factory creates new threads configured to run well in the container environment, e.g. * <ul> * <li> all threads are <em>daeemon</em> threads so that they can't interfere with container shutdown. * <li> the priority is the same as that of the calling component thread (which is created by the ORB) * <li> uncaught user exceptions are logged as WARNING before the thread terminates. * <li> when a component is removed from the container, surviving user threads created by that component * are killed using {@link Thread#stop()} (which even though deprecated, seems like the perfect choice * in this particular situation). * Otherwise a faulty components could permanently take away resources from a running container * and from the other components. * </ul> * @return the thread factory to be used by the component to create new threads. */ public ThreadFactory getThreadFactory(); ///////////////////////////////////////////////////////////// // Notification Channel API ///////////////////////////////////////////////////////////// /** * Creates a new {@link AcsEventPublisher} object for a given channel. * It is the abstraction of a Corba Notification Channel supplier, a DDS publisher, * or a publisher for some other supported pub/sub technology. * <p> * The user is expected to call {@link alma.acs.nc.AcsEventPublisher#disconnect()} when the publisher is no longer needed. * To avoid resource problems, the ContainerServices object calls this method during its own deactivation, * just in case the user forgot to do so. * * @param channelName The Notification Channel name where events will be published. * @param eventType The type of event that can be sent using the AcsEventPublisher, e.g. "MySchedulingEvent.class". * Specifying the type offers additional compile time checking. * It should generally be used unless more than one event type must be sent through this publisher, * in which case you can specify a common base type (e.g. "IDLEntity" in case of different IDL-generated structs), * or just "Object" for total type freedom (though the underlying pub-sub framework may later throw runtime exceptions * if unsupported event types get used). * @return a Notification Channel publisher, that will get automatically stopped and disconnected when the component is unloaded, * or the client disconnected, depending on the case, if the user doesn't do so. * @throws AcsJContainerServicesEx if anything goes wrong while creating the publisher */ public <T> AcsEventPublisher<T> createNotificationChannelPublisher(String channelName, Class<T> eventType) throws AcsJContainerServicesEx; /** * Similar to {@link #createNotificationChannelPublisher(String, Class)}, * but with additional NC domain specification. * <p> * Details of this NC domain concept: * <ul> * <li> All publishers and subscribers that access an NC must consistently use the same NC domain name. * <li> The CDB may specify a mapping of NC domain to a notify service, which then decides where the NC is hosted. * <li> Specifying the NC domain through the API as opposed to doing it in the NC's CDB description * allows mapping of "dynamic" NCs to notify services, whose names are not known at deployment time. * This may be the case for NCs created by 3rd party software such as the alarm system. * </ul> * * @param ncDomain The Notification Channel Service Domain name. * @param eventType * @see #createNotificationChannelSubscriber(String, String) */ public <T> AcsEventPublisher<T> createNotificationChannelPublisher(String channelName, String ncDomain, Class<T> eventType) throws AcsJContainerServicesEx; /** * Creates a new {@link AcsEventSubscriber} object, which is the abstraction of a Notification Channel subscriber (consumer), * for the given channel name. * The created subscriber will be automatically disconnected when the component or client that created it through this method * is finished, in case the user doesn't explicitly do it before. * * @param channelName The Notification Channel name to listen to * @param eventType The type of event that can be sent using the AcsEventSubscriber, e.g. "MySchedulingEvent.class". * The specific event type should be used unless more than one event types must be received by this subscriber, * in which case you can specify a common base type (e.g. "IDLEntity.class" in case of different IDL-generated structs), * or just "Object" for total type freedom (though the underlying pub-sub framework may later throw runtime exceptions * if unsupported event types are received). * @return a Notification Channel subscriber, to which the user can attach one or more handlers for each data type, and that will * be automatically disconnected if the user doesn't do so. * @throws AcsJContainerServicesEx if anything goes wrong while creating the subscriber */ public <T> AcsEventSubscriber<T> createNotificationChannelSubscriber(String channelName, Class<T> eventType) throws AcsJContainerServicesEx; /** * Creates a new {@link AcsEventSubscriber} object, which is the abstraction of a Notification Channel subscriber (consumer), * for the given channel name and notify service domain name. * The created subscriber will be automatically disconnected when the component or client that created it through this method * is finished, in case the user doesn't explicitly do it before. * <p> * Details of the NC domain concept: * <ul> * <li> All publishers and subscribers that access an NC must consistently use the same NC domain name. * <li> The CDB may specify a mapping of NC domain to a notify service, which then decides where the NC is hosted. * <li> Specifying the NC domain through the API as opposed to doing it in the NC's CDB description * allows mapping of "dynamic" NCs to notify services, whose names are not known at deployment time. * This may be the case for NCs created by 3rd party software such as the alarm system. * </ul> * * @param channelName The Notification Channel name to listen to * @param ncDomain The Notification Channel Service Domain name. * @param eventType See {@link #createNotificationChannelPublisher(String, Class)}. * @return a Notification Channel subscriber, to which the user can attach one or more handlers for each data type, and that will * be automatically disconnected if the user doesn't do so. * @throws AcsJContainerServicesEx if anything goes wrong while creating the subscriber */ public <T> AcsEventSubscriber<T> createNotificationChannelSubscriber(String channelName, String ncDomain, Class<T> eventType) throws AcsJContainerServicesEx; }