View Javadoc
1   package org.andromda.maven.plugin.bootstrap.install;
2   
3   import org.apache.commons.collections.CollectionUtils;
4   import org.apache.commons.collections.Predicate;
5   import org.apache.commons.lang.StringUtils;
6   import org.apache.maven.artifact.Artifact;
7   import org.apache.maven.artifact.repository.ArtifactRepository;
8   import org.apache.maven.model.Dependency;
9   import org.apache.maven.model.Model;
10  import org.apache.maven.plugin.AbstractMojo;
11  import org.apache.maven.plugin.MojoExecutionException;
12  import org.apache.maven.plugin.MojoFailureException;
13  import org.apache.maven.project.MavenProject;
14  import org.apache.commons.io.FileUtils;
15  
16  import java.io.File;
17  import java.io.FileWriter;
18  import java.io.IOException;
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  
23  /**
24   * Provides the installation of bootstrap artifacts.
25   *
26   * @author Chad Brandon
27   * @goal install
28   * @phase install
29   */
30  public class BootstrapInstallMojo
31          extends AbstractMojo
32  {
33      /**
34       * The maven project.
35       *
36       * @parameter expression="${project}"
37       * @required
38       * @readonly
39       * @description "the maven project to use"
40       */
41      protected MavenProject project;
42  
43      /**
44       * @parameter expression="${localRepository}"
45       * @required
46       * @readonly
47       */
48      protected ArtifactRepository localRepository;
49  
50      /**
51       * @parameter expression="${bootstrap.artifacts}"
52       * @description whether or not bootstrap artifacts should be installed, by default they are.
53       */
54      protected boolean installBootstraps = true;
55  
56      /**
57       * @parameter
58       * @required
59       * @description the directory to which the bootstrap artifact should be installed.
60       */
61      protected String installDirectory;
62  
63      /**
64       * @parameter expression="org.andromda"
65       * @required
66       * @readonly
67       * @description the name of the project groupId.
68       */
69      protected String projectGroupId;
70  
71      /**
72       * @parameter expression="org.andromda.bootstrap"
73       * @required
74       * @readonly
75       * @description the name of the project bootstrap groupId.
76       */
77      protected String projectBootstrapGroupId;
78  
79      /**
80       * The extension for "JAR" files.
81       */
82      private static final String JAR_EXTENSION = "jar";
83  
84      /**
85       * The extension for "POM" files.
86       */
87      private static final String POM_EXTENSION = "pom";
88  
89      /**
90       * The qualifier for source artifacts.
91       */
92      private static final String SOURCES_QUALIFIER = "-sources";
93  
94      /**
95       * The qualifier for javadoc artifacts.
96       */
97      private static final String JAVADOC_QUALIFIER = "-javadoc";
98  
99      /**
100      * The qualifier for test artifacts.
101      */
102     private static final String TEST_QUALIFIER = "-test";
103 
104     /**
105      * @see org.apache.maven.plugin.Mojo#execute()
106      */
107     public void execute()
108             throws MojoExecutionException, MojoFailureException
109     {
110         if (this.installBootstraps)
111         {
112             try
113             {
114                 final File installDirectory = new File(this.installDirectory);
115                 if (!installDirectory.exists() || !installDirectory.isDirectory())
116                 {
117                     throw new MojoExecutionException("'" + installDirectory + "' is not a valid install directory");
118                 }
119                 Artifact artifact = this.project.getArtifact();
120 
121                 final String path = this.replaceExtension(artifact, JAR_EXTENSION, null);
122                 final String localRepositoryDirectory = this.localRepository.getBasedir();
123                 final File existingFile = new File(localRepositoryDirectory, path);
124                 final String bootstrapGroupId = this.getBootstrapGroupId(artifact);
125                 final String bootstrapPath = bootstrapGroupId.replace('.', '/')
126                     + '/' + artifact.getArtifactId();
127                 final File bootstrapPomFile = new File(installDirectory, bootstrapPath + '.' + POM_EXTENSION);
128                 this.writeMinimalPom(bootstrapPomFile);
129                 final File bootstrapFile = new File(installDirectory, bootstrapPath + '.' + JAR_EXTENSION);
130                 this.getLog().info("Installing bootstrap artifact: " + bootstrapFile);
131                 if (path != null)
132                 {
133                     FileUtils.copyFile(existingFile, bootstrapFile);
134                 }
135                 final String sourcePath = this.replaceExtension(artifact, JAR_EXTENSION, SOURCES_QUALIFIER);
136                 if (sourcePath != null)
137                 {
138                     this.getLog().info("Installing bootstrap artifact: " + sourcePath);
139                     FileUtils.copyFile(new File(localRepositoryDirectory, sourcePath), new File(installDirectory, bootstrapPath + SOURCES_QUALIFIER + '.' + JAR_EXTENSION));
140                 }
141                 final String javadocPath = this.replaceExtension(artifact, JAR_EXTENSION, JAVADOC_QUALIFIER);
142                 if (javadocPath != null)
143                 {
144                     this.getLog().info("Installing bootstrap artifact: " + javadocPath);
145                     FileUtils.copyFile(new File(localRepositoryDirectory, javadocPath), new File(installDirectory, bootstrapPath + JAVADOC_QUALIFIER + '.' + JAR_EXTENSION));
146                 }
147                 final String testSourcePath = this.replaceExtension(artifact, JAR_EXTENSION, TEST_QUALIFIER + SOURCES_QUALIFIER);
148                 if (testSourcePath != null)
149                 {
150                     this.getLog().info("Installing bootstrap artifact: " + testSourcePath);
151                     FileUtils.copyFile(new File(localRepositoryDirectory, testSourcePath), new File(installDirectory, bootstrapPath + TEST_QUALIFIER + SOURCES_QUALIFIER + '.' + JAR_EXTENSION));
152                 }
153                 final String testJavadocPath = this.replaceExtension(artifact, JAR_EXTENSION, TEST_QUALIFIER + JAVADOC_QUALIFIER);
154                 if (testJavadocPath != null)
155                 {
156                     this.getLog().info("Installing bootstrap artifact: " + testJavadocPath);
157                     FileUtils.copyFile(new File(localRepositoryDirectory, testJavadocPath), new File(installDirectory, bootstrapPath + TEST_QUALIFIER + JAVADOC_QUALIFIER + '.' + JAR_EXTENSION));
158                 }
159             }
160             catch (final Throwable throwable)
161             {
162                 throw new MojoExecutionException("Error creating bootstrap artifact", throwable);
163             }
164         }
165     }
166 
167     /**
168      * Clears the POM's model of its parent or any dependencies
169      * it may have so that we can write a POM that isn't dependent on anything
170      * (which we need for bootstrap artifacts).
171      *
172      * @param bootstrapPomFile the bootstrap POM file to write.
173      */
174     private void writeMinimalPom(final File bootstrapPomFile)
175             throws IOException
176     {
177         final Model model = this.project.getModel();
178 
179         final MavenProject minimalProject = new MavenProject();
180         final Model minModel = minimalProject.getModel();
181 
182         minModel.setGroupId(getBootstrapGroupId(this.project.getArtifact()));
183         minModel.setArtifactId(model.getArtifactId());
184         minModel.setVersion(model.getVersion());
185         minModel.setName(model.getName());
186         minModel.setPackaging("jar");
187         minModel.setDescription(model.getDescription());
188         minModel.setModelEncoding(model.getModelEncoding());
189         minModel.setModelVersion(model.getModelVersion());
190         minModel.setUrl(model.getUrl());
191         minModel.setScm(model.getScm());
192         minModel.setDevelopers(model.getDevelopers());
193         minModel.setCiManagement(model.getCiManagement());
194         minModel.setIssueManagement(model.getIssueManagement());
195 
196         minModel.setPrerequisites(model.getPrerequisites());
197         minModel.setOrganization(model.getOrganization());
198         minModel.setInceptionYear(model.getInceptionYear());
199         minModel.setLicenses(model.getLicenses());
200 
201         final List<Dependency> dependencies = new ArrayList<Dependency>(model.getDependencies());
202         // filter all of andromda dependencies away
203         CollectionUtils.filter(dependencies, new Predicate()
204         {
205             public boolean evaluate(Object object)
206             {
207                 Dependency dependency = (Dependency)object;
208                 final String lGroupId = dependency.getGroupId();
209                 return !lGroupId.startsWith("org.andromda") || lGroupId.startsWith("org.andromda.thirdparty");
210             }
211         });
212         minModel.setDependencies(dependencies);
213 
214         final FileWriter fileWriter = new FileWriter(bootstrapPomFile);
215         minimalProject.writeModel(fileWriter);
216         fileWriter.flush();
217     }
218 
219     /**
220      * Retrieves the project's bootstrap groupId from the given <code>artifact</code>.
221      *
222      * @param artifact the artifact from which to retrieve the group Id.
223      * @return the bootstrap groupId.
224      */
225     private String getBootstrapGroupId(final Artifact artifact)
226     {
227         return StringUtils.replaceOnce(
228                 artifact.getGroupId(),
229                 this.projectGroupId,
230                 this.projectBootstrapGroupId);
231     }
232 
233     /**
234      * Retrieves the repository artifact file name with extension removed and qualifier added.
235      * If the file does not yet exist in the local repository, returns null
236      *
237      * @param artifact     the artifact from which to retrieve the version information.
238      * @param newExtension new extension for the file
239      * @param qualifier the -qualifier for the repo artifact such as -sources -javadocs -test-sources -test-javadocs
240      * @return the artifact name with no version and extension removed.
241      */
242     private String replaceExtension(
243             final Artifact artifact,
244             final String newExtension,
245             final String qualifier)
246     {
247         String path = this.localRepository.pathOf(artifact);
248         File artifactFile = new File(this.localRepository.getBasedir(), path);
249         if (!artifactFile.exists())
250         {
251             this.getLog().error("Bootstrap artifact does not exist: " + path);
252             return null;
253         }
254         final String version = artifact.getVersion() != null ? artifact.getVersion().trim() : "";
255         int versionIndex = path.lastIndexOf(artifact.getVersion());
256         final String extension = path.substring(
257                 versionIndex + version.length() + 1,
258                 path.length());
259         int extensionIndex = path.lastIndexOf(extension);
260         if (StringUtils.isNotBlank(qualifier))
261         {
262             path = path.substring(0, extensionIndex-1) + qualifier + '.' + extension;
263             File qualifiedFile = new File(this.localRepository.getBasedir(), path);
264             if (!qualifiedFile.exists())
265             {
266                 this.getLog().warn("Bootstrap qualified artifact does not exist: " + path);
267                 return null;
268             }
269         }
270         if (!newExtension.equals(extension))
271         {
272             path = path.substring(0, extensionIndex) + newExtension;
273         }
274         return path;
275     }
276 }