blob: b5dfc422634308bd453412f50d5afd329c6ac227 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 2017 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
*******************************************************************************/
package org.eclipse.pde.build.internal.tests;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.util.*;
import java.util.jar.*;
import org.apache.tools.ant.filters.ReplaceTokens;
import org.apache.tools.ant.util.ReaderInputStream;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.frameworkadmin.BundleInfo;
import org.eclipse.equinox.simpleconfigurator.manipulator.SimpleConfiguratorManipulator;
import org.eclipse.pde.build.tests.Activator;
import org.eclipse.pde.internal.build.*;
import org.eclipse.pde.internal.build.site.BuildTimeSiteFactory;
public class Utils {
private static final String ID = "id";
private static final String VERSION = "version";
/**
* Transfer the contents of resource into the destination IFile. During the
* transfer, replace all instances of "@replaceTag@" with "replaceString"
*
* @param resource
* - input URL
* @param destination
* - IFile destination
* @param replacements
* - map of tokens and values to replaces, file should contain
* "@replaceTag@"
* @throws IOException
* @throws CoreException
*/
static public void transferAndReplace(URL resource, IFile destination, Map<String, String> replacements)
throws IOException, CoreException {
Reader reader = new InputStreamReader(new BufferedInputStream(resource.openStream()));
final ReplaceTokens replaces = new ReplaceTokens(reader);
for (Iterator<String> iterator = replacements.keySet().iterator(); iterator.hasNext();) {
String replaceTag = iterator.next();
String replaceString = replacements.get(replaceTag);
ReplaceTokens.Token token = new ReplaceTokens.Token();
token.setKey(replaceTag);
token.setValue(replaceString);
replaces.addConfiguredToken(token);
}
try (ReaderInputStream inputStream = new ReaderInputStream(replaces)) {
destination.create(inputStream, true, null);
}
}
static public String[] getVersionsNoQualifier(String[] bundles) {
String[] results = new String[bundles.length];
for (int i = 0; i < bundles.length; i++) {
org.osgi.framework.Version version = Platform.getBundle(bundles[i]).getVersion();
results[i] = String.valueOf(version.getMajor()) + "." + version.getMinor() + '.' + version.getMicro();
}
return results;
}
static public void generateAllElements(IFolder buildFolder, String element) throws CoreException, IOException {
if (element != null) {
// get the productBuild/allElements.xml and replace @ELEMENT@ with element
URL allElements = FileLocator.find(Platform.getBundle(Activator.PLUGIN_ID),
new Path("/resources/allElements.xml"), null);
Map<String, String> replacements = new HashMap<>(1);
replacements.put("ELEMENT", element);
transferAndReplace(allElements, buildFolder.getFile("allElements.xml"), replacements);
buildFolder.refreshLocal(IResource.DEPTH_INFINITE, null);
}
}
static public void generatePluginBuildProperties(IFolder folder, Properties properties)
throws FileNotFoundException, IOException {
Properties buildProperties = properties != null ? properties : new Properties();
// default contents:
if (!buildProperties.containsKey("source.."))
buildProperties.put("source..", "src/");
if (!buildProperties.containsKey("output.."))
buildProperties.put("output..", "bin/");
if (!buildProperties.containsKey("bin.includes"))
buildProperties.put("bin.includes", "META-INF/, .");
storeBuildProperties(folder, buildProperties);
}
static public void generateBundleManifest(IFolder folder, String bundleId, String bundleVersion,
Attributes additionalAttributes) throws CoreException, IOException {
Manifest manifest = new Manifest();
Attributes mainAttributes = manifest.getMainAttributes();
mainAttributes.put(Attributes.Name.MANIFEST_VERSION, "1.0");
mainAttributes.put(new Attributes.Name("Bundle-ManifestVersion"), "2");
mainAttributes.put(new Attributes.Name("Bundle-Name"), "Test Bundle " + bundleId);
mainAttributes.put(new Attributes.Name("Bundle-SymbolicName"), bundleId);
mainAttributes.put(new Attributes.Name("Bundle-Version"), bundleVersion);
if (additionalAttributes != null)
mainAttributes.putAll(additionalAttributes);
IFile manifestFile = folder.getFile(JarFile.MANIFEST_NAME);
IFolder metaInf = (IFolder) manifestFile.getParent();
if (!metaInf.exists())
metaInf.create(true, true, null);
try (OutputStream outputStream = new BufferedOutputStream(
new FileOutputStream(manifestFile.getLocation().toFile()))) {
manifest.write(outputStream);
}
}
static public void generateBundle(IFolder folder, String bundleId) throws CoreException, IOException {
generateBundleManifest(folder, bundleId, "1.0.0", null);
generatePluginBuildProperties(folder, null);
writeBuffer(folder.getFile("src/foo.java"), new StringBuffer("public class foo { int i; }"));
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
}
static public void generateBundle(IFolder folder, String bundleId, String version)
throws CoreException, IOException {
generateBundleManifest(folder, bundleId, version, null);
generatePluginBuildProperties(folder, null);
writeBuffer(folder.getFile("src/foo.java"), new StringBuffer("public class foo { int i; }"));
folder.refreshLocal(IResource.DEPTH_INFINITE, null);
}
static public void storeBuildProperties(IFolder buildFolder, Properties buildProperties)
throws FileNotFoundException, IOException {
storeProperties(buildFolder.getFile("build.properties"), buildProperties);
}
static public void storeProperties(IFile propertiesFile, Properties buildProperties)
throws FileNotFoundException, IOException {
File buildPropertiesFile = propertiesFile.getLocation().toFile();
try (OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(buildPropertiesFile))) {
buildProperties.store(outputStream, "");
}
}
static public void generateFeature(IFolder workingDirectory, String id, String[] featureList, String[] pluginList)
throws CoreException, IOException {
generateFeature(workingDirectory, id, featureList, pluginList, null, false, false, null);
}
static public void generateFeature(IFolder workingDirectory, String id, String[] featureList, String[] pluginList,
String version) throws CoreException, IOException {
generateFeature(workingDirectory, id, featureList, pluginList, null, false, false, version);
}
static public void generateFeature(IFolder workingDirectory, String id, String[] featureList, String[] pluginList,
String product, boolean includeLaunchers, boolean verify, String version)
throws CoreException, IOException {
FeatureGenerator generator = new FeatureGenerator();
if (verify) {
AbstractScriptGenerator.setConfigInfo("*,*,*");
String baseLocation = Platform.getInstallLocation().getURL().getPath();
BuildTimeSiteFactory.setInstalledBaseSite(baseLocation);
File executable = findExecutable();
if (executable != null && !executable.equals(new File(baseLocation)))
generator.setPluginPath(new String[] { executable.getAbsolutePath() });
}
generator.setIncludeLaunchers(includeLaunchers);
generator.setVerify(verify);
generator.setFeatureId(id);
generator.setVersion(version);
generator.setProductFile(product);
generator.setFeatureList(featureList);
generator.setPluginList(pluginList);
generator.setWorkingDirectory(workingDirectory.getLocation().toOSString());
generator.generate();
}
static public void generateProduct(IFile productFile, String id, String version, String[] entryList,
boolean features) throws CoreException, IOException {
generateProduct(productFile, id, version, null, entryList, features, null);
}
static public void generateProduct(IFile productFile, String id, String version, String application,
String[] entryList, boolean features) throws CoreException, IOException {
generateProduct(productFile, id, version, application, entryList, features, null);
}
static public void generateProduct(IFile productFile, String id, String version, String application,
String[] entryList, boolean features, StringBuffer extra) throws CoreException, IOException {
generateProduct(productFile, null, id, version, application, null, entryList, features, extra);
}
static public void generateProduct(IFile productFile, String id, String version, String application,
String launcher, String[] entryList, boolean features, StringBuffer extra)
throws CoreException, IOException {
generateProduct(productFile, null, id, version, application, launcher, entryList, features, extra);
}
static public void generateProduct(IFile productFile, String uid, String id, String version, String application,
String launcher, String[] entryList, boolean features, StringBuffer extra)
throws CoreException, IOException {
StringBuffer buffer = new StringBuffer();
buffer.append("<product ");
if (uid != null) {
buffer.append(" uid=\"");
buffer.append(uid);
buffer.append("\"");
}
if (id != null) {
buffer.append(" name=\"");
buffer.append(id);
buffer.append("\" id=\"");
buffer.append(id);
buffer.append("\"");
}
if (version != null) {
buffer.append(" version=\"");
buffer.append(version);
buffer.append("\"");
}
if (application != null) {
buffer.append(" application=\"");
buffer.append(application);
buffer.append("\"");
}
buffer.append(" useFeatures=\"");
buffer.append(Boolean.valueOf(features).toString());
buffer.append("\">\n");
buffer.append(" <configIni use=\"default\"/>\n");
buffer.append(" <launcher name=\"" + (launcher != null ? launcher : "eclipse") + "\"/>\n");
if (features) {
buffer.append(" <features>\n");
for (int i = 0; i < entryList.length; i++) {
Map<String, Object> items = org.eclipse.pde.internal.build.Utils.parseExtraBundlesString(entryList[i],
false);
buffer.append(" <feature id=\"");
buffer.append(items.get(ID));
buffer.append("\"");
if (items.containsKey(VERSION)) {
buffer.append(" version=\"");
buffer.append(items.get(VERSION));
buffer.append("\"");
}
buffer.append("/>\n");
}
buffer.append(" </features>\n");
} else {
buffer.append(" <plugins>\n");
for (int i = 0; i < entryList.length; i++) {
Map<String, Object> items = org.eclipse.pde.internal.build.Utils.parseExtraBundlesString(entryList[i],
false);
buffer.append(" <plugin id=\"");
buffer.append(items.get(ID));
buffer.append("\"");
if (items.containsKey(VERSION)) {
buffer.append(" version=\"");
buffer.append(items.get(VERSION));
buffer.append("\"");
}
buffer.append("/>\n");
}
buffer.append(" </plugins>\n");
}
if (extra != null)
buffer.append(extra);
buffer.append("</product>\n");
Utils.writeBuffer(productFile, buffer);
productFile.refreshLocal(IResource.DEPTH_INFINITE, null);
}
/**
* Creates a IFolder resources. Will create any folders necessary under parent
*/
static public IFolder createFolder(IFolder parent, String path) throws CoreException {
parent.refreshLocal(IResource.DEPTH_INFINITE, null);
IFolder folder = parent.getFolder(path);
if (folder.exists())
return folder;
IFolder container = (IFolder) folder.getParent();
if (!container.exists()) {
LinkedList<IFolder> stack = new LinkedList<>();
while (!container.equals(parent) && !container.exists()) {
stack.add(0, container);
container = (IFolder) container.getParent();
}
for (Iterator<IFolder> iterator = stack.iterator(); iterator.hasNext();) {
container = iterator.next();
container.create(true, true, null);
}
}
folder.create(true, true, null);
return folder;
}
private static File findExecutable(File baseLocation) {
File features = new File(baseLocation, "features");
FilenameFilter filter = (dir, name) -> name.startsWith("org.eclipse.equinox.executable");
String[] files = features.list(filter);
if (files != null && files.length > 0)
return baseLocation;
return null;
}
static private File executableLocation = null;
public static File findExecutable() throws IOException {
if (executableLocation != null)
return executableLocation;
File baseLocation = new File(Platform.getInstallLocation().getURL().getPath());
executableLocation = findExecutable(baseLocation);
if (executableLocation != null)
return executableLocation;
SimpleConfiguratorManipulator manipulator = BundleHelper.getDefault()
.acquireService(SimpleConfiguratorManipulator.class);
if (manipulator != null) {
BundleInfo[] bundles = manipulator
.loadConfiguration(BundleHelper.getDefault().getBundle().getBundleContext(), null);
// find a fragment for a platform we aren't
String id = "org.eclipse.equinox.launcher.win32.win32.x86_64";
for (int i = 0; i < bundles.length; i++) {
if (bundles[i].getSymbolicName().equals(id)) {
URI location = bundles[i].getLocation();
executableLocation = findExecutable(URIUtil.toFile(URIUtil.append(location, "../..")));
if (executableLocation != null)
return executableLocation;
break;
}
}
}
if (Platform.OS_MACOSX.equals(Platform.getOS())) {
// After https://bugs.eclipse.org/431116 and related changes, the install
// location on the Mac
// moved down two directories (from <folder-containing-Eclipse.app> to
// Eclipse.app/Contents/Eclipse).
baseLocation = baseLocation.getParentFile().getParentFile();
}
executableLocation = findExecutable(new File(baseLocation.getParent(), "deltapack/eclipse"));
return executableLocation;
}
public static void writeBuffer(IFile outputFile, StringBuffer buffer) throws IOException, CoreException {
File output = outputFile.getLocation().toFile();
output.getParentFile().mkdirs();
try (FileOutputStream stream = new FileOutputStream(output)) {
stream.write(buffer.toString().getBytes());
}
outputFile.getParent().refreshLocal(IResource.DEPTH_INFINITE, null);
}
public static void transferStreams(InputStream source, OutputStream destination) throws IOException {
transferStreams(source, true, destination, true);
}
public static void transferStreams(InputStream source, boolean closeIn, OutputStream destination, boolean closeOut)
throws IOException {
source = new BufferedInputStream(source);
destination = new BufferedOutputStream(destination);
try {
byte[] buffer = new byte[8192];
while (true) {
int bytesRead = -1;
if ((bytesRead = source.read(buffer)) == -1)
break;
destination.write(buffer, 0, bytesRead);
}
} finally {
try {
if (closeIn)
source.close();
} catch (IOException e) {
// ignore
}
try {
destination.flush();
if (closeOut)
destination.close();
} catch (IOException e) {
// ignore
}
}
}
public static boolean extractFromZip(IFolder buildFolder, String zipFile, String zipEntry, IFile outputFile)
throws CoreException {
File folder = new File(buildFolder.getLocation().toOSString());
File archiveFile = new File(folder, zipFile);
if (!archiveFile.exists())
return false;
try (ZipFile zip = new ZipFile(archiveFile);) {
ZipEntry entry = zip.getEntry(zipEntry);
if (entry == null)
return false;
InputStream stream = new BufferedInputStream(zip.getInputStream(entry));
OutputStream out = new BufferedOutputStream(new FileOutputStream(outputFile.getLocation().toFile()));
transferStreams(stream, out);
} catch (Exception e) {
return false;
}
outputFile.refreshLocal(IResource.DEPTH_ONE, null);
return true;
}
public static Properties loadProperties(IFile propertiesFile) throws CoreException {
propertiesFile.refreshLocal(IResource.DEPTH_INFINITE, null);
if (!propertiesFile.exists())
return null;
Properties props = new Properties();
try (InputStream stream = propertiesFile.getContents(true)) {
props.load(stream);
return props;
} catch (IOException e) {
return null;
}
}
public static void copy(File source, File target) throws IOException {
if (!source.exists())
return;
if (source.isDirectory()) {
if (target.exists() && target.isFile())
target.delete();
if (!target.exists())
target.mkdirs();
File[] children = source.listFiles();
for (int i = 0; i < children.length; i++)
copy(children[i], new File(target, children[i].getName()));
return;
}
try (InputStream input = new BufferedInputStream(new FileInputStream(source));
OutputStream output = new BufferedOutputStream(new FileOutputStream(target))) {
byte[] buffer = new byte[8192];
int bytesRead = 0;
while ((bytesRead = input.read(buffer)) != -1)
output.write(buffer, 0, bytesRead);
}
}
public static Manifest loadManifest(IFile file) throws IOException {
IPath location = file.getLocation();
if (location.getFileExtension().equals(".jar")) {
JarFile jar = null;
try {
jar = new JarFile(location.toFile());
return jar.getManifest();
} finally {
org.eclipse.pde.internal.build.Utils.close(jar);
}
} else if (location.lastSegment().equalsIgnoreCase("MANIFEST.MF")) {
InputStream stream = new FileInputStream(location.toFile());
try {
return new Manifest(stream);
} finally {
org.eclipse.pde.internal.build.Utils.close(stream);
}
}
return null;
}
}