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  import java.io.FileOutputStream;
21  import java.io.IOException;
22  import java.io.PrintStream;
23  import java.util.Iterator;
24  import java.util.Map;
25  import java.util.Properties;
26  
27  import org.apache.maven.plugin.MojoExecutionException;
28  import org.apache.maven.plugin.MojoFailureException;
29  import org.codehaus.mojo.pde.descriptor.DescriptorUtil;
30  import org.codehaus.mojo.pde.descriptor.FeatureDescriptor;
31  import org.codehaus.mojo.pde.descriptor.ProductDescriptor;
32  import org.codehaus.plexus.util.cli.Commandline;
33  
34  /**
35   * Build PDE artifact. The output is not deployable.
36   * 
37   * @goal pde
38   * @phase compile
39   * @requiresProject false
40   * @aggregator
41   * @requiresDependencyResolution test
42   * 
43   * @version $Id:$
44   * @author dtran@gmail.com
45   */
46  
47  public class EclipsePDEMojo
48      extends AbstractEclipsePDEMojo
49  {
50      /**
51       * PDE Ant build temporary directory
52       * 
53       * @parameter expression="${pdeTempDirectory}"
54       *            default-value="${project.build.directory}/pdeTemp"
55       * 
56       * This param should be moved to systemProperties, but due a bug in PDE Ant build, we must
57       * specify default value
58       */
59      protected File pdeBuildTempFolder;
60  
61      /**
62       * Additional system properties to be passed into PDE ant build. See the generated build.xml
63       * files for list of overrideable properties. javacFailOnError=true is injected automatically if
64       * not found.
65       * 
66       * @parameter
67       */
68  
69      private Map buildProperties = new Properties();
70  
71      /**
72       * Additional system properties to be passed into PDE eclipse.buildScript task which is use to
73       * generete PDE Ant build files. buildDirectory and baseLocation are automatically injected if
74       * not set.
75       * 
76       * @parameter
77       */
78      private Map eclipseBuildScriptProperties = new Properties();
79  
80      /**
81       * {@inheritDoc}
82       */
83      protected void initialize()
84          throws MojoExecutionException, MojoFailureException
85      {
86          super.initialize();
87      }
88  
89      /**
90       * {@inheritDoc}
91       */
92      public void execute()
93          throws MojoExecutionException, MojoFailureException
94      {
95          super.execute();
96  
97          if ( pdeProductFilename == null )
98          {
99              this.executeCommandLine( this.createBootstrapCommandLine() );
100         }
101 
102         this.executeCommandLine( this.createBuildCommandLine() );
103 
104     }
105 
106     /**
107      * @return a command line for building the PDE project.
108      * @throws MojoExecutionException build failures.
109      */
110     protected Commandline createBuildCommandLine()
111         throws MojoExecutionException
112     {
113         Commandline cl = null;
114 
115         if ( pdeProductFilename != null )
116         {
117             cl = createProductBuildCommandLine();
118         }
119         else
120         {
121             cl = createFeatureBuildCommandLine();
122         }
123 
124         cl.createArgument().setLine( "-DbuildTempFolder=" + this.pdeBuildTempFolder );
125 
126         if ( this.buildProperties.get( "javacFailOnError" ) == null )
127         {
128             this.buildProperties.put( "javacFailOnError", "true" );
129         }
130 
131         Iterator iter = this.buildProperties.entrySet().iterator();
132 
133         while ( iter.hasNext() )
134         {
135             String arg = iter.next().toString();
136 
137             cl.createArgument().setLine( "-D" + arg );
138         }
139 
140         return cl;
141     }
142 
143     /**
144      * Create a command line for a product build.
145      * 
146      * See
147      * http://help.eclipse.org/help32/topic/org.eclipse.pde.doc.user/guide/tasks/pde_product_build.htm
148      * for more details.
149      * 
150      * @return a command line for building the product.
151      * @throws MojoExecutionException build failures.
152      */
153     private Commandline createProductBuildCommandLine()
154         throws MojoExecutionException
155     {
156         File buildFile =
157             new File( eclipseInstall, "plugins/org.eclipse.pde.build_" + pdeBuildVersion
158                 + "/scripts/productBuild/productBuild.xml" );
159 
160         Commandline cl = createCommandLine( buildFile );
161 
162         File buildConfigDirectory = new File( pdeDirectory, pdeBuildConfigDirectory );
163 
164         try
165         {
166             cl.createArgument().setLine( "-Dbuilder=" + buildConfigDirectory.getCanonicalPath() );
167             cl.createArgument().setLine( "-DbuildDirectory=" + this.getPDEBuildDirectory().getPath() );
168         }
169         catch ( IOException e )
170         {
171             throw new MojoExecutionException( "createProductBuildCommandLine failed: ", e );
172         }
173 
174         return cl;
175     }
176 
177     /**
178      * Create a command line for a feature build (plug-ins and fragments are also feature builds).
179      * See
180      * http://help.eclipse.org/help32/topic/org.eclipse.pde.doc.user/guide/tasks/pde_plugins_build.htm
181      * for more details.
182      * 
183      * @return a command line for building the feature
184      */
185     private Commandline createFeatureBuildCommandLine()
186     {
187         Commandline cl = this.createCommandLine( new File( this.pdeDirectory, "build.xml" ), this.getAntTarget() );
188 
189         return cl;
190     }
191 
192     /**
193      * Return the file that the PDE Ant build creates. Note that a PDE product build can create a
194      * zip file for each config that is specified, however this mojo does not support that
195      * situation.
196      * 
197      * The product file from a PDE build is located at
198      * ${buildDirectory}/${buildLabel}/${buildId}-${configs}.zip.
199      * 
200      * However the buildConfiguration/build.properties file does not specify the buildDirectory as
201      * this is overriden by the Mojo to always be "../..".
202      * 
203      * <b>Note:</b> A normal pde build supports multiple configs to be built. This maven mojo only
204      * supports <b>ONE</b> config to be built. Otherwise attaching the generated artifacts becomes
205      * difficult, as which one is the main build and which ones are the extras with classifiers?
206      * 
207      * @return the output of the PDE Ant build.
208      * @throws MojoExecutionException build failures.
209      */
210     protected File locateAntOutputFile()
211         throws MojoExecutionException
212     {
213         if ( this.descriptor instanceof ProductDescriptor )
214         {
215             String config = convertPdeConfigsToFilenameSuffix( buildConfigurationProperties.getString( "configs" ) );
216             return new File( getPDEBuildDirectory(), buildConfigurationProperties.getString( "buildLabel" ) + "/"
217                 + buildConfigurationProperties.getProperty( "buildId" ) + "-" + config + ".zip" );
218         }
219         if ( this.descriptor instanceof FeatureDescriptor )
220         {
221             return new File( this.pdeDirectory, this.descriptor.getId() + "_" + this.descriptor.getVersion()
222                 + ".bin.dist.zip" );
223         }
224         else
225         {
226             return new File( pdeDirectory, descriptor.getId() + "_" + descriptor.getVersion() + ".zip" );
227         }
228     }
229 
230     /**
231      * 
232      * @return Ant targets to do the build depending PDE type
233      */
234     private String getAntTarget()
235     {
236         String targets = "clean build.jars zip.plugin";
237 
238         if ( this.descriptor instanceof FeatureDescriptor )
239         {
240             targets = "clean build.jars zip.distribution";
241         }
242 
243         return targets;
244     }
245 
246     /**
247      * 
248      * @return a generated bootstrap Ant build.xml so that it can be used to generate neccessary ant
249      *         build files to build the PDE project
250      * @throws MojoExecutionException build failures.
251      */
252     private File createBootstrapAntFile()
253         throws MojoExecutionException
254     {
255         File bootstrapFile = new File( this.project.getBuild().getDirectory() + "/pdeBuilder/build.xml" );
256         bootstrapFile.getParentFile().mkdirs();
257 
258         if ( this.eclipseBuildScriptProperties.get( "buildDirectory" ) == null )
259         {
260             this.eclipseBuildScriptProperties.put( "buildDirectory", this.getPDEBuildDirectory().getPath() );
261         }
262 
263         if ( this.eclipseBuildScriptProperties.get( "baseLocation" ) == null )
264         {
265             this.eclipseBuildScriptProperties.put( "baseLocation", this.getBaseLocation().getPath() );
266         }
267 
268         try
269         {
270             PrintStream out = new PrintStream( new FileOutputStream( bootstrapFile ) );
271 
272             out.println();
273             out.println( "<project default=\"generate\" > " );
274             out.println( "  <target name=\"generate\" >" );
275             out.println( "    <eclipse.buildScript " );
276             out.println( "      elements=\"" + DescriptorUtil.getPDEType( descriptor ) + "@" + this.descriptor.getId()
277                 + "\"" );
278 
279             Iterator iter = this.eclipseBuildScriptProperties.keySet().iterator();
280             while ( iter.hasNext() )
281             {
282                 String key = iter.next().toString();
283                 String value = (String) this.eclipseBuildScriptProperties.get( key );
284                 out.println( "      " + key + "=\"" + value + "\"" );
285             }
286 
287             out.println( "    />" );
288             out.println( "  </target>" );
289             out.println( "</project>" );
290 
291             out.close();
292         }
293         catch ( IOException e )
294         {
295             throw new MojoExecutionException( "Error generating bootstrap file: " + bootstrapFile );
296         }
297 
298         return bootstrapFile;
299     }
300 
301     /**
302      * Returns a command for creating a bootstrap ant file. The bootratp ant file is then used to
303      * create the build ant file for building the plugin or feature. A product does not require
304      * bootstrapping and will cause a build failure if one is attempted to be created.
305      * 
306      * @return a command to create a bootstrap ant file
307      * @throws MojoExecutionException build failures.
308      */
309     protected Commandline createBootstrapCommandLine()
310         throws MojoExecutionException
311     {
312         if ( pdeProductFilename != null )
313         {
314             throw new MojoExecutionException( "A Product Build does not require bootstrapping." );
315         }
316         File bootstrapFile = this.createBootstrapAntFile();
317         return this.createCommandLine( bootstrapFile );
318     }
319 }