001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar 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 * Sonar 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
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
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.Dependency;
025 import org.apache.maven.model.Plugin;
026 import org.apache.maven.model.ReportPlugin;
027 import org.apache.maven.project.MavenProject;
028 import org.codehaus.plexus.util.xml.Xpp3Dom;
029
030 import java.util.Collection;
031 import java.util.Iterator;
032 import java.util.List;
033
034 /**
035 * A class to handle maven plugins
036 *
037 * @since 1.10
038 */
039 public class MavenPlugin {
040
041 private Plugin plugin;
042 private Xpp3Dom configuration;
043
044 /**
045 * Creates a MavenPlugin based on a Plugin
046 *
047 * @param plugin the plugin
048 */
049 public MavenPlugin(Plugin plugin) {
050 this.plugin = plugin;
051 this.configuration = (Xpp3Dom) plugin.getConfiguration();
052 if (this.configuration == null) {
053 configuration = new Xpp3Dom("configuration");
054 plugin.setConfiguration(this.configuration);
055 }
056 }
057
058 /**
059 * Creates a Maven plugin based on artifact + group + version
060 *
061 * @param groupId the group id
062 * @param artifactId the artifact id
063 * @param version the version
064 */
065 public MavenPlugin(String groupId, String artifactId, String version) {
066 this.plugin = new Plugin();
067 plugin.setGroupId(groupId);
068 plugin.setArtifactId(artifactId);
069 plugin.setVersion(version);
070 configuration = new Xpp3Dom("configuration");
071 plugin.setConfiguration(this.configuration);
072 }
073
074 /**
075 * Sets the maven plugin version
076 *
077 * @param version the version
078 * @return this
079 */
080 public MavenPlugin setVersion(String version) {
081 this.plugin.setVersion(version);
082 return this;
083 }
084
085 /**
086 * @return the underlying plugin
087 */
088 public Plugin getPlugin() {
089 return plugin;
090 }
091
092 /**
093 * Gets a parameter of the plugin based on its key
094 *
095 * @param key the param key
096 * @return the parameter if exist, null otherwise
097 */
098 public String getParameter(String key) {
099 Xpp3Dom node = findNodeWith(key);
100 return node == null ? null : node.getValue();
101 }
102
103 /**
104 * Gets a list of parameters of the plugin from a param key
105 *
106 * @param key the param key
107 * @return an array of parameters if any, an empty array otherwise
108 */
109 public String[] getParameters(String key) {
110 String[] keyParts = StringUtils.split(key, "/");
111 Xpp3Dom node = configuration;
112 for (int i = 0; i < keyParts.length - 1; i++) {
113 node = getOrCreateChild(node, keyParts[i]);
114 }
115 Xpp3Dom[] children = node.getChildren(keyParts[keyParts.length - 1]);
116 String[] result = new String[children.length];
117 for (int i = 0; i < children.length; i++) {
118 result[i] = children[i].getValue();
119 }
120 return result;
121 }
122
123 /**
124 * Sets a parameter for the maven plugin. This will overrides an existing parameter.
125 *
126 * @param key the param key
127 * @param value the param value
128 * @return this
129 */
130 public MavenPlugin setParameter(String key, String value) {
131 checkKeyArgument(key);
132 String[] keyParts = StringUtils.split(key, "/");
133 Xpp3Dom node = configuration;
134 for (String keyPart : keyParts) {
135 node = getOrCreateChild(node, keyPart);
136 }
137 node.setValue(value);
138 return this;
139 }
140
141 /**
142 * Sets a parameter to the maven plugin. Overrides existing parameter only id specified.
143 *
144 * @param key the param key
145 * @param value the param value
146 * @param override whether to override existing parameter
147 */
148 public void setParameter(String key, String value, boolean override) {
149 if (getParameter(key) == null || override) {
150 setParameter(key, value);
151 }
152 }
153
154 /**
155 * Removes all parameters from the maven plugin
156 */
157 public void removeParameters() {
158 configuration = new Xpp3Dom("configuration");
159 plugin.setConfiguration(this.configuration);
160 }
161
162 /**
163 * Adds a parameter to the maven plugin
164 *
165 * @param key the param key
166 * @param value the param value
167 * @return this
168 */
169 public MavenPlugin addParameter(String key, String value) {
170 String[] keyParts = StringUtils.split(key, "/");
171 Xpp3Dom node = configuration;
172 for (int i = 0; i < keyParts.length - 1; i++) {
173 node = getOrCreateChild(node, keyParts[i]);
174 }
175 Xpp3Dom leaf = new Xpp3Dom(keyParts[keyParts.length - 1]);
176 leaf.setValue(value);
177 node.addChild(leaf);
178 return this;
179 }
180
181 private static Xpp3Dom getOrCreateChild(Xpp3Dom node, String key) {
182 Xpp3Dom child = node.getChild(key);
183 if (child == null) {
184 child = new Xpp3Dom(key);
185 node.addChild(child);
186 }
187 return child;
188 }
189
190 /**
191 * Remove a parameter from the maven plugin based on its key
192 *
193 * @param key the param key
194 */
195 public void removeParameter(String key) {
196 Xpp3Dom node = findNodeWith(key);
197 if (node != null) {
198 remove(node);
199 }
200 }
201
202 private Xpp3Dom findNodeWith(String key) {
203 checkKeyArgument(key);
204 String[] keyParts = key.split("/");
205 Xpp3Dom node = configuration;
206 for (String keyPart : keyParts) {
207 node = node.getChild(keyPart);
208 if (node == null) {
209 return null;
210 }
211 }
212 return node;
213 }
214
215 private static void remove(Xpp3Dom node) {
216 Xpp3Dom parent = node.getParent();
217 for (int i = 0; i < parent.getChildCount(); i++) {
218 Xpp3Dom child = parent.getChild(i);
219 if (child.equals(node)) {
220 parent.removeChild(i);
221 break;
222 }
223 }
224 }
225
226 /**
227 * @return whether the maven plugin has got configuration
228 */
229 public boolean hasConfiguration() {
230 return configuration.getChildCount()>0;
231 }
232
233 private static void checkKeyArgument(String key) {
234 if (key == null) {
235 throw new IllegalArgumentException("Parameter 'key' should not be null.");
236 }
237 }
238
239 /**
240 * Registers a plugin in a project pom
241 * <p/>
242 * <p>Adds the plugin if it does not exist or amend its version if it does exist and specified</p>
243 *
244 * @param pom the project pom
245 * @param groupId the plugin group id
246 * @param artifactId the plugin artifact id
247 * @param version the plugin version
248 * @param overrideVersion whether to override the version if the plugin is already registered
249 * @return the registered plugin
250 */
251 public static MavenPlugin registerPlugin(MavenProject pom, String groupId, String artifactId, String version, boolean overrideVersion) {
252 MavenPlugin plugin = getPlugin(pom, groupId, artifactId);
253 if (plugin == null) {
254 plugin = new MavenPlugin(groupId, artifactId, version);
255
256 } else if (overrideVersion) {
257 plugin.setVersion(version);
258 }
259
260 // remove from pom
261 unregisterPlugin(pom, groupId, artifactId);
262
263 // register
264 pom.getBuild().addPlugin(plugin.getPlugin());
265
266 return plugin;
267 }
268
269 /**
270 * Returns a plugin from a pom based on its group id and artifact id
271 * <p/>
272 * <p>It searches in the build section, then the reporting section and finally the pluginManagement section</p>
273 *
274 * @param pom the project pom
275 * @param groupId the plugin group id
276 * @param artifactId the plugin artifact id
277 * @return the plugin if it exists, null otherwise
278 */
279 public static MavenPlugin getPlugin(MavenProject pom, String groupId, String artifactId) {
280 if (pom == null) {
281 return null;
282 }
283 // look for plugin in <build> section
284 Plugin plugin = null;
285 if (pom.getBuildPlugins() != null) {
286 plugin = getPlugin(pom.getBuildPlugins(), groupId, artifactId);
287 }
288
289 // look for plugin in <report> section
290 if (plugin == null && pom.getReportPlugins() != null) {
291 plugin = getReportPlugin(pom.getReportPlugins(), groupId, artifactId);
292 }
293
294 // look for plugin in <pluginManagement> section
295 if (pom.getPluginManagement() != null) {
296 Plugin pluginManagement = getPlugin(pom.getPluginManagement().getPlugins(), groupId, artifactId);
297 if (plugin == null) {
298 plugin = pluginManagement;
299
300 } else if (pluginManagement != null) {
301 if (pluginManagement.getConfiguration() != null) {
302 if (plugin.getConfiguration() == null) {
303 plugin.setConfiguration(pluginManagement.getConfiguration());
304 } else {
305 Xpp3Dom.mergeXpp3Dom((Xpp3Dom) plugin.getConfiguration(), (Xpp3Dom) pluginManagement.getConfiguration());
306 }
307 }
308 if (plugin.getDependencies() == null && pluginManagement.getDependencies() != null) {
309 plugin.setDependencies(pluginManagement.getDependencies());
310 }
311 if (plugin.getVersion() == null) {
312 plugin.setVersion(pluginManagement.getVersion());
313 }
314 }
315 }
316
317 if (plugin != null) {
318 return new MavenPlugin(plugin);
319 }
320 return null;
321 }
322
323 private static Plugin getPlugin(Collection<Plugin> plugins, String groupId, String artifactId) {
324 if (plugins == null) {
325 return null;
326 }
327
328 for (Plugin plugin : plugins) {
329 if (MavenUtils.equals(plugin, groupId, artifactId)) {
330 return plugin;
331 }
332 }
333 return null;
334 }
335
336 private static Plugin getReportPlugin(Collection<ReportPlugin> plugins, String groupId, String artifactId) {
337 if (plugins == null) {
338 return null;
339 }
340
341 for (ReportPlugin plugin : plugins) {
342 if (MavenUtils.equals(plugin, groupId, artifactId)) {
343 return cloneReportPluginToPlugin(plugin);
344 }
345 }
346 return null;
347 }
348
349 private static Plugin cloneReportPluginToPlugin(ReportPlugin reportPlugin) {
350 Plugin plugin = new Plugin();
351 plugin.setGroupId(reportPlugin.getGroupId());
352 plugin.setArtifactId(reportPlugin.getArtifactId());
353 plugin.setVersion(reportPlugin.getVersion());
354 plugin.setConfiguration(reportPlugin.getConfiguration());
355 return plugin;
356 }
357
358 private static void unregisterPlugin(MavenProject pom, String groupId, String artifactId) {
359 if (pom.getPluginManagement() != null && pom.getPluginManagement().getPlugins() != null) {
360 unregisterPlugin(pom.getPluginManagement().getPlugins(), groupId, artifactId);
361 }
362 if (pom.getBuildPlugins() != null && pom.getBuildPlugins() != null) {
363 unregisterPlugin(pom.getBuildPlugins(), groupId, artifactId);
364 }
365 if (pom.getReportPlugins() != null) {
366 unregisterReportPlugin(pom.getReportPlugins(), groupId, artifactId);
367 }
368 }
369
370 private static void unregisterPlugin(List<Plugin> plugins, String groupId, String artifactId) {
371 for (Iterator<Plugin> iterator = plugins.iterator(); iterator.hasNext();) {
372 Plugin p = iterator.next();
373 if (MavenUtils.equals(p, groupId, artifactId)) {
374 iterator.remove();
375 }
376 }
377 }
378
379 private static void unregisterReportPlugin(List<ReportPlugin> plugins, String groupId, String artifactId) {
380 for (Iterator<ReportPlugin> iterator = plugins.iterator(); iterator.hasNext();) {
381 ReportPlugin p = iterator.next();
382 if (MavenUtils.equals(p, groupId, artifactId)) {
383 iterator.remove();
384 }
385 }
386 }
387
388
389 @Override
390 public String toString() {
391 return new ToStringBuilder(this)
392 .append("groupId", plugin.getGroupId())
393 .append("artifactId", plugin.getArtifactId())
394 .append("version", plugin.getVersion())
395 .toString();
396 }
397 }