1 package org.codehaus.mojo.pde;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 }