/* * ****************************************************************************** * MontiCore Language Workbench * Copyright (c) 2015, MontiCore, All rights reserved. * * This project is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3.0 of the License, or (at your option) any later version. * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this project. If not, see <http://www.gnu.org/licenses/>. * ****************************************************************************** */ package de.monticore.mojo.m2e; import java.io.File; import java.util.HashSet; import java.util.List; import java.util.Set; import org.apache.maven.plugin.MojoExecution; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.IScopeContext; import org.eclipse.jdt.core.JavaCore; import org.eclipse.m2e.core.MavenPlugin; import org.eclipse.m2e.core.project.IMavenProjectFacade; import org.eclipse.m2e.core.project.MavenProjectUtils; import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest; import org.eclipse.m2e.jdt.AbstractSourcesGenerationProjectConfigurator; import org.eclipse.m2e.jdt.IClasspathDescriptor; import org.osgi.service.prefs.BackingStoreException; /** * An {@link AbstractSourcesGenerationProjectConfigurator} for the * monticore-maven-plugin. * * @author (last commit) $Author: antonio $ * @version $Revision: 18256 $, $Date: 2014-05-12 13:11:31 +0200 (Mo, 12 Mai * 2014) $ */ public class MontiCoreProjectConfigurator extends AbstractSourcesGenerationProjectConfigurator { private static final String GRAMMARS_PARAMETER = "grammars"; private static final String DEFAULT_GRAMMARS_DIRECTORY = "src/main/grammars"; private static final String OUTPUT_DIRECTORY_PARAMETER = "outputDirectory"; private static final String DEFAULT_OUTPUT_DIRECTORY = "target/generated-sources/monticore/sourcecode"; private static final String SYMBOL_TABLE_DIRECTORY_PARAMETER = "symbolTableDirectory"; private static final String DEFAULT_SYMBOL_TABLE_DIRECTORY = "target/generated-sources/monticore/symboltable"; private static final boolean IS_GENERATED = true; private static final boolean IS_NOT_GENERATED = false; private ProjectConfigurationRequest request; private IClasspathDescriptor classpath; private IProgressMonitor monitor; private File basedir; /** * Configures all source folders contributed by the plugin to be added as * source folders in the Eclipse project. */ @Override public void configureRawClasspath( ProjectConfigurationRequest request, IClasspathDescriptor classpath, IProgressMonitor monitor) throws CoreException { assertHasNature(request.getProject(), JavaCore.NATURE_ID); this.request = request; this.classpath = classpath; this.monitor = monitor; this.basedir = request.getMavenProject().getBasedir(); addSourceEntries(getModelDirectories(), IS_NOT_GENERATED); addSourceEntries(getOutputDirectory(), IS_GENERATED); configureMontiCoreSettings(); } /** * Puts into the MontiCore project settings the symbol table directory and * configuration file value taken from the POM. */ private final void configureMontiCoreSettings() throws CoreException { // write into project .settings IScopeContext projectContext = new ProjectScope(request.getProject()); IEclipsePreferences prefs = projectContext.getNode("org.eclipse.monticore.core"); if (prefs != null) { try { File symbolTableDirectory = getFileOrDirectoryFromFileParameter( SYMBOL_TABLE_DIRECTORY_PARAMETER, DEFAULT_SYMBOL_TABLE_DIRECTORY, true); prefs.put(SYMBOL_TABLE_DIRECTORY_PARAMETER, symbolTableDirectory.getPath()); File outputDirectory = getFileOrDirectoryFromFileParameter(OUTPUT_DIRECTORY_PARAMETER, DEFAULT_OUTPUT_DIRECTORY, true); prefs.put(OUTPUT_DIRECTORY_PARAMETER, outputDirectory.getPath()); prefs.flush(); } catch (BackingStoreException e) { // TODO find out how to properly react in such cases e.printStackTrace(); } } } /** * Extracts the file or directory parameter value. */ private File getFileOrDirectoryFromFileParameter(String fileParameter, String defaultValue, boolean isDirectory) throws CoreException { Set<File> files = isDirectory ? getDirectoriesFromFileParameter(fileParameter) : getFilesFromFileParameter(fileParameter); if (files.isEmpty()) { files.add(new File(this.basedir, defaultValue)); } // is this a good implementation (we only take the first element returned // from the iterator) return files.iterator().next(); } /** * Adds all the given paths to this build's set of source directories. */ private final void addSourceEntries(Set<File> directories, boolean isGenerated) { for (File directory : directories) { addSourceEntry(directory, isGenerated); } } /** * Adds the given path to this build's set of source directories. */ private final void addSourceEntry(File directory, boolean isGenerated) { if (directory != null && directory.isDirectory()) { IMavenProjectFacade mavenProject = this.request.getMavenProjectFacade(); IProject project = this.request.getMavenProjectFacade().getProject(); IPath path = MavenProjectUtils.getProjectRelativePath(project, directory.getAbsolutePath()); path = project.getFullPath().append(path); this.classpath.addSourceEntry(path, mavenProject.getOutputLocation(), isGenerated); } } /** * Removes all files from a set that are a sub-directory of a file of another * set. */ private Set<File> filterNested(Set<File> files) { Set<File> filteredFiles = new HashSet<File>(files); for (File f1 : files) { for (File f2 : files) { if (f1 != f2) { File f = f1; while (f != null) { if (f.equals(f2)) { filteredFiles.remove(f1); break; } f = f.getParentFile(); } } } } return filteredFiles; } /** * Returns a set of directories from the value configured by the given MOJO * parameter. */ private Set<File> getDirectoriesFromFileListParameter(String parameterName) throws CoreException { Set<File> directories = new HashSet<File>(); for (MojoExecution mojoExecution : getMojoExecutions(this.request, this.monitor)) { List<?> directoryFiles = getMojoParameterValue(parameterName, List.class, mojoExecution); if (directoryFiles != null) { for (Object object : directoryFiles) { if (object != null) { File directory = new File(this.basedir, (String) object); if (directory.isDirectory()) { directories.add(directory); } else if (directory.isFile()) { directories.add(directory.getParentFile()); } } } } } return directories; } /** * Returns a set of directories from the values configured by the given MOJO * parameter. */ private Set<File> getDirectoriesFromFileParameter(String parameterName) throws CoreException { Set<File> directories = new HashSet<File>(); for (MojoExecution mojoExecution : getMojoExecutions(this.request, this.monitor)) { File directory = getMojoParameterValue(parameterName, File.class, mojoExecution); if (directory != null) { if (directory.isDirectory()) { directories.add(directory); } else if (directory.isFile()) { directories.add(directory.getParentFile()); } } } return directories; } /** * Returns a set of files from the values configured by the given MOJO * parameter. */ private Set<File> getFilesFromFileParameter(String parameterName) throws CoreException { Set<File> files = new HashSet<File>(); for (MojoExecution mojoExecution : getMojoExecutions(this.request, this.monitor)) { File file = getMojoParameterValue(parameterName, File.class, mojoExecution); if (file != null && !file.isDirectory()) { files.add(file); } } return files; } /** * Retrieves the configured model directories of the current MOJO execution. */ private Set<File> getModelDirectories() throws CoreException { Set<File> modelDirectories = getDirectoriesFromFileListParameter(GRAMMARS_PARAMETER); if (modelDirectories.isEmpty()) { modelDirectories.add(new File(this.basedir, DEFAULT_GRAMMARS_DIRECTORY)); } modelDirectories = filterNested(modelDirectories); return modelDirectories; } /** * Retrieves the value of the given MOJO parameter. * * @throws CoreException */ private final <T> T getMojoParameterValue(String parameterName, Class<T> valueClass, MojoExecution mojoExecution) throws CoreException { return MavenPlugin.getMaven().getMojoParameterValue( this.request.getMavenProject(), mojoExecution, parameterName, valueClass, monitor); } /** * Retrieves the configured output directory of the current MOJO execution. */ private final Set<File> getOutputDirectory() throws CoreException { return getDirectoriesFromFileParameter(OUTPUT_DIRECTORY_PARAMETER); } }