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
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
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
190 loadBuildConfigurationProperties();
191
192 }
193
194 this.descriptor = DescriptorUtil.getDescriptor( this.pdeDirectory, pdeProductFilename );
195
196
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 }