Java tutorial
/** * <copyright> * * Copyright (c) 2007, 2008 Obeo. * 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 * * </copyright> * * Contributors: * Quentin Glineur - initial API and implementation * * $Id: ATLVMExecutor.java,v 1.12 2009/02/25 18:23:19 qglineur Exp $ */ package org.eclipse.qvt.declarative.relations.atlvm; import java.io.BufferedInputStream; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.InvalidPropertiesFormatException; import java.util.List; import java.util.Map; import java.util.Properties; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.xmi.XMLResource; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.m2m.atl.drivers.emf4atl.ASMEMFModel; import org.eclipse.m2m.atl.drivers.emf4atl.EMFModelLoader; import org.eclipse.m2m.atl.engine.vm.ASM; import org.eclipse.m2m.atl.engine.vm.ASMExecEnv; import org.eclipse.m2m.atl.engine.vm.ASMInterpreter; import org.eclipse.m2m.atl.engine.vm.ASMXMLReader; import org.eclipse.m2m.atl.engine.vm.Debugger; import org.eclipse.m2m.atl.engine.vm.SimpleDebugger; import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModel; import org.eclipse.m2m.atl.engine.vm.nativelib.ASMModule; import org.eclipse.qvt.declarative.common.framework.service.Operation; import org.eclipse.qvt.declarative.execution.ExecuteOperation; import org.eclipse.qvt.declarative.execution.ExecutionContext; import org.eclipse.qvt.declarative.execution.ExecutionProvider; import org.eclipse.qvt.declarative.execution.LabelledModel; import org.eclipse.qvt.declarative.execution.QVTRelationsExecutionException; import org.eclipse.qvt.declarative.execution.ExecutionContext.ExecutionMode; /** * A client implementation to provide an execution of QVT Relations by the * regular ATL VM. * * @author Quentin Glineur * */ public class ATLVMExecutor implements ExecutionProvider { private static final String DEFAULT_DEBUGGER_PROPERTIES_LOCATION = "debugger.properties.xml"; //$NON-NLS-1$ private static final Debugger DEFAULT_DEBUGGER; private static final String STEP_PROPERTY = "step"; //$NON-NLS-1$ private static final String SHOW_SUMMARY_PROPERTY = "showSummary"; //$NON-NLS-1$ private static final String PROFILE_PROPERTY = "profile"; //$NON-NLS-1$ private static final String CONTINUE_AFTER_ERROR_PROPERTY = "continueAfterError"; //$NON-NLS-1$ static { // start the static initializations DEFAULT_DEBUGGER = createDefaultDebugger(); } // TODO remove duplicate with ATLVM compiler /** * Create a default debugger with the parameters stored in the corresponding * configuration file */ private static Debugger createDefaultDebugger() { Properties debuggerProperties = new Properties(); URL debuggerPropertiesURL = ATLVMExecutor.class.getResource(DEFAULT_DEBUGGER_PROPERTIES_LOCATION); try { debuggerProperties.loadFromXML(debuggerPropertiesURL.openStream()); } catch (InvalidPropertiesFormatException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } boolean showSummary = Boolean.toString(true).equals(debuggerProperties.get(SHOW_SUMMARY_PROPERTY)); boolean profile = Boolean.toString(true).equals(debuggerProperties.get(PROFILE_PROPERTY)); boolean continueAfterError = Boolean.toString(true) .equals(debuggerProperties.get(CONTINUE_AFTER_ERROR_PROPERTY)); Debugger result = new SimpleDebugger(Boolean.toString(true).equals(debuggerProperties.get(STEP_PROPERTY)), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), new ArrayList<String>(), true, showSummary, profile, continueAfterError); return result; } /* * (non-Javadoc) * * @see * org.eclipse.qvt.declarative.common.framework.service.Provider#provides * (org.eclipse.qvt.declarative.common.framework.service.Operation) */ public boolean provides(Operation operation) { if (operation instanceof ExecuteOperation) { try { // TODO // ExecuteOperation executeOperation = (ExecuteOperation) // operation; // IPath abstractSyntaxTreePath = // executeOperation.getSourceFile() // .getLocation(); // String direction = executeOperation.getParameters() // .getDirectionModel().getName(); // IFolder sourceFolder = executeOperation.getSourceFolder(); // IFolder buildFolder = executeOperation.getBinFolder(); // TODO // // IPath executablePath = // ATLVMCompiler.getDefaultExecutablePath( // abstractSyntaxTreePath, // direction, sourceFolder, buildFolder); // return executablePath.toFile().canRead(); return true; } catch (ClassCastException exception) { return false; } } return false; } Map<String, String> getTransformationParameters(ExecutionContext parameters) { Map<String, String> transformationParameters = new HashMap<String, String>(); boolean isCheckOnly = parameters.getMode() == ExecutionMode.checkOnly; transformationParameters.put("enforce", Boolean.toString(!isCheckOnly)); return transformationParameters; } List<ASMModel> getLinkedModels(ExecutionContext parameters) throws QVTRelationsExecutionException { List<ASMModel> linkedModels = new ArrayList<ASMModel>(); EMFModelLoader emfModelLoader = new EMFModelLoader(); try { for (LabelledModel namedModel : parameters.getSourceModels()) { ASMModel metamodel = emfModelLoader.loadModel(namedModel.getMetamodel().getName(), emfModelLoader.getMOF(), URI.createURI(namedModel.getMetamodel().getAccessor())); linkedModels.add(metamodel); URI modelURI = URI.createURI(namedModel.getAccessor()); boolean created = createResourceIfMissing(emfModelLoader, modelURI); ASMModel model = emfModelLoader.loadModel(namedModel.getName(), metamodel, modelURI); if (created || "traces".equals(model.getName())) { model.setIsTarget(true); ((ASMEMFModel) model).setCheckSameModel(false); } linkedModels.add(model); } LabelledModel directionNamedModel = parameters.getDirectionModel(); ASMModel metamodel = emfModelLoader.loadModel(directionNamedModel.getMetamodel().getName(), emfModelLoader.getMOF(), URI.createURI(directionNamedModel.getMetamodel().getAccessor())); linkedModels.add(metamodel); URI modelURI = URI.createURI(directionNamedModel.getAccessor()); createResourceIfMissing(emfModelLoader, modelURI); ASMModel model = emfModelLoader.loadModel(directionNamedModel.getName(), metamodel, modelURI); model.setIsTarget(true); linkedModels.add(model); } catch (Exception e) { String message = "Unable to load models into the ATLVM \n" + e.getMessage(); throw new QVTRelationsExecutionException(message); } return linkedModels; } private static boolean createResourceIfMissing(EMFModelLoader emfModelLoader, URI modelURI) { boolean result = false; try { emfModelLoader.getResourceSet().getResource(modelURI, true); } catch (Exception r) { emfModelLoader.getResourceSet().createResource(modelURI); result = true; } return result; } private static IFile getExecutableFile(IFile sourceFile, String direction) { IJavaProject javaProject = JavaCore.create(sourceFile.getProject()); IClasspathEntry srcContainer = null; IPath currentTransformationPath = sourceFile.getFullPath(); try { for (IClasspathEntry classpathEntry : javaProject.getRawClasspath()) { if (classpathEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { IPath classPathEntryPath = classpathEntry.getPath(); if (classPathEntryPath.isPrefixOf(currentTransformationPath)) { srcContainer = classpathEntry; } } } IPath relativeTransformationPath = currentTransformationPath .removeFirstSegments(srcContainer.getPath().segmentCount()); IPath binPath = srcContainer.getOutputLocation(); IPath relativeExecutablePath = binPath.append(relativeTransformationPath).removeFileExtension() .addFileExtension(direction).addFileExtension("asm"); IFile executableFile = ResourcesPlugin.getWorkspace().getRoot().getFile(relativeExecutablePath); return executableFile; } catch (JavaModelException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } ASM getQVTRTransformation(String transformationQualifiedName, ExecutionContext parameters) throws QVTRelationsExecutionException { String direction = parameters.getDirectionModel().getName(); IFile transformationFile = ResourcesPlugin.getWorkspace().getRoot() .getFile(new Path(transformationQualifiedName)); IFile executableFile = getExecutableFile(transformationFile, direction); ASM qvtrTransformation = null; try { qvtrTransformation = new ASMXMLReader().read(new BufferedInputStream(executableFile.getContents())); } catch (CoreException e) { String message = "Unable to load ASM code in the ATLVM \n" + e.getMessage(); throw new QVTRelationsExecutionException(message); } return qvtrTransformation; } /* * (non-Javadoc) * * @see * org.eclipse.qvt.declarative.execution.ExecutionProvider#execute(org.eclipse * .core.resources.IFile, * org.eclipse.qvt.declarative.execution.ExecutionContext, * org.eclipse.core.resources.IFolder, org.eclipse.core.resources.IFolder) */ public List<?> execute(String transformationQualifiedName, ExecutionContext parameters) throws QVTRelationsExecutionException { Map<String, String> transformationParameters = getTransformationParameters(parameters); List<ASMModel> linkedModels = getLinkedModels(parameters); ASM qvtrTransformation = getQVTRTransformation(transformationQualifiedName, parameters); List<ASM> librairies = Collections.<ASM>emptyList(); Object result = execute(qvtrTransformation, linkedModels, librairies, transformationParameters, DEFAULT_DEBUGGER); for (ASMModel model : linkedModels) { Map<String, Boolean> serializationParameters = new HashMap<String, Boolean>(); URI metamodelURI = ((ASMEMFModel) model.getMetamodel()).getExtent().getURI(); if (metamodelURI.isFile() || metamodelURI.isPlatformResource()) { serializationParameters.put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE); } try { ASMEMFModel emfModel = (ASMEMFModel) model; emfModel.getExtent().save(serializationParameters); } catch (IOException e) { String message = "Unable to save the model \n" + e.getMessage(); throw new QVTRelationsExecutionException(message); } } return Collections.singletonList(result); } protected Object execute(final ASM qvtrTransformation, final List<ASMModel> linkedModels, final List<ASM> libraries, final Map<String, String> parameters, final Debugger debugger) throws QVTRelationsExecutionException { ASMModule asmModule = new ASMModule(qvtrTransformation); /* * Create an execution environment with the handled models */ ASMExecEnv env = new ASMExecEnv(asmModule, debugger, true); env.addPermission("file.read"); //$NON-NLS-1$ env.addPermission("file.write"); //$NON-NLS-1$ for (ASMModel model : linkedModels) { env.addModel(model.getMetamodel().getName(), model.getMetamodel()); env.addModel(model.getName(), model); } env.registerOperations(qvtrTransformation); /* * libraries overriding operations */ for (ASM asm : libraries) { env.registerOperations(asm); } /* * Launch the interpretation of the compiler on the QVTR abstract syntax * tree */ try { new ASMInterpreter(qvtrTransformation, asmModule, env, parameters); } catch (Exception e) { String message = "Problem interpreting the compiled transformation \n" + e.getMessage(); throw new QVTRelationsExecutionException(message); } return linkedModels.get(linkedModels.size() - 1); } }