/******************************************************************************* * Copyright (c) 2014, 2015 Willink Transformations 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: * E.D.Willink - Initial API and implementation *******************************************************************************/ package org.eclipse.ocl.examples.debug.ui.delegate; import java.util.HashMap; import java.util.Map; //import org.eclipse.core.filesystem.EFS; //import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchConfigurationType; import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; import org.eclipse.debug.core.ILaunchManager; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.core.model.IProcess; import org.eclipse.debug.core.model.IThread; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.dialogs.ErrorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.ocl.examples.debug.launching.OCLLaunchConstants; import org.eclipse.ocl.examples.debug.ui.OCLDebugUIPlugin; import org.eclipse.ocl.pivot.ExpressionInOCL; import org.eclipse.ocl.pivot.internal.delegate.OCLDelegateDomain; import org.eclipse.ocl.pivot.internal.delegate.OCLSettingDelegate; import org.eclipse.ocl.pivot.utilities.MetamodelManager; import org.eclipse.ocl.pivot.utilities.OCL; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.PlatformUI; /** * An implementation of a setting delegate that computes OCL derived features. */ public class OCLDebugSettingDelegate extends OCLSettingDelegate { /** * The DebugStarter sequences the start up of the debugger off the thread. */ protected static class DebugStarter implements IRunnableWithProgress { protected final @NonNull Display display; protected final @NonNull MetamodelManager metamodelManager; protected final @Nullable Object contextObject; protected final @NonNull ExpressionInOCL constraint; private @Nullable ILaunch launch = null; public DebugStarter(@NonNull Display display, @NonNull MetamodelManager metamodelManager, @Nullable Object contextObject, @NonNull ExpressionInOCL constraint) { this.display = display; this.metamodelManager = metamodelManager; this.contextObject = contextObject; this.constraint = constraint; } public ILaunch getLaunch() { return launch; } /** * Create and launch an internal launch configuration to debug expressionInOCL applied to contextObject. */ protected ILaunch launchDebugger(IProgressMonitor monitor, @Nullable Object contextObject, @NonNull ExpressionInOCL expressionInOCL) throws CoreException { ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); ILaunchConfigurationType launchConfigurationType = launchManager.getLaunchConfigurationType(OCLLaunchConstants.LAUNCH_CONFIGURATION_TYPE_ID); ILaunchConfigurationWorkingCopy launchConfiguration = launchConfigurationType.newInstance(null, "test" /*constraint.getName()*/); Map<String,Object> attributes = new HashMap<String,Object>(); attributes.put(OCLLaunchConstants.EXPRESSION_OBJECT, expressionInOCL); attributes.put(OCLLaunchConstants.CONTEXT_OBJECT, contextObject); launchConfiguration.setAttributes(attributes); return launchConfiguration.launch(ILaunchManager.DEBUG_MODE, monitor); } protected void openError(final String message, final @NonNull Exception e) { display.asyncExec(new Runnable() { @Override public void run() { IStatus status = new Status(IStatus.ERROR, OCLDebugUIPlugin.PLUGIN_ID, e.getLocalizedMessage(), e); ErrorDialog.openError(display.getActiveShell(), "ConsoleMessages.Debug_Starter", message, status); } }); } @Override public void run(IProgressMonitor monitor) { String expression = constraint.toString(); monitor.beginTask(NLS.bind("ConsoleMessages.Debug_Starter", expression), 1); try { monitor.subTask("ConsoleMessages.Debug_ProgressLoad"); try { launch = launchDebugger(monitor, contextObject, constraint); } catch (CoreException e) { openError("ConsoleMessages.Debug_FailLaunch", e); } monitor.worked(1); } finally { monitor.done(); } } } public OCLDebugSettingDelegate(@NonNull OCLDelegateDomain delegateDomain, @NonNull EStructuralFeature structuralFeature) { super(delegateDomain, structuralFeature); } @Override protected @Nullable Object evaluateEcore(@NonNull OCL ocl, @NonNull ExpressionInOCL query, @Nullable Object contextObject) { MetamodelManager metamodelManager = ocl.getMetamodelManager(); @SuppressWarnings("null")@NonNull Display display = Display.getCurrent(); DebugStarter runnable = new DebugStarter(display, metamodelManager, contextObject, query); runnable.run(new NullProgressMonitor()); ILaunch launch = runnable.getLaunch(); if (launch != null) { try { waitForLaunchToTerminate(launch); // launch. } catch (DebugException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } return launch != null; } public static void flushEvents() { for (int i = 0; i < 10; i++) { IWorkbench workbench = PlatformUI.getWorkbench(); while (workbench.getDisplay().readAndDispatch()); } } protected void waitForLaunchToTerminate(@NonNull ILaunch launch) throws InterruptedException, DebugException { while (true) { for (int i = 0; i < 10; i++){ flushEvents(); Thread.sleep(100); } boolean allDead = true; for (IDebugTarget debugTarget : launch.getDebugTargets()) { IProcess process = debugTarget.getProcess(); if (!process.isTerminated()) { allDead = false; } for (IThread debugThread : debugTarget.getThreads()) { if (!debugThread.isTerminated()) { allDead = false; } } } if (allDead) { break; } } } }