Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Tanasenko2016-05-29 22:55:12 +0000
committerFred Bricon2016-05-31 19:39:18 +0000
commitb5df3e6ad3307e3a7f107af307efeee7e66fbb08 (patch)
treed1bf9419979ebb4c10274cda1c9ee9fd16ab89ee
parenta216aad800082fcf7c8243c8faf470ecb6a3f407 (diff)
downloadm2e-core-b5df3e6ad3307e3a7f107af307efeee7e66fbb08.tar.gz
m2e-core-b5df3e6ad3307e3a7f107af307efeee7e66fbb08.tar.xz
m2e-core-b5df3e6ad3307e3a7f107af307efeee7e66fbb08.zip
494858 Support processing instructions for lifecycle mapping
Change-Id: I015f648fba3bab8d792543177b68c4f051150e4b Signed-off-by: Anton Tanasenko <atg.sleepless@gmail.com>
-rw-r--r--org.eclipse.m2e.core/.settings/org.eclipse.jdt.ui.prefs2
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/Messages.java4
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/AnnotationMappingMetadataSource.java306
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/LifecycleMappingFactory.java32
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/SimpleMappingMetadataSource.java12
-rw-r--r--org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/messages.properties2
6 files changed, 343 insertions, 15 deletions
diff --git a/org.eclipse.m2e.core/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.m2e.core/.settings/org.eclipse.jdt.ui.prefs
index 595d9975..6cc57db7 100644
--- a/org.eclipse.m2e.core/.settings/org.eclipse.jdt.ui.prefs
+++ b/org.eclipse.m2e.core/.settings/org.eclipse.jdt.ui.prefs
@@ -28,7 +28,7 @@ sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=true
-sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.format_source_code_changes_only=true
sp_cleanup.make_local_variable_final=false
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/Messages.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/Messages.java
index d5d48924..3cd24b0d 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/Messages.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/Messages.java
@@ -252,6 +252,10 @@ public class Messages extends NLS {
public static String AbstractMavenRuntime_unknownProject;
+ public static String AnnotationMappingMetadataSource_ErrorParsingInstruction;
+
+ public static String AnnotationMappingMetadataSource_UnsupportedInstructionFormat;
+
public static String ProjectConfiguratorToRunBeforeNotAvailable;
public static String ProjectConfiguratorToRunAfterNotAvailable;
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/AnnotationMappingMetadataSource.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/AnnotationMappingMetadataSource.java
new file mode 100644
index 00000000..aaf1fd23
--- /dev/null
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/AnnotationMappingMetadataSource.java
@@ -0,0 +1,306 @@
+/*******************************************************************************
+ * Copyright (c) 2016 Anton Tanasenko.
+ * 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:
+ * Anton Tanasenko - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.core.internal.lifecyclemapping;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import com.google.common.base.CharMatcher;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableMap;
+
+import org.codehaus.plexus.util.ReaderFactory;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.MXParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+
+import org.apache.maven.model.InputLocation;
+import org.apache.maven.model.InputLocationTracker;
+import org.apache.maven.model.InputSource;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginContainer;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.project.MavenProject;
+
+import org.eclipse.m2e.core.internal.Messages;
+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.markers.SourceLocation;
+import org.eclipse.m2e.core.lifecyclemapping.model.PluginExecutionAction;
+import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
+
+
+/**
+ * AnnotationMappingMetadataSource
+ *
+ * @author atgsl
+ */
+public class AnnotationMappingMetadataSource implements MappingMetadataSource {
+
+ private static final String SELF = ""; //$NON-NLS-1$
+
+ private final MavenProject project;
+
+ private final String projectId;
+
+ private final List<PI> pis;
+
+ public static AnnotationMappingMetadataSource get(MavenProject project) {
+ List<PI> pis = parsePIs(project);
+ if(!pis.isEmpty()) {
+ return new AnnotationMappingMetadataSource(project, pis);
+ }
+ return null;
+ }
+
+ private AnnotationMappingMetadataSource(MavenProject project, List<PI> pis) {
+ this.project = project;
+ this.pis = pis;
+ projectId = project.getModel().getLocation(SELF).getSource().getModelId();
+ }
+
+ public List<PluginExecutionMetadata> getPluginExecutionMetadata(MojoExecutionKey execution) {
+ Xpp3Dom action = getAction(execution);
+ if(action != null) {
+ return Collections.singletonList(createMetadata(action));
+ }
+ return Collections.emptyList();
+ }
+
+ private Xpp3Dom getAction(MojoExecutionKey execution) {
+
+ String key = Plugin.constructKey(execution.getGroupId(), execution.getArtifactId());
+ Plugin plugin = getPlugin(project.getBuild(), key);
+ Plugin mplugin = getPlugin(project.getPluginManagement(), key);
+
+ String executionId = execution.getExecutionId();
+ if(executionId != null) {
+
+ // find pi for the executionId
+ if(plugin != null) {
+ PluginExecution pluginExecution = plugin.getExecutionsAsMap().get(executionId);
+ if(pluginExecution != null) {
+ Xpp3Dom action = getAction(pluginExecution);
+ if(action != null)
+ return action;
+ }
+ }
+ if(mplugin != null) {
+ PluginExecution pluginExecution = mplugin.getExecutionsAsMap().get(executionId);
+ if(pluginExecution != null) {
+ Xpp3Dom action = getAction(pluginExecution);
+ if(action != null)
+ return action;
+ }
+ }
+
+ // find pi for the whole plugin
+ if(plugin != null) {
+ Xpp3Dom action = getAction(plugin);
+ if(action != null)
+ return action;
+ }
+ if(mplugin != null) {
+ Xpp3Dom action = getAction(mplugin);
+ if(action != null)
+ return action;
+ }
+ }
+ return null;
+ }
+
+ private Plugin getPlugin(PluginContainer plugins, String key) {
+ return plugins == null ? null : plugins.getPluginsAsMap().get(key);
+ }
+
+ public LifecycleMappingMetadata getLifecycleMappingMetadata(String packagingType) throws DuplicateMappingException {
+ return null;
+ }
+
+ private Xpp3Dom getAction(InputLocationTracker tracker) {
+ InputLocation location = tracker.getLocation(SELF);
+
+ if(location != null && location.getSource() != null && projectId.equals(location.getSource().getModelId())) {
+ int l = location.getLineNumber();
+ int c = location.getColumnNumber();
+ for(PI pi : pis) {
+ if(pi.l == l && pi.c == c) {
+ return pi.action;
+ }
+ }
+ }
+ return null;
+ }
+
+ private PluginExecutionMetadata createMetadata(Xpp3Dom action) {
+ Xpp3Dom actionDom = new Xpp3Dom("action"); //$NON-NLS-1$
+ actionDom.addChild(action);
+
+ PluginExecutionMetadata md = new PluginExecutionMetadata();
+ md.setActionDom(actionDom);
+ LifecycleMappingMetadataSource source = new LifecycleMappingMetadataSource();
+ source.setSource(project);
+ md.setSource(source);
+ md.setFilter(new PluginExecutionFilter());
+ return md;
+ }
+
+ private static List<PI> parsePIs(MavenProject project) {
+
+ File pom = project.getFile();
+ InputSource source = project.getModel().getLocation(SELF).getSource();
+
+ List<PI> pis = new ArrayList<>();
+
+ XmlPullParser parser = new MXParser();
+
+ try (InputStream in = new FileInputStream(pom)) {
+ parser.setInput(ReaderFactory.newXmlReader(in));
+
+ Deque<State> stack = new LinkedList<>();
+
+ int eventType = parser.getEventType();
+ while(eventType != XmlPullParser.END_DOCUMENT) {
+
+ if(eventType == XmlPullParser.START_TAG) {
+
+ stack.push(new State(parser.getLineNumber(), parser.getColumnNumber()));
+
+ } else if(eventType == XmlPullParser.END_TAG) {
+
+ stack.pop();
+
+ } else if(eventType == XmlPullParser.PROCESSING_INSTRUCTION && !stack.isEmpty()) {
+
+
+ String text = parser.getText();
+ if(text.startsWith("m2e ")) { //$NON-NLS-1$
+ // found it
+ Xpp3Dom dom = parse(text.substring(4));
+ if(dom == null) {
+ SourceLocation location = new SourceLocation(source.getLocation(), source.getModelId(),
+ parser.getLineNumber(), parser.getColumnNumber(), text.length() + 4);
+ throw new LifecycleMappingConfigurationException(Messages.AnnotationMappingMetadataSource_UnsupportedInstructionFormat, location);
+ }
+ State s = stack.peek();
+ PI pi = new PI(s.l, s.c, dom);
+ pis.add(pi);
+ }
+ }
+
+ eventType = parser.nextToken();
+ }
+
+ } catch(XmlPullParserException | IOException ex) {
+ SourceLocation location = new SourceLocation(source.getLocation(), source.getModelId(), parser.getLineNumber(),
+ parser.getColumnNumber(), 1);
+ throw new LifecycleMappingConfigurationException(Messages.AnnotationMappingMetadataSource_ErrorParsingInstruction, location);
+ }
+
+ return pis;
+ }
+
+ private static final Splitter PI_SPLITTER = Splitter.on(CharMatcher.WHITESPACE).omitEmptyStrings().limit(2);
+
+ private static final Splitter EXECUTE_SPLITTER = Splitter.on(',').omitEmptyStrings();
+
+ private static final Map<String, String> EXECUTE_OPTIONS = new ImmutableMap.Builder<String, String>()
+ .put("onConfiguration", LifecycleMappingFactory.ELEMENT_RUN_ON_CONFIGURATION) //$NON-NLS-1$
+ .put("onIncremental", LifecycleMappingFactory.ELEMENT_RUN_ON_INCREMENTAL).build(); //$NON-NLS-1$
+
+ private static Xpp3Dom parse(String pi) {
+
+ List<String> split = PI_SPLITTER.splitToList(pi);
+
+ PluginExecutionAction a = getAction(split.get(0));
+ if(a == null) {
+ return null;
+ }
+ switch(a) {
+ case ignore:
+ return new Xpp3Dom("ignore"); //$NON-NLS-1$
+
+ case configurator:
+ if(split.size() != 2) {
+ return null;
+ }
+ Xpp3Dom conf = new Xpp3Dom("configurator"); //$NON-NLS-1$
+ Xpp3Dom id = new Xpp3Dom("id"); //$NON-NLS-1$
+ id.setValue(split.get(1));
+ conf.addChild(id);
+ return conf;
+
+ case execute:
+ Xpp3Dom exec = new Xpp3Dom("execute"); //$NON-NLS-1$
+ if(split.size() > 1) {
+ for(String option : EXECUTE_SPLITTER.split(split.get(1))) {
+ String value = EXECUTE_OPTIONS.get(option);
+ if(value == null) {
+ return null;
+ }
+ Xpp3Dom opt = new Xpp3Dom(value);
+ opt.setValue("true"); //$NON-NLS-1$
+ exec.addChild(opt);
+ }
+ }
+ return exec;
+
+ default:
+ return null;
+ }
+ }
+
+ private static PluginExecutionAction getAction(String value) {
+ for(PluginExecutionAction a : PluginExecutionAction.values()) {
+ if(value.toLowerCase().equals(a.name())) {
+ return a;
+ }
+ }
+ return null;
+ }
+
+ private static class State {
+ final int l;
+
+ final int c;
+
+ State(int l, int c) {
+ this.l = l;
+ this.c = c;
+ }
+ }
+
+ private static class PI {
+ final int l;
+
+ final int c;
+
+ final Xpp3Dom action;
+
+ PI(int l, int c, Xpp3Dom action) {
+ this.l = l;
+ this.c = c;
+ this.action = action;
+ }
+ }
+}
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/LifecycleMappingFactory.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/LifecycleMappingFactory.java
index 9343cc1c..93f12331 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/LifecycleMappingFactory.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/LifecycleMappingFactory.java
@@ -152,9 +152,9 @@ public class LifecycleMappingFactory {
private static final String ELEMENT_MESSAGE = "message"; //$NON-NLS-1$
- private static final String ELEMENT_RUN_ON_INCREMENTAL = "runOnIncremental";
+ static final String ELEMENT_RUN_ON_INCREMENTAL = "runOnIncremental";
- private static final String ELEMENT_RUN_ON_CONFIGURATION = "runOnConfiguration";
+ static final String ELEMENT_RUN_ON_CONFIGURATION = "runOnConfiguration";
private static final String ATTR_GROUPID = "groupId";
@@ -266,7 +266,7 @@ public class LifecycleMappingFactory {
// List order
// 1. preferences in project (*** not implemented yet)
// 2. preferences in ancestor project (*** not implemented yet)
- // 3. this pom embedded, this pom referenced, parent embedded, parent referenced, grand parent embedded...
+ // 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
@@ -275,10 +275,8 @@ public class LifecycleMappingFactory {
// TODO validate metadata and replace invalid entries with error mapping
List<MappingMetadataSource> metadataSources = new ArrayList<MappingMetadataSource>();
- for(LifecycleMappingMetadataSource source : getPomMappingMetadataSources(mavenProject, monitor)) {
- metadataSources.add(new SimpleMappingMetadataSource(source));
- }
- metadataSourcesMap.put("pomMappingMetadataSources", metadataSources);
+
+ metadataSourcesMap.put("pomMappingMetadataSources", getPomMappingMetadataSources(mavenProject, monitor));
metadataSourcesMap.put("workspaceMetadataSources", //
Collections
@@ -838,11 +836,11 @@ public class LifecycleMappingFactory {
*
* @throws CoreException if metadata sources cannot be resolved or read
*/
- public static List<LifecycleMappingMetadataSource> getPomMappingMetadataSources(MavenProject mavenProject,
+ public static List<MappingMetadataSource> getPomMappingMetadataSources(MavenProject mavenProject,
IProgressMonitor monitor) throws CoreException {
IMaven maven = MavenPlugin.getMaven();
- ArrayList<LifecycleMappingMetadataSource> sources = new ArrayList<LifecycleMappingMetadataSource>();
+ List<MappingMetadataSource> sources = new ArrayList<MappingMetadataSource>();
HashSet<String> referenced = new LinkedHashSet<String>();
@@ -851,17 +849,27 @@ public class LifecycleMappingFactory {
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) {
- maven.detachFromSession(project); // don't cache maven session
+ detach = true;
embeddedSource.setSource(project);
- sources.add(embeddedSource);
+ sources.add(new SimpleMappingMetadataSource(embeddedSource));
}
for(LifecycleMappingMetadataSource referencedSource : getReferencedMetadataSources(referenced, project,
monitor)) {
- sources.add(referencedSource);
+ 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
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/SimpleMappingMetadataSource.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/SimpleMappingMetadataSource.java
index 79052c2d..b9519afe 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/SimpleMappingMetadataSource.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/lifecyclemapping/SimpleMappingMetadataSource.java
@@ -27,16 +27,20 @@ import org.eclipse.m2e.core.project.configurator.MojoExecutionKey;
*/
public class SimpleMappingMetadataSource implements MappingMetadataSource {
- private final List<LifecycleMappingMetadata> lifecycleMappings = new ArrayList<LifecycleMappingMetadata>();
+ private final List<LifecycleMappingMetadataSource> sources = new ArrayList<>();
- private final List<PluginExecutionMetadata> pluginExecutions = new ArrayList<PluginExecutionMetadata>();
+ private final List<LifecycleMappingMetadata> lifecycleMappings = new ArrayList<>();
+
+ private final List<PluginExecutionMetadata> pluginExecutions = new ArrayList<>();
public SimpleMappingMetadataSource(LifecycleMappingMetadataSource source) {
+ this.sources.add(source);
this.lifecycleMappings.addAll(source.getLifecycleMappings());
this.pluginExecutions.addAll(source.getPluginExecutions());
}
public SimpleMappingMetadataSource(List<LifecycleMappingMetadataSource> sources) {
+ this.sources.addAll(sources);
for(LifecycleMappingMetadataSource source : sources) {
this.lifecycleMappings.addAll(source.getLifecycleMappings());
this.pluginExecutions.addAll(source.getPluginExecutions());
@@ -48,6 +52,10 @@ public class SimpleMappingMetadataSource implements MappingMetadataSource {
this.pluginExecutions.addAll(lifecycleMapping.getPluginExecutions());
}
+ public List<LifecycleMappingMetadataSource> getSources() {
+ return this.sources;
+ }
+
public LifecycleMappingMetadata getLifecycleMappingMetadata(String packagingType) throws DuplicateMappingException {
if(packagingType == null) {
return null;
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/messages.properties b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/messages.properties
index cc1c8418..cbfb0fa2 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/messages.properties
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/messages.properties
@@ -7,6 +7,8 @@ AbstractTransferListenerAdapter_cancelled=Transfer is canceled
AbstractTransferListenerAdapter_kb=KB
AbstractTransferListenerAdapter_mb=MB
AbstractTransferListenerAdapter_subtask=error {0}
+AnnotationMappingMetadataSource_ErrorParsingInstruction=Error parsing lifecycle processing instructions
+AnnotationMappingMetadataSource_UnsupportedInstructionFormat=Unsupported instruction format
ArchetypeCatalogFactory_default_local=Default Local
ArchetypeCatalogFactory_error_missing_catalog=Error looking up archetype catalog; {0}
ArchetypeCatalogFactory_indexer_catalog=Nexus Indexer

Back to the top