001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2014 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * SonarQube is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.api.batch.maven;
021
022 import org.apache.commons.lang.StringUtils;
023 import org.apache.commons.lang.builder.ToStringBuilder;
024 import org.apache.maven.model.Plugin;
025 import org.apache.maven.model.ReportPlugin;
026 import org.apache.maven.project.MavenProject;
027 import org.codehaus.plexus.util.xml.Xpp3Dom;
028
029 import java.util.Collection;
030 import java.util.Iterator;
031 import java.util.List;
032
033 /**
034 * A class to handle maven plugins
035 *
036 * @since 1.10
037 * @deprecated since 4.5 we don't want any dependency on Maven anymore
038 */
039 @Deprecated
040 public class MavenPlugin {
041
042 private static final String CONFIGURATION_ELEMENT = "configuration";
043 private Plugin plugin;
044 private Xpp3Dom configuration;
045
046 /**
047 * Creates a MavenPlugin based on a Plugin
048 *
049 * @param plugin the plugin
050 */
051 public MavenPlugin(Plugin plugin) {
052 this.plugin = plugin;
053 this.configuration = (Xpp3Dom) plugin.getConfiguration();
054 if (this.configuration == null) {
055 configuration = new Xpp3Dom(CONFIGURATION_ELEMENT);
056 plugin.setConfiguration(this.configuration);
057 }
058 }
059
060 /**
061 * Creates a Maven plugin based on artifact + group + version
062 *
063 * @param groupId the group id
064 * @param artifactId the artifact id
065 * @param version the version
066 */
067 public MavenPlugin(String groupId, String artifactId, String version) {
068 this.plugin = new Plugin();
069 plugin.setGroupId(groupId);
070 plugin.setArtifactId(artifactId);
071 plugin.setVersion(version);
072 configuration = new Xpp3Dom(CONFIGURATION_ELEMENT);
073 plugin.setConfiguration(this.configuration);
074 }
075
076 /**
077 * @since 3.5 - see SONAR-4070
078 * @return the XML node <configuration> of pom
079 */
080 public Xpp3Dom getConfigurationXmlNode() {
081 return configuration;
082 }
083
084 /**
085 * Sets the maven plugin version
086 *
087 * @param version the version
088 * @return this
089 */
090 public MavenPlugin setVersion(String version) {
091 this.plugin.setVersion(version);
092 return this;
093 }
094
095 /**
096 * @return the underlying plugin
097 */
098 public Plugin getPlugin() {
099 return plugin;
100 }
101
102 /**
103 * Gets a parameter of the plugin based on its key
104 *
105 * @param key the param key
106 * @return the parameter if exist, null otherwise
107 */
108 public String getParameter(String key) {
109 Xpp3Dom node = findNodeWith(key);
110 return node == null ? null : node.getValue();
111 }
112
113 /**
114 * Gets a list of parameters of the plugin from a param key
115 *
116 * @param key param key with option-index snippet: e.g. item[0], item[1]. If no index snippet is passed, then
117 * 0 is default (index <=> index[0])
118 * @return an array of parameters if any, an empty array otherwise
119 */
120 public String[] getParameters(String key) {
121 String[] keyParts = StringUtils.split(key, "/");
122 Xpp3Dom node = configuration;
123 for (int i = 0; i < keyParts.length - 1; i++) {
124 node = getOrCreateChild(node, keyParts[i]);
125 }
126 Xpp3Dom[] children = node.getChildren(keyParts[keyParts.length - 1]);
127 String[] result = new String[children.length];
128 for (int i = 0; i < children.length; i++) {
129 result[i] = children[i].getValue();
130 }
131 return result;
132 }
133
134 /**
135 * Sets a parameter for the maven plugin. This will overrides an existing parameter.
136 *
137 * @param key the param key
138 * @param value the param value
139 * @return this
140 */
141 public MavenPlugin setParameter(String key, String value) {
142 checkKeyArgument(key);
143 String[] keyParts = StringUtils.split(key, "/");
144 Xpp3Dom node = configuration;
145 for (String keyPart : keyParts) {
146 node = getOrCreateChild(node, keyPart);
147 }
148 node.setValue(value);
149 return this;
150 }
151
152 /**
153 * Sets a parameter to the maven plugin. Overrides existing parameter only id specified.
154 *
155 * @param key the param key
156 * @param value the param value
157 * @param override whether to override existing parameter
158 */
159 public void setParameter(String key, String value, boolean override) {
160 if (getParameter(key) == null || override) {
161 setParameter(key, value);
162 }
163 }
164
165 /**
166 * Removes all parameters from the maven plugin
167 */
168 public void removeParameters() {
169 configuration = new Xpp3Dom(CONFIGURATION_ELEMENT);
170 plugin.setConfiguration(this.configuration);
171 }
172
173 /**
174 * Adds a parameter to the maven plugin
175 *
176 * @param key the param key with option-index snippet: e.g. item[0], item[1]. If no index snippet is passed, then
177 * 0 is default (index <=> index[0])
178 * @param value the param value
179 * @return this
180 */
181 public MavenPlugin addParameter(String key, String value) {
182 String[] keyParts = StringUtils.split(key, "/");
183 Xpp3Dom node = configuration;
184 for (int i = 0; i < keyParts.length - 1; i++) {
185 node = getOrCreateChild(node, keyParts[i]);
186 }
187 Xpp3Dom leaf = new Xpp3Dom(keyParts[keyParts.length - 1]);
188 leaf.setValue(value);
189 node.addChild(leaf);
190 return this;
191 }
192
193 private static Xpp3Dom getOrCreateChild(Xpp3Dom node, String key) {
194 int childIndex = getIndex(key);
195
196 if (node.getChildren(removeIndexSnippet(key)).length <= childIndex) {
197 Xpp3Dom child = new Xpp3Dom(removeIndexSnippet(key));
198 node.addChild(child);
199 return child;
200 }
201 return node.getChildren(removeIndexSnippet(key))[childIndex];
202
203 }
204
205 private static int getIndex(String key) {
206 // parsing index-syntax (e.g. item[1])
207 if (key.matches(".*?\\[\\d+\\]")) {
208 return Integer.parseInt(StringUtils.substringBetween(key, "[", "]"));
209 }
210 // for down-compatibility of api we fallback to default 0
211 return 0;
212 }
213
214 private static String removeIndexSnippet(String key) {
215 return StringUtils.substringBefore(key, "[");
216 }
217
218 /**
219 * Remove a parameter from the maven plugin based on its key
220 *
221 * @param key param key with option-index snippet: e.g. item[0], item[1]. If no index snippet is passed, then
222 * 0 is default (index <=> index[0])
223 */
224 public void removeParameter(String key) {
225 Xpp3Dom node = findNodeWith(key);
226 if (node != null) {
227 remove(node);
228 }
229 }
230
231 private Xpp3Dom findNodeWith(String key) {
232 checkKeyArgument(key);
233 String[] keyParts = key.split("/");
234 Xpp3Dom node = configuration;
235 for (String keyPart : keyParts) {
236
237 if (node.getChildren(removeIndexSnippet(keyPart)).length <= getIndex(keyPart)) {
238 return null;
239 }
240
241 node = node.getChildren(removeIndexSnippet(keyPart))[getIndex(keyPart)];
242 if (node == null) {
243 return null;
244 }
245 }
246 return node;
247 }
248
249 private static void remove(Xpp3Dom node) {
250 Xpp3Dom parent = node.getParent();
251 for (int i = 0; i < parent.getChildCount(); i++) {
252 Xpp3Dom child = parent.getChild(i);
253 if (child.equals(node)) {
254 parent.removeChild(i);
255 break;
256 }
257 }
258 }
259
260 /**
261 * @return whether the maven plugin has got configuration
262 */
263 public boolean hasConfiguration() {
264 return configuration.getChildCount() > 0;
265 }
266
267 private static void checkKeyArgument(String key) {
268 if (key == null) {
269 throw new IllegalArgumentException("Parameter 'key' should not be null.");
270 }
271 }
272
273 /**
274 * Registers a plugin in a project pom
275 * <p/>
276 * <p>Adds the plugin if it does not exist or amend its version if it does exist and specified</p>
277 *
278 * @param pom the project pom
279 * @param groupId the plugin group id
280 * @param artifactId the plugin artifact id
281 * @param version the plugin version
282 * @param overrideVersion whether to override the version if the plugin is already registered
283 * @return the registered plugin
284 */
285 public static MavenPlugin registerPlugin(MavenProject pom, String groupId, String artifactId, String version, boolean overrideVersion) {
286 MavenPlugin plugin = getPlugin(pom, groupId, artifactId);
287 if (plugin == null) {
288 plugin = new MavenPlugin(groupId, artifactId, version);
289
290 } else if (overrideVersion) {
291 plugin.setVersion(version);
292 }
293
294 // remove from pom
295 unregisterPlugin(pom, groupId, artifactId);
296
297 // register
298 pom.getBuild().addPlugin(plugin.getPlugin());
299
300 return plugin;
301 }
302
303 /**
304 * Returns a plugin from a pom based on its group id and artifact id
305 * <p/>
306 * <p>It searches in the build section, then the reporting section and finally the pluginManagement section</p>
307 *
308 * @param pom the project pom
309 * @param groupId the plugin group id
310 * @param artifactId the plugin artifact id
311 * @return the plugin if it exists, null otherwise
312 */
313 public static MavenPlugin getPlugin(MavenProject pom, String groupId, String artifactId) {
314 if (pom == null) {
315 return null;
316 }
317 // look for plugin in <build> section
318 Plugin plugin = null;
319 if (pom.getBuildPlugins() != null) {
320 plugin = getPlugin(pom.getBuildPlugins(), groupId, artifactId);
321 }
322
323 // look for plugin in <report> section
324 if (plugin == null && pom.getReportPlugins() != null) {
325 plugin = getReportPlugin(pom.getReportPlugins(), groupId, artifactId);
326 }
327
328 // look for plugin in <pluginManagement> section
329 if (pom.getPluginManagement() != null) {
330 Plugin pluginManagement = getPlugin(pom.getPluginManagement().getPlugins(), groupId, artifactId);
331 if (plugin == null) {
332 plugin = pluginManagement;
333
334 } else if (pluginManagement != null) {
335 if (pluginManagement.getConfiguration() != null) {
336 if (plugin.getConfiguration() == null) {
337 plugin.setConfiguration(pluginManagement.getConfiguration());
338 } else {
339 Xpp3Dom.mergeXpp3Dom((Xpp3Dom) plugin.getConfiguration(), (Xpp3Dom) pluginManagement.getConfiguration());
340 }
341 }
342 if (plugin.getDependencies() == null && pluginManagement.getDependencies() != null) {
343 plugin.setDependencies(pluginManagement.getDependencies());
344 }
345 if (plugin.getVersion() == null) {
346 plugin.setVersion(pluginManagement.getVersion());
347 }
348 }
349 }
350
351 if (plugin != null) {
352 return new MavenPlugin(plugin);
353 }
354 return null;
355 }
356
357 private static Plugin getPlugin(Collection<Plugin> plugins, String groupId, String artifactId) {
358 if (plugins == null) {
359 return null;
360 }
361
362 for (Plugin plugin : plugins) {
363 if (MavenUtils.equals(plugin, groupId, artifactId)) {
364 return plugin;
365 }
366 }
367 return null;
368 }
369
370 private static Plugin getReportPlugin(Collection<ReportPlugin> plugins, String groupId, String artifactId) {
371 if (plugins == null) {
372 return null;
373 }
374
375 for (ReportPlugin plugin : plugins) {
376 if (MavenUtils.equals(plugin, groupId, artifactId)) {
377 return cloneReportPluginToPlugin(plugin);
378 }
379 }
380 return null;
381 }
382
383 private static Plugin cloneReportPluginToPlugin(ReportPlugin reportPlugin) {
384 Plugin plugin = new Plugin();
385 plugin.setGroupId(reportPlugin.getGroupId());
386 plugin.setArtifactId(reportPlugin.getArtifactId());
387 plugin.setVersion(reportPlugin.getVersion());
388 plugin.setConfiguration(reportPlugin.getConfiguration());
389 return plugin;
390 }
391
392 private static void unregisterPlugin(MavenProject pom, String groupId, String artifactId) {
393 if (pom.getPluginManagement() != null && pom.getPluginManagement().getPlugins() != null) {
394 unregisterPlugin(pom.getPluginManagement().getPlugins(), groupId, artifactId);
395 }
396 if (pom.getBuildPlugins() != null && pom.getBuildPlugins() != null) {
397 unregisterPlugin(pom.getBuildPlugins(), groupId, artifactId);
398 }
399 if (pom.getReportPlugins() != null) {
400 unregisterReportPlugin(pom.getReportPlugins(), groupId, artifactId);
401 }
402 }
403
404 private static void unregisterPlugin(List<Plugin> plugins, String groupId, String artifactId) {
405 for (Iterator<Plugin> iterator = plugins.iterator(); iterator.hasNext();) {
406 Plugin p = iterator.next();
407 if (MavenUtils.equals(p, groupId, artifactId)) {
408 iterator.remove();
409 }
410 }
411 }
412
413 private static void unregisterReportPlugin(List<ReportPlugin> plugins, String groupId, String artifactId) {
414 for (Iterator<ReportPlugin> iterator = plugins.iterator(); iterator.hasNext();) {
415 ReportPlugin p = iterator.next();
416 if (MavenUtils.equals(p, groupId, artifactId)) {
417 iterator.remove();
418 }
419 }
420 }
421
422 @Override
423 public String toString() {
424 return new ToStringBuilder(this)
425 .append("groupId", plugin.getGroupId())
426 .append("artifactId", plugin.getArtifactId())
427 .append("version", plugin.getVersion())
428 .toString();
429 }
430 }