blob: edf894e57842ed182813c4d0054e663aef2edb86 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 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.equinox.p2.tests;
import java.io.*;
import java.util.*;
import org.osgi.framework.Version;
/*
* Class which can generate features and bundles for test data.
* See #printUsage for arguments.
*/
public class GenerateTestData {
static final String baseBundleName = "My Bundle";
static final String baseBundleId = "com.example.bundle";
static final Version bundleVersion = new Version("1.0");
static final String baseFeatureName = "My feature";
static final String baseFeatureId = "com.example.feature";
static final Version featureVersion = new Version("1.0");
static int numFeatures = 0;
static int numBundles = 0;
static int numRequires = 0;
static File outputFile = null;
static Random random = new Random(System.currentTimeMillis());
Set<TestFeature> features = new HashSet<>();
List<TestBundle> bundles = new ArrayList<>();
/*
* Abstract class representing a feature or a bundle.
*/
static abstract class TestObject {
String name;
String id;
Version version;
// use a set to avoid duplicates
Set<TestObject> requires = new HashSet<>();
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TestBundle))
return false;
TestBundle other = (TestBundle) obj;
return id.equals(other.id) && version.equals(other.version);
}
@Override
public int hashCode() {
return id.hashCode() + version.hashCode();
}
// subclasses override to write out feature.xml or manifest.mf
abstract String getManifest();
}
static class TestBundle extends TestObject {
@Override
String getManifest() {
StringBuilder manifest = new StringBuilder();
manifest.append("Manifest-Version: 1.0\n");
manifest.append("Bundle-RequiredExecutionEnvironment: J2SE-1.4\n");
manifest.append("Bundle-ManifestVersion: 2\n");
manifest.append("Bundle-Name: " + name + '\n');
manifest.append("Bundle-SymbolicName: " + id + '\n');
manifest.append("Bundle-Version: " + version + '\n');
if (!requires.isEmpty()) {
StringBuilder buffer = new StringBuilder();
buffer.append("Require-Bundle: ");
for (Iterator<TestObject> iter = requires.iterator(); iter.hasNext();) {
TestObject req = iter.next();
buffer.append(req.id);
if (iter.hasNext())
buffer.append(",\n ");
}
manifest.append(buffer.toString());
}
return manifest.toString();
}
}
static class TestFeature extends TestObject {
@Override
String getManifest() {
StringBuilder buffer = new StringBuilder();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
buffer.append(" <feature\n");
buffer.append("\t\tid=\"" + id + "\"\n");
buffer.append("\t\tlabel=\"" + name + "\"\n");
buffer.append("\t\tversion=\"" + version + "\"\n");
buffer.append("\t\tprovider-name=\"providerName\"\n");
buffer.append("\t\timage=\"eclipse_update_120.jpg\">\n");
buffer.append("\t<description>\n");
buffer.append("\t\tdescription\n");
buffer.append("\t</description>\n");
buffer.append("\t<copyright>\n");
buffer.append("\t\tcopyright\n");
buffer.append("\t</copyright>\n");
buffer.append("\t<license url=\"licenseURL\">\n");
buffer.append("\t\tlicense\n");
buffer.append("\t</license>\n");
for (TestObject bundle : requires) {
buffer.append("\t<plugin\n");
buffer.append("\t\tid=\"" + bundle.id + "\"\n");
buffer.append("\t\tdownload-size=\"0\"\n");
buffer.append("\t\tinstall-size=\"0\"\n");
buffer.append("\t\tversion=\"" + bundle.version + "\"/>\n");
}
buffer.append("</feature>\n");
return buffer.toString();
}
}
public static void main(String[] args) throws IOException {
processCommandLineArgs(args);
if (!validate()) {
printUsage();
return;
}
new GenerateTestData().generate();
}
static void printUsage() {
StringBuilder buffer = new StringBuilder();
buffer.append("\nUse this application to generate test feature and bundle data.\n");
buffer.append("Parameters:\n");
buffer.append("-output <location>\n");
buffer.append("-features <number of features>\n");
buffer.append("-bundles <number of bundles>\n");
buffer.append("-requires <max number of requires for each bundle> [optional]\n");
buffer.append("\tSpecifying a requires of X bundles picks up to X of previously created bundles to be required.\n");
buffer.append("\tThis means bundles produced at the end are more likely to have X requirements.\n");
buffer.append("\tThis is done to avoid circular dependencies.\n");
System.err.println(buffer.toString());
}
/*
* Verify setup before starting. Ensure all required parameters have been set.
*/
static boolean validate() {
StringBuilder buffer = new StringBuilder();
if (outputFile == null)
buffer.append("Need to set an output directory.\n");
if (numFeatures < 0 || numBundles <= 0)
buffer.append("Need to specifiy at least one bundle.\n");
if (numFeatures > numBundles)
buffer.append("Number of features must be the same or less than the number of bundles.\n");
if (numRequires > numBundles - 1)
buffer.append("Cannot have more required bundles than bundles.\n");
if (buffer.length() == 0)
return true;
System.err.println(buffer.toString());
return false;
}
static void processCommandLineArgs(String[] args) {
for (int i = 0; i < args.length - 1; i++) {
String arg = args[i];
String next = args[++i];
if ("-features".equalsIgnoreCase(arg)) {
numFeatures = Integer.parseInt(next);
} else if ("-bundles".equalsIgnoreCase(arg) || "-plugins".equalsIgnoreCase(arg)) {
numBundles = Integer.parseInt(next);
} else if ("-requires".equalsIgnoreCase(arg)) {
numRequires = Integer.parseInt(next);
} else if ("-output".equalsIgnoreCase(arg)) {
outputFile = new File(next);
}
}
}
void generate() throws IOException {
System.out.println("Generating " + numBundles + " bundles.");
for (int i = 0; i < numBundles; i++) {
TestBundle bundle = generateBundle(baseBundleName + i, baseBundleId + i, bundleVersion);
bundles.add(bundle);
}
System.out.println("Generating " + numFeatures + " features.");
for (int i = 0; i < numFeatures; i++) {
TestFeature feature = generateFeature(baseFeatureName + i, baseFeatureId + i, featureVersion, i);
features.add(feature);
}
save();
}
/*
* Persist the features and bundles to disk.
*/
void save() throws IOException {
outputFile.mkdirs();
File featuresDir = new File(outputFile, "features");
featuresDir.mkdirs();
File pluginsDir = new File(outputFile, "plugins");
pluginsDir.mkdirs();
System.out.println("Writing " + features.size() + " features.");
for (TestFeature feature : features) {
File featureDir = new File(featuresDir, feature.id + '_' + feature.version);
File location = new File(featureDir, "feature.xml");
write(location, feature.getManifest());
}
System.out.println("Writing " + bundles.size() + " bundles.");
for (TestBundle bundle : bundles) {
File pluginDir = new File(pluginsDir, bundle.id + '_' + bundle.version);
File location = new File(new File(pluginDir, "META-INF"), "MANIFEST.MF");
write(location, bundle.getManifest());
}
}
void write(File location, String data) throws IOException {
File parent = location.getParentFile();
if (parent == null)
throw new RuntimeException("Unable to write to: " + location.getAbsolutePath() + "due to null parent.");
parent.mkdirs();
try (OutputStream output = new BufferedOutputStream(new FileOutputStream(location))) {
output.write(data.getBytes());
}
}
// Return a random bundle from the collection of already produced ones.
TestBundle getRandomBundle() {
if (bundles.isEmpty())
return null;
int index = random.nextInt(bundles.size());
return bundles.get(index);
}
TestBundle generateBundle(String name, String id, Version version) {
TestBundle bundle = new TestBundle();
bundle.id = id;
bundle.name = name;
bundle.version = version;
for (int i = 0; i < numRequires; i++) {
TestBundle req = getRandomBundle();
if (req != null)
bundle.requires.add(req);
}
return bundle;
}
TestFeature generateFeature(String name, String id, Version version, int index) {
TestFeature feature = new TestFeature();
feature.id = id;
feature.name = name;
feature.version = version;
// bundles were generated first and we already checked that we have more/equal bundles and features
// so we should be ok here.
TestBundle bundle = bundles.get(index);
if (bundle == null)
throw new RuntimeException("Could not find bundle at index: " + index + " to match feature: " + id);
feature.requires.add(bundle);
return feature;
}
}