blob: 416decc8ebf8c9593bf07d238347fa08572d4636 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008-2015 Sonatype, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Sonatype, Inc. - initial API and implementation
* Andrew Eisenberg - Work on Bug 350414
* Fred Bricon (Red Hat) - project configurator sort (Bug #449495)
* Anton Tanasenko - Refactor marker resolutions and quick fixes (Bug #484359)
*******************************************************************************/
package org.eclipse.m2e.core.internal.lifecyclemapping;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.spi.RegistryContributor;
import org.eclipse.osgi.util.NLS;
import org.codehaus.plexus.util.IOUtil;
import org.codehaus.plexus.util.dag.CycleDetectedException;
import org.codehaus.plexus.util.xml.Xpp3Dom;
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.versioning.ComparableVersion;
import org.apache.maven.model.Build;
import org.apache.maven.model.BuildBase;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.Profile;
import org.apache.maven.plugin.MojoExecution;
import org.apache.maven.project.MavenProject;
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.embedder.IMaven;
import org.eclipse.m2e.core.internal.IMavenConstants;
import org.eclipse.m2e.core.internal.MavenPluginActivator;
import org.eclipse.m2e.core.internal.Messages;
import org.eclipse.m2e.core.internal.embedder.MavenImpl;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.LifecycleMappingMetadata;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.LifecycleMappingMetadataSource;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.PluginExecutionFilter;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.PluginExecutionMetadata;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.io.xpp3.LifecycleMappingMetadataSourceXpp3Reader;
import org.eclipse.m2e.core.internal.lifecyclemapping.model.io.xpp3.LifecycleMappingMetadataSourceXpp3Writer;
import org.eclipse.m2e.core.internal.markers.IMavenMarkerManager;
import org.eclipse.m2e.core.internal.markers.MavenProblemInfo;
import org.eclipse.m2e.core.internal.markers.SourceLocation;
import org.eclipse.m2e.core.internal.markers.SourceLocationHelper;
import org.eclipse.m2e.core.internal.preferences.ProblemSeverity;
import org.eclipse.m2e.core.internal.project.registry.EclipseWorkspaceArtifactRepository;
import org.eclipse.m2e.core.internal.project.registry.MavenProjectFacade;
import org.eclipse.m2e.core.lifecyclemapping.model.IPluginExecutionMetadata;
import org.eclipse.m2e.core.lifecyclemapping.model.PluginExecutionAction;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.core.project.configurator.AbstractCustomizableLifecycleMapping;
import org.eclipse.m2e.core.project.configurator.AbstractLifecycleMapping;
import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
import org.eclipse.m2e.core.project.configurator.ILifecycleMapping;
import org.eclipse.m2e.core.project.configurator.ILifecycleMappingConfiguration;
import org.eclipse.m2e.core.project.configurator.MojoExecutionBuildParticipant;
import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
import org.eclipse.m2e.core.project.configurator.NoopLifecycleMapping;
/**
* @author igor
*/
public class LifecycleMappingFactory {
private static final Logger log = LoggerFactory.getLogger(LifecycleMappingFactory.class);
public static final String LIFECYCLE_MAPPING_PLUGIN_GROUPID = "org.eclipse.m2e"; //$NON-NLS-1$
public static final String LIFECYCLE_MAPPING_PLUGIN_ARTIFACTID = "lifecycle-mapping"; //$NON-NLS-1$
public static final String LIFECYCLE_MAPPING_PLUGIN_VERSION = "1.0.0"; //$NON-NLS-1$
private static final String LIFECYCLE_MAPPING_PLUGIN_KEY = LIFECYCLE_MAPPING_PLUGIN_GROUPID + ":" //$NON-NLS-1$
+ LIFECYCLE_MAPPING_PLUGIN_ARTIFACTID;
private static final String DEFAULT_LIFECYCLE_METADATA_BUNDLE = "org.eclipse.m2e.lifecyclemapping.defaults";
public static final String LIFECYCLE_MAPPING_METADATA_SOURCE_NAME = "lifecycle-mapping-metadata.xml"; //$NON-NLS-1$
private static final String LIFECYCLE_MAPPING_METADATA_SOURCE_PATH = '/' + LIFECYCLE_MAPPING_METADATA_SOURCE_NAME;
private static final String LIFECYCLE_MAPPING_METADATA_EMBEDDED_SOURCE_PATH = "META-INF/m2e/" //$NON-NLS-1$
+ LIFECYCLE_MAPPING_METADATA_SOURCE_NAME;
public static final String EXTENSION_LIFECYCLE_MAPPINGS = IMavenConstants.PLUGIN_ID + ".lifecycleMappings"; //$NON-NLS-1$
public static final String EXTENSION_PROJECT_CONFIGURATORS = IMavenConstants.PLUGIN_ID + ".projectConfigurators"; //$NON-NLS-1$
public static final String EXTENSION_LIFECYCLE_MAPPING_METADATA_SOURCE = IMavenConstants.PLUGIN_ID
+ ".lifecycleMappingMetadataSource"; //$NON-NLS-1$
private static final String ELEMENT_LIFECYCLE_MAPPING_METADATA = "lifecycleMappingMetadata"; //$NON-NLS-1$
private static final String ELEMENT_LIFECYCLE_MAPPING = "lifecycleMapping"; //$NON-NLS-1$
private static final String ELEMENT_SOURCES = "sources"; //$NON-NLS-1$
private static final String ELEMENT_SOURCE = "source"; //$NON-NLS-1$
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
private static final String ATTR_ID = "id"; //$NON-NLS-1$
private static final String ATTR_NAME = "name"; //$NON-NLS-1$
private static final String ELEMENT_CONFIGURATOR = "configurator"; //$NON-NLS-1$
private static final String ELEMENT_MESSAGE = "message"; //$NON-NLS-1$
static final String ELEMENT_RUN_ON_INCREMENTAL = "runOnIncremental";
static final String ELEMENT_RUN_ON_CONFIGURATION = "runOnConfiguration";
private static final String ATTR_GROUPID = "groupId";
private static final String ATTR_ARTIFACTID = "artifactId";
private static final String ATTR_VERSION = "version";
private static final String LIFECYCLE_MAPPING_METADATA_CLASSIFIER = "lifecycle-mapping-metadata";
private static List<LifecycleMappingMetadataSource> bundleMetadataSources = null;
/**
* Do not instantiate, use statically
*/
private LifecycleMappingFactory() {
}
public static LifecycleMappingResult calculateLifecycleMapping(MavenProject mavenProject,
List<MojoExecution> mojoExecutions, String lifecycleMappingId, IProgressMonitor monitor) {
long start = System.currentTimeMillis();
log.debug("Loading lifecycle mapping for {}.", mavenProject); //$NON-NLS-1$
LifecycleMappingResult result = new LifecycleMappingResult();
try {
if(lifecycleMappingId != null) {
instantiateLifecycleMapping(result, mavenProject, lifecycleMappingId);
}
calculateEffectiveLifecycleMappingMetadata(result, mavenProject, mojoExecutions, monitor);
if(result.getLifecycleMapping() == null) {
lifecycleMappingId = result.getLifecycleMappingId();
instantiateLifecycleMapping(result, mavenProject, lifecycleMappingId);
}
if(result.getLifecycleMapping() instanceof AbstractCustomizableLifecycleMapping) {
instantiateProjectConfigurators(mavenProject, result, result.getMojoExecutionMapping());
}
} catch(CoreException ex) {
log.error(ex.getMessage(), ex);
result.addProblem(new MavenProblemInfo(1, ex)); // XXX that looses most of useful info
} finally {
log.info("Using {} lifecycle mapping for {}.", result.getLifecycleMappingId(), mavenProject); //$NON-NLS-1$
log.debug("Loaded lifecycle mapping in {} ms for {}.", System.currentTimeMillis() - start, //$NON-NLS-1$
mavenProject);
}
return result;
}
public static void calculateEffectiveLifecycleMappingMetadata(LifecycleMappingResult result,
MavenProject mavenProject, List<MojoExecution> mojoExecutions, IProgressMonitor monitor) throws CoreException {
String packagingType = mavenProject.getPackaging();
if("pom".equals(packagingType)) { //$NON-NLS-1$
log.debug("Using NoopLifecycleMapping lifecycle mapping for {}.", mavenProject); //$NON-NLS-1$
LifecycleMappingMetadata lifecycleMappingMetadata = new LifecycleMappingMetadata();
lifecycleMappingMetadata.setLifecycleMappingId(NoopLifecycleMapping.LIFECYCLE_MAPPING_ID);
result.setLifecycleMappingMetadata(lifecycleMappingMetadata);
Map<MojoExecutionKey, List<IPluginExecutionMetadata>> executionMapping = new LinkedHashMap<>();
result.setMojoExecutionMapping(executionMapping);
return;
}
if(result.getLifecycleMapping() != null
&& !(result.getLifecycleMapping() instanceof AbstractCustomizableLifecycleMapping)) {
String lifecycleMappingId = result.getLifecycleMapping().getId();
log.debug("Using non-customizable lifecycle mapping {} for {}.", lifecycleMappingId, mavenProject); // $NON-NLS-1$
LifecycleMappingMetadata lifecycleMappingMetadata = new LifecycleMappingMetadata();
lifecycleMappingMetadata.setLifecycleMappingId(lifecycleMappingId);
result.setLifecycleMappingMetadata(lifecycleMappingMetadata);
Map<MojoExecutionKey, List<IPluginExecutionMetadata>> executionMapping = new LinkedHashMap<>();
result.setMojoExecutionMapping(executionMapping);
return;
}
List<MappingMetadataSource> metadataSources;
try {
metadataSources = getProjectMetadataSources(mavenProject, getBundleMetadataSources(), mojoExecutions, true,
monitor);
} catch(LifecycleMappingConfigurationException e) {
// could not read/parse/interpret mapping metadata configured in the pom or inherited from parent pom.
// record the problem and return
result.addProblem(new MavenProblemInfo(mavenProject, e));
return;
}
calculateEffectiveLifecycleMappingMetadata(result, metadataSources, mavenProject, mojoExecutions, true, monitor);
}
public static List<MappingMetadataSource> getProjectMetadataSources(MavenProject mavenProject,
List<LifecycleMappingMetadataSource> bundleMetadataSources, List<MojoExecution> mojoExecutions,
boolean includeDefault, IProgressMonitor monitor) throws CoreException, LifecycleMappingConfigurationException {
Map<String, List<MappingMetadataSource>> metadataSourcesMap = getProjectMetadataSourcesMap(mavenProject,
bundleMetadataSources, mojoExecutions, includeDefault, monitor);
return asList(metadataSourcesMap);
}
public static Map<String, List<MappingMetadataSource>> getProjectMetadataSourcesMap(MavenProject mavenProject,
List<LifecycleMappingMetadataSource> bundleMetadataSources, List<MojoExecution> mojoExecutions,
boolean includeDefault, IProgressMonitor monitor) throws CoreException, LifecycleMappingConfigurationException {
Map<String, List<MappingMetadataSource>> metadataSourcesMap = new HashMap<>();
// List order
// 1. preferences in project (*** not implemented yet)
// 2. preferences in ancestor project (*** not implemented yet)
// 3. this pom (annotated, embedded, referenced), parent (annotated, embedded, referenced), grand parent (embedded...
// 4. preferences in workspace
// 5. sources contributed by eclipse extensions
// 6. maven-plugin embedded metadata
// 7. default source, if present
// TODO validate metadata and replace invalid entries with error mapping
metadataSourcesMap.put("pomMappingMetadataSources", getPomMappingMetadataSources(mavenProject, monitor));
metadataSourcesMap.put("workspaceMetadataSources", //
Collections
.singletonList((MappingMetadataSource) new SimpleMappingMetadataSource(getWorkspaceMetadata(false))));
// TODO filter out invalid metadata from sources contributed by eclipse extensions and the default source
if(bundleMetadataSources != null) {
metadataSourcesMap.put("bundleMetadataSources",
Collections.singletonList((MappingMetadataSource) new SimpleMappingMetadataSource(bundleMetadataSources)));
}
List<MappingMetadataSource> metadataSources = new ArrayList<>();
for(LifecycleMappingMetadataSource source : getMavenPluginEmbeddedMetadataSources(mojoExecutions,
mavenProject.getPluginArtifactRepositories(), monitor)) {
metadataSources.add(new SimpleMappingMetadataSource(source));
}
metadataSourcesMap.put("mavenPluginEmbeddedMetadataSources", metadataSources);
if(includeDefault) {
LifecycleMappingMetadataSource defaultSource = getDefaultLifecycleMappingMetadataSource();
if(defaultSource != null) {
metadataSourcesMap.put("defaultLifecycleMappingMetadataSource",
Collections.singletonList((MappingMetadataSource) new SimpleMappingMetadataSource(defaultSource)));
}
}
return metadataSourcesMap;
}
public static void addLifecyclePluginExecution(LifecycleMappingMetadataSource mapping, String groupId,
String artifactId, String version, String[] goals, PluginExecutionAction action) {
PluginExecutionMetadata execution = getPluginExecutionMetadata(mapping, groupId, artifactId, version, action);
if(execution == null) {
execution = new PluginExecutionMetadata();
execution.setSource(mapping);
execution.setFilter(new PluginExecutionFilter(groupId, artifactId, version, new HashSet<String>()));
Xpp3Dom actionDom = new Xpp3Dom("action");
actionDom.addChild(new Xpp3Dom(action.toString()));
execution.setActionDom(actionDom);
mapping.addPluginExecution(execution);
}
for(String goal : goals) {
execution.getFilter().addGoal(goal);
}
}
private static PluginExecutionMetadata getPluginExecutionMetadata(LifecycleMappingMetadataSource mapping,
String groupId, String artifactId, String version, PluginExecutionAction action) {
for(PluginExecutionMetadata execution : mapping.getPluginExecutions()) {
PluginExecutionFilter filter = execution.getFilter();
if(eq(groupId, filter.getGroupId()) && eq(artifactId, filter.getArtifactId())
&& eq(version, filter.getVersionRange()) && action == execution.getAction()) {
return execution;
}
}
return null;
}
public static List<MappingMetadataSource> asList(Map<String, List<MappingMetadataSource>> map) {
if(map == null || map.isEmpty()) {
return Collections.emptyList();
}
List<MappingMetadataSource> metadataSources = new ArrayList<>();
safeAddAll(map.get("pomMappingMetadataSources"), metadataSources);
safeAddAll(map.get("workspaceMetadataSources"), metadataSources);
safeAddAll(map.get("bundleMetadataSources"), metadataSources);
safeAddAll(map.get("mavenPluginEmbeddedMetadataSources"), metadataSources);
safeAddAll(map.get("defaultLifecycleMappingMetadataSource"), metadataSources);
return metadataSources;
}
private static <T> void safeAddAll(List<T> source, List<T> dest) {
if(source != null && dest != null)
dest.addAll(source);
}
private static List<LifecycleMappingMetadataSource> getMavenPluginEmbeddedMetadataSources(
List<MojoExecution> mojoExecutions, List<ArtifactRepository> remoteRepositories, IProgressMonitor monitor) {
if(mojoExecutions == null || mojoExecutions.isEmpty()) {
// TODO need to understand under what conditions execution plan is null here
return Collections.emptyList();
}
Map<File, LifecycleMappingMetadataSource> result = new LinkedHashMap<>();
MavenImpl maven = (MavenImpl) MavenPlugin.getMaven();
for(MojoExecution execution : mojoExecutions) {
Artifact artifact;
// 422135 disable workspace resolution for plugin artifacts
boolean disabled = EclipseWorkspaceArtifactRepository.isDisabled();
EclipseWorkspaceArtifactRepository.setDisabled(true);
try {
artifact = maven.resolvePluginArtifact(execution.getPlugin(), remoteRepositories, monitor);
} catch(CoreException e) {
// skip this plugin, it won't run anyways
continue;
} finally {
EclipseWorkspaceArtifactRepository.setDisabled(disabled);
}
File file = artifact.getFile();
if(file == null || result.containsKey(file) || !file.canRead()) {
continue;
}
LifecycleMappingMetadataSource metadata = readMavenPluginEmbeddedMetadata(artifact);
if(metadata != null) {
// enforce embedded metadata only contains mappings for this plugin and nothing else
for(LifecycleMappingMetadata lifecycleMetadta : metadata.getLifecycleMappings()) {
enforcePluginMapping(artifact, lifecycleMetadta.getPluginExecutions());
}
enforcePluginMapping(artifact, metadata.getPluginExecutions());
result.put(file, metadata);
}
}
return new ArrayList<>(result.values());
}
private static void enforcePluginMapping(Artifact artifact, List<PluginExecutionMetadata> executions) {
if(executions == null) {
return;
}
ListIterator<PluginExecutionMetadata> iter = executions.listIterator();
while(iter.hasNext()) {
PluginExecutionMetadata execution = iter.next();
PluginExecutionFilter filter = execution.getFilter();
if(!isNullOrEqual(artifact.getGroupId(), filter.getGroupId())
|| !isNullOrEqual(artifact.getArtifactId(), filter.getArtifactId())
|| !isNullOrEqual(artifact.getBaseVersion(), filter.getVersionRange())) {
String mappingGAV = filter.getGroupId() + ":" + filter.getArtifactId() + ":" + filter.getVersionRange();
String pluginGAV = artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getBaseVersion();
log.warn(
"Ignoring plugin execution mapping {} defined in maven plugin {} because it matches other plugins and/or plugin versions",
mappingGAV, pluginGAV);
iter.remove();
} else {
// filter may have empty GAV elements
filter.setGroupId(artifact.getGroupId());
filter.setArtifactId(artifact.getArtifactId());
filter.setVersionRange(artifact.getBaseVersion());
}
}
}
private static boolean isNullOrEqual(String expected, String actual) {
return actual == null || actual.equals(expected);
}
private static LifecycleMappingMetadataSource readMavenPluginEmbeddedMetadata(Artifact artifact) {
File file = artifact.getFile();
LifecycleMappingMetadataSource metadata = null;
try {
if(file.isFile()) {
JarFile jar = new JarFile(file);
try {
ZipEntry entry = jar.getEntry(LIFECYCLE_MAPPING_METADATA_EMBEDDED_SOURCE_PATH);
if(entry == null) {
return null;
}
InputStream is = jar.getInputStream(entry);
metadata = createLifecycleMappingMetadataSource(is);
} finally {
try {
jar.close();
} catch(IOException e) {
// too bad
}
}
} else if(file.isDirectory()) {
try {
InputStream is = new BufferedInputStream(
new FileInputStream(new File(file, LIFECYCLE_MAPPING_METADATA_EMBEDDED_SOURCE_PATH)));
try {
metadata = createLifecycleMappingMetadataSource(is);
} finally {
IOUtil.close(is);
}
} catch(FileNotFoundException e) {
// expected and tolerated
}
}
} catch(XmlPullParserException | IOException e) {
throw new LifecycleMappingConfigurationException(
"Cannot read lifecycle mapping metadata for artifact " + artifact, e);
}
if(metadata != null) {
metadata.setSource(artifact);
}
return metadata;
}
private static File getWorkspaceMetadataFile() {
return new File(MavenPlugin.getMavenConfiguration().getWorkspaceLifecycleMappingMetadataFile());
}
private static LifecycleMappingMetadataSource workspaceMetadataSource;
public static synchronized LifecycleMappingMetadataSource getWorkspaceMetadata(boolean reload) {
if(workspaceMetadataSource == null || reload) {
File mappingFile = getWorkspaceMetadataFile();
try {
InputStream is = new BufferedInputStream(new FileInputStream(mappingFile));
try {
workspaceMetadataSource = createLifecycleMappingMetadataSource(is);
} finally {
IOUtil.close(is);
}
} catch(FileNotFoundException e) {
// this is expected, ignore
} catch(IOException | XmlPullParserException ex) {
log.error(ex.getMessage(), ex);
}
if(workspaceMetadataSource == null) {
workspaceMetadataSource = new LifecycleMappingMetadataSource();
}
workspaceMetadataSource.setSource("workspace");
}
return workspaceMetadataSource;
}
public static synchronized void writeWorkspaceMetadata(LifecycleMappingMetadataSource metadata) {
LifecycleMappingMetadataSourceXpp3Writer writer = new LifecycleMappingMetadataSourceXpp3Writer();
File mappingFile = getWorkspaceMetadataFile();
mappingFile.getParentFile().mkdirs();
try (
OutputStream os = new BufferedOutputStream(new FileOutputStream(mappingFile));
) {
writer.write(os, metadata);
} catch(IOException ex) {
log.error(ex.getMessage(), ex);
}
workspaceMetadataSource = metadata;
}
public static void calculateEffectiveLifecycleMappingMetadata(final LifecycleMappingResult result,
final List<MappingMetadataSource> metadataSources, final MavenProject mavenProject,
final List<MojoExecution> mojoExecutions, final boolean applyDefaultStrategy, final IProgressMonitor monitor) {
calculateEffectiveLifecycleMappingMetadata0(result, metadataSources, mavenProject, mojoExecutions,
applyDefaultStrategy, monitor);
}
/*package*/static void calculateEffectiveLifecycleMappingMetadata0(LifecycleMappingResult result,
List<MappingMetadataSource> metadataSources, MavenProject mavenProject, List<MojoExecution> mojoExecutions,
boolean applyDefaultStrategy, IProgressMonitor monitor) {
//
// PHASE 1. Look for lifecycle mapping for packaging type
//
LifecycleMappingMetadata lifecycleMappingMetadata = null;
MappingMetadataSource originalMetadataSource = null;
for(int i = 0; i < metadataSources.size(); i++ ) {
MappingMetadataSource source = metadataSources.get(i);
try {
lifecycleMappingMetadata = source.getLifecycleMappingMetadata(mavenProject.getPackaging());
if(lifecycleMappingMetadata != null) {
originalMetadataSource = new SimpleMappingMetadataSource(lifecycleMappingMetadata);
metadataSources.add(i, originalMetadataSource);
break;
}
} catch(DuplicateMappingException e) {
log.error("Duplicate lifecycle mapping metadata for {}.", mavenProject);
result.addProblem(new MavenProblemInfo(1, NLS.bind(Messages.LifecycleDuplicate, mavenProject.getPackaging())));
return; // fatal error
}
}
if(lifecycleMappingMetadata == null && applyDefaultStrategy) {
lifecycleMappingMetadata = new LifecycleMappingMetadata();
lifecycleMappingMetadata.setLifecycleMappingId("DEFAULT"); // TODO proper constant
lifecycleMappingMetadata.setPackagingType(mavenProject.getPackaging());
}
// TODO if lifecycleMappingMetadata.lifecycleMappingId==null, convert to error lifecycle mapping metadata
result.setLifecycleMappingMetadata(lifecycleMappingMetadata);
//
// PHASE 2. Bind project configurators to mojo executions.
//
Map<MojoExecutionKey, List<IPluginExecutionMetadata>> executionMapping = new LinkedHashMap<>();
if(mojoExecutions != null && !mojoExecutions.isEmpty()) {
Map<String, IConfigurationElement> elements = getProjectConfiguratorExtensions();
for(MojoExecution execution : mojoExecutions) {
MojoExecutionKey executionKey = new MojoExecutionKey(execution);
Map<String, PluginExecutionMetadata> configuratorMetadataMap = new HashMap<>();
PluginExecutionMetadata primaryMetadata = null;
Map<MappingMetadataSource, List<PluginExecutionMetadata>> metadatasPerSource = new LinkedHashMap<>();
// collect all metadatasPerSource and extract all configurator execution metadatas
for(MappingMetadataSource source : metadataSources) {
try {
List<PluginExecutionMetadata> metadatas = applyParametersFilter(
source.getPluginExecutionMetadata(executionKey), mavenProject, execution, monitor);
metadatasPerSource.put(source, metadatas);
for(PluginExecutionMetadata executionMetadata : metadatas) {
if(isConfigurator(executionMetadata)) {
String id = getProjectConfiguratorId(executionMetadata);
configuratorMetadataMap.put(id, executionMetadata);
}
}
} catch(CoreException e) {
SourceLocation location = SourceLocationHelper.findLocation(mavenProject, executionKey);
result.addProblem(new MavenProblemInfo(location, e));
metadatasPerSource.put(source, Collections.<PluginExecutionMetadata> emptyList());
}
}
//Sort configurator execution metadatas
ProjectConfigurationElementSorter sorter = null;
try {
sorter = new ProjectConfigurationElementSorter(configuratorMetadataMap.keySet(), elements);
} catch(CycleDetectedException ex) {
log.error(ex.getMessage(), ex);
result.addProblem(new MavenProblemInfo(1,
NLS.bind("Cyclic dependency detected between project configurators for {0}", mavenProject.toString())));
return;// fatal error
}
//find primary mapping across different sources
try {
for(Map.Entry<MappingMetadataSource, List<PluginExecutionMetadata>> entry : metadatasPerSource.entrySet()) {
for(PluginExecutionMetadata executionMetadata : entry.getValue()) {
if(isPrimaryMapping(executionMetadata, sorter)) {
if(primaryMetadata != null) {
primaryMetadata = null;
throw new DuplicateMappingException();
}
primaryMetadata = executionMetadata;
}
}
if(primaryMetadata != null) {
break;
}
}
} catch(DuplicateMappingException e) {
log.debug("Duplicate plugin execution mapping metadata for {}.", executionKey);
result.addProblem(
new MavenProblemInfo(1, NLS.bind(Messages.PluginExecutionMappingDuplicate, executionKey.toString())));
}
if(primaryMetadata != null && !isValidPluginExecutionMetadata(primaryMetadata)) {
log.debug("Invalid plugin execution mapping metadata for {}.", executionKey);
result.addProblem(
new MavenProblemInfo(1, NLS.bind(Messages.PluginExecutionMappingInvalid, executionKey.toString())));
primaryMetadata = null;
}
//add secondary configurators in order
List<IPluginExecutionMetadata> executionMetadatas = new ArrayList<>();
if(primaryMetadata != null) {
executionMetadatas.add(primaryMetadata);
if(isConfigurator(primaryMetadata)) {
String primaryConfiguratorId = getProjectConfiguratorId(primaryMetadata);
List<String> secondaryConfiguratorIds = sorter.getSecondaryConfigurators(primaryConfiguratorId);
for(String id : secondaryConfiguratorIds) {
IPluginExecutionMetadata metadata = configuratorMetadataMap.get(id);
if(metadata == null) {
log.debug("Invalid secondary lifecycle mapping metadata {} for {}.", id, executionKey);
} else {
executionMetadatas.add(metadata);
}
}
}
}
// TODO valid executionMetadatas and convert to error mapping invalid entries.
executionMapping.put(executionKey, executionMetadatas);
}
} else {
log.debug("Execution plan is null, could not calculate mojo execution mapping for {}.", mavenProject);
}
result.setMojoExecutionMapping(executionMapping);
}
private static List<PluginExecutionMetadata> applyParametersFilter(List<PluginExecutionMetadata> metadatas,
MavenProject mavenProject, MojoExecution execution, IProgressMonitor monitor) throws CoreException {
IMaven maven = MavenPlugin.getMaven();
List<PluginExecutionMetadata> result = new ArrayList<>();
all_metadatas: for(PluginExecutionMetadata metadata : metadatas) {
@SuppressWarnings("unchecked")
Map<String, String> parameters = metadata.getFilter().getParameters();
if(!parameters.isEmpty()) {
for(Entry<String, String> entry : parameters.entrySet()) {
MojoExecution setupExecution = maven.setupMojoExecution(mavenProject, execution, monitor);
if(!eq(entry.getValue(),
maven.getMojoParameterValue(mavenProject, setupExecution, entry.getKey(), String.class, monitor))) {
continue all_metadatas;
}
}
}
result.add(metadata);
}
return result;
}
private static boolean isValidPluginExecutionMetadata(PluginExecutionMetadata metadata) {
switch(metadata.getAction()) {
case error:
case execute:
case ignore:
return true;
case configurator:
return isConfigurator(metadata);
}
return false;
}
private static boolean isConfigurator(PluginExecutionMetadata metadata) {
if(PluginExecutionAction.configurator == metadata.getAction()) {
try {
getProjectConfiguratorId(metadata);
return true;
} catch(LifecycleMappingConfigurationException e) {
// fall through
}
}
return false;
}
public static void instantiateLifecycleMapping(LifecycleMappingResult result, MavenProject mavenProject,
String lifecycleMappingId) {
// validate lifecycle mapping id and bail if it's invalid
AbstractLifecycleMapping lifecycleMapping = null;
if(lifecycleMappingId != null) {
lifecycleMapping = getLifecycleMapping(lifecycleMappingId);
if(lifecycleMapping == null) {
SourceLocation markerLocation = SourceLocationHelper.findPackagingLocation(mavenProject);
result.addProblem(new MissingLifecycleExtensionPoint(lifecycleMappingId, markerLocation));
}
}
result.setLifecycleMapping(lifecycleMapping);
}
public static void instantiateProjectConfigurators(MavenProject mavenProject, LifecycleMappingResult result,
Map<MojoExecutionKey, List<IPluginExecutionMetadata>> map) {
if(map == null) {
Map<String, AbstractProjectConfigurator> configurators = Collections.emptyMap();
result.setProjectConfigurators(configurators);
return;
}
ProblemSeverity notCoveredMojoExecutionSeverity = ProblemSeverity
.get(MavenPlugin.getMavenConfiguration().getNotCoveredMojoExecutionSeverity());
boolean reportNotCoveredMojoExecutionProblems = !ProblemSeverity.ignore.equals(notCoveredMojoExecutionSeverity);
Map<String, AbstractProjectConfigurator> configurators = new LinkedHashMap<>();
for(Map.Entry<MojoExecutionKey, List<IPluginExecutionMetadata>> entry : map.entrySet()) {
MojoExecutionKey executionKey = entry.getKey();
List<IPluginExecutionMetadata> executionMetadatas = entry.getValue();
if(executionMetadatas == null || executionMetadatas.isEmpty()) {
if(reportNotCoveredMojoExecutionProblems && isInterestingPhase(executionKey.getLifecyclePhase())) {
SourceLocation markerLocation = SourceLocationHelper.findLocation(mavenProject, executionKey);
result.addProblem(
new NotCoveredMojoExecution(executionKey, notCoveredMojoExecutionSeverity.getSeverity(), markerLocation));
}
continue;
}
for(IPluginExecutionMetadata metadata : executionMetadatas) {
String message = LifecycleMappingFactory.getActionMessage(metadata);
switch(metadata.getAction()) {
case error: {
if(message == null) {
message = NLS.bind(Messages.LifecycleConfigurationPluginExecutionErrorMessage, executionKey.toString());
}
SourceLocation markerLocation = SourceLocationHelper.findLocation(mavenProject, executionKey);
result.addProblem(new ActionMessageProblemInfo(message, IMarker.SEVERITY_ERROR, executionKey,
markerLocation, isPomMapping(metadata)));
break;
}
case execute:
if(message != null) {
SourceLocation markerLocation = SourceLocationHelper.findLocation(mavenProject, executionKey);
result.addProblem(new ActionMessageProblemInfo(message, IMarker.SEVERITY_WARNING, executionKey,
markerLocation, isPomMapping(metadata)));
}
break;
case configurator:
String configuratorId = LifecycleMappingFactory.getProjectConfiguratorId(metadata);
try {
if(!configurators.containsKey(configuratorId)) {
configurators.put(configuratorId, LifecycleMappingFactory.createProjectConfigurator(metadata));
}
} catch(LifecycleMappingConfigurationException e) {
log.debug("Could not instantiate project configurator {}.", configuratorId, e);
if(reportNotCoveredMojoExecutionProblems) {
SourceLocation markerLocation = SourceLocationHelper.findLocation(mavenProject, executionKey);
result.addProblem(new MissingConfiguratorProblemInfo(configuratorId, executionKey,
notCoveredMojoExecutionSeverity.getSeverity(), markerLocation));
}
}
break;
case ignore:
if(message != null) {
SourceLocation markerLocation = SourceLocationHelper.findLocation(mavenProject, executionKey);
result.addProblem(new ActionMessageProblemInfo(message, IMarker.SEVERITY_WARNING, executionKey,
markerLocation, isPomMapping(metadata)));
}
break;
default:
// TODO invalid metadata
}
}
}
result.setProjectConfigurators(configurators);
}
private static boolean isPomMapping(IPluginExecutionMetadata metadata) {
LifecycleMappingMetadataSource source = ((PluginExecutionMetadata) metadata).getSource();
return source != null && source.getSource() instanceof MavenProject;
}
/**
* Returns lifecycle mapping metadata sources embedded or referenced by pom.xml in the following order
* <ol>
* <li>this pom.xml embedded</li>
* <li>this pom.xml referenced</li>
* <li>parent pom.xml embedded</li>
* <li>parent pom.xml referenced</li>
* <li>grand parent embedded</li>
* <li>and so on</li>
* </ol>
* Returns empty list if no metadata sources are embedded/referenced by pom.xml
*
* @throws CoreException if metadata sources cannot be resolved or read
*/
public static List<MappingMetadataSource> getPomMappingMetadataSources(MavenProject mavenProject,
IProgressMonitor monitor) throws CoreException {
IMaven maven = MavenPlugin.getMaven();
List<MappingMetadataSource> sources = new ArrayList<>();
HashSet<String> referenced = new LinkedHashSet<>();
MavenProject project = mavenProject;
do {
if(monitor.isCanceled()) {
break;
}
boolean detach = false;
AnnotationMappingMetadataSource annSource = AnnotationMappingMetadataSource.get(project);
if(annSource != null) {
detach = true;
sources.add(annSource);
}
LifecycleMappingMetadataSource embeddedSource = getEmbeddedMetadataSource(project);
if(embeddedSource != null) {
detach = true;
embeddedSource.setSource(project);
sources.add(new SimpleMappingMetadataSource(embeddedSource));
}
for(LifecycleMappingMetadataSource referencedSource : getReferencedMetadataSources(referenced, project,
monitor)) {
sources.add(new SimpleMappingMetadataSource(referencedSource));
}
if(detach) {
maven.detachFromSession(project); // don't cache maven session
}
// TODO ideally, we need to reuse the same parent MavenProject instance in all child modules
// each instance takes ~1M, so we can easily save 100M+ of heap for larger workspaces
project = maven.resolveParentProject(project, monitor);
} while(project != null);
return sources;
}
public static AbstractProjectConfigurator createProjectConfigurator(IPluginExecutionMetadata metadata) {
PluginExecutionAction pluginExecutionAction = metadata.getAction();
if(pluginExecutionAction != PluginExecutionAction.configurator) {
throw new IllegalArgumentException();
}
String configuratorId = getProjectConfiguratorId(metadata);
AbstractProjectConfigurator projectConfigurator = createProjectConfigurator(configuratorId);
if(projectConfigurator == null) {
String message = NLS.bind(Messages.ProjectConfiguratorNotAvailable, configuratorId);
throw new LifecycleMappingConfigurationException(message);
}
return projectConfigurator;
}
public static String getProjectConfiguratorId(IPluginExecutionMetadata metadata) {
Xpp3Dom configuration = ((PluginExecutionMetadata) metadata).getConfiguration();
Xpp3Dom child = configuration == null ? null : configuration.getChild(ATTR_ID);
if(child == null || child.getValue().trim().length() == 0) {
throw new LifecycleMappingConfigurationException("A configurator id must be specified");
}
return child.getValue();
}
public static String getActionMessage(IPluginExecutionMetadata metadata) {
Xpp3Dom configuration = ((PluginExecutionMetadata) metadata).getConfiguration();
Xpp3Dom child = configuration == null ? null : configuration.getChild(ELEMENT_MESSAGE);
if(child == null || child.getValue().trim().length() == 0) {
return null;
}
return child.getValue();
}
public static LifecycleMappingMetadataSource createLifecycleMappingMetadataSource(InputStream is)
throws IOException, XmlPullParserException {
LifecycleMappingMetadataSource metadataSource = new LifecycleMappingMetadataSourceXpp3Reader().read(is);
postCreateLifecycleMappingMetadataSource(metadataSource);
return metadataSource;
}
private static void postCreateLifecycleMappingMetadataSource(LifecycleMappingMetadataSource metadataSource) {
for(LifecycleMappingMetadata lifecycleMappingMetadata : metadataSource.getLifecycleMappings()) {
lifecycleMappingMetadata.setSource(metadataSource);
for(PluginExecutionMetadata executionMetadata : lifecycleMappingMetadata.getPluginExecutions()) {
executionMetadata.setSource(metadataSource);
}
}
for(PluginExecutionMetadata executionMetadata : metadataSource.getPluginExecutions()) {
executionMetadata.setSource(metadataSource);
}
}
private static AbstractLifecycleMapping createLifecycleMapping(IConfigurationElement element) {
String mappingId = null;
try {
AbstractLifecycleMapping mapping = (AbstractLifecycleMapping) element.createExecutableExtension(ATTR_CLASS);
mappingId = element.getAttribute(ATTR_ID);
mapping.setId(mappingId);
mapping.setName(element.getAttribute(ATTR_NAME));
return mapping;
} catch(CoreException ex) {
log.error(ex.getMessage(), ex);
}
return null;
}
public static MojoExecutionBuildParticipant createMojoExecutionBuildParicipant(MojoExecution mojoExecution,
IPluginExecutionMetadata executionMetadata) {
boolean runOnIncremental = false;
boolean runOnConfiguration = false;
Xpp3Dom child = ((PluginExecutionMetadata) executionMetadata).getConfiguration()
.getChild(ELEMENT_RUN_ON_INCREMENTAL);
if(child != null) {
runOnIncremental = Boolean.parseBoolean(child.getValue());
}
child = ((PluginExecutionMetadata) executionMetadata).getConfiguration().getChild(ELEMENT_RUN_ON_CONFIGURATION);
if(child != null) {
runOnConfiguration = Boolean.parseBoolean(child.getValue());
}
return new MojoExecutionBuildParticipant(mojoExecution, runOnIncremental, runOnConfiguration);
}
public static Map<String, IConfigurationElement> getLifecycleMappingExtensions() {
Map<String, IConfigurationElement> mappings = new HashMap<>(); // not ordered
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint configuratorsExtensionPoint = registry.getExtensionPoint(EXTENSION_LIFECYCLE_MAPPINGS);
if(configuratorsExtensionPoint != null) {
IExtension[] configuratorExtensions = configuratorsExtensionPoint.getExtensions();
for(IExtension extension : configuratorExtensions) {
IConfigurationElement[] elements = extension.getConfigurationElements();
for(IConfigurationElement element : elements) {
if(element.getName().equals(ELEMENT_LIFECYCLE_MAPPING)) {
mappings.put(element.getAttribute(ATTR_ID), element);
}
}
}
}
return mappings;
}
private static AbstractLifecycleMapping getLifecycleMapping(String mappingId) {
IConfigurationElement element = getLifecycleMappingExtensions().get(mappingId);
if(element != null && element.getName().equals(ELEMENT_LIFECYCLE_MAPPING)) {
if(mappingId.equals(element.getAttribute(ATTR_ID))) {
return createLifecycleMapping(element);
}
}
return null;
}
public static AbstractProjectConfigurator createProjectConfigurator(String configuratorId) {
IConfigurationElement element = getProjectConfiguratorExtension(configuratorId);
if(element != null) {
try {
AbstractProjectConfigurator configurator = (AbstractProjectConfigurator) element
.createExecutableExtension(AbstractProjectConfigurator.ATTR_CLASS);
configurator.setProjectManager(MavenPlugin.getMavenProjectRegistry());
configurator.setMavenConfiguration(MavenPlugin.getMavenConfiguration());
configurator.setMarkerManager(MavenPluginActivator.getDefault().getMavenMarkerManager());
return configurator;
} catch(CoreException ex) {
log.error(ex.getMessage(), ex);
}
}
return null;
}
public static Map<String, IConfigurationElement> getProjectConfiguratorExtensions() {
IExtensionRegistry registry = Platform.getExtensionRegistry();
return getProjectConfiguratorExtensions(registry);
}
public static Map<String, IConfigurationElement> getProjectConfiguratorExtensions(IExtensionRegistry registry) {
Map<String, IConfigurationElement> extensions = new HashMap<>();
IExtensionPoint configuratorsExtensionPoint = registry.getExtensionPoint(EXTENSION_PROJECT_CONFIGURATORS);
if(configuratorsExtensionPoint != null) {
IExtension[] configuratorExtensions = configuratorsExtensionPoint.getExtensions();
for(IExtension extension : configuratorExtensions) {
IConfigurationElement[] elements = extension.getConfigurationElements();
for(IConfigurationElement element : elements) {
if(element.getName().equals(ELEMENT_CONFIGURATOR)) {
extensions.put(element.getAttribute(AbstractProjectConfigurator.ATTR_ID), element);
}
}
}
}
return extensions;
}
private static IConfigurationElement getProjectConfiguratorExtension(String configuratorId,
Map<String, IConfigurationElement> elements) {
if(elements == null) {
return null;
}
IConfigurationElement element = elements.get(configuratorId);
if(element != null && element.getName().equals(ELEMENT_CONFIGURATOR)) {
if(configuratorId.equals(element.getAttribute(AbstractProjectConfigurator.ATTR_ID))) {
return element;
}
}
return null;
}
private static IConfigurationElement getProjectConfiguratorExtension(String configuratorId) {
return getProjectConfiguratorExtension(configuratorId, getProjectConfiguratorExtensions());
}
private static void checkCompatibleVersion(Plugin metadataPlugin) {
String v = metadataPlugin.getVersion();
if(v == null) {
return; //TODO doesn't inherit version from parent, so we can't check the value
}
ComparableVersion version = new ComparableVersion(v);
if(!version.equals(new ComparableVersion(LIFECYCLE_MAPPING_PLUGIN_VERSION))) {
SourceLocation location = SourceLocationHelper.findLocation(metadataPlugin, SourceLocationHelper.VERSION);
throw new LifecycleMappingConfigurationException(
NLS.bind(Messages.LifecycleMappingPluginVersionIncompatible, metadataPlugin.getVersion()), location);
}
}
private static LifecycleMappingMetadataSource getEmbeddedMetadataSource(MavenProject mavenProject)
throws CoreException {
// TODO this does not merge configuration from profiles
PluginManagement pluginManagement = getPluginManagement(mavenProject);
if(pluginManagement == null) {
return null;
}
Plugin metadataPlugin = pluginManagement.getPluginsAsMap().get(LIFECYCLE_MAPPING_PLUGIN_KEY);
if(metadataPlugin != null) {
checkCompatibleVersion(metadataPlugin);
Xpp3Dom configurationDom = (Xpp3Dom) metadataPlugin.getConfiguration();
if(configurationDom != null) {
Xpp3Dom lifecycleMappingDom = configurationDom.getChild(ELEMENT_LIFECYCLE_MAPPING_METADATA);
if(lifecycleMappingDom != null) {
try {
LifecycleMappingMetadataSource metadataSource = new LifecycleMappingMetadataSourceXpp3Reader()
.read(new StringReader(lifecycleMappingDom.toString()));
postCreateLifecycleMappingMetadataSource(metadataSource);
String packagingType = mavenProject.getPackaging();
if(!"pom".equals(packagingType)) { //$NON-NLS-1$
for(LifecycleMappingMetadata lifecycleMappingMetadata : metadataSource.getLifecycleMappings()) {
if(!packagingType.equals(lifecycleMappingMetadata.getPackagingType())) {
SourceLocation location = SourceLocationHelper.findLocation(metadataPlugin,
SourceLocationHelper.CONFIGURATION);
throw new LifecycleMappingConfigurationException(NLS.bind(Messages.LifecycleMappingPackagingMismatch,
lifecycleMappingMetadata.getPackagingType(), packagingType), location);
}
}
}
return metadataSource;
} catch(IOException e) {
throw new LifecycleMappingConfigurationException(
"Cannot read lifecycle mapping metadata for maven project " + mavenProject, e);
} catch(XmlPullParserException e) {
throw new LifecycleMappingConfigurationException(
"Cannot parse lifecycle mapping metadata for maven project " + mavenProject, e);
} catch(LifecycleMappingConfigurationException e) {
throw e;
} catch(RuntimeException e) {
throw new LifecycleMappingConfigurationException(
"Cannot load lifecycle mapping metadata for maven project " + mavenProject, e);
}
}
}
}
return null;
}
/**
* Returns metadata sources referenced by this project in the order they are specified in pom.xml. Returns empty list
* if no metadata sources are referenced in pom.xml.
*/
private static List<LifecycleMappingMetadataSource> getReferencedMetadataSources(Set<String> referenced,
MavenProject mavenProject, IProgressMonitor monitor) throws CoreException {
List<LifecycleMappingMetadataSource> metadataSources = new ArrayList<>();
PluginManagement pluginManagement = getPluginManagement(mavenProject);
for(Plugin plugin : pluginManagement.getPlugins()) {
if(!LIFECYCLE_MAPPING_PLUGIN_KEY.equals(plugin.getKey())) {
continue;
}
Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration();
if(configuration != null) {
checkCompatibleVersion(plugin);
Xpp3Dom sources = configuration.getChild(ELEMENT_SOURCES);
if(sources != null) {
for(Xpp3Dom source : sources.getChildren(ELEMENT_SOURCE)) {
String groupId = null;
Xpp3Dom child = source.getChild(ATTR_GROUPID);
if(child != null) {
groupId = child.getValue();
}
String artifactId = null;
child = source.getChild(ATTR_ARTIFACTID);
if(child != null) {
artifactId = child.getValue();
}
String version = null;
child = source.getChild(ATTR_VERSION);
if(child != null) {
version = child.getValue();
}
if(referenced.add(groupId + ":" + artifactId)) {
try {
LifecycleMappingMetadataSource lifecycleMappingMetadataSource = getLifecycleMappingMetadataSource(
groupId, artifactId, version, mavenProject.getRemoteArtifactRepositories(), monitor);
metadataSources.add(lifecycleMappingMetadataSource);
} catch(LifecycleMappingConfigurationException e) {
SourceLocation location = SourceLocationHelper.findLocation(plugin, SourceLocationHelper.CONFIGURATION);
e.setLocation(location);
throw e;
}
}
}
}
}
}
return metadataSources;
}
private static PluginManagement getPluginManagement(MavenProject mavenProject) throws CoreException {
Model model = new Model();
Build build = new Build();
model.setBuild(build);
PluginManagement result = new PluginManagement();
build.setPluginManagement(result);
if(mavenProject == null) {
return null;
}
addBuild(result, mavenProject.getOriginalModel().getBuild());
for(Profile profile : mavenProject.getActiveProfiles()) {
addBuild(result, profile.getBuild());
}
MavenImpl maven = (MavenImpl) MavenPlugin.getMaven();
maven.interpolateModel(mavenProject, model);
return result;
}
private static void addBuild(PluginManagement result, BuildBase build) {
if(build != null) {
PluginManagement pluginManagement = build.getPluginManagement();
if(pluginManagement != null) {
for(Plugin plugin : pluginManagement.getPlugins()) {
result.addPlugin(plugin.clone());
}
}
}
}
private static LifecycleMappingMetadataSource defaultLifecycleMappingMetadataSource;
public static LifecycleMappingMetadataSource getDefaultLifecycleMappingMetadataSource() {
if(!useDefaultLifecycleMappingMetadataSource) {
return null;
}
if(defaultLifecycleMappingMetadataSource == null) {
Bundle bundle = Platform.getBundle(DEFAULT_LIFECYCLE_METADATA_BUNDLE);
defaultLifecycleMappingMetadataSource = getMetadataSource(bundle);
if(defaultLifecycleMappingMetadataSource == null) {
defaultLifecycleMappingMetadataSource = new LifecycleMappingMetadataSource();
}
defaultLifecycleMappingMetadataSource.setSource("default");
}
return defaultLifecycleMappingMetadataSource;
}
/** For unit tests only */
public static void setDefaultLifecycleMappingMetadataSource(
LifecycleMappingMetadataSource defaultLifecycleMappingMetadataSource) {
LifecycleMappingFactory.defaultLifecycleMappingMetadataSource = defaultLifecycleMappingMetadataSource;
useDefaultLifecycleMappingMetadataSource = true;
}
private static boolean useDefaultLifecycleMappingMetadataSource = true;
/** For unit tests only */
public static void setUseDefaultLifecycleMappingMetadataSource(boolean use) {
useDefaultLifecycleMappingMetadataSource = use;
if(!use) {
defaultLifecycleMappingMetadataSource = null;
}
}
// TODO: cache LifecycleMappingMetadataSource instances
private static LifecycleMappingMetadataSource getLifecycleMappingMetadataSource(String groupId, String artifactId,
String version, List<ArtifactRepository> repositories, IProgressMonitor monitor) {
IMaven maven = MavenPlugin.getMaven();
try {
Artifact artifact = maven.resolve(groupId, artifactId, version, "xml", LIFECYCLE_MAPPING_METADATA_CLASSIFIER,
repositories, monitor);
File file = artifact.getFile();
if(file == null || !file.exists() || !file.canRead()) {
throw new LifecycleMappingConfigurationException("Cannot find file for artifact " + artifact);
}
try {
LifecycleMappingMetadataSource metadataSource = createLifecycleMappingMetadataSource(groupId, artifactId,
version, file);
metadataSource.setSource(artifact);
return metadataSource;
} catch(IOException e) {
throw new LifecycleMappingConfigurationException("Cannot read lifecycle mapping metadata for " + artifact, e);
} catch(XmlPullParserException e) {
throw new LifecycleMappingConfigurationException("Cannot parse lifecycle mapping metadata for " + artifact, e);
} catch(RuntimeException e) {
throw new LifecycleMappingConfigurationException("Cannot load lifecycle mapping metadata for " + artifact, e);
}
} catch(CoreException ex) {
throw new LifecycleMappingConfigurationException(ex);
}
}
private static LifecycleMappingMetadataSource createLifecycleMappingMetadataSource(String groupId, String artifactId,
String version, File configuration) throws IOException, XmlPullParserException {
InputStream in = new FileInputStream(configuration);
try {
LifecycleMappingMetadataSource lifecycleMappingMetadataSource = createLifecycleMappingMetadataSource(in);
lifecycleMappingMetadataSource.setGroupId(groupId);
lifecycleMappingMetadataSource.setArtifactId(artifactId);
lifecycleMappingMetadataSource.setVersion(version);
return lifecycleMappingMetadataSource;
} finally {
IOUtil.close(in);
}
}
/**
* Returns lifecycle mapping metadata sources provided by all installed bundles
*/
public synchronized static List<LifecycleMappingMetadataSource> getBundleMetadataSources() {
if(bundleMetadataSources == null) {
bundleMetadataSources = new ArrayList<>();
IExtensionRegistry registry = Platform.getExtensionRegistry();
IExtensionPoint configuratorsExtensionPoint = registry
.getExtensionPoint(EXTENSION_LIFECYCLE_MAPPING_METADATA_SOURCE);
if(configuratorsExtensionPoint != null) {
IExtension[] configuratorExtensions = configuratorsExtensionPoint.getExtensions();
for(IExtension extension : configuratorExtensions) {
RegistryContributor contributor = (RegistryContributor) extension.getContributor();
Bundle bundle = Platform.getBundle(contributor.getActualName());
LifecycleMappingMetadataSource source = getMetadataSource(bundle);
if(source != null) {
bundleMetadataSources.add(source);
}
}
}
}
return bundleMetadataSources;
}
private static LifecycleMappingMetadataSource getMetadataSource(Bundle bundle) {
if(bundle == null) {
return null;
}
URL url = bundle.getEntry(LIFECYCLE_MAPPING_METADATA_SOURCE_PATH);
if(url != null) {
try {
InputStream in = url.openStream();
try {
LifecycleMappingMetadataSource metadata = createLifecycleMappingMetadataSource(in);
metadata.setSource(bundle);
return metadata;
} finally {
IOUtil.close(in);
}
} catch(IOException | XmlPullParserException e) {
log.warn("Could not read lifecycle-mapping-metadata.xml for bundle {}", bundle.getSymbolicName(), e);
}
}
return null;
}
private static boolean isPrimaryMapping(PluginExecutionMetadata executionMetadata,
ProjectConfigurationElementSorter sorter) {
if(executionMetadata == null) {
return false;
}
if(isConfigurator(executionMetadata)) {
String configuratorId = getProjectConfiguratorId(executionMetadata);
return sorter.isRootConfigurator(configuratorId);
}
return true;
}
public static ILifecycleMapping getLifecycleMapping(IMavenProjectFacade facade) {
ILifecycleMapping lifecycleMapping = (ILifecycleMapping) facade
.getSessionProperty(MavenProjectFacade.PROP_LIFECYCLE_MAPPING);
if(lifecycleMapping == null) {
String lifecycleMappingId = facade.getLifecycleMappingId();
if(lifecycleMappingId != null) {
lifecycleMapping = getLifecycleMapping(lifecycleMappingId);
}
if(lifecycleMapping == null) {
lifecycleMapping = new InvalidLifecycleMapping();
}
facade.setSessionProperty(MavenProjectFacade.PROP_LIFECYCLE_MAPPING, lifecycleMapping);
}
return lifecycleMapping;
}
public static Map<String, AbstractProjectConfigurator> getProjectConfigurators(IMavenProjectFacade facade) {
@SuppressWarnings("unchecked")
Map<String, AbstractProjectConfigurator> configurators = (Map<String, AbstractProjectConfigurator>) facade
.getSessionProperty(MavenProjectFacade.PROP_CONFIGURATORS);
if(configurators == null) {
// Project configurators are stored as a facade session property, so they are "lost" on eclipse restart.
LifecycleMappingResult result = new LifecycleMappingResult();
instantiateProjectConfigurators(facade.getMavenProject(), result, facade.getMojoExecutionMapping());
configurators = setProjectConfigurators(facade, result);
// TODO deal with configurators that have been removed since facade was first created
if(result.hasProblems()) {
IMavenMarkerManager markerManager = MavenPluginActivator.getDefault().getMavenMarkerManager();
for(MavenProblemInfo problem : result.getProblems()) {
markerManager.addErrorMarker(facade.getPom(), IMavenConstants.MARKER_LIFECYCLEMAPPING_ID, problem);
}
}
}
return configurators;
}
public static Map<String, AbstractProjectConfigurator> setProjectConfigurators(IMavenProjectFacade facade,
LifecycleMappingResult mappingResult) {
Map<String, AbstractProjectConfigurator> unsorted = mappingResult.getProjectConfigurators();
if(unsorted == null || unsorted.isEmpty()) {
facade.setSessionProperty(MavenProjectFacade.PROP_CONFIGURATORS, unsorted);
return unsorted;
}
Map<String, AbstractProjectConfigurator> configurators = new LinkedHashMap<>(unsorted.size());
Map<String, IConfigurationElement> elements = getProjectConfiguratorExtensions();
try {
ProjectConfigurationElementSorter sorter = new ProjectConfigurationElementSorter(unsorted.keySet(), elements);
List<String> sortedConfigurators = sorter.getSortedConfigurators();
log.debug("{} is configured by :", facade.getProject().getName());
for(String id : sortedConfigurators) {
AbstractProjectConfigurator configurator = unsorted.get(id);
if(configurator != null) {
log.debug("\t- {}", id);
configurators.put(id, configurator);
}
}
} catch(CycleDetectedException e) {
log.error("Cycle detecting while sorting configurators", e);
SourceLocation location = SourceLocationHelper.findPackagingLocation(facade.getMavenProject());
mappingResult.addProblem(new MavenProblemInfo(location, e));
}
facade.setSessionProperty(MavenProjectFacade.PROP_CONFIGURATORS, configurators);
return configurators;
}
public static boolean isLifecycleMappingChanged(IMavenProjectFacade newFacade,
ILifecycleMappingConfiguration oldConfiguration, IProgressMonitor monitor) {
if(oldConfiguration == null || newFacade == null) {
return false; // we have bigger problems to worry
}
String lifecycleMappingId = newFacade.getLifecycleMappingId();
if(lifecycleMappingId == null || newFacade.getMojoExecutionMapping() == null) {
return false; // we have bigger problems to worry
}
if(!eq(lifecycleMappingId, oldConfiguration.getLifecycleMappingId())) {
return true;
}
// at this point we know lifecycleMappingId is not null and has not changed
AbstractLifecycleMapping lifecycleMapping = getLifecycleMapping(lifecycleMappingId);
if(lifecycleMapping == null) {
return false; // we have bigger problems to worry about
}
return lifecycleMapping.hasLifecycleMappingChanged(newFacade, oldConfiguration, monitor);
}
private static <T> boolean eq(T a, T b) {
return a != null ? a.equals(b) : b == null;
}
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 static boolean isInterestingPhase(String phase) {
for(String interestingPhase : INTERESTING_PHASES) {
if(interestingPhase.equals(phase)) {
return true;
}
}
return false;
}
/**
* @param bundleMetadataSources The bundleMetadataSources to set.
*/
public static synchronized void setBundleMetadataSources(List<LifecycleMappingMetadataSource> bundleMetadataSources) {
LifecycleMappingFactory.bundleMetadataSources = bundleMetadataSources;
}
}