/*
* ALMA - Atacama Large Millimiter Array
* (c) European Southern Observatory, 2002
* Copyright by ESO (in the framework of the ALMA collaboration)
* and Cosylab 2002, 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 com.cosylab.logging.engine.ACS;
import java.util.logging.Level;
import org.jacorb.orb.acs.AcsORBProfiler;
import org.jacorb.orb.acs.AcsProfilingORB;
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NameComponent;
import org.omg.CosNaming.NamingContext;
import org.omg.CosNotifyChannelAdmin.InterFilterGroupOperator;
import org.omg.CosNotifyFilter.ConstraintExp;
import org.omg.CosNotifyFilter.ConstraintInfo;
import org.omg.CosNotifyFilter.Filter;
import org.omg.CosNotifyFilter.FilterFactory;
import org.omg.CosNotifyFilter.InvalidConstraint;
import org.omg.CosNotifyFilter.InvalidGrammar;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAHelper;
import org.omg.PortableServer.POAManager;
import com.cosylab.logging.engine.FiltersVector;
import com.cosylab.logging.engine.RemoteAccess;
import gov.sandia.NotifyMonitoringExt.ConsumerAdmin;
import gov.sandia.NotifyMonitoringExt.ConsumerAdminHelper;
import gov.sandia.NotifyMonitoringExt.EventChannel;
import gov.sandia.NotifyMonitoringExt.EventChannelHelper;
import si.ijs.maci.Manager;
import alma.acs.logging.AcsLogger;
import alma.acs.profiling.orb.AcsORBProfilerImplBase;
import alma.acscommon.ACS_NC_DOMAIN_LOGGING;
import alma.acscommon.LOGGING_CHANNEL_NAME;
import alma.acscommon.LOGGING_CHANNEL_XML_NAME;
import alma.acscommon.NAMESERVICE_BINDING_NC_DOMAIN_SEPARATOR;
import alma.acscommon.NAMING_SERVICE_NAME;
import alma.maciErrType.CannotGetComponentEx;
import alma.maciErrType.ComponentConfigurationNotFoundEx;
import alma.maciErrType.ComponentNotAlreadyActivatedEx;
import alma.maciErrType.NoPermissionEx;
/**
* This class implements methods for declaring the naming service
* and the notification channel to which the client is subscribed.
*
* Creation date: (10/30/2001 3:48:32 PM)
* @author:
*/
public final class ACSRemoteAccess implements RemoteAccess {
public static final String MANAGER_PROPERTY = System.getProperty("ACS.manager");
public static final String NAME_SERVICE = NAMING_SERVICE_NAME.value;
public static final String LOGGING_XML_CHANNEL = LOGGING_CHANNEL_XML_NAME.value;
public static final String LOGGING_BIN_CHANNEL = LOGGING_CHANNEL_NAME.value;
private boolean isInitialized = false;
private ORB orb;
private boolean isExternalORB;
private EventChannel eventChannel = null;
private ConsumerAdmin consumerAdmin = null;
private ACSStructuredPushConsumer acsSPS = null;
// The object to dispatch messages to the listeners
private ACSListenersDispatcher listenersDispatcher = null;
// The engine filters
private FiltersVector filters = null;
// The object to send new logs to
private ACSLogRetrieval logRetrieval;
private final AcsLogger logger;
/**
* ACSRemoteAccss constructor comment.
*
* @param listeners The object to send messages to the listeners
*/
public ACSRemoteAccess(ACSListenersDispatcher listeners, ACSLogRetrieval retrieval, AcsLogger logger) {
if (listeners==null) {
throw new IllegalArgumentException("The object to dispatch messages to listeners can't be null");
}
if (retrieval==null) {
throw new IllegalArgumentException("The ACSLogRetrieval can't be null");
}
if (logger==null) {
throw new IllegalArgumentException("The logger can't be null");
}
listenersDispatcher=listeners;
logRetrieval=retrieval;
this.logger = logger;
}
/**
* This method can not be used in the current implementation of ACS logging
* But it will be useful for archiving.
*/
private ConstraintExp[] createConstraints() {
final int numConstraints = 2;
String[] constraintStrings = {
"$upper == 'A'",
"$lower == 'a'"
};
// ... and so on
// Orbacus Notify book, page 64 (programming example).
return null;
}
/**
* Creates a consumer admin on the server, that is used only by this jlog instance.
* @see #consumerAdmin
*/
private boolean createConsumerAdmin() {
listenersDispatcher.publishReport("Creating Consumer Admin...");
try {
InterFilterGroupOperator ifgo = org.omg.CosNotifyChannelAdmin.InterFilterGroupOperator.OR_OP;
org.omg.CORBA.IntHolder adminID = new org.omg.CORBA.IntHolder();
consumerAdmin = ConsumerAdminHelper.narrow(
eventChannel.new_for_consumers(ifgo, adminID)
);
} catch (Exception e) {
listenersDispatcher.publishReport("Exception occurred when creating Consumer Admin.");
System.out.println("Exception in ACSRemoteAccess::createConsumerAdmin(): " + e);
return false;
}
listenersDispatcher.publishReport("Consumer Admin created.");
return true;
}
/**
* This method can not be used in the current implementation of ACS logging
* But it will be useful for archiving.
*/
private void createFilter() {
// create filter
if (eventChannel == null) return;
FilterFactory filterFactory = eventChannel.default_filter_factory();
Filter filter = null;
try {
filter = filterFactory.create_filter("EXTENDED_TCL");
}
catch (InvalidGrammar e) {
System.out.println("Invalid grammar in ACSRemoteAccess::createFilter(): " + e);
}
// create constaints
try {
ConstraintInfo[] info = filter.add_constraints(createConstraints());
} catch (InvalidConstraint e) {
System.out.println("Invalid constraint in ACSRemoteAccess::createFilter(): " + e);
}
// add constraints to filter
}
private boolean createStructuredPushConsumer() {
listenersDispatcher.publishReport("Initializing Structured Push Consumer...");
acsSPS = new ACSStructuredPushConsumer(
this,
listenersDispatcher,
logRetrieval);
if (!acsSPS.isInitialized) return false;
acsSPS.connect();
if (!acsSPS.isConnected) return false;
acsSPS.setupEvents();
if (!acsSPS.isEventSetup) return false;
listenersDispatcher.publishReport("Structured Push Consumer initialized.");
return true;
}
/**
* destroy method comment. Not implemented yet.
*/
public synchronized void destroy() {
if (orb==null) {
return;
}
if (acsSPS!=null) {
acsSPS.destroy();
}
// consumerAdmin.destroy();
if (!isExternalORB && orb!=null) {
orb.shutdown(true);
orb.destroy();
orb=null;
}
}
public ConsumerAdmin getConsumerAdmin() {
return consumerAdmin;
}
public ORB getORB() {
return orb;
}
/**
* Initialize the connection.
*
* @param theORB The ORB.
* If it is null then a new CORBA connection is initialized.
* @param manager A reference to the Manager
* If it is null a reference is built by reading the properties.
*/
public void initialize(ORB theORB, Manager manager) {
isExternalORB = (theORB != null);
this.orb=theORB;
if (orb==null) {
listenersDispatcher.publishReport("Initializing CORBA...");
// ORB stanza
java.util.Properties orbprops = java.lang.System.getProperties();
orb = ORB.init(new String[0], orbprops);
// POA stanza -- use RootPOA
POA rootPOA = null;
try
{
rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
} catch (org.omg.CORBA.ORBPackage.InvalidName in)
{
throw new IllegalStateException("Cannot resolve RootPOA: " + in);
}
POAManager poaManager = rootPOA.the_POAManager();
try
{
poaManager.activate();
} catch (Exception e)
{
throw new IllegalStateException("POAManager activation failed." + e);
}
// setup ORB profiling
try {
if (orb instanceof AcsProfilingORB) {
AcsORBProfiler profiler = new AcsORBProfilerImplBase(logger);
((AcsProfilingORB)orb).registerAcsORBProfiler(profiler);
logger.finer("Orb profiling set up, using class " + AcsORBProfilerImplBase.class.getName());
}
} catch (Throwable th) {
logger.log(Level.WARNING, "Failed to setup ORB profiling.", th);
}
// end of CORBA stanza
listenersDispatcher.publishReport("CORBA initialized.");
}
Manager maciManager=manager;
if (maciManager==null) {
maciManager = resolveManagerReference();
if (maciManager == null) {
return; // HSO: Ale, should this not throw an exception?
}
}
NamingContext namingContext = resolveNamingServiceContext(maciManager);
if (namingContext == null) {
return;
}
if (!resolveNotifyChannel(LOGGING_XML_CHANNEL, namingContext)) {
return;
}
boolean isConsumerAdminCreated = createConsumerAdmin();
if (!isConsumerAdminCreated) {
return;
}
isInitialized = createStructuredPushConsumer();
}
/**
* isInitialized method comment.
*/
public boolean isInitialized() {
return isInitialized;
}
/**
*
* @return true if the consumer is suspended
*/
public boolean isSupended() {
return acsSPS.isSuspended();
}
private si.ijs.maci.Manager resolveManagerReference() {
listenersDispatcher.publishReport("Resolving " + MANAGER_PROPERTY + " manager reference...");
org.omg.CORBA.Object obj = null;
si.ijs.maci.Manager manager;
try {
if (MANAGER_PROPERTY == null) throw new IllegalStateException("Manager system property ACS.manager is null.");
obj = orb.string_to_object(MANAGER_PROPERTY);
//if (obj == null) throw new IllegalStateException("Could not resolve Manager reference from the ACS.manager system property (" + MANAGER_PROPERTY + ").");
manager = si.ijs.maci.ManagerHelper.narrow(obj);
} catch (Exception e) {
listenersDispatcher.publishReport("Exception occurred when resolving manager reference.");
System.out.println("Exception in ACSRemoteAccess::resolveManagerReference(): " + e);
return null;
}
listenersDispatcher.publishReport("Manager reference resolved.");
return manager;
}
private NamingContext resolveNamingServiceContext(si.ijs.maci.Manager manager) {
listenersDispatcher.publishReport("Resolving Naming Service...");
org.omg.CORBA.Object nameService = null;
try
{
nameService = manager.get_service(0, NAME_SERVICE, false);
}
catch(NoPermissionEx e)
{
throw new IllegalStateException("Failed to obtaine NameService from the manager. No permission");
}
catch(CannotGetComponentEx e)
{
throw new IllegalStateException("Failed to obtain NameService from the manager.");
}
catch(ComponentNotAlreadyActivatedEx e)
{
throw new IllegalStateException("Failed to obtaine NameService from the manager.");
}
catch(ComponentConfigurationNotFoundEx e)
{
throw new IllegalStateException("Failed to obtaine NameService from the manager.");
}
NamingContext namingContext = null;
try {
namingContext = org.omg.CosNaming.NamingContextHelper.narrow(nameService);
} catch (Exception e) {
listenersDispatcher.publishReport("Exception occurred when narrowing Naming Service Context from the Naming Service.");
System.out.println("Exception in resloveNamingServiceContext(): " + e);
return null;
}
listenersDispatcher.publishReport("Naming Service resolved.");
return namingContext;
}
private boolean resolveNotifyChannel(String channelName, NamingContext namingContext) {
// Cannot use jcontnc Helper for this, due to module order...
String channelWithDomain = channelName + NAMESERVICE_BINDING_NC_DOMAIN_SEPARATOR.value + ACS_NC_DOMAIN_LOGGING.value;
listenersDispatcher.publishReport("Resolving channel \"" + channelWithDomain + "\" from Notify Service...");
try {
NameComponent[] nc = new NameComponent[1];
nc[0] = new NameComponent(channelWithDomain, alma.acscommon.NC_KIND.value);
org.omg.CORBA.Object obj = namingContext.resolve(nc);
eventChannel = EventChannelHelper.narrow(obj);
} catch (Exception e) {
listenersDispatcher.publishReport("Exception occurred when obtaining channel \"" + channelWithDomain + "\" from the Notify Service.");
System.out.println("ACSRemoteAccess::Exception in resolveNotifyChannel(): " + e);
return false;
}
listenersDispatcher.publishReport("Channel \"" + channelWithDomain + "\" resolved.");
return true;
}
public boolean isConnected() {
if (acsSPS==null) {
return false;
}
return acsSPS.isConnected();
}
/**
* Suspend the notification of the incoming logs
* @see LCEngine
* @param suspended If true suspend the notification of new logs
*/
public void setSuspended(boolean suspended) {
if (acsSPS!=null) {
acsSPS.setSupended(suspended);
}
}
/**
* Close the threads and free all the resources
* @param sync If it is true wait the termination of the threads before returning
*/
public void close(boolean sync) {
if (acsSPS!=null) {
acsSPS.close(sync);
}
}
}