001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package org.apache.geronimo.genesis; 021 022 import java.io.File; 023 import java.util.ArrayList; 024 import java.util.HashSet; 025 import java.util.Iterator; 026 import java.util.List; 027 import java.util.Set; 028 import java.util.Collections; 029 030 import org.apache.maven.artifact.Artifact; 031 import org.apache.maven.artifact.factory.ArtifactFactory; 032 import org.apache.maven.artifact.repository.ArtifactRepository; 033 import org.apache.maven.artifact.resolver.ArtifactNotFoundException; 034 import org.apache.maven.artifact.resolver.ArtifactResolutionException; 035 import org.apache.maven.artifact.resolver.ArtifactResolver; 036 import org.apache.maven.artifact.resolver.filter.ArtifactFilter; 037 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter; 038 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 039 import org.apache.maven.artifact.versioning.VersionRange; 040 import org.apache.maven.model.Dependency; 041 import org.apache.maven.model.Exclusion; 042 import org.apache.maven.plugin.AbstractMojo; 043 import org.apache.maven.plugin.MojoExecutionException; 044 import org.apache.maven.plugin.MojoFailureException; 045 import org.apache.maven.plugin.logging.Log; 046 import org.apache.maven.project.MavenProject; 047 import org.codehaus.plexus.PlexusConstants; 048 import org.codehaus.plexus.PlexusContainer; 049 import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 050 import org.codehaus.plexus.context.Context; 051 import org.codehaus.plexus.context.ContextException; 052 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Contextualizable; 053 054 import org.apache.geronimo.genesis.dependency.DependencyHelper; 055 import org.apache.geronimo.genesis.util.ArtifactItem; 056 import org.apache.geronimo.genesis.logging.MavenPluginLog; 057 import org.apache.geronimo.genesis.logging.Logging; 058 import org.apache.geronimo.genesis.logging.DelegatingLog; 059 060 /** 061 * Support for Mojo implementations. 062 * 063 * @version $Rev: 470159 $ $Date: 2006-11-01 17:19:16 -0800 (Wed, 01 Nov 2006) $ 064 */ 065 public abstract class MojoSupport 066 extends AbstractMojo 067 implements Contextualizable 068 { 069 protected PlexusContainer container; 070 071 /** 072 * Instance logger. This is initialized to the value of {@link #getLog} 073 * on execution. 074 */ 075 protected Log log; 076 077 private DependencyHelper dependencyHelper; 078 079 protected MojoSupport() { 080 // Need to init our logging support before components are initialized and attached 081 Logging.init(); 082 } 083 084 /** 085 * Initializes logging. Called by {@link #execute}. 086 * 087 * @throws MojoExecutionException Initialization failed 088 * @throws MojoFailureException Initialization failed 089 */ 090 protected void init() throws MojoExecutionException, MojoFailureException { 091 this.log = getLog(); 092 093 // Install the bridge from JCL to this plugins Log 094 MavenPluginLog.setMojo(this); 095 DelegatingLog.setDelegateType(MavenPluginLog.class); 096 097 // 098 // NOTE: Using direct lookup because this class may not have been directly configured 099 // 100 try { 101 this.dependencyHelper = (DependencyHelper)container.lookup(DependencyHelper.class.getName()); 102 } 103 catch (ComponentLookupException e) { 104 throw new MojoExecutionException("Failed to lookup required components", e); 105 } 106 } 107 108 public void contextualize(final Context context) throws ContextException { 109 container = (PlexusContainer) context.get(PlexusConstants.PLEXUS_KEY); 110 } 111 112 /** 113 * Main Mojo execution hook. Sub-class should use {@link #doExecute} instead. 114 * 115 * @throws MojoExecutionException 116 * @throws MojoFailureException 117 */ 118 public void execute() throws MojoExecutionException, MojoFailureException { 119 init(); 120 121 try { 122 doExecute(); 123 } 124 catch (Exception e) { 125 // 126 // NOTE: Wrap to avoid truncating the stacktrace 127 // 128 if (e instanceof MojoExecutionException) { 129 throw new MojoExecutionException(e.getMessage(), e); 130 } 131 else if (e instanceof MojoFailureException) { 132 MojoFailureException x = new MojoFailureException(e.getMessage()); 133 x.initCause(e); 134 throw x; 135 } 136 else { 137 throw new MojoExecutionException(e.getMessage(), e); 138 } 139 } 140 finally { 141 // Reset logging after we are done to avoid complications with other plugins using JCL 142 Logging.reset(); 143 } 144 } 145 146 /** 147 * Sub-class should override to provide custom execution logic. 148 * 149 * @throws Exception Execution failed 150 */ 151 protected void doExecute() throws Exception { 152 // Empty 153 } 154 155 // 156 // NOTE: These are not abstract because not all sub-classes will need this functionality 157 // 158 159 /** 160 * Get the Maven project. 161 * 162 * <p> 163 * Sub-class must overridde to provide access. 164 * </p> 165 * 166 * @return The maven project; never null 167 */ 168 protected MavenProject getProject() { 169 throw new Error("Sub-class must override to provide access to : " + MavenProject.class); 170 } 171 172 /** 173 * Get the artifact repository. 174 * 175 * <p> 176 * Sub-class must overridde to provide access. 177 * </p> 178 * 179 * @return An artifact repository; never null 180 */ 181 protected ArtifactRepository getArtifactRepository() { 182 throw new Error("Sub-class must override to provide access to: " + ArtifactRepository.class); 183 } 184 185 /** 186 * Get the artifact factory. 187 * 188 * @return An artifact factory; never null 189 */ 190 protected final ArtifactFactory getArtifactFactory() { 191 return dependencyHelper.getArtifactFactory(); 192 } 193 194 /** 195 * Get the artifact resolver. 196 * 197 * @return An artifact resolver; never null 198 */ 199 protected final ArtifactResolver getArtifactResolver() { 200 return dependencyHelper.getArtifactResolver(); 201 } 202 203 /** 204 * Create a new artifact. If no version is specified, it will be retrieved from the dependency 205 * list or from the DependencyManagement section of the pom. 206 * 207 * @param item The item to create an artifact for 208 * @return An unresolved artifact for the given item. 209 * 210 * @throws MojoExecutionException Failed to create artifact 211 */ 212 protected Artifact createArtifact(final ArtifactItem item) throws MojoExecutionException { 213 assert item != null; 214 215 if (item.getVersion() == null) { 216 fillMissingArtifactVersion(item); 217 218 if (item.getVersion() == null) { 219 throw new MojoExecutionException("Unable to find artifact version of " + item.getGroupId() 220 + ":" + item.getArtifactId() + " in either dependency list or in project's dependency management."); 221 } 222 } 223 224 // Convert the string version to a range 225 VersionRange range; 226 try { 227 range = VersionRange.createFromVersionSpec(item.getVersion()); 228 if (log.isDebugEnabled()) { 229 log.debug("Using version range: " + range); 230 } 231 } 232 catch (InvalidVersionSpecificationException e) { 233 throw new MojoExecutionException("Could not create range for version: " + item.getVersion(), e); 234 } 235 236 return getArtifactFactory().createDependencyArtifact( 237 item.getGroupId(), 238 item.getArtifactId(), 239 range, 240 item.getType(), 241 item.getClassifier(), 242 Artifact.SCOPE_PROVIDED); 243 } 244 245 /** 246 * Resolves the Artifact from the remote repository if nessessary. If no version is specified, it will 247 * be retrieved from the dependency list or from the DependencyManagement section of the pom. 248 * 249 * 250 * @param item The item to create an artifact for; must not be null 251 * @return The artifact for the given item 252 * 253 * @throws MojoExecutionException Failed to create artifact 254 */ 255 protected Artifact getArtifact(final ArtifactItem item) throws MojoExecutionException { 256 assert item != null; 257 258 Artifact artifact = createArtifact(item); 259 260 return resolveArtifact(artifact); 261 } 262 263 /** 264 * Resolves the Artifact from the remote repository if nessessary. If no version is specified, it will 265 * be retrieved from the dependency list or from the DependencyManagement section of the pom. 266 * 267 * @param artifact The artifact to be resolved; must not be null 268 * @param transitive True to resolve the artifact transitivly 269 * @return The resolved artifact; never null 270 * 271 * @throws MojoExecutionException Failed to resolve artifact 272 */ 273 protected Artifact resolveArtifact(final Artifact artifact, final boolean transitive) throws MojoExecutionException { 274 assert artifact != null; 275 276 try { 277 if (transitive) { 278 getArtifactResolver().resolveTransitively( 279 Collections.singleton(artifact), 280 getProject().getArtifact(), 281 getProject().getRemoteArtifactRepositories(), 282 getArtifactRepository(), 283 dependencyHelper.getArtifactMetadataSource()); 284 } 285 else { 286 getArtifactResolver().resolve( 287 artifact, 288 getProject().getRemoteArtifactRepositories(), 289 getArtifactRepository()); 290 } 291 } 292 catch (ArtifactResolutionException e) { 293 throw new MojoExecutionException("Unable to resolve artifact.", e); 294 } 295 catch (ArtifactNotFoundException e) { 296 throw new MojoExecutionException("Unable to find artifact.", e); 297 } 298 299 return artifact; 300 } 301 302 /** 303 * Resolves the Artifact from the remote repository non-transitivly. 304 * 305 * @param artifact The artifact to be resolved; must not be null 306 * @return The resolved artifact; never null 307 * 308 * @throws MojoExecutionException Failed to resolve artifact 309 * 310 * @see #resolveArtifact(Artifact,boolean) 311 */ 312 protected Artifact resolveArtifact(final Artifact artifact) throws MojoExecutionException { 313 return resolveArtifact(artifact, false); 314 } 315 316 /** 317 * Tries to find missing version from dependancy list and dependency management. 318 * If found, the artifact is updated with the correct version. 319 * 320 * @param item The item to fill in missing version details into 321 */ 322 private void fillMissingArtifactVersion(final ArtifactItem item) { 323 log.debug("Attempting to find missing version in " + item.getGroupId() + ":" + item.getArtifactId()); 324 325 List list = getProject().getDependencies(); 326 327 for (int i = 0; i < list.size(); ++i) { 328 Dependency dependency = (Dependency) list.get(i); 329 330 if (dependency.getGroupId().equals(item.getGroupId()) 331 && dependency.getArtifactId().equals(item.getArtifactId()) 332 && dependency.getType().equals(item.getType())) 333 { 334 log.debug("Found missing version: " + dependency.getVersion() + " in dependency list."); 335 336 item.setVersion(dependency.getVersion()); 337 338 return; 339 } 340 } 341 342 list = getProject().getDependencyManagement().getDependencies(); 343 344 for (int i = 0; i < list.size(); i++) { 345 Dependency dependency = (Dependency) list.get(i); 346 347 if (dependency.getGroupId().equals(item.getGroupId()) 348 && dependency.getArtifactId().equals(item.getArtifactId()) 349 && dependency.getType().equals(item.getType())) 350 { 351 log.debug("Found missing version: " + dependency.getVersion() + " in dependency management list"); 352 353 item.setVersion(dependency.getVersion()); 354 } 355 } 356 } 357 358 // 359 // Access to Project artifacts 360 // 361 362 protected Set getProjectArtifacts(final MavenProject project, final boolean resolve) throws MojoExecutionException { 363 Set artifacts = new HashSet(); 364 365 Iterator dependencies = project.getDependencies().iterator(); 366 while (dependencies.hasNext()) { 367 Dependency dep = (Dependency) dependencies.next(); 368 369 String groupId = dep.getGroupId(); 370 String artifactId = dep.getArtifactId(); 371 VersionRange versionRange = VersionRange.createFromVersion(dep.getVersion()); 372 String type = dep.getType(); 373 if (type == null) { 374 type = "jar"; 375 } 376 377 String classifier = dep.getClassifier(); 378 boolean optional = dep.isOptional(); 379 String scope = dep.getScope(); 380 if (scope == null) { 381 scope = Artifact.SCOPE_COMPILE; 382 } 383 384 Artifact artifact = getArtifactFactory().createDependencyArtifact( 385 groupId, 386 artifactId, 387 versionRange, 388 type, 389 classifier, 390 scope, 391 optional); 392 393 if (scope.equalsIgnoreCase(Artifact.SCOPE_SYSTEM)) { 394 artifact.setFile(new File(dep.getSystemPath())); 395 } 396 397 List exclusions = new ArrayList(); 398 for (Iterator j = dep.getExclusions().iterator(); j.hasNext();) { 399 Exclusion e = (Exclusion) j.next(); 400 exclusions.add(e.getGroupId() + ":" + e.getArtifactId()); 401 } 402 403 ArtifactFilter newFilter = new ExcludesArtifactFilter(exclusions); 404 artifact.setDependencyFilter(newFilter); 405 406 if (resolve && !artifact.isResolved()) { 407 log.debug("Resolving artifact: " + artifact); 408 artifact = resolveArtifact(artifact); 409 } 410 411 artifacts.add(artifact); 412 } 413 414 return artifacts; 415 } 416 417 protected Set getProjectArtifacts(final boolean resolve) throws MojoExecutionException { 418 return getProjectArtifacts(getProject(), resolve); 419 } 420 421 protected Set getProjectArtifacts() throws MojoExecutionException { 422 return getProjectArtifacts(false); 423 } 424 }