/**
* This file is protected by Copyright.
* Please refer to the COPYRIGHT file distributed with this source distribution.
*
* This file is part of REDHAWK IDE.
*
* All rights reserved. This program and the accompanying materials are made available under
* the terms of the Eclipse Public License v1.0 which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package gov.redhawk.logging.ui.eventconsole;
import java.io.IOException;
import java.util.concurrent.Callable;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.omg.CORBA.Any;
import org.omg.CORBA.SystemException;
import org.omg.CORBA.UserException;
import org.omg.CosEventChannelAdmin.ProxyPushSupplier;
import org.omg.CosEventChannelAdmin.ProxyPushSupplierHelper;
import org.omg.CosEventComm.Disconnected;
import org.omg.CosEventComm.PushConsumer;
import org.omg.CosEventComm.PushConsumerHelper;
import org.omg.CosEventComm.PushConsumerPOA;
import org.omg.PortableServer.POA;
import org.omg.PortableServer.POAPackage.ServantNotActive;
import org.omg.PortableServer.POAPackage.WrongPolicy;
import CF.LogEvent;
import CF.LogEventHelper;
import gov.redhawk.logging.ui.LogLevels;
import gov.redhawk.logging.ui.LoggingUiPlugin;
import gov.redhawk.logging.ui.jobs.EventChannelCleanupFamily;
import gov.redhawk.model.sca.ScaEventChannel;
import gov.redhawk.sca.util.OrbSession;
import gov.redhawk.sca.util.SubMonitor;
import mil.jpeojtrs.sca.util.CorbaUtils;
/**
* Receives {@link LogEvent}s from an event channel and writes them to an {@link IOConsole} output stream.
*/
public class EventChannelToConsoleStream extends PushConsumerPOA {
private ScaEventChannel eventChannel;
private IOConsoleOutputStream outputStream;
private OrbSession session;
private ProxyPushSupplier pushSupplier;
private boolean activated = false;
private volatile boolean disposed = false;
public EventChannelToConsoleStream(ScaEventChannel eventChannel, IOConsole eventConsole) {
this.eventChannel = eventChannel;
this.outputStream = eventConsole.newOutputStream();
this.session = OrbSession.createSession("gov.redhawk.logging.ui"); //$NON-NLS-1$
}
/**
* Activates this object with the POA and registers with the event channel.
* @throws CoreException
*/
public void activateAndConnect(IProgressMonitor monitor) throws CoreException {
final int WORK_ACTIVATE = 1;
final int WORK_CONNECT = 1;
SubMonitor progress = SubMonitor.convert(monitor, WORK_ACTIVATE + WORK_CONNECT);
// Activate with the POA
POA poa = session.getPOA();
final PushConsumer pushConsumer;
try {
pushConsumer = PushConsumerHelper.narrow(poa.servant_to_reference(this));
} catch (ServantNotActive | WrongPolicy e) {
disposeSession();
throw new CoreException(new Status(IStatus.ERROR, LoggingUiPlugin.PLUGIN_ID, Messages.EventChannelToConsoleStream_1, e));
}
activated = true;
progress.worked(WORK_ACTIVATE);
// Connect to the event channel
try {
CorbaUtils.invoke(new Callable<Object>() {
@Override
public Object call() throws Exception {
// Create a new push supplier
ProxyPushSupplier tmpPushSupplier = eventChannel.getObj().for_consumers().obtain_push_supplier();
// Transition the object to our ORB (so we won't lose it if the domain gets disposed)
String ior = session.getOrb().object_to_string(tmpPushSupplier);
CorbaUtils.release(tmpPushSupplier);
pushSupplier = ProxyPushSupplierHelper.unchecked_narrow(session.getOrb().string_to_object(ior));
// Connect this class as a push consumer
pushSupplier.connect_push_consumer(pushConsumer);
return null;
}
}, progress.newChild(WORK_CONNECT));
} catch (CoreException e) {
deactivate();
disposeSession();
throw new CoreException(new Status(IStatus.ERROR, LoggingUiPlugin.PLUGIN_ID, Messages.EventChannelToConsoleStream_2, e));
} catch (InterruptedException e) {
deactivate();
disposeSession();
throw new CoreException(new Status(IStatus.ERROR, LoggingUiPlugin.PLUGIN_ID, Messages.EventChannelToConsoleStream_3));
}
}
public void disconnectAndDeactivate(IProgressMonitor monitor) {
final int WORK_DISCONNECT = 1;
final int WORK_DEACTIVATE = 1;
SubMonitor progress = SubMonitor.convert(monitor, WORK_DISCONNECT + WORK_DEACTIVATE);
disconnect(progress.newChild(WORK_DISCONNECT));
deactivate();
progress.worked(WORK_DEACTIVATE);
disposeSession();
}
/**
* Deactivate to stop receiving CORBA requests
*/
private void deactivate() {
if (!activated) {
return;
}
activated = false;
try {
POA poa = session.getPOA();
byte[] id = poa.servant_to_id(this);
poa.deactivate_object(id);
} catch (UserException | SystemException e) {
IStatus status = new Status(IStatus.ERROR, LoggingUiPlugin.PLUGIN_ID, Messages.EventChannelToConsoleStream_4, e);
LoggingUiPlugin.getDefault().getLog().log(status);
} catch (CoreException e) {
IStatus status = new Status(IStatus.ERROR, LoggingUiPlugin.PLUGIN_ID, Messages.EventChannelToConsoleStream_5, e);
LoggingUiPlugin.getDefault().getLog().log(status);
}
}
/**
* Disconnect the push supplier
* @monitor The progress monitor (supports cancellation)
*/
private void disconnect(IProgressMonitor monitor) {
if (pushSupplier == null) {
monitor.done();
return;
}
try {
CorbaUtils.invoke(new Callable<Object>() {
@Override
public Object call() throws Exception {
pushSupplier.disconnect_push_supplier();
return null;
}
}, monitor);
} catch (CoreException e) {
IStatus status = new Status(IStatus.ERROR, LoggingUiPlugin.PLUGIN_ID, Messages.EventChannelToConsoleStream_6, e);
LoggingUiPlugin.getDefault().getLog().log(status);
} catch (InterruptedException e) {
IStatus status = new Status(IStatus.ERROR, LoggingUiPlugin.PLUGIN_ID, Messages.EventChannelToConsoleStream_7);
LoggingUiPlugin.getDefault().getLog().log(status);
}
pushSupplier = null;
}
private void disposeSession() {
if (session != null) {
session.dispose();
session = null;
}
}
@Override
public void disconnect_push_consumer() {
// This means that we've been disconnected
deactivate();
}
@Override
public void push(Any any) throws Disconnected {
if (disposed) {
return;
}
if (!LogEventHelper.type().equals(any.type())) {
return;
}
LogEvent logEvent = LogEventHelper.extract(any);
LogLevels logLevel = LogLevels.intToLogLevel(logEvent.level);
String line = String.format("%1$tY-%1$tb-%1$te %1$tT %2$s %3$s\n", logEvent.timeStamp * 1000, logLevel.toString(), logEvent.msg); //$NON-NLS-1$
try {
outputStream.write(line);
} catch (IOException e) {
asyncDispose();
}
}
public synchronized void asyncDispose() {
if (disposed) {
return;
}
disposed = true;
Job job = new Job(Messages.EventChannelToConsoleStream_8 + eventChannel.getName()) {
@Override
public boolean belongsTo(Object family) {
// Make jobs of this class part of a family so they can be found from the job manager
return family.equals(EventChannelCleanupFamily.class);
}
@Override
protected IStatus run(IProgressMonitor monitor) {
disconnectAndDeactivate(monitor);
return Status.OK_STATUS;
}
};
job.setSystem(true);
job.schedule();
}
}