001 /* 002 * Copyright (C) 2006-2007 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017 package org.codehaus.gmaven.plugin; 018 019 import org.apache.maven.artifact.Artifact; 020 import org.apache.maven.artifact.DependencyResolutionRequiredException; 021 import org.apache.maven.artifact.factory.ArtifactFactory; 022 import org.apache.maven.artifact.metadata.ArtifactMetadataSource; 023 import org.apache.maven.artifact.repository.ArtifactRepository; 024 import org.apache.maven.artifact.resolver.ArtifactNotFoundException; 025 import org.apache.maven.artifact.resolver.ArtifactResolutionException; 026 import org.apache.maven.artifact.resolver.ArtifactResolver; 027 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; 028 import org.apache.maven.artifact.versioning.VersionRange; 029 import org.apache.maven.model.Dependency; 030 import org.apache.maven.plugin.AbstractMojo; 031 import org.apache.maven.plugin.MojoExecutionException; 032 import org.apache.maven.plugin.MojoFailureException; 033 import org.apache.maven.project.MavenProject; 034 import org.codehaus.gmaven.common.ArtifactItem; 035 import org.slf4j.Logger; 036 import org.slf4j.LoggerFactory; 037 038 import java.io.File; 039 import java.net.URL; 040 import java.util.ArrayList; 041 import java.util.Collections; 042 import java.util.List; 043 044 /** 045 * Support for Mojo implementations. 046 * 047 * @version $Id: MojoSupport.java 76 2009-12-05 12:04:30Z user57 $ 048 * @author <a href="mailto:jason@planet57.com">Jason Dillon</a> 049 */ 050 public abstract class MojoSupport 051 extends AbstractMojo 052 { 053 protected final Logger log = LoggerFactory.getLogger(getClass()); 054 055 /** 056 * @parameter expression="${project}" 057 * @required 058 * @readonly 059 * 060 * @noinspection UnusedDeclaration 061 */ 062 protected MavenProject project; 063 064 /** 065 * Main Mojo execution hook. Sub-class should use {@link #doExecute} instead. 066 */ 067 public void execute() throws MojoExecutionException, MojoFailureException { 068 try { 069 doExecute(); 070 } 071 catch (Exception e) { 072 // 073 // NOTE: Wrap to avoid truncating the stacktrace 074 // 075 076 if (e instanceof MojoExecutionException) { 077 throw new MojoExecutionException(e.getMessage(), e); 078 } 079 else if (e instanceof MojoFailureException) { 080 MojoFailureException x = new MojoFailureException(e.getMessage()); 081 x.initCause(e); 082 throw x; 083 } 084 else { 085 throw new MojoExecutionException(e.getMessage(), e); 086 } 087 } 088 } 089 090 protected abstract void doExecute() throws Exception; 091 092 // 093 // Classpath Muck 094 // 095 096 protected List getProjectClasspathElements() throws DependencyResolutionRequiredException { 097 return Collections.EMPTY_LIST; 098 } 099 100 protected ArtifactItem[] getUserClassspathElements() { 101 return new ArtifactItem[0]; 102 } 103 104 protected URL[] createClassPath() throws Exception { 105 List list = new ArrayList(); 106 107 // Add the projects dependencies 108 List files = getProjectClasspathElements(); 109 if (files != null) { 110 log.debug("Project Classpath:"); 111 112 for (int i = 0; i < files.size(); ++i) { 113 URL url = new File((String)files.get(i)).toURI().toURL(); 114 list.add(url); 115 log.debug(" {}", url); 116 } 117 } 118 119 // Add user dependencies (if there are any) 120 ArtifactItem[] items = getUserClassspathElements(); 121 122 if (items != null) { 123 log.debug("User Classpath:"); 124 125 for (int i=0; i < items.length; i++) { 126 Artifact artifact = getArtifact(items[i]); 127 URL url = artifact.getFile().toURI().toURL(); 128 list.add(url); 129 log.debug(" {}", url); 130 } 131 } 132 133 return (URL[])list.toArray(new URL[list.size()]); 134 } 135 136 // 137 // Artifact Muck 138 // 139 140 /** 141 * @component 142 * @readonly 143 * @required 144 * 145 * @noinspection UnusedDeclaration 146 */ 147 protected ArtifactFactory artifactFactory; 148 149 /** 150 * @component 151 * @readonly 152 * @required 153 * 154 * @noinspection UnusedDeclaration 155 */ 156 protected ArtifactResolver artifactResolver; 157 158 /** 159 * @component 160 * @readonly 161 * @required 162 * 163 * @noinspection UnusedDeclaration 164 */ 165 protected ArtifactMetadataSource artifactMetadataSource; 166 167 /** 168 * @parameter expression="${localRepository}" 169 * @readonly 170 * @required 171 * 172 * @noinspection UnusedDeclaration 173 */ 174 protected ArtifactRepository artifactRepository; 175 176 /** 177 * @parameter expression="${project.pluginArtifactRepositories}" 178 * @required 179 * @readonly 180 * 181 * @noinspection UnusedDeclaration 182 */ 183 protected List remoteRepositories; 184 185 /** 186 * Create a new artifact. If no version is specified, it will be retrieved from the dependency 187 * list or from the DependencyManagement section of the pom. 188 * 189 * @param item The item to create an artifact for 190 * @return An unresolved artifact for the given item. 191 * 192 * @throws MojoExecutionException Failed to create artifact 193 */ 194 protected Artifact createArtifact(final ArtifactItem item) throws MojoExecutionException { 195 assert item != null; 196 197 if (item.getVersion() == null) { 198 fillMissingArtifactVersion(item); 199 200 if (item.getVersion() == null) { 201 throw new MojoExecutionException("Unable to find artifact version of " + item.getGroupId() 202 + ":" + item.getArtifactId() + " in either dependency list or in project's dependency management."); 203 } 204 } 205 206 // Convert the string version to a range 207 VersionRange range; 208 try { 209 range = VersionRange.createFromVersionSpec(item.getVersion()); 210 log.trace("Using version range: {}", range); 211 } 212 catch (InvalidVersionSpecificationException e) { 213 throw new MojoExecutionException("Could not create range for version: " + item.getVersion(), e); 214 } 215 216 return artifactFactory.createDependencyArtifact( 217 item.getGroupId(), 218 item.getArtifactId(), 219 range, 220 item.getType(), 221 item.getClassifier(), 222 Artifact.SCOPE_PROVIDED); 223 } 224 225 /** 226 * Resolves the Artifact from the remote repository if necessary. If no version is specified, it will 227 * be retrieved from the dependency list or from the DependencyManagement section of the pom. 228 * 229 * 230 * @param item The item to create an artifact for; must not be null 231 * @return The artifact for the given item 232 * 233 * @throws MojoExecutionException Failed to create artifact 234 */ 235 protected Artifact getArtifact(final ArtifactItem item) throws MojoExecutionException { 236 assert item != null; 237 238 Artifact artifact = createArtifact(item); 239 240 return resolveArtifact(artifact, false); 241 } 242 243 /** 244 * Resolves the Artifact from the remote repository if necessary. If no version is specified, it will 245 * be retrieved from the dependency list or from the DependencyManagement section of the pom. 246 * 247 * @param artifact The artifact to be resolved; must not be null 248 * @param transitive True to resolve the artifact transitively 249 * @return The resolved artifact; never null 250 * 251 * @throws MojoExecutionException Failed to resolve artifact 252 */ 253 protected Artifact resolveArtifact(final Artifact artifact, final boolean transitive) throws MojoExecutionException { 254 assert artifact != null; 255 256 try { 257 if (transitive) { 258 artifactResolver.resolveTransitively( 259 Collections.singleton(artifact), 260 project.getArtifact(), 261 project.getRemoteArtifactRepositories(), 262 artifactRepository, 263 artifactMetadataSource); 264 } 265 else { 266 artifactResolver.resolve( 267 artifact, 268 project.getRemoteArtifactRepositories(), 269 artifactRepository); 270 } 271 } 272 catch (ArtifactResolutionException e) { 273 throw new MojoExecutionException("Unable to resolve artifact", e); 274 } 275 catch (ArtifactNotFoundException e) { 276 throw new MojoExecutionException("Unable to find artifact", e); 277 } 278 279 return artifact; 280 } 281 282 /** 283 * Tries to find missing version from dependency list and dependency management. 284 * If found, the artifact is updated with the correct version. 285 * 286 * @param item The item to fill in missing version details into 287 */ 288 private void fillMissingArtifactVersion(final ArtifactItem item) { 289 log.trace("Attempting to find missing version in {}:{}", item.getGroupId() , item.getArtifactId()); 290 291 List list = project.getDependencies(); 292 293 for (int i = 0; i < list.size(); ++i) { 294 Dependency dependency = (Dependency) list.get(i); 295 296 if (dependency.getGroupId().equals(item.getGroupId()) 297 && dependency.getArtifactId().equals(item.getArtifactId()) 298 && dependency.getType().equals(item.getType())) 299 { 300 log.trace("Found missing version: {} in dependency list", dependency.getVersion()); 301 302 item.setVersion(dependency.getVersion()); 303 304 return; 305 } 306 } 307 308 list = project.getDependencyManagement().getDependencies(); 309 310 for (int i = 0; i < list.size(); i++) { 311 Dependency dependency = (Dependency) list.get(i); 312 313 if (dependency.getGroupId().equals(item.getGroupId()) 314 && dependency.getArtifactId().equals(item.getArtifactId()) 315 && dependency.getType().equals(item.getType())) 316 { 317 log.trace("Found missing version: {} in dependency management list", dependency.getVersion()); 318 319 item.setVersion(dependency.getVersion()); 320 } 321 } 322 } 323 }