blob: 5960aa6912a3d441313f4f94fdb3d546aa73f9c4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
* Lars Vogel <Lars.Vogel@vogella.com> - Bug 477527
* Jan-Ove Weichel <janove.weichel@vogella.com> - Bug 477658
* Martin Karpisek <martin.karpisek@gmail.com> - Bug 525701
*******************************************************************************/
package org.eclipse.pde.internal.core.exports;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.ant.core.AntCorePlugin;
import org.eclipse.ant.core.AntCorePreferences;
import org.eclipse.ant.core.AntRunner;
import org.eclipse.ant.core.IAntClasspathEntry;
import org.eclipse.ant.core.Property;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.preferences.DefaultScope;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.launching.JavaRuntime;
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.service.resolver.State;
import org.eclipse.osgi.util.NLS;
import org.eclipse.pde.core.IModel;
import org.eclipse.pde.core.build.IBuild;
import org.eclipse.pde.core.build.IBuildEntry;
import org.eclipse.pde.core.build.IBuildModel;
import org.eclipse.pde.core.plugin.IPluginModelBase;
import org.eclipse.pde.core.plugin.PluginRegistry;
import org.eclipse.pde.core.plugin.TargetPlatform;
import org.eclipse.pde.internal.build.AbstractScriptGenerator;
import org.eclipse.pde.internal.build.BuildScriptGenerator;
import org.eclipse.pde.internal.build.IBuildPropertiesConstants;
import org.eclipse.pde.internal.build.IPDEBuildConstants;
import org.eclipse.pde.internal.build.IXMLConstants;
import org.eclipse.pde.internal.build.site.QualifierReplacer;
import org.eclipse.pde.internal.core.ClasspathHelper;
import org.eclipse.pde.internal.core.FeatureModelManager;
import org.eclipse.pde.internal.core.ICoreConstants;
import org.eclipse.pde.internal.core.P2Utils;
import org.eclipse.pde.internal.core.PDECore;
import org.eclipse.pde.internal.core.PDECoreMessages;
import org.eclipse.pde.internal.core.TargetPlatformHelper;
import org.eclipse.pde.internal.core.XMLPrintHandler;
import org.eclipse.pde.internal.core.build.WorkspaceBuildModel;
import org.eclipse.pde.internal.core.bundle.BundlePluginModel;
import org.eclipse.pde.internal.core.feature.ExternalFeatureModel;
import org.eclipse.pde.internal.core.feature.FeatureChild;
import org.eclipse.pde.internal.core.ifeature.IFeature;
import org.eclipse.pde.internal.core.ifeature.IFeatureChild;
import org.eclipse.pde.internal.core.ifeature.IFeatureModel;
import org.eclipse.pde.internal.core.ifeature.IFeaturePlugin;
import org.eclipse.pde.internal.core.project.PDEProject;
import org.eclipse.pde.internal.core.target.TargetMetadataCollector;
import org.eclipse.pde.internal.core.util.CoreUtility;
import org.osgi.framework.InvalidSyntaxException;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
public class FeatureExportOperation extends Job {
// Location where the build takes place
protected String fBuildTempLocation;
protected String fBuildTempMetadataLocation;
private String fDevProperties;
private static boolean fHasErrors;
protected HashMap<String, String> fAntBuildProperties;
protected WorkspaceExportHelper fWorkspaceExportHelper;
protected State fStateCopy;
protected static String FEATURE_POST_PROCESSING = "features.postProcessingSteps.properties"; //$NON-NLS-1$
protected static String PLUGIN_POST_PROCESSING = "plugins.postProcessingSteps.properties"; //$NON-NLS-1$
private static final String[] GENERIC_CONFIG = new String[] {"*", "*", "*", ""}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
protected FeatureExportInfo fInfo;
private boolean isPreviewFeatureEnabled;
public FeatureExportOperation(FeatureExportInfo info, String name) {
super(name);
fInfo = info;
String qualifier = info.qualifier;
if (qualifier == null) {
qualifier = QualifierReplacer.getDateQualifier();
}
QualifierReplacer.setGlobalQualifier(qualifier);
fBuildTempLocation = PDECore.getDefault().getStateLocation().append("temp").toString(); //$NON-NLS-1$
fBuildTempMetadataLocation = PDECore.getDefault().getStateLocation().append("tempp2metadata").toString(); //$NON-NLS-1$
}
@Override
protected IStatus run(IProgressMonitor monitor) {
try {
createDestination();
String[][] configurations = fInfo.targets;
if (configurations == null) {
configurations = new String[][] {null};
}
SubMonitor subMonitor = SubMonitor.convert(monitor, "Exporting...", (fInfo.items.length * 23) + 5 + 10); //$NON-NLS-1$
IStatus status = testBuildWorkspaceBeforeExport(subMonitor.split(10));
if (fInfo.exportSource && fInfo.exportSourceBundle) {
// create a feature to contain all plug-ins and features depth first
String featureID = "org.eclipse.pde.container.feature"; //$NON-NLS-1$
String fFeatureLocation = fBuildTempLocation + File.separator + featureID;
createFeature(featureID, fFeatureLocation, fInfo.items, null, null, null);
ExternalFeatureModel model = new ExternalFeatureModel();
model.setInstallLocation(fFeatureLocation);
try (InputStream stream = new BufferedInputStream(new FileInputStream(
new File(fFeatureLocation + File.separator + ICoreConstants.FEATURE_FILENAME_DESCRIPTOR)))) {
model.load(stream, true);
}
doExport(model, null, subMonitor.split(20));
} else {
for (Object item : fInfo.items) {
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
try {
doExport((IFeatureModel) item, configurations, subMonitor.split(20));
} catch (CoreException e) {
return e.getStatus();
} finally {
cleanup(subMonitor.split(3));
}
}
}
return status;
} catch (InvocationTargetException | CoreException e) {
return Status.error(PDECoreMessages.FeatureBasedExportOperation_ProblemDuringExport, e.getCause() != null ? e.getCause() : e);
} catch (IOException e) {
return Status.error(PDECoreMessages.FeatureBasedExportOperation_ProblemDuringExport, e);
}
}
protected void save(File file, Properties properties, String header) {
try (FileOutputStream stream = new FileOutputStream(file)) {
properties.store(stream, header);
} catch (IOException e) {
PDECore.logException(e);
}
}
/**
* Takes the generated metadata and adds it to the destination zip.
* This method should only be called if exporting to an archive file
* and metadata was generated at fBuildMetadataLocation.
* @param monitor progress monitor
*/
protected void appendMetadataToArchive(String[] configuration, IProgressMonitor monitor) {
String filename = fInfo.zipFileName;
if (configuration != null) {
int i = filename.lastIndexOf('.');
filename = filename.substring(0, i) + '.' + configuration[0] + '.' + configuration[1] + '.' + configuration[2] + filename.substring(i);
}
String archive = fInfo.destinationDirectory + File.separator + filename;
File scriptFile = null;
SubMonitor subMonitor = SubMonitor.convert(monitor, 1);
try {
scriptFile = createScriptFile("append.xml"); //$NON-NLS-1$
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().newDocument();
Element root = doc.createElement("project"); //$NON-NLS-1$
root.setAttribute("name", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
root.setAttribute("default", "append"); //$NON-NLS-1$ //$NON-NLS-2$
root.setAttribute("basedir", "."); //$NON-NLS-1$ //$NON-NLS-2$
doc.appendChild(root);
Element target = doc.createElement("target"); //$NON-NLS-1$
target.setAttribute("name", "clean"); //$NON-NLS-1$ //$NON-NLS-2$
Element child = doc.createElement("delete"); //$NON-NLS-1$
child.setAttribute("dir", fBuildTempMetadataLocation); //$NON-NLS-1$
target.appendChild(child);
root.appendChild(target);
target = doc.createElement("target"); //$NON-NLS-1$
target.setAttribute("name", "append"); //$NON-NLS-1$ //$NON-NLS-2$
child = doc.createElement("zip"); //$NON-NLS-1$
child.setAttribute("zipfile", archive); //$NON-NLS-1$
child.setAttribute("basedir", fBuildTempMetadataLocation); //$NON-NLS-1$
child.setAttribute("update", "true"); //$NON-NLS-1$ //$NON-NLS-2$
target.appendChild(child);
root.appendChild(target);
XMLPrintHandler.writeFile(doc, scriptFile);
String[] targets = new String[] {"append", "clean"}; //$NON-NLS-1$ //$NON-NLS-2$
AntRunner runner = new AntRunner();
runner.setBuildFileLocation(scriptFile.getAbsolutePath());
runner.setExecutionTargets(targets);
runner.run(subMonitor.split(1));
} catch (FactoryConfigurationError | ParserConfigurationException | CoreException | IOException e) {
PDECore.logException(e);
} finally {
if (scriptFile != null && scriptFile.exists()) {
scriptFile.delete();
}
}
}
private void createDestination(String os, String ws, String arch) throws InvocationTargetException {
if (!fInfo.toDirectory || groupedConfigurations()) {
return;
}
File file = new File(fInfo.destinationDirectory, os + '.' + ws + '.' + arch);
if (!file.exists() || !file.isDirectory()) {
if (!file.mkdirs()) {
throw new InvocationTargetException(new Exception(PDECoreMessages.ExportWizard_badDirectory));
}
}
}
private void doExport(IFeatureModel model, String[][] configs, IProgressMonitor monitor) throws CoreException, InvocationTargetException {
IFeature feature = model.getFeature();
if (configs == null || configs.length == 0 || configs[0] == null) {
configs = new String[][] {{getOS(feature), getWS(feature), getOSArch(feature)}};
} else {
for (String[] config : configs) {
createDestination(config[0], config[1], config[2]);
}
}
try {
String location = model.getInstallLocation();
if (fInfo.useJarFormat) {
createPostProcessingFile(new File(location, FEATURE_POST_PROCESSING));
createPostProcessingFile(new File(location, PLUGIN_POST_PROCESSING));
}
doExport(feature.getId(), feature.getVersion(), location, configs, monitor);
} finally {
deleteBuildFiles(model);
}
}
protected void createPostProcessingFile(File file) {
try (FileOutputStream stream = new FileOutputStream(file);) {
Properties prop = new Properties();
prop.put("*", "updateJar"); //$NON-NLS-1$ //$NON-NLS-2$
prop.store(stream, ""); //$NON-NLS-1$
stream.flush();
} catch (IOException e) {
}
}
protected void doExport(String featureID, String version, String featureLocation, String[][] configs, IProgressMonitor monitor) throws CoreException, InvocationTargetException {
fHasErrors = false;
int subTaskLength = 6 + (configs.length * 4) + (publishingP2Metadata() ? 2 : 0);
SubMonitor subMonitor = SubMonitor.convert(monitor, PDECoreMessages.FeatureExportJob_taskName, subTaskLength);
HashMap<String, String> properties = createAntBuildProperties(configs);
BuildScriptGenerator generator = new BuildScriptGenerator();
setupGenerator(generator, featureID, version, configs, featureLocation);
generator.generate();
subMonitor.split(1);
subMonitor.setTaskName(PDECoreMessages.FeatureExportOperation_runningBuildScript);
// compile the classes
runScript(featureLocation + IPath.SEPARATOR + "compile." + featureID + ".xml", new String[] {"main"}, properties, subMonitor.split(1)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
// grab the source if needed
if (fInfo.exportSource && !fInfo.exportSourceBundle) {
runScript(getBuildScriptName(featureLocation), new String[] {"build.sources"}, properties, subMonitor.split(1)); //$NON-NLS-1$
}
if (publishingP2Metadata()) {
subMonitor.setTaskName(PDECoreMessages.FeatureExportOperation_publishingMetadata);
runScript(getAssembleP2ScriptName(featureID, featureLocation), new String[] {"main"}, properties, subMonitor.split(2)); //$NON-NLS-1$
//metadata implies groups if we aren't exporting products
if (groupedConfigurations()) {
configs = new String[][] {{"group", "group", "group"}}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
}
}
subMonitor.setTaskName(PDECoreMessages.FeatureExportOperation_runningAssemblyScript);
for (String[] config : configs) {
setArchiveLocation(properties, config[0], config[1], config[2]);
runScript(getAssemblyScriptName(featureID, config[0], config[1], config[2], featureLocation), new String[] {"main"}, //$NON-NLS-1$
properties, subMonitor.split(2));
}
subMonitor.setTaskName(PDECoreMessages.FeatureExportOperation_runningPackagerScript);
for (String[] config : configs) {
setArchiveLocation(properties, config[0], config[1], config[2]);
runScript(getPackagerScriptName(featureID, config[0], config[1], config[2], featureLocation), null, properties, subMonitor.split(2));
}
properties.put("destination.temp.folder", fBuildTempLocation + "/pde.logs"); //$NON-NLS-1$ //$NON-NLS-2$
runScript(getBuildScriptName(featureLocation), new String[] {"gather.logs"}, properties, subMonitor.split(2)); //$NON-NLS-1$
}
protected boolean groupedConfigurations() {
//feature export with p2 metadata results in a grouped repo
return publishingP2Metadata();
}
private void setArchiveLocation(Map<String, String> antProperties, String os, String ws, String arch) {
if (!fInfo.toDirectory) {
String filename = fInfo.zipFileName;
if (fInfo.targets != null && !groupedConfigurations()) {
int i = filename.lastIndexOf('.');
filename = filename.substring(0, i) + '.' + os + '.' + ws + '.' + arch + filename.substring(i);
}
antProperties.put(IXMLConstants.PROPERTY_ARCHIVE_FULLPATH, fInfo.destinationDirectory + File.separator + filename);
} else {
String dir = fInfo.destinationDirectory;
if (fInfo.targets != null && !groupedConfigurations()) {
dir += File.separatorChar + os + '.' + ws + '.' + arch;
}
antProperties.put(IXMLConstants.PROPERTY_ASSEMBLY_TMP, dir);
}
}
public void deleteBuildFiles(Object object) throws CoreException {
IModel model = null;
if (object instanceof BundleDescription) {
model = PluginRegistry.findModel((BundleDescription) object);
} else if (object instanceof IModel) {
model = (IModel) object;
}
if (model == null) {
return;
}
if (model.getUnderlyingResource() != null && !isCustomBuild(model)) {
String directory = (model instanceof IFeatureModel) ? ((IFeatureModel) model).getInstallLocation() : ((IPluginModelBase) model).getInstallLocation();
File dir = new File(directory);
File[] children = dir.listFiles();
if (children != null) {
for (int i = 0; i < children.length; i++) {
if (!children[i].isDirectory()) {
String filename = children[i].getName();
if (filename.equals("build.xml") //$NON-NLS-1$
|| (filename.startsWith("javaCompiler.") && filename.endsWith(".args")) //$NON-NLS-1$ //$NON-NLS-2$
|| (filename.startsWith("assemble.") && filename.endsWith(".xml")) //$NON-NLS-1$ //$NON-NLS-2$
|| (filename.startsWith("package.") && filename.endsWith(".xml")) //$NON-NLS-1$ //$NON-NLS-2$
|| (filename.startsWith("compile.") && filename.endsWith(".xml")) //$NON-NLS-1$ //$NON-NLS-2$
|| filename.equals(FEATURE_POST_PROCESSING) || filename.equals(PLUGIN_POST_PROCESSING)) {
children[i].delete();
}
} else if (children[i].getName().equals("temp.folder")) { //$NON-NLS-1$
CoreUtility.deleteContent(children[i]);
}
}
}
}
if (model instanceof IFeatureModel) {
IFeature feature = ((IFeatureModel) model).getFeature();
IFeatureChild[] children = feature.getIncludedFeatures();
for (IFeatureChild featureChild : children) {
IFeature ref = ((FeatureChild) featureChild).getReferencedFeature();
if (ref != null) {
deleteBuildFiles(ref.getModel());
}
}
IFeaturePlugin[] plugins = feature.getPlugins();
for (IFeaturePlugin featurePlugin : plugins) {
IPluginModelBase plugin = PluginRegistry.findModel(featurePlugin.getId());
if (plugin != null) {
deleteBuildFiles(plugin);
}
}
}
}
private String getBuildScriptName(String featureLocation) {
return featureLocation + IPath.SEPARATOR + "build.xml"; //$NON-NLS-1$
}
protected String getAssemblyScriptName(String featureID, String os, String ws, String arch, String featureLocation) {
return featureLocation + IPath.SEPARATOR + "assemble." //$NON-NLS-1$
+ featureID + "." + os + "." //$NON-NLS-1$ //$NON-NLS-2$
+ ws + "." + arch //$NON-NLS-1$
+ ".xml"; //$NON-NLS-1$
}
protected String getAssembleP2ScriptName(String featureID, String featureLocation) {
return featureLocation + IPath.SEPARATOR + "assemble." + featureID + ".p2.xml"; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Execute the script at the given location.
*
* @param location the script to run
* @param targets the targets in the script to run, use <code>null</code> to run all
* @param properties map of user properties
* @param monitor progress monitor
* @throws InvocationTargetException
* @throws CoreException
*/
protected void runScript(String location, String[] targets, Map<String, String> properties, IProgressMonitor monitor) throws InvocationTargetException, CoreException {
AntRunner runner = new AntRunner();
runner.addUserProperties(properties);
runner.setAntHome(location);
runner.setBuildFileLocation(location);
runner.addBuildListener("org.eclipse.pde.internal.core.ant.ExportBuildListener"); //$NON-NLS-1$
runner.setExecutionTargets(targets);
if (fInfo.signingInfo != null) {
AntCorePreferences preferences = AntCorePlugin.getPlugin().getPreferences();
IAntClasspathEntry entry = preferences.getToolsJarEntry();
if (entry != null) {
IAntClasspathEntry[] classpath = preferences.getAntHomeClasspathEntries();
URL[] urls = new URL[classpath.length + 2];
for (int i = 0; i < classpath.length; i++) {
urls[i] = classpath[i].getEntryURL();
}
IPath path = new Path(entry.getEntryURL().toString()).removeLastSegments(2);
path = path.append("bin"); //$NON-NLS-1$
try {
urls[classpath.length] = new URL(path.toString());
} catch (MalformedURLException e) {
urls[classpath.length] = entry.getEntryURL();
} finally {
urls[classpath.length + 1] = entry.getEntryURL();
}
runner.setCustomClasspath(urls);
}
}
runner.run(monitor);
}
protected String getPackagerScriptName(String featureID, String os, String ws, String arch, String featureLocation) {
return featureLocation + IPath.SEPARATOR + "package." //$NON-NLS-1$
+ featureID + "." + os + "." //$NON-NLS-1$ //$NON-NLS-2$
+ ws + "." + arch //$NON-NLS-1$
+ ".xml"; //$NON-NLS-1$
}
protected HashMap<String, String> createAntBuildProperties(String[][] configs) {
if (fAntBuildProperties == null) {
fAntBuildProperties = new HashMap<>(15);
List<Property> defaultProperties = AntCorePlugin.getPlugin().getPreferences().getProperties();
ListIterator<Property> li = defaultProperties.listIterator();
while (li.hasNext()) {
Property prop = li.next();
fAntBuildProperties.put(prop.getName(), prop.getValue());
}
if (fInfo.signingInfo != null) {
fAntBuildProperties.put(IXMLConstants.PROPERTY_SIGN_ALIAS, fInfo.signingInfo[0]);
fAntBuildProperties.put(IXMLConstants.PROPERTY_SIGN_KEYSTORE, fInfo.signingInfo[1]);
fAntBuildProperties.put(IXMLConstants.PROPERTY_SIGN_STOREPASS, fInfo.signingInfo[2]);
fAntBuildProperties.put(IXMLConstants.PROPERTY_SIGN_KEYPASS, fInfo.signingInfo[3]);
}
if (fInfo.jnlpInfo != null) {
fAntBuildProperties.put(IXMLConstants.PROPERTY_JNLP_CODEBASE, fInfo.jnlpInfo[0]);
fAntBuildProperties.put(IXMLConstants.PROPERTY_JNLP_J2SE, fInfo.jnlpInfo[1]);
}
fAntBuildProperties.put(IXMLConstants.PROPERTY_BUILD_TEMP, fBuildTempLocation + "/destination"); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_FEATURE_TEMP_FOLDER, fBuildTempLocation + "/destination"); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_INCLUDE_CHILDREN, "true"); //$NON-NLS-1$
fAntBuildProperties.put("eclipse.running", "true"); //$NON-NLS-1$ //$NON-NLS-2$
fAntBuildProperties.put(IXMLConstants.PROPERTY_GENERATE_API_DESCRIPTION, "true"); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_BASE_OS, TargetPlatform.getOS());
fAntBuildProperties.put(IXMLConstants.PROPERTY_BASE_WS, TargetPlatform.getWS());
fAntBuildProperties.put(IXMLConstants.PROPERTY_BASE_ARCH, TargetPlatform.getOSArch());
fAntBuildProperties.put(IXMLConstants.PROPERTY_BASE_NL, TargetPlatform.getNL());
fAntBuildProperties.put(IXMLConstants.PROPERTY_BOOTCLASSPATH, BuildUtilities.getBootClasspath());
IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
IExecutionEnvironment[] envs = manager.getExecutionEnvironments();
for (IExecutionEnvironment env : envs) {
String id = env.getId();
if (id != null) {
fAntBuildProperties.put(id, BuildUtilities.getBootClasspath(id));
}
}
fAntBuildProperties.put(IXMLConstants.PROPERTY_JAVAC_FAIL_ON_ERROR, "false"); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_JAVAC_DEBUG_INFO, "on"); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_JAVAC_VERBOSE, "false"); //$NON-NLS-1$
if (isPreviewFeatureEnabled){
fAntBuildProperties.put(IXMLConstants.PROPERTY_JAVAC_COMPILERARG, "--enable-preview"); //$NON-NLS-1$
}
IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
IEclipsePreferences def = DefaultScope.INSTANCE.getNode(JavaCore.PLUGIN_ID);
String source = prefs.get(JavaCore.COMPILER_SOURCE, null);
if (source == null) {
source = def.get(JavaCore.COMPILER_SOURCE, null);
}
if (source != null) {
fAntBuildProperties.put(IXMLConstants.PROPERTY_JAVAC_SOURCE, source);
}
String target = prefs.get(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, null);
if (target == null) {
target = def.get(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, null);
}
if (target != null) {
float tar = Float.parseFloat(target);
if (tar < 1.8) {
target = "1.8"; //$NON-NLS-1$
}
fAntBuildProperties.put(IXMLConstants.PROPERTY_JAVAC_TARGET, target);
}
// for the assembler...
fAntBuildProperties.put(IXMLConstants.PROPERTY_BUILD_DIRECTORY, fBuildTempLocation + "/assemblyLocation"); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_BUILD_LABEL, "."); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_COLLECTING_FOLDER, "."); //$NON-NLS-1$
String prefix = Platform.getOS().equals("macosx") ? "." : ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
fAntBuildProperties.put(IXMLConstants.PROPERTY_ARCHIVE_PREFIX, prefix);
fAntBuildProperties.put(IXMLConstants.PROPERTY_TAR_ARGS, ""); //$NON-NLS-1$
fAntBuildProperties.put(IXMLConstants.PROPERTY_RUN_PACKAGER, "true"); //$NON-NLS-1$
}
setP2MetaDataProperties(fAntBuildProperties);
return fAntBuildProperties;
}
/**
* Whether or not to use new metadata publishing or old generation
*/
protected boolean publishingP2Metadata() {
return fInfo.useJarFormat && fInfo.exportMetadata;
}
/**
* Returns a list of URI metadata repository locations that contain metadata for some
* or all of the target platform. The repositories may not contain metadata for all
* plugins in the target. This method returns <code>null</code> if the target does not
* have any repositories.
*
* @return list of URI representing metadata repositories or <code>null</code>
*/
protected URI[] getMetadataContextFromTargetPlatform() {
try {
URI[] context = TargetMetadataCollector.getMetadataRepositories(null);
if (context.length > 0) {
return context;
}
} catch (CoreException e) {
return null;
}
return null;
}
/**
* @return the location of the category definition file, or null if none is specified
*/
protected String getCategoryDefinition() {
return fInfo.categoryDefinition;
}
/**
* Adds the necessary properties to invoke the p2 metadata generator. This method will
* be called when creating the ant build properties map.
*
* @param map the map to add generator properties to
*/
protected void setP2MetaDataProperties(Map<String, String> map) {
if (fInfo.useJarFormat && fInfo.exportMetadata) {
map.put(IXMLConstants.TARGET_P2_METADATA, IBuildPropertiesConstants.TRUE);
map.put(IBuildPropertiesConstants.PROPERTY_P2_FLAVOR, P2Utils.P2_FLAVOR_DEFAULT);
map.put(IBuildPropertiesConstants.PROPERTY_P2_PUBLISH_ARTIFACTS, IBuildPropertiesConstants.FALSE);
map.put(IBuildPropertiesConstants.PROPERTY_P2_FINAL_MODE_OVERRIDE, IBuildPropertiesConstants.TRUE);
map.put(IBuildPropertiesConstants.PROPERTY_P2_COMPRESS, IBuildPropertiesConstants.TRUE);
map.put(IBuildPropertiesConstants.PROPERTY_P2_GATHERING, Boolean.toString(publishingP2Metadata()));
if (getCategoryDefinition() != null) {
map.put(IBuildPropertiesConstants.PROPERTY_P2_CATEGORY_DEFINITION, getCategoryDefinition());
}
try {
String destination = ""; //$NON-NLS-1$
if (publishingP2Metadata()) {
destination = new File(fBuildTempMetadataLocation).toURL().toString();
map.put(IBuildPropertiesConstants.PROPERTY_P2_BUILD_REPO, destination);
} else {
if (fInfo.toDirectory) {
destination = new File(fInfo.destinationDirectory).toURL().toString();
} else {
destination = new File(fBuildTempMetadataLocation).toURI().toURL().toString();
}
map.put(IBuildPropertiesConstants.PROPERTY_P2_METADATA_REPO, destination);
map.put(IBuildPropertiesConstants.PROPERTY_P2_ARTIFACT_REPO, destination);
}
map.put(IBuildPropertiesConstants.PROPERTY_P2_METADATA_REPO_NAME, PDECoreMessages.FeatureExportOperation_0);
map.put(IBuildPropertiesConstants.PROPERTY_P2_ARTIFACT_REPO_NAME, PDECoreMessages.FeatureExportOperation_0);
} catch (MalformedURLException e) {
PDECore.log(e);
}
}
}
private String getOS(IFeature feature) {
String os = feature.getOS();
if (os == null || os.trim().length() == 0 || os.indexOf(',') != -1 || os.equals("*")) { //$NON-NLS-1$
return TargetPlatform.getOS();
}
return os;
}
private String getWS(IFeature feature) {
String ws = feature.getWS();
if (ws == null || ws.trim().length() == 0 || ws.indexOf(',') != -1 || ws.equals("*")) { //$NON-NLS-1$
return TargetPlatform.getWS();
}
return ws;
}
private String getOSArch(IFeature feature) {
String arch = feature.getArch();
if (arch == null || arch.trim().length() == 0 || arch.indexOf(',') != -1 || arch.equals("*")) { //$NON-NLS-1$
return TargetPlatform.getOSArch();
}
return arch;
}
protected void createDestination() throws InvocationTargetException {
File file = new File(fInfo.destinationDirectory);
if (!file.exists() || !file.isDirectory()) {
if (!file.mkdirs()) {
throw new InvocationTargetException(new Exception(PDECoreMessages.ExportWizard_badDirectory));
}
}
File metadataTemp = new File(fBuildTempMetadataLocation);
if (metadataTemp.exists()) {
//make sure our build metadata repo is clean
deleteDir(metadataTemp);
}
}
protected void deleteDir(File dir) {
if (dir.exists()) {
if (dir.isDirectory()) {
File[] children = dir.listFiles();
if (children != null) {
for (File element : children) {
deleteDir(element);
}
}
}
dir.delete();
}
}
private String getConfigInfo(String[][] configs) {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < configs.length; i++) {
if (i > 0) {
buffer.append('&');
}
buffer.append(configs[i][0]);
buffer.append(',');
buffer.append(configs[i][1]);
buffer.append(',');
buffer.append(configs[i][2]);
}
return buffer.toString();
}
private String getArchivesFormat(String[][] configs) {
StringBuilder buffer = new StringBuilder();
for (int i = 0; i < configs.length; i++) {
if (i > 0) {
buffer.append('&');
}
buffer.append(configs[i][0]);
buffer.append(',');
buffer.append(configs[i][1]);
buffer.append(',');
buffer.append(configs[i][2]);
buffer.append('-');
buffer.append(fInfo.toDirectory ? IXMLConstants.FORMAT_FOLDER : IXMLConstants.FORMAT_ANTZIP);
}
if (groupedConfigurations()) {
buffer.append('&');
buffer.append("group,group,group-"); //$NON-NLS-1$
buffer.append(fInfo.toDirectory ? IXMLConstants.FORMAT_FOLDER : IXMLConstants.FORMAT_ANTZIP);
}
return buffer.toString();
}
protected void setupGenerator(BuildScriptGenerator generator, String featureID, String versionId, String[][] configs, String featureLocation) throws CoreException {
generator.setChildren(true);
generator.setWorkingDirectory(featureLocation);
generator.setDevEntries(getDevProperties());
generator.setElements(new String[] {"feature@" + featureID + (versionId == null ? "" : ":" + versionId)}); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
generator.setPluginPath(getPaths());
generator.setReportResolutionErrors(false);
generator.setIgnoreMissingPropertiesFile(true);
generator.setSignJars(fInfo.signingInfo != null);
generator.setGenerateJnlp(fInfo.jnlpInfo != null);
generator.setFlattenDependencies(true);
AbstractScriptGenerator.setConfigInfo(getConfigInfo(configs)); //This needs to be set before we set the format
generator.setArchivesFormat(getArchivesFormat(configs));
generator.setPDEState(getBuildState());
generator.setNextId(TargetPlatformHelper.getPDEState().getNextId());
if (fInfo.useWorkspaceCompiledClasses) {
generator.setUseWorkspaceBinaries(true);
generator.setStateExtraData(TargetPlatformHelper.getBundleClasspaths(TargetPlatformHelper.getPDEState()), TargetPlatformHelper.getPatchMap(TargetPlatformHelper.getPDEState()), getWorkspaceExportHelper().getWorkspaceOutputFolders(fInfo.items));
} else {
generator.setStateExtraData(TargetPlatformHelper.getBundleClasspaths(TargetPlatformHelper.getPDEState()), TargetPlatformHelper.getPatchMap(TargetPlatformHelper.getPDEState()));
}
AbstractScriptGenerator.setForceUpdateJar(false);
AbstractScriptGenerator.setEmbeddedSource(fInfo.exportSource && !fInfo.exportSourceBundle);
// allow for binary cycles
Properties properties = new Properties();
properties.put(IBuildPropertiesConstants.PROPERTY_ALLOW_BINARY_CYCLES, Boolean.toString(fInfo.allowBinaryCycles));
properties.put(IBuildPropertiesConstants.PROPERTY_P2_GATHERING, Boolean.toString(publishingP2Metadata()));
//TODO this is duplicate from createAntBuildProperties
IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
IExecutionEnvironment[] envs = manager.getExecutionEnvironments();
for (IExecutionEnvironment env : envs) {
String id = env.getId();
if (id != null) {
properties.put(id, BuildUtilities.getBootClasspath(id));
}
}
generator.setImmutableAntProperties(properties);
// allow for custom execution environments
String[] extraLocations = ExecutionEnvironmentProfileManager.getCustomProfileLocations();
if (extraLocations != null) {
generator.setEESources(extraLocations);
}
// if we are exporting metadata, provide context repositories from the target if available and option is turned on
if (publishingP2Metadata()) {
URI[] contexts = getMetadataContextFromTargetPlatform();
if (contexts != null) {
generator.setContextMetadataRepositories(contexts);
}
}
}
protected State getState(String os, String ws, String arch) {
State main = TargetPlatformHelper.getState();
if (os.equals(TargetPlatform.getOS()) && ws.equals(TargetPlatform.getWS()) && arch.equals(TargetPlatform.getOSArch())) {
return main;
}
if (fStateCopy == null) {
copyState(main);
}
Dictionary<String, String>[] dictionaries = fStateCopy.getPlatformProperties();
for (Dictionary<String, String> properties : dictionaries) {
properties.put("osgi.os", os); //$NON-NLS-1$
properties.put("osgi.ws", ws); //$NON-NLS-1$
properties.put("osgi.arch", arch); //$NON-NLS-1$
}
fStateCopy.resolve(false);
return fStateCopy;
}
protected State getBuildState() {
State main = TargetPlatformHelper.getState();
if (fStateCopy == null) {
copyState(main);
}
//this state is expected to get platform properties set by pde.build and re-resolved there.
//TODO should main.getPlatformProperties() be passed to pde/build?
return fStateCopy;
}
protected void copyState(State state) {
fStateCopy = state.getFactory().createState(state);
fStateCopy.setResolver(Platform.getPlatformAdmin().createResolver());
fStateCopy.setPlatformProperties(state.getPlatformProperties());
}
private String getDevProperties() throws CoreException {
if (fDevProperties == null) {
fDevProperties = ClasspathHelper.getDevEntriesProperties(fBuildTempLocation + "/dev.properties", false); //$NON-NLS-1$
}
return fDevProperties;
}
protected boolean isCustomBuild(IModel model) throws CoreException {
IBuildModel buildModel = null;
IFile buildFile = PDEProject.getBuildProperties(model.getUnderlyingResource().getProject());
if (buildFile.exists()) {
buildModel = new WorkspaceBuildModel(buildFile);
buildModel.load();
}
if (buildModel != null) {
IBuild build = buildModel.getBuild();
if (build == null) {
return false;
}
IBuildEntry entry = build.getEntry("custom"); //$NON-NLS-1$
if (entry != null) {
String[] tokens = entry.getTokens();
for (final String token : tokens) {
if (token.equals("true")) { //$NON-NLS-1$
return true;
}
}
}
}
return false;
}
protected String[] getPaths() {
Map<String, String> map = new LinkedHashMap<>(); // merge workspace and external features using workspace over external
FeatureModelManager fmm = PDECore.getDefault().getFeatureModelManager();
IFeatureModel[] models = fmm.getExternalModels();
for (IFeatureModel model : models) {
map.put(model.getFeature().getId(), model.getInstallLocation());
}
// remove anything that we have in the workspace models
models = fmm.getWorkspaceModels();
String[] locations = new String[models.length];
for (int i = 0; i < models.length; i++) {
map.remove(models[i].getFeature().getId());
locations[i] = models[i].getInstallLocation();
}
// add all workspace models
String[] paths = new String[map.size() + models.length];
paths = map.values().toArray(paths);
System.arraycopy(locations, 0, paths, map.size(), models.length);
return paths;
}
protected void cleanup(IProgressMonitor monitor) {
SubMonitor subMonitor = SubMonitor.convert(monitor, 1);
// clear out some cached values that depend on the configuration being built.
fDevProperties = null;
fAntBuildProperties = null;
File scriptFile = null;
try {
scriptFile = createScriptFile("zip.xml"); //$NON-NLS-1$
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().newDocument();
Element root = doc.createElement("project"); //$NON-NLS-1$
root.setAttribute("name", "temp"); //$NON-NLS-1$ //$NON-NLS-2$
root.setAttribute("default", "clean"); //$NON-NLS-1$ //$NON-NLS-2$
root.setAttribute("basedir", "."); //$NON-NLS-1$ //$NON-NLS-2$
doc.appendChild(root);
Element target = doc.createElement("target"); //$NON-NLS-1$
target.setAttribute("name", "clean"); //$NON-NLS-1$ //$NON-NLS-2$
Element child = doc.createElement("delete"); //$NON-NLS-1$
child.setAttribute("dir", fBuildTempLocation); //$NON-NLS-1$
target.appendChild(child);
root.appendChild(target);
if (hasAntErrors()) {
target = doc.createElement("target"); //$NON-NLS-1$
target.setAttribute("name", "zip.logs"); //$NON-NLS-1$ //$NON-NLS-2$
child = doc.createElement("zip"); //$NON-NLS-1$
child.setAttribute("zipfile", fInfo.destinationDirectory + logName(null)); //$NON-NLS-1$
child.setAttribute("basedir", fBuildTempLocation + "/pde.logs"); //$NON-NLS-1$ //$NON-NLS-2$
target.appendChild(child);
root.appendChild(target);
}
XMLPrintHandler.writeFile(doc, scriptFile);
String[] targets = hasAntErrors() ? new String[] {"zip.logs", "clean"} //$NON-NLS-1$ //$NON-NLS-2$
: new String[] {"clean"}; //$NON-NLS-1$
AntRunner runner = new AntRunner();
runner.setBuildFileLocation(scriptFile.getAbsolutePath());
runner.setExecutionTargets(targets);
runner.run(subMonitor.split(1));
} catch (FactoryConfigurationError | ParserConfigurationException | CoreException | IOException e) {
} finally {
if (scriptFile != null && scriptFile.exists()) {
scriptFile.delete();
}
}
}
protected File createScriptFile(String filename) throws IOException {
String path = PDECore.getDefault().getStateLocation().toOSString();
File zip = new File(path, filename);
if (zip.exists()) {
zip.delete();
zip.createNewFile();
}
return zip;
}
private String logName(String[] config) {
if (config == null) {
return "/logs.zip"; //$NON-NLS-1$
}
return "/logs." + config[0] + '.' + config[1] + '.' + config[2] + ".zip"; //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* This method recurses on the feature list and creates feature.xml and build.properties.
*
* @param featureID
* @param featureLocation
* @param featuresExported
* @param doc
* @param root
* @param prop
* @throws IOException
*/
private void createFeature(String featureID, String featureLocation, Object[] featuresExported, Document doc, Element root, Properties prop) throws IOException {
try {
if (doc == null) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
doc = factory.newDocumentBuilder().newDocument();
root = doc.createElement("feature"); //$NON-NLS-1$
root.setAttribute("id", featureID); //$NON-NLS-1$
root.setAttribute("version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
doc.appendChild(root);
prop = new Properties();
prop.put("pde", "marker"); //$NON-NLS-1$ //$NON-NLS-2$
prop.put("individualSourceBundles", "true"); //$NON-NLS-1$ //$NON-NLS-2$
}
boolean returnAfterLoop = false;
for (final Object element : featuresExported) {
if (element instanceof IFeatureModel) {
IFeature feature = ((IFeatureModel) element).getFeature();
if (feature.getIncludedFeatures().length > 0) {
createFeature(featureID, featureLocation, feature.getIncludedFeatures(), doc, root, prop);
}
Element includes = doc.createElement("includes"); //$NON-NLS-1$
includes.setAttribute("id", feature.getId() + ".source"); //$NON-NLS-1$ //$NON-NLS-2$
includes.setAttribute("version", feature.getVersion()); //$NON-NLS-1$
root.appendChild(includes);
prop.put("generate.feature@" + feature.getId() + ".source", feature.getId()); //$NON-NLS-1$ //$NON-NLS-2$
includes = doc.createElement("includes"); //$NON-NLS-1$
includes.setAttribute("id", feature.getId()); //$NON-NLS-1$
includes.setAttribute("version", feature.getVersion()); //$NON-NLS-1$
root.appendChild(includes);
} else if (element instanceof IFeatureChild) {
returnAfterLoop = true;
IFeature feature = ((FeatureChild) element).getReferencedFeature();
if (feature != null) {
if (feature.getIncludedFeatures().length > 0) {
createFeature(featureID, featureLocation, feature.getIncludedFeatures(), doc, root, prop);
}
Element includes = doc.createElement("includes"); //$NON-NLS-1$
includes.setAttribute("id", feature.getId() + ".source"); //$NON-NLS-1$ //$NON-NLS-2$
includes.setAttribute("version", feature.getVersion()); //$NON-NLS-1$
root.appendChild(includes);
prop.put("generate.feature@" + feature.getId() + ".source", feature.getId()); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
if (returnAfterLoop) {
return;
}
File file = new File(featureLocation);
if (!file.exists() || !file.isDirectory()) {
file.mkdirs();
}
save(new File(file, ICoreConstants.BUILD_FILENAME_DESCRIPTOR), prop, "Marker File"); //$NON-NLS-1$
XMLPrintHandler.writeFile(doc, new File(file, ICoreConstants.FEATURE_FILENAME_DESCRIPTOR));
} catch (DOMException | FactoryConfigurationError | ParserConfigurationException e1) {
}
}
private Dictionary<String, String> getEnvironment(String[] config) {
Dictionary<String, String> environment = new Hashtable<>(4);
environment.put("osgi.os", config[0]); //$NON-NLS-1$
environment.put("osgi.ws", config[1]); //$NON-NLS-1$
environment.put("osgi.arch", config[2]); //$NON-NLS-1$
environment.put("osgi.nl", config[3]); //$NON-NLS-1$
return environment;
}
private void setFilterAttributes(Element plugin, String[] config) {
if (config != GENERIC_CONFIG) {
plugin.setAttribute("os", config[0]); //$NON-NLS-1$
plugin.setAttribute("ws", config[1]); //$NON-NLS-1$
plugin.setAttribute("arch", config[2]); //$NON-NLS-1$
}
}
private BundleDescription getMatchingLauncher(String[] configuration, BundleDescription[] fragments) {
//return the launcher fragment that matches the given configuration
Dictionary<String, String> environment = getEnvironment(configuration);
for (int i = 0; i < fragments.length; i++) {
if (!isNLFragment(fragments[i]) && shouldAddPlugin(fragments[i], environment)) {
return fragments[i];
}
}
return null;
}
private boolean isNLFragment(BundleDescription fragment) {
//this assumes a name like org.eclipse.equinox.launcher.<ws>.<os>.<arch>.nl_de
String symbolicName = fragment.getSymbolicName();
int idx = symbolicName.lastIndexOf('.');
return (idx > -1 && symbolicName.regionMatches(true, idx + 1, "nl", 0, 2)); //$NON-NLS-1$
}
protected void createFeature(String featureID, String featureLocation, String[][] configurations, boolean includeLauncher) throws IOException {
File file = new File(featureLocation);
if (!file.exists() || !file.isDirectory()) {
file.mkdirs();
}
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
Document doc = factory.newDocumentBuilder().newDocument();
Element root = doc.createElement("feature"); //$NON-NLS-1$
root.setAttribute("id", featureID); //$NON-NLS-1$
root.setAttribute("version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
doc.appendChild(root);
if (includeLauncher) {
IFeatureModel model = PDECore.getDefault().getFeatureModelManager().getDeltaPackFeature();
if (model != null) {
IFeature feature = model.getFeature();
Element includes = doc.createElement("includes"); //$NON-NLS-1$
includes.setAttribute("id", feature.getId()); //$NON-NLS-1$
includes.setAttribute("version", feature.getVersion()); //$NON-NLS-1$
root.appendChild(includes);
} else {
IPluginModelBase launcherPlugin = PluginRegistry.findModel(IPDEBuildConstants.BUNDLE_EQUINOX_LAUNCHER);
if (launcherPlugin != null) {
BundleDescription bundle = launcherPlugin.getBundleDescription();
if (bundle != null) {
Element plugin = doc.createElement("plugin"); //$NON-NLS-1$
plugin.setAttribute("id", bundle.getSymbolicName()); //$NON-NLS-1$
plugin.setAttribute("version", bundle.getVersion().toString()); //$NON-NLS-1$
plugin.setAttribute("unpack", "false"); //$NON-NLS-1$ //$NON-NLS-2$
root.appendChild(plugin);
BundleDescription[] fragments = bundle.getFragments();
for (String[] configuration : configurations) {
BundleDescription launcherFragment = getMatchingLauncher(configuration, fragments);
if (launcherFragment != null) {
Element fragment = doc.createElement("plugin"); //$NON-NLS-1$
fragment.setAttribute("id", launcherFragment.getSymbolicName()); //$NON-NLS-1$
fragment.setAttribute("version", launcherFragment.getVersion().toString()); //$NON-NLS-1$
fragment.setAttribute("fragment", "true"); //$NON-NLS-1$ //$NON-NLS-2$
setFilterAttributes(fragment, configuration);
root.appendChild(fragment);
}
}
}
}
}
}
List<IPluginModelBase> workspacePlugins = Arrays.asList(PluginRegistry.getWorkspaceModels());
for (Object item : fInfo.items) {
if (item instanceof IFeatureModel) {
IFeature feature = ((IFeatureModel) item).getFeature();
Element includes = doc.createElement("includes"); //$NON-NLS-1$
includes.setAttribute("id", feature.getId()); //$NON-NLS-1$
includes.setAttribute("version", feature.getVersion()); //$NON-NLS-1$
root.appendChild(includes);
if (fInfo.exportSource && fInfo.exportSourceBundle) {
includes = doc.createElement("includes"); //$NON-NLS-1$
includes.setAttribute("id", feature.getId() + ".source"); //$NON-NLS-1$ //$NON-NLS-2$
includes.setAttribute("version", feature.getVersion()); //$NON-NLS-1$
root.appendChild(includes);
}
} else {
BundleDescription bundle = null;
if (item instanceof BundlePluginModel) {
IProject project = ((BundlePluginModel) item).getUnderlyingResource().getProject();
IJavaProject javaProject = JavaCore.create(project);
if (javaProject != null) {
String option = javaProject.getOption(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES, true);
if (option != null && option.equals("enabled")) { //$NON-NLS-1$
isPreviewFeatureEnabled = true;
}
}
}
if (item instanceof IPluginModelBase) {
bundle = ((IPluginModelBase) item).getBundleDescription();
}
if (bundle == null) {
if (item instanceof BundleDescription) {
bundle = (BundleDescription) item;
}
}
if (bundle == null) {
continue;
}
List<String[]> configs = new ArrayList<>();
if (configurations.length > 1) {
configs.add(GENERIC_CONFIG);
}
configs.addAll(Arrays.asList(configurations));
//when doing multiplatform we need filters set on the plugin elements that need them
//so check the Bundle's platfrom filter against each config
for (String[] currentConfig : configs) {
Dictionary<String, String> environment = getEnvironment(currentConfig);
if (shouldAddPlugin(bundle, environment)) {
Element plugin = doc.createElement("plugin"); //$NON-NLS-1$
plugin.setAttribute("id", bundle.getSymbolicName()); //$NON-NLS-1$
plugin.setAttribute("version", bundle.getVersion().toString()); //$NON-NLS-1$
setFilterAttributes(plugin, currentConfig);
setAdditionalAttributes(plugin, bundle);
root.appendChild(plugin);
if (fInfo.exportSource && fInfo.exportSourceBundle) {
if (workspacePlugins.contains(PluginRegistry.findModel(bundle))) { // Is it a workspace plugin?
plugin = doc.createElement("plugin"); //$NON-NLS-1$
plugin.setAttribute("id", bundle.getSymbolicName() + ".source"); //$NON-NLS-1$ //$NON-NLS-2$
plugin.setAttribute("version", bundle.getVersion().toString()); //$NON-NLS-1$
setFilterAttributes(plugin, currentConfig);
setAdditionalAttributes(plugin, bundle);
root.appendChild(plugin);
} else // include the .source plugin, if available
{
IPluginModelBase model = PluginRegistry.findModel(bundle.getSymbolicName() + ".source"); //$NON-NLS-1$
if (model != null) {
bundle = model.getBundleDescription();
plugin = doc.createElement("plugin"); //$NON-NLS-1$
plugin.setAttribute("id", bundle.getSymbolicName()); //$NON-NLS-1$
plugin.setAttribute("version", bundle.getVersion().toString()); //$NON-NLS-1$
setFilterAttributes(plugin, currentConfig);
setAdditionalAttributes(plugin, bundle);
root.appendChild(plugin);
}
}
}
if (currentConfig == GENERIC_CONFIG) {
//if the bundle matched the generic configuration, we don't need to generated additional inclusions
//for the rest of the configs
break;
}
}
}
}
}
XMLPrintHandler.writeFile(doc, new File(file, ICoreConstants.FEATURE_FILENAME_DESCRIPTOR));
} catch (DOMException | FactoryConfigurationError | ParserConfigurationException e1) {
}
}
protected void setAdditionalAttributes(Element plugin, BundleDescription bundle) {
}
public static void errorFound() {
fHasErrors = true;
}
public boolean hasAntErrors() {
return fHasErrors;
}
protected boolean shouldAddPlugin(BundleDescription bundle, Dictionary<String, String> environment) {
String filterSpec = bundle.getPlatformFilter();
try {
return (filterSpec == null || PDECore.getDefault().getBundleContext().createFilter(filterSpec).match(environment));
} catch (InvalidSyntaxException e) {
}
return false;
}
/**
* If we are exporting using the compiled classes from the workspace, this method will
* start an incremental build and test for build errors. Returns a status explaining
* any errors found or Status.OK_STATUS.
* @param monitor progress monitor
* @return status explaining build errors or an OK status.
* @throws CoreException
*/
protected IStatus testBuildWorkspaceBeforeExport(IProgressMonitor monitor) throws CoreException {
SubMonitor subMonitor = SubMonitor.convert(monitor, 50);
if (fInfo.useWorkspaceCompiledClasses) {
getWorkspaceExportHelper().buildBeforeExport(fInfo.items, subMonitor.split(45));
Set<IProject> errors = getWorkspaceExportHelper().checkForErrors(fInfo.items);
subMonitor.split(5);
if (!errors.isEmpty()) {
return Status.error(NLS.bind(PDECoreMessages.FeatureExportOperation_workspaceBuildErrorsFoundDuringExport, errors));
}
}
return Status.OK_STATUS;
}
/**
* @return an instance of the WorkspaceExportHelper used to set up exports using class files built in the workspace
*/
protected WorkspaceExportHelper getWorkspaceExportHelper() {
if (fWorkspaceExportHelper == null) {
fWorkspaceExportHelper = new WorkspaceExportHelper();
}
return fWorkspaceExportHelper;
}
}