Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.m2e.core/src/org/eclipse/m2e/core/project')
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/AbstractProjectScanner.java55
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenMarkerManager.java54
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectChangedListener.java21
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectFacade.java163
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectImportResult.java32
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor.java41
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor2.java29
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IProjectConfigurationManager.java66
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/LocalProjectScanner.java187
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectChangedEvent.java69
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectInfo.java198
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectManager.java166
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectPomScanner.java219
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectScmInfo.java108
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectUtils.java98
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenUpdateRequest.java124
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ProjectImportConfiguration.java142
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ResolverConfiguration.java56
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractBuildParticipant.java68
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractLifecycleMapping.java219
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractProjectConfigurator.java243
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/CustomizableLifecycleMapping.java40
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/DefaultLifecycleMapping.java121
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ILifecycleMapping.java56
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenProjectConfigurator.java120
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenResourcesProjectConfigurator.java20
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MojoExecutionBuildParticipant.java61
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/NoopLifecycleMapping.java55
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/PluginExecutionFilter.java81
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ProjectConfigurationRequest.java72
30 files changed, 2984 insertions, 0 deletions
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/AbstractProjectScanner.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/AbstractProjectScanner.java
new file mode 100644
index 00000000..c996a869
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/AbstractProjectScanner.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+
+/**
+ * Project Scanner
+ *
+ * @author Eugene Kuleshov
+ */
+public abstract class AbstractProjectScanner<T extends MavenProjectInfo> {
+
+ private final List<T> projects = new ArrayList<T>();
+ private final List<Throwable> errors = new ArrayList<Throwable>();
+
+ /**
+ * Returns <code>List</code> of {@link MavenProjectInfo}
+ */
+ public List<T> getProjects() {
+ return projects;
+ }
+
+ /**
+ * Returns <code>List</code> of <code>Exception</code>
+ */
+ public List<Throwable> getErrors() {
+ return this.errors;
+ }
+
+ protected void addProject(T mavenProjectInfo) {
+ projects.add(mavenProjectInfo);
+ }
+
+ protected void addError(Throwable exception) {
+ errors.add(exception);
+ }
+
+ public abstract String getDescription();
+
+ public abstract void run(IProgressMonitor monitor) throws InterruptedException;
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenMarkerManager.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenMarkerManager.java
new file mode 100644
index 00000000..a96622ba
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenMarkerManager.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+
+import org.apache.maven.execution.MavenExecutionResult;
+
+/**
+ * IMavenMarkerManager
+ *
+ * @author Fred Bricon
+ */
+public interface IMavenMarkerManager {
+
+ /**
+ * Add markers to a pom file from a MavenExecutionResult.
+ * @param pomFile the pom file to attach markers to.
+ * @param result containing messages to be addedd as markers
+ */
+ public void addMarkers(IResource pomFile, String type, MavenExecutionResult result);
+
+ /**
+ * Add a Maven marker to a resource
+ * @param resource : the IResource to attach the marker to.
+ * @param message : the marker's message.
+ * @param lineNumber : the resource line to attach the marker to.
+ * @param severity : the severity of the marker.
+ */
+ public IMarker addMarker(IResource resource, String type, String message, int lineNumber, int severity);
+
+ /**
+ * Delete all Maven markers of the specified type from an IResource
+ */
+ public void deleteMarkers(IResource resource, String type) throws CoreException;
+
+ /**
+ * Transform an exception into an error marker on an IResource
+ */
+ public void addErrorMarkers(IResource resource, String type, Exception ex);
+
+ public void addEditorHintMarkers(IResource pom, String type);
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectChangedListener.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectChangedListener.java
new file mode 100644
index 00000000..f37ec18d
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectChangedListener.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+
+public interface IMavenProjectChangedListener {
+ /**
+ * This method is called while holding workspace lock.
+ */
+ public void mavenProjectChanged(MavenProjectChangedEvent[] events, IProgressMonitor monitor);
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectFacade.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectFacade.java
new file mode 100644
index 00000000..ded501aa
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectFacade.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.File;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.project.MavenProject;
+
+import org.eclipse.m2e.core.embedder.ArtifactKey;
+import org.eclipse.m2e.core.embedder.ArtifactRef;
+import org.eclipse.m2e.core.embedder.ArtifactRepositoryRef;
+import org.eclipse.m2e.core.internal.project.ProjectConfigurationManager;
+import org.eclipse.m2e.core.project.configurator.ILifecycleMapping;
+
+/**
+ * IMavenProjectFacade
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ *
+ * @author Igor Fedorenko
+ */
+public interface IMavenProjectFacade {
+
+ /**
+ * Returns project relative paths of resource directories
+ */
+ IPath[] getResourceLocations();
+
+ /**
+ * Returns project relative paths of test resource directories
+ */
+ IPath[] getTestResourceLocations();
+
+ IPath[] getCompileSourceLocations();
+
+ IPath[] getTestCompileSourceLocations();
+
+ /**
+ * Returns project resource for given file system location or null the location is outside of project.
+ *
+ * @param resourceLocation absolute file system location
+ * @return IPath the full, absolute workspace path resourceLocation
+ */
+ IPath getProjectRelativePath(String resourceLocation);
+
+ /**
+ * Returns the full, absolute path of this project maven build output directory relative to the workspace or null if
+ * maven build output directory cannot be determined or outside of the workspace.
+ */
+ IPath getOutputLocation();
+
+ /**
+ * Returns the full, absolute path of this project maven build test output directory relative to the workspace or null
+ * if maven build output directory cannot be determined or outside of the workspace.
+ */
+ IPath getTestOutputLocation();
+
+ IPath getFullPath();
+
+ /**
+ * Lazy load and cache MavenProject instance
+ */
+ MavenProject getMavenProject(IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Returns cached MavenProject instance associated with this facade or null,
+ * if the cache has not been populated yet.
+ */
+ MavenProject getMavenProject();
+
+ /**
+ * Lazy load and cache build execution plan
+ */
+ MavenExecutionPlan getExecutionPlan(IProgressMonitor monitor) throws CoreException;
+
+ String getPackaging();
+
+ IProject getProject();
+
+ IFile getPom();
+
+ File getPomFile();
+
+ /**
+ * Returns the full, absolute path of the given file relative to the workspace. Returns null if the file does not
+ * exist or is not a member of this project.
+ */
+ IPath getFullPath(File file);
+
+ /**
+ * Visits trough Maven project artifacts and modules
+ *
+ * @param visitor a project visitor used to visit Maven project
+ * @param flags flags to specify visiting behavior. See {@link IMavenProjectVisitor#LOAD},
+ * {@link IMavenProjectVisitor#NESTED_MODULES}.
+ */
+ void accept(IMavenProjectVisitor visitor, int flags) throws CoreException;
+
+ void accept(IMavenProjectVisitor2 visitor, int flags, IProgressMonitor monitor) throws CoreException;
+
+ List<String> getMavenProjectModules();
+
+ Set<ArtifactRef> getMavenProjectArtifacts();
+
+ ResolverConfiguration getResolverConfiguration();
+
+ /**
+ * @return true if maven project needs to be re-read from disk
+ */
+ boolean isStale();
+
+ ArtifactKey getArtifactKey();
+
+ /**
+ * Associates the value with the key in session (i.e. transient) context.
+ * Intended as a mechanism to cache state derived from MavenProject.
+ * Session properties are cleared when MavenProject is re-read from disk.
+ *
+ * @see #getSessionProperty(String)
+ */
+ public void setSessionProperty(String key, Object value);
+
+ /**
+ * @return the value associated with the key in session context or null
+ * if the key is not associated with any value.
+ *
+ * @see #setSessionProperty(String, Object)
+ */
+ public Object getSessionProperty(String key);
+
+ public Set<ArtifactRepositoryRef> getArtifactRepositoryRefs();
+
+ public Set<ArtifactRepositoryRef> getPluginArtifactRepositoryRefs();
+
+ public ILifecycleMapping getLifecycleMapping(IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Returns true if the project configuration is valid. This flag is set by
+ * {@link ProjectConfigurationManager#validateProjectConfiguration(IMavenProjectFacade, IProgressMonitor)}. Returns
+ * false if the project configuration has not been validated yet.
+ */
+ boolean hasValidConfiguration();
+
+ void setHasValidConfiguration(boolean hasValidConfiguration);
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectImportResult.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectImportResult.java
new file mode 100644
index 00000000..218e5a4d
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectImportResult.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import org.eclipse.core.resources.IProject;
+
+/**
+ * Holds IProject that was created during project import
+ *
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface IMavenProjectImportResult {
+
+ /**
+ * @return MavenProjectInfo maven project import request
+ */
+ MavenProjectInfo getMavenProjectInfo();
+
+ /**
+ * @return IProject imported project or <code>null</code> if the project could not be imported.
+ */
+ IProject getProject();
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor.java
new file mode 100644
index 00000000..71a5e400
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import org.eclipse.core.runtime.CoreException;
+
+/**
+ * This interface is implemented by clients that visit MavenProject tree.
+ */
+public interface IMavenProjectVisitor {
+
+ public static int NONE = 0;
+
+ public static int LOAD = 1 << 0;
+
+ /**
+ * Visit Maven project or project module
+ *
+ * @param projectFacade a facade for visited Maven project
+ * @return true if nested artifacts and modules should be visited
+ */
+ public boolean visit(IMavenProjectFacade projectFacade) throws CoreException;
+
+ /**
+ * Visit Maven project dependency/artifact
+ *
+ * @param projectFacade a facade for visited Maven project
+ * @param artifact an artifact for project dependency
+ */
+// public void visit(IMavenProjectFacade projectFacade, Artifact artifact);
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor2.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor2.java
new file mode 100644
index 00000000..5effc055
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IMavenProjectVisitor2.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import org.apache.maven.artifact.Artifact;
+
+/**
+ * IMavenProjectVisitor2
+ *
+ * @author Igor Fedorenko
+ */
+public interface IMavenProjectVisitor2 extends IMavenProjectVisitor {
+
+ /**
+ * @param mavenProjectFacade
+ * @param artifact
+ */
+ void visit(IMavenProjectFacade mavenProjectFacade, Artifact artifact);
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IProjectConfigurationManager.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IProjectConfigurationManager.java
new file mode 100644
index 00000000..a36aa966
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/IProjectConfigurationManager.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+
+import org.apache.maven.archetype.catalog.Archetype;
+import org.apache.maven.model.Model;
+
+import org.eclipse.m2e.core.project.configurator.ILifecycleMapping;
+
+
+public interface IProjectConfigurationManager {
+
+ ISchedulingRule getRule();
+
+ List<IMavenProjectImportResult> importProjects(Collection<MavenProjectInfo> projects, //
+ ProjectImportConfiguration configuration, IProgressMonitor monitor) throws CoreException;
+
+ void createSimpleProject(IProject project, IPath location, Model model, String[] folders,
+ ProjectImportConfiguration configuration, IProgressMonitor monitor) throws CoreException;
+
+ void createArchetypeProject(IProject project, IPath location, Archetype archetype, //
+ String groupId, String artifactId, String version, String javaPackage, Properties properties, //
+ ProjectImportConfiguration configuration, IProgressMonitor monitor) throws CoreException;
+
+ Set<MavenProjectInfo> collectProjects(Collection<MavenProjectInfo> projects);
+
+ void enableMavenNature(IProject project, ResolverConfiguration configuration, IProgressMonitor monitor)
+ throws CoreException;
+
+ void disableMavenNature(IProject project, IProgressMonitor monitor) throws CoreException;
+
+ void updateProjectConfiguration(IProject project, ResolverConfiguration configuration, IProgressMonitor monitor)
+ throws CoreException;
+
+ ILifecycleMapping getLifecycleMapping(IMavenProjectFacade projectFacade, IProgressMonitor monitor)
+ throws CoreException;
+
+ /**
+ * Validates that the project configuration is valid. It does not actually (re)configure the project, but it validates
+ * that the project configure action will not fail for obvious reasons like missing lifecycle mapping, missing project
+ * configuration, etc.
+ *
+ * @return true if the configuration is valid
+ */
+ boolean validateProjectConfiguration(IMavenProjectFacade projectFacade, IProgressMonitor monitor);
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/LocalProjectScanner.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/LocalProjectScanner.java
new file mode 100644
index 00000000..b397910e
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/LocalProjectScanner.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubProgressMonitor;
+
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Profile;
+
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenConsole;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.internal.Messages;
+
+
+/**
+ * @author Eugene Kuleshov
+ */
+public class LocalProjectScanner extends AbstractProjectScanner<MavenProjectInfo> {
+ private final File workspaceRoot;
+ private final List<String> folders;
+ private final boolean basedirRemameRequired;
+
+ private Set<File> scannedFolders = new HashSet<File>();
+ private final MavenConsole console;
+ private final MavenModelManager modelManager;
+
+ public LocalProjectScanner(File workspaceRoot, String folder, boolean needsRename, MavenModelManager modelManager,
+ MavenConsole console) {
+ this(workspaceRoot, Collections.singletonList(folder), needsRename, modelManager, console);
+ }
+
+ public LocalProjectScanner(File workspaceRoot, List<String> folders, boolean basedirRemameRequired,
+ MavenModelManager modelManager, MavenConsole console) {
+ this.workspaceRoot = workspaceRoot;
+ this.folders = folders;
+ this.basedirRemameRequired = basedirRemameRequired;
+ this.modelManager = modelManager;
+ this.console = console;
+ }
+
+ public void run(IProgressMonitor monitor) throws InterruptedException {
+ monitor.beginTask(Messages.LocalProjectScanner_task_scanning, IProgressMonitor.UNKNOWN);
+ try {
+ for(String folderName : folders) {
+ try {
+ File folder = new File(folderName).getCanonicalFile();
+ scanFolder(folder, new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
+ } catch(IOException ex) {
+ addError(ex);
+ }
+ }
+ } finally {
+ monitor.done();
+ }
+ }
+
+ private void scanFolder(File baseDir, IProgressMonitor monitor) throws InterruptedException {
+ if(monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+
+ monitor.subTask(baseDir.toString());
+ monitor.worked(1);
+
+ // Don't scan the .metadata folder
+ if(!baseDir.exists() || !baseDir.isDirectory() || IMavenConstants.METADATA_FOLDER.equals(baseDir.getName())) {
+ return;
+ }
+
+ MavenProjectInfo projectInfo = readMavenProjectInfo(baseDir, "", null); //$NON-NLS-1$
+ if(projectInfo != null) {
+ addProject(projectInfo);
+ return; // don't scan subfolders of the Maven project
+ }
+
+ File[] files = baseDir.listFiles();
+ for(int i = 0; i < files.length; i++ ) {
+ File file;
+ try {
+ file = files[i].getCanonicalFile();
+ if(file.isDirectory()) {
+ scanFolder(file, monitor);
+ }
+ } catch(IOException ex) {
+ addError(ex);
+ }
+ }
+ }
+
+ private MavenProjectInfo readMavenProjectInfo(File baseDir, String modulePath, MavenProjectInfo parentInfo) {
+ try {
+ baseDir = baseDir.getCanonicalFile();
+
+ File pomFile = new File(baseDir, IMavenConstants.POM_FILE_NAME);
+ if(!pomFile.exists()) {
+ return null;
+ }
+
+ Model model = modelManager.readMavenModel(pomFile);
+
+ if (!scannedFolders.add(baseDir)) {
+ return null; // we already know this project
+ }
+
+ String pomName = modulePath + "/" + IMavenConstants.POM_FILE_NAME; //$NON-NLS-1$
+
+ MavenProjectInfo projectInfo = newMavenProjectInfo(pomName, pomFile, model, parentInfo);
+ projectInfo.setBasedirRename(getBasedirRename(projectInfo));
+
+ Map<String, Set<String>> modules = new LinkedHashMap<String, Set<String>>();
+ for(String module : model.getModules()) {
+ modules.put(module, new HashSet<String>());
+ }
+
+ for(Profile profile : model.getProfiles()) {
+ for(String module : profile.getModules()) {
+ Set<String> profiles = modules.get(module);
+ if(profiles == null) {
+ profiles = new HashSet<String>();
+ modules.put(module, profiles);
+ }
+ profiles.add(profile.getId());
+ }
+ }
+
+ for(Map.Entry<String, Set<String>> e : modules.entrySet()) {
+ String module = e.getKey();
+ Set<String> profiles = e.getValue();
+
+ File moduleBaseDir = new File(baseDir, module);
+ MavenProjectInfo moduleInfo = readMavenProjectInfo(moduleBaseDir, module, projectInfo);
+ if(moduleInfo != null) {
+ moduleInfo.addProfiles(profiles);
+ projectInfo.add(moduleInfo);
+ }
+ }
+
+ return projectInfo;
+
+ } catch(CoreException ex) {
+ addError(ex);
+ console.logError("Unable to read model " + baseDir.getAbsolutePath());
+ } catch(IOException ex) {
+ addError(ex);
+ console.logError("Unable to read model " + baseDir.getAbsolutePath());
+ }
+
+ return null;
+ }
+
+ protected MavenProjectInfo newMavenProjectInfo(String label, File pomFile, Model model, MavenProjectInfo parent) {
+ return new MavenProjectInfo(label, pomFile, model, parent);
+ }
+
+ public String getDescription() {
+ return folders.toString();
+ }
+
+ private int getBasedirRename(MavenProjectInfo mavenProjectInfo) throws IOException {
+ File cannonical = mavenProjectInfo.getPomFile().getParentFile().getParentFile().getCanonicalFile();
+ if (basedirRemameRequired && cannonical.equals(workspaceRoot.getCanonicalFile())) {
+ return MavenProjectInfo.RENAME_REQUIRED;
+ }
+ return MavenProjectInfo.RENAME_NO;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectChangedEvent.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectChangedEvent.java
new file mode 100644
index 00000000..e0d775ef
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectChangedEvent.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import org.eclipse.core.resources.IFile;
+
+public class MavenProjectChangedEvent {
+
+ private final IFile source;
+
+ private final int kind;
+
+ private final int flags;
+
+ public static final int KIND_ADDED = 1;
+
+ public static final int KIND_REMOVED = 2;
+
+ public static final int KIND_CHANGED = 3;
+
+ public static final int FLAG_NONE = 0;
+
+ public static final int FLAG_DEPENDENCIES = 1;
+
+ public static final int FLAG_DEPENDENCY_SOURCES = 2;
+
+ public static final int FLAG_ENTRY_SOURCES = 3;
+
+ private final IMavenProjectFacade oldMavenProject;
+
+ private final IMavenProjectFacade mavenProject;
+
+ public MavenProjectChangedEvent(IFile source, int kind, int flags, IMavenProjectFacade oldMavenProject, IMavenProjectFacade mavenProject) {
+ this.source = source;
+ this.kind = kind;
+ this.flags = flags;
+ this.oldMavenProject = oldMavenProject;
+ this.mavenProject = mavenProject;
+ }
+
+ public int getKind() {
+ return kind;
+ }
+
+ public int getFlags() {
+ return flags;
+ }
+
+ public IMavenProjectFacade getMavenProject() {
+ return mavenProject;
+ }
+
+ public IMavenProjectFacade getOldMavenProject() {
+ return oldMavenProject;
+ }
+
+ public IFile getSource() {
+ return source;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectInfo.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectInfo.java
new file mode 100644
index 00000000..64088a15
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectInfo.java
@@ -0,0 +1,198 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.maven.model.Model;
+
+import org.eclipse.m2e.core.core.MavenLogger;
+
+
+/**
+ * @author Eugene Kuleshov
+ */
+public class MavenProjectInfo {
+
+ /**
+ * Project basedir must NOT be renamed on filesystem.
+ */
+ public static final int RENAME_NO = 0;
+
+ /**
+ * Project basedir MUST be ranamed to match workspace project name.
+ */
+ public static final int RENAME_REQUIRED = 2;
+
+ private final String label;
+
+ private File pomFile;
+
+ private Model model;
+
+ private final MavenProjectInfo parent;
+
+ /**
+ * Map of MavenProjectInfo
+ */
+ private final Map<String, MavenProjectInfo> projects = new LinkedHashMap<String, MavenProjectInfo>();
+
+ private final Set<String> profiles = new HashSet<String>();
+
+ private int basedirRename = RENAME_NO;
+
+ public MavenProjectInfo(String label, File pomFile, Model model, MavenProjectInfo parent) {
+ this.label = label;
+ this.pomFile = pomFile;
+ this.model = model;
+ this.parent = parent;
+ }
+
+ public void setPomFile(File pomFile) {
+ File oldDir = this.pomFile.getParentFile();
+ File newDir = pomFile.getParentFile();
+
+ for(MavenProjectInfo projectInfo : projects.values()) {
+ File childPom = projectInfo.getPomFile();
+ if(isSubDir(oldDir, childPom.getParentFile())) {
+ String oldPath = oldDir.getAbsolutePath();
+ String path = childPom.getAbsolutePath().substring(oldPath.length());
+ projectInfo.setPomFile(new File(newDir, path));
+ }
+ }
+
+ this.pomFile = pomFile;
+ }
+
+ /** @deprecated use set/get BasedirRename */
+ public void setNeedsRename(boolean needsRename) {
+ setBasedirRename(needsRename? RENAME_REQUIRED: RENAME_NO);
+ }
+
+ /** @deprecated use set/get BasedirRenamePolicy */
+ public boolean isNeedsRename() {
+ return getBasedirRename() == RENAME_REQUIRED;
+ }
+
+ /**
+ * See {@link #RENAME_NO}, {@link #RENAME_REQUIRED}
+ */
+ public void setBasedirRename(int basedirRename) {
+ this.basedirRename = basedirRename;
+ }
+
+ /**
+ * See {@link #RENAME_NO}, {@link #RENAME_REQUIRED}
+ */
+ public int getBasedirRename() {
+ return basedirRename;
+ }
+
+ private boolean isSubDir(File parentDir, File subDir) {
+ if(parentDir.equals(subDir)) {
+ return true;
+ }
+
+ if(subDir.getParentFile()!=null) {
+ return isSubDir(parentDir, subDir.getParentFile());
+ }
+
+ return false;
+ }
+
+ public void add(MavenProjectInfo info) {
+ String key;
+ try {
+ if(info.getPomFile() == null) {
+ // Is this possible?
+ key = info.getLabel();
+ } else {
+ key = info.getPomFile().getCanonicalPath();
+ }
+ } catch(IOException ex) {
+ throw new RuntimeException(ex);
+ }
+ MavenProjectInfo i = projects.get(key);
+ if(i==null) {
+ projects.put(key, info);
+ } else {
+ MavenLogger.log("Project info " + this + " already has a child project info with key '" + key + "'"); //$NON-NLS-3$
+ for(Iterator<String> it = info.getProfiles().iterator(); it.hasNext();) {
+ i.addProfile(it.next());
+ }
+ }
+ }
+
+ public void addProfile(String profileId) {
+ if(profileId!=null) {
+ this.profiles.add(profileId);
+ }
+ }
+
+ public void addProfiles(Collection<String> profiles) {
+ this.profiles.addAll(profiles);
+ }
+
+ public String getLabel() {
+ return this.label;
+ }
+
+ public File getPomFile() {
+ return this.pomFile;
+ }
+
+ public Model getModel() {
+ return this.model;
+ }
+
+ public void setModel(Model model) {
+ this.model = model;
+ }
+
+ public Collection<MavenProjectInfo> getProjects() {
+ return this.projects.values();
+ }
+
+ public MavenProjectInfo getParent() {
+ return this.parent;
+ }
+
+ public Set<String> getProfiles() {
+ return this.profiles;
+ }
+
+ public boolean equals(Object obj) {
+ if(obj instanceof MavenProjectInfo) {
+ MavenProjectInfo info = (MavenProjectInfo) obj;
+ if(pomFile == null) {
+ return info.getPomFile() == null;
+ }
+ return pomFile.equals(info.getPomFile());
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return pomFile==null ? 0 : pomFile.hashCode();
+ }
+
+ public String toString() {
+ return "'" + label + "'" + (pomFile == null ? "" : " " + pomFile.getAbsolutePath()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectManager.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectManager.java
new file mode 100644
index 00000000..303d30a7
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectManager.java
@@ -0,0 +1,166 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.File;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+import org.apache.maven.artifact.repository.MavenArtifactRepository;
+import org.apache.maven.execution.MavenExecutionRequest;
+
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.internal.project.registry.ProjectRegistryManager;
+import org.eclipse.m2e.core.internal.project.registry.ProjectRegistryRefreshJob;
+
+
+/**
+ * This class keeps track of all Maven projects present in the workspace and provides mapping between Maven artifacts
+ * and Workspace projects.
+ */
+public class MavenProjectManager {
+
+ public static final String STATE_FILENAME = "workspacestate.properties"; //$NON-NLS-1$
+
+ private final ProjectRegistryManager manager;
+
+ private final ProjectRegistryRefreshJob mavenBackgroundJob;
+
+ private final File workspaceStateFile;
+
+ public MavenProjectManager(ProjectRegistryManager manager, ProjectRegistryRefreshJob mavenBackgroundJob, File stateLocation) {
+ this.manager = manager;
+ this.mavenBackgroundJob = mavenBackgroundJob;
+ this.workspaceStateFile = new File(stateLocation, STATE_FILENAME);
+ }
+
+ // Maven projects
+
+ /**
+ * Performs requested Maven project update asynchronously, using background
+ * job. This method returns immediately.
+ */
+ public void refresh(MavenUpdateRequest request) {
+ mavenBackgroundJob.refresh(request);
+ }
+
+ /**
+ * Performs requested Maven project update synchronously. In other words, this method
+ * does not return until all affected projects have been updated and
+ * corresponding MavenProjectChangeEvent's broadcast.
+ *
+ * This method acquires a lock on the workspace's root.
+ */
+ public void refresh(MavenUpdateRequest request, IProgressMonitor monitor) throws CoreException {
+ manager.refresh(request, monitor);
+ }
+
+ public void addMavenProjectChangedListener(IMavenProjectChangedListener listener) {
+ manager.addMavenProjectChangedListener(listener);
+ }
+
+ public void removeMavenProjectChangedListener(IMavenProjectChangedListener listener) {
+ manager.removeMavenProjectChangedListener(listener);
+ }
+
+ /**
+ * Returns MavenProjectFacade corresponding to the pom. This method first looks in the project cache, then attempts to
+ * load the pom if the pom is not found in the cache. In the latter case, workspace resolution is assumed to be
+ * enabled for the pom but the pom will not be added to the cache.
+ */
+ public IMavenProjectFacade create(IFile pom, boolean load, IProgressMonitor monitor) {
+ return manager.create(pom, load, monitor);
+ }
+
+ public IMavenProjectFacade create(IProject project, IProgressMonitor monitor) {
+ return manager.create(project, monitor);
+ }
+
+ public ResolverConfiguration getResolverConfiguration(IProject project) {
+ IMavenProjectFacade projectFacade = create(project, new NullProgressMonitor());
+ if(projectFacade!=null) {
+ return projectFacade.getResolverConfiguration();
+ }
+ return manager.readResolverConfiguration(project);
+ }
+
+ public boolean setResolverConfiguration(IProject project, ResolverConfiguration configuration) {
+ return manager.setResolverConfiguration(project, configuration);
+ }
+
+ /**
+ * @return MavenProjectFacade[] all maven projects which exist under workspace root
+ */
+ public IMavenProjectFacade[] getProjects() {
+ return manager.getProjects();
+ }
+
+ /**
+ * @return IMavenProjectFacade cached IMavenProjectFacade corresponding
+ * to the project or null if there is no cache entry for the project.
+ */
+ public IMavenProjectFacade getProject(IProject project) {
+ return manager.getProject(project);
+ }
+
+ public IMavenProjectFacade getMavenProject(String groupId, String artifactId, String version) {
+ return manager.getMavenProject(groupId, artifactId, version);
+ }
+
+ public File getWorkspaceStateFile() {
+ return workspaceStateFile;
+ }
+
+ /**
+ * Request full maven build for a project.
+ *
+ * This call only has effect for projects that have maven nature and
+ * Maven builder configured.
+ *
+ * This call does not trigger the build. Instead next time Maven builder
+ * processes the project it will use goals to execute during clean
+ * build regardless of the build type requested.
+ *
+ * The main purpose of this call is to allow coordination between multiple
+ * builders configured for the same project.
+ */
+ public void requestFullMavenBuild(IProject project) throws CoreException {
+ project.setSessionProperty(IMavenConstants.FULL_MAVEN_BUILD, Boolean.TRUE);
+ }
+
+ /**
+ * PROVISIONAL
+ */
+ public MavenExecutionRequest createExecutionRequest(IFile pom, ResolverConfiguration resolverConfiguration, IProgressMonitor monitor) throws CoreException {
+ return manager.createExecutionRequest(pom, resolverConfiguration, monitor);
+ }
+
+ /**
+ * PROVISIONAL
+ */
+ public MavenExecutionRequest createExecutionRequest(IMavenProjectFacade project, IProgressMonitor monitor) throws CoreException {
+ return manager.createExecutionRequest(project.getPom(), project.getResolverConfiguration(), monitor);
+ }
+
+ /**
+ * Local repository implementation that checks artifacts in workspace first.
+ *
+ * PROVISIONAL
+ */
+ public MavenArtifactRepository getWorkspaceLocalRepository() throws CoreException {
+ return manager.getWorkspaceLocalRepository();
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectPomScanner.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectPomScanner.java
new file mode 100644
index 00000000..fe73112f
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectPomScanner.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.osgi.util.NLS;
+
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Model;
+import org.apache.maven.model.Parent;
+import org.apache.maven.model.Profile;
+import org.apache.maven.model.Scm;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenConsole;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.embedder.MavenModelManager;
+import org.eclipse.m2e.core.internal.Messages;
+
+/**
+ * Maven project scanner using dependency list
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenProjectPomScanner<T> extends AbstractProjectScanner<MavenProjectScmInfo> {
+
+ private final boolean developer;
+
+ private final Dependency[] dependencies;
+
+ private MavenConsole console;
+
+ private IMaven maven;
+
+ public MavenProjectPomScanner(boolean developer, Dependency[] dependencies, //
+ MavenModelManager modelManager, MavenConsole console) {
+ this.developer = developer;
+ this.dependencies = dependencies;
+ this.console = console;
+ this.maven = MavenPlugin.getDefault().getMaven();
+ }
+
+ public String getDescription() {
+ if(dependencies.length==1) {
+ Dependency d = dependencies[0];
+ return d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion() + (d.getClassifier()==null ? "" : ":" + d.getClassifier()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ }
+ return "" + dependencies.length + " projects"; //$NON-NLS-1$
+ }
+
+ public void run(IProgressMonitor monitor) throws InterruptedException {
+ for(int i = 0; i < dependencies.length; i++ ) {
+ if(monitor.isCanceled()) {
+ throw new InterruptedException();
+ }
+
+ Dependency d = dependencies[i];
+
+ try {
+ Model model = resolveModel(d.getGroupId(), d.getArtifactId(), d.getVersion(), monitor);
+ if(model==null) {
+ String msg = "Can't resolve " + d.getArtifactId();
+ console.logError(msg);
+ addError(new Exception(msg));
+ continue;
+ }
+
+ Scm scm = resolveScm(model, monitor);
+ if(scm==null) {
+ String msg = "No SCM info for " + d.getArtifactId();
+ console.logError(msg);
+ addError(new Exception(msg));
+ continue;
+ }
+
+ String tag = scm.getTag();
+
+ console.logMessage(d.getArtifactId());
+ console.logMessage("Connection: " + scm.getConnection());
+ console.logMessage(" dev: " + scm.getDeveloperConnection());
+ console.logMessage(" url: " + scm.getUrl());
+ console.logMessage(" tag: " + tag);
+
+ String connection;
+ if(developer) {
+ connection = scm.getDeveloperConnection();
+ if(connection==null) {
+ String msg = d.getArtifactId() + " doesn't specify developer SCM connection";
+ console.logError(msg);
+ addError(new Exception(msg));
+ continue;
+ }
+ } else {
+ connection = scm.getConnection();
+ if(connection==null) {
+ String msg = d.getArtifactId() + " doesn't specify SCM connection";
+ console.logError(msg);
+ addError(new Exception(msg));
+ continue;
+ }
+ }
+
+ // connection: scm:svn:https://svn.apache.org/repos/asf/incubator/wicket/branches/wicket-1.2.x/wicket
+ // dev: scm:svn:https://svn.apache.org/repos/asf/incubator/wicket/branches/wicket-1.2.x/wicket
+ // url: http://svn.apache.org/viewvc/incubator/wicket/branches/wicket-1.2.x/wicket
+ // tag: HEAD
+
+ // TODO add an option to select all modules/projects and optimize scan
+
+ if(connection.endsWith("/")) { //$NON-NLS-1$
+ connection = connection.substring(0, connection.length()-1);
+ }
+
+ int n = connection.lastIndexOf("/"); //$NON-NLS-1$
+ String label = (n == -1 ? connection : connection.substring(n)) + "/" + IMavenConstants.POM_FILE_NAME; //$NON-NLS-1$
+
+ addProject(new MavenProjectScmInfo(label, model, null, tag, connection, connection));
+
+ } catch(Exception ex) {
+ addError(ex);
+ String msg = "Error reading " + d.getArtifactId();
+ console.logError(msg);
+ MavenLogger.log(msg, ex);
+ }
+ }
+ }
+
+ private Scm resolveScm(Model model, IProgressMonitor monitor) throws ArtifactResolutionException,
+ ArtifactNotFoundException, XmlPullParserException, IOException, CoreException {
+ Scm scm = model.getScm();
+ if(scm != null) {
+ return scm;
+ }
+
+ Parent parent = model.getParent();
+ if(parent == null) {
+ return null;
+ }
+
+ Model parentModel = resolveModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), monitor);
+ if(parentModel==null) {
+ return null;
+ }
+
+ Scm parentScm = resolveScm(parentModel, monitor);
+ if(parentScm==null) {
+ return null;
+ }
+
+ Set<String> modules = new HashSet<String>(parentModel.getModules());
+ List<Profile> parentModelProfiles = parentModel.getProfiles();
+ for(Profile profile : parentModelProfiles) {
+ modules.addAll(profile.getModules());
+ }
+
+ // heuristics for matching module names to artifactId
+ String artifactId = model.getArtifactId();
+ for(String module : modules) {
+ if(module.equals(artifactId) || module.endsWith("/" + artifactId)) { //$NON-NLS-1$
+ if(parentScm.getConnection()!=null) {
+ parentScm.setConnection(parentScm.getConnection() + "/" + module); //$NON-NLS-1$
+ }
+ if(parentScm.getDeveloperConnection()!=null) {
+ parentScm.setDeveloperConnection(parentScm.getDeveloperConnection() + "/" + module); //$NON-NLS-1$
+ }
+ return parentScm;
+ }
+ }
+
+ // XXX read modules from profiles
+
+ return parentScm;
+ }
+
+ private Model resolveModel(String groupId, String artifactId, String version, IProgressMonitor monitor)
+ throws CoreException {
+ monitor.subTask(NLS.bind(Messages.MavenProjectPomScanner_task_resolving, new Object[] { groupId, artifactId, version}));
+
+ List<ArtifactRepository> repositories = maven.getArtifactRepositories();
+ Artifact artifact = maven.resolve(groupId, artifactId, version, "pom", null, repositories, monitor); //$NON-NLS-1$
+
+ File file = artifact.getFile();
+ if(file == null) {
+ return null;
+ }
+
+ // XXX this fail on reading extensions
+ // MavenProject project = embedder.readProject(file);
+
+ monitor.subTask(NLS.bind(Messages.MavenProjectPomScanner_23, new Object[] {groupId, artifactId, version}));
+ return maven.readModel(file);
+ }
+
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectScmInfo.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectScmInfo.java
new file mode 100644
index 00000000..fc810dfa
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectScmInfo.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.File;
+
+import org.apache.maven.model.Model;
+
+
+/**
+ * @author Eugene Kuleshov
+ */
+public class MavenProjectScmInfo extends MavenProjectInfo {
+
+ private final String folderUrl;
+ private final String repositoryUrl;
+ private final String revision;
+ private final String branch;
+
+ private String username;
+ private String password;
+
+ private File sslCertificate;
+ private String sslCertificatePassphrase;
+
+ public MavenProjectScmInfo(String label, Model model, MavenProjectInfo parent, //
+ String revision, String folderUrl, String repositoryUrl) {
+ this(label, model, parent, null, revision, folderUrl, repositoryUrl);
+ }
+
+ public MavenProjectScmInfo(String label, Model model, MavenProjectInfo parent, //
+ String branch, String revision, String folderUrl, String repositoryUrl) {
+ super(label, null, model, parent);
+ this.revision = revision;
+ this.folderUrl = folderUrl;
+ this.repositoryUrl = repositoryUrl;
+ this.branch = branch;
+ }
+
+ public String getBranch() {
+ return this.branch;
+ }
+
+ public String getRevision() {
+ return this.revision;
+ }
+
+ public String getFolderUrl() {
+ return folderUrl;
+ }
+
+ public String getRepositoryUrl() {
+ return repositoryUrl;
+ }
+
+ public boolean equals(Object obj) {
+ if(obj instanceof MavenProjectScmInfo) {
+ MavenProjectScmInfo info = (MavenProjectScmInfo) obj;
+ return folderUrl.equals(info.getFolderUrl());
+ }
+ return false;
+ }
+
+ public int hashCode() {
+ return folderUrl.hashCode();
+ }
+
+ public String toString() {
+ return getLabel() + " " + folderUrl; //$NON-NLS-1$
+ }
+
+ public String getUsername() {
+ return username;
+ }
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public void setSSLCertificate(File certificate) {
+ this.sslCertificate = certificate;
+ }
+ public File getSSLCertificate() {
+ return sslCertificate;
+ }
+
+ public String getSSLCertificatePassphrase() {
+ return sslCertificatePassphrase;
+ }
+ public void setSSLCertificatePassphrase(String passphrase) {
+ this.sslCertificatePassphrase = passphrase;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectUtils.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectUtils.java
new file mode 100644
index 00000000..cbcf60e6
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenProjectUtils.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.File;
+import java.util.LinkedHashSet;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+import org.apache.maven.model.Resource;
+
+/**
+ * Collection of helper methods to map between MavenProject and IResource.
+ *
+ * @author igor
+ */
+public class MavenProjectUtils {
+
+ private MavenProjectUtils() {
+ }
+
+ /**
+ * Returns project resource for given filesystem location or null the location is outside of project.
+ *
+ * @param resourceLocation absolute filesystem location
+ * @return IPath the full, absolute workspace path resourceLocation
+ */
+ public static IPath getProjectRelativePath(IProject project, String resourceLocation) {
+ if(resourceLocation == null) {
+ return null;
+ }
+ IPath projectLocation = project.getLocation();
+ IPath directory = Path.fromOSString(resourceLocation); // this is an absolute path!
+ if(projectLocation == null || !projectLocation.isPrefixOf(directory)) {
+ return null;
+ }
+
+ return directory.removeFirstSegments(projectLocation.segmentCount()).makeRelative().setDevice(null);
+ }
+
+ public static IPath[] getResourceLocations(IProject project, List<Resource> resources) {
+ LinkedHashSet<IPath> locations = new LinkedHashSet<IPath>();
+ for(Resource resource : resources) {
+ locations.add(getProjectRelativePath(project, resource.getDirectory()));
+ }
+ return locations.toArray(new IPath[locations.size()]);
+ }
+
+ public static IPath[] getSourceLocations(IProject project, List<String> roots) {
+ LinkedHashSet<IPath> locations = new LinkedHashSet<IPath>();
+ for(String root : roots) {
+ IPath path = getProjectRelativePath(project, root);
+ if(path != null) {
+ locations.add(path);
+ }
+ }
+ return locations.toArray(new IPath[locations.size()]);
+ }
+
+ /**
+ * Returns the full, absolute path of the given file relative to the workspace. Returns null if the file does not
+ * exist or is not a member of this project.
+ */
+ public static IPath getFullPath(IProject project, File file) {
+ if (project == null || file == null) {
+ return null;
+ }
+
+ IPath projectPath = project.getLocation();
+ if(projectPath == null) {
+ return null;
+ }
+
+ IPath filePath = new Path(file.getAbsolutePath());
+ if (!projectPath.isPrefixOf(filePath)) {
+ return null;
+ }
+ IResource resource = project.findMember(filePath.removeFirstSegments(projectPath.segmentCount()));
+ if (resource == null) {
+ return null;
+ }
+ return resource.getFullPath();
+ }
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenUpdateRequest.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenUpdateRequest.java
new file mode 100644
index 00000000..8f936f24
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/MavenUpdateRequest.java
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+
+import org.eclipse.m2e.core.core.IMavenConstants;
+
+/**
+ * Maven project update request
+ *
+ * @author Eugene Kuleshov
+ */
+public class MavenUpdateRequest {
+ private boolean offline = false;
+ private boolean updateSnapshots = false;
+ private boolean force = true;
+
+ /**
+ * Set of {@link IFile}
+ */
+ private final Set<IFile> pomFiles = new LinkedHashSet<IFile>();
+
+ public MavenUpdateRequest(boolean offline, boolean updateSnapshots) {
+ this.offline = offline;
+ this.updateSnapshots = updateSnapshots;
+ }
+
+ public MavenUpdateRequest(IProject project, boolean offline, boolean updateSnapshots) {
+ this(offline, updateSnapshots);
+ addPomFile(project);
+ }
+
+ public MavenUpdateRequest(IProject[] projects, boolean offline, boolean updateSnapshots) {
+ this(offline, updateSnapshots);
+
+ for(int i = 0; i < projects.length; i++ ) {
+ addPomFile(projects[i]);
+ }
+ }
+
+ public boolean isOffline() {
+ return this.offline;
+ }
+
+ public boolean isUpdateSnapshots() {
+ return this.updateSnapshots;
+ }
+
+ public void addPomFiles(Set<IFile> pomFiles) {
+ for (IFile pomFile : pomFiles) {
+ addPomFile(pomFile);
+ }
+ }
+
+ public void addPomFile(IFile pomFile) {
+ pomFiles.add(pomFile);
+ }
+
+ public void addPomFile(IProject project) {
+ pomFiles.add(project.getFile(IMavenConstants.POM_FILE_NAME));
+
+ }
+
+ public void removePomFile(IFile pomFile) {
+ pomFiles.remove(pomFile);
+ }
+
+ /**
+ * Returns Set of {@link IFile}
+ */
+ public Set<IFile> getPomFiles() {
+ return this.pomFiles;
+ }
+
+ public boolean isEmpty() {
+ return this.pomFiles.isEmpty();
+ }
+
+ public boolean isForce() {
+ return force;
+ }
+
+ public void setForce(boolean force) {
+ this.force = force;
+ }
+
+ public String toString() {
+ StringBuilder sb = new StringBuilder("["); //$NON-NLS-1$
+ String sep = ""; //$NON-NLS-1$
+ for(IFile pomFile : pomFiles) {
+ sb.append(sep);
+ sb.append(pomFile.getFullPath());
+ sep = ", "; //$NON-NLS-1$
+ }
+ sb.append("]"); //$NON-NLS-1$
+
+ if(offline) {
+ sb.append(" offline"); //$NON-NLS-1$
+ }
+ if(updateSnapshots) {
+ sb.append(" updateSnapshots"); //$NON-NLS-1$
+ }
+ if(force) {
+ sb.append(" force"); //$NON-NLS-1$
+ }
+
+ return sb.toString();
+ }
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ProjectImportConfiguration.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ProjectImportConfiguration.java
new file mode 100644
index 00000000..e8f8b8bf
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ProjectImportConfiguration.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspace;
+import org.eclipse.core.resources.IWorkspaceRoot;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.ui.IWorkingSet;
+
+import org.apache.maven.model.Model;
+
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.Messages;
+
+
+/**
+ * Project import configuration bean.
+ */
+public class ProjectImportConfiguration {
+
+ private static final String GROUP_ID = "\\[groupId\\]"; //$NON-NLS-1$
+
+ private static final String ARTIFACT_ID = "\\[artifactId\\]"; //$NON-NLS-1$
+
+ private static final String VERSION = "\\[version\\]"; //$NON-NLS-1$
+
+ /** resolver configuration bean */
+ private ResolverConfiguration resolverConfiguration;
+
+ /** the project name template */
+ private String projectNameTemplate = ""; //$NON-NLS-1$
+
+ private IWorkingSet[] workingSets;
+
+ /** Creates a new configuration. */
+ public ProjectImportConfiguration(ResolverConfiguration resolverConfiguration) {
+ this.resolverConfiguration = resolverConfiguration;
+ }
+
+ /** Creates a new configuration. */
+ public ProjectImportConfiguration() {
+ this(new ResolverConfiguration());
+ }
+
+ /** Returns the resolver configuration bean. */
+ public ResolverConfiguration getResolverConfiguration() {
+ return resolverConfiguration;
+ }
+
+ /** Sets the project name template. */
+ public void setProjectNameTemplate(String projectNameTemplate) {
+ this.projectNameTemplate = projectNameTemplate;
+ }
+
+ /** Returns the project name template. */
+ public String getProjectNameTemplate() {
+ return projectNameTemplate;
+ }
+
+ /** @deprecated UI aspects will be refactored out of core import logic */
+ public void setWorkingSet(IWorkingSet workingSet) {
+ this.workingSets = workingSet == null ? null : new IWorkingSet[]{workingSet};
+ }
+
+ /** @deprecated UI aspects will be refactored out of core import logic */
+ public void setWorkingSets(IWorkingSet[] workingSets) {
+ this.workingSets = workingSets;
+ }
+
+ /** @deprecated UI aspects will be refactored out of core import logic */
+ public IWorkingSet[] getWorkingSets() {
+ return this.workingSets;
+ }
+
+ /**
+ * Calculates the project name for the given model.
+ *
+ * @deprecated This method does not take into account MavenProjectInfo.basedirRename
+ */
+ public String getProjectName(Model model) {
+ // XXX should use resolved MavenProject or Model
+ if(projectNameTemplate.length() == 0) {
+ return model.getArtifactId();
+ }
+
+ String artifactId = model.getArtifactId();
+ String groupId = model.getGroupId();
+ if(groupId == null && model.getParent() != null) {
+ groupId = model.getParent().getGroupId();
+ }
+ String version = model.getVersion();
+ if(version == null && model.getParent() != null) {
+ version = model.getParent().getVersion();
+ }
+
+ // XXX needs MavenProjectManager update to resolve groupId and version
+ return projectNameTemplate.replaceAll(GROUP_ID, groupId).replaceAll(ARTIFACT_ID, artifactId).replaceAll(VERSION,
+ version == null ? "" : version); //$NON-NLS-1$
+ }
+
+ /**
+ * @deprecated This method does not take into account MavenProjectInfo.basedirRename.
+ * Use IMavenProjectImportResult#getProject instead
+ */
+ public IProject getProject(IWorkspaceRoot root, Model model) {
+ return root.getProject(getProjectName(model));
+ }
+
+ /**
+ * @deprecated business logic does not belong to a value object
+ */
+ public IStatus validateProjectName(Model model) {
+ String projectName = getProjectName(model);
+ IWorkspace workspace = ResourcesPlugin.getWorkspace();
+
+ // check if the project name is valid
+ IStatus nameStatus = workspace.validateName(projectName, IResource.PROJECT);
+ if(!nameStatus.isOK()) {
+ return nameStatus;
+ }
+
+ // check if project already exists
+ if(workspace.getRoot().getProject(projectName).exists()) {
+ return new Status( IStatus.ERROR, IMavenConstants.PLUGIN_ID, 0, Messages.getString("wizard.project.page.project.validator.projectExists",projectName), null); //$NON-NLS-1$
+ }
+
+ return Status.OK_STATUS;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ResolverConfiguration.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ResolverConfiguration.java
new file mode 100644
index 00000000..8271bd19
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/ResolverConfiguration.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Resolver configuration holder.
+ *
+ * TODO need a better name, this configures all aspects of maven project in eclipse,
+ * not just dependency resolution.
+ *
+ * @author Eugene Kuleshov
+ */
+public class ResolverConfiguration implements Serializable {
+ private static final long serialVersionUID = 1258510761534886581L;
+
+ private boolean resolveWorkspaceProjects = true;
+
+ private String activeProfiles = ""; //$NON-NLS-1$
+
+ public boolean shouldResolveWorkspaceProjects() {
+ return this.resolveWorkspaceProjects;
+ }
+
+ public String getActiveProfiles() {
+ return this.activeProfiles;
+ }
+
+ public List<String> getActiveProfileList() {
+ if (activeProfiles.trim().length() > 0) {
+ return Arrays.asList(activeProfiles.split("[,\\s\\|]")); //$NON-NLS-1$
+ }
+ return new ArrayList<String>();
+ }
+
+ public void setResolveWorkspaceProjects(boolean resolveWorkspaceProjects) {
+ this.resolveWorkspaceProjects = resolveWorkspaceProjects;
+ }
+
+ public void setActiveProfiles(String activeProfiles) {
+ this.activeProfiles = activeProfiles;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractBuildParticipant.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractBuildParticipant.java
new file mode 100644
index 00000000..ebc79a35
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractBuildParticipant.java
@@ -0,0 +1,68 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResourceDelta;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.apache.maven.execution.MavenSession;
+
+import org.sonatype.plexus.build.incremental.BuildContext;
+
+import org.eclipse.m2e.core.internal.builder.InternalBuildParticipant;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+
+
+/**
+ * AbstractMavenBuildParticipant
+ *
+ * @author igor
+ */
+public abstract class AbstractBuildParticipant extends InternalBuildParticipant {
+
+ /**
+ * This method is called during workspace full or incremental build.
+ */
+ public abstract Set<IProject> build(int kind, IProgressMonitor monitor) throws Exception;
+
+ public boolean callOnEmptyDelta() {
+ return false;
+ }
+
+ /**
+ * This method is called during workspace clean build.
+ */
+ @SuppressWarnings("unused")
+ public void clean(IProgressMonitor monitor) throws CoreException {
+ // default implementation does nothing
+ }
+
+ protected IMavenProjectFacade getMavenProjectFacade() {
+ return super.getMavenProjectFacade();
+ }
+
+ protected IResourceDelta getDelta(IProject project) {
+ return super.getDelta(project);
+ }
+
+ protected MavenSession getSession() {
+ return super.getSession();
+ }
+
+ protected BuildContext getBuildContext() {
+ return super.getBuildContext();
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractLifecycleMapping.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractLifecycleMapping.java
new file mode 100644
index 00000000..e64db998
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractLifecycleMapping.java
@@ -0,0 +1,219 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.ICommand;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+
+import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.plugin.MojoExecution;
+
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+
+
+/**
+ * AbstractLifecycleMapping
+ *
+ * @author igor
+ */
+public abstract class AbstractLifecycleMapping implements ILifecycleMapping {
+
+ private String name;
+
+ private String id;
+
+ private boolean showConfigurators;
+
+ /**
+ * Calls #configure method of all registered project configurators
+ */
+ public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
+ addMavenBuilder(request.getProject(), monitor);
+
+ for(AbstractProjectConfigurator configurator : getProjectConfigurators(request.getMavenProjectFacade(), monitor)) {
+ if(monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ configurator.configure(request, monitor);
+ }
+ }
+
+ public void unconfigure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
+ for(AbstractProjectConfigurator configurator : getProjectConfigurators(request.getMavenProjectFacade(), monitor)) {
+ if(monitor.isCanceled()) {
+ throw new OperationCanceledException();
+ }
+ configurator.unconfigure(request, monitor);
+ }
+ }
+
+ protected static void addMavenBuilder(IProject project, IProgressMonitor monitor) throws CoreException {
+ IProjectDescription description = project.getDescription();
+
+ // ensure Maven builder is always the last one
+ ICommand mavenBuilder = null;
+ ArrayList<ICommand> newSpec = new ArrayList<ICommand>();
+ for(ICommand command : description.getBuildSpec()) {
+ if(IMavenConstants.BUILDER_ID.equals(command.getBuilderName())) {
+ mavenBuilder = command;
+ } else {
+ newSpec.add(command);
+ }
+ }
+ if(mavenBuilder == null) {
+ mavenBuilder = description.newCommand();
+ mavenBuilder.setBuilderName(IMavenConstants.BUILDER_ID);
+ }
+ newSpec.add(mavenBuilder);
+ description.setBuildSpec(newSpec.toArray(new ICommand[newSpec.size()]));
+
+ project.setDescription(description, monitor);
+ }
+
+ /**
+ * @return Returns the name.
+ */
+ public String getName() {
+ return this.name;
+ }
+
+ /**
+ * @param name The name to set.
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return Returns the id.
+ */
+ public String getId() {
+ return this.id;
+ }
+
+ /**
+ * @param id The id to set.
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * @param show Set whether the project configurators should show. Default is true.
+ */
+ public void setShowConfigurators(boolean show) {
+ this.showConfigurators = show;
+ }
+
+ /**
+ * Returns whether the project configurators will be shown in the UI. Default is true.
+ */
+ public boolean showConfigurators() {
+ return this.showConfigurators;
+ }
+
+ protected List<AbstractBuildParticipant> getBuildParticipants(IMavenProjectFacade facade,
+ List<AbstractProjectConfigurator> configurators, IProgressMonitor monitor) throws CoreException {
+ List<AbstractBuildParticipant> participants = new ArrayList<AbstractBuildParticipant>();
+
+ for(MojoExecution execution : facade.getExecutionPlan(monitor).getMojoExecutions()) {
+ for(AbstractProjectConfigurator configurator : configurators) {
+ if(configurator.isSupportedExecution(execution)) {
+ AbstractBuildParticipant participant = configurator.getBuildParticipant(execution);
+ if(participant != null) {
+ participants.add(participant);
+ }
+ }
+ }
+ }
+
+ return participants;
+ }
+
+ public List<MojoExecution> getNotCoveredMojoExecutions(IMavenProjectFacade mavenProjectFacade,
+ IProgressMonitor monitor) throws CoreException {
+ List<MojoExecution> result = new ArrayList<MojoExecution>();
+
+ List<AbstractProjectConfigurator> projectConfigurators = getProjectConfigurators(mavenProjectFacade, monitor);
+ MavenExecutionPlan mavenExecutionPlan = mavenProjectFacade.getExecutionPlan(monitor);
+ List<MojoExecution> allMojoExecutions = mavenExecutionPlan.getMojoExecutions();
+ for(MojoExecution mojoExecution : allMojoExecutions) {
+ if(!isInterestingPhase(mojoExecution.getLifecyclePhase())) {
+ continue;
+ }
+ boolean isCovered = false;
+ for(AbstractProjectConfigurator configurator : projectConfigurators) {
+ if(configurator.isSupportedExecution(mojoExecution)) {
+ isCovered = true;
+ break;
+ }
+ }
+ if(!isCovered) {
+ result.add(mojoExecution);
+ }
+ }
+ return result;
+ }
+
+ public List<AbstractBuildParticipant> getBuildParticipants(IMavenProjectFacade facade, IProgressMonitor monitor)
+ throws CoreException {
+ List<AbstractProjectConfigurator> configurators = getProjectConfigurators(facade, monitor);
+
+ return getBuildParticipants(facade, configurators, monitor);
+ }
+
+ private static final String[] INTERESTING_PHASES = {"validate", //
+ "initialize", //
+ "generate-sources", //
+ "process-sources", //
+ "generate-resources", //
+ "process-resources", //
+ "compile", //
+ "process-classes", //
+ "generate-test-sources", //
+ "process-test-sources", //
+ "generate-test-resources", //
+ "process-test-resources", //
+ "test-compile", //
+ "process-test-classes", //
+ // "test", //
+ // "prepare-package", //
+ // "package", //
+ //"pre-integration-test", //
+ // "integration-test", //
+ // "post-integration-test", //
+ // "verify", //
+ // "install", //
+ // "deploy", //
+ };
+
+ public boolean isInterestingPhase(String phase) {
+ for(String interestingPhase : INTERESTING_PHASES) {
+ if(interestingPhase.equals(phase)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public abstract List<AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade mavenProjectFacade,
+ IProgressMonitor monitor) throws CoreException;
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractProjectConfigurator.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractProjectConfigurator.java
new file mode 100644
index 00000000..d6d51c76
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/AbstractProjectConfigurator.java
@@ -0,0 +1,243 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IProjectDescription;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExecutableExtension;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.plugin.MojoExecution;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.IMavenConstants;
+import org.eclipse.m2e.core.core.MavenConsole;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.embedder.IMavenConfiguration;
+import org.eclipse.m2e.core.internal.Messages;
+import org.eclipse.m2e.core.project.IMavenMarkerManager;
+import org.eclipse.m2e.core.project.IMavenProjectChangedListener;
+import org.eclipse.m2e.core.project.MavenProjectChangedEvent;
+import org.eclipse.m2e.core.project.MavenProjectManager;
+
+
+/**
+ * Used to configure maven projects.
+ *
+ * @author Igor Fedorenko
+ */
+public abstract class AbstractProjectConfigurator implements IExecutableExtension, IMavenProjectChangedListener {
+
+ public static final String ATTR_ID = "id"; //$NON-NLS-1$
+
+ public static final String ATTR_PRIORITY = "priority"; //$NON-NLS-1$
+
+ public static final String ATTR_NAME = "name"; //$NON-NLS-1$
+
+ public static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+
+ private int priority;
+
+ private String id;
+
+ private String name;
+
+ /**
+ * List of maven plugin goal patterns for which this project configurator is enabled automatically. Can be null, in
+ * which case the project configurator can only be enabled explicitly in pom.xml.
+ */
+ protected List<PluginExecutionFilter> pluginExecutionFilters;
+
+ protected MavenProjectManager projectManager;
+
+ protected IMavenConfiguration mavenConfiguration;
+
+ protected IMavenMarkerManager markerManager;
+
+ protected MavenConsole console;
+
+ protected IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ public void setProjectManager(MavenProjectManager projectManager) {
+ this.projectManager = projectManager;
+ }
+
+ public void setMavenConfiguration(IMavenConfiguration mavenConfiguration) {
+ this.mavenConfiguration = mavenConfiguration;
+ }
+
+ public void setMarkerManager(IMavenMarkerManager markerManager) {
+ this.markerManager = markerManager;
+ }
+
+ public void setConsole(MavenConsole console) {
+ this.console = console;
+ }
+
+ /**
+ * Configures Eclipse project passed in ProjectConfigurationRequest, using information from Maven project and other
+ * configuration request parameters
+ * <p>
+ * <i>Should be implemented by subclass</i>
+ *
+ * @param request a project configuration request
+ * @param monitor a progress monitor
+ */
+ public abstract void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Removes Maven specific configuration from the project passed in ProjectConfigurationRequest
+ *
+ * @param request a project un-configuration request
+ * @param monitor a progress monitor
+ */
+ @SuppressWarnings("unused")
+ public void unconfigure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
+ }
+
+ /**
+ * Updates project configuration according project changes.
+ * <p>
+ * <i>Can be overwritten by subclass</i>
+ *
+ * @param event a project change event
+ * @param monitor a progress monitor
+ */
+ @SuppressWarnings("unused")
+ public void mavenProjectChanged(MavenProjectChangedEvent event, IProgressMonitor monitor) throws CoreException {
+ }
+
+ // IMavenProjectChangedListener
+
+ public final void mavenProjectChanged(MavenProjectChangedEvent[] events, IProgressMonitor monitor) {
+ for(int i = 0; i < events.length; i++ ) {
+ try {
+ mavenProjectChanged(events[i], monitor);
+ } catch(CoreException ex) {
+ MavenLogger.log(ex);
+ }
+ }
+ }
+
+ public int getPriority() {
+ return priority;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ // IExecutableExtension
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+ this.id = config.getAttribute(ATTR_ID);
+ this.name = config.getAttribute(ATTR_NAME);
+ String priorityString = config.getAttribute(ATTR_PRIORITY);
+ try {
+ priority = Integer.parseInt(priorityString);
+ } catch(Exception ex) {
+ priority = Integer.MAX_VALUE;
+ }
+
+ IConfigurationElement[] mojos = config.getChildren("mojo"); //$NON-NLS-1$
+ if(mojos != null && mojos.length > 0) {
+ pluginExecutionFilters = new ArrayList<PluginExecutionFilter>();
+ for(IConfigurationElement mojo : mojos) {
+ String groupId = mojo.getAttribute("groupId"); //$NON-NLS-1$
+ String artifactId = mojo.getAttribute("artifactId"); //$NON-NLS-1$
+ String versionRange = mojo.getAttribute("versionRange"); //$NON-NLS-1$
+ String goals = mojo.getAttribute("goals"); //$NON-NLS-1$
+ addPluginExecutionFilter(groupId, artifactId, versionRange, goals);
+ }
+ }
+ }
+
+ protected void addPluginExecutionFilter(String groupId, String artifactId, String versionRange, String goals) {
+ addPluginExecutionFilter(new PluginExecutionFilter(groupId, artifactId, versionRange, goals));
+ }
+
+ public void addPluginExecutionFilter(PluginExecutionFilter filter) {
+ // TODO validate
+ if(pluginExecutionFilters == null) {
+ pluginExecutionFilters = new ArrayList<PluginExecutionFilter>();
+ }
+ pluginExecutionFilters.add(filter);
+ }
+
+ // TODO move to a helper
+ public static void addNature(IProject project, String natureId, IProgressMonitor monitor) throws CoreException {
+ if(!project.hasNature(natureId)) {
+ IProjectDescription description = project.getDescription();
+ String[] prevNatures = description.getNatureIds();
+ String[] newNatures = new String[prevNatures.length + 1];
+ System.arraycopy(prevNatures, 0, newNatures, 1, prevNatures.length);
+ newNatures[0] = natureId;
+ description.setNatureIds(newNatures);
+ project.setDescription(description, monitor);
+ }
+ }
+
+ @Deprecated
+ protected <T> T getParameterValue(MavenSession session, MojoExecution execution, String parameter, Class<T> asType)
+ throws CoreException {
+ return maven.getMojoParameterValue(session, execution, parameter, asType);
+ }
+
+ protected <T> T getParameterValue(String parameter, Class<T> asType, MavenSession session, MojoExecution mojoExecution)
+ throws CoreException {
+ PluginExecution execution = new PluginExecution();
+ execution.setConfiguration(mojoExecution.getConfiguration());
+ return maven.getMojoParameterValue(parameter, asType, session, mojoExecution.getPlugin(), execution,
+ mojoExecution.getGoal());
+ }
+
+ protected void assertHasNature(IProject project, String natureId) throws CoreException {
+ if(project.getNature(natureId) == null) {
+ throw new CoreException(new Status(IStatus.ERROR, IMavenConstants.PLUGIN_ID, -1,
+ Messages.AbstractProjectConfigurator_error_missing_nature + natureId, null));
+ }
+ }
+
+ @Override
+ public String toString() {
+ return id + ":" + name + "(" + priority + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ public AbstractBuildParticipant getBuildParticipant(MojoExecution execution) {
+ return null;
+ }
+
+ public boolean isSupportedExecution(MojoExecution mojoExecution) {
+ if(pluginExecutionFilters == null) {
+ return false;
+ }
+ for(PluginExecutionFilter key : pluginExecutionFilters) {
+ if(key.match(mojoExecution)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/CustomizableLifecycleMapping.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/CustomizableLifecycleMapping.java
new file mode 100644
index 00000000..762ffd04
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/CustomizableLifecycleMapping.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+
+
+/**
+ * @author igor
+ */
+public class CustomizableLifecycleMapping extends AbstractLifecycleMapping {
+ public static final String EXTENSION_ID = "customizable"; //$NON-NLS-1$
+
+ private List<AbstractProjectConfigurator> configurators = new ArrayList<AbstractProjectConfigurator>();
+
+ @SuppressWarnings("unused")
+ public List<AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade facade, IProgressMonitor monitor)
+ throws CoreException {
+ return configurators;
+ }
+
+ public void addConfigurator(AbstractProjectConfigurator configurator) {
+ this.configurators.add(configurator);
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/DefaultLifecycleMapping.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/DefaultLifecycleMapping.java
new file mode 100644
index 00000000..3f5c2f00
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/DefaultLifecycleMapping.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.apache.maven.lifecycle.MavenExecutionPlan;
+import org.apache.maven.plugin.MojoExecution;
+
+import org.eclipse.m2e.core.internal.lifecycle.LifecycleMappingFactory;
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+
+
+/**
+ * DefaultLifecycleMapping
+ *
+ * @author igor
+ */
+public class DefaultLifecycleMapping extends CustomizableLifecycleMapping {
+
+ private static class MojoExecutionKey {
+ private final MojoExecution execution;
+
+ public MojoExecutionKey(MojoExecution execution) {
+ this.execution = execution;
+ }
+
+ public MojoExecution getMojoExecution() {
+ return execution;
+ }
+
+ public int hashCode() {
+ int hash = execution.getGroupId().hashCode();
+ hash = 17 * hash + execution.getArtifactId().hashCode();
+ hash = 17 * hash + execution.getVersion().hashCode();
+ hash = 17 * execution.getGoal().hashCode();
+ return hash;
+ }
+
+ public boolean equals(Object obj) {
+ if(this == obj) {
+ return true;
+ }
+ if(!(obj instanceof MojoExecutionKey)) {
+ return false;
+ }
+
+ MojoExecutionKey other = (MojoExecutionKey) obj;
+
+ return execution.getGroupId().equals(other.execution.getGroupId())
+ && execution.getArtifactId().equals(other.execution.getArtifactId())
+ && execution.getVersion().equals(other.execution.getVersion())
+ && execution.getGoal().equals(other.execution.getGoal());
+ }
+ }
+
+ public List<AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade facade, IProgressMonitor monitor)
+ throws CoreException {
+
+ List<AbstractProjectConfigurator> configurators = super.getProjectConfigurators(facade, monitor);
+
+ Map<MojoExecutionKey, AbstractProjectConfigurator> executions = new LinkedHashMap<MojoExecutionKey, AbstractProjectConfigurator>();
+
+ MavenExecutionPlan executionPlan = facade.getExecutionPlan(monitor);
+ execution: for(MojoExecution execution : executionPlan.getMojoExecutions()) {
+ MojoExecutionKey key = new MojoExecutionKey(execution);
+ for(AbstractProjectConfigurator configurator : configurators) {
+ if(configurator.isSupportedExecution(execution)) {
+ executions.put(key, configurator);
+ continue execution;
+ }
+ }
+ executions.put(key, null);
+ }
+
+ for(Map.Entry<MojoExecutionKey, AbstractProjectConfigurator> entry : executions.entrySet()) {
+ MojoExecutionKey key = entry.getKey();
+ if(entry.getValue() == null) {
+ // make sure to reuse the same instance of project configurator
+ for(AbstractProjectConfigurator configurator : executions.values()) {
+ if(configurator != null && configurator.isSupportedExecution(key.getMojoExecution())) {
+ entry.setValue(configurator);
+ break;
+ }
+ }
+ }
+ if(entry.getValue() == null) {
+ AbstractProjectConfigurator configurator = LifecycleMappingFactory.createProjectConfiguratorFor(key
+ .getMojoExecution());
+ if(configurator != null) {
+ entry.setValue(configurator);
+ }
+ }
+ }
+
+ ArrayList<AbstractProjectConfigurator> result = new ArrayList<AbstractProjectConfigurator>();
+
+ for(AbstractProjectConfigurator configurator : executions.values()) {
+ if(configurator != null && !result.contains(configurator)) {
+ result.add(configurator);
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ILifecycleMapping.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ILifecycleMapping.java
new file mode 100644
index 00000000..80ece0df
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ILifecycleMapping.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.apache.maven.plugin.MojoExecution;
+
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+
+/**
+ * LifecycleMapping
+ *
+ * @author igor
+ */
+public interface ILifecycleMapping {
+ String getId();
+
+ String getName();
+
+ /**
+ * Configure Eclipse workspace project according to Maven build project configuration.
+ */
+ void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Undo any Eclipse project configuration done during previous call(s) to {@link #configure(ProjectConfigurationRequest, IProgressMonitor)}
+ */
+ void unconfigure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException;
+
+ /**
+ * Returns list of AbstractBuildParticipant that need to be executed during
+ * Eclipse workspace build. List can be empty but cannot be null.
+ */
+ List<AbstractBuildParticipant> getBuildParticipants(IMavenProjectFacade facade, IProgressMonitor monitor) throws CoreException;
+
+ /** TODO does this belong here? */
+ List<AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade facade, IProgressMonitor monitor) throws CoreException;
+
+ List<MojoExecution> getNotCoveredMojoExecutions(IMavenProjectFacade mavenProjectFacade, IProgressMonitor monitor)
+ throws CoreException;
+
+ boolean isInterestingPhase(String phase);
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenProjectConfigurator.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenProjectConfigurator.java
new file mode 100644
index 00000000..204fcb98
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenProjectConfigurator.java
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+
+import org.apache.maven.execution.MavenExecutionRequest;
+import org.apache.maven.model.Build;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.project.MavenProject;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.core.MavenLogger;
+import org.eclipse.m2e.core.embedder.IMaven;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+
+
+/**
+ * Generic project configurator that using Maven plugins
+ *
+ * @author Eugene Kuleshov
+ * @see AbstractProjectConfigurator
+ */
+public class MavenProjectConfigurator extends AbstractProjectConfigurator {
+
+ String pluginKey;
+
+ List<String> goals;
+
+ public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) {
+ if(pluginKey == null || goals == null) {
+ return;
+ }
+
+ MavenProject mavenProject = request.getMavenProject();
+ Build build = mavenProject.getBuild();
+ if(build != null) {
+ Map<String, Plugin> pluginMap = build.getPluginsAsMap();
+ Plugin mavenPlugin = pluginMap.get(pluginKey);
+ if(mavenPlugin != null) {
+ IFile pomFile = request.getPom();
+ ResolverConfiguration resolverConfiguration = request.getResolverConfiguration();
+ // MavenPlugin plugin = MavenPlugin.getDefault();
+ try {
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+ MavenExecutionRequest executionRequest = projectManager.createExecutionRequest(pomFile, resolverConfiguration, monitor);
+ executionRequest.setGoals(goals);
+ maven.execute(executionRequest, monitor);
+ } catch(Exception ex) {
+ String msg = ex.getMessage() == null ? ex.toString() : ex.getMessage();
+ console.logError(msg);
+ MavenLogger.log(msg, ex);
+ }
+
+ try {
+ request.getProject().refreshLocal(IResource.DEPTH_INFINITE, monitor);
+ } catch(CoreException ex) {
+ IStatus status = ex.getStatus();
+ String msg = status.getMessage();
+ Throwable t = status.getException();
+ console.logError(msg + (t == null ? "" : "; " + t.toString())); //$NON-NLS-1$ //$NON-NLS-2$
+ MavenLogger.log(ex);
+ }
+ }
+ }
+ }
+
+ public String getPluginKey() {
+ return this.pluginKey;
+ }
+
+ public List<String> getGoals() {
+ return this.goals;
+ }
+
+ // IExecutableExtension
+
+ @Override
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) {
+ super.setInitializationData(config, propertyName, data);
+
+ Pattern pattern = Pattern.compile("(.+?)\\:(.+?)\\|(.+)"); //$NON-NLS-1$
+ String params = (String) data;
+ if(params != null) {
+ Matcher matcher = pattern.matcher(params);
+ if(matcher.find() && matcher.groupCount() == 3) {
+ pluginKey = matcher.group(1) + ":" + matcher.group(2); //$NON-NLS-1$
+ goals = Arrays.asList(matcher.group(3).split("\\|")); //$NON-NLS-1$
+ return;
+ }
+ }
+ MavenLogger.log("Unable to parse configuration for project configurator " + getId() + "; " + data, null); //$NON-NLS-2$
+ }
+
+ @Override
+ public String toString() {
+ return super.toString() + " " + pluginKey + goals; //$NON-NLS-1$
+ }
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenResourcesProjectConfigurator.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenResourcesProjectConfigurator.java
new file mode 100644
index 00000000..87c013fe
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MavenResourcesProjectConfigurator.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Sonatype, Inc.
+ * 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.m2e.core.project.configurator;
+
+import org.eclipse.m2e.core.internal.project.MojoExecutionProjectConfigurator;
+
+/**
+ * Project configurator for maven-resources-plugin
+ */
+public class MavenResourcesProjectConfigurator extends MojoExecutionProjectConfigurator {
+ public MavenResourcesProjectConfigurator() {
+ super(true /*runOnIncremental*/);
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MojoExecutionBuildParticipant.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MojoExecutionBuildParticipant.java
new file mode 100644
index 00000000..f0852f35
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/MojoExecutionBuildParticipant.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.Set;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IncrementalProjectBuilder;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.apache.maven.plugin.MojoExecution;
+
+import org.eclipse.m2e.core.MavenPlugin;
+import org.eclipse.m2e.core.embedder.IMaven;
+
+
+/**
+ * MojoExecutionBuildParticipant
+ *
+ * @author igor
+ */
+public class MojoExecutionBuildParticipant extends AbstractBuildParticipant {
+
+ private final MojoExecution execution;
+ private final boolean runOnIncremental;
+
+ public MojoExecutionBuildParticipant(MojoExecution execution, boolean runOnIncremental) {
+ this.execution = execution;
+ this.runOnIncremental = runOnIncremental;
+ }
+
+ public Set<IProject> build(int kind, IProgressMonitor monitor) throws Exception {
+ if(appliesToBuildKind(kind)) {
+ IMaven maven = MavenPlugin.getDefault().getMaven();
+
+ maven.execute(getSession(), getMojoExecution(), monitor);
+ }
+ return null;
+ }
+
+ public boolean appliesToBuildKind(int kind) {
+ if(IncrementalProjectBuilder.FULL_BUILD == kind || IncrementalProjectBuilder.CLEAN_BUILD == kind) {
+ return true;
+ }
+ return runOnIncremental;
+ }
+
+ public MojoExecution getMojoExecution() {
+ return execution;
+ }
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/NoopLifecycleMapping.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/NoopLifecycleMapping.java
new file mode 100644
index 00000000..9273aa71
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/NoopLifecycleMapping.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+
+/**
+ * NoopLifecycleMapping
+ *
+ * @author igor
+ */
+public class NoopLifecycleMapping extends AbstractLifecycleMapping {
+
+ public void configure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
+ // do nothing
+ }
+
+ public List<AbstractBuildParticipant> getBuildParticipants(IMavenProjectFacade facade, IProgressMonitor monitor)
+ throws CoreException {
+ return new ArrayList<AbstractBuildParticipant>();
+ }
+
+ public List<AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade facade, IProgressMonitor monitor)
+ throws CoreException {
+ return new ArrayList<AbstractProjectConfigurator>();
+ }
+
+ public void unconfigure(ProjectConfigurationRequest request, IProgressMonitor monitor) throws CoreException {
+ // do nothing
+ }
+
+ public List<String> getPotentialMojoExecutionsForBuildKind(IMavenProjectFacade facade, int kind, IProgressMonitor progressMonitor) {
+ return Collections.emptyList();
+ }
+
+ public boolean isInterestingPhase(String phase) {
+ return false;
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/PluginExecutionFilter.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/PluginExecutionFilter.java
new file mode 100644
index 00000000..18f8b260
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/PluginExecutionFilter.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.plugin.MojoExecution;
+
+
+public final class PluginExecutionFilter {
+
+ private final String groupId;
+
+ private final String artifactId;
+
+ private final String versionRange;
+
+ private final Set<String> goals;
+
+ private final VersionRange parsedVersionRange;
+
+ public PluginExecutionFilter(String groupId, String artifactId, String versionRange, String goals) {
+ this.groupId = groupId;
+ this.artifactId = artifactId;
+ this.versionRange = versionRange;
+ this.goals = new LinkedHashSet<String>(Arrays.asList(goals.split(","))); //$NON-NLS-1$;
+ try {
+ this.parsedVersionRange = VersionRange.createFromVersionSpec(versionRange);
+ } catch(InvalidVersionSpecificationException e) {
+ throw new IllegalArgumentException("Can't parse version range", e);
+ }
+ }
+
+ public String getVersionRange() {
+ return this.versionRange;
+ }
+
+ public String getGroupId() {
+ return this.groupId;
+ }
+
+ public String getArtifactId() {
+ return this.artifactId;
+ }
+
+ public Set<String> getGoals() {
+ return this.goals;
+ }
+
+ /**
+ * @return true if mojoExecution matches this key or false otherwise
+ */
+ public boolean match(MojoExecution mojoExecution) {
+ if(!groupId.equals(mojoExecution.getGroupId()) || !artifactId.equals(mojoExecution.getArtifactId())) {
+ return false;
+ }
+
+ DefaultArtifactVersion version = new DefaultArtifactVersion(mojoExecution.getVersion());
+
+ if(!parsedVersionRange.containsVersion(version)) {
+ return false;
+ }
+
+ return goals.contains(mojoExecution.getGoal());
+ }
+
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ProjectConfigurationRequest.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ProjectConfigurationRequest.java
new file mode 100644
index 00000000..f6f08f49
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/project/configurator/ProjectConfigurationRequest.java
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2008-2010 Sonatype, Inc.
+ * 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:
+ * Sonatype, Inc. - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.project.configurator;
+
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.IProject;
+
+import org.apache.maven.execution.MavenSession;
+import org.apache.maven.project.MavenProject;
+
+import org.eclipse.m2e.core.project.IMavenProjectFacade;
+import org.eclipse.m2e.core.project.ResolverConfiguration;
+
+/**
+ * ProjectConfigurationRequest
+ *
+ * @author igor
+ */
+public class ProjectConfigurationRequest {
+ private final boolean updateSources;
+ private final IMavenProjectFacade facade;
+ private final MavenProject mavenProject;
+ private final MavenSession mavenSession;
+
+ public ProjectConfigurationRequest(IMavenProjectFacade facade, MavenProject mavenProject, MavenSession mavenSession, boolean updateSources) {
+ this.facade = facade;
+ this.mavenSession = mavenSession;
+ this.updateSources = updateSources;
+ this.mavenProject = mavenProject;
+ }
+
+ public IProject getProject() {
+ return facade.getProject();
+ }
+
+ public ResolverConfiguration getResolverConfiguration() {
+ return facade.getResolverConfiguration();
+ }
+
+ public boolean isProjectConfigure() {
+ return updateSources;
+ }
+
+ public boolean isProjectImport() {
+ return !updateSources;
+ }
+
+ public MavenProject getMavenProject() {
+ return mavenProject;
+ }
+
+ public MavenSession getMavenSession() {
+ return mavenSession;
+ }
+
+ public IFile getPom() {
+ return facade.getPom();
+ }
+
+ public IMavenProjectFacade getMavenProjectFacade() {
+ return facade;
+ }
+}

Back to the top