blob: f4d6e25b25640eb85316cb892f91d670f398b007 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2018 Willink Transformations and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* R.Dvorak and others - QVTo debugger framework
* E.D.Willink - revised API for OCL debugger framework
*******************************************************************************/
package org.eclipse.ocl.examples.debug.vm.launching;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.List;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.debug.vm.IVMDebuggerShell;
import org.eclipse.ocl.examples.debug.vm.core.EvaluationContext;
import org.eclipse.ocl.examples.debug.vm.evaluator.IDebuggableRunnerFactory;
import org.eclipse.ocl.examples.debug.vm.evaluator.IVMContext;
import org.eclipse.ocl.examples.debug.vm.request.VMStartRequest;
import org.eclipse.ocl.examples.debug.vm.utils.CompiledUnit;
import org.eclipse.ocl.examples.debug.vm.utils.ExecutionDiagnostic;
import org.eclipse.ocl.examples.debug.vm.utils.IVMStackTraceElement;
import org.eclipse.ocl.pivot.NamedElement;
import org.eclipse.ocl.pivot.utilities.MetamodelManager;
public class DebuggableRunner
{
/**
* Successfully finished execution, no errors and user interruption
*/
protected static boolean isSuccess(Diagnostic diagnostic) {
int severity = diagnostic.getSeverity();
return severity != Diagnostic.ERROR && severity != Diagnostic.CANCEL;
}
protected final @NonNull IDebuggableRunnerFactory debuggableRunnerFactory;
protected final @NonNull URI debuggableURI;
protected final @NonNull InternalDebuggableExecutor executor;
// private final List<URI> fModelParamURIs;
private URI fTraceFileURI;
private BasicDiagnostic fDiagnostic;
// private List<ModelExtent> fModelParams;
// private ModelExtentHelper fExtentHelper;
private @Nullable IVMDebuggerShell fDebugShell;
private PrintWriter fErrorLog;
public DebuggableRunner(@NonNull IDebuggableRunnerFactory debuggableRunnerFactory, @NonNull URI debuggableURI, @NonNull InternalDebuggableExecutor executor) {
this.debuggableRunnerFactory = debuggableRunnerFactory;
this.debuggableURI = debuggableURI;
this.executor = executor;
// fModelParamURIs = modelParamURIs;
fErrorLog = new PrintWriter(new OutputStream() {
@Override
public void write(int b) throws IOException {
// do nothing I'm a <null> log
}
}, true);
}
public @NonNull VMDebuggableExecutorAdapter createDebuggableAdapter(final @NonNull EvaluationContext evaluationContext) {
return new VMDebuggableExecutorAdapter() {
public Diagnostic execute(@NonNull VMStartRequest startRequest) throws IllegalStateException {
if (fDebugShell == null) {
throw new IllegalStateException("Executor not connected to debugger"); //$NON-NLS-1$
}
CompiledUnit mainUnit = getUnit();
if (mainUnit != null) {
// OCLDebugUtil.attachEnvironment(mainUnit);
}
Diagnostic execDiagnostic = DebuggableRunner.this.execute(startRequest, evaluationContext);
if (execDiagnostic.getSeverity() != Diagnostic.OK) {
fErrorLog.println(execDiagnostic);
}
return execDiagnostic;
}
public @Nullable CompiledUnit getUnit() {
return executor.getUnit();
}
public void connect(@NonNull IVMDebuggerShell debugShell) {
fDebugShell = debugShell;
}
};
}
public Diagnostic execute(@NonNull VMStartRequest startRequest, @NonNull EvaluationContext evaluationContext) {
Diagnostic diagnostic = initialize();
if(!isSuccess(diagnostic)) {
return diagnostic;
}
// fExecutor.setEnvironmentFactory(getEnvFactory());
try {
// ModelExtent[] params = fModelParams.toArray(new ModelExtent[fModelParams.size()]);
ExecutionDiagnostic execDiagnostic = executor.execute(startRequest, evaluationContext); //, params);
handleExecution(execDiagnostic);
// Trace traces = fExecutor.fTraces;
// executor.resetTraces();
if(!isSuccess(execDiagnostic)) {
// skip saving any output
return execDiagnostic;
}
// can continue and save output
// Diagnostic saveExtentsDiagnostic = fExtentHelper.saveExtents();
// handleSaveExtents(saveExtentsDiagnostic);
executor.getVMExecutor().saveModels();
// if(!isSuccess(saveExtentsDiagnostic)) {
// return saveExtentsDiagnostic;
// }
// Diagnostic saveTracesDiagnostic = saveTraces(traces);
// if(!isSuccess(saveTracesDiagnostic)) {
// return saveTracesDiagnostic;
// }
return execDiagnostic;
} finally {
executor.cleanup();
}
}
public @NonNull URI getDebuggableURI() {
return debuggableURI;
}
public @NonNull MetamodelManager getMetamodelManager() {
return executor.getVMExecutor().getEnvironmentFactory().getMetamodelManager();
}
public @NonNull IDebuggableRunnerFactory getRunnerFactory() {
return debuggableRunnerFactory;
}
public URI getTraceFileURI() {
return fTraceFileURI;
}
protected CompiledUnit getUnit() {
return executor.getUnit();
}
protected @NonNull IVMContext getVMContext() {
return executor.getVMContext();
}
protected void handleLoadExtents(Diagnostic diagnostic) {
// do nothing
}
protected void handleExecution(ExecutionDiagnostic execDiagnostic) {
List<IVMStackTraceElement> stackTrace = execDiagnostic.getStackTrace();
if(stackTrace != null && execDiagnostic.getCode() != ExecutionDiagnostic.USER_INTERRUPTED) {
fErrorLog.println(execDiagnostic);
if (!stackTrace.isEmpty()) {
fErrorLog.println("[OCL Stack trace:]");
execDiagnostic.printStackTrace(fErrorLog);
fErrorLog.println();
}
}
if(execDiagnostic.getException() != null) {
fErrorLog.println("[Java cause:]");
execDiagnostic.getException().printStackTrace(fErrorLog);
}
fErrorLog.flush();
}
protected void handleLoadDebuggable(Diagnostic diagnostic) {
// do nothing
}
protected void handleSaveExtents(Diagnostic diagnostic) {
// do nothing
}
public Diagnostic initialize() { // FIXME This is called twice, first time from LaunchConfigDelegate fDebugShell is still null
IVMContext vmContext = getVMContext();
vmContext.setShell(fDebugShell);
if(fDiagnostic != null) {
return fDiagnostic;
}
fDiagnostic = debuggableRunnerFactory.createDiagnostic("Transformation runner initiliaze");
Diagnostic loadDiagnostic = executor.loadDebuggable();
if (!isSuccess(loadDiagnostic)) {
fDiagnostic.add(loadDiagnostic);
}
handleLoadDebuggable(loadDiagnostic);
NamedElement debuggable = executor.getDebuggable();
if (debuggable == null) {
return fDiagnostic;
}
// Note: initialized here already loaded transformation is required
// fExtentHelper = new ModelExtentHelper(transformation, fModelParamURIs, fExecutor.getResourceSet());
// Diagnostic extentsDiagnostic = Diagnostic.OK_INSTANCE;
// try {
// fModelParams = fExtentHelper.loadExtents();
// } catch (DiagnosticException e) {
// extentsDiagnostic = e.getDiagnostic();
// }
// handleLoadExtents(extentsDiagnostic);
// if(!OCLDebugUIPlugin.isSuccess(extentsDiagnostic)) {
// fDiagnostic.add(extentsDiagnostic);
// }
// FIXME -
// add validation for configuration properties and param count
// into the internal executor
// TODO - collect WARN, INFO diagnostics?
return fDiagnostic;
}
/* private Diagnostic saveTraces(Trace trace) {
if(fTraceFileURI != null) {
Resource resource = new ResourceSetImpl().createResource(fTraceFileURI);
resource.getContents().add(trace);
try {
Map<String, String> options = new HashMap<String, String>();
options.put(XMLResource.OPTION_PROCESS_DANGLING_HREF, XMLResource.OPTION_PROCESS_DANGLING_HREF_DISCARD);
resource.save(options);
} catch (IOException e) {
String message = NLS.bind("Failed to save trace model uri={0}", fTraceFileURI);
return new BasicDiagnostic(Diagnostic.ERROR, OCLDebugUIPlugin.PLUGIN_ID, 0,
message, new Object[] { e });
}
}
return Diagnostic.OK_INSTANCE;
} */
public void setErrorLog(@NonNull PrintWriter errorLog) {
this.fErrorLog = errorLog;
}
public void setTraceFile(URI traceFileURI) {
fTraceFileURI = traceFileURI;
}
}