/* * ALMA - Atacama Large Millimiter Array (c) European Southern Observatory, 2007 * * 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.clients; import java.util.Collection; import java.util.HashSet; import java.util.logging.Logger; import cern.laser.source.alarmsysteminterface.FaultState; import cern.laser.source.alarmsysteminterface.impl.ASIMessageHelper; import cern.laser.source.alarmsysteminterface.impl.XMLMessageHelper; import cern.laser.source.alarmsysteminterface.impl.message.ASIMessage; import com.cosylab.acs.jms.ACSJMSMessageEntity; import alma.acs.container.ContainerServices; import alma.acs.logging.AcsLogLevel; import alma.acs.nc.AcsEventSubscriber; import alma.acscommon.ACS_NC_DOMAIN_ALARMSYSTEM; import alma.acsnc.EventDescription; import alma.alarmsystem.clients.source.SourceListener; public class SourceClient implements AcsEventSubscriber.Callback<ACSJMSMessageEntity> { // The listeners of alarms private HashSet<SourceListener> listeners = new HashSet<SourceListener>(); private AcsEventSubscriber<ACSJMSMessageEntity> m_consumer; // TODO: Is there no IDL-defined constant for this NC name? private static final String m_channelName = "CMW.ALARM_SYSTEM.ALARMS.SOURCES.ALARM_SYSTEM_SOURCES"; // Container services private final ContainerServices contSvcs; // To avoid to release the resources twice private volatile boolean closed=false; // Logger private Logger logger; public SourceClient(ContainerServices svc) throws Exception { if (svc==null) { throw new IllegalArgumentException("Invalid ContainerServices"); } contSvcs=svc; logger=contSvcs.getLogger(); } /** * Connect to the sources NC * * @throws Exception */ public void connect() throws Exception { if (closed) { throw new IllegalStateException("SourceClient is closed!"); } logger.log(AcsLogLevel.DEBUG,"Connecting to source channel "+m_channelName); m_consumer = contSvcs.createNotificationChannelSubscriber(m_channelName, ACS_NC_DOMAIN_ALARMSYSTEM.value, ACSJMSMessageEntity.class); m_consumer.addSubscription(this); m_consumer.startReceivingEvents(); logger.log(AcsLogLevel.DEBUG,"Source channel "+m_channelName+" connected"); } /** * The method receives all the messages published in the NC * For each message received it check if its content is right * i.e. the name of the class, the member and the code contains the * number of the message in the sequence. In this way it also checks * if the messages are received in the same order they were sent. * The method also checks if all the messages have been received * and prints a message if receives more messages then the messages * pushed * * @param msg The message received from the NC * @see alma.acs.nc.Consumer */ @Override public void receive(ACSJMSMessageEntity msg, EventDescription eventDescrip) { ASIMessage asiMsg; Collection<FaultState> faultStates; try { asiMsg=XMLMessageHelper.unmarshal(msg.text); faultStates = ASIMessageHelper.unmarshal(asiMsg); } catch (Exception e) { System.out.println("Exception caught while unmarshalling the msg "+e.getMessage()); e.printStackTrace(); return; } dispatchXMLASIMessage(msg.text); for (FaultState fs: faultStates) { dispatchFaultState(fs); } } @Override public Class<ACSJMSMessageEntity> getEventType() { return ACSJMSMessageEntity.class; } /** * Add a listener for the alarms. * * Add the listeners to the set of listeners to be notified when * a new alarms is received from the categories. * * @param newListener The listener for alarms from categories */ public void addAlarmListener(SourceListener newListener) { if (newListener==null) { throw new IllegalArgumentException("Invalid null listener"); } if (closed) { throw new IllegalStateException("SourceClient is closed!"); } synchronized(listeners) { listeners.add(newListener); } } /** * Remove a listener from the list of listeners to be notified * when a new alarm is received * * @param listener The not null listener to remove * @return true if the list of listeners contained the specified listener */ public boolean removeListener(SourceListener listener) { if (listener==null) { throw new IllegalArgumentException("Invalid null listener"); } if (closed) { throw new IllegalStateException("SourceClient is closed!"); } boolean ret; synchronized(listeners) { ret=listeners.remove(listener); } return ret; } /** * This method, called when a new XML message arrives, dispatches * string to the listeners. * * @param msg The XML string to send to the listeners */ private synchronized void dispatchXMLASIMessage(String msg) { if (msg==null) { throw new IllegalArgumentException("The message to dispatch can't be null"); } synchronized(listeners) { for (SourceListener listener: listeners) { listener.sourceXMLMsgReceived(msg); } } } /** * This method, called when a new message arrives, dispatches * the alarm to the listeners. * * @param newAlarm The alarm to send to the listeners */ private synchronized void dispatchFaultState(FaultState faultState) { if (faultState==null) { throw new IllegalArgumentException("Invalid null alarm to dispatch"); } synchronized(listeners) { for (SourceListener listener: listeners) { listener.faultStateReceived(faultState); } } } /** * Frees all the resources */ public void close() { if (closed) { return; } closed=true; if (m_consumer!=null) { try { m_consumer.disconnect(); } catch (Exception ex) { // Should we throw something? Who all calls this method? ex.printStackTrace(); } } } /** * Ensure that the resources have been released before destroying the object */ protected void finalize() throws Throwable { if (!closed) { close(); } super.finalize(); } }