package org.codehaus.mojo.pde; /* * Copyright 2006 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.util.Iterator; import java.util.Map; import java.util.Properties; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.codehaus.mojo.pde.descriptor.DescriptorUtil; import org.codehaus.mojo.pde.descriptor.FeatureDescriptor; import org.codehaus.mojo.pde.descriptor.ProductDescriptor; import org.codehaus.plexus.util.cli.Commandline; /** * Build PDE artifact. The output is not deployable. * * @goal pde * @phase compile * @requiresProject false * @aggregator * @requiresDependencyResolution test * * @version $Id:$ * @author dtran@gmail.com */ public class EclipsePDEMojo extends AbstractEclipsePDEMojo { /** * PDE Ant build temporary directory * * @parameter expression="${pdeTempDirectory}" * default-value="${project.build.directory}/pdeTemp" * * This param should be moved to systemProperties, but due a bug in PDE Ant build, we must * specify default value */ protected File pdeBuildTempFolder; /** * Additional system properties to be passed into PDE ant build. See the generated build.xml * files for list of overrideable properties. javacFailOnError=true is injected automatically if * not found. * * @parameter */ private Map buildProperties = new Properties(); /** * Additional system properties to be passed into PDE eclipse.buildScript task which is use to * generete PDE Ant build files. buildDirectory and baseLocation are automatically injected if * not set. * * @parameter */ private Map eclipseBuildScriptProperties = new Properties(); /** * {@inheritDoc} */ protected void initialize() throws MojoExecutionException, MojoFailureException { super.initialize(); } /** * {@inheritDoc} */ public void execute() throws MojoExecutionException, MojoFailureException { super.execute(); if ( pdeProductFilename == null ) { this.executeCommandLine( this.createBootstrapCommandLine() ); } this.executeCommandLine( this.createBuildCommandLine() ); } /** * @return a command line for building the PDE project. * @throws MojoExecutionException build failures. */ protected Commandline createBuildCommandLine() throws MojoExecutionException { Commandline cl = null; if ( pdeProductFilename != null ) { cl = createProductBuildCommandLine(); } else { cl = createFeatureBuildCommandLine(); } cl.createArgument().setLine( "-DbuildTempFolder=" + this.pdeBuildTempFolder ); if ( this.buildProperties.get( "javacFailOnError" ) == null ) { this.buildProperties.put( "javacFailOnError", "true" ); } Iterator iter = this.buildProperties.entrySet().iterator(); while ( iter.hasNext() ) { String arg = iter.next().toString(); cl.createArgument().setLine( "-D" + arg ); } return cl; } /** * Create a command line for a product build. * * See * http://help.eclipse.org/help32/topic/org.eclipse.pde.doc.user/guide/tasks/pde_product_build.htm * for more details. * * @return a command line for building the product. * @throws MojoExecutionException build failures. */ private Commandline createProductBuildCommandLine() throws MojoExecutionException { File buildFile = new File( eclipseInstall, "plugins/org.eclipse.pde.build_" + pdeBuildVersion + "/scripts/productBuild/productBuild.xml" ); Commandline cl = createCommandLine( buildFile ); File buildConfigDirectory = new File( pdeDirectory, pdeBuildConfigDirectory ); try { cl.createArgument().setLine( "-Dbuilder=" + buildConfigDirectory.getCanonicalPath() ); cl.createArgument().setLine( "-DbuildDirectory=" + this.getPDEBuildDirectory().getPath() ); } catch ( IOException e ) { throw new MojoExecutionException( "createProductBuildCommandLine failed: ", e ); } return cl; } /** * Create a command line for a feature build (plug-ins and fragments are also feature builds). * See * http://help.eclipse.org/help32/topic/org.eclipse.pde.doc.user/guide/tasks/pde_plugins_build.htm * for more details. * * @return a command line for building the feature */ private Commandline createFeatureBuildCommandLine() { Commandline cl = this.createCommandLine( new File( this.pdeDirectory, "build.xml" ), this.getAntTarget() ); return cl; } /** * Return the file that the PDE Ant build creates. Note that a PDE product build can create a * zip file for each config that is specified, however this mojo does not support that * situation. * * The product file from a PDE build is located at * ${buildDirectory}/${buildLabel}/${buildId}-${configs}.zip. * * However the buildConfiguration/build.properties file does not specify the buildDirectory as * this is overriden by the Mojo to always be "../..". * * <b>Note:</b> A normal pde build supports multiple configs to be built. This maven mojo only * supports <b>ONE</b> config to be built. Otherwise attaching the generated artifacts becomes * difficult, as which one is the main build and which ones are the extras with classifiers? * * @return the output of the PDE Ant build. * @throws MojoExecutionException build failures. */ protected File locateAntOutputFile() throws MojoExecutionException { if ( this.descriptor instanceof ProductDescriptor ) { String config = convertPdeConfigsToFilenameSuffix( buildConfigurationProperties.getString( "configs" ) ); return new File( getPDEBuildDirectory(), buildConfigurationProperties.getString( "buildLabel" ) + "/" + buildConfigurationProperties.getProperty( "buildId" ) + "-" + config + ".zip" ); } if ( this.descriptor instanceof FeatureDescriptor ) { return new File( this.pdeDirectory, this.descriptor.getId() + "_" + this.descriptor.getVersion() + ".bin.dist.zip" ); } else { return new File( pdeDirectory, descriptor.getId() + "_" + descriptor.getVersion() + ".zip" ); } } /** * * @return Ant targets to do the build depending PDE type */ private String getAntTarget() { String targets = "clean build.jars zip.plugin"; if ( this.descriptor instanceof FeatureDescriptor ) { targets = "clean build.jars zip.distribution"; } return targets; } /** * * @return a generated bootstrap Ant build.xml so that it can be used to generate neccessary ant * build files to build the PDE project * @throws MojoExecutionException build failures. */ private File createBootstrapAntFile() throws MojoExecutionException { File bootstrapFile = new File( this.project.getBuild().getDirectory() + "/pdeBuilder/build.xml" ); bootstrapFile.getParentFile().mkdirs(); if ( this.eclipseBuildScriptProperties.get( "buildDirectory" ) == null ) { this.eclipseBuildScriptProperties.put( "buildDirectory", this.getPDEBuildDirectory().getPath() ); } if ( this.eclipseBuildScriptProperties.get( "baseLocation" ) == null ) { this.eclipseBuildScriptProperties.put( "baseLocation", this.getBaseLocation().getPath() ); } try { PrintStream out = new PrintStream( new FileOutputStream( bootstrapFile ) ); out.println(); out.println( "<project default=\"generate\" > " ); out.println( " <target name=\"generate\" >" ); out.println( " <eclipse.buildScript " ); out.println( " elements=\"" + DescriptorUtil.getPDEType( descriptor ) + "@" + this.descriptor.getId() + "\"" ); Iterator iter = this.eclipseBuildScriptProperties.keySet().iterator(); while ( iter.hasNext() ) { String key = iter.next().toString(); String value = (String) this.eclipseBuildScriptProperties.get( key ); out.println( " " + key + "=\"" + value + "\"" ); } out.println( " />" ); out.println( " </target>" ); out.println( "</project>" ); out.close(); } catch ( IOException e ) { throw new MojoExecutionException( "Error generating bootstrap file: " + bootstrapFile ); } return bootstrapFile; } /** * Returns a command for creating a bootstrap ant file. The bootratp ant file is then used to * create the build ant file for building the plugin or feature. A product does not require * bootstrapping and will cause a build failure if one is attempted to be created. * * @return a command to create a bootstrap ant file * @throws MojoExecutionException build failures. */ protected Commandline createBootstrapCommandLine() throws MojoExecutionException { if ( pdeProductFilename != null ) { throw new MojoExecutionException( "A Product Build does not require bootstrapping." ); } File bootstrapFile = this.createBootstrapAntFile(); return this.createCommandLine( bootstrapFile ); } }