/* * Copyright 2000-2010 JetBrains s.r.o. * * 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. */ package jetbrains.buildServer.eclipse.agent.builder; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.Map; import jetbrains.buildServer.RunBuildException; import jetbrains.buildServer.agent.BuildRunnerContext; import jetbrains.buildServer.agent.runner.ProgramCommandLine; import jetbrains.buildServer.agent.runner.SimpleProgramCommandLine; import jetbrains.buildServer.eclipse.EclipseConstants; import jetbrains.buildServer.eclipse.agent.EclipseBuilderFactory; import jetbrains.buildServer.eclipse.agent.IBuilder; import jetbrains.buildServer.eclipse.java.BuildDescriptor; import jetbrains.buildServer.eclipse.java.PlatformDescriptor; import jetbrains.buildServer.util.FileUtil; import org.apache.log4j.Logger; import org.jetbrains.annotations.NotNull; public class FeatureBasedProjectBuilder implements IBuilder { private final static Logger LOG = Logger.getLogger(FeatureBasedProjectBuilder.class); private PlatformDescriptor myPlatform; private BuildDescriptor myBuildDescriptor; private BuildRunnerContext myContext; private File myOutputFolder; private File myCopiedPropertiesFile; private HashMap myCommandLineSystemProperties; private String myQualifier; public FeatureBasedProjectBuilder(final @NotNull BuildRunnerContext buildRunnerContext, final @NotNull PlatformDescriptor platform, final @NotNull BuildDescriptor buildDescriptor) { myPlatform = platform; myBuildDescriptor = buildDescriptor; myContext = buildRunnerContext; } public String getName() { return "PDE builder"; } protected PlatformDescriptor getBuildPlatform() { return myPlatform; } protected BuildDescriptor getBuildDescriptor() { return myBuildDescriptor; } protected File getOutputFolder() { if (myOutputFolder == null) { final String outputParam = myContext.getRunnerParameters().get(EclipseConstants.SETTINGS_ARTIFACTS_OUTPUT_PATH); myOutputFolder = new File(myContext.getWorkingDirectory(), outputParam); } return myOutputFolder; } protected String getQualifier() { if (myQualifier == null) { final String qualifier = myContext.getRunnerParameters().get(EclipseConstants.SETTINGS_OPTIONS_CONTEXT_QUALIFIER); if (qualifier != null && qualifier.trim().length() > 0) { myQualifier = qualifier.trim(); } } return myQualifier; } protected String getJavacSource() { return myBuildDescriptor.getJavacSource(); } protected String getJavacTarget() { return myBuildDescriptor.getJavacTarget(); } protected Map getCommandLineSystemProperties() { if (myCommandLineSystemProperties == null) { myCommandLineSystemProperties = new HashMap(); } return myCommandLineSystemProperties; } protected ProgramCommandLine makeCommandLinesFor(final @NotNull String topLevelType, final @NotNull String topLevelTypeId) { final LinkedList args = new LinkedList(); //launching args.add("-jar"); args.add(String.format("\"%s\"", myPlatform.getEquinoxLauncherJar().getAbsolutePath())); LOG.debug(String.format("Use '%s' as Launcher", myPlatform.getEquinoxLauncherJar().getAbsolutePath())); args.add("-application"); args.add("org.eclipse.ant.core.antRunner"); args.add("-buildfile"); args.add(String.format("\"%s/scripts/build.xml\"", myPlatform.getPDEBuilderFolder())); LOG.debug(String.format("Use '%s' as Builder", myPlatform.getPDEBuilderFolder())); //TODO: move next to default properties of UI settings? final Map cliSysProps = loadUIDefined(loadCustom(loadDefault(getCommandLineSystemProperties()))); //target element cliSysProps.put("topLevelElementType", topLevelType); cliSysProps.put("topLevelElementId", topLevelTypeId); //fit command line populateSystemPropertiesParams(args, cliSysProps); return new SimpleProgramCommandLine(myContext, EclipseBuilderFactory.getJavaExecutable(myContext), args); } public ProgramCommandLine[] makeCommandLines() { return new ProgramCommandLine[] { makeCommandLinesFor(myBuildDescriptor.getType(), myBuildDescriptor.getTypeId()[0]) }; } private Map loadDefault(Map props) { //load build.properties file of PDE builder return props; } private Map loadCustom(Map props) { //load build.properties from a working folder return props; } private Map loadUIDefined(Map props) { props.put("generate.p2.metadata", Boolean.TRUE.toString()); props.put("p2.append", Boolean.TRUE.toString()); props.put("p2.publish.artifacts", Boolean.TRUE.toString()); props.put("p2.compress", Boolean.TRUE.toString()); props.put("p2.flavor", "tooling"); //output part final String repoPath = getOutputFolder().getAbsolutePath(); props.put("p2.metadata.repo", String.format("file:%s", repoPath));//TODO: UrlEncoder ? props.put("p2.artifact.repo", String.format("file:%s", repoPath));//TODO: UrlEncoder ? //project related properties final String workingDirectory = myContext.getWorkingDirectory().getAbsolutePath(); props.put("builder", String.format("\"%s\"", workingDirectory)); // outputUpdateJars = false props.put("buildDirectory", workingDirectory); props.put("forceContextQualifier", getQualifier()); // generateFeatureVersionSuffix=true // args.add(String.format("-DgenerateFeatureVersionSuffix=%s", Boolean.TRUE)); // base=C:/eclipse/eclipse-PDE-build final File eclipseHome = myPlatform.getHome().getParentFile(); props.put("base", String.format("\"%s\"", eclipseHome.getAbsolutePath()));//MUST skip 'eclipse' segment which past in a script // #pluginPath=Z:/tests/ws-PDERunner/pfeature/;Z:/tests/ws-PDERunner/pplugin.core;Z:/tests/ws-PDERunner/pplugin.ui if (Boolean.parseBoolean(myContext.getRunnerParameters().get(EclipseConstants.SETTINGS_ARTIFACTS_OUTPUT_ZIP))) { //TODO: setup archive } //javac's ... if (Boolean.parseBoolean(myContext.getRunnerParameters().get(EclipseConstants.SETTINGS_OPTIONS_INCLUDE_DEBUG_INFO))) { props.put(EclipseConstants.SETTINGS_OPTIONS_INCLUDE_DEBUG_INFO, Boolean.TRUE.toString()); } props.put(EclipseConstants.PDE_BUILD_PROP_JAVAC_SOURCE, getJavacSource()); props.put(EclipseConstants.PDE_BUILD_PROP_JAVAC_TARGET, getJavacTarget()); return props; } private void populateSystemPropertiesParams(final @NotNull Collection args, Map properties) { for (Map.Entry entry : properties.entrySet()) { args.add(String.format("-D%s=%s", entry.getKey(), entry.getValue())); LOG.debug(String.format("set %s='%s'", entry.getKey(), entry.getValue())); } } public void init() throws RunBuildException { try { //copy default 'build.properties' into work directory if one does not exist final File customBuildProperties = new File(myContext.getWorkingDirectory(), "build.properties"); if (customBuildProperties.exists()) { LOG.debug(String.format("Found custom build properties file: '%s'. Use this one for PDE build", customBuildProperties)); } else { final File defaultBuildPropertiesFile = new File(myPlatform.getPDEBuilderFolder(), "templates/headless-build/build.properties"); LOG.debug(String.format("Custom build properties is not found. Use '%s' as default one", defaultBuildPropertiesFile)); FileUtil.copy(defaultBuildPropertiesFile, customBuildProperties); LOG.debug(String.format("Default '%s' copied to '%s'", defaultBuildPropertiesFile, customBuildProperties)); myCopiedPropertiesFile = customBuildProperties; } } catch (IOException e) { throw new RunBuildException(e); } } public void destroy() { //cleanup copied properties file if (myCopiedPropertiesFile != null && myCopiedPropertiesFile.exists()) { LOG.debug(String.format("Remove copied to default propertues '%s'", myCopiedPropertiesFile)); FileUtil.delete(myCopiedPropertiesFile); myCopiedPropertiesFile = null; } //TODO: pack output folder if required } }