/** | |
* Copyright (c) 2008 INRIA. | |
* 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: | |
* INRIA - initial API and implementation | |
* | |
* $Id: WorkspaceLanguage.java,v 1.9 2008/06/24 14:27:32 fjouault Exp $ | |
*/ | |
package org.eclipse.gmt.tcs.metadata.adhoc; | |
import java.io.BufferedInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.net.MalformedURLException; | |
import java.net.URL; | |
import java.util.Map; | |
import java.util.Properties; | |
import org.eclipse.core.resources.IFile; | |
import org.eclipse.core.resources.IProject; | |
import org.eclipse.core.runtime.CoreException; | |
import org.eclipse.emf.common.util.URI; | |
import org.eclipse.gmt.tcs.metadata.AbstractLanguage; | |
import org.eclipse.gmt.tcs.metadata.Language; | |
import org.eclipse.gmt.tcs.metadata.LanguageSource; | |
import org.eclipse.gmt.tcs.metadata.ModelFactory; | |
import org.eclipse.m2m.atl.core.launch.ILauncher; | |
import org.eclipse.m2m.atl.dsls.DSLResourceProvider; | |
import org.eclipse.m2m.atl.dsls.textsource.IFileTextSource; | |
import org.eclipse.m2m.atl.dsls.textsource.TextSource; | |
import org.eclipse.m2m.atl.engine.vm.ASM; | |
import org.eclipse.m2m.atl.engine.vm.ASMXMLReader; | |
/** | |
* | |
* @author Frédéric Jouault | |
*/ | |
public class WorkspaceLanguage extends AbstractLanguage implements Language, LanguageSource { | |
private static class ModelCacheFromIFile extends ModelCache { | |
private String metamodelName; | |
private URI metamodelURI; | |
private String modelName; | |
private IFile modelFile; | |
private long timestamp; | |
public ModelCacheFromIFile(String metamodelName, URI metamodelURI, String modelName, IFile modelFile) { | |
this.metamodelName = metamodelName; | |
this.metamodelURI = metamodelURI; | |
this.modelName = modelName; | |
this.modelFile = modelFile; | |
} | |
protected Object loadModel(ModelFactory factory) { | |
Object metamodel = factory.loadMetamodel(metamodelName, metamodelURI); | |
Object ret = null; | |
try { | |
ret = factory.loadModel(modelName + "-" + metamodelName, metamodel, modelFile.getContents()); | |
this.timestamp = modelFile.getModificationStamp(); | |
} catch (CoreException e) { | |
throw new RuntimeException(e); | |
} | |
return ret; | |
} | |
protected boolean shouldReload() { | |
return modelFile.getModificationStamp() != timestamp; | |
} | |
} | |
private static final String DEFAULT_PARSER_GENERATOR_NAME = "antlr3"; | |
private IProject project; | |
private String name; | |
private String extension; | |
// TODO: properties timestamp | |
private long propertiesTimestamp; | |
private IFile propertiesFile; | |
private Properties properties; | |
private IFile editorFile; | |
private ModelCache editorCache; | |
private IFile outlineFile; | |
private ModelCache outlineCache; | |
private IFile ecoreFile; | |
private ModelCache metamodelCache; | |
private IFile compilerFile; | |
private IFile jarFile; | |
private IFile km3File; | |
private IFile annotationFile; | |
private IFile tcsFile; | |
private IFile antlrFile; | |
private IFile acgFile; | |
public WorkspaceLanguage(IProject project) { | |
this.project = project; | |
propertiesFile = project.getFile("build.properties"); | |
if(!propertiesFile.exists()) { | |
throw new RuntimeException("Missing property file"); | |
} | |
try { | |
properties = new Properties(); | |
InputStream in = propertiesFile.getContents(); | |
properties.load(in); | |
in.close(); | |
propertiesTimestamp = propertiesFile.getModificationStamp(); | |
} catch(IOException e) { | |
throw new RuntimeException("Error reading properties file", e); | |
} catch(CoreException e) { | |
throw new RuntimeException("Error reading properties file", e); | |
} | |
name = properties.getProperty("dsl.name"); | |
extension = properties.getProperty("dsl.ext"); | |
if(extension == null) { | |
throw new RuntimeException("Missing extension"); | |
} | |
if(name == null) { | |
throw new RuntimeException("Missing name"); | |
} | |
km3File = project.getFile("Metamodel/" + name + ".km3"); | |
annotationFile = project.getFile("Metamodel/" + name + ".ann"); | |
tcsFile = project.getFile("Syntax/" + name + ".tcs"); | |
if(!km3File.exists()) { | |
throw new RuntimeException("Missing KM3 file"); | |
} | |
if(!tcsFile.exists()) { | |
throw new RuntimeException("Missing TCS file"); | |
} | |
editorFile = project.getFile("TGE/" + name + "-Editor.xmi"); | |
editorCache = new ModelCacheFromIFile("Editor", DSLResourceProvider.getDefault().getResource("Editor/Metamodel/Editor.ecore").asEMFURI(), name, editorFile); | |
outlineFile = project.getFile("TGE/" + name + "-Outline.xmi"); | |
outlineCache = new ModelCacheFromIFile("Outline", DSLResourceProvider.getDefault().getResource("Outline/Metamodel/Outline.ecore").asEMFURI(), name, outlineFile); | |
ecoreFile = project.getFile("Metamodel/" + name + ".ecore"); | |
metamodelCache = new ModelCache() { | |
private long timestamp; | |
private String metamodelOverrideURI = properties.getProperty("override.metamodel.uri"); | |
protected Object loadModel(ModelFactory factory) { | |
try { | |
Object location; | |
if(metamodelOverrideURI != null) { | |
location = URI.createURI(metamodelOverrideURI); | |
} else { | |
location = ecoreFile.getContents(); | |
this.timestamp = ecoreFile.getModificationStamp(); | |
} | |
Object ret = factory.loadMetamodel(name, location); | |
return ret; | |
} catch (CoreException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
protected boolean shouldReload() { | |
String newMetamodelOverrideURI = getProperty("override.metamodel.uri"); | |
if(metamodelOverrideURI != newMetamodelOverrideURI) { | |
metamodelOverrideURI = newMetamodelOverrideURI; | |
return true; | |
} else { | |
return ecoreFile.getModificationStamp() != timestamp; | |
} | |
} | |
}; | |
antlrFile = project.getFile("Syntax/" + name + "_ANTLR3.g"); | |
jarFile = project.getFile("Syntax/" + name + "-parser.jar"); | |
acgFile = project.getFile("Compiler/" + name + ".acg"); | |
compilerFile = project.getFile("Compiler/" + name + ".asm"); | |
} | |
public Object getEditorModel(ModelFactory factory) { | |
return editorCache.getModel(factory); | |
} | |
public Object getOutlineModel(ModelFactory factory) { | |
return outlineCache.getModel(factory); | |
} | |
public Object getMetamodel(ModelFactory factory) { | |
return metamodelCache.getModel(factory); | |
} | |
public LanguageSource getSource() { | |
return this; | |
} | |
public String getExtension() { | |
return extension; | |
} | |
public String getName() { | |
return name; | |
} | |
public ASM getCompiler() { | |
ASM ret = null; | |
if(compilerFile != null && compilerFile.exists()) { | |
try { | |
ret = new ASMXMLReader().read(new BufferedInputStream(compilerFile.getContents())); | |
} catch (CoreException e) { | |
e.printStackTrace(); | |
} | |
} | |
return ret; | |
} | |
public String getProperty(String key) { | |
if(propertiesFile.getModificationStamp() != propertiesTimestamp) { | |
properties = new Properties(); | |
try { | |
properties.load(propertiesFile.getContents()); | |
} catch (IOException e) { | |
throw new RuntimeException("Error reading properties file", e); | |
} catch (CoreException e) { | |
throw new RuntimeException("Error reading properties file", e); | |
} | |
propertiesTimestamp = propertiesFile.getModificationStamp(); | |
if(!name.equals(properties.getProperty("dsl.name"))) { | |
throw new RuntimeException("Language name changed, restart Eclipse"); | |
} | |
if(!extension.equals(properties.getProperty("dsl.ext"))) { | |
throw new RuntimeException("language extension changed, restart Eclipse"); | |
} | |
} | |
return properties.getProperty(key); | |
} | |
public IFile getEditorFile() { | |
return editorFile; | |
} | |
public IFile getKM3SourceFile() { | |
return km3File; | |
} | |
public IFile getAnnotationSourceFile() { | |
return annotationFile; | |
} | |
public IFile getOutlineFile() { | |
return outlineFile; | |
} | |
public IFile getTCSSourceFile() { | |
return tcsFile; | |
} | |
public IFile getMetamodelFile() { | |
return ecoreFile; | |
} | |
public IFile getGrammarFile() { | |
return antlrFile; | |
} | |
public String getParserGenerator() { | |
String ret = getProperty("parser.generator.name"); | |
if(ret == null) { | |
ret = DEFAULT_PARSER_GENERATOR_NAME; | |
} | |
return ret; | |
} | |
public IFile getParserFile() { | |
return jarFile; | |
} | |
public IFile getACGSourceFile() { | |
return acgFile; | |
} | |
public IFile getCompilerFile() { | |
return compilerFile; | |
} | |
private void addLibraries(ILauncher launcher, String propertyName) throws IOException { | |
String libNameAndPathsCSV = this.getProperty(propertyName); | |
if(libNameAndPathsCSV != null) { | |
String libNameAndPaths[] = libNameAndPathsCSV.split(","); | |
for(int i = 0 ; i < libNameAndPaths.length ; i++) { | |
String parts[] = libNameAndPaths[i].split("="); | |
launcher.addLibrary(parts[0], project.getFile(parts[1]).getLocationURI().toURL().openStream()); | |
} | |
} | |
} | |
protected void addWFRLibraries(ILauncher launcher) throws IOException { | |
this.addLibraries(launcher, "wfr.libraries"); | |
} | |
protected void addPreExtractLibraries(ILauncher launcher) throws IOException { | |
this.addLibraries(launcher, "pre-extract.libraries"); | |
} | |
private IFile getFile(String path) { | |
return project.getFile(path); | |
} | |
private InputStream getASM(String path) throws IOException { | |
IFile wfrFile = getFile(path); | |
if(wfrFile.exists()) { | |
return wfrFile.getLocationURI().toURL().openStream(); | |
} else { | |
return null; | |
} | |
} | |
protected boolean hasWFR() { | |
return this.getFile("WFR/" + name + ".asm").exists(); | |
} | |
protected InputStream getWFR() throws IOException { | |
return this.getASM("WFR/" + name + ".asm"); | |
} | |
protected boolean hasPreExtract() { | |
return this.getFile("WFR/PreExtract.asm").exists(); | |
} | |
protected InputStream getPreExtract() throws IOException { | |
return this.getASM("WFR/PreExtract.asm"); | |
} | |
protected void addExtractOptions(Map params) { | |
String opts = getProperty("extract.options"); | |
if(opts != null) { | |
String optsParts[] = opts.split(","); | |
for(int i = 0 ; i < optsParts.length ; i++) { | |
String mapping[] = optsParts[i].split("="); | |
params.put(mapping[0], mapping[1]); | |
} | |
} | |
} | |
protected TextSource getTCS() { | |
return new IFileTextSource(tcsFile); | |
} | |
protected URL getJarURL() throws MalformedURLException { | |
return jarFile.getLocationURI().toURL(); | |
} | |
} |