View Javadoc
1   package org.codehaus.mojo.appassembler;
2   
3   /*
4    * The MIT License
5    *
6    * Copyright (c) 2006-2013, The Codehaus
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  
27  import java.io.File;
28  import java.util.ArrayList;
29  import java.util.Collections;
30  import java.util.List;
31  
32  import org.apache.maven.artifact.Artifact;
33  import org.apache.maven.artifact.repository.ArtifactRepository;
34  import org.apache.maven.execution.MavenSession;
35  import org.apache.maven.model.Resource;
36  import org.apache.maven.plugin.MojoExecutionException;
37  import org.apache.maven.plugin.MojoFailureException;
38  import org.apache.maven.plugins.annotations.Component;
39  import org.apache.maven.plugins.annotations.Parameter;
40  import org.apache.maven.project.MavenProject;
41  import org.apache.maven.shared.filtering.MavenFilteringException;
42  import org.apache.maven.shared.filtering.MavenResourcesExecution;
43  import org.apache.maven.shared.filtering.MavenResourcesFiltering;
44  import org.codehaus.mojo.appassembler.daemon.DaemonGeneratorService;
45  import org.codehaus.plexus.util.FileUtils;
46  
47  /**
48   * This is intended to collect all generic parts of the script generating Mojos assemble and generate-daemons into a
49   * single class. A first step of hopefully merging the two into one some day.
50   *
51   * @author Dennis Lundberg
52   * @version $Id$
53   */
54  public abstract class AbstractScriptGeneratorMojo
55      extends AbstractAppAssemblerMojo
56  {
57      // -----------------------------------------------------------------------
58      // Parameters
59      // -----------------------------------------------------------------------
60  
61      /**
62       * Setup file in <code>$BASEDIR/bin</code> to be called prior to execution.
63       * <p>
64       * <b>Note:</b> only for the <code>jsw</code> platform. If this optional environment file also sets up
65       * WRAPPER_CONF_OVERRIDES variable, it will be passed into JSW native launcher's command line arguments to override
66       * wrapper.conf's properties. See http://wrapper.tanukisoftware.com/doc/english/props-command-line.html for details.
67       * </p>
68       *
69       * @since 1.2.3 (generate-daemons)
70       */
71      @Parameter
72      protected String environmentSetupFileName;
73  
74      /**
75       * You can define a license header file which will be used instead the default header in the generated scripts.
76       *
77       * @since 1.2
78       */
79      @Parameter
80      protected File licenseHeaderFile;
81  
82      /**
83       * The unix template of the generated script. It can be a file or resource path. If not given, an internal one is
84       * used. Use with care since it is not guaranteed to be compatible with new plugin release.
85       *
86       * @since 1.3
87       */
88      @Parameter( property = "unixScriptTemplate" )
89      protected String unixScriptTemplate;
90  
91      /**
92       * Sometimes it happens that you have many dependencies which means having a very long classpath, and
93       * becomes too long (in particular on Windows based platforms). This option can help in such
94       * situation. If you activate this option, your classpath contains only a <a href=
95       * "http://docs.oracle.com/javase/6/docs/technotes/tools/windows/classpath.html" >classpath wildcard</a> (REPO/*).
96       * But be aware that this works only in combination with Java 1.6 and above and with {@link #repositoryLayout}
97       * <code>flat</code>.
98       *
99       * @since 1.2.3 (assemble), 1.3.1 (generate-daemons)
100      */
101     @Parameter( defaultValue = "false" )
102     protected boolean useWildcardClassPath;
103 
104     /**
105      * The windows template of the generated script. It can be a file or resource path. If not given, an internal one is
106      * used. Use with care since it is not guaranteed to be compatible with new plugin release.
107      *
108      * @since 1.3
109      */
110     @Parameter( property = "windowsScriptTemplate" )
111     protected String windowsScriptTemplate;
112 
113     // -----------------------------------------------------------------------
114     // Read-only Parameters
115     // -----------------------------------------------------------------------
116 
117     @Parameter( defaultValue = "${project.runtimeArtifacts}", readonly = true )
118     protected List<Artifact> artifacts;
119 
120     @Parameter( defaultValue = "${project}", readonly = true, required = true )
121     protected MavenProject mavenProject;
122 
123     /**
124      * Set to <code>false</code> to skip repository generation.
125      */
126     @Parameter( defaultValue = "true" )
127     protected boolean generateRepository;
128 
129     /**
130      * The name of the target directory for configuration files. Prior to version 1.7 this value defaults to 'conf' for
131      * assemble goal and 'etc' for generate-daemons
132      */
133     @Parameter( defaultValue = "etc" )
134     protected String configurationDirectory;
135 
136     /**
137      * The source directory for configuration files.
138      *
139      * @since 1.1
140      */
141     @Parameter( defaultValue = "src/main/config" )
142     protected File configurationSourceDirectory;
143 
144     /**
145      * If the source configuration directory should be filtered when copied to the configured
146      * <code>configurationDirectory</code>. This configuration can be replaced by a more generic
147      * <code>preAssembleDirectory</code> option
148      *
149      * @since 1.8
150      */
151     @Parameter( defaultValue = "false" )
152     protected boolean filterConfigurationDirectory;
153 
154     /**
155      * If the source configuration directory should be copied to the configured <code>configurationDirectory</code>.
156      *
157      * @since 1.1 (assemble), 1.7 (generate-daemons)
158      */
159     @Parameter( defaultValue = "false" )
160     protected boolean copyConfigurationDirectory;
161 
162     /**
163      * If exists, copy this directory's contents to the configured <code>assembleDirectory</code> with option to filter.
164      * This configuration can replace <i>copyConfigurationDirectory</i>
165      *
166      * @since 1.10
167      */
168     @Parameter
169     protected File preAssembleDirectory;
170 
171     /**
172      * If the source pre-assemble directory should be filtered when copied to the configured
173      * <code>assembleDirectory</code>.
174      *
175      * @since 1.10
176      */
177     @Parameter( defaultValue = "false" )
178     protected boolean filterPreAssembleDirectory;
179 
180     /**
181      * Location under base directory where all of files non-recursively are added before the generated classpath. Java
182      * 6+ only since it uses wildcard classpath format. This is a convenient way to have user to add artifacts that not
183      * possible to be part of final assembly such as LGPL/GPL artifacts
184      *
185      * @since 1.6
186      */
187     @Parameter
188     protected String endorsedDir;
189 
190     /**
191      * Project build filters.
192      *
193      * @since 1.8
194      */
195     @Parameter( defaultValue = "${project.build.filters}", readonly = true )
196     protected List<String> buildFilters;
197 
198     /**
199      * The character encoding scheme to be applied when filtering the source configuration directory.
200      *
201      * @since 1.8
202      */
203     @Parameter( defaultValue = "${project.build.sourceEncoding}" )
204     protected String encoding;
205 
206     /**
207      * Expressions preceded with this String won't be interpolated. <code>\${foo}</code> will be replaced with
208      * <code>${foo}</code>.
209      *
210      * @since 1.8
211      */
212     @Parameter
213     protected String escapeString;
214 
215     /**
216      * @since 1.8
217      */
218     @Parameter( defaultValue = "${session}", readonly = true, required = true )
219     private MavenSession session;
220 
221     /**
222      * The logs directory for the assembled project. If you specify a value for this parameter an empty directory with
223      * the name given will be created.
224      *
225      * @since 1.8
226      */
227     @Parameter( property = "logsDirectory" )
228     protected String logsDirectory;
229 
230     /**
231      * The temp directory of the assembled project. If you specify a value for this parameter an empty directory with
232      * the name given will be created.
233      *
234      * @since 1.8
235      */
236     @Parameter( property = "tempDirectory" )
237     protected String tempDirectory;
238 
239     // -----------------------------------------------------------------------
240     // Components
241     // -----------------------------------------------------------------------
242 
243     @Component
244     protected DaemonGeneratorService daemonGeneratorService;
245 
246     /**
247      * The filtering component used when copying the source configuration directory.
248      *
249      * @since 1.8
250      */
251     @Component( role = MavenResourcesFiltering.class, hint = "default" )
252     protected MavenResourcesFiltering mavenResourcesFiltering;
253 
254     protected void doCopyConfigurationDirectory( final String targetDirectory )
255         throws MojoFailureException
256     {
257         getLog().debug( "copying configuration directory." );
258 
259         // Create a Resource from the configuration source directory
260         Resource resource = new Resource();
261         resource.setDirectory( configurationSourceDirectory.getAbsolutePath() );
262         resource.setFiltering( filterConfigurationDirectory );
263         resource.setTargetPath( configurationDirectory );
264         List<Resource> resources = new ArrayList<Resource>();
265         resources.add( resource );
266 
267         MavenResourcesExecution mavenResourcesExecution =
268             new MavenResourcesExecution( resources, new File( targetDirectory ), mavenProject, encoding, buildFilters,
269                                          Collections.<String>emptyList(), session );
270 
271         mavenResourcesExecution.setEscapeString( escapeString );
272         // Include empty directories, to be backwards compatible
273         mavenResourcesExecution.setIncludeEmptyDirs( true );
274         mavenResourcesExecution.setUseDefaultFilterWrappers( true );
275 
276         // @todo Possible future enhancements
277         // mavenResourcesExecution.setEscapedBackslashesInFilePath( escapedBackslashesInFilePath );
278         // mavenResourcesExecution.setOverwrite( overwrite );
279         // mavenResourcesExecution.setSupportMultiLineFiltering( supportMultiLineFiltering );
280 
281         try
282         {
283             getLog().debug( "Will try to copy configuration files from "
284                                 + configurationSourceDirectory.getAbsolutePath() + " to " + targetDirectory
285                                 + FileUtils.FS + configurationDirectory );
286 
287             // Use a MavenResourcesFiltering component to filter and copy the configuration files
288             mavenResourcesFiltering.filterResources( mavenResourcesExecution );
289         }
290         catch ( MavenFilteringException mfe )
291         {
292             throw new MojoFailureException( "Failed to copy/filter the configuration files." );
293         }
294     }
295 
296     protected void doCopyPreAssembleDirectory( final String targetDirectory )
297         throws MojoFailureException
298     {
299         // Create a Resource from the configuration source directory
300         Resource resource = new Resource();
301         resource.setDirectory( preAssembleDirectory.getAbsolutePath() );
302         resource.setFiltering( filterPreAssembleDirectory );
303         List<Resource> resources = new ArrayList<Resource>();
304         resources.add( resource );
305 
306         MavenResourcesExecution mavenResourcesExecution =
307             new MavenResourcesExecution( resources, new File( targetDirectory ), mavenProject, encoding, buildFilters,
308                                          Collections.<String>emptyList(), session );
309 
310         mavenResourcesExecution.setEscapeString( escapeString );
311         // Include empty directories, to be backwards compatible
312         mavenResourcesExecution.setIncludeEmptyDirs( true );
313         mavenResourcesExecution.setUseDefaultFilterWrappers( true );
314 
315         try
316         {
317             getLog().info( "Copy pre-assemble files from " + this.preAssembleDirectory.getAbsolutePath() + " to "
318                                 + targetDirectory );
319 
320             // Use a MavenResourcesFiltering component to filter and copy the configuration files
321             mavenResourcesFiltering.filterResources( mavenResourcesExecution );
322         }
323         catch ( MavenFilteringException mfe )
324         {
325             throw new MojoFailureException( "Failed to copy/filter the configuration files." );
326         }
327     }
328 
329     // -----------------------------------------------------------------------
330     // Protected helper methods.
331     // -----------------------------------------------------------------------
332 
333     protected void doCreateExtraDirectories( File targetDirectory )
334         throws MojoFailureException
335     {
336         if ( this.logsDirectory != null )
337         {
338             File logsDirectory = new File( targetDirectory, this.logsDirectory );
339             if ( logsDirectory.exists() )
340             {
341                 if ( !logsDirectory.delete() )
342                 {
343                     throw new MojoFailureException( "Failed to delete existing directory for log files." );
344                 }
345             }
346             boolean success = logsDirectory.mkdirs();
347             if ( !success )
348             {
349                 throw new MojoFailureException( "Failed to create directory for log files." );
350             }
351         }
352         if ( this.tempDirectory != null )
353         {
354             File tempDirectory = new File( targetDirectory, this.tempDirectory );
355             if ( tempDirectory.exists() )
356             {
357                 if ( !tempDirectory.delete() )
358                 {
359                     throw new MojoFailureException( "Failed to delete existing directory for temp files." );
360                 }
361             }
362             boolean success = tempDirectory.mkdirs();
363             if ( !success )
364             {
365                 throw new MojoFailureException( "Failed to create directory for temp files." );
366             }
367         }
368     }
369 
370     protected void installDependencies( final String outputDirectory, final String repositoryName )
371         throws MojoExecutionException, MojoFailureException
372     {
373         if ( generateRepository )
374         {
375             // The repo where the jar files will be installed
376             ArtifactRepository artifactRepository =
377                 artifactRepositoryFactory.createDeploymentArtifactRepository( "appassembler", "file://"
378                     + outputDirectory + "/" + repositoryName, getArtifactRepositoryLayout(), false );
379 
380             for ( Artifact artifact : artifacts )
381             {
382                 installArtifact( artifact, artifactRepository, this.useTimestampInSnapshotFileName );
383             }
384 
385             // install the project's artifact in the new repository
386             installArtifact( projectArtifact, artifactRepository );
387         }
388     }
389 }