blob: b29095c06bd469a35ed9bf118a8f905329e99cbb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2016 Ericsson and others.
* 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
*
* Contributors:
* Ericsson - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.dsf.gdb.internal.ui.console;
import java.io.IOException;
import java.io.OutputStream;
import java.util.concurrent.RejectedExecutionException;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlInitializedDMEvent;
import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
import org.eclipse.cdt.dsf.gdb.service.command.IGDBControl;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
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.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.IOConsole;
/**
* A console that is used to print traces. The console is attached to a launch.
*
* Any input to this console is read and discarded, since this console should be
* read-only. We don't actually make the console read-only because it is nice
* for the user to be able to add delimiters such as empty lines within the traces.
*
* @since 2.1
* This class was moved from package org.eclipse.cdt.dsf.gdb.internal.ui.tracing
*/
public class TracingConsole extends IOConsole {
private ILaunch fLaunch;
private OutputStream fTracingStream = null;
private DsfSession fSession = null;
private String fLabel = ""; //$NON-NLS-1$
public TracingConsole(ILaunch launch, String label) {
super("", null, null, false); //$NON-NLS-1$
fLaunch = launch;
fTracingStream = newOutputStream();
fSession = ((GdbLaunch)launch).getSession();
fLabel = label;
resetName();
// Start a job to swallow all the input from the user
new InputReadJob().schedule();
// This is needed if the service has already been created.
// For example, if we turn on tracing after a launch is started.
setStreamInService();
}
@Override
protected void init() {
super.init();
fSession.getExecutor().submit(new DsfRunnable() {
@Override
public void run() {
fSession.addServiceEventListener(TracingConsole.this, null);
}
});
}
@Override
protected void dispose() {
try {
fTracingStream.close();
} catch (IOException e) {
}
try {
fSession.getExecutor().submit(new DsfRunnable() {
@Override
public void run() {
fSession.removeServiceEventListener(TracingConsole.this);
}
});
} catch (RejectedExecutionException e) {
// Session already disposed
}
super.dispose();
}
public ILaunch getLaunch() { return fLaunch; }
private void setStreamInService() {
try {
fSession.getExecutor().submit(new DsfRunnable() {
@Override
public void run() {
DsfServicesTracker tracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), fSession.getId());
IGDBControl control = tracker.getService(IGDBControl.class);
tracker.dispose();
if (control != null) {
// Special method that need not be called on the executor
control.setTracingStream(fTracingStream);
}
}
});
} catch (RejectedExecutionException e) {
}
}
protected String computeName() {
String label = fLabel;
ILaunchConfiguration config = fLaunch.getLaunchConfiguration();
if (config != null && !DebugUITools.isPrivate(config)) {
String type = null;
try {
type = config.getType().getName();
} catch (CoreException e) {
}
StringBuilder buffer = new StringBuilder();
buffer.append(config.getName());
if (type != null) {
buffer.append(" ["); //$NON-NLS-1$
buffer.append(type);
buffer.append("] "); //$NON-NLS-1$
}
buffer.append(label);
label = buffer.toString();
}
if (fLaunch.isTerminated()) {
return ConsoleMessages.ConsoleMessages_console_terminated + label;
}
return label;
}
public void resetName() {
final String newName = computeName();
String name = getName();
if (!name.equals(newName)) {
Display display = PlatformUI.getWorkbench().getDisplay();
if (!display.isDisposed()) {
display.asyncExec(() -> setName(newName));
}
}
}
@DsfServiceEventHandler
public final void eventDispatched(ICommandControlInitializedDMEvent event) {
// Now that the service is started, we can set the stream.
// We won't receive this event if we enable tracing after a launch
// has been started.
setStreamInService();
}
/**
* A reading Job which will prevent the input stream
* from filling up. We don't actually do anything with
* the data we read, since the Trace console should not
* accept input.
*
* But instead of making the console read-only, we allow
* the user to type things to allow for comments to be
* inserted within the traces.
*/
private class InputReadJob extends Job {
{
setSystem(true);
}
InputReadJob() {
super("Traces Input Job"); //$NON-NLS-1$
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
byte[] b = new byte[1024];
int read = 0;
while (getInputStream() != null && read >= 0) {
// Read the input and swallow it.
read = getInputStream().read(b);
}
} catch (IOException e) {
}
return Status.OK_STATUS;
}
}
}