/*******************************************************************************
* Copyright (c) 2011 itemis AG (http://www.itemis.eu) 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
*******************************************************************************/
package org.eclipse.xtend.maven;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Lists.newArrayList;
import static org.eclipse.xtext.util.Strings.concat;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.eclipse.xtend.core.compiler.batch.XtendBatchCompiler;
import org.eclipse.xtend.lib.macro.file.Path;
import org.eclipse.xtext.xbase.file.ProjectConfig;
import org.eclipse.xtext.xbase.file.RuntimeWorkspaceConfigProvider;
import org.eclipse.xtext.xbase.file.WorkspaceConfig;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Provider;
/**
* @author Michael Clay - Initial contribution and API
*/
public abstract class AbstractXtendCompilerMojo extends AbstractXtendMojo {
protected static final Predicate<String> FILE_EXISTS = new Predicate<String>() {
public boolean apply(String filePath) {
return new File(filePath).exists();
}
};
@Inject
protected Provider<XtendBatchCompiler> xtendBatchCompilerProvider;
/**
* Xtend-File encoding argument for the compiler.
*
* @parameter expression="${encoding}" default-value="${project.build.sourceEncoding}"
*/
protected String encoding;
/**
* Set this to false to suppress the creation of *._trace files.
*
* @parameter default-value="true" expression="${writeTraceFiles}"
*/
protected boolean writeTraceFiles;
/**
* Location of the Xtend settings file.
*
* @parameter default-value="${basedir}/.settings/org.eclipse.xtend.core.Xtend.prefs"
* @readonly
*/
private String propertiesFileLocation;
@Inject
private RuntimeWorkspaceConfigProvider workspaceConfigProvider;
protected XtendBatchCompiler createXtendBatchCompiler() {
Injector injector = new XtendMavenStandaloneSetup().createInjectorAndDoEMFRegistration();
XtendBatchCompiler instance = injector.getInstance(XtendBatchCompiler.class);
return instance;
}
protected void compile(XtendBatchCompiler xtend2BatchCompiler, String classPath, List<String> sourceDirectories,
String outputPath) throws MojoExecutionException {
configureWorkspace(sourceDirectories, outputPath);
xtend2BatchCompiler.setResourceSetProvider(new MavenProjectResourceSetProvider(project));
Iterable<String> filtered = filter(sourceDirectories, FILE_EXISTS);
if (Iterables.isEmpty(filtered)) {
getLog().info(
"skip compiling sources because the configured directory '" + Iterables.toString(sourceDirectories)
+ "' does not exists.");
return;
}
getLog().debug("Set temp directory: " + getTempDirectory());
xtend2BatchCompiler.setTempDirectory(getTempDirectory());
getLog().debug("Set DeleteTempDirectory: " + false);
xtend2BatchCompiler.setDeleteTempDirectory(false);
getLog().debug("Set classpath: " + classPath);
xtend2BatchCompiler.setClassPath(classPath);
getLog().debug("Set source path: " + concat(File.pathSeparator, newArrayList(filtered)));
xtend2BatchCompiler.setSourcePath(concat(File.pathSeparator, newArrayList(filtered)));
getLog().debug("Set output path: " + outputPath);
xtend2BatchCompiler.setOutputPath(outputPath);
getLog().debug("Set encoding: " + encoding);
xtend2BatchCompiler.setFileEncoding(encoding);
getLog().debug("Set writeTraceFiles: " + writeTraceFiles);
xtend2BatchCompiler.setWriteTraceFiles(writeTraceFiles);
if (!xtend2BatchCompiler.compile()) {
throw new MojoExecutionException("Error compiling xtend sources in '"
+ concat(File.pathSeparator, newArrayList(filtered)) + "'.");
}
}
private void configureWorkspace(List<String> sourceDirectories, String outputPath) throws MojoExecutionException {
WorkspaceConfig workspaceConfig = new WorkspaceConfig(project.getBasedir().getParentFile().getAbsolutePath());
ProjectConfig projectConfig = new ProjectConfig(project.getBasedir().getName());
URI absoluteRootPath = project.getBasedir().getAbsoluteFile().toURI();
URI relativizedTarget = absoluteRootPath.relativize(new File(outputPath).toURI());
if (relativizedTarget.isAbsolute()) {
throw new MojoExecutionException("Output path '" + outputPath
+ "' must be a child of the project folder '" + absoluteRootPath + "'");
}
for (String source : sourceDirectories) {
URI relativizedSrc = absoluteRootPath.relativize(new File(source).toURI());
if (relativizedSrc.isAbsolute()) {
throw new MojoExecutionException("Source folder " + source
+ " must be a child of the project folder " + absoluteRootPath);
}
projectConfig.addSourceFolderMapping(relativizedSrc.getPath(), relativizedTarget.getPath());
}
workspaceConfig.addProjectConfig(projectConfig);
workspaceConfigProvider.setWorkspaceConfig(workspaceConfig);
if (getLog().isDebugEnabled()) {
getLog().debug("WS config root: " + workspaceConfig.getAbsoluteFileSystemPath());
getLog().debug("Project name: " + projectConfig.getName());
getLog().debug("Project root path: " + projectConfig.getRootPath());
for (Entry<Path, Path> entry : projectConfig.getSourceFolderMappings().entrySet()) {
getLog().debug("Source path: " + entry.getKey() + " -> " + entry.getValue());
}
}
}
protected abstract String getTempDirectory();
protected void addDependencies(Set<String> classPath, List<Artifact> dependencies) {
for (Artifact artifact : dependencies) {
classPath.add(artifact.getFile().getAbsolutePath());
}
}
protected void readXtendEclipseSetting(String sourceDirectory, Procedure1<String> fieldSetter) {
if (propertiesFileLocation != null) {
File f = new File(propertiesFileLocation);
if (f.canRead()) {
Properties xtendSettings = new Properties();
try {
xtendSettings.load(new FileInputStream(f));
// TODO read Xtend setup to compute the properties file loc and property name
String xtendOutputDirProp = xtendSettings.getProperty("outlet.DEFAULT_OUTPUT.directory", null);
if (xtendOutputDirProp != null) {
File srcDir = new File(sourceDirectory);
getLog().debug("Source dir : " + srcDir.getPath() + " exists " + srcDir.exists());
if (srcDir.exists() && srcDir.getParent() != null) {
String path = new File(srcDir.getParent(), xtendOutputDirProp).getPath();
getLog().debug("Applying Xtend property: " + xtendOutputDirProp);
fieldSetter.apply(path);
}
}
} catch (FileNotFoundException e) {
getLog().warn(e);
} catch (IOException e) {
getLog().warn(e);
}
} else {
getLog().info(
"Can't find Xtend properties under " + propertiesFileLocation + ", maven defaults are used.");
}
}
}
protected String resolveToBaseDir(final String directory) throws MojoExecutionException {
File outDir = new File(directory);
if (!outDir.isAbsolute()) {
outDir = new File(project.getBasedir(), directory);
}
return outDir.getAbsolutePath();
}
}