| /******************************************************************************* |
| * Copyright (c) 2009, 2018 R.Dvorak 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: |
| * Radek Dvorak - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.m2m.internal.qvt.oml.jdt.debug.ui.launch; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.List; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| 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.debug.core.DebugEvent; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.IDebugEventSetListener; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.model.IProcess; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.m2m.internal.qvt.oml.common.MdaException; |
| import org.eclipse.m2m.internal.qvt.oml.common.launch.TargetUriData; |
| import org.eclipse.m2m.internal.qvt.oml.emf.util.urimap.MappingContainer; |
| import org.eclipse.m2m.internal.qvt.oml.emf.util.urimap.MetamodelURIMappingHelper; |
| import org.eclipse.m2m.internal.qvt.oml.emf.util.urimap.URIMapping; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.launch.QvtLaunchUtil; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtTransformation.TransformationParameter; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.project.QvtTransformation.TransformationParameter.DirectionKind; |
| import org.eclipse.m2m.internal.qvt.oml.runtime.project.WorkspaceQvtModule; |
| import org.eclipse.m2m.qvt.oml.debug.core.QVTODebugCore; |
| import org.eclipse.m2m.qvt.oml.debug.core.QVTODebugUtil; |
| import org.eclipse.m2m.qvt.oml.debug.core.app.QVTOApplication; |
| import org.eclipse.pde.launching.EclipseApplicationLaunchConfiguration; |
| import org.eclipse.pde.launching.IPDELauncherConstants; |
| |
| public class QVTOApplicationConfiguration extends EclipseApplicationLaunchConfiguration { |
| |
| private final List<URI> fModels; |
| private URI fTraceURI; |
| |
| public QVTOApplicationConfiguration() { |
| fModels = new ArrayList<URI>(); |
| } |
| |
| @Override |
| public String[] getProgramArguments(ILaunchConfiguration configuration) throws CoreException { |
| String[] programArguments = super.getProgramArguments(configuration); |
| |
| List<String> result = new ArrayList<String>(Arrays.asList(programArguments)); |
| |
| String transformationURI = QvtLaunchUtil.getTransformationURI(configuration); |
| if(transformationURI != null) { |
| result.add(createArgStr(QVTOApplication.ARG_TRANSFORMATION, |
| createPlatformURI(transformationURI).toString())); |
| } |
| |
| String traceFileURI = QvtLaunchUtil.getTraceFileURI(configuration); |
| if (traceFileURI != null && traceFileURI.trim().length() != 0) { |
| fTraceURI = QVTODebugUtil.toFileURI(traceFileURI); |
| result.add(createArgStr(QVTOApplication.ARG_TRACE, fTraceURI.toString())); |
| } |
| |
| if (QvtLaunchUtil.shouldGenerateTraceFile(configuration) && fTraceURI != null) { |
| result.add(QVTOApplication.ARG_TRACE_SAVE); |
| } |
| |
| if (QvtLaunchUtil.isIncrementalUpdate(configuration) && fTraceURI != null) { |
| result.add(QVTOApplication.ARG_TRACE_INCREMENTAL); |
| } |
| |
| List<DirectionKind> transfParams = getTransfParams(transformationURI); |
| int paramIndex = 0; |
| |
| List<TargetUriData> modelURIs = QvtLaunchUtil.getTargetUris(configuration); |
| for (TargetUriData targetUriData : modelURIs) { |
| String nextURI = targetUriData.getUriString(); |
| boolean isPlatformUri = paramIndex < transfParams.size() && transfParams.get(paramIndex++) == DirectionKind.IN; |
| URI nextModelURI = isPlatformUri ? createPlatformURI(nextURI) : QVTODebugUtil.toFileURI(nextURI); |
| fModels.add(nextModelURI); |
| |
| result.add(createArgStr(QVTOApplication.ARG_PARAM, |
| nextModelURI.toString())); |
| } |
| |
| List<String> mappings = createMetamodelMappings(transformationURI); |
| for (String m : mappings) { |
| result.add(createArgStr(QVTOApplication.ARG_MMAPINGS, m)); |
| } |
| |
| return result.toArray(new String[result.size()]); |
| } |
| |
| @Override |
| public void launch(ILaunchConfiguration configuration, String mode, ILaunch launch, IProgressMonitor monitor) throws CoreException { |
| reset(); |
| |
| configuration = validateLaunchConfiguration(configuration); |
| |
| super.launch(configuration, mode, launch, monitor == null ? new NullProgressMonitor() : monitor); |
| |
| IProcess p = getProcess(launch); |
| if(p != null) { |
| addTerminationHook(p); |
| } |
| } |
| |
| ILaunchConfiguration validateLaunchConfiguration(ILaunchConfiguration configuration) { |
| try { |
| ILaunchConfigurationWorkingCopy workingCopy = configuration.getWorkingCopy(); |
| workingCopy.setAttribute(IPDELauncherConstants.APPLICATION, QVTOApplication.ID); |
| return workingCopy.doSave(); |
| } catch (CoreException e) { |
| QVTODebugCore.log(e.getStatus()); |
| } |
| return configuration; |
| } |
| |
| IProcess getProcess(ILaunch launch) { |
| IProcess[] launchedProcesses = launch.getProcesses(); |
| if(launchedProcesses.length == 0) { |
| // the process have been terminated, hopefully reported the reason ;) |
| return null; |
| } |
| |
| return launchedProcesses[0]; |
| } |
| |
| private URI createPlatformURI(String uriStr) { |
| URI uri = URI.createURI(uriStr, true); |
| IFile file = getIFile(uriStr); |
| if (file != null) { |
| URI platformPluginURI = QVTODebugCore.getDefault().resolvePlatformPluginURI(file); |
| if (platformPluginURI != null) { |
| return platformPluginURI; |
| } |
| |
| if (uri.isPlatformResource()) { |
| URI baseURI = URI.createURI(ResourcesPlugin.getWorkspace().getRoot().getLocationURI().toString()); |
| uri = URI.createURI(baseURI.toString() + uri.toPlatformString(true), true); |
| } |
| } |
| |
| return uri; |
| } |
| |
| private IFile getIFile(String uriStr) { |
| try { |
| URI uri = URI.createURI(uriStr); |
| IFile file = QVTODebugUtil.toFile(uri); |
| if (file != null && file.exists()) { |
| return file; |
| } |
| } catch (Exception e) { |
| } |
| return null; |
| } |
| |
| static String createArgStr(String argName, String argValue) { |
| return argName + "=" + argValue; //$NON-NLS-1$ |
| } |
| |
| private List<String> createMetamodelMappings(String transformationURI) throws CoreException { |
| IFile file = getIFile(transformationURI); |
| if (file == null) { |
| return Collections.emptyList(); |
| } |
| if (!MetamodelURIMappingHelper.hasMappingResource(file.getProject())) { |
| return Collections.emptyList(); |
| } |
| |
| try { |
| MappingContainer mappings = MetamodelURIMappingHelper.loadMappings(file.getProject()); |
| List<String> args = new ArrayList<String>(mappings.getMapping().size()); |
| for (URIMapping m : mappings.getMapping()) { |
| args.add(m.getSourceURI() + ';' + createPlatformURI(m.getTargetURI()).toString()); |
| } |
| return args; |
| } catch (Exception e) { |
| throw new CoreException(QVTODebugCore.createStatus(IStatus.ERROR, "Failed to load metamodel mappings", e)); //$NON-NLS-1$ |
| } |
| } |
| |
| private List<DirectionKind> getTransfParams(String transformationURI) throws CoreException { |
| IFile file = getIFile(transformationURI); |
| if (file == null) { |
| return Collections.emptyList(); |
| } |
| |
| try { |
| List<DirectionKind> params = new ArrayList<DirectionKind>(2); |
| for (TransformationParameter p : new WorkspaceQvtModule(file).getParameters()) { |
| params.add(p.getDirectionKind()); |
| } |
| return params; |
| } catch (MdaException e) { |
| QVTODebugCore.log(QVTODebugCore.createStatus(IStatus.ERROR, "Failed to load transformation", e)); //$NON-NLS-1$ |
| } |
| return Collections.emptyList(); |
| } |
| |
| private void addTerminationHook(final IProcess process) { |
| DebugPlugin.getDefault().addDebugEventListener(new IDebugEventSetListener() { |
| public void handleDebugEvents(DebugEvent[] events) { |
| for (DebugEvent event : events) { |
| if (event.getSource() == process |
| && event.getKind() == DebugEvent.TERMINATE) { |
| DebugPlugin.getDefault().removeDebugEventListener(this); |
| |
| onTerminate(); |
| } |
| } |
| } |
| }); |
| |
| if(process.isTerminated()) { |
| onTerminate(); |
| } |
| } |
| |
| private void onTerminate() { |
| // TODO - refresh only [out, inout] models, trace files in the workspace |
| // currently it's hard to deduce this info from the TargetURIData class |
| QVTODebugUtil.refreshInWorkspace(fModels); |
| if(fTraceURI != null) { |
| QVTODebugUtil.refreshInWorkspace(Collections.singletonList(fTraceURI)); |
| } |
| } |
| |
| protected void reset() { |
| fModels.clear(); |
| fTraceURI = null; |
| } |
| } |