1 /**
2 * The MIT License
3 *
4 * Copyright 2006-2012 The Codehaus.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy of
7 * this software and associated documentation files (the "Software"), to deal in
8 * the Software without restriction, including without limitation the rights to
9 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
10 * of the Software, and to permit persons to whom the Software is furnished to do
11 * so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24 package org.codehaus.mojo.appassembler;
25
26 import java.io.File;
27 import java.io.IOException;
28 import java.util.Collections;
29 import java.util.Iterator;
30 import java.util.Map;
31 import java.util.Set;
32
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.artifact.factory.ArtifactFactory;
35 import org.apache.maven.artifact.installer.ArtifactInstallationException;
36 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
37 import org.apache.maven.artifact.repository.ArtifactRepository;
38 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
39 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
40 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
41 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
42 import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
43 import org.apache.maven.artifact.resolver.ArtifactResolver;
44 import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
45 import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
46 import org.apache.maven.artifact.versioning.VersionRange;
47 import org.apache.maven.plugin.AbstractMojo;
48 import org.apache.maven.plugin.MojoExecutionException;
49 import org.apache.maven.plugin.MojoFailureException;
50 import org.codehaus.plexus.util.FileUtils;
51
52 /**
53 * Creates an appassembler repository. Note that this is deliberately a bit more specific than the assembly plugin
54 * version - if it can generate a flat layout and exclude JARs, it may be a suitable replacement.
55 *
56 * @author <a href="mailto:kristian.nordal@gmail.com">Kristian Nordal</a>
57 * @version $Id: CreateRepositoryMojo.java 16448 2012-04-22 15:47:18Z khmarbaise $
58 * @goal create-repository
59 * @requiresDependencyResolution runtime
60 * @phase package
61 * @threadsafe
62 */
63 public class CreateRepositoryMojo
64 extends AbstractMojo
65 {
66 // -----------------------------------------------------------------------
67 // Parameters
68 // -----------------------------------------------------------------------
69
70 /**
71 * The directory that will be used to assemble the artifacts in and place the bin scripts.
72 *
73 * @required
74 * @parameter expression="${project.build.directory}/appassembler"
75 */
76 private File assembleDirectory;
77
78 /**
79 * The directory that will be used for the dependencies, relative to <code>assembleDirectory</code>.
80 *
81 * @required
82 * @parameter default-value="repo"
83 * @todo customisation doesn't work due to the shell scripts not honouring it
84 */
85 private String repoPath;
86
87 /**
88 * The layout of the generated Maven repository. Supported types - "default" (Maven2) | "legacy" (Maven1) | "flat"
89 * (flat <code>lib/</code> style).
90 * The style "legacy" is only supported if you are running under Maven 2.2.1 and before.
91 *
92 * @parameter default-value="default"
93 */
94 private String repositoryLayout;
95
96 // -----------------------------------------------------------------------
97 // Read-only parameters
98 // -----------------------------------------------------------------------
99
100 /**
101 * @readonly
102 * @parameter expression="${project.artifacts}"
103 */
104 private Set artifacts;
105
106 /**
107 * @readonly
108 * @parameter expression="${plugin.version}"
109 */
110 private String pluginVersion;
111
112 /**
113 * @readonly
114 * @parameter expression="${localRepository}"
115 */
116 private ArtifactRepository localRepository;
117
118 /**
119 * @readonly
120 * @parameter expression="${project.artifact}"
121 */
122 private Artifact projectArtifact;
123
124 /**
125 * Whether to install the booter artifacts into the repository. This may be needed if you are using the Shell script
126 * generators.
127 *
128 * @parameter default-value="false"
129 */
130 private boolean installBooterArtifacts;
131
132 // -----------------------------------------------------------------------
133 // Components
134 // -----------------------------------------------------------------------
135
136 /** @component */
137 private ArtifactFactory artifactFactory;
138
139 /**
140 * @component
141 */
142 private ArtifactRepositoryFactory artifactRepositoryFactory;
143
144 /**
145 * @component role="org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout"
146 */
147 private Map availableRepositoryLayouts;
148
149 /** @component */
150 private ArtifactResolver artifactResolver;
151
152 /** @component */
153 private ArtifactMetadataSource metadataSource;
154
155 /* (non-Javadoc)
156 * @see org.apache.maven.plugin.AbstractMojo#execute()
157 */
158 public void execute ()
159 throws MojoExecutionException, MojoFailureException
160 {
161 // ----------------------------------------------------------------------
162 // Create new repository for dependencies
163 // ----------------------------------------------------------------------
164
165 ArtifactRepositoryLayout artifactRepositoryLayout =
166 ( ArtifactRepositoryLayout ) availableRepositoryLayouts.get ( repositoryLayout );
167 if ( artifactRepositoryLayout == null )
168 {
169 throw new MojoFailureException ( "Unknown repository layout '" + repositoryLayout + "'." );
170 }
171
172 // -----------------------------------------------------------------------
173 // Initialize
174 // -----------------------------------------------------------------------
175
176 String path = "file://" + assembleDirectory.getAbsolutePath ( ) + "/" + repoPath;
177
178 ArtifactRepository artifactRepository =
179 artifactRepositoryFactory.createDeploymentArtifactRepository ( "appassembler", path,
180 artifactRepositoryLayout, true );
181
182 // -----------------------------------------------------------------------
183 // Install the project's artifact in the new repository
184 // -----------------------------------------------------------------------
185
186 installArtifact ( projectArtifact, artifactRepository );
187
188 // ----------------------------------------------------------------------
189 // Install dependencies in the new repository
190 // ----------------------------------------------------------------------
191
192 // TODO: merge with the artifacts below so no duplicate versions included
193 for ( Iterator it = artifacts.iterator ( ); it.hasNext ( ); )
194 {
195 Artifact artifact = ( Artifact ) it.next ( );
196
197 installArtifact ( artifact, artifactRepository );
198 }
199
200 if ( installBooterArtifacts )
201 {
202 // ----------------------------------------------------------------------
203 // Install appassembler booter in the new repos
204 // ----------------------------------------------------------------------
205 installBooterArtifacts ( artifactRepository );
206 }
207 }
208
209 private void installBooterArtifacts ( ArtifactRepository artifactRepository )
210 throws MojoExecutionException
211 {
212 Artifact artifact =
213 artifactFactory.createDependencyArtifact ( "org.codehaus.mojo.appassembler", "appassembler-booter",
214 VersionRange.createFromVersion ( pluginVersion ), "jar", null,
215 Artifact.SCOPE_RUNTIME );
216 try
217 {
218 Artifact p =
219 artifactFactory.createBuildArtifact ( "org.codehaus.mojo.appassembler", "appassembler-maven-plugin",
220 pluginVersion, "jar" );
221
222 ArtifactFilter filter = new ExcludesArtifactFilter ( Collections.singletonList ( "junit:junit" ) );
223 ArtifactResolutionResult result =
224 artifactResolver.resolveTransitively ( Collections.singleton ( artifact ), p, localRepository,
225 Collections.EMPTY_LIST, metadataSource, filter );
226 for ( Iterator i = result.getArtifacts ( ).iterator ( ); i.hasNext ( ); )
227 {
228 Artifact a = ( Artifact ) i.next ( );
229 installArtifact ( a, artifactRepository );
230 }
231 }
232 catch ( ArtifactResolutionException e )
233 {
234 throw new MojoExecutionException ( "Failed to copy artifact.", e );
235 }
236 catch ( ArtifactNotFoundException e )
237 {
238 throw new MojoExecutionException ( "Failed to copy artifact.", e );
239 }
240 }
241
242 private void installArtifact ( Artifact artifact, ArtifactRepository artifactRepository )
243 throws MojoExecutionException
244 {
245 if ( artifact.getFile ( ) != null )
246 {
247 try
248 {
249 // Necessary for the artifact's baseVersion to be set correctly
250 // See: http://mail-archives.apache.org/mod_mbox/maven-dev/200511.mbox/%3c437288F4.4080003@apache.org%3e
251 artifact.isSnapshot ( );
252
253 install ( artifact.getFile ( ), artifact, artifactRepository );
254 }
255 catch ( ArtifactInstallationException e )
256 {
257 throw new MojoExecutionException ( "Failed to copy artifact.", e );
258 }
259 }
260 }
261
262 /**
263 * Set the available repository layouts.
264 * @param availableRepositoryLayouts
265 */
266 public void setAvailableRepositoryLayouts ( Map availableRepositoryLayouts )
267 {
268 this.availableRepositoryLayouts = availableRepositoryLayouts;
269 }
270
271 private void install ( File source, Artifact artifact, ArtifactRepository destinationRepository )
272 throws ArtifactInstallationException
273 {
274 try
275 {
276 String localPath = destinationRepository.pathOf ( artifact );
277
278 File destination = new File ( destinationRepository.getBasedir ( ), localPath );
279 if ( !destination.getParentFile ( ).exists ( ) )
280 {
281 destination.getParentFile ( ).mkdirs ( );
282 }
283
284 getLog ( ).info ( "Installing artifact " + source.getPath ( ) + " to " + destination );
285
286 FileUtils.copyFile ( source, destination );
287
288 }
289 catch ( IOException e )
290 {
291 throw new ArtifactInstallationException ( "Error installing artifact: " + e.getMessage ( ), e );
292 }
293 }
294 }