View Javadoc

1   package org.codehaus.mojo.pde;
2   
3   /*
4    * Copyright 2006 The Apache Software Foundation.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import java.io.File;
20  
21  import org.apache.commons.configuration.ConfigurationException;
22  import org.apache.commons.configuration.PropertiesConfiguration;
23  import org.apache.maven.plugin.AbstractMojo;
24  import org.apache.maven.plugin.MojoExecutionException;
25  import org.apache.maven.plugin.MojoFailureException;
26  import org.apache.maven.project.MavenProject;
27  import org.codehaus.mojo.pde.descriptor.Descriptor;
28  import org.codehaus.mojo.pde.descriptor.DescriptorUtil;
29  import org.codehaus.plexus.util.StringUtils;
30  import org.codehaus.plexus.util.cli.CommandLineException;
31  import org.codehaus.plexus.util.cli.CommandLineUtils;
32  import org.codehaus.plexus.util.cli.Commandline;
33  import org.codehaus.plexus.util.cli.DefaultConsumer;
34  
35  /**
36   * Base class of all Eclispe PDE mojos
37   * 
38   * @author dtran@gmail.com
39   * @version $Id:$
40   */
41  
42  public abstract class AbstractEclipsePDEMojo
43      extends AbstractMojo
44  {
45  
46      /**
47       * A pde build.properties ${configs} must contain this many comma separated fields.
48       */
49      private static final int CONFIG_TUPLE = 3;
50  
51      /**
52       * The POM
53       * 
54       * @parameter expression="${project}
55       * @required
56       * @readonly
57       */
58  
59      protected MavenProject project;
60  
61      /**
62       * Contains the PDE project source
63       * 
64       * @parameter expression="${pdeDirectory}" default-value="${project.basedir}"
65       * @required
66       * @readonly
67       */
68      protected File pdeDirectory;
69  
70      /**
71       * Build a product instead of a feature.
72       * 
73       * If defined then a PDE Product will be built (instead of the feature, fragment or plug-in).
74       * This value defines the product file that will be used to build the product.
75       * 
76       * @parameter expression="${pdeProductFilename}"
77       * @optional
78       */
79      protected String pdeProductFilename;
80  
81      /**
82       * When a product build is run then use this version of the pde build scripts. The build scripts
83       * are located at
84       * ${eclipseInstall}/plugins/org.eclipse.pde.build_{pdeBuildVersion}/scripts/productBuild
85       * 
86       * @parameter expression="${pdeBuildVersion}"
87       * @optional
88       */
89      protected String pdeBuildVersion;
90  
91      /**
92       * When a product build is run, then the location of the PDE build configuration directory must
93       * be specified. A product build will expect a build.properties file to exist in this directory.
94       * You can use
95       * ${eclipseInstall}/plugins/org.eclipse.pde.build_{pdeBuildVersion}/templates/headless-build/build.properties
96       * as a starter file. See
97       * http://help.eclipse.org/help32/topic/org.eclipse.pde.doc.user/guide/tasks/pde_product_build.htm
98       * Building an RCP application from a product configuration file for more details.
99       * 
100      * @parameter expression="${pdeBuildConfigDirectory}" default-value="buildConfiguration"
101      * @optional
102      */
103     protected String pdeBuildConfigDirectory;
104 
105     /**
106      * Eclipse Platform SDK Directory
107      * 
108      * @parameter expression="${eclipseInstall}" default-value="c:/eclipse"
109      * @required
110      */
111 
112     protected File eclipseInstall;
113 
114     /**
115      * Ant debug capability
116      * 
117      * @parameter expression="${antDebug}" default-value="false"
118      */
119 
120     protected boolean antDebug;
121 
122     /**
123      * Ant verbose capability
124      * 
125      * @parameter expression="${antVerbose}" default-value="false"
126      */
127 
128     protected boolean antVerbose;
129 
130     // ////////////////////////////////////////////////////////////////////
131     // Other internal properties
132     // ////////////////////////////////////////////////////////////////////
133 
134     /**
135      * The pde descriptor for the pde project.
136      */
137     protected Descriptor descriptor;
138 
139     /**
140      * The eclipse startup.jar file.
141      */
142     private File startupJar;
143 
144     /**
145      * The pdeDirectory/buildConfiguraion/build.properties file.
146      */
147     PropertiesConfiguration buildConfigurationProperties = null;
148 
149     /**
150      * Execute the Mojo
151      * 
152      * @throws MojoExecutionException build failure
153      * @throws MojoFailureException build failure
154      */
155     public void execute()
156         throws MojoExecutionException, MojoFailureException
157     {
158         initialize();
159     }
160 
161     /**
162      * Initialise the mojo.
163      * 
164      * @throws MojoExecutionException build failure
165      * @throws MojoFailureException build failure
166      */
167     protected void initialize()
168         throws MojoExecutionException, MojoFailureException
169     {
170 
171         if ( this.pdeDirectory == null )
172         {
173             this.pdeDirectory = new File( System.getProperty( "user.dir" ) );
174         }
175 
176         this.startupJar = new File( this.eclipseInstall, "startup.jar" );
177         if ( !startupJar.exists() )
178         {
179             throw new MojoExecutionException( startupJar.getPath()
180                 + " not found.  Have you set up your -DeclipseInstall?" );
181         }
182 
183         if ( pdeProductFilename != null )
184         {
185             if ( pdeBuildVersion == null )
186             {
187                 throw new MojoExecutionException( "pdeBuildVersion must be specified for a product build." );
188             }
189             // Fail fast on build.properties missing.
190             loadBuildConfigurationProperties();
191             
192         }
193 
194         this.descriptor = DescriptorUtil.getDescriptor( this.pdeDirectory, pdeProductFilename );
195 
196         // TODO check for empty id
197 
198     }
199 
200     /**
201      * Execute the specified Commandline
202      * 
203      * @param cl the Commandline to execute
204      * @throws MojoExecutionException build failures
205      */
206     protected void executeCommandLine( Commandline cl )
207         throws MojoExecutionException
208     {
209         int ok;
210 
211         try
212         {
213             DefaultConsumer stdout = new DefaultConsumer();
214 
215             DefaultConsumer stderr = stdout;
216 
217             this.getLog().info( cl.toString() );
218 
219             ok = CommandLineUtils.executeCommandLine( cl, stdout, stderr );
220         }
221         catch ( CommandLineException e )
222         {
223             throw new MojoExecutionException( "Error executing command line", e );
224         }
225 
226         if ( ok != 0 )
227         {
228             throw new MojoExecutionException( "Error executing command line. Exit code:" + ok );
229         }
230     }
231 
232     /**
233      * Create a command line to invoke an Ant build file using the Eclipse pde environment.
234      * 
235      * @param buildFile the Ant buildfile to use as part of the command
236      * @param targets the targets to invoke on the Ant build file
237      * @return A command line to invoke the targets on the Ant buildfile
238      */
239     protected Commandline createCommandLine( File buildFile, String targets )
240     {
241         Commandline cl = new Commandline();
242 
243         cl.setWorkingDirectory( this.pdeDirectory.getPath() );
244 
245         cl.setExecutable( "java" );
246 
247         cl.createArgument().setValue( "-classpath" );
248 
249         cl.createArgument().setFile( this.startupJar );
250 
251         cl.createArgument().setValue( "org.eclipse.core.launcher.Main" );
252 
253         cl.createArgument().setValue( "-application" );
254         cl.createArgument().setValue( "org.eclipse.ant.core.antRunner" );
255 
256         cl.createArgument().setValue( "-buildfile" );
257         cl.createArgument().setValue( buildFile.toString() );
258 
259         if ( targets != null )
260         {
261             cl.createArgument().setLine( targets );
262         }
263 
264         if ( this.antVerbose )
265         {
266             cl.createArgument().setValue( "-verbose" );
267         }
268 
269         if ( this.antDebug )
270         {
271             cl.createArgument().setValue( "-debug" );
272         }
273 
274         return cl;
275 
276     }
277 
278     /**
279      * Create a command line to invoke an Ant build file with the default target
280      * 
281      * @param buildFile the Ant buildfile to use as part of the command
282      * @return A command line to invoke the targets on the Ant buildfile
283      */
284     protected Commandline createCommandLine( File buildFile )
285     {
286         return this.createCommandLine( buildFile, null );
287     }
288 
289     /**
290      * The PDE Build Directory, which is always located two directories higher than the pdeDirectory
291      * (i.e "../../${pdeDirectory")
292      * 
293      * @return The PDE Build Directory
294      */
295     protected File getPDEBuildDirectory()
296     {
297         return new File( this.pdeDirectory, "../.." );
298     }
299 
300     /**
301      * @return The Eclipse Base Location.
302      */
303     protected File getBaseLocation()
304     {
305         return this.eclipseInstall;
306     }
307 
308     /**
309      * Load the properties from pdeBuildConfiguration\build.properties.
310      * 
311      * @return the properties from pdeBuildConfiguration\build.properties.
312      * @throws MojoExecutionException build failures.
313      */
314     protected PropertiesConfiguration loadBuildConfigurationProperties()
315         throws MojoExecutionException
316     {
317         if ( buildConfigurationProperties != null )
318         {
319             return buildConfigurationProperties;
320         }
321     
322         File buildPropertiesFile = new File( pdeDirectory, pdeBuildConfigDirectory + "/build.properties" );
323         try
324         {
325             buildConfigurationProperties = new PropertiesConfiguration();
326             buildConfigurationProperties.setDelimiterParsingDisabled( true );
327             buildConfigurationProperties.load( buildPropertiesFile );
328     
329             return buildConfigurationProperties;
330         }
331         catch ( ConfigurationException e )
332         {
333             throw new MojoExecutionException( "Failed to load pde build.properties from "
334                 + buildPropertiesFile.getPath(), e );
335         }
336     }
337 
338     /**
339      * Convert the list of {os, ws, arch} configurations to build as contained in the
340      * build.properties file ${configs} field into the filename suffix for the created artifact. *
341      * 
342      * <b>Note</b> PDE Build support multiple configs, here only one config is supported.
343      * 
344      * @param configs the string form of the configs
345      * @return the filename suffix for the configs
346      * @throws MojoExecutionException build failures.
347      */
348     protected String convertPdeConfigsToFilenameSuffix( String configs )
349         throws MojoExecutionException
350     {
351         if ( StringUtils.isEmpty( configs ) )
352         {
353             throw new MojoExecutionException( "Null pde configs can not be converted to filename suffix" );
354         }
355         if ( configs.indexOf( "&" ) > 0 )
356         {
357             throw new MojoExecutionException( "Pde build only supports a build with a single config only." );
358         }
359         String[] strings = StringUtils.split( configs, "," );
360         if ( strings.length != CONFIG_TUPLE )
361         {
362             throw new MojoExecutionException( "Invalid PDE Config \"" + configs
363                 + "\": must be of the form: os, ws, arch" );
364         }
365         for ( int i = 0; i < strings.length; i++ )
366         {
367             strings[i] = strings[i].trim();
368         }
369         return StringUtils.join( strings, "." );
370     }
371 
372 }