package org.jetbrains.idea.maven.plugins.api;
-import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.text.StringUtil;
+import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.model.MavenPlugin;
+import org.jetbrains.plugins.groovy.util.ClassInstanceCache;
-import java.util.*;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
/**
* @author Sergey Evdokimov
*/
public class MavenModelPropertiesPatcher {
- private static volatile Map<String, Map<String, String[]>> ourMap;
-
- private static Map<String, Map<String, String[]>> getMap() {
- Map<String, Map<String, String[]>> res = ourMap;
+ /*
+ * Add properties those should be added by plugins.
+ */
+ public static void patch(Properties modelProperties, @Nullable Collection<MavenPlugin> plugins) {
+ if (plugins == null) return;
- if (res == null) {
- res = new HashMap<String, Map<String, String[]>>();
+ Map<String, Map<String, Map<String, List<MavenPluginDescriptor>>>> map = MavenPluginDescriptor.getDescriptorsMap();
- for (MavenPluginDescriptor pluginDescriptor : MavenPluginDescriptor.EP_NAME.getExtensions()) {
- if (pluginDescriptor.properties != null && pluginDescriptor.properties.length > 0) {
- Pair<String, String> pluginId = MavenPluginDescriptor.parsePluginId(pluginDescriptor.mavenId);
+ for (MavenPlugin plugin : plugins) {
+ Map<String, Map<String, List<MavenPluginDescriptor>>> groupMap = map.get(plugin.getArtifactId());
+ if (groupMap != null) {
+ Map<String, List<MavenPluginDescriptor>> goalsMap = groupMap.get(plugin.getGroupId());
- String[] properties = new String[pluginDescriptor.properties.length];
- for (int i = 0; i < pluginDescriptor.properties.length; i++) {
- properties[i] = pluginDescriptor.properties[i].name;
- }
+ patch(modelProperties, goalsMap.get(null), null, plugin.getConfigurationElement(), plugin);
- Map<String, String[]> groupMap = res.get(pluginId.second);// pluginId.second is artifactId
- if (groupMap == null) {
- groupMap = new HashMap<String, String[]>();
- res.put(pluginId.second, groupMap);
+ for (MavenPlugin.Execution execution : plugin.getExecutions()) {
+ for (String goal : execution.getGoals()) {
+ patch(modelProperties, goalsMap.get(goal), goal, execution.getConfigurationElement(), plugin);
}
-
- groupMap.put(pluginId.first, properties); // pluginId.first is groupId
}
}
-
- ourMap = res;
}
-
- return res;
}
- /*
- * Add properties those should be added by plugins.
- */
- public static void patch(Properties modelProperties, @Nullable Collection<MavenPlugin> plugins) {
- if (plugins == null) return;
-
- Map<String, Map<String, String[]>> map = getMap();
+ private static void patch(Properties modelProperties, @Nullable List<MavenPluginDescriptor> descriptors, @Nullable String goal, Element cfgElement, MavenPlugin plugin) {
+ if (descriptors == null) return;
- for (MavenPlugin plugin : plugins) {
- Map<String, String[]> groupMap = map.get(plugin.getArtifactId());
- if (groupMap != null) {
- String[] properties = groupMap.get(plugin.getGroupId());
-
- if (properties != null) {
- for (String property : properties) {
- if (!modelProperties.containsKey(property)) {
- modelProperties.setProperty(property, "");
- }
+ for (MavenPluginDescriptor descriptor : descriptors) {
+ if (descriptor.properties != null) {
+ for (MavenPluginDescriptor.ModelProperty property : descriptor.properties) {
+ if (StringUtil.isNotEmpty(property.name)) {
+ modelProperties.setProperty(property.name, "");
}
}
}
+
+ if (descriptor.propertyGenerator != null) {
+ MavenPropertiesGenerator generator = ClassInstanceCache.getInstance(descriptor.propertyGenerator, descriptor.getLoaderForClass());
+ generator.generate(modelProperties, goal, plugin, cfgElement);
+ }
}
}
import com.intellij.openapi.extensions.AbstractExtensionPointBean;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.Pair;
+import com.intellij.util.SmartList;
import com.intellij.util.xml.Required;
import com.intellij.util.xmlb.annotations.AbstractCollection;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.Property;
import com.intellij.util.xmlb.annotations.Tag;
+import org.jetbrains.idea.maven.utils.MavenUtil;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
* @author Sergey Evdokimov
public static final ExtensionPointName<MavenPluginDescriptor> EP_NAME = new ExtensionPointName<MavenPluginDescriptor>("org.jetbrains.idea.maven.pluginDescriptor");
+ // Map artifactId -> groupId -> goal -> List<MavenPluginDescriptor>
+ public static volatile Map<String, Map<String, Map<String, List<MavenPluginDescriptor>>>> ourDescriptorsMap;
+
+ @Attribute("goal")
+ public String goal;
+
@Attribute("mavenId")
@Required
public String mavenId;
@AbstractCollection(surroundWithTag = false)
public ModelProperty[] properties;
+ @Attribute("propertyGenerator")
+ public String propertyGenerator;
+
@Tag("property")
public static class ModelProperty {
@Attribute("name")
@Required
public String name;
- @Attribute("goal")
- public String goal;
-
/**
* Class name of reference provider. The reference provider must implement MavenParamReferenceProvider or PsiReferenceProvider.
*/
return new Pair<String, String>(mavenId.substring(0, idx), mavenId.substring(idx + 1));
}
+ public static Map<String, Map<String, Map<String, List<MavenPluginDescriptor>>>> getDescriptorsMap() {
+ Map<String, Map<String, Map<String, List<MavenPluginDescriptor>>>> res = ourDescriptorsMap;
+ if (res == null) {
+ res = new HashMap<String, Map<String, Map<String, List<MavenPluginDescriptor>>>>();
+
+ for (MavenPluginDescriptor pluginDescriptor : MavenPluginDescriptor.EP_NAME.getExtensions()) {
+ Pair<String, String> pluginId = parsePluginId(pluginDescriptor.mavenId);
+
+ Map<String, Map<String, List<MavenPluginDescriptor>>> groupMap = MavenUtil.getOrCreate(res, pluginId.second);// pluginId.second is artifactId
+
+ Map<String, List<MavenPluginDescriptor>> goalsMap = MavenUtil.getOrCreate(groupMap, pluginId.first);// pluginId.first is groupId
+
+ List<MavenPluginDescriptor> descriptorList = goalsMap.get(pluginDescriptor.goal);
+ if (descriptorList == null) {
+ descriptorList = new SmartList<MavenPluginDescriptor>();
+ goalsMap.put(pluginDescriptor.goal, descriptorList);
+ }
+
+ descriptorList.add(pluginDescriptor);
+ }
+
+ ourDescriptorsMap = res;
+ }
+
+ return res;
+ }
}
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.model.*;
+import org.jetbrains.idea.maven.utils.MavenUtil;
import java.util.*;
Map pluginsMap = res;
for (int i = paramPath.length - 1; i >= 0; i--) {
- pluginsMap = getOrCreate(pluginsMap, paramPath[i]);
+ pluginsMap = MavenUtil.getOrCreate(pluginsMap, paramPath[i]);
}
ParamInfo paramInfo = new ParamInfo(pluginDescriptor.getPluginDescriptor().getPluginClassLoader(), param);
- Map<String, ParamInfo> goalsMap = getOrCreate(pluginsMap, pluginId);
+ Map<String, ParamInfo> goalsMap = MavenUtil.getOrCreate(pluginsMap, pluginId);
- ParamInfo oldValue = goalsMap.put(param.goal, paramInfo);
+ String goal = pluginDescriptor.goal;
+ assert goal == null || !goal.isEmpty();
+
+ ParamInfo oldValue = goalsMap.put(goal, paramInfo);
if (oldValue != null) {
LOG.error("Duplicated maven plugin parameter descriptor: "
+ pluginId.first + ':' + pluginId.second + " -> "
- + (param.goal != null ? "[" + param.goal + ']' : "") + param.name);
+ + (goal != null ? "[" + goal + ']' : "") + param.name);
}
}
}
return res;
}
- @NotNull
- private static <K, V extends Map> V getOrCreate(Map map, K key) {
- Map res = (Map)map.get(key);
- if (res == null) {
- res = new HashMap();
- map.put(key, res);
- }
-
- return (V)res;
- }
-
public static boolean isSimpleText(@NotNull XmlText paramValue) {
PsiElement prevSibling = paramValue.getPrevSibling();
if (!(prevSibling instanceof LeafPsiElement) || ((LeafPsiElement)prevSibling).getElementType() != XmlTokenType.XML_TAG_END) {
--- /dev/null
+package org.jetbrains.idea.maven.plugins.api;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.model.MavenPlugin;
+
+import java.util.Properties;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public abstract class MavenPropertiesGenerator {
+
+ public abstract void generate(@NotNull Properties modelProperties,
+ @Nullable String goal,
+ @NotNull MavenPlugin plugin,
+ @Nullable Element cfgElement);
+
+}
--- /dev/null
+package org.jetbrains.idea.maven.plugins.buildHelper;
+
+import org.jdom.Element;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.idea.maven.model.MavenPlugin;
+import org.jetbrains.idea.maven.plugins.api.MavenPropertiesGenerator;
+
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class MavenBuildHelperPropertyGenerator extends MavenPropertiesGenerator {
+ @Override
+ public void generate(@NotNull Properties modelProperties,
+ @Nullable String goal,
+ @NotNull MavenPlugin plugin,
+ @Nullable Element cfgElement) {
+ if (cfgElement == null) return;
+
+ Element portNames = cfgElement.getChild("portNames");
+ if (portNames == null) return;
+
+ List<Element> portName = portNames.getChildren("portName");
+ for (Element element : portName) {
+ String propertyName = element.getTextTrim();
+ if (!propertyName.isEmpty()) {
+ modelProperties.setProperty(propertyName, "");
+ }
+ }
+ }
+}
return ModuleRootManager.getInstance(module).getSdk();
}
+
+ @NotNull
+ public static <K, V extends Map> V getOrCreate(Map map, K key) {
+ Map res = (Map)map.get(key);
+ if (res == null) {
+ res = new HashMap();
+ map.put(key, res);
+ }
+
+ return (V)res;
+ }
+
}
<property name="timestamp"/>
</pluginDescriptor>
+ <pluginDescriptor mavenId="org.codehaus.mojo:build-helper-maven-plugin" goal="reserve-network-port"
+ propertyGenerator="org.jetbrains.idea.maven.plugins.buildHelper.MavenBuildHelperPropertyGenerator"/>
+
<pluginDescriptor mavenId="org.codehaus.mojo:sql-maven-plugin">
<param name="sqlCommand" language="SQL"/>
</pluginDescriptor>
--- /dev/null
+package org.jetbrains.idea.maven.plugins
+
+import org.jetbrains.idea.maven.dom.MavenDomTestCase
+
+/**
+ * @author Sergey Evdokimov
+ */
+class MavenBuildHelperPluginTest extends MavenDomTestCase {
+
+ public void testCompletion() {
+ importProject("""
+<groupId>test</groupId>
+<artifactId>project</artifactId>
+<version>1</version>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>yyy</id>
+ <goals>
+ <goal>reserve-network-port</goal>
+ </goals>
+ <configuration>
+ <portNames>
+ <portName>someNewProperty1</portName>
+ <portName>someNewProperty2</portName>
+ </portNames>
+ </configuration>
+ </execution>
+ <execution>
+ <id>xxx</id>
+ <goals>
+ <goal>foo</goal>
+ </goals>
+ <configuration>
+ <portNames>
+ <portName>someNewProperty3</portName>
+ </portNames>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <aaa>\${someNew}</aaa>
+ </properties>
+""")
+
+ createProjectPom("""
+<groupId>test</groupId>
+<artifactId>project</artifactId>
+<version>1</version>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>yyy</id>
+ <goals>
+ <goal>reserve-network-port</goal>
+ </goals>
+ <configuration>
+ <portNames>
+ <portName>someNewProperty1</portName>
+ <portName>someNewProperty2</portName>
+ </portNames>
+ </configuration>
+ </execution>
+ <execution>
+ <id>xxx</id>
+ <goals>
+ <goal>foo</goal>
+ </goals>
+ <configuration>
+ <portNames>
+ <portName>someNewProperty3</portName>
+ </portNames>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <properties>
+ <aaa>\${someNew<caret>}</aaa>
+ </properties>
+""")
+
+ assertCompletionVariants(myProjectPom, "someNewProperty1", "someNewProperty2")
+ }
+
+}