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.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 */ 038 public class MavenPlugin { 039 040 private Plugin plugin; 041 private Xpp3Dom configuration; 042 043 /** 044 * Creates a MavenPlugin based on a Plugin 045 * 046 * @param plugin the plugin 047 */ 048 public MavenPlugin(Plugin plugin) { 049 this.plugin = plugin; 050 this.configuration = (Xpp3Dom) plugin.getConfiguration(); 051 if (this.configuration == null) { 052 configuration = new Xpp3Dom("configuration"); 053 plugin.setConfiguration(this.configuration); 054 } 055 } 056 057 /** 058 * Creates a Maven plugin based on artifact + group + version 059 * 060 * @param groupId the group id 061 * @param artifactId the artifact id 062 * @param version the version 063 */ 064 public MavenPlugin(String groupId, String artifactId, String version) { 065 this.plugin = new Plugin(); 066 plugin.setGroupId(groupId); 067 plugin.setArtifactId(artifactId); 068 plugin.setVersion(version); 069 configuration = new Xpp3Dom("configuration"); 070 plugin.setConfiguration(this.configuration); 071 } 072 073 /** 074 * Sets the maven plugin version 075 * 076 * @param version the version 077 * @return this 078 */ 079 public MavenPlugin setVersion(String version) { 080 this.plugin.setVersion(version); 081 return this; 082 } 083 084 /** 085 * @return the underlying plugin 086 */ 087 public Plugin getPlugin() { 088 return plugin; 089 } 090 091 /** 092 * Gets a parameter of the plugin based on its key 093 * 094 * @param key the param key 095 * @return the parameter if exist, null otherwise 096 */ 097 public String getParameter(String key) { 098 Xpp3Dom node = findNodeWith(key); 099 return node == null ? null : node.getValue(); 100 } 101 102 /** 103 * Gets a list of parameters of the plugin from a param key 104 * 105 * @param key param key with option-index snippet: e.g. item[0], item[1]. If no index snippet is passed, then 106 * 0 is default (index <=> index[0]) 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 with option-index snippet: e.g. item[0], item[1]. If no index snippet is passed, then 166 * 0 is default (index <=> index[0]) 167 * @param value the param value 168 * @return this 169 */ 170 public MavenPlugin addParameter(String key, String value) { 171 String[] keyParts = StringUtils.split(key, "/"); 172 Xpp3Dom node = configuration; 173 for (int i = 0; i < keyParts.length - 1; i++) { 174 node = getOrCreateChild(node, keyParts[i]); 175 } 176 Xpp3Dom leaf = new Xpp3Dom(keyParts[keyParts.length - 1]); 177 leaf.setValue(value); 178 node.addChild(leaf); 179 return this; 180 } 181 182 private static Xpp3Dom getOrCreateChild(Xpp3Dom node, String key) { 183 int childIndex = getIndex(key); 184 185 if (node.getChildren(removeIndexSnippet(key)).length <= childIndex) { 186 Xpp3Dom child = new Xpp3Dom(removeIndexSnippet(key)); 187 node.addChild(child); 188 return child; 189 } 190 return node.getChildren(removeIndexSnippet(key))[childIndex]; 191 192 } 193 194 private static int getIndex(String key) { 195 //parsing index-syntax (e.g. item[1]) 196 if (key.matches(".*?\\[\\d+\\]")) { 197 return Integer.parseInt(StringUtils.substringBetween(key, "[", "]")); 198 } 199 // for down-compatibility of api we fallback to default 0 200 return 0; 201 } 202 203 private static String removeIndexSnippet(String key) { 204 return StringUtils.substringBefore(key, "["); 205 } 206 207 /** 208 * Remove a parameter from the maven plugin based on its key 209 * 210 * @param key param key with option-index snippet: e.g. item[0], item[1]. If no index snippet is passed, then 211 * 0 is default (index <=> index[0]) 212 */ 213 public void removeParameter(String key) { 214 Xpp3Dom node = findNodeWith(key); 215 if (node != null) { 216 remove(node); 217 } 218 } 219 220 private Xpp3Dom findNodeWith(String key) { 221 checkKeyArgument(key); 222 String[] keyParts = key.split("/"); 223 Xpp3Dom node = configuration; 224 for (String keyPart : keyParts) { 225 226 if(node.getChildren(removeIndexSnippet(keyPart)).length <= getIndex(keyPart)) { 227 return null; 228 } 229 230 node = node.getChildren(removeIndexSnippet(keyPart))[getIndex(keyPart)]; 231 if (node == null) { 232 return null; 233 } 234 } 235 return node; 236 } 237 238 private static void remove(Xpp3Dom node) { 239 Xpp3Dom parent = node.getParent(); 240 for (int i = 0; i < parent.getChildCount(); i++) { 241 Xpp3Dom child = parent.getChild(i); 242 if (child.equals(node)) { 243 parent.removeChild(i); 244 break; 245 } 246 } 247 } 248 249 /** 250 * @return whether the maven plugin has got configuration 251 */ 252 public boolean hasConfiguration() { 253 return configuration.getChildCount()>0; 254 } 255 256 private static void checkKeyArgument(String key) { 257 if (key == null) { 258 throw new IllegalArgumentException("Parameter 'key' should not be null."); 259 } 260 } 261 262 /** 263 * Registers a plugin in a project pom 264 * <p/> 265 * <p>Adds the plugin if it does not exist or amend its version if it does exist and specified</p> 266 * 267 * @param pom the project pom 268 * @param groupId the plugin group id 269 * @param artifactId the plugin artifact id 270 * @param version the plugin version 271 * @param overrideVersion whether to override the version if the plugin is already registered 272 * @return the registered plugin 273 */ 274 public static MavenPlugin registerPlugin(MavenProject pom, String groupId, String artifactId, String version, boolean overrideVersion) { 275 MavenPlugin plugin = getPlugin(pom, groupId, artifactId); 276 if (plugin == null) { 277 plugin = new MavenPlugin(groupId, artifactId, version); 278 279 } else if (overrideVersion) { 280 plugin.setVersion(version); 281 } 282 283 // remove from pom 284 unregisterPlugin(pom, groupId, artifactId); 285 286 // register 287 pom.getBuild().addPlugin(plugin.getPlugin()); 288 289 return plugin; 290 } 291 292 /** 293 * Returns a plugin from a pom based on its group id and artifact id 294 * <p/> 295 * <p>It searches in the build section, then the reporting section and finally the pluginManagement section</p> 296 * 297 * @param pom the project pom 298 * @param groupId the plugin group id 299 * @param artifactId the plugin artifact id 300 * @return the plugin if it exists, null otherwise 301 */ 302 public static MavenPlugin getPlugin(MavenProject pom, String groupId, String artifactId) { 303 if (pom == null) { 304 return null; 305 } 306 // look for plugin in <build> section 307 Plugin plugin = null; 308 if (pom.getBuildPlugins() != null) { 309 plugin = getPlugin(pom.getBuildPlugins(), groupId, artifactId); 310 } 311 312 // look for plugin in <report> section 313 if (plugin == null && pom.getReportPlugins() != null) { 314 plugin = getReportPlugin(pom.getReportPlugins(), groupId, artifactId); 315 } 316 317 // look for plugin in <pluginManagement> section 318 if (pom.getPluginManagement() != null) { 319 Plugin pluginManagement = getPlugin(pom.getPluginManagement().getPlugins(), groupId, artifactId); 320 if (plugin == null) { 321 plugin = pluginManagement; 322 323 } else if (pluginManagement != null) { 324 if (pluginManagement.getConfiguration() != null) { 325 if (plugin.getConfiguration() == null) { 326 plugin.setConfiguration(pluginManagement.getConfiguration()); 327 } else { 328 Xpp3Dom.mergeXpp3Dom((Xpp3Dom) plugin.getConfiguration(), (Xpp3Dom) pluginManagement.getConfiguration()); 329 } 330 } 331 if (plugin.getDependencies() == null && pluginManagement.getDependencies() != null) { 332 plugin.setDependencies(pluginManagement.getDependencies()); 333 } 334 if (plugin.getVersion() == null) { 335 plugin.setVersion(pluginManagement.getVersion()); 336 } 337 } 338 } 339 340 if (plugin != null) { 341 return new MavenPlugin(plugin); 342 } 343 return null; 344 } 345 346 private static Plugin getPlugin(Collection<Plugin> plugins, String groupId, String artifactId) { 347 if (plugins == null) { 348 return null; 349 } 350 351 for (Plugin plugin : plugins) { 352 if (MavenUtils.equals(plugin, groupId, artifactId)) { 353 return plugin; 354 } 355 } 356 return null; 357 } 358 359 private static Plugin getReportPlugin(Collection<ReportPlugin> plugins, String groupId, String artifactId) { 360 if (plugins == null) { 361 return null; 362 } 363 364 for (ReportPlugin plugin : plugins) { 365 if (MavenUtils.equals(plugin, groupId, artifactId)) { 366 return cloneReportPluginToPlugin(plugin); 367 } 368 } 369 return null; 370 } 371 372 private static Plugin cloneReportPluginToPlugin(ReportPlugin reportPlugin) { 373 Plugin plugin = new Plugin(); 374 plugin.setGroupId(reportPlugin.getGroupId()); 375 plugin.setArtifactId(reportPlugin.getArtifactId()); 376 plugin.setVersion(reportPlugin.getVersion()); 377 plugin.setConfiguration(reportPlugin.getConfiguration()); 378 return plugin; 379 } 380 381 private static void unregisterPlugin(MavenProject pom, String groupId, String artifactId) { 382 if (pom.getPluginManagement() != null && pom.getPluginManagement().getPlugins() != null) { 383 unregisterPlugin(pom.getPluginManagement().getPlugins(), groupId, artifactId); 384 } 385 if (pom.getBuildPlugins() != null && pom.getBuildPlugins() != null) { 386 unregisterPlugin(pom.getBuildPlugins(), groupId, artifactId); 387 } 388 if (pom.getReportPlugins() != null) { 389 unregisterReportPlugin(pom.getReportPlugins(), groupId, artifactId); 390 } 391 } 392 393 private static void unregisterPlugin(List<Plugin> plugins, String groupId, String artifactId) { 394 for (Iterator<Plugin> iterator = plugins.iterator(); iterator.hasNext();) { 395 Plugin p = iterator.next(); 396 if (MavenUtils.equals(p, groupId, artifactId)) { 397 iterator.remove(); 398 } 399 } 400 } 401 402 private static void unregisterReportPlugin(List<ReportPlugin> plugins, String groupId, String artifactId) { 403 for (Iterator<ReportPlugin> iterator = plugins.iterator(); iterator.hasNext();) { 404 ReportPlugin p = iterator.next(); 405 if (MavenUtils.equals(p, groupId, artifactId)) { 406 iterator.remove(); 407 } 408 } 409 } 410 411 412 @Override 413 public String toString() { 414 return new ToStringBuilder(this) 415 .append("groupId", plugin.getGroupId()) 416 .append("artifactId", plugin.getArtifactId()) 417 .append("version", plugin.getVersion()) 418 .toString(); 419 } 420 }