Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff McAffer2008-03-14 04:24:12 +0000
committerJeff McAffer2008-03-14 04:24:12 +0000
commit618de1745b89297893c6c48e8bd36972a1a92d87 (patch)
tree967fc61dedf8dc293f8619810f0051b956609b17 /bundles/org.eclipse.equinox.p2.publisher/src
parent4acb3c0f22fd044b4c91500ffd68036a51f06649 (diff)
downloadrt.equinox.p2-618de1745b89297893c6c48e8bd36972a1a92d87.tar.gz
rt.equinox.p2-618de1745b89297893c6c48e8bd36972a1a92d87.tar.xz
rt.equinox.p2-618de1745b89297893c6c48e8bd36972a1a92d87.zip
Cut the chord from metadatagenerator
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.publisher/src')
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java (renamed from bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractGeneratorApplication.java)15
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublishingAction.java158
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/BundleDescriptionFactory.java355
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/FileSetDescriptor.java50
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/GeneratorBundleInfo.java161
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IProductDescriptor.java42
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherInfo.java34
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherResult.java39
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAction.java1
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAdvice.java12
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java (renamed from bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisher.java)15
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/MetadataGeneratorHelper.java1262
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Publisher.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherInfo.java33
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherResult.java158
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/AccumulateConfigDataAction.java149
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundleAdvice.java70
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundlesAction.java165
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/ConfigCUsAction.java147
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/DefaultCUsAction.java50
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EclipseInstallAction.java23
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxExecutableAction.java23
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxLauncherCUAction.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FeaturesAction.java202
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FragmentIUsAction.java16
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IBundleAdvice.java24
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/JREAction.java18
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/MergeResultsAction.java7
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootFilesAction.java31
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootIUAction.java59
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/UpdateSiteAction.java33
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DefaultSiteParser.java850
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DigestParser.java97
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Feature.java278
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureEntry.java179
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureParser.java335
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Messages.java43
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/ProductFile.java520
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteCategory.java175
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteFeature.java408
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteModel.java312
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/URLEntry.java41
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/messages.properties30
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties23
44 files changed, 6374 insertions, 280 deletions
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractGeneratorApplication.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java
index 96a005a08..20b3b2370 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractGeneratorApplication.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java
@@ -30,7 +30,7 @@ import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadata
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.ServiceRegistration;
-public abstract class AbstractGeneratorApplication implements IApplication {
+public abstract class AbstractPublisherApplication implements IApplication {
// The mapping rules for in-place generation need to construct paths into the structure
// of an eclipse installation; in the future the default artifact mapping declared in
@@ -62,6 +62,8 @@ public abstract class AbstractGeneratorApplication implements IApplication {
protected boolean reusePackedFiles = false;
protected void initialize(PublisherInfo info) throws ProvisionException {
+ if (inplace)
+ initializeForInplace(info);
initializeRepositories(info);
}
@@ -113,8 +115,8 @@ public abstract class AbstractGeneratorApplication implements IApplication {
} catch (MalformedURLException e) {
// ought not happen...
}
- info.setPublishArtifactRepository(true);
- info.setPublishArtifacts(false);
+ info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_INDEX);
+ info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_PUBLISH);
}
protected void initializeMetadataRepository(PublisherInfo info) throws ProvisionException {
@@ -192,10 +194,13 @@ public abstract class AbstractGeneratorApplication implements IApplication {
protected void processFlag(String arg, PublisherInfo info) {
if (arg.equalsIgnoreCase("-publishArtifacts") || arg.equalsIgnoreCase("-pa")) //$NON-NLS-1$ //$NON-NLS-2$
- info.setPublishArtifacts(true);
+ info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_PUBLISH);
if (arg.equalsIgnoreCase("-publishArtifactRepository") || arg.equalsIgnoreCase("-par")) //$NON-NLS-1$ //$NON-NLS-2$
- info.setPublishArtifactRepository(true);
+ info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_INDEX);
+
+ if (arg.equalsIgnoreCase("-overwriteArtifacts")) //$NON-NLS-1$
+ info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_OVERWRITE);
if (arg.equalsIgnoreCase("-append")) //$NON-NLS-1$
append = true;
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublishingAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublishingAction.java
new file mode 100644
index 000000000..fc0729bc0
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublishingAction.java
@@ -0,0 +1,158 @@
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+
+public abstract class AbstractPublishingAction implements IPublishingAction {
+
+ public static final int AS_IS = 1;
+ public static final int INCLUDE_ROOT = 2;
+
+ public static final String CONFIG_SEGMENT_SEPARATOR = "."; //$NON-NLS-1$
+
+ /**
+ * Convert a list of tokens into an array. The list separator has to be
+ * specified.
+ */
+ public static String[] getArrayFromString(String list, String separator) {
+ if (list == null || list.trim().equals("")) //$NON-NLS-1$
+ return new String[0];
+ List result = new ArrayList();
+ for (StringTokenizer tokens = new StringTokenizer(list, separator); tokens.hasMoreTokens();) {
+ String token = tokens.nextToken().trim();
+ if (!token.equals("")) //$NON-NLS-1$
+ result.add(token);
+ }
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+ /**
+ * Returns a string array of { ws, os, arch } as parsed from the given string
+ * @param configSpec the string to parse
+ * @return the ws, os, arch form of the given string
+ */
+ public static String[] parseConfigSpec(String configSpec) {
+ String[] result = getArrayFromString(configSpec, CONFIG_SEGMENT_SEPARATOR);
+ return result;
+ }
+
+ /**
+ * Returns the LDAP filter form that matches the given config spec. Returns
+ * an empty String if the spec does not identify an ws, os or arch.
+ * @param configSpec a config spec to filter
+ * @return the LDAP filter for the given spec.
+ */
+ public static String createFilterSpec(String configSpec) {
+ String[] config = parseConfigSpec(configSpec);
+ if (config[0] != null || config[1] != null || config[2] != null) {
+ String filterWs = config[0] != null ? "(osgi.ws=" + config[0] + ")" : ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ String filterOs = config[1] != null ? "(osgi.os=" + config[1] + ")" : ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ String filterArch = config[2] != null ? "(osgi.arch=" + config[2] + ")" : ""; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ return "(& " + filterWs + filterOs + filterArch + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return ""; //$NON-NLS-1$
+ }
+
+ /**
+ * Returns the normalized string form of the given config spec. This is useful for putting
+ * in IU ids etc. Note that the result is not intended to be machine readable (i.e., parseConfigSpec
+ * may not work on the result).
+ * @param configSpec the config spec to format
+ * @return the readable format of the given config spec
+ */
+ public static String createIdString(String configSpec) {
+ String[] config = parseConfigSpec(configSpec);
+ return config[0] + '.' + config[1] + '.' + config[2];
+ }
+
+ /**
+ * Returns the canonical form of config spec with the given ws, os and arch.
+ * Note that the result is intended to be machine readable (i.e., parseConfigSpec
+ * will parse the the result).
+ * @param ws the window system
+ * @param os the operating system
+ * @param arch the machine architecture
+ * @return the machine readable format of the given config spec
+ */
+ public static String createConfigSpec(String ws, String os, String arch) {
+ return ws + '.' + os + '.' + arch;
+ }
+
+ protected void publishArtifact(IArtifactDescriptor descriptor, File base, File[] files, IPublisherInfo info, int mode) {
+ IArtifactRepository destination = info.getArtifactRepository();
+
+ if (descriptor == null || destination == null)
+ return;
+
+ // publish the given files
+ publishArtifact(descriptor, files, info, mode);
+
+ // if we are assimilating pack200 files then add the packed descriptor
+ // into the repo assuming it does not already exist.
+ boolean reuse = "true".equals(destination.getProperties().get(AbstractPublisherApplication.PUBLISH_PACK_FILES_AS_SIBLINGS)); //$NON-NLS-1$
+ if (base != null && reuse && (info.getArtifactOptions() & IPublisherInfo.A_PUBLISH) > 0) {
+ File packFile = new Path(base.getAbsolutePath()).addFileExtension("pack.gz").toFile(); //$NON-NLS-1$
+ if (packFile.exists()) {
+ IArtifactDescriptor ad200 = MetadataGeneratorHelper.createPack200ArtifactDescriptor(descriptor.getArtifactKey(), packFile, descriptor.getProperty(IArtifactDescriptor.ARTIFACT_SIZE));
+ publishArtifact(ad200, new File[] {packFile}, info, AS_IS | INCLUDE_ROOT);
+ }
+ }
+ }
+
+ protected void publishArtifact(IArtifactDescriptor descriptor, File[] files, IPublisherInfo info, int mode) {
+ IArtifactRepository destination = info.getArtifactRepository();
+
+ // if the destination already contains the descriptor, there is nothing to do.
+ if (destination.contains(descriptor))
+ return;
+ // if all we are doing is indexing things then add the descriptor and get on with ti
+ if ((info.getArtifactOptions() & IPublisherInfo.A_PUBLISH) == 0) {
+ destination.addDescriptor(descriptor);
+ return;
+ }
+
+ boolean overwrite = (info.getArtifactOptions() & IPublisherInfo.A_OVERWRITE) > 0;
+ // if there is just one file and the mode is as-is, just copy the file into the repo
+ if (((mode & AS_IS) > 0) && files.length == 1) {
+ try {
+ OutputStream output = destination.getOutputStream(descriptor, overwrite);
+ if (output == null)
+ return;
+ output = new BufferedOutputStream(output);
+ FileUtils.copyStream(new BufferedInputStream(new FileInputStream(files[0])), true, output, true);
+ } catch (ProvisionException e) {
+ LogHelper.log(e.getStatus());
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error publishing artifacts", e)); //$NON-NLS-1$
+ }
+ } else {
+ // otherwise, zip up the files and copy the zip into the repo
+ File tempFile = null;
+ try {
+ OutputStream output = destination.getOutputStream(descriptor, overwrite);
+ if (output == null)
+ return;
+ output = new BufferedOutputStream(output);
+ tempFile = File.createTempFile("p2.generator", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ FileUtils.zip(files, tempFile, (mode & INCLUDE_ROOT) > 0);
+ if (output != null)
+ FileUtils.copyStream(new BufferedInputStream(new FileInputStream(tempFile)), true, output, true);
+ } catch (ProvisionException e) {
+ LogHelper.log(e.getStatus());
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error publishing artifacts", e)); //$NON-NLS-1$
+ } finally {
+ if (tempFile != null)
+ tempFile.delete();
+ }
+ }
+ }
+
+ public abstract IStatus perform(IPublisherInfo info, IPublisherResult results);
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/BundleDescriptionFactory.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/BundleDescriptionFactory.java
new file mode 100644
index 000000000..776e78252
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/BundleDescriptionFactory.java
@@ -0,0 +1,355 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.io.*;
+import java.util.*;
+import java.util.jar.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.metadata.repository.Activator;
+import org.eclipse.osgi.service.pluginconversion.PluginConversionException;
+import org.eclipse.osgi.service.pluginconversion.PluginConverter;
+import org.eclipse.osgi.service.resolver.*;
+import org.eclipse.osgi.util.ManifestElement;
+import org.eclipse.osgi.util.NLS;
+import org.osgi.framework.BundleException;
+
+public class BundleDescriptionFactory {
+ public static final String DIR = "dir"; //$NON-NLS-1$
+ public static final String JAR = "jar"; //$NON-NLS-1$
+ private static final String FEATURE_FILENAME_DESCRIPTOR = "feature.xml"; //$NON-NLS-1$
+ private static final String PLUGIN_FILENAME_DESCRIPTOR = "plugin.xml"; //$NON-NLS-1$
+ private static final String FRAGMENT_FILENAME_DESCRIPTOR = "fragment.xml"; //$NON-NLS-1$
+
+ public static String BUNDLE_SHAPE = "Eclipse-BundleShape"; //$NON-NLS-1$
+
+ // static final String DEFAULT_BUNDLE_LOCALIZATION = "plugin"; //$NON-NLS-1$
+ // static final String PROPERTIES_FILE_EXTENSION = ".properties"; //$NON-NLS-1$
+ // static final String MANIFEST_LOCALIZATIONS = "eclipse.p2.manifest.localizations"; //$NON-NLS-1$
+ //
+ // static final Locale DEFAULT_LOCALE = new Locale("df", "LT"); //$NON-NLS-1$//$NON-NLS-2$
+ // static final Locale PSEUDO_LOCALE = new Locale("zz", "ZZ"); //$NON-NLS-1$//$NON-NLS-2$
+
+ StateObjectFactory factory;
+ State state;
+
+ public BundleDescriptionFactory(StateObjectFactory factory, State state) {
+ this.factory = factory;
+ this.state = state;
+ //TODO find a state and a factory when not provided
+ }
+
+ private static PluginConverter acquirePluginConverter() {
+ return (PluginConverter) ServiceHelper.getService(Activator.getContext(), PluginConverter.class.getName());
+ }
+
+ private static Dictionary convertPluginManifest(File bundleLocation, boolean logConversionException) {
+ PluginConverter converter;
+ try {
+ converter = acquirePluginConverter();
+ if (converter == null)
+ return null;
+ return converter.convertManifest(bundleLocation, false, null, true, null);
+ } catch (PluginConversionException convertException) {
+ if (bundleLocation.getName().equals(FEATURE_FILENAME_DESCRIPTOR))
+ return null;
+ if (!new File(bundleLocation, PLUGIN_FILENAME_DESCRIPTOR).exists() && !new File(bundleLocation, FRAGMENT_FILENAME_DESCRIPTOR).exists())
+ return null;
+ if (logConversionException) {
+ IStatus status = new Status(IStatus.WARNING, Activator.ID, 0, NLS.bind(Messages.exception_errorConverting, bundleLocation.getAbsolutePath()), convertException);
+ System.out.println(status);
+ //TODO Need to find a way to get a logging service to log
+ }
+ return null;
+ }
+ }
+
+ public BundleDescription getBundleDescription(Dictionary enhancedManifest, File bundleLocation) {
+ try {
+ BundleDescription descriptor = factory.createBundleDescription(state, enhancedManifest, bundleLocation != null ? bundleLocation.getAbsolutePath() : null, 1); //TODO Do we need to have a real bundle id
+ descriptor.setUserObject(enhancedManifest);
+ return descriptor;
+ } catch (BundleException e) {
+ // IStatus status = new Status(IStatus.WARNING, IPDEBuildConstants.PI_PDEBUILD, EXCEPTION_STATE_PROBLEM, NLS.bind(Messages.exception_stateAddition, enhancedManifest.get(Constants.BUNDLE_NAME)), e);
+ // BundleHelper.getDefault().getLog().log(status);
+ System.err.println(NLS.bind(Messages.exception_stateAddition, bundleLocation != null ? bundleLocation.getAbsoluteFile() : null));
+ return null;
+ }
+ }
+
+ public BundleDescription getBundleDescription(File bundleLocation) {
+ Dictionary manifest = loadManifest(bundleLocation);
+ if (manifest == null)
+ return null;
+ return getBundleDescription(manifest, bundleLocation);
+ }
+
+ public BundleDescription getBundleDescription(InputStream manifestStream, File bundleLocation) {
+ Hashtable entries = new Hashtable();
+ try {
+ ManifestElement.parseBundleManifest(manifestStream, entries);
+ return getBundleDescription(entries, bundleLocation);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (BundleException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static Dictionary loadManifest(File bundleLocation) {
+ InputStream manifestStream = null;
+ ZipFile jarFile = null;
+ try {
+ if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && bundleLocation.isFile()) { //$NON-NLS-1$
+ jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ);
+ ZipEntry manifestEntry = jarFile.getEntry(JarFile.MANIFEST_NAME);
+ if (manifestEntry != null) {
+ manifestStream = jarFile.getInputStream(manifestEntry);
+ }
+ } else {
+ manifestStream = new BufferedInputStream(new FileInputStream(new File(bundleLocation, JarFile.MANIFEST_NAME)));
+ }
+ } catch (IOException e) {
+ //ignore
+ }
+
+ Dictionary manifest = null;
+ if (manifestStream != null) {
+ try {
+ manifest = manifestToProperties(new Manifest(manifestStream).getMainAttributes());
+ } catch (IOException ioe) {
+ return null;
+ } finally {
+ try {
+ manifestStream.close();
+ } catch (IOException e1) {
+ //Ignore
+ }
+ try {
+ if (jarFile != null)
+ jarFile.close();
+ } catch (IOException e2) {
+ //Ignore
+ }
+ }
+ } else {
+ manifest = convertPluginManifest(bundleLocation, true);
+ }
+
+ if (manifest == null)
+ return null;
+
+ //Deal with the pre-3.0 plug-in shape who have a default jar manifest.mf
+ if (manifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME) == null)
+ manifest = convertPluginManifest(bundleLocation, true);
+
+ // if the bundle itself does not define its shape, infer the shape from the current form
+ if (manifest.get(BUNDLE_SHAPE) == null)
+ manifest.put(BUNDLE_SHAPE, bundleLocation.isDirectory() ? DIR : JAR);
+ getManifestLocalizations(manifest, bundleLocation);
+ // localizeManifest(manifest, bundleLocation);
+ return manifest;
+ }
+
+ // private Properties loadProperties(File bundleLocation, String localizationFile) throws IOException {
+ // Properties result = new Properties();
+ // InputStream propertyStream = null;
+ // try {
+ // try {
+ // if (bundleLocation.isDirectory())
+ // propertyStream = new FileInputStream(new File(bundleLocation, localizationFile));
+ // else {
+ // URLConnection connection = new URL("jar:" + bundleLocation.toURL().toExternalForm() + "!/" + localizationFile).openConnection(); //$NON-NLS-1$ //$NON-NLS-2$
+ // connection.setUseCaches(false);
+ // propertyStream = connection.getInputStream();
+ // }
+ // } catch (FileNotFoundException e) {
+ // // if there is no messages file then just return;
+ // return result;
+ // }
+ // result.load(propertyStream);
+ // } finally {
+ // if (propertyStream != null)
+ // propertyStream.close();
+ // }
+ // return result;
+ // }
+
+ // Collect the manifest localizations from the bundle directory
+ // and store them in the manifest.
+ private static void getManifestLocalizations(Dictionary manifest, File bundleLocation) {
+ // Map localizations;
+ // Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo
+ // String bundleLocalization = (String) manifest.get(Constants.BUNDLE_LOCALIZATION);
+ // if (bundleLocalization == null || bundleLocalization.trim().length() == 0)
+ // bundleLocalization = DEFAULT_BUNDLE_LOCALIZATION;
+ //
+ // if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$
+ // bundleLocation.isFile()) {
+ // localizations = getJarManifestLocalization(bundleLocation, bundleLocalization, manifest, defaultLocale);
+ // } else {
+ // localizations = getDirManifestLocalization(bundleLocation, bundleLocalization, manifest, defaultLocale);
+ // }
+ //
+ // if (localizations.size() > 0) {
+ // manifest.put(MANIFEST_LOCALIZATIONS, localizations);
+ // }
+ }
+
+ // private Map getJarManifestLocalization(File bundleLocation, String bundleLocalization, Dictionary manifest, Locale defaultLocale) {
+ // ZipFile jarFile = null;
+ // Map localizations = new HashMap(4);
+ // try {
+ // jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ);
+ // for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) {
+ // ZipEntry nextEntry = (ZipEntry) entries.nextElement();
+ // String nextName = nextEntry.getName();
+ // String localeString = getLocaleString(nextName, bundleLocalization);
+ //
+ // if (!nextEntry.isDirectory() && localeString != null) {
+ // Locale nextLocale = getLocale(localeString);
+ // InputStream stream = null;
+ // try {
+ // stream = jarFile.getInputStream(nextEntry);
+ // Properties properties = new Properties();
+ // properties.load(stream);
+ // Properties localizedStrings = getLocalizedProperties(manifest, properties);
+ // if (localizedStrings.size() > 0) {
+ // localizations.put(nextLocale, localizedStrings);
+ // if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) {
+ // localizations.put(nextLocale, localizedStrings);
+ // }
+ // }
+ // } finally {
+ // if (stream != null)
+ // stream.close();
+ // }
+ // }
+ // }
+ // } catch (IOException ioe) {
+ // ioe.printStackTrace();
+ // } finally {
+ // if (jarFile != null) {
+ // try {
+ // jarFile.close();
+ // } catch (IOException ioe) {
+ // // do nothing
+ // }
+ // }
+ // }
+ //
+ // return localizations;
+ // }
+ //
+ // private Map getDirManifestLocalization(File bundleLocation, String bundleLocalization, Dictionary manifest, Locale defaultLocale) {
+ // File localizationPath = new File(bundleLocation, bundleLocalization);
+ // File localizationDir = localizationPath.getParentFile();
+ // String localizationFile = localizationPath.getName();
+ // String[] localizationFiles = localizationDir.list(new LocalizationFileFilter(localizationFile));
+ //
+ // HashMap localizations = null;
+ //
+ // if (localizationFiles != null) {
+ // localizations = new HashMap(localizationFiles.length);
+ // for (int i = 0; i < localizationFiles.length; i++) {
+ // String nextFile = localizationFiles[i];
+ // Locale nextLocale = getLocale(getLocaleString(nextFile, localizationFile));
+ //
+ // try {
+ // Properties properties = loadProperties(bundleLocation, nextFile);
+ // Properties localizedStrings = getLocalizedProperties(manifest, properties);
+ // if (localizedStrings.size() > 0) {
+ // localizations.put(nextLocale, localizedStrings);
+ // if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) {
+ // localizations.put(nextLocale, localizedStrings);
+ // }
+ // }
+ // } catch (IOException ioe) {
+ // ioe.printStackTrace();
+ // }
+ // }
+ // }
+ //
+ // return localizations;
+ // }
+
+ // private class LocalizationFileFilter implements FilenameFilter {
+ //
+ // String filenamePrefix;
+ //
+ // public LocalizationFileFilter(String filenamePrefix) {
+ // this.filenamePrefix = filenamePrefix;
+ // }
+ //
+ // /* (non-Javadoc)
+ // * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
+ // */
+ // public boolean accept(File directory, String filename) {
+ // return (getLocaleString(filename, filenamePrefix) != null ? true : false);
+ // }
+ // }
+
+ // static public String getLocaleString(String filename, String filenamePrefix) {
+ // String localeString = null;
+ // if (filename.startsWith(filenamePrefix) && filename.endsWith(PROPERTIES_FILE_EXTENSION)) {
+ // if (filename.length() > filenamePrefix.length() + PROPERTIES_FILE_EXTENSION.length()) {
+ // localeString = filename.substring(filenamePrefix.length() + 1, filename.length() - PROPERTIES_FILE_EXTENSION.length());
+ // } else {
+ // localeString = ""; //$NON-NLS-1$
+ // }
+ // }
+ // return localeString;
+ // }
+
+ // static private Locale getLocale(String localeString) {
+ // Locale locale = DEFAULT_LOCALE;
+ // if (localeString.length() == 5 && localeString.indexOf('_') == 2) {
+ // locale = new Locale(localeString.substring(0, 2), localeString.substring(3, 5));
+ // } else if (localeString.length() == 2) {
+ // locale = new Locale(localeString.substring(0, 2));
+ // }
+ // return locale;
+ // }
+ //
+ // static private Properties getLocalizedProperties(Dictionary manifest, Properties properties) {
+ // // Walk over the manifest and find all %xxx with the string value
+ // // in the properties file and copy them to the localized properties.
+ // Properties localizedProperties = new Properties();
+ // for (Enumeration e = manifest.keys(); e.hasMoreElements();) {
+ // String key = (String) e.nextElement();
+ // Object value = manifest.get(key);
+ // if (value instanceof String) {
+ // String stringValue = (String) value;
+ // if (stringValue.startsWith("%")) { //$NON-NLS-1$
+ // String newValue = properties.getProperty(stringValue.substring(1));
+ // if (newValue != null)
+ // localizedProperties.put(key, newValue);
+ // }
+ // }
+ // }
+ // return localizedProperties;
+ // }
+
+ private static Properties manifestToProperties(Attributes attributes) {
+ Properties result = new Properties();
+ for (Iterator i = attributes.keySet().iterator(); i.hasNext();) {
+ Attributes.Name key = (Attributes.Name) i.next();
+ result.put(key.toString(), attributes.get(key));
+ }
+ return result;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/FileSetDescriptor.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/FileSetDescriptor.java
new file mode 100644
index 000000000..91a204695
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/FileSetDescriptor.java
@@ -0,0 +1,50 @@
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.util.ArrayList;
+
+public class FileSetDescriptor {
+ private final String key;
+ private String configSpec = null;
+ private String files = ""; //$NON-NLS-1$
+ private final ArrayList permissions = new ArrayList();
+ private String links = ""; //$NON-NLS-1$
+
+ public FileSetDescriptor(String key, String configSpec) {
+ this.key = key;
+ this.configSpec = configSpec;
+ }
+
+ public void setFiles(String property) {
+ files = property;
+ }
+
+ // a permission spec is { <perm>, file patterns }
+ public void addPermissions(String[] property) {
+ permissions.add(property);
+ }
+
+ public void setLinks(String property) {
+ links = property;
+ }
+
+ public String getConfigSpec() {
+ return configSpec;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getLinks() {
+ return links;
+ }
+
+ public String[][] getPermissions() {
+ return (String[][]) permissions.toArray(new String[permissions.size()][]);
+ }
+
+ public String getFiles() {
+ return files;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/GeneratorBundleInfo.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/GeneratorBundleInfo.java
new file mode 100644
index 000000000..c2cf5b542
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/GeneratorBundleInfo.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2006, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.io.ByteArrayInputStream;
+import org.eclipse.equinox.internal.p2.core.helpers.Headers;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.BundleInfo;
+import org.eclipse.osgi.util.ManifestElement;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+
+public class GeneratorBundleInfo extends BundleInfo {
+ // public static final int NO_LEVEL = -1;
+
+ // private String symbolicName;
+ // private String version;
+ // private String location;
+ // private int expectedState;
+ // private int startLevel = NO_LEVEL;
+ // private String manifest;
+
+ private String specialConfigCommands;
+ private String specialUnconfigCommands;
+
+ public GeneratorBundleInfo(BundleInfo bInfo) {
+ super.setBundleId(bInfo.getBundleId());
+ super.setLocation(bInfo.getLocation());
+ super.setManifest(bInfo.getManifest());
+ super.setMarkedAsStarted(bInfo.isMarkedAsStarted());
+ super.setResolved(bInfo.isResolved());
+ super.setStartLevel(bInfo.getStartLevel());
+ super.setSymbolicName(bInfo.getSymbolicName());
+ super.setVersion(bInfo.getVersion());
+ }
+
+ public GeneratorBundleInfo() {
+ // TODO Auto-generated constructor stub
+ }
+
+ // /* (non-Javadoc)
+ // * @see java.lang.Object#hashCode()
+ // */
+ // public int hashCode() {
+ // int result = symbolicName == null ? 0 : symbolicName.hashCode();
+ // result = result + (version == null ? 0 : version.hashCode());
+ // result = result + (location == null ? 0 : location.hashCode());
+ // return result;
+ // }
+ //
+ // public String getSymbolicName() {
+ // return symbolicName;
+ // }
+ //
+ // public String getVersion() {
+ // return version;
+ // }
+ //
+ // public int expectedState() {
+ // return expectedState;
+ // }
+ //
+ // public int getStartLevel() {
+ // return startLevel;
+ // }
+ //
+ // public String getLocation() {
+ // return location;
+ // }
+ //
+ // public void setSymbolicName(String id) {
+ // symbolicName = id;
+ // }
+ //
+ // public void setVersion(String version) {
+ // this.version = version;
+ // }
+ //
+ // public void setExpectedState(int state) {
+ // expectedState = state;
+ // }
+ //
+ // public void setStartLevel(int level) {
+ // this.startLevel = level;
+ // }
+ //
+ // public void setLocation(String location) {
+ // this.location = location;
+ // }
+ //
+ // public void setManifest(String manifest) {
+ // this.manifest = manifest;
+ // }
+ //
+ // public String getManifest() {
+ // return manifest;
+ // }
+ //
+ public String getSpecialConfigCommands() {
+ return specialConfigCommands;
+ }
+
+ public void setSpecialConfigCommands(String specialConfigCommands) {
+ this.specialConfigCommands = specialConfigCommands;
+ }
+
+ public String getSpecialUnconfigCommands() {
+ return specialUnconfigCommands;
+ }
+
+ public void setSpecialUnconfigCommands(String specialUnconfigCommands) {
+ this.specialUnconfigCommands = specialUnconfigCommands;
+ }
+
+ // /* (non-Javadoc)
+ // * @see java.lang.Object#equals(java.lang.Object)
+ // */
+ // public boolean equals(Object toCompare) {
+ // if (toCompare instanceof GeneratorBundleInfo) {
+ // GeneratorBundleInfo info = (GeneratorBundleInfo) toCompare;
+ // if (info.symbolicName.equals(symbolicName) && info.version.equals(version) && (info.location == null || location == null ? true : info.location.equals(location)))
+ // return true;
+ // }
+ // return false;
+ // }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ String superSt = super.toString();
+ if (superSt.length() > 0)
+ buffer.append(superSt.substring(0, superSt.length() - 1));
+ buffer.append(", this.specialConfigCommands="); //$NON-NLS-1$
+ buffer.append(this.specialConfigCommands);
+ buffer.append(')');
+ return buffer.toString();
+ }
+
+ public void initFromManifest(String manifest) {
+ try {
+ super.setManifest(manifest);
+ Headers headers = Headers.parseManifest(new ByteArrayInputStream(manifest.getBytes()));
+ ManifestElement[] element = ManifestElement.parseHeader("bsn", (String) headers.get(Constants.BUNDLE_SYMBOLICNAME)); //$NON-NLS-1$
+ super.setSymbolicName(element[0].getValue());
+ super.setVersion((String) headers.get(Constants.BUNDLE_VERSION));
+ } catch (BundleException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IProductDescriptor.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IProductDescriptor.java
new file mode 100644
index 000000000..ec7f099d8
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IProductDescriptor.java
@@ -0,0 +1,42 @@
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.util.List;
+
+public interface IProductDescriptor {
+
+ public String getLauncherName();
+
+ public List getPlugins();
+
+ public List getPlugins(boolean includeFragments);
+
+ public List getFragments();
+
+ public List getFeatures();
+
+ public boolean containsPlugin(String plugin);
+
+ /**
+ * Parses the specified url and constructs a feature
+ */
+ public String[] getIcons();
+
+ public String getConfigIniPath();
+
+ public String getId();
+
+ public String getSplashLocation();
+
+ public String getProductName();
+
+ public String getApplication();
+
+ public boolean useFeatures();
+
+ public String getVersion();
+
+ public String getVMArguments(String os);
+
+ public String getProgramArguments(String os);
+
+} \ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherInfo.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherInfo.java
index f2e24a436..fc8701628 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherInfo.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherInfo.java
@@ -9,12 +9,30 @@
******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher;
+import java.util.Collection;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
public interface IPublisherInfo {
/**
+ * A bitwise flag to say whether or not the index for the artifact repository should
+ * be updated.
+ */
+ public static final int A_INDEX = 1;
+
+ /**
+ * A bitwise flag to say whether or the artifacts themselves should be published.
+ */
+ public static final int A_PUBLISH = 2;
+
+ /**
+ * A bitwise flag to say whether or not to overwrite disk content discovered
+ * in the repository when publishing an artifact
+ */
+ public static final int A_OVERWRITE = 4;
+
+ /**
* Returns the artifact repository into which any publishable artifacts are published
* or <code>null</code> if none.
* @return a destination artifact repository or <code>null</code>
@@ -29,16 +47,16 @@ public interface IPublisherInfo {
public IMetadataRepository getMetadataRepository();
/**
- * Returns whether or not the artifact repo itself should be published.
- * @return <code>true</code> if the artifact repository should be published.
- * <code>false</code> otherwise.
- */
- public boolean publishArtifactRepository();
-
- /**
* Returns whether or not artifacts themselves should be published.
* @return <code>true</code> if artifacts should be published.
* <code>false</code> otherwise.
*/
- public boolean publishArtifacts();
+ public int getArtifactOptions();
+
+ public IPublishingAdvice getAdvice(String id);
+
+ public void setAdvice(String id, IPublishingAdvice value);
+
+ public Collection getAdviceIds();
+
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherResult.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherResult.java
new file mode 100644
index 000000000..642d9dc21
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherResult.java
@@ -0,0 +1,39 @@
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.util.Collection;
+import java.util.Map;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+
+public interface IPublisherResult {
+ public static final int MERGE_MATCHING = 0;
+ public static final int MERGE_ALL_ROOT = 1;
+ public static final int MERGE_ALL_NON_ROOT = 2;
+
+ public static final String CONFIGURATION_CUS = "CONFIGURATION_CUS"; //$NON-NLS-1$
+
+ // type markers
+ public static final String ROOT = "root"; //$NON-NLS-1$
+ public static final String NON_ROOT = "non_root"; //$NON-NLS-1$
+
+ public void addIU(IInstallableUnit iu, String type);
+
+ public void addIUs(Collection ius, String type);
+
+ public void addFragment(String hostId, IInstallableUnit iu);
+
+ /**
+ * Returns the IUs in this result with the given id.
+ */
+ public Collection getIUs(String id, String type);
+
+ public IInstallableUnit getIU(String id, String type);
+
+ public Collection getFragments(String hostId);
+
+ public Map getFragmentMap();
+
+ public void merge(IPublisherResult result, int mode);
+
+ // TODO not happy about having this here. Need to figure out a better plan
+ public Map getConfigData();
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAction.java
index eea4802d5..5ec1ad5f8 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAction.java
@@ -10,7 +10,6 @@
package org.eclipse.equinox.internal.p2.publisher;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.IPublisherResult;
public interface IPublishingAction {
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAdvice.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAdvice.java
new file mode 100644
index 000000000..dcfcfc838
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublishingAdvice.java
@@ -0,0 +1,12 @@
+package org.eclipse.equinox.internal.p2.publisher;
+
+public interface IPublishingAdvice {
+
+ /**
+ * Merge the given advice together with this advice. <code>null</code> is returned
+ * if the advice is incompatible.
+ * @param advice the advice to merge
+ * @return the merged advice or <code>null</code>
+ */
+ public IPublishingAdvice merge(IPublishingAdvice advice);
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisher.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java
index db3e4dcb1..9a4a8a18e 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisher.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java
@@ -11,17 +11,17 @@ package org.eclipse.equinox.internal.p2.publisher;
import java.util.ArrayList;
import org.eclipse.equinox.internal.p2.publisher.actions.EclipseInstallAction;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.Generator;
-public class InstallPublisher extends AbstractGeneratorApplication {
+public class InstallPublisherApplication extends AbstractPublisherApplication {
protected String id;
protected String version = "1.0.0"; //$NON-NLS-1$
+ protected String name;
protected String flavor;
protected String[] topLevel;
protected String[] configurations;
- public InstallPublisher() {
+ public InstallPublisherApplication() {
}
protected void processParameter(String arg, String parameter, PublisherInfo info) {
@@ -33,14 +33,17 @@ public class InstallPublisher extends AbstractGeneratorApplication {
if (arg.equalsIgnoreCase("-version")) //$NON-NLS-1$
version = parameter;
+ if (arg.equalsIgnoreCase("-name")) //$NON-NLS-1$
+ name = parameter;
+
if (arg.equalsIgnoreCase("-flavor")) //$NON-NLS-1$
flavor = parameter;
if (arg.equalsIgnoreCase("-top")) //$NON-NLS-1$
- topLevel = Generator.getArrayFromString(parameter, ",");
+ topLevel = AbstractPublishingAction.getArrayFromString(parameter, ",");
if (arg.equalsIgnoreCase("-configs")) //$NON-NLS-1$
- configurations = Generator.getArrayFromString(parameter, ",");
+ configurations = AbstractPublishingAction.getArrayFromString(parameter, ",");
}
protected IPublishingAction[] createActions() {
@@ -51,6 +54,6 @@ public class InstallPublisher extends AbstractGeneratorApplication {
private IPublishingAction createEclipseInstallAction() {
String[] exclusions = {"plugins", "features", "configuration"};
- return new EclipseInstallAction(source, id, version, flavor, topLevel, configurations, exclusions);
+ return new EclipseInstallAction(source, id, version, name, flavor, topLevel, configurations, exclusions);
}
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/MetadataGeneratorHelper.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/MetadataGeneratorHelper.java
new file mode 100644
index 000000000..ffd2eaf26
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/MetadataGeneratorHelper.java
@@ -0,0 +1,1262 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Genuitec, LLC - added license support
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.io.*;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
+import org.eclipse.equinox.internal.p2.metadata.InstallableUnit;
+import org.eclipse.equinox.internal.p2.publisher.features.*;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.BundleInfo;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.ArtifactDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStepDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.metadata.*;
+import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
+import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription;
+import org.eclipse.osgi.service.environment.EnvironmentInfo;
+import org.eclipse.osgi.service.resolver.*;
+import org.eclipse.osgi.util.ManifestElement;
+import org.osgi.framework.*;
+
+public class MetadataGeneratorHelper {
+ /**
+ * A capability namespace representing the type of Eclipse resource (bundle, feature, source bundle, etc)
+ * @see RequiredCapability#getNamespace()
+ */
+ public static final String NAMESPACE_ECLIPSE_TYPE = "org.eclipse.equinox.p2.eclipse.type"; //$NON-NLS-1$
+
+ /**
+ * A capability name in the {@link #NAMESPACE_ECLIPSE_TYPE} namespace
+ * representing and OSGi bundle resource
+ * @see RequiredCapability#getName()
+ */
+ public static final String TYPE_ECLIPSE_BUNDLE = "bundle"; //$NON-NLS-1$
+ /**
+ * A capability name in the {@link #NAMESPACE_ECLIPSE_TYPE} namespace
+ * representing a feature
+ * @see RequiredCapability#getName()
+ */
+ public static final String TYPE_ECLIPSE_FEATURE = "feature"; //$NON-NLS-1$
+
+ /**
+ * A capability name in the {@link #NAMESPACE_ECLIPSE_TYPE} namespace
+ * representing a source bundle
+ * @see RequiredCapability#getName()
+ */
+ public static final String TYPE_ECLIPSE_SOURCE = "source"; //$NON-NLS-1$
+
+ /**
+ * A capability name in the {@link #NAMESPACE_ECLIPSE_TYPE} namespace
+ * representing localized manifest properties
+ * @see RequiredCapability#getName()
+ */
+ public static final String TYPE_ECLIPSE_MANIFEST_LOCALIZATION = "manifest.localization"; //$NON-NLS-1$
+
+ // Only certain properties in the bundle manifest are assumed to be localized.
+ public static final String[] BUNDLE_LOCALIZED_PROPERTIES = {Constants.BUNDLE_NAME, Constants.BUNDLE_DESCRIPTION, Constants.BUNDLE_VENDOR, Constants.BUNDLE_CONTACTADDRESS, Constants.BUNDLE_DOCURL, Constants.BUNDLE_UPDATELOCATION};
+ public static final int BUNDLE_LOCALIZATION_INDEX = BUNDLE_LOCALIZED_PROPERTIES.length;
+
+ private static final String[] BUNDLE_IU_PROPERTY_MAP = {Constants.BUNDLE_NAME, IInstallableUnit.PROP_NAME, Constants.BUNDLE_DESCRIPTION, IInstallableUnit.PROP_DESCRIPTION, Constants.BUNDLE_VENDOR, IInstallableUnit.PROP_PROVIDER, Constants.BUNDLE_CONTACTADDRESS, IInstallableUnit.PROP_CONTACT, Constants.BUNDLE_DOCURL, IInstallableUnit.PROP_DOC_URL};
+
+ private static final String CAPABILITY_NS_JAVA_PACKAGE = "java.package"; //$NON-NLS-1$
+ private static final String CAPABILITY_NS_OSGI_BUNDLE = "osgi.bundle"; //$NON-NLS-1$
+ private static final String CAPABILITY_NS_OSGI_FRAGMENT = "osgi.fragment"; //$NON-NLS-1$
+
+ private static final String CAPABILITY_NS_UPDATE_FEATURE = "org.eclipse.update.feature"; //$NON-NLS-1$
+
+ private static final Version DEFAULT_JRE_VERSION = new Version("1.6"); //$NON-NLS-1$
+
+ public static final String ECLIPSE_FEATURE_CLASSIFIER = "org.eclipse.update.feature"; //$NON-NLS-1$
+ public static final String OSGI_BUNDLE_CLASSIFIER = "osgi.bundle"; //$NON-NLS-1$
+ public static final String BINARY_ARTIFACT_CLASSIFIER = "binary"; //$NON-NLS-1$
+
+ public static final String INSTALL_FEATURES_FILTER = "(org.eclipse.update.install.features=true)"; //$NON-NLS-1$
+
+ private static final String IU_NAMESPACE = IInstallableUnit.NAMESPACE_IU_ID;
+
+ private static final String LAUNCHER_ID_PREFIX = "org.eclipse.launcher"; //$NON-NLS-1$
+
+ private static final String ECLIPSE_INSTALL_HANDLER_PROP = "org.eclipse.update.installHandler"; //$NON-NLS-1$
+
+ //TODO - need to come up with a way to infer launcher version
+ private static final Version LAUNCHER_VERSION = new Version(1, 0, 0);
+
+ private static final Version versionMax = new Version(Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE);
+
+ public static final TouchpointType TOUCHPOINT_NATIVE = MetadataFactory.createTouchpointType("org.eclipse.equinox.p2.native", new Version(1, 0, 0)); //$NON-NLS-1$
+ public static final TouchpointType TOUCHPOINT_OSGI = MetadataFactory.createTouchpointType("org.eclipse.equinox.p2.osgi", new Version(1, 0, 0)); //$NON-NLS-1$
+
+ public static final ProvidedCapability BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, new Version(1, 0, 0));
+ public static final ProvidedCapability FEATURE_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_FEATURE, new Version(1, 0, 0));
+ public static final ProvidedCapability SOURCE_BUNDLE_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_SOURCE, new Version(1, 0, 0));
+ public static final ProvidedCapability MANIFEST_LOCALIZATION_CAPABILITY = MetadataFactory.createProvidedCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_MANIFEST_LOCALIZATION, new Version(1, 0, 0));
+
+ static final String DEFAULT_BUNDLE_LOCALIZATION = "plugin"; //$NON-NLS-1$
+ static final String PROPERTIES_FILE_EXTENSION = ".properties"; //$NON-NLS-1$
+ static final String MANIFEST_LOCALIZATIONS = "eclipse.p2.manifest.localizations"; //$NON-NLS-1$
+
+ static final Locale DEFAULT_LOCALE = new Locale("df", "LT"); //$NON-NLS-1$//$NON-NLS-2$
+ static final Locale PSEUDO_LOCALE = new Locale("zz", "ZZ"); //$NON-NLS-1$//$NON-NLS-2$
+
+ public static IArtifactDescriptor createArtifactDescriptor(IArtifactKey key, File pathOnDisk, boolean asIs, boolean recur) {
+ //TODO this size calculation is bogus
+ ArtifactDescriptor result = new ArtifactDescriptor(key);
+ if (pathOnDisk != null) {
+ result.setProperty(IArtifactDescriptor.ARTIFACT_SIZE, Long.toString(pathOnDisk.length()));
+ // TODO - this is wrong but I'm testing a work-around for bug 205842
+ result.setProperty(IArtifactDescriptor.DOWNLOAD_SIZE, Long.toString(pathOnDisk.length()));
+ }
+ return result;
+ }
+
+ public static IArtifactDescriptor createPack200ArtifactDescriptor(IArtifactKey key, File pathOnDisk, String installSize) {
+ final String PACKED_FORMAT = "packed"; //$NON-NLS-1$
+ //TODO this size calculation is bogus
+ ArtifactDescriptor result = new ArtifactDescriptor(key);
+ if (pathOnDisk != null) {
+ result.setProperty(IArtifactDescriptor.ARTIFACT_SIZE, installSize);
+ // TODO - this is wrong but I'm testing a work-around for bug 205842
+ result.setProperty(IArtifactDescriptor.DOWNLOAD_SIZE, Long.toString(pathOnDisk.length()));
+ }
+ ProcessingStepDescriptor[] steps = new ProcessingStepDescriptor[] {new ProcessingStepDescriptor("org.eclipse.equinox.p2.processing.Pack200Unpacker", null, true)}; //$NON-NLS-1$
+ result.setProcessingSteps(steps);
+ result.setProperty(IArtifactDescriptor.FORMAT, PACKED_FORMAT);
+ return result;
+ }
+
+ public static IArtifactKey createBundleArtifactKey(String bsn, String version) {
+ return new ArtifactKey(OSGI_BUNDLE_CLASSIFIER, bsn, new Version(version));
+ }
+
+ public static IInstallableUnit createIUFragment(String id, String version, String flavor, String configSpec, Map touchpointData) {
+ InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
+ String resultId = flavor + AbstractPublishingAction.createIdString(configSpec) + id;
+ cu.setId(resultId);
+ Version resultVersion = new Version(version);
+ cu.setVersion(resultVersion);
+
+ cu.setFilter(AbstractPublishingAction.createFilterSpec(configSpec));
+ cu.setHost(new RequiredCapability[] {MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, id, new VersionRange(resultVersion, true, resultVersion, true), null, false, false)});
+ cu.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
+ cu.setCapabilities(new ProvidedCapability[] {MetadataGeneratorHelper.createSelfCapability(resultId, resultVersion)});
+
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ return MetadataFactory.createInstallableUnit(cu);
+ }
+
+ public static IInstallableUnit createBundleConfigurationUnit(String iuId, Version iuVersion, boolean isBundleFragment, GeneratorBundleInfo configInfo, String configurationFlavor, String filter) {
+ if (configInfo == null)
+ return null;
+
+ InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
+ String configUnitId = configurationFlavor + iuId;
+ cu.setId(configUnitId);
+ cu.setVersion(iuVersion);
+
+ //Indicate the IU to which this CU apply
+ cu.setHost(new RequiredCapability[] { //
+ MetadataFactory.createRequiredCapability(CAPABILITY_NS_OSGI_BUNDLE, iuId, new VersionRange(iuVersion, true, versionMax, true), null, false, false), //
+ MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, new VersionRange(new Version(1, 0, 0), true, new Version(2, 0, 0), false), null, false, false)});
+
+ //Adds capabilities for fragment, self, and describing the flavor supported
+ cu.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
+ cu.setCapabilities(new ProvidedCapability[] {createSelfCapability(configUnitId, iuVersion), MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_FLAVOR, configurationFlavor, new Version(1, 0, 0))});
+
+ Map touchpointData = new HashMap();
+ touchpointData.put("install", "installBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
+ touchpointData.put("uninstall", "uninstallBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
+ touchpointData.put("configure", createConfigScript(configInfo, isBundleFragment)); //$NON-NLS-1$
+ touchpointData.put("unconfigure", createUnconfigScript(configInfo, isBundleFragment)); //$NON-NLS-1$
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ cu.setFilter(filter);
+ return MetadataFactory.createInstallableUnit(cu);
+ }
+
+ public static IInstallableUnit createBundleIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key, Set localizationIUs) {
+ IInstallableUnit bundleIU = createBundleIU(bd, manifest, isFolderPlugin, key);
+
+ if (manifest != null && bd.getLocation() != null) {
+ String bundleLocalization = (String) manifest.get(Constants.BUNDLE_LOCALIZATION);
+ if (bundleLocalization == null) {
+ bundleLocalization = DEFAULT_BUNDLE_LOCALIZATION;
+ }
+ Map manifestLocalizations = getManifestLocalizations(manifest, new File(bd.getLocation()));
+ if (manifestLocalizations != null) {
+ localizationIUs.addAll(createLocalizationFragmentsForBundle(bd, manifestLocalizations));
+ }
+ }
+ return bundleIU;
+ }
+
+ public static IInstallableUnit createBundleIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key) {
+ boolean isBinaryBundle = true;
+ if (manifest != null && manifest.containsKey("Eclipse-SourceBundle")) { //$NON-NLS-1$
+ isBinaryBundle = false;
+ }
+ InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
+ iu.setSingleton(bd.isSingleton());
+ iu.setId(bd.getSymbolicName());
+ iu.setVersion(bd.getVersion());
+ iu.setFilter(bd.getPlatformFilter());
+
+ iu.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(bd.getSymbolicName(), new VersionRange(new Version(0, 0, 0), true, bd.getVersion(), false), IUpdateDescriptor.NORMAL, null));
+
+ boolean isFragment = bd.getHost() != null;
+ // boolean requiresAFragment = isFragment ? false : requireAFragment(bd, manifest);
+
+ //Process the required bundles
+ BundleSpecification requiredBundles[] = bd.getRequiredBundles();
+ ArrayList reqsDeps = new ArrayList();
+ // if (requiresAFragment)
+ // reqsDeps.add(MetadataFactory.createRequiredCapability(CAPABILITY_TYPE_OSGI_FRAGMENTS, bd.getSymbolicName(), VersionRange.emptyRange, null, false, false));
+ if (isFragment)
+ reqsDeps.add(MetadataFactory.createRequiredCapability(CAPABILITY_NS_OSGI_BUNDLE, bd.getHost().getName(), bd.getHost().getVersionRange(), null, false, false));
+ for (int j = 0; j < requiredBundles.length; j++)
+ reqsDeps.add(MetadataFactory.createRequiredCapability(CAPABILITY_NS_OSGI_BUNDLE, requiredBundles[j].getName(), requiredBundles[j].getVersionRange() == VersionRange.emptyRange ? null : requiredBundles[j].getVersionRange(), null, requiredBundles[j].isOptional(), false));
+
+ // Process the import packages
+ ImportPackageSpecification osgiImports[] = bd.getImportPackages();
+ for (int i = 0; i < osgiImports.length; i++) {
+ // TODO we need to sort out how we want to handle wild-carded dynamic imports - for now we ignore them
+ ImportPackageSpecification importSpec = osgiImports[i];
+ String importPackageName = importSpec.getName();
+ if (importPackageName.indexOf('*') != -1)
+ continue;
+
+ VersionRange versionRange = importSpec.getVersionRange() == VersionRange.emptyRange ? null : importSpec.getVersionRange();
+
+ //TODO this needs to be refined to take into account all the attribute handled by imports
+ reqsDeps.add(MetadataFactory.createRequiredCapability(CAPABILITY_NS_JAVA_PACKAGE, importPackageName, versionRange, null, isOptional(importSpec), false));
+ }
+ iu.setRequiredCapabilities((RequiredCapability[]) reqsDeps.toArray(new RequiredCapability[reqsDeps.size()]));
+
+ // Create set of provided capabilities
+ ArrayList providedCapabilities = new ArrayList();
+ providedCapabilities.add(createSelfCapability(bd.getSymbolicName(), bd.getVersion()));
+ providedCapabilities.add(MetadataFactory.createProvidedCapability(CAPABILITY_NS_OSGI_BUNDLE, bd.getSymbolicName(), bd.getVersion()));
+
+ // Process the export package
+ ExportPackageDescription exports[] = bd.getExportPackages();
+ for (int i = 0; i < exports.length; i++) {
+ //TODO make sure that we support all the refinement on the exports
+ providedCapabilities.add(MetadataFactory.createProvidedCapability(CAPABILITY_NS_JAVA_PACKAGE, exports[i].getName(), exports[i].getVersion() == Version.emptyVersion ? null : exports[i].getVersion()));
+ }
+ // Here we add a bundle capability to identify bundles
+ if (isBinaryBundle)
+ providedCapabilities.add(BUNDLE_CAPABILITY);
+ else
+ providedCapabilities.add(SOURCE_BUNDLE_CAPABILITY);
+
+ if (isFragment)
+ providedCapabilities.add(MetadataFactory.createProvidedCapability(CAPABILITY_NS_OSGI_FRAGMENT, bd.getHost().getName(), bd.getVersion()));
+ iu.setCapabilities((ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()]));
+
+ iu.setArtifacts(new IArtifactKey[] {key});
+
+ iu.setTouchpointType(TOUCHPOINT_OSGI);
+
+ // Set certain properties from the manifest header attributes as IU properties.
+ // The values of these attributes may be localized (strings starting with '%')
+ // with the translated values appearing in the localization IU fragments
+ // associated with the bundle IU.
+ if (manifest != null) {
+ int i = 0;
+ while (i < BUNDLE_IU_PROPERTY_MAP.length) {
+ if (manifest.containsKey(BUNDLE_IU_PROPERTY_MAP[i])) {
+ String value = (String) manifest.get(BUNDLE_IU_PROPERTY_MAP[i]);
+ if (value != null && value.length() > 0) {
+ iu.setProperty(BUNDLE_IU_PROPERTY_MAP[i + 1], value);
+ }
+ }
+ i += 2;
+ }
+ }
+
+ // Define the immutable metadata for this IU. In this case immutable means
+ // that this is something that will not impact the configuration.
+ Map touchpointData = new HashMap();
+ if (isFolderPlugin)
+ touchpointData.put("zipped", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ touchpointData.put("manifest", toManifestString(manifest)); //$NON-NLS-1$
+ iu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+
+ return MetadataFactory.createInstallableUnit(iu);
+ }
+
+ private static List createLocalizationFragmentsForBundle(BundleDescription bd, Map manifestLocalizations) {
+ List localizationFragments = new ArrayList(manifestLocalizations.size());
+ for (Iterator iter = manifestLocalizations.keySet().iterator(); iter.hasNext();) {
+ Locale locale = (Locale) iter.next();
+ Properties localizedStrings = (Properties) manifestLocalizations.get(locale);
+ IInstallableUnitFragment nextLocaleFragment = createLocalizationFragmentOfBundle(bd, locale, localizedStrings);
+ localizationFragments.add(nextLocaleFragment);
+ }
+ return localizationFragments;
+ }
+
+ /*
+ * @param bd
+ * @param locale
+ * @param localizedStrings
+ * @return installableUnitFragment
+ */
+ private static IInstallableUnitFragment createLocalizationFragmentOfBundle(BundleDescription bd, Locale locale, Properties localizedStrings) {
+ InstallableUnitFragmentDescription fragment = new MetadataFactory.InstallableUnitFragmentDescription();
+ String fragmentId = makeLocalizationFragmentId(bd.getSymbolicName(), locale);
+ fragment.setId(fragmentId);
+ fragment.setVersion(bd.getVersion());
+
+ RequiredCapability[] hostReqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, bd.getSymbolicName(), new VersionRange(bd.getVersion(), true, bd.getVersion(), true), null, false, false)};
+ fragment.setHost(hostReqs);
+
+ fragment.setSingleton(true);
+
+ Enumeration propertyKeys = localizedStrings.propertyNames();
+ while (propertyKeys.hasMoreElements()) {
+ String nextKey = (String) propertyKeys.nextElement();
+ fragment.setProperty(nextKey, localizedStrings.getProperty(nextKey));
+ }
+ // TODO: do we need any capabilities?
+ // Create set of provided capabilities It's just a tag indicating a localization fragment.
+ ArrayList providedCapabilities = new ArrayList(1);
+ providedCapabilities.add(MANIFEST_LOCALIZATION_CAPABILITY);
+ fragment.setCapabilities((ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()]));
+
+ return MetadataFactory.createInstallableUnitFragment(fragment);
+ }
+
+ public static void createHostLocalizationFragments(BundleDescription bd, String hostId, String[] hostBundleManifestValues, Set localizationIUs) {
+ Map hostLocalizations = getHostLocalizations(new File(bd.getLocation()), hostBundleManifestValues);
+
+ for (Iterator iter = hostLocalizations.keySet().iterator(); iter.hasNext();) {
+ Locale locale = (Locale) iter.next();
+ Properties localizedStrings = (Properties) hostLocalizations.get(locale);
+ IInstallableUnitFragment nextLocaleFragment = createLocalizationFragmentOfHost(hostId, hostBundleManifestValues, bd, locale, localizedStrings);
+ localizationIUs.add(nextLocaleFragment);
+ }
+ }
+
+ /*
+ * @param hostId
+ * @param bd
+ * @param locale
+ * @param localizedStrings
+ * @return installableUnitFragment
+ */
+ private static IInstallableUnitFragment createLocalizationFragmentOfHost(String hostId, String[] hostManifestValues, BundleDescription bd, Locale locale, Properties localizedStrings) {
+ InstallableUnitFragmentDescription fragment = new MetadataFactory.InstallableUnitFragmentDescription();
+ HostSpecification hostSpec = bd.getHost();
+ String fragmentId = makeLocalizationFragmentId(hostId, locale);
+ fragment.setId(fragmentId);
+ fragment.setVersion(bd.getVersion()); // TODO: is this a meaningful version?
+
+ RequiredCapability[] hostReqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, hostSpec.getName(), hostSpec.getVersionRange(), null, false, false)};
+ fragment.setHost(hostReqs);
+
+ fragment.setSingleton(true);
+
+ for (int i = 0; i < BUNDLE_LOCALIZED_PROPERTIES.length; i++) {
+ String nextKey = hostManifestValues[i];
+ String localizedValue = null;
+ if (nextKey != null && (localizedValue = localizedStrings.getProperty(nextKey)) != null) {
+ fragment.setProperty(nextKey, localizedValue);
+ }
+ }
+ // TODO: do we need any capabilities? It's just a tag indicating a localization fragment.
+ // Create set of provided capabilities
+ ArrayList providedCapabilities = new ArrayList(1);
+ providedCapabilities.add(MANIFEST_LOCALIZATION_CAPABILITY);
+ fragment.setCapabilities((ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()]));
+
+ return MetadataFactory.createInstallableUnitFragment(fragment);
+ }
+
+ /**
+ * @param id
+ * @param locale
+ * @return the id for the fragment contain the localized properties
+ * for the manifest of the bundle with the given id
+ * in the given locale.
+ */
+ private static String makeLocalizationFragmentId(String id, Locale locale) {
+ String localeString = (!DEFAULT_LOCALE.equals(locale) ? '_' + locale.toString() : ""); //$NON-NLS-1$
+ return id + "_manifest" + localeString + "_properties"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Creates an IU corresponding to an update site category
+ * @param category The category descriptor
+ * @param featureIUs The IUs of the features that belong to the category
+ * @param parentCategory The parent category, or <code>null</code>
+ * @return an IU representing the category
+ */
+ public static IInstallableUnit createCategoryIU(SiteCategory category, Set featureIUs, IInstallableUnit parentCategory) {
+ InstallableUnitDescription cat = new MetadataFactory.InstallableUnitDescription();
+ cat.setSingleton(true);
+ cat.setId(category.getName());
+ cat.setVersion(Version.emptyVersion);
+ cat.setProperty(IInstallableUnit.PROP_NAME, category.getLabel());
+ cat.setProperty(IInstallableUnit.PROP_DESCRIPTION, category.getDescription());
+
+ ArrayList reqsConfigurationUnits = new ArrayList(featureIUs.size());
+ for (Iterator iterator = featureIUs.iterator(); iterator.hasNext();) {
+ IInstallableUnit iu = (IInstallableUnit) iterator.next();
+ VersionRange range = new VersionRange(iu.getVersion(), true, iu.getVersion(), true);
+ reqsConfigurationUnits.add(MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, iu.getId(), range, iu.getFilter(), false, false));
+ }
+ //note that update sites don't currently support nested categories, but it may be useful to add in the future
+ if (parentCategory != null) {
+ reqsConfigurationUnits.add(MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, parentCategory.getId(), VersionRange.emptyRange, parentCategory.getFilter(), false, false));
+ }
+ cat.setRequiredCapabilities((RequiredCapability[]) reqsConfigurationUnits.toArray(new RequiredCapability[reqsConfigurationUnits.size()]));
+ cat.setCapabilities(new ProvidedCapability[] {MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_IU_ID, category.getName(), Version.emptyVersion)});
+ cat.setArtifacts(new IArtifactKey[0]);
+ cat.setProperty(IInstallableUnit.PROP_TYPE_CATEGORY, "true"); //$NON-NLS-1$
+ return MetadataFactory.createInstallableUnit(cat);
+ }
+
+ private static String createConfigScript(GeneratorBundleInfo configInfo, boolean isBundleFragment) {
+ if (configInfo == null)
+ return ""; //$NON-NLS-1$
+
+ String configScript = "";//$NON-NLS-1$
+ if (!isBundleFragment && configInfo.getStartLevel() != BundleInfo.NO_LEVEL) {
+ configScript += "setStartLevel(startLevel:" + configInfo.getStartLevel() + ");"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (!isBundleFragment && configInfo.isMarkedAsStarted()) {
+ configScript += "markStarted(started: true);"; //$NON-NLS-1$
+ }
+
+ if (configInfo.getSpecialConfigCommands() != null) {
+ configScript += configInfo.getSpecialConfigCommands();
+ }
+
+ return configScript;
+ }
+
+ private static String createDefaultBundleConfigScript(GeneratorBundleInfo configInfo) {
+ return createConfigScript(configInfo, false);
+ }
+
+ public static IInstallableUnit createDefaultBundleConfigurationUnit(GeneratorBundleInfo configInfo, GeneratorBundleInfo unconfigInfo, String configurationFlavor) {
+ InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
+ String configUnitId = createDefaultConfigUnitId(OSGI_BUNDLE_CLASSIFIER, configurationFlavor);
+ cu.setId(configUnitId);
+ Version configUnitVersion = new Version(1, 0, 0);
+ cu.setVersion(configUnitVersion);
+
+ // Add capabilities for fragment, self, and describing the flavor supported
+ cu.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
+ cu.setCapabilities(new ProvidedCapability[] {createSelfCapability(configUnitId, configUnitVersion), MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_FLAVOR, configurationFlavor, new Version(1, 0, 0))});
+
+ // Create a required capability on bundles
+ RequiredCapability[] reqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_BUNDLE, VersionRange.emptyRange, null, false, true)};
+ cu.setHost(reqs);
+ Map touchpointData = new HashMap();
+
+ touchpointData.put("install", "installBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
+ touchpointData.put("uninstall", "uninstallBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
+ touchpointData.put("configure", createDefaultBundleConfigScript(configInfo)); //$NON-NLS-1$
+ touchpointData.put("unconfigure", createDefaultBundleUnconfigScript(unconfigInfo)); //$NON-NLS-1$
+
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ return MetadataFactory.createInstallableUnit(cu);
+ }
+
+ private static String createDefaultBundleUnconfigScript(GeneratorBundleInfo unconfigInfo) {
+ return createUnconfigScript(unconfigInfo, false);
+ }
+
+ public static String createDefaultConfigUnitId(String classifier, String configurationFlavor) {
+ return configurationFlavor + "." + classifier + ".default"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ public static IInstallableUnit createDefaultFeatureConfigurationUnit(String configurationFlavor) {
+ InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
+ String configUnitId = createDefaultConfigUnitId(ECLIPSE_FEATURE_CLASSIFIER, configurationFlavor);
+ cu.setId(configUnitId);
+ Version configUnitVersion = new Version(1, 0, 0);
+ cu.setVersion(configUnitVersion);
+
+ // Add capabilities for fragment, self, and describing the flavor supported
+ cu.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
+ cu.setCapabilities(new ProvidedCapability[] {createSelfCapability(configUnitId, configUnitVersion), MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_FLAVOR, configurationFlavor, new Version(1, 0, 0))});
+
+ // Create a required capability on features
+ RequiredCapability[] reqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_FEATURE, VersionRange.emptyRange, null, true, true)};
+ cu.setHost(reqs);
+
+ cu.setFilter(INSTALL_FEATURES_FILTER);
+ Map touchpointData = new HashMap();
+ touchpointData.put("install", "installFeature(feature:${artifact},featureId:default,featureVersion:default)"); //$NON-NLS-1$//$NON-NLS-2$
+ touchpointData.put("uninstall", "uninstallFeature(feature:${artifact},featureId:default,featureVersion:default)"); //$NON-NLS-1$//$NON-NLS-2$
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+
+ return MetadataFactory.createInstallableUnit(cu);
+ }
+
+ public static IInstallableUnit createDefaultConfigurationUnitForSourceBundles(String configurationFlavor) {
+ InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
+ String configUnitId = createDefaultConfigUnitId("source", configurationFlavor); //$NON-NLS-1$
+ cu.setId(configUnitId);
+ Version configUnitVersion = new Version(1, 0, 0);
+ cu.setVersion(configUnitVersion);
+
+ // Add capabilities for fragment, self, and describing the flavor supported
+ cu.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
+ cu.setCapabilities(new ProvidedCapability[] {createSelfCapability(configUnitId, configUnitVersion), MetadataFactory.createProvidedCapability(IInstallableUnit.NAMESPACE_FLAVOR, configurationFlavor, new Version(1, 0, 0))});
+
+ // Create a required capability on source providers
+ RequiredCapability[] reqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(NAMESPACE_ECLIPSE_TYPE, TYPE_ECLIPSE_SOURCE, VersionRange.emptyRange, null, true, true)};
+ cu.setHost(reqs);
+ Map touchpointData = new HashMap();
+
+ touchpointData.put("install", "addSourceBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
+ touchpointData.put("uninstall", "removeSourceBundle(bundle:${artifact})"); //$NON-NLS-1$ //$NON-NLS-2$
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ return MetadataFactory.createInstallableUnit(cu);
+ }
+
+ private static void addExtraProperties(IInstallableUnit iiu, Properties extraProperties) {
+ if (iiu instanceof InstallableUnit) {
+ InstallableUnit iu = (InstallableUnit) iiu;
+
+ for (Enumeration e = extraProperties.propertyNames(); e.hasMoreElements();) {
+ String name = (String) e.nextElement();
+ iu.setProperty(name, extraProperties.getProperty(name));
+ }
+ }
+ }
+
+ public static IInstallableUnit[] createEclipseIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key, Properties extraProperties) {
+ ArrayList iusCreated = new ArrayList(4);
+
+ IInstallableUnit iu = createBundleIU(bd, manifest, isFolderPlugin, key);
+ addExtraProperties(iu, extraProperties);
+ iusCreated.add(iu);
+
+ if (manifest != null) {
+ String bundleLocalization = null;
+ if (bd.getHost() == null) // not a fragment
+ bundleLocalization = (String) manifest.get(Constants.BUNDLE_LOCALIZATION);
+ if (bundleLocalization == null)
+ bundleLocalization = DEFAULT_BUNDLE_LOCALIZATION;
+
+ Map manifestLocalizations = getManifestLocalizations(manifest, new File(bd.getLocation()));
+
+ if (manifestLocalizations != null) {
+ List localizationFragments = createLocalizationFragmentsForBundle(bd, manifestLocalizations);
+ for (Iterator iter = localizationFragments.iterator(); iter.hasNext();) {
+ addExtraProperties((IInstallableUnit) iter.next(), extraProperties);
+ }
+ iusCreated.addAll(localizationFragments);
+ }
+ }
+
+ return (IInstallableUnit[]) (iusCreated.toArray(new IInstallableUnit[iusCreated.size()]));
+ }
+
+ public static IArtifactKey createFeatureArtifactKey(String fsn, String version) {
+ return new ArtifactKey(ECLIPSE_FEATURE_CLASSIFIER, fsn, new Version(version));
+ }
+
+ public static IInstallableUnit createFeatureJarIU(Feature feature, boolean isExploded) {
+ return createFeatureJarIU(feature, null, isExploded, null);
+ }
+
+ public static IInstallableUnit createFeatureJarIU(Feature feature, ArrayList childIUs, boolean isExploded, Properties extraProperties) {
+ InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
+ String id = getTransformedId(feature.getId(), /*isPlugin*/false, /*isGroup*/false);
+ iu.setId(id);
+ Version version = new Version(feature.getVersion());
+ iu.setVersion(version);
+ if (feature.getLicense() != null)
+ iu.setLicense(new License(feature.getLicenseURL(), feature.getLicense()));
+ if (feature.getCopyright() != null)
+ iu.setCopyright(new Copyright(feature.getCopyrightURL(), feature.getCopyright()));
+
+ // The required capabilities are not specified at this level because we don't want the feature jar to be attractive to install.
+
+ iu.setTouchpointType(TOUCHPOINT_OSGI);
+ iu.setFilter(INSTALL_FEATURES_FILTER);
+ iu.setSingleton(true);
+
+ if (feature.getInstallHandler() != null) {
+ String installHandlerProperty = "handler=" + feature.getInstallHandler(); //$NON-NLS-1$
+
+ if (feature.getInstallHandlerLibrary() != null)
+ installHandlerProperty += ", library=" + feature.getInstallHandlerLibrary(); //$NON-NLS-1$
+
+ if (feature.getInstallHandlerURL() != null)
+ installHandlerProperty += ", url=" + feature.getInstallHandlerURL(); //$NON-NLS-1$
+
+ iu.setProperty(ECLIPSE_INSTALL_HANDLER_PROP, installHandlerProperty);
+ }
+
+ iu.setCapabilities(new ProvidedCapability[] {createSelfCapability(id, version), FEATURE_CAPABILITY, MetadataFactory.createProvidedCapability(CAPABILITY_NS_UPDATE_FEATURE, feature.getId(), version)});
+ iu.setArtifacts(new IArtifactKey[] {createFeatureArtifactKey(feature.getId(), version.toString())});
+
+ // link in all the children (if any) as requirements.
+ // TODO consider if these should be linked as exact version numbers. Should be ok but may be brittle.
+ if (childIUs != null) {
+ RequiredCapability[] required = new RequiredCapability[childIUs.size()];
+ for (int i = 0; i < childIUs.size(); i++) {
+ IInstallableUnit child = (IInstallableUnit) childIUs.get(i);
+ required[i] = MetadataFactory.createRequiredCapability(IU_NAMESPACE, child.getId(), new VersionRange(child.getVersion(), true, child.getVersion(), true), INSTALL_FEATURES_FILTER, false, false);
+ }
+ iu.setRequiredCapabilities(required);
+ }
+
+ if (isExploded) {
+ // Define the immutable metadata for this IU. In this case immutable means
+ // that this is something that will not impact the configuration.
+ Map touchpointData = new HashMap();
+ touchpointData.put("zipped", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ iu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ }
+
+ if (extraProperties != null) {
+ Enumeration e = extraProperties.propertyNames();
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ iu.setProperty(name, extraProperties.getProperty(name));
+ }
+ }
+
+ return MetadataFactory.createInstallableUnit(iu);
+ }
+
+ // moved to FeaturesAction
+ public static IInstallableUnit createGroupIU(Feature feature, IInstallableUnit featureIU) {
+ return createGroupIU(feature, featureIU, null);
+ }
+
+ // moved to FeaturesAction
+ public static IInstallableUnit createGroupIU(Feature feature, IInstallableUnit featureIU, Properties extraProperties) {
+ InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
+ String id = getTransformedId(feature.getId(), /*isPlugin*/false, /*isGroup*/true);
+ iu.setId(id);
+ Version version = new Version(feature.getVersion());
+ iu.setVersion(version);
+ iu.setProperty(IInstallableUnit.PROP_NAME, feature.getLabel());
+ if (feature.getLicense() != null)
+ iu.setLicense(new License(feature.getLicenseURL(), feature.getLicense()));
+ if (feature.getCopyright() != null)
+ iu.setCopyright(new Copyright(feature.getCopyrightURL(), feature.getCopyright()));
+ iu.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(id, new VersionRange(new Version(0, 0, 0), true, new Version(feature.getVersion()), false), IUpdateDescriptor.NORMAL, null));
+
+ FeatureEntry entries[] = feature.getEntries();
+ RequiredCapability[] required = new RequiredCapability[entries.length + 1];
+ for (int i = 0; i < entries.length; i++) {
+ VersionRange range = getVersionRange(entries[i]);
+ required[i] = MetadataFactory.createRequiredCapability(IU_NAMESPACE, getTransformedId(entries[i].getId(), entries[i].isPlugin(), /*isGroup*/true), range, getFilter(entries[i]), entries[i].isOptional(), false);
+ }
+ required[entries.length] = MetadataFactory.createRequiredCapability(IU_NAMESPACE, featureIU.getId(), new VersionRange(featureIU.getVersion(), true, featureIU.getVersion(), true), INSTALL_FEATURES_FILTER, false, false);
+ iu.setRequiredCapabilities(required);
+ iu.setTouchpointType(TouchpointType.NONE);
+ iu.setProperty(IInstallableUnit.PROP_TYPE_GROUP, Boolean.TRUE.toString());
+ // TODO: shouldn't the filter for the group be constructed from os, ws, arch, nl
+ // of the feature?
+ // iu.setFilter(filter);
+ iu.setCapabilities(new ProvidedCapability[] {createSelfCapability(id, version)});
+
+ if (extraProperties != null) {
+ Enumeration e = extraProperties.propertyNames();
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ iu.setProperty(name, extraProperties.getProperty(name));
+ }
+ }
+
+ return MetadataFactory.createInstallableUnit(iu);
+ }
+
+ /**
+ * Creates IUs and artifact descriptors for the JRE. The resulting IUs are added
+ * to the given set, and the resulting artifact descriptor, if any, is returned.
+ * If the jreLocation is <code>null</code>, default information is generated.
+ */
+ public static IArtifactDescriptor createJREData(File jreLocation, IPublisherResult results) {
+ InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
+ iu.setSingleton(false);
+ String id = "a.jre"; //$NON-NLS-1$
+ Version version = DEFAULT_JRE_VERSION;
+ iu.setId(id);
+ iu.setVersion(version);
+ iu.setTouchpointType(TOUCHPOINT_NATIVE);
+
+ InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
+ String configId = "config." + id;//$NON-NLS-1$
+ cu.setId(configId);
+ cu.setVersion(version);
+ cu.setHost(new RequiredCapability[] {MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, id, new VersionRange(version, true, versionMax, true), null, false, false)});
+ cu.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
+ cu.setCapabilities(new ProvidedCapability[] {createSelfCapability(configId, version)});
+ cu.setTouchpointType(TOUCHPOINT_NATIVE);
+ Map touchpointData = new HashMap();
+
+ if (jreLocation == null || !jreLocation.exists()) {
+ //set some reasonable defaults
+ iu.setVersion(version);
+ iu.setCapabilities(generateJRECapability(id, version, null));
+ results.addIU(MetadataFactory.createInstallableUnit(iu), IPublisherResult.ROOT);
+
+ touchpointData.put("install", ""); //$NON-NLS-1$ //$NON-NLS-2$
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ results.addIU(MetadataFactory.createInstallableUnit(cu), IPublisherResult.ROOT);
+ return null;
+ }
+ generateJREIUData(iu, id, version, jreLocation);
+
+ //Generate artifact for JRE
+ IArtifactKey key = new ArtifactKey(BINARY_ARTIFACT_CLASSIFIER, id, version);
+ iu.setArtifacts(new IArtifactKey[] {key});
+ results.addIU(MetadataFactory.createInstallableUnit(iu), IPublisherResult.ROOT);
+
+ //Create config info for the CU
+ String configurationData = "unzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$
+ touchpointData.put("install", configurationData); //$NON-NLS-1$
+ String unConfigurationData = "cleanupzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$
+ touchpointData.put("uninstall", unConfigurationData); //$NON-NLS-1$
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ results.addIU(MetadataFactory.createInstallableUnit(cu), IPublisherResult.ROOT);
+
+ //Create the artifact descriptor
+ return createArtifactDescriptor(key, jreLocation, false, true);
+ }
+
+ public static ArtifactKey createLauncherArtifactKey(String id, Version version) {
+ return new ArtifactKey(BINARY_ARTIFACT_CLASSIFIER, id, version);
+ }
+
+ /**
+ * Creates IUs and artifacts for the Launcher executable. The resulting IUs are added
+ * to the given set, and the resulting artifact descriptor is returned.
+ */
+ public static IArtifactDescriptor createLauncherIU(File launcher, String configurationFlavor, IPublisherResult resultantIUs) {
+ if (launcher == null || !launcher.exists())
+ return null;
+
+ //Create the IU
+ InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
+ iu.setSingleton(true);
+ String launcherId = LAUNCHER_ID_PREFIX + '_' + launcher.getName();
+ iu.setId(launcherId);
+ iu.setVersion(LAUNCHER_VERSION);
+
+ IArtifactKey key = createLauncherArtifactKey(launcherId, LAUNCHER_VERSION);
+ iu.setArtifacts(new IArtifactKey[] {key});
+ iu.setCapabilities(new ProvidedCapability[] {createSelfCapability(launcherId, LAUNCHER_VERSION)});
+ iu.setTouchpointType(TOUCHPOINT_NATIVE);
+ resultantIUs.addIU(MetadataFactory.createInstallableUnit(iu), IPublisherResult.ROOT);
+
+ //Create the CU
+ InstallableUnitFragmentDescription cu = new InstallableUnitFragmentDescription();
+ String configUnitId = configurationFlavor + launcherId;
+ cu.setId(configUnitId);
+ cu.setVersion(LAUNCHER_VERSION);
+ cu.setHost(new RequiredCapability[] {MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, launcherId, new VersionRange(LAUNCHER_VERSION, true, versionMax, true), null, false, false)});
+ cu.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
+ cu.setCapabilities(new ProvidedCapability[] {createSelfCapability(configUnitId, LAUNCHER_VERSION)});
+ cu.setTouchpointType(TOUCHPOINT_NATIVE);
+ Map touchpointData = new HashMap();
+ String configurationData = "unzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$
+ EnvironmentInfo info = (EnvironmentInfo) ServiceHelper.getService(Activator.getContext(), EnvironmentInfo.class.getName());
+ if (!info.getOS().equals(org.eclipse.osgi.service.environment.Constants.OS_WIN32)) {
+ if (info.getOS().equals(org.eclipse.osgi.service.environment.Constants.OS_MACOSX)) {
+ configurationData += " chmod(targetDir:${installFolder}/Eclipse.app/Contents/MacOS, targetFile:eclipse, permissions:755);"; //$NON-NLS-1$
+ String config = AbstractPublishingAction.createConfigSpec(null, "macosx", null);
+ generateLauncherSetter("Eclipse", launcherId, LAUNCHER_VERSION, config, resultantIUs);
+ } else
+ configurationData += " chmod(targetDir:${installFolder}, targetFile:" + launcher.getName() + ", permissions:755);"; //$NON-NLS-1$ //$NON-NLS-2$
+ } else {
+ String config = AbstractPublishingAction.createConfigSpec(null, "win32", null);
+ generateLauncherSetter("eclipse", launcherId, LAUNCHER_VERSION, config, resultantIUs);
+ }
+ touchpointData.put("install", configurationData); //$NON-NLS-1$
+ String unConfigurationData = "cleanupzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$
+ touchpointData.put("uninstall", unConfigurationData); //$NON-NLS-1$
+ cu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ resultantIUs.addIU(MetadataFactory.createInstallableUnitFragment(cu), IPublisherResult.ROOT);
+
+ //Create the artifact descriptor
+ return createArtifactDescriptor(key, launcher, false, true);
+ }
+
+ public static void generateLauncherSetter(String launcherName, String iuId, Version version, String configSpec, IPublisherResult result) {
+ InstallableUnitDescription iud = new MetadataFactory.InstallableUnitDescription();
+ String id = iuId + '.' + launcherName;
+ iud.setId(id);
+ iud.setVersion(version);
+ iud.setTouchpointType(MetadataGeneratorHelper.TOUCHPOINT_OSGI);
+ iud.setCapabilities(new ProvidedCapability[] {MetadataGeneratorHelper.createSelfCapability(id, version)});
+
+ String filter = AbstractPublishingAction.createFilterSpec(configSpec);
+ if (filter.length() > 0)
+ iud.setFilter(filter);
+ Map touchpointData = new HashMap();
+ touchpointData.put("configure", "setLauncherName(name:" + launcherName + ")");
+ touchpointData.put("unconfigure", "setLauncherName()");
+ iud.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ result.addIU(MetadataFactory.createInstallableUnit(iud), IPublisherResult.ROOT);
+ }
+
+ public static ProvidedCapability createSelfCapability(String installableUnitId, Version installableUnitVersion) {
+ return MetadataFactory.createProvidedCapability(IU_NAMESPACE, installableUnitId, installableUnitVersion);
+ }
+
+ private static String createUnconfigScript(GeneratorBundleInfo unconfigInfo, boolean isBundleFragment) {
+ if (unconfigInfo == null)
+ return ""; //$NON-NLS-1$
+ String unconfigScript = "";//$NON-NLS-1$
+ if (!isBundleFragment && unconfigInfo.getStartLevel() != BundleInfo.NO_LEVEL) {
+ unconfigScript += "setStartLevel(startLevel:" + BundleInfo.NO_LEVEL + ");"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ if (!isBundleFragment && unconfigInfo.isMarkedAsStarted()) {
+ unconfigScript += "markStarted(started: false);"; //$NON-NLS-1$
+ }
+
+ if (unconfigInfo.getSpecialUnconfigCommands() != null) {
+ unconfigScript += unconfigInfo.getSpecialUnconfigCommands();
+ }
+ return unconfigScript;
+
+ }
+
+ private static ProvidedCapability[] generateJRECapability(String installableUnitId, Version installableUnitVersion, InputStream profileStream) {
+ if (profileStream == null) {
+ //use the 1.6 profile stored in the generator bundle
+ try {
+ profileStream = Activator.getContext().getBundle().getEntry("/profiles/JavaSE-1.6.profile").openStream(); //$NON-NLS-1$
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ Properties p = new Properties();
+ try {
+ p.load(profileStream);
+ ManifestElement[] jrePackages = ManifestElement.parseHeader("org.osgi.framework.system.packages", (String) p.get("org.osgi.framework.system.packages")); //$NON-NLS-1$ //$NON-NLS-2$
+ ProvidedCapability[] exportedPackageAsCapabilities = new ProvidedCapability[jrePackages.length + 1];
+ exportedPackageAsCapabilities[0] = createSelfCapability(installableUnitId, installableUnitVersion);
+ for (int i = 1; i <= jrePackages.length; i++) {
+ exportedPackageAsCapabilities[i] = MetadataFactory.createProvidedCapability(CAPABILITY_NS_JAVA_PACKAGE, jrePackages[i - 1].getValue(), null);
+ }
+ return exportedPackageAsCapabilities;
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (BundleException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ if (profileStream != null) {
+ try {
+ profileStream.close();
+ } catch (IOException e) {
+ //ignore secondary failure
+ }
+ }
+ }
+ return new ProvidedCapability[0];
+ }
+
+ private static void generateJREIUData(InstallableUnitDescription iu, String installableUnitId, Version installableUnitVersion, File jreLocation) {
+ //Look for a JRE profile file to set version and capabilities
+ File[] profiles = jreLocation.listFiles(new FileFilter() {
+ public boolean accept(File pathname) {
+ return pathname.getAbsolutePath().endsWith(".profile"); //$NON-NLS-1$
+ }
+ });
+ if (profiles.length != 1) {
+ iu.setVersion(DEFAULT_JRE_VERSION);
+ iu.setCapabilities(generateJRECapability(installableUnitId, installableUnitVersion, null));
+ return;
+ }
+ String profileName = profiles[0].getAbsolutePath().substring(profiles[0].getAbsolutePath().lastIndexOf('/'));
+ Version version = DEFAULT_JRE_VERSION;
+ //TODO Find a better way to determine JRE version
+ if (profileName.indexOf("1.6") > 0) { //$NON-NLS-1$
+ version = new Version("1.6"); //$NON-NLS-1$
+ } else if (profileName.indexOf("1.5") > 0) { //$NON-NLS-1$
+ version = new Version("1.5"); //$NON-NLS-1$
+ } else if (profileName.indexOf("1.4") > 0) { //$NON-NLS-1$
+ version = new Version("1.4"); //$NON-NLS-1$
+ }
+ iu.setVersion(version);
+ try {
+ iu.setCapabilities(generateJRECapability(installableUnitId, installableUnitVersion, new FileInputStream(profiles[0])));
+ } catch (FileNotFoundException e) {
+ //Shouldn't happen, but ignore and fall through to use default
+ }
+ }
+
+ // moved to FeatureAction
+ public static String getFilter(FeatureEntry entry) {
+ StringBuffer result = new StringBuffer();
+ result.append("(&"); //$NON-NLS-1$
+ if (entry.getFilter() != null)
+ result.append(entry.getFilter());
+ if (entry.getOS() != null)
+ result.append("(osgi.os=" + entry.getOS() + ')');//$NON-NLS-1$
+ if (entry.getWS() != null)
+ result.append("(osgi.ws=" + entry.getWS() + ')');//$NON-NLS-1$
+ if (entry.getArch() != null)
+ result.append("(osgi.arch=" + entry.getArch() + ')');//$NON-NLS-1$
+ if (entry.getNL() != null)
+ result.append("(osgi.nl=" + entry.getNL() + ')');//$NON-NLS-1$
+ if (result.length() == 2)
+ return null;
+ result.append(')');
+ return result.toString();
+ }
+
+ // moved to FeatureAction
+ public static String getTransformedId(String original, boolean isPlugin, boolean isGroup) {
+ return (isPlugin ? original : original + (isGroup ? ".feature.group" : ".feature.jar")); //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ // moved to FeatureAction
+ public static VersionRange getVersionRange(FeatureEntry entry) {
+ String versionSpec = entry.getVersion();
+ if (versionSpec == null)
+ // TODO should really be returning VersionRange.emptyRange here...
+ return null;
+ Version version = new Version(versionSpec);
+ if (!entry.isRequires())
+ return new VersionRange(version, true, version, true);
+ String match = entry.getMatch();
+ if (match == null)
+ // TODO should really be returning VersionRange.emptyRange here...
+ return null;
+ if (match.equals("perfect")) //$NON-NLS-1$
+ return new VersionRange(version, true, version, true);
+ if (match.equals("equivalent")) { //$NON-NLS-1$
+ Version upper = new Version(version.getMajor(), version.getMinor() + 1, 0);
+ return new VersionRange(version, true, upper, false);
+ }
+ if (match.equals("compatible")) { //$NON-NLS-1$
+ Version upper = new Version(version.getMajor() + 1, 0, 0);
+ return new VersionRange(version, true, upper, false);
+ }
+ if (match.equals("greaterOrEqual")) //$NON-NLS-1$
+ return new VersionRange(version, true, new VersionRange(null).getMaximum(), true);
+ return null;
+ }
+
+ private static boolean isOptional(ImportPackageSpecification importedPackage) {
+ if (importedPackage.getDirective(Constants.RESOLUTION_DIRECTIVE).equals(ImportPackageSpecification.RESOLUTION_DYNAMIC) || importedPackage.getDirective(Constants.RESOLUTION_DIRECTIVE).equals(ImportPackageSpecification.RESOLUTION_OPTIONAL))
+ return true;
+ return false;
+ }
+
+ private static String toManifestString(Map p) {
+ if (p == null)
+ return null;
+ Collection properties = p.entrySet();
+ StringBuffer result = new StringBuffer();
+ for (Iterator iterator = properties.iterator(); iterator.hasNext();) {
+ Map.Entry aProperty = (Map.Entry) iterator.next();
+ if (aProperty.getKey().equals(BundleDescriptionFactory.BUNDLE_SHAPE))
+ continue;
+ result.append(aProperty.getKey()).append(": ").append(aProperty.getValue()).append('\n'); //$NON-NLS-1$
+ }
+ return result.toString();
+ }
+
+ // Return a map from locale to property set for the manifest localizations
+ // from the given bundle directory and given bundle localization path/name
+ // manifest property value.
+ private static Map getManifestLocalizations(Map manifest, File bundleLocation) {
+ Map localizations;
+ Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo
+ String[] bundleManifestValues = getManifestCachedValues(manifest);
+ String bundleLocalization = bundleManifestValues[BUNDLE_LOCALIZATION_INDEX];
+
+ if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$
+ bundleLocation.isFile()) {
+ localizations = getJarManifestLocalization(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues);
+ } else {
+ localizations = getDirManifestLocalization(bundleLocation, bundleLocalization, defaultLocale, bundleManifestValues);
+ }
+
+ return localizations;
+ }
+
+ public static String[] getManifestCachedValues(Map manifest) {
+ String[] cachedValues = new String[BUNDLE_LOCALIZED_PROPERTIES.length + 1];
+ for (int j = 0; j < MetadataGeneratorHelper.BUNDLE_LOCALIZED_PROPERTIES.length; j++) {
+ String value = (String) manifest.get(BUNDLE_LOCALIZED_PROPERTIES[j]);
+ if (value != null && value.length() > 1 && value.charAt(0) == '%') {
+ cachedValues[j] = value.substring(1);
+ }
+ }
+ String localizationFile = (String) manifest.get(org.osgi.framework.Constants.BUNDLE_LOCALIZATION);
+ cachedValues[BUNDLE_LOCALIZATION_INDEX] = (localizationFile != null ? localizationFile : DEFAULT_BUNDLE_LOCALIZATION);
+ return cachedValues;
+ }
+
+ // Return a map from locale to property set for the manifest localizations
+ // from the given bundle directory and given bundle localization path/name
+ // manifest property value.
+ public static Map getHostLocalizations(File bundleLocation, String[] hostBundleManifestValues) {
+ Map localizations;
+ Locale defaultLocale = null; // = Locale.ENGLISH; // TODO: get this from GeneratorInfo
+ String hostBundleLocalization = hostBundleManifestValues[BUNDLE_LOCALIZATION_INDEX];
+
+ if ("jar".equalsIgnoreCase(new Path(bundleLocation.getName()).getFileExtension()) && //$NON-NLS-1$
+ bundleLocation.isFile()) {
+ localizations = getJarManifestLocalization(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues);
+ } else {
+ localizations = getDirManifestLocalization(bundleLocation, hostBundleLocalization, defaultLocale, hostBundleManifestValues);
+ }
+
+ return localizations;
+ }
+
+ private static Map getJarManifestLocalization(File bundleLocation, String bundleLocalization, Locale defaultLocale, String[] bundleManifestValues) {
+ ZipFile jarFile = null;
+ Map localizations = new HashMap(4);
+ try {
+ jarFile = new ZipFile(bundleLocation, ZipFile.OPEN_READ);
+ for (Enumeration entries = jarFile.entries(); entries.hasMoreElements();) {
+ ZipEntry nextEntry = (ZipEntry) entries.nextElement();
+ String nextName = nextEntry.getName();
+ String localeString = getLocaleString(nextName, bundleLocalization);
+
+ if (!nextEntry.isDirectory() && localeString != null) {
+ Locale nextLocale = getLocale(localeString);
+ InputStream stream = null;
+ try {
+ stream = jarFile.getInputStream(nextEntry);
+ Properties properties = new Properties();
+ properties.load(stream);
+ Properties localizedStrings = getLocalizedProperties(bundleManifestValues, properties);
+ if (localizedStrings.size() > 0) {
+ localizations.put(nextLocale, localizedStrings);
+ if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) {
+ localizations.put(nextLocale, localizedStrings);
+ }
+ }
+ } finally {
+ if (stream != null)
+ stream.close();
+ }
+ }
+ }
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ } finally {
+ if (jarFile != null) {
+ try {
+ jarFile.close();
+ } catch (IOException ioe) {
+ // do nothing
+ }
+ }
+ }
+
+ return localizations;
+ }
+
+ private static Map getDirManifestLocalization(File bundleLocation, String bundleLocalization, Locale defaultLocale, String[] hostBundleManifestValues) {
+ File localizationPath = new File(bundleLocation, bundleLocalization);
+ File localizationDir = localizationPath.getParentFile();
+ final String localizationFile = localizationPath.getName();
+ MetadataGeneratorHelper foo = new MetadataGeneratorHelper();
+ String[] localizationFiles = localizationDir.list(foo.new LocalizationFileFilter() {
+ public boolean accept(File directory, String filename) {
+ return (getLocaleString(filename, localizationFile) != null ? true : false);
+ }
+ });
+
+ HashMap localizations = null;
+
+ if (localizationFiles != null) {
+ localizations = new HashMap(localizationFiles.length);
+ for (int i = 0; i < localizationFiles.length; i++) {
+ String nextFile = localizationFiles[i];
+ Locale nextLocale = getLocale(getLocaleString(nextFile, localizationFile));
+
+ try {
+ Properties properties = loadProperties(bundleLocation, nextFile);
+ Properties localizedStrings = getLocalizedProperties(hostBundleManifestValues, properties);
+ if (localizedStrings.size() > 0) {
+ localizations.put(nextLocale, localizedStrings);
+ if (DEFAULT_LOCALE.equals(nextLocale) && defaultLocale != null) {
+ localizations.put(nextLocale, localizedStrings);
+ }
+ }
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ }
+ }
+ }
+
+ return localizations;
+ }
+
+ private abstract class LocalizationFileFilter implements FilenameFilter {
+
+ public LocalizationFileFilter() {
+ // Nothing to do
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.FilenameFilter#accept(java.io.File, java.lang.String)
+ */
+ public abstract boolean accept(File directory, String filename);
+ }
+
+ static public String getLocaleString(String filename, String filenamePrefix) {
+ String localeString = null;
+ if (filename.startsWith(filenamePrefix) && filename.endsWith(PROPERTIES_FILE_EXTENSION)) {
+ if (filename.length() > filenamePrefix.length() + PROPERTIES_FILE_EXTENSION.length()) {
+ localeString = filename.substring(filenamePrefix.length() + 1, filename.length() - PROPERTIES_FILE_EXTENSION.length());
+ } else {
+ localeString = ""; //$NON-NLS-1$
+ }
+ }
+ return localeString;
+ }
+
+ private static Properties loadProperties(File bundleLocation, String localizationFile) throws IOException {
+ Properties result = new Properties();
+ InputStream propertyStream = null;
+ try {
+ try {
+ if (bundleLocation.isDirectory())
+ propertyStream = new FileInputStream(new File(bundleLocation, localizationFile));
+ else {
+ URLConnection connection = new URL("jar:" + bundleLocation.toURL().toExternalForm() + "!/" + localizationFile).openConnection(); //$NON-NLS-1$ //$NON-NLS-2$
+ connection.setUseCaches(false);
+ propertyStream = connection.getInputStream();
+ }
+ } catch (FileNotFoundException e) {
+ // if there is no messages file then just return;
+ return result;
+ }
+ result.load(propertyStream);
+ } finally {
+ if (propertyStream != null)
+ propertyStream.close();
+ }
+ return result;
+ }
+
+ static private Locale getLocale(String localeString) {
+ Locale locale = DEFAULT_LOCALE;
+ if (localeString.length() == 5 && localeString.indexOf('_') == 2) {
+ locale = new Locale(localeString.substring(0, 2), localeString.substring(3, 5));
+ } else if (localeString.length() == 2) {
+ locale = new Locale(localeString.substring(0, 2));
+ }
+ return locale;
+ }
+
+ static private Properties getLocalizedProperties(String[] bundleManifestKeys, Properties properties) {
+ Properties localizedProperties = new Properties();
+ for (int i = 0; i < BUNDLE_LOCALIZED_PROPERTIES.length; i++) {
+ String key = bundleManifestKeys[i];
+ if (key != null) {
+ String localizedValue = properties.getProperty(key);
+ if (localizedValue != null)
+ localizedProperties.put(key, localizedValue);
+ }
+ }
+ return localizedProperties;
+ }
+
+ public static Object[] createFeatureRootFileIU(String featureId, String featureVersion, File location, FileSetDescriptor descriptor) {
+ InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
+ iu.setSingleton(true);
+ String id = featureId + '_' + descriptor.getKey();
+ iu.setId(id);
+ Version version = new Version(featureVersion);
+ iu.setVersion(version);
+ iu.setCapabilities(new ProvidedCapability[] {createSelfCapability(id, version)});
+ iu.setTouchpointType(TOUCHPOINT_NATIVE);
+ String configSpec = descriptor.getConfigSpec();
+ if (configSpec != null)
+ iu.setFilter(AbstractPublishingAction.createFilterSpec(configSpec));
+ File[] fileResult = attachFiles(iu, descriptor, location);
+ setupLinks(iu, descriptor);
+ setupPermissions(iu, descriptor);
+
+ IInstallableUnit iuResult = MetadataFactory.createInstallableUnit(iu);
+ // need to return both the iu and any files.
+ return new Object[] {iuResult, fileResult};
+ }
+
+ // attach the described files from the given location to the given iu description. Return
+ // the list of files identified.
+ private static File[] attachFiles(InstallableUnitDescription iu, FileSetDescriptor descriptor, File location) {
+ String fileList = descriptor.getFiles();
+ String[] fileSpecs = getArrayFromString(fileList, ","); //$NON-NLS-1$
+ File[] files = new File[fileSpecs.length];
+ if (fileSpecs.length > 0) {
+ for (int i = 0; i < fileSpecs.length; i++) {
+ String spec = fileSpecs[i];
+ if (spec.startsWith("file:"))
+ spec = spec.substring(5);
+ files[i] = new File(location, spec);
+ }
+ }
+ // add touchpoint actions to unzip and cleanup as needed
+ // TODO need to support fancy root file location specs
+ Map touchpointData = new HashMap(2);
+ String configurationData = "unzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$
+ touchpointData.put("install", configurationData); //$NON-NLS-1$
+ String unConfigurationData = "cleanupzip(source:@artifact, target:${installFolder});"; //$NON-NLS-1$
+ touchpointData.put("uninstall", unConfigurationData); //$NON-NLS-1$
+ iu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+
+ // prime the IU with an artifact key that will correspond to the zipped up root files.
+ IArtifactKey key = createLauncherArtifactKey(iu.getId(), iu.getVersion());
+ iu.setArtifacts(new IArtifactKey[] {key});
+ return files;
+ }
+
+ private static void setupPermissions(InstallableUnitDescription iu, FileSetDescriptor descriptor) {
+ Map touchpointData = new HashMap();
+ String[][] permsList = descriptor.getPermissions();
+ for (int i = 0; i < permsList.length; i++) {
+ String[] permSpec = permsList[i];
+ String configurationData = " chmod(targetDir:${installFolder}, targetFile:" + permSpec[1] + ", permissions:" + permSpec[0] + ");"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ touchpointData.put("install", configurationData); //$NON-NLS-1$
+ iu.addTouchpointData(MetadataFactory.createTouchpointData(touchpointData));
+ }
+ }
+
+ private static void setupLinks(InstallableUnitDescription iu, FileSetDescriptor descriptor) {
+ // TODO setup the link support.
+ }
+
+ public static String[] getArrayFromString(String list, String separator) {
+ if (list == null || list.trim().equals("")) //$NON-NLS-1$
+ return new String[0];
+ List result = new ArrayList();
+ for (StringTokenizer tokens = new StringTokenizer(list, separator); tokens.hasMoreTokens();) {
+ String token = tokens.nextToken().trim();
+ if (!token.equals("")) //$NON-NLS-1$
+ result.add(token);
+ }
+ return (String[]) result.toArray(new String[result.size()]);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Publisher.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Publisher.java
index 8f9e5b2c5..b84d08a14 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Publisher.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Publisher.java
@@ -12,8 +12,6 @@ package org.eclipse.equinox.internal.p2.publisher;
import java.util.Collection;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.IPublisherResult;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.PublisherResult;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
public class Publisher {
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherInfo.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherInfo.java
index 33e3ee683..d08b264c2 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherInfo.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherInfo.java
@@ -9,15 +9,28 @@
******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher;
+import java.util.*;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
public class PublisherInfo implements IPublisherInfo {
- private boolean publishArtifacts = false;
- private boolean publishArtifactRepository = false;
+ private int artifactOptions = 0;
private IMetadataRepository metadataRepository;
private IArtifactRepository artifactRepository;
+ private Map adviceMap = new HashMap(11);
+
+ public IPublishingAdvice getAdvice(String id) {
+ return (IPublishingAdvice) adviceMap.get(id);
+ }
+
+ public void setAdvice(String id, IPublishingAdvice value) {
+ adviceMap.put(id, value);
+ }
+
+ public Collection getAdviceIds() {
+ return adviceMap.keySet();
+ }
public IArtifactRepository getArtifactRepository() {
return artifactRepository;
@@ -27,12 +40,8 @@ public class PublisherInfo implements IPublisherInfo {
return metadataRepository;
}
- public boolean publishArtifactRepository() {
- return publishArtifactRepository;
- }
-
- public boolean publishArtifacts() {
- return publishArtifacts;
+ public int getArtifactOptions() {
+ return artifactOptions;
}
public void setArtifactRepository(IArtifactRepository value) {
@@ -43,12 +52,8 @@ public class PublisherInfo implements IPublisherInfo {
metadataRepository = value;
}
- public void setPublishArtifactRepository(boolean value) {
- publishArtifactRepository = value;
- }
-
- public void setPublishArtifacts(boolean value) {
- publishArtifacts = value;
+ public void setArtifactOptions(int value) {
+ artifactOptions = value;
}
public String getSummary() {
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherResult.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherResult.java
new file mode 100644
index 000000000..03eba964c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherResult.java
@@ -0,0 +1,158 @@
+package org.eclipse.equinox.internal.p2.publisher;
+
+import java.util.*;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+
+public class PublisherResult implements IPublisherResult {
+ // type markers
+ public static final String ROOT = "root"; //$NON-NLS-1$
+ public static final String NON_ROOT = "non_root"; //$NON-NLS-1$
+ public static final String FRAGMENT = "fragment"; //$NON-NLS-1$
+
+ // The set of top level IUs
+ final Map rootIUs = new HashMap();
+
+ // The set of internal and leaf IUs
+ final Map nonRootIUs = new HashMap();
+
+ // Map of IU id to a set of fragments for that IU
+ final Map fragmentMap = new HashMap();
+
+ // map of os, ws, arch to ConfigData objects
+ private final Map configData = new HashMap(11);
+
+ public void addIU(IInstallableUnit iu, String type) {
+ if (type == ROOT)
+ addIU(rootIUs, iu.getId(), iu);
+ if (type == NON_ROOT)
+ addIU(nonRootIUs, iu.getId(), iu);
+ }
+
+ public void addIUs(Collection ius, String type) {
+ for (Iterator i = ius.iterator(); i.hasNext();) {
+ IInstallableUnit iu = (IInstallableUnit) i.next();
+ addIU(iu, type);
+ }
+ }
+
+ public void addFragment(String hostId, IInstallableUnit iu) {
+ addIU(fragmentMap, hostId, iu);
+ }
+
+ public Map getFragmentMap() {
+ return fragmentMap;
+ }
+
+ public Collection getFragments(String hostId) {
+ return Arrays.asList((IInstallableUnit[]) fragmentMap.get(hostId));
+ }
+
+ private void addIU(Map map, String id, IInstallableUnit iu) {
+ IInstallableUnit[] ius = (IInstallableUnit[]) map.get(id);
+ if (ius == null) {
+ ius = new IInstallableUnit[] {iu};
+ map.put(id, ius);
+ } else {
+ IInstallableUnit[] newIUs = new IInstallableUnit[ius.length + 1];
+ System.arraycopy(ius, 0, newIUs, 0, ius.length);
+ newIUs[ius.length] = iu;
+ map.put(id, newIUs);
+ }
+ }
+
+ /**
+ * Returns all IUs generated during this execution of the generator.
+ */
+ public Map getGeneratedIUs(String type) {
+ if (type == null) {
+ HashMap all = new HashMap();
+ all.putAll(rootIUs);
+ all.putAll(nonRootIUs);
+ return all;
+ }
+ if (type == ROOT)
+ return rootIUs;
+ if (type == NON_ROOT)
+ return nonRootIUs;
+ throw new IllegalArgumentException("Invalid IU type: " + type); //$NON-NLS-1$
+ }
+
+ // TODO this method really should not be needed as it just returns the first
+ // matching IU non-deterministically.
+ public IInstallableUnit getIU(String id, String type) {
+ if (type == null || type == ROOT) {
+ IInstallableUnit[] ius = (IInstallableUnit[]) rootIUs.get(id);
+ if (ius != null && ius.length > 0)
+ return ius[0];
+ }
+ if (type == null || type == NON_ROOT) {
+ IInstallableUnit[] ius = (IInstallableUnit[]) nonRootIUs.get(id);
+ if (ius != null && ius.length > 0)
+ return ius[0];
+ }
+ return null;
+ }
+
+ /**
+ * Returns the IUs in this result with the given id.
+ */
+ public Collection getIUs(String id, String type) {
+ if (type == null) {
+ ArrayList result = new ArrayList();
+ result.addAll(id == null ? flatten(rootIUs.values()) : Arrays.asList((Object[]) rootIUs.get(id)));
+ result.addAll(id == null ? flatten(nonRootIUs.values()) : Arrays.asList((Object[]) nonRootIUs.get(id)));
+ return result;
+ }
+ if (type == ROOT)
+ return id == null ? flatten(rootIUs.values()) : Arrays.asList((Object[]) rootIUs.get(id));
+ if (type == NON_ROOT)
+ return id == null ? flatten(nonRootIUs.values()) : Arrays.asList((Object[]) nonRootIUs.get(id));
+ return null;
+ }
+
+ private List flatten(Collection values) {
+ ArrayList result = new ArrayList();
+ for (Iterator i = values.iterator(); i.hasNext();) {
+ IInstallableUnit[] ius = (IInstallableUnit[]) i.next();
+ for (int j = 0; j < ius.length; j++)
+ result.add(ius[j]);
+ }
+ return result;
+ }
+
+ public Map getConfigData() {
+ return configData;
+ }
+
+ public void merge(IPublisherResult result, int mode) {
+ // merge non-conditional pieces
+ fragmentMap.putAll(result.getFragmentMap());
+ configData.putAll(result.getConfigData());
+ // mergeAdvice(result);
+
+ if (mode == MERGE_MATCHING) {
+ addIUs(result.getIUs(null, ROOT), ROOT);
+ addIUs(result.getIUs(null, NON_ROOT), NON_ROOT);
+ } else if (mode == MERGE_ALL_ROOT) {
+ addIUs(result.getIUs(null, ROOT), ROOT);
+ addIUs(result.getIUs(null, NON_ROOT), ROOT);
+ } else if (mode == MERGE_ALL_NON_ROOT) {
+ addIUs(result.getIUs(null, ROOT), NON_ROOT);
+ addIUs(result.getIUs(null, NON_ROOT), NON_ROOT);
+ }
+ }
+
+ // private void mergeAdvice(IPublisherResult result) {
+ // for (Iterator i = result.getAdviceIds().iterator(); i.hasNext();) {
+ // String id = (String) i.next();
+ // IPublishingAdvice advice = result.getAdvice(id);
+ // if (advice == null)
+ // continue;
+ // IPublishingAdvice thisAdvice = getAdvice(id);
+ // if (thisAdvice == null)
+ // adviceMap.put(id, advice);
+ // else
+ // adviceMap.put(id, thisAdvice.merge(advice));
+ // }
+ // }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/AccumulateConfigDataAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/AccumulateConfigDataAction.java
index d7be913c5..10eebc091 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/AccumulateConfigDataAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/AccumulateConfigDataAction.java
@@ -10,34 +10,147 @@
package org.eclipse.equinox.internal.p2.publisher.actions;
import java.io.File;
+import java.io.IOException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
+import org.eclipse.equinox.internal.frameworkadmin.equinox.EquinoxConstants;
+import org.eclipse.equinox.internal.frameworkadmin.equinox.EquinoxFwConfigFileParser;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.publisher.*;
+import org.eclipse.equinox.internal.provisional.frameworkadmin.*;
+import org.osgi.framework.*;
+import org.osgi.service.packageadmin.PackageAdmin;
+import org.osgi.util.tracker.ServiceTracker;
-public class AccumulateConfigDataAction extends Generator implements IPublishingAction {
+public class AccumulateConfigDataAction extends AbstractPublishingAction {
- private String config;
+ private final static String FILTER_OBJECTCLASS = "(" + Constants.OBJECTCLASS + "=" + FrameworkAdmin.class.getName() + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ private final static String filterFwName = "(" + FrameworkAdmin.SERVICE_PROP_KEY_FW_NAME + "=Equinox)"; //$NON-NLS-1$ //$NON-NLS-2$
+ //String filterFwVersion = "(" + FrameworkAdmin.SERVICE_PROP_KEY_FW_VERSION + "=" + props.getProperty("equinox.fw.version") + ")";
+ private final static String filterLauncherName = "(" + FrameworkAdmin.SERVICE_PROP_KEY_LAUNCHER_NAME + "=Eclipse.exe)"; //$NON-NLS-1$ //$NON-NLS-2$
+ //String filterLauncherVersion = "(" + FrameworkAdmin.SERVICE_PROP_KEY_LAUNCHER_VERSION + "=" + props.getProperty("equinox.launcher.version") + ")";
+ private final static String frameworkAdminFillter = "(&" + FILTER_OBJECTCLASS + filterFwName + filterLauncherName + ")"; //$NON-NLS-1$ //$NON-NLS-2$
- public AccumulateConfigDataAction(IPublisherInfo info, String config, File configurationLocation, File executableLocation) {
- super(createGeneratorInfo(info, configurationLocation, executableLocation));
- this.config = config;
- }
+ private static final String ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_MANIPULATOR = "org.eclipse.equinox.simpleconfigurator.manipulator"; //$NON-NLS-1$
+ private static final String ORG_ECLIPSE_EQUINOX_FRAMEWORKADMIN_EQUINOX = "org.eclipse.equinox.frameworkadmin.equinox"; //$NON-NLS-1$
+
+ private String configSpec;
+ private File configurationLocation;
+ private Manipulator manipulator;
+ private ServiceTracker frameworkAdminTracker;
+ private File executableLocation;
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info, File configurationLocation, File executableLocation) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- result.initializeFrameworkManipulator(configurationLocation, executableLocation);
- return result;
+ public AccumulateConfigDataAction(IPublisherInfo info, String configSpec, File configurationLocation, File executableLocation) {
+ this.configSpec = configSpec;
+ this.configurationLocation = configurationLocation;
+ this.executableLocation = executableLocation;
}
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
- storeConfigData(results, config);
+ initializeFrameworkManipulator(configurationLocation, executableLocation);
+ storeConfigData(info, configSpec, results);
return Status.OK_STATUS;
}
+ protected void storeConfigData(IPublisherInfo info, String configSpec, IPublisherResult result) {
+ if (result.getConfigData().containsKey(configSpec))
+ return; //been here, done this
+
+ File fwConfigFile = new File(configurationLocation, EquinoxConstants.CONFIG_INI);
+ if (fwConfigFile.exists()) {
+ ConfigData data = loadConfigData(fwConfigFile);
+ result.getConfigData().put(configSpec, data);
+ }
+ }
+
+ public void initializeFrameworkManipulator(File config, File executable) {
+ createFrameworkManipulator();
+
+ LauncherData launcherData = manipulator.getLauncherData();
+ launcherData.setFwPersistentDataLocation(config, true);
+ launcherData.setLauncher(executable);
+ try {
+ manipulator.load();
+ } catch (IllegalStateException e2) {
+ // TODO Auto-generated catch block
+ e2.printStackTrace();
+ } catch (FrameworkAdminRuntimeException e2) {
+ // TODO Auto-generated catch block
+ e2.printStackTrace();
+ } catch (IOException e2) {
+ // TODO Auto-generated catch block
+ e2.printStackTrace();
+ }
+ }
+
+ public ConfigData loadConfigData(File location) {
+ if (manipulator == null)
+ return null;
+
+ EquinoxFwConfigFileParser parser = new EquinoxFwConfigFileParser(Activator.getContext());
+ try {
+ parser.readFwConfig(manipulator, location);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return manipulator.getConfigData();
+ }
+
+ public LauncherData getLauncherData() {
+ return manipulator == null ? null : manipulator.getLauncherData();
+ }
+
+ /**
+ * Obtains the framework manipulator instance. Throws an exception
+ * if it could not be created.
+ */
+ protected void createFrameworkManipulator() {
+ FrameworkAdmin admin = getFrameworkAdmin();
+ if (admin == null)
+ throw new RuntimeException("Framework admin service not found"); //$NON-NLS-1$
+ manipulator = admin.getManipulator();
+ if (manipulator == null)
+ throw new RuntimeException("Framework manipulator not found"); //$NON-NLS-1$
+ }
+
+ private FrameworkAdmin getFrameworkAdmin() {
+ if (frameworkAdminTracker == null) {
+ try {
+ Filter filter = Activator.getContext().createFilter(frameworkAdminFillter);
+ frameworkAdminTracker = new ServiceTracker(Activator.getContext(), filter, null);
+ frameworkAdminTracker.open();
+ } catch (InvalidSyntaxException e) {
+ // never happens
+ }
+ }
+ FrameworkAdmin admin = (FrameworkAdmin) frameworkAdminTracker.getService();
+ if (admin == null) {
+ startBundle(ORG_ECLIPSE_EQUINOX_FRAMEWORKADMIN_EQUINOX);
+ startBundle(ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR_MANIPULATOR);
+ admin = (FrameworkAdmin) frameworkAdminTracker.getService();
+ }
+ return admin;
+ }
+
+ private boolean startBundle(String bundleId) {
+ PackageAdmin packageAdmin = (PackageAdmin) ServiceHelper.getService(Activator.getContext(), PackageAdmin.class.getName());
+ if (packageAdmin == null)
+ return false;
+
+ Bundle[] bundles = packageAdmin.getBundles(bundleId, null);
+ if (bundles != null && bundles.length > 0) {
+ for (int i = 0; i < bundles.length; i++) {
+ try {
+ if ((bundles[0].getState() & Bundle.RESOLVED) > 0) {
+ bundles[0].start();
+ return true;
+ }
+ } catch (BundleException e) {
+ // failed, try next bundle
+ }
+ }
+ }
+ return false;
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundleAdvice.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundleAdvice.java
new file mode 100644
index 000000000..ffb8ad78b
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundleAdvice.java
@@ -0,0 +1,70 @@
+package org.eclipse.equinox.internal.p2.publisher.actions;
+
+import java.util.*;
+import org.eclipse.equinox.internal.p2.publisher.IPublishingAdvice;
+
+public class BundleAdvice implements IBundleAdvice {
+
+ Map shapes = new HashMap(11);
+
+ public String getShape(String id, String version) {
+ Object[] values = (Object[]) shapes.get(id);
+ // if no one says anything then don't say anything. someone else might have an opinion
+ if (values == null)
+ return null;
+
+ // otherwise if the object is mentioned, assume its shape is DIR
+ for (int i = 0; i < values.length; i++) {
+ if (values[i].equals(version))
+ return IBundleAdvice.DIR;
+ }
+ // if no one says anything then don't say anything. someone else might have an opinion
+ return null;
+ }
+
+ public void setShape(String id, String version, String shape) {
+ Object[] values = (Object[]) shapes.get(id);
+ if (values == null) {
+ values = new Object[] {version};
+ shapes.put(id, values);
+ } else {
+ Object[] newObjects = new Object[values.length + 1];
+ System.arraycopy(values, 0, newObjects, 0, values.length);
+ newObjects[values.length] = version;
+ shapes.put(id, newObjects);
+ }
+ }
+
+ public IPublishingAdvice merge(IPublishingAdvice advice) {
+ if (!(advice instanceof BundleAdvice))
+ return this;
+ BundleAdvice source = (BundleAdvice) advice;
+ for (Iterator i = source.shapes.keySet().iterator(); i.hasNext();) {
+ String id = (String) i.next();
+ Object[] myValues = (Object[]) shapes.get(id);
+ Object[] sourceValues = (Object[]) source.shapes.get(id);
+ if (myValues == null)
+ shapes.put(id, sourceValues);
+ else if (sourceValues != null)
+ shapes.put(id, merge(myValues, sourceValues));
+ }
+ return this;
+ }
+
+ private Object[] merge(Object[] myValues, Object[] sourceValues) {
+ List result = Arrays.asList(myValues);
+ for (int i = 0; i < sourceValues.length; i++) {
+ Object object = sourceValues[i];
+ boolean found = false;
+ for (Iterator j = result.iterator(); j.hasNext();) {
+ if (j.next().equals(object)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ result.add(object);
+ }
+ return (Object[]) result.toArray(new Object[result.size()]);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundlesAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundlesAction.java
index 43b3e20f5..d045b45d9 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundlesAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundlesAction.java
@@ -10,39 +10,40 @@
package org.eclipse.equinox.internal.p2.publisher.actions;
import java.io.File;
-import java.util.ArrayList;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
-import org.eclipse.osgi.service.resolver.BundleDescription;
+import java.io.IOException;
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.p2.publisher.*;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+import org.eclipse.osgi.service.resolver.*;
/**
* Publish IUs for all of the bundles in the given set of locations. The locations can
* be actual locations of the bundles or folders of bundles.
*/
-public class BundlesAction extends Generator implements IPublishingAction {
+public class BundlesAction extends AbstractPublishingAction {
+
+ protected static final String ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR = "org.eclipse.equinox.simpleconfigurator"; //$NON-NLS-1$
+ protected static final String ORG_ECLIPSE_UPDATE_CONFIGURATOR = "org.eclipse.update.configurator"; //$NON-NLS-1$
private File[] locations;
+ private StateObjectFactory stateObjectFactory;
- public BundlesAction(File[] locations, IPublisherInfo info) {
- super(createGeneratorInfo(info));
+ public BundlesAction(File[] locations) {
this.locations = expandLocations(locations);
- }
-
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- return result;
+ // TODO need to figure a better way of configuring the generator...
+ PlatformAdmin platformAdmin = (PlatformAdmin) ServiceHelper.getService(Activator.getContext(), PlatformAdmin.class.getName());
+ if (platformAdmin != null)
+ stateObjectFactory = platformAdmin.getFactory();
}
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
BundleDescription[] bundles = getBundleDescriptions(locations);
- generateBundleIUs(bundles, results, info.getArtifactRepository());
+ generateBundleIUs(bundles, results, info);
return Status.OK_STATUS;
}
@@ -63,4 +64,128 @@ public class BundlesAction extends Generator implements IPublishingAction {
return (File[]) result.toArray(new File[result.size()]);
}
+ protected void generateBundleIUs(BundleDescription[] bundles, IPublisherResult result, IPublisherInfo info) {
+ // Computing the path for localized property files in a NL fragment bundle
+ // requires the BUNDLE_LOCALIZATION property from the manifest of the host bundle,
+ // so a first pass is done over all the bundles to cache this value as well as the tags
+ // from the manifest for the localizable properties.
+ final int CACHE_PHASE = 0;
+ final int GENERATE_PHASE = 1;
+ final int BUNDLE_LOCALIZATION_INDEX = MetadataGeneratorHelper.BUNDLE_LOCALIZATION_INDEX;
+ Map bundleLocalizationMap = new HashMap(bundles.length);
+ Set localizationIUs = new HashSet(32);
+ for (int phase = CACHE_PHASE; phase <= GENERATE_PHASE; phase++) {
+ for (int i = 0; i < bundles.length; i++) {
+ BundleDescription bd = bundles[i];
+ // A bundle may be null if the associated plug-in does not have a manifest file -
+ // for example, org.eclipse.jdt.launching.j9
+ if (bd != null && bd.getSymbolicName() != null && bd.getVersion() != null) {
+ Map bundleManifest = (Map) bd.getUserObject();
+
+ if (phase == CACHE_PHASE) {
+ if (bundleManifest != null) {
+ String[] cachedValues = MetadataGeneratorHelper.getManifestCachedValues(bundleManifest);
+ bundleLocalizationMap.put(makeSimpleKey(bd), cachedValues);
+ }
+ } else {
+ IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(bd.getSymbolicName(), bd.getVersion().toString());
+ IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(key, new File(bd.getLocation()), true, false);
+ IArtifactRepository destination = info.getArtifactRepository();
+ // don't consider any advice here as we want to know about the real form on disk
+ if (isDir(bd, null))
+ publishArtifact(ad, new File(bd.getLocation()), new File(bd.getLocation()).listFiles(), info, INCLUDE_ROOT);
+ else
+ publishArtifact(ad, new File(bd.getLocation()), new File[] {new File(bd.getLocation())}, info, AS_IS | INCLUDE_ROOT);
+
+ boolean isDir = isDir(bd, (IBundleAdvice) info.getAdvice(IBundleAdvice.ID));
+ IInstallableUnit bundleIU = MetadataGeneratorHelper.createBundleIU(bd, bundleManifest, isDir, key, localizationIUs);
+
+ if (isFragment(bd)) {
+ // TODO: Can NL fragments be multi-host? What special handling
+ // is required for multi-host fragments in general?
+ String hostId = bd.getHost().getName();
+ String hostKey = makeSimpleKey(hostId);
+ String[] cachedValues = (String[]) bundleLocalizationMap.get(hostKey);
+
+ if (cachedValues != null) {
+ MetadataGeneratorHelper.createHostLocalizationFragments(bd, hostId, cachedValues, localizationIUs);
+ }
+ }
+
+ result.addIU(bundleIU, IPublisherResult.ROOT);
+ result.addIUs(localizationIUs, IPublisherResult.NON_ROOT);
+ localizationIUs.clear();
+ }
+ }
+ }
+ }
+ }
+
+ private boolean isDir(BundleDescription bundle, IBundleAdvice advice) {
+ // if the advice has a shape, use it
+ if (advice != null) {
+ String shape = advice.getShape(bundle.getSymbolicName(), bundle.getVersion().toString());
+ if (shape != null)
+ return shape.equals(IBundleAdvice.DIR);
+ }
+ // otherwise go with whatever we figured out from the manifest or the shape on disk
+ Map manifest = (Map) bundle.getUserObject();
+ String format = (String) manifest.get(BundleDescriptionFactory.BUNDLE_SHAPE);
+ return BundleDescriptionFactory.DIR.equals(format);
+ }
+
+ private String makeSimpleKey(BundleDescription bd) {
+ // TODO: can't use the bundle version in the key for the BundleLocalization
+ // property map since the host specification for a fragment has a
+ // version range, not a version. Hence, this mechanism for finding
+ // manifest localization property files may break under changes
+ // to the BundleLocalization property of a bundle.
+ return makeSimpleKey(bd.getSymbolicName() /*, bd.getVersion() */);
+ }
+
+ private String makeSimpleKey(String id /*, Version version */) {
+ return id; // + '_' + version.toString();
+ }
+
+ private boolean isFragment(BundleDescription bd) {
+ return (bd.getHost() != null ? true : false);
+ }
+
+ protected BundleDescription[] getBundleDescriptions(File[] bundleLocations) {
+ if (bundleLocations == null)
+ return new BundleDescription[0];
+ boolean addSimpleConfigurator = false;
+ boolean scIn = false;
+ for (int i = 0; i < bundleLocations.length; i++) {
+ if (!addSimpleConfigurator)
+ addSimpleConfigurator = bundleLocations[i].toString().indexOf(ORG_ECLIPSE_UPDATE_CONFIGURATOR) > 0;
+ if (!scIn) {
+ scIn = bundleLocations[i].toString().indexOf(ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR) > 0;
+ if (scIn)
+ break;
+ }
+ }
+ if (scIn)
+ addSimpleConfigurator = false;
+ BundleDescription[] result = new BundleDescription[bundleLocations.length + (addSimpleConfigurator ? 1 : 0)];
+ BundleDescriptionFactory factory = getBundleFactory();
+ for (int i = 0; i < bundleLocations.length; i++) {
+ result[i] = factory.getBundleDescription(bundleLocations[i]);
+ }
+ if (addSimpleConfigurator) {
+ //Add simple configurator to the list of bundles
+ try {
+ File location = new File(FileLocator.toFileURL(Activator.getContext().getBundle().getEntry(ORG_ECLIPSE_EQUINOX_SIMPLECONFIGURATOR + ".jar")).getFile()); //$NON-NLS-1$
+ result[result.length - 1] = factory.getBundleDescription(location);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return result;
+ }
+
+ protected BundleDescriptionFactory getBundleFactory() {
+ return new BundleDescriptionFactory(stateObjectFactory, null);
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/ConfigCUsAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/ConfigCUsAction.java
index 9129bbc24..e156a45ea 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/ConfigCUsAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/ConfigCUsAction.java
@@ -13,24 +13,25 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.*;
+import java.util.Map.Entry;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
+import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.provisional.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.provisional.frameworkadmin.ConfigData;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.osgi.util.ManifestElement;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.Constants;
+import org.osgi.framework.*;
/**
* Publish CUs for all the configuration data in the current result.
* This adds config-specific CUs to capture start levels etc found in the config.ini
* etc for is os, ws, arch combination seen so far.
*/
-public class ConfigCUsAction extends Generator implements IPublishingAction {
+public class ConfigCUsAction extends AbstractPublishingAction {
+
+ protected static final String ORG_ECLIPSE_UPDATE_CONFIGURATOR = "org.eclipse.update.configurator"; //$NON-NLS-1$
public static final int NO_INI = 0;
public static final int CONFIG_INI = 1;
@@ -41,33 +42,22 @@ public class ConfigCUsAction extends Generator implements IPublishingAction {
int mode;
public ConfigCUsAction(IPublisherInfo info, String flavor, String id, String version, int mode) {
- super(createGeneratorInfo(info, flavor));
this.flavor = flavor;
this.mode = mode;
this.id = id;
this.version = version;
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info, String flavor) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- result.setFlavor(flavor);
- return result;
- }
-
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
// generation from remembered config.ini's
// we have N platforms, generate a CU for each
// TODO try and find common properties across platforms
for (Iterator iterator = results.getConfigData().keySet().iterator(); iterator.hasNext();) {
- String configuration = (String) iterator.next();
- ConfigData data = (ConfigData) results.getConfigData().get(configuration);
+ String configSpec = (String) iterator.next();
+ ConfigData data = (ConfigData) results.getConfigData().get(configSpec);
BundleInfo[] bundles = fillInBundles(data.getBundles(), results);
- generateBundleConfigIUs(bundles, results, configuration);
- publishIniIUs(data, results, configuration);
+ generateBundleConfigIUs(info, bundles, configSpec, results);
+ publishIniIUs(data, results, configSpec);
}
return Status.OK_STATUS;
}
@@ -138,4 +128,119 @@ public class ConfigCUsAction extends Generator implements IPublishingAction {
IInstallableUnit cu = MetadataGeneratorHelper.createIUFragment(id, version, flavor, configuration, touchpointData);
results.addIU(cu, IPublisherResult.ROOT);
}
+
+ protected String[] getConfigurationStrings(ConfigData configData) {
+ String configurationData = ""; //$NON-NLS-1$
+ String unconfigurationData = ""; //$NON-NLS-1$
+ for (Iterator iterator = configData.getFwDependentProps().entrySet().iterator(); iterator.hasNext();) {
+ Entry aProperty = (Entry) iterator.next();
+ String key = ((String) aProperty.getKey());
+ if (key.equals("osgi.frameworkClassPath") || key.equals("osgi.framework") || key.equals("osgi.bundles") || key.equals("eof")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ continue;
+ configurationData += "setProgramProperty(propName:" + key + ", propValue:" + ((String) aProperty.getValue()) + ");"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ unconfigurationData += "setProgramProperty(propName:" + key + ", propValue:);"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ for (Iterator iterator = configData.getFwIndependentProps().entrySet().iterator(); iterator.hasNext();) {
+ Entry aProperty = (Entry) iterator.next();
+ String key = ((String) aProperty.getKey());
+ if (key.equals("osgi.frameworkClassPath") || key.equals("osgi.framework") || key.equals("osgi.bundles") || key.equals("eof")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+ continue;
+ configurationData += "setProgramProperty(propName:" + key + ", propValue:" + ((String) aProperty.getValue()) + ");"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ unconfigurationData += "setProgramProperty(propName:" + key + ", propValue:);"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ return new String[] {configurationData, unconfigurationData};
+ }
+
+ protected String[] getLauncherConfigStrings(final String[] jvmArgs, final String[] programArgs) {
+ String configurationData = ""; //$NON-NLS-1$
+ String unconfigurationData = ""; //$NON-NLS-1$
+
+ for (int i = 0; i < jvmArgs.length; i++) {
+ configurationData += "addJvmArg(jvmArg:" + jvmArgs[i] + ");"; //$NON-NLS-1$ //$NON-NLS-2$
+ unconfigurationData += "removeJvmArg(jvmArg:" + jvmArgs[i] + ");"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ for (int i = 0; i < programArgs.length; i++) {
+ String programArg = programArgs[i];
+ if (programArg.equals("--launcher.library") || programArg.equals("-startup") || programArg.equals("-configuration")) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ i++;
+ configurationData += "addProgramArg(programArg:" + programArg + ");"; //$NON-NLS-1$ //$NON-NLS-2$
+ unconfigurationData += "removeProgramArg(programArg:" + programArg + ");"; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return new String[] {configurationData, unconfigurationData};
+ }
+
+ protected void generateBundleConfigIUs(IPublisherInfo info, BundleInfo[] bundles, String configSpec, IPublisherResult result) {
+ if (bundles == null)
+ return;
+
+ String cuIdPrefix = ""; //$NON-NLS-1$
+ String filter = null;
+ if (configSpec != null) {
+ cuIdPrefix = createIdString(configSpec);
+ filter = createFilterSpec(configSpec);
+ }
+
+ for (int i = 0; i < bundles.length; i++) {
+ GeneratorBundleInfo bundle = createGeneratorBundleInfo(bundles[i], result);
+ if (bundle == null)
+ continue;
+
+ if (bundle.getSymbolicName().equals(ORG_ECLIPSE_UPDATE_CONFIGURATOR)) {
+ bundle.setStartLevel(BundleInfo.NO_LEVEL);
+ bundle.setMarkedAsStarted(false);
+ bundle.setSpecialConfigCommands("setProgramProperty(propName:org.eclipse.update.reconcile, propValue:false);"); //$NON-NLS-1$
+ bundle.setSpecialUnconfigCommands("setProgramProperty(propName:org.eclipse.update.reconcile, propValue:);"); //$NON-NLS-1$
+ } else if (bundle.getStartLevel() == BundleInfo.NO_LEVEL && !bundle.isMarkedAsStarted()) {
+ // this bundle does not require any particular configuration, the plug-in default IU will handle installing it
+ continue;
+ }
+
+ IInstallableUnit cu = MetadataGeneratorHelper.createBundleConfigurationUnit(bundle.getSymbolicName(), new Version(bundle.getVersion()), false, bundle, flavor + cuIdPrefix, filter);
+ if (cu != null) {
+ // Product Query will run against the repo, make sure these CUs are in before then
+ IMetadataRepository metadataRepository = info.getMetadataRepository();
+ if (metadataRepository != null) {
+ metadataRepository.addInstallableUnits(new IInstallableUnit[] {cu});
+ }
+ result.addIU(cu, IPublisherResult.ROOT);
+ // String key = (product != null && product.useFeatures()) ? IPublisherResult.CONFIGURATION_CUS : bundle.getSymbolicName();
+ String key = bundle.getSymbolicName();
+ result.addFragment(key, cu);
+ }
+ }
+ }
+
+ protected GeneratorBundleInfo createGeneratorBundleInfo(BundleInfo bundleInfo, IPublisherResult result) {
+ if (bundleInfo.getLocation() != null)
+ return new GeneratorBundleInfo(bundleInfo);
+
+ String name = bundleInfo.getSymbolicName();
+
+ //easy case: do we have a matching IU?
+ IInstallableUnit iu = result.getIU(name, null);
+ if (iu != null) {
+ bundleInfo.setVersion(iu.getVersion().toString());
+ return new GeneratorBundleInfo(bundleInfo);
+ }
+
+ //harder: try id_version
+ int i = name.indexOf('_');
+ while (i > -1) {
+ Version version = null;
+ try {
+ version = new Version(name.substring(i));
+ bundleInfo.setSymbolicName(name.substring(0, i));
+ bundleInfo.setVersion(version.toString());
+ return new GeneratorBundleInfo(bundleInfo);
+ } catch (IllegalArgumentException e) {
+ // the '_' found was probably part of the symbolic id
+ i = name.indexOf('_', i);
+ }
+ }
+
+ return null;
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/DefaultCUsAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/DefaultCUsAction.java
index 6e92bf399..bd93e6618 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/DefaultCUsAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/DefaultCUsAction.java
@@ -11,27 +11,17 @@ package org.eclipse.equinox.internal.p2.publisher.actions;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
+import org.eclipse.equinox.internal.p2.publisher.*;
/**
* Publish IUs that install/configure the standard things like bundles, features and source bundles
*/
-public class DefaultCUsAction extends Generator implements IPublishingAction {
+public class DefaultCUsAction extends AbstractPublishingAction {
- public DefaultCUsAction(IPublisherInfo info, String flavor) {
- super(createGeneratorInfo(info, flavor));
- }
+ private String flavor;
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info, String flavor) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- result.setFlavor(flavor);
- return result;
+ public DefaultCUsAction(IPublisherInfo info, String flavor) {
+ this.flavor = flavor;
}
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
@@ -39,4 +29,34 @@ public class DefaultCUsAction extends Generator implements IPublishingAction {
return Status.OK_STATUS;
}
+ protected void generateDefaultConfigIU(IPublisherResult result) {
+ // TODO this is a bit of a hack. We need to have the default IU fragment generated with code that configures
+ // and unconfigures. The Generator should be decoupled from any particular provider but it is not clear
+ // that we should add the create* methods to IGeneratorInfo...
+ // MockBundleDescription bd1 = new MockBundleDescription("defaultConfigure");
+ // MockBundleDescription bd2 = new MockBundleDescription("defaultUnconfigure");
+ result.addIU(MetadataGeneratorHelper.createDefaultBundleConfigurationUnit(createDefaultConfigurationBundleInfo(), createDefaultUnconfigurationBundleInfo(), flavor), IPublisherResult.ROOT);
+ result.addIU(MetadataGeneratorHelper.createDefaultFeatureConfigurationUnit(flavor), IPublisherResult.ROOT);
+ result.addIU(MetadataGeneratorHelper.createDefaultConfigurationUnitForSourceBundles(flavor), IPublisherResult.ROOT);
+ }
+
+ protected GeneratorBundleInfo createDefaultConfigurationBundleInfo() {
+ GeneratorBundleInfo result = new GeneratorBundleInfo();
+ result.setSymbolicName("defaultConfigure"); //$NON-NLS-1$
+ result.setVersion("1.0.0"); //$NON-NLS-1$
+ result.setStartLevel(4);
+ // These should just be in the install section now
+ // result.setSpecialConfigCommands("installBundle(bundle:${artifact});");
+ return result;
+ }
+
+ protected GeneratorBundleInfo createDefaultUnconfigurationBundleInfo() {
+ GeneratorBundleInfo result = new GeneratorBundleInfo();
+ result.setSymbolicName("defaultUnconfigure"); //$NON-NLS-1$
+ result.setVersion("1.0.0"); //$NON-NLS-1$
+ // These should just be in the uninstall section now
+ // result.setSpecialConfigCommands("uninstallBundle(bundle:${artifact});");
+ return result;
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EclipseInstallAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EclipseInstallAction.java
index 8cae7624b..60fbc948e 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EclipseInstallAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EclipseInstallAction.java
@@ -13,26 +13,24 @@ import java.io.File;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.Generator;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.IPublisherResult;
+import org.eclipse.equinox.internal.p2.publisher.*;
public class EclipseInstallAction implements IPublishingAction {
-
+ protected String source;
protected String id;
protected String version = "1.0.0"; //$NON-NLS-1$
+ protected String name;
protected String flavor;
protected String[] topLevel;
protected IPublisherInfo info;
protected String[] configurations;
- protected String source;
protected String[] nonRootFiles;
- public EclipseInstallAction(String source, String id, String version, String flavor, String[] topLevel, String[] configurations, String[] nonRootFiles) {
+ public EclipseInstallAction(String source, String id, String version, String name, String flavor, String[] topLevel, String[] configurations, String[] nonRootFiles) {
this.source = source;
this.id = id;
this.version = version;
+ this.name = name == null ? id : name;
this.flavor = flavor;
this.topLevel = topLevel;
this.configurations = configurations;
@@ -50,7 +48,7 @@ public class EclipseInstallAction implements IPublishingAction {
protected IPublishingAction[] createActions() {
ArrayList result = new ArrayList();
// create an action that just publishes the raw bundles and features
- IPublishingAction action = new MergeResultsAction(new IPublishingAction[] {createBundlesAction(), createFeaturesAction()}, IPublisherResult.MERGE_ALL_NON_ROOT);
+ IPublishingAction action = new MergeResultsAction(new IPublishingAction[] {createFeaturesAction(), createBundlesAction()}, IPublisherResult.MERGE_ALL_NON_ROOT);
result.add(action);
result.addAll(createEquinoxExecutableActions(configurations));
result.addAll(createRootFilesActions(configurations));
@@ -68,7 +66,7 @@ public class EclipseInstallAction implements IPublishingAction {
}
protected IPublishingAction createRootIUAction() {
- return new RootIUAction(id, version, topLevel, info);
+ return new RootIUAction(id, version, name, topLevel, info);
}
protected IPublishingAction createJREAction() {
@@ -84,8 +82,7 @@ public class EclipseInstallAction implements IPublishingAction {
Collection result = new ArrayList(configs.length);
for (int i = 0; i < configs.length; i++) {
File configuration = computeConfigurationLocation(configs[i]);
- File[] executables = computeExecutables(configs[i]);
- File executable = executables[0];
+ File executable = computeExecutables(configs[i])[0];
IPublishingAction action = new AccumulateConfigDataAction(info, configs[i], configuration, executable);
result.add(action);
}
@@ -137,7 +134,7 @@ public class EclipseInstallAction implements IPublishingAction {
}
protected File[] computeExecutables(String configSpec) {
- String os = Generator.parseConfigSpec(configSpec)[1];
+ String os = AbstractPublishingAction.parseConfigSpec(configSpec)[1];
return EquinoxExecutableAction.findExecutables(computeExecutableLocation(configSpec), os, "eclipse");
}
@@ -154,7 +151,7 @@ public class EclipseInstallAction implements IPublishingAction {
}
protected IPublishingAction createBundlesAction() {
- return new BundlesAction(new File[] {new File(source, "plugins")}, info); //$NON-NLS-1$
+ return new BundlesAction(new File[] {new File(source, "plugins")}); //$NON-NLS-1$
}
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxExecutableAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxExecutableAction.java
index 52d32d2e3..13cf90e0b 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxExecutableAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxExecutableAction.java
@@ -13,18 +13,16 @@ import java.io.File;
import java.io.FilenameFilter;
import java.util.*;
import org.eclipse.core.runtime.*;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
+import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
import org.eclipse.equinox.internal.provisional.p2.metadata.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
import org.eclipse.osgi.service.environment.Constants;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.osgi.framework.Version;
-public class EquinoxExecutableAction extends Generator implements IPublishingAction {
+public class EquinoxExecutableAction extends AbstractPublishingAction {
private String configSpec;
private String idBase;
@@ -45,7 +43,7 @@ public class EquinoxExecutableAction extends Generator implements IPublishingAct
if (!Constants.OS_WIN32.equals(os) && !Constants.OS_MACOSX.equals(os)) {
ArrayList result = new ArrayList();
File[] files = root.listFiles();
- for (int i = 0; i < files.length; i++) {
+ for (int i = 0; files != null && i < files.length; i++) {
String extension = new Path(files[i].getName()).getFileExtension();
if (files[i].isFile() && (extension == null || extension.equals("so")))
result.add(files[i]);
@@ -64,7 +62,6 @@ public class EquinoxExecutableAction extends Generator implements IPublishingAct
}
public EquinoxExecutableAction(IPublisherInfo info, File[] executables, String configSpec, String idBase, String version, String flavor) {
- super(createGeneratorInfo(info, flavor));
this.executables = executables;
this.configSpec = configSpec;
this.idBase = idBase == null ? "org.eclipse" : idBase; //$NON-NLS-1$
@@ -74,16 +71,6 @@ public class EquinoxExecutableAction extends Generator implements IPublishingAct
this.flavor = flavor;
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info, String flavor) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- result.setFlavor(flavor);
- return result;
- }
-
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
generateExecutableIUs(info, results);
return Status.OK_STATUS;
@@ -115,7 +102,7 @@ public class EquinoxExecutableAction extends Generator implements IPublishingAct
String ws = config[0];
String os = config[1];
String arch = config[2];
- String launcherFragment = ORG_ECLIPSE_EQUINOX_LAUNCHER + '.' + ws + '.' + os;
+ String launcherFragment = EquinoxLauncherCUAction.ORG_ECLIPSE_EQUINOX_LAUNCHER + '.' + ws + '.' + os;
if (!Constants.OS_MACOSX.equals(os))
launcherFragment += '.' + arch;
iu.setRequiredCapabilities(new RequiredCapability[] {MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, launcherFragment, VersionRange.emptyRange, filter, false, false)});
@@ -170,7 +157,7 @@ public class EquinoxExecutableAction extends Generator implements IPublishingAct
//Create the artifact descriptor. we have several files so no path on disk
IArtifactDescriptor descriptor = MetadataGeneratorHelper.createArtifactDescriptor(key, null, false, true);
- publishArtifact(descriptor, executables, info.getArtifactRepository(), false, true);
+ publishArtifact(descriptor, null, executables, info, INCLUDE_ROOT);
}
private void mungeLauncherFileNames(File[] files) {
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxLauncherCUAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxLauncherCUAction.java
index 3946bc8d5..8d117fa8e 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxLauncherCUAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxLauncherCUAction.java
@@ -11,19 +11,16 @@ package org.eclipse.equinox.internal.p2.publisher.actions;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
+import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.GeneratorBundleInfo;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.IPublisherResult;
/**
* Create fragments for all Equinox launcher IUs (not fragments) such that the corresponding
* host IU is configured as the launch.library.
*/
-public class EquinoxLauncherCUAction extends FragmentIUsAction implements IPublishingAction {
+public class EquinoxLauncherCUAction extends FragmentIUsAction {
- private static final String ORG_ECLIPSE_EQUINOX_LAUNCHER = "org.eclipse.equinox.launcher"; //$NON-NLS-1$
+ public static final String ORG_ECLIPSE_EQUINOX_LAUNCHER = "org.eclipse.equinox.launcher"; //$NON-NLS-1$
public EquinoxLauncherCUAction(IPublisherInfo info, GeneratorBundleInfo[] bundles, String flavor) {
super(info, null, flavor);
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FeaturesAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FeaturesAction.java
index 052b74170..7a030c126 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FeaturesAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FeaturesAction.java
@@ -16,38 +16,35 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.publisher.*;
-import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
-import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
-import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
+import org.eclipse.equinox.internal.p2.publisher.features.*;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.ArtifactDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
+import org.eclipse.equinox.internal.provisional.p2.metadata.*;
+import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
+import org.eclipse.osgi.service.resolver.VersionRange;
+import org.osgi.framework.Version;
/**
* Publish IUs for all of the features in the given set of locations. The locations can
* be actual locations of the features or folders of features.
*/
-public class FeaturesAction extends Generator implements IPublishingAction {
+public class FeaturesAction extends AbstractPublishingAction {
+
+ public static final String INSTALL_FEATURES_FILTER = "(org.eclipse.update.install.features=true)"; //$NON-NLS-1$
private File[] locations;
- IPublisherInfo info;
- public FeaturesAction(File[] locations, IPublisherInfo info) {
- super(createGeneratorInfo(info));
- this.locations = expandLocations(locations);
- this.info = info;
+ public static String getTransformedId(String original, boolean isPlugin, boolean isGroup) {
+ return (isPlugin ? original : original + (isGroup ? ".feature.group" : ".feature.jar")); //$NON-NLS-1$//$NON-NLS-2$
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- return result;
+ public FeaturesAction(File[] locations, IPublisherInfo info) {
+ this.locations = expandLocations(locations);
}
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
Feature[] features = getFeatures(locations);
- generateFeatureIUs(features, results, info.getArtifactRepository());
+ generateFeatureIUs(features, results, info);
return Status.OK_STATUS;
}
@@ -68,14 +65,14 @@ public class FeaturesAction extends Generator implements IPublishingAction {
return (File[]) result.toArray(new File[result.size()]);
}
- protected void generateFeatureIUs(Feature[] features, IPublisherResult result, IArtifactRepository destination) {
- //Build Feature IUs, and add them to any corresponding categories
+ protected void generateFeatureIUs(Feature[] features, IPublisherResult result, IPublisherInfo info) {
+ // Build Feature IUs, and add them to any corresponding categories
for (int i = 0; i < features.length; i++) {
Feature feature = features[i];
// generate the root file IUs for this feature. The IU hierarchy must
// be built from the bottom up so do the root files first.
- ArrayList childIUs = generateFeatureRootIUs(feature, result, destination);
+ ArrayList childIUs = generateRootFileIUs(feature, result, info);
// create the basic feature IU with all the children
String location = feature.getLocation();
@@ -87,21 +84,38 @@ public class FeaturesAction extends Generator implements IPublishingAction {
for (int arti = 0; arti < artifacts.length; arti++) {
IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(artifacts[arti], new File(location), true, false);
if (isExploded)
- publishArtifact(ad, new File(location).listFiles(), destination, false, true);
+ publishArtifact(ad, new File(location).listFiles(), info, INCLUDE_ROOT);
else
- publishArtifact(ad, new File[] {new File(location)}, destination, true, true);
+ publishArtifact(ad, new File[] {new File(location)}, info, AS_IS | INCLUDE_ROOT);
}
+ gatherAdvice(feature, info);
+
// create the associated group and register the feature and group in the result.
- IInstallableUnit generated = MetadataGeneratorHelper.createGroupIU(feature, featureIU);
+ IInstallableUnit generated = createGroupIU(feature, featureIU, null);
result.addIU(generated, IPublisherResult.ROOT);
result.addIU(featureIU, IPublisherResult.ROOT);
}
}
- private ArrayList generateFeatureRootIUs(Feature feature, IPublisherResult result, IArtifactRepository destination) {
- ArrayList ius = new ArrayList();
+ private ArrayList generateRootFileIUs(Feature feature, IPublisherResult result, IPublisherInfo info) {
File location = new File(feature.getLocation());
+ Properties props = loadProperties(location, "build.properties");
+ return generateRootFileIUs(feature.getId(), feature.getVersion(), props, location, result, info);
+ }
+
+ private ArrayList generateRootFileIUs(String featureId, String featureVersion, Properties props, File location, IPublisherResult result, IPublisherInfo info) {
+ ArrayList ius = new ArrayList();
+ FileSetDescriptor[] rootFileDescriptors = getRootFileDescriptors(props);
+ for (int i = 0; i < rootFileDescriptors.length; i++) {
+ IInstallableUnit iu = generateRootFileIU(featureId, featureVersion, location, rootFileDescriptors[i], result, info);
+ ius.add(iu);
+ }
+ return ius;
+ }
+
+ private Properties loadProperties(File location, String file) {
+ Properties props = new Properties();
File tempFile = null;
try {
// if the feature is a dir then just return the location
@@ -111,11 +125,10 @@ public class FeaturesAction extends Generator implements IPublishingAction {
FileUtils.unzipFile(location, tempFile);
location = tempFile;
}
- Properties props = new Properties();
try {
InputStream in = null;
try {
- in = new BufferedInputStream(new FileInputStream(new File(location, "build.properties"))); //$NON-NLS-1$
+ in = new BufferedInputStream(new FileInputStream(new File(location, file))); //$NON-NLS-1$
props.load(in);
} finally {
if (in != null)
@@ -124,13 +137,7 @@ public class FeaturesAction extends Generator implements IPublishingAction {
} catch (FileNotFoundException e) {
// ignore if it is just a file not found.
} catch (IOException e) {
- LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error parsing feature build.properties", e)); //$NON-NLS-1$
- }
-
- FileSetDescriptor[] rootFileDescriptors = getRootFileDescriptors(props);
- for (int i = 0; i < rootFileDescriptors.length; i++) {
- IInstallableUnit iu = generateFeatureRootFileIU(feature, location, rootFileDescriptors[i], result, destination);
- ius.add(iu);
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error parsing " + file, e)); //$NON-NLS-1$
}
} catch (IOException e) {
LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error publishing artifacts", e)); //$NON-NLS-1$
@@ -138,17 +145,17 @@ public class FeaturesAction extends Generator implements IPublishingAction {
if (tempFile != null)
tempFile.delete();
}
- return ius;
+ return props;
}
- private IInstallableUnit generateFeatureRootFileIU(Feature feature, File location, FileSetDescriptor rootFile, IPublisherResult result, IArtifactRepository destination) {
- Object[] iuAndFiles = MetadataGeneratorHelper.createFeatureRootFileIU(feature, location, rootFile);
+ private IInstallableUnit generateRootFileIU(String featureId, String featureVersion, File location, FileSetDescriptor rootFile, IPublisherResult result, IPublisherInfo info) {
+ Object[] iuAndFiles = MetadataGeneratorHelper.createFeatureRootFileIU(featureId, featureVersion, location, rootFile);
IInstallableUnit iuResult = (IInstallableUnit) iuAndFiles[0];
File[] fileResult = (File[]) iuAndFiles[1];
if (fileResult != null && fileResult.length > 0) {
IArtifactKey artifact = iuResult.getArtifacts()[0];
ArtifactDescriptor descriptor = new ArtifactDescriptor(artifact);
- publishArtifact(descriptor, fileResult, destination, false, false);
+ publishArtifact(descriptor, fileResult, info, 0);
}
result.addIU(iuResult, IPublisherResult.NON_ROOT);
return iuResult;
@@ -192,4 +199,121 @@ public class FeaturesAction extends Generator implements IPublishingAction {
return (FileSetDescriptor[]) values.toArray(new FileSetDescriptor[values.size()]);
}
+ /**
+ * Gather any advice we can from the given feature. In particular, it may have
+ * information about the shape of the bundles it includes. The discovered advice is
+ * added to the given result.
+ * @param feature the feature to process
+ * @param info the publishing info to update
+ */
+ public void gatherAdvice(Feature feature, IPublisherInfo info) {
+ IBundleAdvice advice = (IBundleAdvice) info.getAdvice(IBundleAdvice.ID);
+ if (advice == null) {
+ advice = new BundleAdvice();
+ info.setAdvice(IBundleAdvice.ID, advice);
+ }
+ FeatureEntry entries[] = feature.getEntries();
+ for (int i = 0; i < entries.length; i++) {
+ FeatureEntry entry = entries[i];
+ if (entry.isUnpack())
+ advice.setShape(entry.getId(), entry.getVersion(), IBundleAdvice.DIR);
+ }
+ }
+
+ public IInstallableUnit createGroupIU(Feature feature, IInstallableUnit featureIU, Properties extraProperties) {
+ InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
+ String id = getTransformedId(feature.getId(), /*isPlugin*/false, /*isGroup*/true);
+ iu.setId(id);
+ Version version = new Version(feature.getVersion());
+ iu.setVersion(version);
+ iu.setProperty(IInstallableUnit.PROP_NAME, feature.getLabel());
+ if (feature.getLicense() != null)
+ iu.setLicense(new License(feature.getLicenseURL(), feature.getLicense()));
+ if (feature.getCopyright() != null)
+ iu.setCopyright(new Copyright(feature.getCopyrightURL(), feature.getCopyright()));
+ iu.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(id, new VersionRange(new Version(0, 0, 0), true, new Version(feature.getVersion()), false), IUpdateDescriptor.NORMAL, null));
+
+ // generate requirements for the feature inclusions/requirement
+ FeatureEntry entries[] = feature.getEntries();
+ RequiredCapability[] required = new RequiredCapability[entries.length + 1];
+ for (int i = 0; i < entries.length; i++) {
+ VersionRange range = getVersionRange(entries[i]);
+ required[i] = MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, getTransformedId(entries[i].getId(), entries[i].isPlugin(), /*isGroup*/true), range, getFilter(entries[i]), entries[i].isOptional(), false);
+ }
+ required[entries.length] = MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, featureIU.getId(), new VersionRange(featureIU.getVersion(), true, featureIU.getVersion(), true), INSTALL_FEATURES_FILTER, false, false);
+ iu.setRequiredCapabilities(required);
+ iu.setTouchpointType(TouchpointType.NONE);
+ iu.setProperty(IInstallableUnit.PROP_TYPE_GROUP, Boolean.TRUE.toString());
+ // TODO: shouldn't the filter for the group be constructed from os, ws, arch, nl
+ // of the feature?
+ // iu.setFilter(filter);
+ iu.setCapabilities(new ProvidedCapability[] {MetadataGeneratorHelper.createSelfCapability(id, version)});
+
+ if (extraProperties != null) {
+ Enumeration e = extraProperties.propertyNames();
+ while (e.hasMoreElements()) {
+ String name = (String) e.nextElement();
+ iu.setProperty(name, extraProperties.getProperty(name));
+ }
+ }
+ return MetadataFactory.createInstallableUnit(iu);
+ }
+
+ public VersionRange getVersionRange(FeatureEntry entry) {
+ String versionSpec = entry.getVersion();
+ if (versionSpec == null)
+ // TODO should really be returning VersionRange.emptyRange here...
+ return null;
+ Version version = new Version(versionSpec);
+ if (!entry.isRequires())
+ return new VersionRange(version, true, version, true);
+ String match = entry.getMatch();
+ if (match == null)
+ // TODO should really be returning VersionRange.emptyRange here...
+ return null;
+ if (match.equals("perfect")) //$NON-NLS-1$
+ return new VersionRange(version, true, version, true);
+ if (match.equals("equivalent")) { //$NON-NLS-1$
+ Version upper = new Version(version.getMajor(), version.getMinor() + 1, 0);
+ return new VersionRange(version, true, upper, false);
+ }
+ if (match.equals("compatible")) { //$NON-NLS-1$
+ Version upper = new Version(version.getMajor() + 1, 0, 0);
+ return new VersionRange(version, true, upper, false);
+ }
+ if (match.equals("greaterOrEqual")) //$NON-NLS-1$
+ return new VersionRange(version, true, new VersionRange(null).getMaximum(), true);
+ return null;
+ }
+
+ public String getFilter(FeatureEntry entry) {
+ StringBuffer result = new StringBuffer();
+ result.append("(&"); //$NON-NLS-1$
+ if (entry.getFilter() != null)
+ result.append(entry.getFilter());
+ if (entry.getOS() != null)
+ result.append("(osgi.os=" + entry.getOS() + ')');//$NON-NLS-1$
+ if (entry.getWS() != null)
+ result.append("(osgi.ws=" + entry.getWS() + ')');//$NON-NLS-1$
+ if (entry.getArch() != null)
+ result.append("(osgi.arch=" + entry.getArch() + ')');//$NON-NLS-1$
+ if (entry.getNL() != null)
+ result.append("(osgi.nl=" + entry.getNL() + ')');//$NON-NLS-1$
+ if (result.length() == 2)
+ return null;
+ result.append(')');
+ return result.toString();
+ }
+
+ protected Feature[] getFeatures(File[] locations) {
+ ArrayList result = new ArrayList(locations.length);
+ for (int i = 0; i < locations.length; i++) {
+ Feature feature = new FeatureParser().parse(locations[i]);
+ if (feature != null) {
+ feature.setLocation(locations[i].getAbsolutePath());
+ result.add(feature);
+ }
+ }
+ return (Feature[]) result.toArray(new Feature[result.size()]);
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FragmentIUsAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FragmentIUsAction.java
index d2a23b95c..bb9f9e508 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FragmentIUsAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FragmentIUsAction.java
@@ -11,32 +11,20 @@ package org.eclipse.equinox.internal.p2.publisher.actions;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
+import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
import org.osgi.framework.Version;
-public class FragmentIUsAction extends Generator implements IPublishingAction {
+public class FragmentIUsAction extends AbstractPublishingAction {
protected GeneratorBundleInfo[] bundles;
private String flavor;
public FragmentIUsAction(IPublisherInfo info, GeneratorBundleInfo[] bundles, String flavor) {
- super(createGeneratorInfo(info));
this.bundles = bundles;
this.flavor = flavor;
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- return result;
- }
-
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
for (int i = 0; i < bundles.length; i++)
createFragment(bundles[i], results);
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IBundleAdvice.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IBundleAdvice.java
new file mode 100644
index 000000000..305fc16f1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IBundleAdvice.java
@@ -0,0 +1,24 @@
+package org.eclipse.equinox.internal.p2.publisher.actions;
+
+import org.eclipse.equinox.internal.p2.publisher.BundleDescriptionFactory;
+import org.eclipse.equinox.internal.p2.publisher.IPublishingAdvice;
+
+public interface IBundleAdvice extends IPublishingAdvice {
+
+ public static final String ID = "bundle_advice";
+ public static final String DIR = BundleDescriptionFactory.DIR;
+ public static final String JAR = BundleDescriptionFactory.JAR;
+
+ /**
+ * Returns the shape (e.g., folder or JAR) of the bundle with the given name and version.
+ * If the version is <code>null</code> then return the advice for the most likely version
+ * of the bundle.
+ * @param id the bundle to lookup
+ * @param version the version of the bundle (may be <code>null</code>)
+ * @return the shape of the given bundle.
+ */
+ public String getShape(String id, String version);
+
+ public void setShape(String id, String version, String shape);
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/JREAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/JREAction.java
index 7c8ae0d0a..5e69c020d 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/JREAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/JREAction.java
@@ -12,32 +12,20 @@ package org.eclipse.equinox.internal.p2.publisher.actions;
import java.io.File;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
+import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
-public class JREAction extends Generator implements IPublishingAction {
+public class JREAction extends AbstractPublishingAction {
private File location;
public JREAction(IPublisherInfo info, File location) {
- super(createGeneratorInfo(info));
this.location = location;
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- return result;
- }
-
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
IArtifactDescriptor artifact = MetadataGeneratorHelper.createJREData(location, results);
- publishArtifact(artifact, new File[] {location}, info.getArtifactRepository(), false, true);
+ publishArtifact(artifact, null, new File[] {location}, info, INCLUDE_ROOT);
return Status.OK_STATUS;
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/MergeResultsAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/MergeResultsAction.java
index caab15283..fa8ccdf7e 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/MergeResultsAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/MergeResultsAction.java
@@ -11,17 +11,14 @@ package org.eclipse.equinox.internal.p2.publisher.actions;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
+import org.eclipse.equinox.internal.p2.publisher.*;
-public class MergeResultsAction extends Generator implements IPublishingAction {
+public class MergeResultsAction extends AbstractPublishingAction {
private IPublishingAction[] actions;
private int mode;
public MergeResultsAction(IPublishingAction[] actions, int mode) {
- super(null);
this.actions = actions;
this.mode = mode;
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootFilesAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootFilesAction.java
index 2626e696c..984c83be5 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootFilesAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootFilesAction.java
@@ -1,10 +1,8 @@
-/************************************************import com.code9.ubiquity.publisher.IPublisherInfo;
-import com.code9.ubiquity.publisher.IPublishingAction;
-import java.io.File;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
-.eclipse.org/legal/epl-v10.html
+/*******************************************************************************
+ * Copyright (c) 2008 Code 9 and others. All rights reserved. This
+ * program and the accompanying materials are made available under the terms of
+ * the Eclipse Public License v1.0 which accompanies this distribution, and is
+ * available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Code 9 - initial API and implementation
@@ -15,17 +13,15 @@ import java.io.File;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
+import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor;
import org.eclipse.equinox.internal.provisional.p2.metadata.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitFragmentDescription;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
import org.eclipse.osgi.service.resolver.VersionRange;
import org.osgi.framework.Version;
-public class RootFilesAction extends Generator implements IPublishingAction {
+public class RootFilesAction extends AbstractPublishingAction {
private String configSpec;
private String idBase;
@@ -35,7 +31,6 @@ public class RootFilesAction extends Generator implements IPublishingAction {
private String flavor;
public RootFilesAction(IPublisherInfo info, File root, File[] exclusions, String configSpec, String idBase, String version, String flavor) {
- super(createGeneratorInfo(info, flavor));
this.root = root;
this.exclusions = exclusions;
this.configSpec = configSpec;
@@ -46,16 +41,6 @@ public class RootFilesAction extends Generator implements IPublishingAction {
this.flavor = flavor;
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info, String flavor) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- result.setFlavor(flavor);
- return result;
- }
-
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
generateExecutableIUs(info, results);
return Status.OK_STATUS;
@@ -109,7 +94,7 @@ public class RootFilesAction extends Generator implements IPublishingAction {
//Create the artifact descriptor. we have several files so no path on disk
IArtifactDescriptor descriptor = MetadataGeneratorHelper.createArtifactDescriptor(key, null, false, true);
- publishArtifact(descriptor, excludeFiles(root, exclusions), info.getArtifactRepository(), false, true);
+ publishArtifact(descriptor, null, excludeFiles(root, exclusions), info, INCLUDE_ROOT);
}
private File[] excludeFiles(File base, File[] exclusions) {
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootIUAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootIUAction.java
index ee928125f..be36f12ce 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootIUAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootIUAction.java
@@ -9,42 +9,33 @@
******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher.actions;
-import java.util.Collection;
+import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
-import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory;
+import org.eclipse.equinox.internal.p2.publisher.*;
+import org.eclipse.equinox.internal.provisional.p2.metadata.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
+import org.eclipse.osgi.service.resolver.VersionRange;
+import org.osgi.framework.Version;
/**
* Create a top level IU that lists all the current roots as well as any explicitly identified
* top level IUs.
*/
-public class RootIUAction extends Generator implements IPublishingAction {
+public class RootIUAction extends AbstractPublishingAction {
private String version;
private String id;
private String[] topLevel;
+ private String name;
- public RootIUAction(String id, String version, String[] topLevel, IPublisherInfo info) {
- super(createGeneratorInfo(info));
+ public RootIUAction(String id, String version, String name, String[] topLevel, IPublisherInfo info) {
this.id = id;
this.version = version;
+ this.name = name;
this.topLevel = topLevel;
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- return result;
- }
-
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
generateRootIU(results);
return Status.OK_STATUS;
@@ -58,13 +49,41 @@ public class RootIUAction extends Generator implements IPublishingAction {
if (iu != null)
children.add(iu);
}
- InstallableUnitDescription descriptor = createTopLevelIUDescription(children, id, version, /* name */id, null, false);
+ InstallableUnitDescription descriptor = createTopLevelIUDescription(children, id, version, name, null, false);
IInstallableUnit rootIU = MetadataFactory.createInstallableUnit(descriptor);
if (rootIU == null)
return;
result.addIU(rootIU, IPublisherResult.NON_ROOT);
// TODO why do we create a category here?
- result.addIU(generateDefaultCategory(rootIU, rootCategory), IPublisherResult.NON_ROOT);
+ // result.addIU(generateDefaultCategory(rootIU, rootCategory), IPublisherResult.NON_ROOT);
+ }
+
+ protected InstallableUnitDescription createTopLevelIUDescription(Collection children, String id, String version, String name, Collection requires, boolean configureLauncherData) {
+ InstallableUnitDescription root = new MetadataFactory.InstallableUnitDescription();
+ root.setSingleton(true);
+ root.setId(id);
+ root.setVersion(new Version(version));
+ root.setProperty(IInstallableUnit.PROP_NAME, name);
+
+ ArrayList requiredCapabilities = new ArrayList(children.size());
+ for (Iterator iterator = children.iterator(); iterator.hasNext();) {
+ IInstallableUnit iu = (IInstallableUnit) iterator.next();
+ VersionRange range = new VersionRange(iu.getVersion(), true, iu.getVersion(), true);
+ // boolean isOptional = checkOptionalRootDependency(iu);
+ requiredCapabilities.add(MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, iu.getId(), range, iu.getFilter(), false, false));
+ }
+ if (requires != null)
+ requiredCapabilities.addAll(requires);
+ root.setRequiredCapabilities((RequiredCapability[]) requiredCapabilities.toArray(new RequiredCapability[requiredCapabilities.size()]));
+ root.setArtifacts(new IArtifactKey[0]);
+
+ root.setProperty("lineUp", "true"); //$NON-NLS-1$ //$NON-NLS-2$
+ root.setUpdateDescriptor(MetadataFactory.createUpdateDescriptor(id, VersionRange.emptyRange, IUpdateDescriptor.NORMAL, null));
+ root.setProperty(IInstallableUnit.PROP_TYPE_GROUP, Boolean.TRUE.toString());
+ root.setCapabilities(new ProvidedCapability[] {MetadataGeneratorHelper.createSelfCapability(id, new Version(version))});
+ root.setTouchpointType(MetadataGeneratorHelper.TOUCHPOINT_OSGI);
+ return root;
}
+
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/UpdateSiteAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/UpdateSiteAction.java
index 5c305bc00..5c452e5d0 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/UpdateSiteAction.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/UpdateSiteAction.java
@@ -15,18 +15,15 @@ import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
-import org.eclipse.equinox.internal.p2.metadata.generator.Activator;
-import org.eclipse.equinox.internal.p2.metadata.generator.Messages;
-import org.eclipse.equinox.internal.p2.metadata.generator.features.*;
-import org.eclipse.equinox.internal.p2.publisher.IPublisherInfo;
-import org.eclipse.equinox.internal.p2.publisher.IPublishingAction;
+import org.eclipse.equinox.internal.p2.publisher.*;
+import org.eclipse.equinox.internal.p2.publisher.Messages;
+import org.eclipse.equinox.internal.p2.publisher.features.*;
import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Version;
-public class UpdateSiteAction extends Generator implements IPublishingAction {
+public class UpdateSiteAction extends AbstractPublishingAction {
private URL location;
private IPublisherInfo info;
@@ -34,7 +31,6 @@ public class UpdateSiteAction extends Generator implements IPublishingAction {
private HashSet defaultCategorySet;
public UpdateSiteAction(URL location, IPublisherInfo info) {
- super(createGeneratorInfo(info));
this.location = location;
this.info = info;
initialize();
@@ -49,15 +45,6 @@ public class UpdateSiteAction extends Generator implements IPublishingAction {
defaultCategorySet.add(defaultCategory);
}
- private static IGeneratorInfo createGeneratorInfo(IPublisherInfo info) {
- EclipseInstallGeneratorInfoProvider result = new EclipseInstallGeneratorInfoProvider();
- result.setArtifactRepository(info.getArtifactRepository());
- result.setMetadataRepository(info.getMetadataRepository());
- result.setPublishArtifactRepository(info.publishArtifactRepository());
- result.setPublishArtifacts(info.publishArtifacts());
- return result;
- }
-
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
generateCategories(results);
return Status.OK_STATUS;
@@ -145,4 +132,16 @@ public class UpdateSiteAction extends Generator implements IPublishingAction {
}
return mappings;
}
+
+ /**
+ * Generates IUs corresponding to update site categories.
+ * @param categoriesToFeatures Map of SiteCategory ->Set (Feature IUs in that category).
+ * @param result The generator result being built
+ */
+ protected void generateCategoryIUs(Map categoriesToFeatures, IPublisherResult result) {
+ for (Iterator it = categoriesToFeatures.keySet().iterator(); it.hasNext();) {
+ SiteCategory category = (SiteCategory) it.next();
+ result.addIU(MetadataGeneratorHelper.createCategoryIU(category, (Set) categoriesToFeatures.get(category), null), IPublisherResult.NON_ROOT);
+ }
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DefaultSiteParser.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DefaultSiteParser.java
new file mode 100644
index 000000000..fa99d90fe
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DefaultSiteParser.java
@@ -0,0 +1,850 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.io.*;
+import java.util.*;
+import javax.xml.parsers.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+import org.eclipse.equinox.internal.p2.core.helpers.Tracing;
+import org.eclipse.equinox.internal.p2.metadata.repository.Activator;
+import org.eclipse.osgi.util.NLS;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Parses a site.xml file.
+ * This class was initially copied from org.eclipse.update.core.model.DefaultSiteParser.
+ */
+public class DefaultSiteParser extends DefaultHandler {
+
+ private static final String ARCHIVE = "archive"; //$NON-NLS-1$
+ private static final String CATEGORY = "category"; //$NON-NLS-1$
+ private static final String CATEGORY_DEF = "category-def"; //$NON-NLS-1$
+
+ //private static final String ASSOCIATE_SITES = "associateSites"; //$NON-NLS-1$
+ // private static final String ASSOCIATE_SITE = "associateSite"; //$NON-NLS-1$
+ private static final String DEFAULT_INFO_URL = "index.html"; //$NON-NLS-1$
+ private static final String DESCRIPTION = "description"; //$NON-NLS-1$
+ private static final String FEATURE = "feature"; //$NON-NLS-1$
+ private static final String FEATURES = "features/"; //$NON-NLS-1$
+ private static final String MIRROR = "mirror"; //$NON-NLS-1$
+ private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ private static final String PLUGIN_ID = Activator.ID;
+ private static final String SITE = "site"; //$NON-NLS-1$
+
+ private static final int STATE_ARCHIVE = 3;
+ private static final int STATE_CATEGORY = 4;
+ private static final int STATE_CATEGORY_DEF = 5;
+ private static final int STATE_DESCRIPTION_CATEGORY_DEF = 7;
+ private static final int STATE_DESCRIPTION_SITE = 6;
+ private static final int STATE_FEATURE = 2;
+ private static final int STATE_IGNORED_ELEMENT = -1;
+ private static final int STATE_INITIAL = 0;
+ private static final int STATE_SITE = 1;
+
+ private int currentState;
+
+ private boolean DESCRIPTION_SITE_ALREADY_SEEN = false;
+ // Current object stack (used to hold the current object we are
+ // populating in this plugin descriptor
+ Stack objectStack = new Stack();
+
+ private SAXParser parser;
+
+ // Current State Information
+ Stack stateStack = new Stack();
+
+ private MultiStatus status;
+
+ /*
+ *
+ */
+ private static void debug(String s) {
+ Tracing.debug("DefaultSiteParser: " + s); //$NON-NLS-1$
+ }
+
+ // private static URLEntry[] getAssociateSites(String associateSitesURL) {
+ //
+ // try {
+ // DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ // DocumentBuilder builder = domFactory.newDocumentBuilder();
+ // Document document = builder.parse(associateSitesURL);
+ // if (document == null)
+ // return null;
+ // NodeList mirrorNodes = document.getElementsByTagName(ASSOCIATE_SITE);
+ // URLEntry[] mirrors = new URLEntry[mirrorNodes.getLength()];
+ // for (int i = 0; i < mirrorNodes.getLength(); i++) {
+ // Element mirrorNode = (Element) mirrorNodes.item(i);
+ // mirrors[i] = new URLEntry();
+ // String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
+ // String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$
+ // mirrors[i].setURL(infoURL);
+ // mirrors[i].setAnnotation(label);
+ //
+ // if (Tracing.DEBUG_GENERATOR_PARSING)
+ // debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
+ // }
+ // return mirrors;
+ // } catch (Exception e) {
+ // // log if absolute url
+ // if (associateSitesURL != null && (associateSitesURL.startsWith("http://") //$NON-NLS-1$
+ // || associateSitesURL.startsWith("https://") //$NON-NLS-1$
+ // || associateSitesURL.startsWith("file://") //$NON-NLS-1$
+ // || associateSitesURL.startsWith("ftp://") //$NON-NLS-1$
+ // || associateSitesURL.startsWith("jar://"))) //$NON-NLS-1$
+ // log(Messages.DefaultSiteParser_mirrors, e);
+ // return null;
+ // }
+ // }
+
+ static URLEntry[] getMirrors(String mirrorsURL) {
+
+ try {
+ String countryCode = Locale.getDefault().getCountry().toLowerCase();
+ int timeZone = (new GregorianCalendar()).get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000);
+
+ if (mirrorsURL.indexOf("?") != -1) { //$NON-NLS-1$
+ mirrorsURL = mirrorsURL + "&"; //$NON-NLS-1$
+ } else {
+ mirrorsURL = mirrorsURL + "?"; //$NON-NLS-1$
+ }
+ mirrorsURL = mirrorsURL + "countryCode=" + countryCode + "&timeZone=" + timeZone + "&responseType=xml"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = domFactory.newDocumentBuilder();
+ Document document = builder.parse(mirrorsURL);
+ if (document == null)
+ return null;
+ NodeList mirrorNodes = document.getElementsByTagName(MIRROR);
+ URLEntry[] mirrors = new URLEntry[mirrorNodes.getLength()];
+ for (int i = 0; i < mirrorNodes.getLength(); i++) {
+ Element mirrorNode = (Element) mirrorNodes.item(i);
+ mirrors[i] = new URLEntry();
+ String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
+ String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$
+ mirrors[i].setURL(infoURL);
+ mirrors[i].setAnnotation(label);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return mirrors;
+ } catch (Exception e) {
+ // log if absolute url
+ if (mirrorsURL != null && (mirrorsURL.startsWith("http://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("https://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("file://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("ftp://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("jar://"))) //$NON-NLS-1$
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, Messages.DefaultSiteParser_mirrors, e));
+ return null;
+ }
+ }
+
+ static void log(Exception e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Internal Error", e)); //$NON-NLS-1$
+ }
+
+ static void log(IStatus error) {
+ LogHelper.log(error);
+ }
+
+ static void log(String message) {
+ LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, null));
+ }
+
+ static void log(String message, Exception e) {
+ LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, e));
+ }
+
+ /**
+ * Constructs a site parser.
+ */
+ public DefaultSiteParser() {
+ super();
+ stateStack = new Stack();
+ objectStack = new Stack();
+ status = null;
+ DESCRIPTION_SITE_ALREADY_SEEN = false;
+ try {
+ parserFactory.setNamespaceAware(true);
+ this.parser = parserFactory.newSAXParser();
+ } catch (ParserConfigurationException e) {
+ log(e);
+ } catch (SAXException e) {
+ log(e);
+ }
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("Created"); //$NON-NLS-1$
+ }
+
+ /**
+ * Handle character text
+ * @see DefaultHandler#characters(char[], int, int)
+ * @since 2.0
+ */
+ public void characters(char[] ch, int start, int length) {
+ String text = new String(ch, start, length);
+ //only push if description
+ int state = ((Integer) stateStack.peek()).intValue();
+ if (state == STATE_DESCRIPTION_SITE || state == STATE_DESCRIPTION_CATEGORY_DEF)
+ objectStack.push(text);
+
+ }
+
+ /**
+ * Handle end of element tags
+ * @see DefaultHandler#endElement(String, String, String)
+ * @since 2.0
+ */
+ public void endElement(String uri, String localName, String qName) {
+
+ String text = null;
+ URLEntry info = null;
+
+ int state = ((Integer) stateStack.peek()).intValue();
+ switch (state) {
+ case STATE_IGNORED_ELEMENT :
+ case STATE_ARCHIVE :
+ case STATE_CATEGORY :
+ stateStack.pop();
+ break;
+
+ case STATE_INITIAL :
+ internalError(Messages.DefaultSiteParser_ParsingStackBackToInitialState);
+ break;
+
+ case STATE_SITE :
+ stateStack.pop();
+ if (objectStack.peek() instanceof String) {
+ text = (String) objectStack.pop();
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.getDescription().setAnnotation(text);
+ }
+ //do not pop the object
+ break;
+
+ case STATE_FEATURE :
+ stateStack.pop();
+ objectStack.pop();
+ break;
+
+ case STATE_CATEGORY_DEF :
+ stateStack.pop();
+ if (objectStack.peek() instanceof String) {
+ text = (String) objectStack.pop();
+ SiteCategory category = (SiteCategory) objectStack.peek();
+ category.setDescription(text);
+ }
+ objectStack.pop();
+ break;
+
+ case STATE_DESCRIPTION_SITE :
+ stateStack.pop();
+ text = ""; //$NON-NLS-1$
+ while (objectStack.peek() instanceof String) {
+ // add text, preserving at most one space between text fragments
+ String newText = (String) objectStack.pop();
+ if (trailingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ text = newText.trim() + text;
+ if (leadingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ }
+ text = text.trim();
+
+ info = (URLEntry) objectStack.pop();
+ if (text != null)
+ info.setAnnotation(text);
+
+ SiteModel siteModel = (SiteModel) objectStack.peek();
+ // override description.
+ // do not raise error as previous description may be default one
+ // when parsing site tag
+ if (DESCRIPTION_SITE_ALREADY_SEEN)
+ debug(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] {getState(state)})));
+ siteModel.setDescription(info);
+ DESCRIPTION_SITE_ALREADY_SEEN = true;
+ break;
+
+ case STATE_DESCRIPTION_CATEGORY_DEF :
+ stateStack.pop();
+ text = ""; //$NON-NLS-1$
+ while (objectStack.peek() instanceof String) {
+ // add text, preserving at most one space between text fragments
+ String newText = (String) objectStack.pop();
+ if (trailingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ text = newText.trim() + text;
+ if (leadingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ }
+ text = text.trim();
+
+ info = (URLEntry) objectStack.pop();
+ if (text != null)
+ info.setAnnotation(text);
+
+ SiteCategory category = (SiteCategory) objectStack.peek();
+ if (category.getDescription() != null)
+ internalError(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] {getState(state), category.getLabel()})));
+ else
+ category.setDescription(info.getAnnotation());
+ break;
+
+ default :
+ internalError(NLS.bind(Messages.DefaultSiteParser_UnknownEndState, (new String[] {getState(state)})));
+ break;
+ }
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End Element:" + uri + ":" + localName + ":" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ /*
+ * Handles an error state specified by the status. The collection of all logged status
+ * objects can be accessed using <code>getStatus()</code>.
+ *
+ * @param error a status detailing the error condition
+ */
+ private void error(IStatus error) {
+
+ if (status == null) {
+ status = new MultiStatus(PLUGIN_ID, 0, Messages.DefaultSiteParser_ErrorParsingSite, null);
+ }
+
+ status.add(error);
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ LogHelper.log(error);
+ }
+
+ /**
+ * Handle errors
+ * @see DefaultHandler#error(SAXParseException)
+ * @since 2.0
+ */
+ public void error(SAXParseException ex) {
+ logStatus(ex);
+ }
+
+ /**
+ * Handle fatal errors
+ * @see DefaultHandler#fatalError(SAXParseException)
+ * @exception SAXException
+ * @since 2.0
+ */
+ public void fatalError(SAXParseException ex) throws SAXException {
+ logStatus(ex);
+ throw ex;
+ }
+
+ /*
+ * return the state as String
+ */
+ private String getState(int state) {
+
+ switch (state) {
+ case STATE_IGNORED_ELEMENT :
+ return "Ignored"; //$NON-NLS-1$
+
+ case STATE_INITIAL :
+ return "Initial"; //$NON-NLS-1$
+
+ case STATE_SITE :
+ return "Site"; //$NON-NLS-1$
+
+ case STATE_FEATURE :
+ return "Feature"; //$NON-NLS-1$
+
+ case STATE_ARCHIVE :
+ return "Archive"; //$NON-NLS-1$
+
+ case STATE_CATEGORY :
+ return "Category"; //$NON-NLS-1$
+
+ case STATE_CATEGORY_DEF :
+ return "Category Def"; //$NON-NLS-1$
+
+ case STATE_DESCRIPTION_CATEGORY_DEF :
+ return "Description / Category Def"; //$NON-NLS-1$
+
+ case STATE_DESCRIPTION_SITE :
+ return "Description / Site"; //$NON-NLS-1$
+
+ default :
+ return Messages.DefaultSiteParser_UnknownState;
+ }
+ }
+
+ /**
+ * Returns all status objects accumulated by the parser.
+ *
+ * @return multi-status containing accumulated status, or <code>null</code>.
+ * @since 2.0
+ */
+ public MultiStatus getStatus() {
+ return status;
+ }
+
+ private void handleCategoryDefState(String elementName, Attributes attributes) {
+ if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_CATEGORY_DEF));
+ processInfo(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ private void handleCategoryState(String elementName, Attributes attributes) {
+ if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
+ processInfo(attributes);
+ } else if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else if (elementName.equals(CATEGORY)) {
+ stateStack.push(new Integer(STATE_CATEGORY));
+ processCategory(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ private void handleFeatureState(String elementName, Attributes attributes) {
+ if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
+ processInfo(attributes);
+ } else if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else if (elementName.equals(CATEGORY)) {
+ stateStack.push(new Integer(STATE_CATEGORY));
+ processCategory(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ private void handleInitialState(String elementName, Attributes attributes) throws SAXException {
+ if (elementName.equals(SITE)) {
+ stateStack.push(new Integer(STATE_SITE));
+ processSite(attributes);
+ } else {
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ // what we received was not a site.xml, no need to continue
+ throw new SAXException(Messages.DefaultSiteParser_InvalidXMLStream);
+ }
+
+ }
+
+ private void handleSiteState(String elementName, Attributes attributes) {
+ if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
+ processInfo(attributes);
+ } else if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ /*
+ *
+ */
+ private void internalError(String message) {
+ error(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, null));
+ }
+
+ /*
+ *
+ */
+ private void internalErrorUnknownTag(String msg) {
+ stateStack.push(new Integer(STATE_IGNORED_ELEMENT));
+ internalError(msg);
+ }
+
+ private boolean leadingSpace(String str) {
+ if (str.length() <= 0) {
+ return false;
+ }
+ return Character.isWhitespace(str.charAt(0));
+ }
+
+ /*
+ *
+ */
+ private void logStatus(SAXParseException ex) {
+ String name = ex.getSystemId();
+ if (name == null)
+ name = ""; //$NON-NLS-1$
+ else
+ name = name.substring(1 + name.lastIndexOf("/")); //$NON-NLS-1$
+
+ String msg;
+ if (name.equals("")) //$NON-NLS-1$
+ msg = NLS.bind(Messages.DefaultSiteParser_ErrorParsing, (new String[] {ex.getMessage()}));
+ else {
+ String[] values = new String[] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()};
+ msg = NLS.bind(Messages.DefaultSiteParser_ErrorlineColumnMessage, values);
+ }
+ error(new Status(IStatus.ERROR, PLUGIN_ID, msg, ex));
+ }
+
+ /**
+ * Parses the specified input steam and constructs a site model.
+ * The input stream is not closed as part of this operation.
+ *
+ * @param in input stream
+ * @return site model
+ * @exception SAXException
+ * @exception IOException
+ * @since 2.0
+ */
+ public SiteModel parse(InputStream in) throws SAXException, IOException {
+ stateStack.push(new Integer(STATE_INITIAL));
+ currentState = ((Integer) stateStack.peek()).intValue();
+ parser.parse(new InputSource(in), this);
+ if (objectStack.isEmpty())
+ throw new SAXException(Messages.DefaultSiteParser_NoSiteTag);
+ if (objectStack.peek() instanceof SiteModel) {
+ return (SiteModel) objectStack.pop();
+ }
+ String stack = ""; //$NON-NLS-1$
+ Iterator iter = objectStack.iterator();
+ while (iter.hasNext()) {
+ stack = stack + iter.next().toString() + "\r\n"; //$NON-NLS-1$
+ }
+ throw new SAXException(NLS.bind(Messages.DefaultSiteParser_WrongParsingStack, (new String[] {stack})));
+ }
+
+ /*
+ * process archive info
+ */
+ private void processArchive(Attributes attributes) {
+ URLEntry archive = new URLEntry();
+ String id = attributes.getValue("path"); //$NON-NLS-1$
+ if (id == null || id.trim().equals("")) { //$NON-NLS-1$
+ internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"path", getState(currentState)}))); //$NON-NLS-1$
+ }
+
+ archive.setAnnotation(id);
+
+ String url = attributes.getValue("url"); //$NON-NLS-1$
+ if (url == null || url.trim().equals("")) { //$NON-NLS-1$
+ internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"archive", getState(currentState)}))); //$NON-NLS-1$
+ } else {
+ archive.setURL(url);
+
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.addArchive(archive);
+ }
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End processing Archive: path:" + id + " url:" + url);//$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ /*
+ * process the Category info
+ */
+ private void processCategory(Attributes attributes) {
+ String category = attributes.getValue("name"); //$NON-NLS-1$
+ SiteFeature feature = (SiteFeature) objectStack.peek();
+ feature.addCategoryName(category);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End processing Category: name:" + category); //$NON-NLS-1$
+ }
+
+ /*
+ * process category def info
+ */
+ private void processCategoryDef(Attributes attributes) {
+ SiteCategory category = new SiteCategory();
+ String name = attributes.getValue("name"); //$NON-NLS-1$
+ String label = attributes.getValue("label"); //$NON-NLS-1$
+ category.setName(name);
+ category.setLabel(label);
+
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.addCategory(category);
+ objectStack.push(category);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End processing CategoryDef: name:" + name + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /*
+ * process feature info
+ */
+ private void processFeature(Attributes attributes) {
+ SiteFeature feature = new SiteFeature();
+
+ // feature location on the site
+ String urlInfo = attributes.getValue("url"); //$NON-NLS-1$
+ // identifier and version
+ String id = attributes.getValue("id"); //$NON-NLS-1$
+ String ver = attributes.getValue("version"); //$NON-NLS-1$
+
+ boolean noURL = (urlInfo == null || urlInfo.trim().equals("")); //$NON-NLS-1$
+ boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$
+ boolean noVersion = (ver == null || ver.trim().equals("")); //$NON-NLS-1$
+
+ // We need to have id and version, or the url, or both.
+ if (noURL) {
+ if (noId || noVersion)
+ internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState)}))); //$NON-NLS-1$
+ else
+ // default url
+ urlInfo = FEATURES + id + '_' + ver; //
+ }
+
+ feature.setURLString(urlInfo);
+
+ String type = attributes.getValue("type"); //$NON-NLS-1$
+ feature.setType(type);
+
+ // if one is null, and not the other
+ if (noId ^ noVersion) {
+ String[] values = new String[] {id, ver, getState(currentState)};
+ log(NLS.bind(Messages.DefaultFeatureParser_IdOrVersionInvalid, values));
+ } else {
+ feature.setFeatureIdentifier(id);
+ feature.setFeatureVersion(ver);
+ }
+
+ // get label if it exists
+ String label = attributes.getValue("label"); //$NON-NLS-1$
+ if (label != null) {
+ if ("".equals(label.trim())) //$NON-NLS-1$
+ label = null;
+ }
+ feature.setLabel(label);
+
+ // OS
+ String os = attributes.getValue("os"); //$NON-NLS-1$
+ feature.setOS(os);
+
+ // WS
+ String ws = attributes.getValue("ws"); //$NON-NLS-1$
+ feature.setWS(ws);
+
+ // NL
+ String nl = attributes.getValue("nl"); //$NON-NLS-1$
+ feature.setNL(nl);
+
+ // arch
+ String arch = attributes.getValue("arch"); //$NON-NLS-1$
+ feature.setArch(arch);
+
+ //patch
+ String patch = attributes.getValue("patch"); //$NON-NLS-1$
+ feature.setPatch(patch);
+
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.addFeature(feature);
+ feature.setSiteModel(site);
+
+ objectStack.push(feature);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End Processing DefaultFeature Tag: url:" + urlInfo + " type:" + type); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ /*
+ * process URL info with element text
+ */
+ private void processInfo(Attributes attributes) {
+ URLEntry inf = new URLEntry();
+ String infoURL = attributes.getValue("url"); //$NON-NLS-1$
+ inf.setURL(infoURL);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("Processed Info: url:" + infoURL); //$NON-NLS-1$
+
+ objectStack.push(inf);
+ }
+
+ /*
+ * process site info
+ */
+ private void processSite(Attributes attributes) {
+ // create site map
+ SiteModel site = new SiteModel();
+
+ // if URL is specified, it replaces the URL of the site
+ // used to calculate the location of features and archives
+ String siteURL = attributes.getValue("url"); //$NON-NLS-1$
+ if (siteURL != null && !("".equals(siteURL.trim()))) { //$NON-NLS-1$
+ if (!siteURL.endsWith("/") && !siteURL.endsWith(File.separator)) { //$NON-NLS-1$
+ siteURL += "/"; //$NON-NLS-1$
+ }
+ site.setLocationURLString(siteURL);
+ }
+
+ // provide default description URL
+ // If <description> is specified, for the site, it takes precedence
+ URLEntry description = new URLEntry();
+ description.setURL(DEFAULT_INFO_URL);
+ site.setDescription(description);
+
+ // verify we can parse the site ...if the site has
+ // a different type throw an exception to force reparsing
+ // with the matching parser
+ String type = attributes.getValue("type"); //$NON-NLS-1$
+ site.setType(type);
+
+ // get mirrors, if any
+ String mirrorsURL = attributes.getValue("mirrorsURL"); //$NON-NLS-1$
+ if (mirrorsURL != null && mirrorsURL.trim().length() > 0) {
+ // URLEntry[] mirrors = getMirrors(mirrorsURL);
+ // if (mirrors != null)
+ // site.setMirrors(mirrors);
+ // else
+
+ //Since we are parsing the site at p2 generation time and the
+ //mirrors may change, there is no point doing the mirror expansion now
+ site.setMirrorsURLString(mirrorsURL);
+ }
+
+ String pack200 = attributes.getValue("pack200"); //$NON-NLS-1$
+ if (pack200 != null && new Boolean(pack200).booleanValue()) {
+ site.setSupportsPack200(true);
+ }
+
+ // if (attributes.getValue("digestURL") != null) { //$NON-NLS-1$
+ // site.setDigestExist(true);
+ // site.setDigestURL(attributes.getValue("digestURL")); //$NON-NLS-1$
+ //
+ // if ((attributes.getValue("availableLocales") != null) && (!attributes.getValue("availableLocales").trim().equals(""))) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ // StringTokenizer locals = new StringTokenizer(attributes.getValue("availableLocales"), ","); //$NON-NLS-1$//$NON-NLS-2$
+ // String[] availableLocals = new String[locals.countTokens()];
+ // int i = 0;
+ // while (locals.hasMoreTokens()) {
+ // availableLocals[i++] = locals.nextToken();
+ // }
+ // extendedSite.setAvailableLocals(availableLocals);
+ // }
+ // }
+ //
+ // if ((site instanceof ExtendedSite) && (attributes.getValue("associateSitesURL") != null)) { //$NON-NLS-1$
+ // IURLEntry[] associateSites = getAssociateSites(attributes.getValue("associateSitesURL"), factory); //$NON-NLS-1$
+ // if (associateSites != null)
+ // ((ExtendedSite) site).setAssociateSites(associateSites);
+ // else
+ // site.setMirrorsURLString(mirrorsURL);
+ // }
+
+ objectStack.push(site);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End process Site tag: siteURL:" + siteURL + " type:" + type);//$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ /**
+ * Handle start of element tags
+ * @see DefaultHandler#startElement(String, String, String, Attributes)
+ * @since 2.0
+ */
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+
+ if (Tracing.DEBUG_GENERATOR_PARSING) {
+ debug("State: " + currentState); //$NON-NLS-1$
+ debug("Start Element: uri:" + uri + " local Name:" + localName + " qName:" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ switch (currentState) {
+ case STATE_IGNORED_ELEMENT :
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {localName, getState(currentState)})));
+ break;
+ case STATE_INITIAL :
+ handleInitialState(localName, attributes);
+ break;
+
+ case STATE_SITE :
+ handleSiteState(localName, attributes);
+ break;
+
+ case STATE_FEATURE :
+ handleFeatureState(localName, attributes);
+ break;
+
+ case STATE_ARCHIVE :
+ handleSiteState(localName, attributes);
+ break;
+
+ case STATE_CATEGORY :
+ handleCategoryState(localName, attributes);
+ break;
+
+ case STATE_CATEGORY_DEF :
+ handleCategoryDefState(localName, attributes);
+ break;
+
+ case STATE_DESCRIPTION_SITE :
+ handleSiteState(localName, attributes);
+ break;
+
+ case STATE_DESCRIPTION_CATEGORY_DEF :
+ handleSiteState(localName, attributes);
+ break;
+
+ default :
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownStartState, (new String[] {getState(currentState)})));
+ break;
+ }
+ int newState = ((Integer) stateStack.peek()).intValue();
+ if (newState != STATE_IGNORED_ELEMENT)
+ currentState = newState;
+
+ }
+
+ private boolean trailingSpace(String str) {
+ if (str.length() <= 0) {
+ return false;
+ }
+ return Character.isWhitespace(str.charAt(str.length() - 1));
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DigestParser.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DigestParser.java
new file mode 100644
index 000000000..bd7062624
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/DigestParser.java
@@ -0,0 +1,97 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import javax.xml.parsers.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Default feature parser.
+ * Parses the feature manifest file as defined by the platform.
+ *
+ * @since 3.0
+ */
+public class DigestParser extends DefaultHandler {
+
+ private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ private SAXParser parser;
+ private final List features = new ArrayList();
+ private final FeatureParser featureHandler = new FeatureParser(false);
+
+ public DigestParser() {
+ super();
+ try {
+ parserFactory.setNamespaceAware(true);
+ this.parser = parserFactory.newSAXParser();
+ } catch (ParserConfigurationException e) {
+ System.out.println(e);
+ } catch (SAXException e) {
+ System.out.println(e);
+ }
+ }
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ featureHandler.characters(ch, start, length);
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if ("digest".equals(localName)) { //$NON-NLS-1$
+ return;
+ }
+ if ("feature".equals(localName)) { //$NON-NLS-1$
+ Feature feature = featureHandler.getResult();
+ features.add(feature);
+ } else
+ featureHandler.endElement(uri, localName, qName);
+ }
+
+ public Feature[] parse(File location) {
+ if (!location.exists())
+ return null;
+
+ InputStream is = null;
+ try {
+ JarFile jar = new JarFile(location);
+ JarEntry entry = jar.getJarEntry("digest.xml"); //$NON-NLS-1$
+ if (entry == null)
+ return null;
+ is = new BufferedInputStream(jar.getInputStream(entry));
+ parser.parse(new InputSource(is), this);
+ return (Feature[]) features.toArray(new Feature[features.size()]);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (SAXException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e1) {
+ //
+ }
+ }
+ return null;
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if ("digest".equals(localName)) { //$NON-NLS-1$
+ return;
+ }
+ featureHandler.startElement(uri, localName, qName, attributes);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Feature.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Feature.java
new file mode 100644
index 000000000..847c5cf5e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Feature.java
@@ -0,0 +1,278 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.util.ArrayList;
+
+/**
+ *
+ * Feature information
+ */
+public class Feature {
+
+ private final String id;
+ private String version;
+ private String label;
+ private String image;
+
+ private URLEntry description;
+ private URLEntry license;
+ private URLEntry copyright;
+
+ private String installHandler;
+ private String installHandlerURL;
+ private String installHandlerLibrary;
+
+ private URLEntry updateSite;
+ private ArrayList discoverySites;
+
+ private ArrayList entries;
+ private String providerName;
+ private String os;
+ private String ws;
+ private String arch;
+ private String nl;
+
+ private String location;
+
+ public Feature(String id, String version) {
+ if (id == null)
+ throw new IllegalArgumentException();
+ this.id = id;
+ this.version = version;
+ }
+
+ public void addDiscoverySite(String label, String url) {
+ if (label == null && url == null)
+ return;
+
+ if (this.discoverySites == null)
+ this.discoverySites = new ArrayList();
+
+ URLEntry entry = new URLEntry(url, label);
+ this.discoverySites.add(entry);
+ }
+
+ public void addEntry(FeatureEntry plugin) {
+ if (entries == null)
+ entries = new ArrayList();
+ entries.add(plugin);
+ }
+
+ public String getArch() {
+ return arch;
+ }
+
+ public String getCopyright() {
+ if (copyright != null)
+ return copyright.getAnnotation();
+ return null;
+ }
+
+ public String getCopyrightURL() {
+ if (copyright != null)
+ return copyright.getURL();
+ return null;
+ }
+
+ public String getDescription() {
+ if (description != null)
+ return description.getAnnotation();
+ return null;
+ }
+
+ public String getDescriptionURL() {
+ if (description != null)
+ return description.getURL();
+ return null;
+ }
+
+ public URLEntry[] getDiscoverySites() {
+ if (discoverySites == null)
+ return new URLEntry[0];
+ return (URLEntry[]) discoverySites.toArray(new URLEntry[discoverySites.size()]);
+ }
+
+ public FeatureEntry[] getEntries() {
+ if (entries == null)
+ return new FeatureEntry[0];
+ return (FeatureEntry[]) entries.toArray(new FeatureEntry[entries.size()]);
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getImage() {
+ return image;
+ }
+
+ public String getInstallHandler() {
+ return installHandler;
+ }
+
+ public String getInstallHandlerLibrary() {
+ return installHandlerLibrary;
+ }
+
+ public String getInstallHandlerURL() {
+ return installHandlerURL;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public String getLicense() {
+ if (license != null)
+ return license.getAnnotation();
+ return null;
+ }
+
+ public String getLicenseURL() {
+ if (license != null)
+ return license.getURL();
+ return null;
+ }
+
+ public String getLocation() {
+ return this.location;
+ }
+
+ public String getNL() {
+ return nl;
+ }
+
+ public String getOS() {
+ return os;
+ }
+
+ public String getProviderName() {
+ return providerName;
+ }
+
+ public String getUpdateSiteLabel() {
+ if (updateSite != null)
+ return updateSite.getAnnotation();
+ return null;
+ }
+
+ public String getUpdateSiteURL() {
+ if (updateSite != null)
+ return updateSite.getURL();
+ return null;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getWS() {
+ return ws;
+ }
+
+ public void setCopyright(String copyright) {
+ if (this.copyright == null)
+ this.copyright = new URLEntry();
+ this.copyright.setAnnotation(copyright);
+ }
+
+ public void setCopyrightURL(String copyrightURL) {
+ if (this.copyright == null)
+ this.copyright = new URLEntry();
+ this.copyright.setURL(copyrightURL);
+ }
+
+ public void setDescription(String description) {
+ if (this.description == null)
+ this.description = new URLEntry();
+ this.description.setAnnotation(description);
+ }
+
+ public void setDescriptionURL(String descriptionURL) {
+ if (this.description == null)
+ this.description = new URLEntry();
+ this.description.setURL(descriptionURL);
+ }
+
+ public void setEnvironment(String os, String ws, String arch, String nl) {
+ this.os = os;
+ this.ws = ws;
+ this.arch = arch;
+ this.nl = nl;
+ }
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+ public void setInstallHandler(String installHandler) {
+ this.installHandler = installHandler;
+ }
+
+ public void setInstallHandlerLibrary(String installHandlerLibrary) {
+ this.installHandlerLibrary = installHandlerLibrary;
+ }
+
+ public void setInstallHandlerURL(String installHandlerURL) {
+ this.installHandlerURL = installHandlerURL;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public void setLicense(String license) {
+ if (this.license == null)
+ this.license = new URLEntry();
+ this.license.setAnnotation(license);
+ }
+
+ public void setLicenseURL(String licenseURL) {
+ if (this.license == null)
+ this.license = new URLEntry();
+ this.license.setURL(licenseURL);
+ }
+
+ public void setLocation(String location) {
+ this.location = location;
+ }
+
+ public void setProviderName(String value) {
+ providerName = value;
+ }
+
+ public void setUpdateSiteLabel(String updateSiteLabel) {
+ if (this.updateSite == null)
+ this.updateSite = new URLEntry();
+ this.updateSite.setAnnotation(updateSiteLabel);
+ }
+
+ public void setUpdateSiteURL(String updateSiteURL) {
+ if (this.updateSite == null)
+ this.updateSite = new URLEntry();
+ this.updateSite.setURL(updateSiteURL);
+ }
+
+ public void setURL(String value) {
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ /**
+ * For debugging purposes only.
+ */
+ public String toString() {
+ return "Feature " + id + " version: " + version; //$NON-NLS-1$ //$NON-NLS-2$
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureEntry.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureEntry.java
new file mode 100644
index 000000000..ae974c445
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureEntry.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+/**
+ */
+public class FeatureEntry {
+ private final String id;
+ private final String version;
+ private String url;
+ private String os;
+ private String ws;
+ private String arch;
+ private String nl;
+ private String match;
+ private final boolean isPlugin;
+ private boolean isFragment = false;
+ private boolean isRequires = false;
+ private boolean unpack = true;
+ private boolean optional = false;
+
+ /**
+ * Temporary field to add provisioning filters to features
+ */
+ private String filter;
+
+ public static FeatureEntry createRequires(String id, String version, String match, String filter, boolean isPlugin) {
+ FeatureEntry result = new FeatureEntry(id, version, isPlugin);
+ result.match = match;
+ result.isRequires = true;
+ // for requires we don't care what the form is so leave it as false (JAR'd)
+ result.unpack = false;
+ if (filter != null)
+ result.setFilter(filter);
+ return result;
+ }
+
+ public FeatureEntry(String id, String version, boolean isPlugin) {
+ this.id = id;
+ this.version = version;
+ this.isPlugin = isPlugin;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final FeatureEntry other = (FeatureEntry) obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ if (version == null) {
+ if (other.version != null)
+ return false;
+ } else if (!version.equals(other.version))
+ return false;
+ return true;
+ }
+
+ public String getArch() {
+ return arch;
+ }
+
+ /**
+ * Temporary method to add provisioning filters to features
+ */
+ public String getFilter() {
+ return filter;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getMatch() {
+ return match;
+ }
+
+ public String getNL() {
+ return nl;
+ }
+
+ public String getOS() {
+ return os;
+ }
+
+ public String getURL() {
+ return url;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public String getWS() {
+ return ws;
+ }
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ result = prime * result + ((version == null) ? 0 : version.hashCode());
+ return result;
+ }
+
+ public boolean isFragment() {
+ return isFragment;
+ }
+
+ public boolean isOptional() {
+ return optional;
+ }
+
+ public boolean isPlugin() {
+ return isPlugin;
+ }
+
+ public boolean isRequires() {
+ return isRequires;
+ }
+
+ public boolean isUnpack() {
+ return unpack;
+ }
+
+ public void setEnvironment(String os, String ws, String arch, String nl) {
+ this.os = os;
+ this.ws = ws;
+ this.arch = arch;
+ this.nl = nl;
+ }
+
+ /**
+ * Temporary method to add provisioning filters to features
+ */
+ public void setFilter(String filter) {
+ this.filter = filter;
+
+ }
+
+ public void setFragment(boolean value) {
+ isFragment = value;
+ }
+
+ public void setOptional(boolean value) {
+ optional = value;
+ }
+
+ public void setUnpack(boolean value) {
+ unpack = value;
+ }
+
+ public void setURL(String value) {
+ url = value;
+ }
+
+ public String toString() {
+ StringBuffer result = new StringBuffer();
+
+ result.append(isPlugin ? "Plugin: " : "Feature: "); //$NON-NLS-1$ //$NON-NLS-2$
+ result.append(id != null ? id.toString() : ""); //$NON-NLS-1$
+ result.append(version != null ? " " + version.toString() : ""); //$NON-NLS-1$ //$NON-NLS-2$
+ return result.toString();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureParser.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureParser.java
new file mode 100644
index 000000000..c69414071
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/FeatureParser.java
@@ -0,0 +1,335 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.io.*;
+import java.net.URL;
+import java.util.Properties;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import javax.xml.parsers.*;
+import org.eclipse.osgi.util.NLS;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Default feature parser.
+ * Parses the feature manifest file as defined by the platform.
+ *
+ * @since 3.0
+ */
+public class FeatureParser extends DefaultHandler {
+
+ private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ private SAXParser parser;
+ private Feature result;
+ private URL url;
+ private StringBuffer characters = null;
+
+ private Properties messages = null;
+
+ public FeatureParser() {
+ this(true);
+ }
+
+ protected FeatureParser(boolean createParser) {
+ super();
+ if (!createParser)
+ return;
+ try {
+ parserFactory.setNamespaceAware(true);
+ this.parser = parserFactory.newSAXParser();
+ } catch (ParserConfigurationException e) {
+ System.out.println(e);
+ } catch (SAXException e) {
+ System.out.println(e);
+ }
+ }
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if (characters == null)
+ return;
+ characters.append(ch, start, length);
+ }
+
+ protected Feature createFeature(String id, String version) {
+ return new Feature(id, version);
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if (characters == null)
+ return;
+ if ("description".equals(localName)) { //$NON-NLS-1$
+ result.setDescription(localize(characters.toString().trim()));
+ } else if ("license".equals(localName)) { //$NON-NLS-1$
+ result.setLicense(localize(characters.toString().trim()));
+ } else if ("copyright".equals(localName)) { //$NON-NLS-1$
+ result.setCopyright(localize(characters.toString().trim()));
+ }
+ characters = null;
+ }
+
+ public Feature getResult() {
+ return result;
+ }
+
+ private Properties loadProperties(File directory) {
+ //skip directories that don't contain a feature.properties file
+ File file = new File(directory, "feature.properties"); //$NON-NLS-1$
+ if (!file.exists())
+ return null;
+ try {
+ InputStream input = new BufferedInputStream(new FileInputStream(file));
+ try {
+ Properties result = new Properties();
+ result.load(input);
+ return result;
+ } finally {
+ if (input != null)
+ input.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private Properties loadProperties(JarFile jar) {
+ JarEntry entry = jar.getJarEntry("feature.properties"); //$NON-NLS-1$
+ if (entry == null)
+ return null;
+ try {
+ InputStream input = new BufferedInputStream(jar.getInputStream(entry));
+ try {
+ Properties result = new Properties();
+ result.load(input);
+ return result;
+ } finally {
+ if (input != null)
+ input.close();
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ private String localize(String value) {
+ if (messages == null || value == null)
+ return value;
+ if (!value.startsWith("%")) //$NON-NLS-1$
+ return value;
+ return messages.getProperty(value.substring(1), value);
+ }
+
+ /**
+ * Parses the specified location and constructs a feature. The given location
+ * should be either the location of the feature JAR or the directory containing
+ * the feature.
+ *
+ * @param location the location of the feature to parse.
+ */
+ public Feature parse(File location) {
+ if (!location.exists())
+ return null;
+ if (location.isDirectory()) {
+ //skip directories that don't contain a feature.xml file
+ File file = new File(location, "feature.xml"); //$NON-NLS-1$
+ if (!file.exists())
+ return null;
+ Properties properties = loadProperties(location);
+ try {
+ InputStream input = new BufferedInputStream(new FileInputStream(file));
+ return parse(input, properties);
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ }
+ } else if (location.getName().endsWith(".jar")) { //$NON-NLS-1$
+ try {
+ JarFile jar = new JarFile(location);
+ Properties properties = loadProperties(jar);
+ JarEntry entry = jar.getJarEntry("feature.xml"); //$NON-NLS-1$
+ if (entry == null)
+ return null;
+ InputStream input = new BufferedInputStream(jar.getInputStream(entry));
+ return parse(input, properties);
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Parse the given input stream and return a feature object
+ * or null. This method closes the input stream.
+ */
+ public Feature parse(InputStream in, Properties messages) {
+ this.messages = messages;
+ result = null;
+ try {
+ parser.parse(new InputSource(in), this);
+ } catch (SAXException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ } finally {
+ try {
+ in.close();
+ } catch (IOException e1) {
+ // Utils.log(e1.getLocalizedMessage());
+ }
+ }
+ return result;
+ }
+
+ private void processCopyright(Attributes attributes) {
+ result.setCopyrightURL(attributes.getValue("url")); //$NON-NLS-1$
+ characters = new StringBuffer();
+ }
+
+ private void processDescription(Attributes attributes) {
+ result.setDescriptionURL(attributes.getValue("url")); //$NON-NLS-1$
+ characters = new StringBuffer();
+ }
+
+ private void processDiscoverySite(Attributes attributes) {
+ result.addDiscoverySite(attributes.getValue("url"), attributes.getValue("label")); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ protected void processFeature(Attributes attributes) {
+ String id = attributes.getValue("id"); //$NON-NLS-1$
+ String ver = attributes.getValue("version"); //$NON-NLS-1$
+
+ if (id == null || id.trim().equals("") //$NON-NLS-1$
+ || ver == null || ver.trim().equals("")) { //$NON-NLS-1$
+ // System.out.println(NLS.bind(Messages.FeatureParser_IdOrVersionInvalid, (new String[] { id, ver})));
+ } else {
+ result = createFeature(id, ver);
+
+ String os = attributes.getValue("os"); //$NON-NLS-1$
+ String ws = attributes.getValue("ws"); //$NON-NLS-1$
+ String nl = attributes.getValue("nl"); //$NON-NLS-1$
+ String arch = attributes.getValue("arch"); //$NON-NLS-1$
+ result.setEnvironment(os, ws, arch, nl);
+
+ //TODO rootURLs
+ if (url != null && "file".equals(url.getProtocol())) { //$NON-NLS-1$
+ File f = new File(url.getFile().replace('/', File.separatorChar));
+ result.setURL("features" + "/" + f.getParentFile().getName() + "/");// + f.getName()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ } else {
+ // externalized URLs might be in relative form, ensure they are absolute
+ // feature.setURL(Utils.makeAbsolute(Utils.getInstallURL(), url).toExternalForm());
+ }
+
+ result.setProviderName(localize(attributes.getValue("provider-name"))); //$NON-NLS-1$
+ result.setLabel(localize(attributes.getValue("label"))); //$NON-NLS-1$
+ result.setImage(attributes.getValue("image")); //$NON-NLS-1$
+
+ // Utils.debug("End process DefaultFeature tag: id:" +id + " ver:" +ver + " url:" + feature.getURL()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+
+ private void processImport(Attributes attributes) {
+ String id = attributes.getValue("feature"); //$NON-NLS-1$
+ FeatureEntry entry = null;
+ if (id != null) {
+ entry = FeatureEntry.createRequires(id, attributes.getValue("version"), attributes.getValue("match"), attributes.getValue("filter"), false); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ } else {
+ id = attributes.getValue("plugin"); //$NON-NLS-1$
+ entry = FeatureEntry.createRequires(id, attributes.getValue("version"), attributes.getValue("match"), attributes.getValue("filter"), true); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ result.addEntry(entry);
+ }
+
+ private void processIncludes(Attributes attributes) {
+ FeatureEntry entry = new FeatureEntry(attributes.getValue("id"), attributes.getValue("version"), false); //$NON-NLS-1$ //$NON-NLS-2$
+ String flag = attributes.getValue("optional"); //$NON-NLS-1$
+ if (flag != null)
+ entry.setOptional(Boolean.valueOf(flag).booleanValue());
+ setEnvironment(attributes, entry);
+ result.addEntry(entry);
+ }
+
+ private void processInstallHandler(Attributes attributes) {
+ result.setInstallHandler(attributes.getValue("handler")); //$NON-NLS-1$
+ result.setInstallHandlerLibrary(attributes.getValue("library")); //$NON-NLS-1$
+ result.setInstallHandlerURL(attributes.getValue("url")); //$NON-NLS-1$
+ }
+
+ private void processLicense(Attributes attributes) {
+ result.setLicenseURL(attributes.getValue("url")); //$NON-NLS-1$
+ characters = new StringBuffer();
+ }
+
+ private void processPlugin(Attributes attributes) {
+ String id = attributes.getValue("id"); //$NON-NLS-1$
+ String version = attributes.getValue("version"); //$NON-NLS-1$
+
+ if (id == null || id.trim().equals("") || version == null || version.trim().equals("")) { //$NON-NLS-1$ //$NON-NLS-2$
+ System.out.println(NLS.bind("FeatureParser#processPlugin, ID {0} or version {1} invalid", (new String[] {id, version}))); //$NON-NLS-1$
+ } else {
+ FeatureEntry plugin = new FeatureEntry(id, version, true);
+ setEnvironment(attributes, plugin);
+ String unpack = attributes.getValue("unpack"); //$NON-NLS-1$
+ if (unpack != null)
+ plugin.setUnpack(Boolean.valueOf(unpack).booleanValue());
+ String fragment = attributes.getValue("fragment"); //$NON-NLS-1$
+ if (fragment != null)
+ plugin.setFragment(Boolean.valueOf(fragment).booleanValue());
+ String filter = attributes.getValue("filter"); //$NON-NLS-1$
+ if (filter != null)
+ plugin.setFilter(filter);
+ result.addEntry(plugin);
+
+ // Utils.debug("End process DefaultFeature tag: id:" + id + " ver:" + ver + " url:" + feature.getURL()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+ }
+
+ private void processUpdateSite(Attributes attributes) {
+ result.setUpdateSiteLabel(attributes.getValue("label")); //$NON-NLS-1$
+ result.setUpdateSiteURL(attributes.getValue("url")); //$NON-NLS-1$
+ }
+
+ private void setEnvironment(Attributes attributes, FeatureEntry entry) {
+ String os = attributes.getValue("os"); //$NON-NLS-1$
+ String ws = attributes.getValue("ws"); //$NON-NLS-1$
+ String nl = attributes.getValue("nl"); //$NON-NLS-1$
+ String arch = attributes.getValue("arch"); //$NON-NLS-1$
+ entry.setEnvironment(os, ws, arch, nl);
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ // Utils.debug("Start Element: uri:" + uri + " local Name:" + localName + " qName:" + qName); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ if ("plugin".equals(localName)) { //$NON-NLS-1$
+ processPlugin(attributes);
+ } else if ("description".equals(localName)) { //$NON-NLS-1$
+ processDescription(attributes);
+ } else if ("license".equals(localName)) { //$NON-NLS-1$
+ processLicense(attributes);
+ } else if ("copyright".equals(localName)) { //$NON-NLS-1$
+ processCopyright(attributes);
+ } else if ("feature".equals(localName)) { //$NON-NLS-1$
+ processFeature(attributes);
+ } else if ("import".equals(localName)) { //$NON-NLS-1$
+ processImport(attributes);
+ } else if ("includes".equals(localName)) { //$NON-NLS-1$
+ processIncludes(attributes);
+ } else if ("install-handler".equals(localName)) { //$NON-NLS-1$
+ processInstallHandler(attributes);
+ } else if ("update".equals(localName)) { //$NON-NLS-1$
+ processUpdateSite(attributes);
+ } else if ("discovery".equals(localName)) { //$NON-NLS-1$
+ processDiscoverySite(attributes);
+ }
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Messages.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Messages.java
new file mode 100644
index 000000000..7afe31e63
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Messages.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import org.eclipse.osgi.util.NLS;
+
+public final class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.eclipse.update.internal.core.messages";//$NON-NLS-1$
+
+ public static String DefaultFeatureParser_IdOrVersionInvalid;
+ public static String DefaultSiteParser_NoSiteTag;
+ public static String DefaultSiteParser_WrongParsingStack;
+ public static String DefaultSiteParser_UnknownElement;
+ public static String DefaultSiteParser_UnknownStartState;
+ public static String DefaultSiteParser_Missing;
+ public static String DefaultSiteParser_ParsingStackBackToInitialState;
+ public static String DefaultSiteParser_ElementAlreadySet;
+ public static String DefaultSiteParser_CategoryAlreadySet;
+ public static String DefaultSiteParser_UnknownEndState;
+ public static String DefaultSiteParser_ErrorParsing;
+ public static String DefaultSiteParser_ErrorlineColumnMessage;
+ public static String DefaultSiteParser_ErrorParsingSite;
+ public static String DefaultSiteParser_UnknownState;
+ public static String DefaultSiteParser_InvalidXMLStream;
+ public static String DefaultSiteParser_mirrors;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ // Do not instantiate
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/ProductFile.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/ProductFile.java
new file mode 100644
index 000000000..553c488ce
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/ProductFile.java
@@ -0,0 +1,520 @@
+/*******************************************************************************
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.io.*;
+import java.util.*;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import org.eclipse.equinox.internal.p2.publisher.IProductDescriptor;
+import org.xml.sax.Attributes;
+import org.xml.sax.InputSource;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ *
+ * @since 3.1
+ */
+public class ProductFile extends DefaultHandler implements IProductDescriptor {
+ private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+
+ private static final String PROGRAM_ARGS = "programArgs"; //$NON-NLS-1$
+ private static final String PROGRAM_ARGS_LINUX = "programArgsLin"; //$NON-NLS-1$
+ private static final String PROGRAM_ARGS_MAC = "programArgsMac"; //$NON-NLS-1$
+ private static final String PROGRAM_ARGS_SOLARIS = "programArgsSol"; //$NON-NLS-1$
+ private static final String PROGRAM_ARGS_WIN = "programArgsWin"; //$NON-NLS-1$
+ private static final String VM_ARGS = "vmArgs"; //$NON-NLS-1$
+ private static final String VM_ARGS_LINUX = "vmArgsLin"; //$NON-NLS-1$
+ private static final String VM_ARGS_MAC = "vmArgsMac"; //$NON-NLS-1$
+ private static final String VM_ARGS_SOLARIS = "vmArgsSol"; //$NON-NLS-1$
+ private static final String VM_ARGS_WIN = "vmArgsWin"; //$NON-NLS-1$
+
+ private static final String SOLARIS_LARGE = "solarisLarge"; //$NON-NLS-1$
+ private static final String SOLARIS_MEDIUM = "solarisMedium"; //$NON-NLS-1$
+ private static final String SOLARIS_SMALL = "solarisSmall"; //$NON-NLS-1$
+ private static final String SOLARIS_TINY = "solarisTiny"; //$NON-NLS-1$
+ private static final String WIN32_16_LOW = "winSmallLow"; //$NON-NLS-1$
+ private static final String WIN32_16_HIGH = "winSmallHigh"; //$NON-NLS-1$
+ private static final String WIN32_24_LOW = "win24Low"; //$NON-NLS-1$
+ private static final String WIN32_32_LOW = "winMediumLow"; //$NON-NLS-1$
+ private static final String WIN32_32_HIGH = "winMediumHigh"; //$NON-NLS-1$
+ private static final String WIN32_48_LOW = "winLargeLow"; //$NON-NLS-1$
+ private static final String WIN32_48_HIGH = "winLargeHigh"; //$NON-NLS-1$
+
+ private static final String OS_WIN32 = "win32";//$NON-NLS-1$
+ private static final String OS_LINUX = "linux";//$NON-NLS-1$
+ private static final String OS_SOLARIS = "solaris";//$NON-NLS-1$
+ private static final String OS_MACOSX = "macosx";//$NON-NLS-1$
+
+ private static final String PRODUCT = "product"; //$NON-NLS-1$
+ private static final String CONFIG_INI = "configIni"; //$NON-NLS-1$
+ private static final String LAUNCHER = "launcher"; //$NON-NLS-1$
+ private static final String LAUNCHER_ARGS = "launcherArgs"; //$NON-NLS-1$
+ private static final String PLUGINS = "plugins"; //$NON-NLS-1$
+ private static final String FEATURES = "features"; //$NON-NLS-1$
+ private static final String SPLASH = "splash"; //$NON-NLS-1$
+ private static final String P_USE_ICO = "useIco"; //$NON-NLS-1$
+
+ //These constants form a small state machine to parse the .product file
+ private static final int STATE_START = 0;
+ private static final int STATE_PRODUCT = 1;
+ private static final int STATE_LAUNCHER = 2;
+ private static final int STATE_LAUNCHER_ARGS = 3;
+ private static final int STATE_PLUGINS = 4;
+ private static final int STATE_FEATURES = 5;
+ private static final int STATE_PROGRAM_ARGS = 6;
+ private static final int STATE_PROGRAM_ARGS_LINUX = 7;
+ private static final int STATE_PROGRAM_ARGS_MAC = 8;
+ private static final int STATE_PROGRAM_ARGS_SOLARIS = 9;
+ private static final int STATE_PROGRAM_ARGS_WIN = 10;
+ private static final int STATE_VM_ARGS = 11;
+ private static final int STATE_VM_ARGS_LINUX = 12;
+ private static final int STATE_VM_ARGS_MAC = 13;
+ private static final int STATE_VM_ARGS_SOLARIS = 14;
+ private static final int STATE_VM_ARGS_WIN = 15;
+
+ private int state = STATE_START;
+
+ private final SAXParser parser;
+ private String currentOS = null;
+ private boolean useIco = false;
+ private final ArrayList result = new ArrayList(6);
+ private String launcherName = null;
+ private String icons[] = null;
+ private String configPath = null;
+ private String id = null;
+ private boolean useFeatures = false;
+ private List plugins = null;
+ private List fragments = null;
+ private List features = null;
+ private String splashLocation = null;
+ private String productName = null;
+ private String application = null;
+ private String version = null;
+
+ private Properties launcherArgs = new Properties();
+
+ private static String normalize(String text) {
+ if (text == null || text.trim().length() == 0)
+ return ""; //$NON-NLS-1$
+
+ text = text.replaceAll("\\r|\\n|\\f|\\t", " "); //$NON-NLS-1$ //$NON-NLS-2$
+ return text.replaceAll("\\s+", " "); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Constructs a feature parser.
+ */
+ public ProductFile(String location, String os) throws Exception {
+ super();
+ this.currentOS = os;
+ // try {
+ parserFactory.setNamespaceAware(true);
+ parser = parserFactory.newSAXParser();
+ InputStream in = new BufferedInputStream(new FileInputStream(location));
+ parser.parse(new InputSource(in), this);
+ // } catch (ParserConfigurationException e) {
+ // throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FORMAT, NLS.bind(Messages.exception_productParse, location), e));
+ // } catch (SAXException e) {
+ // throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FORMAT, NLS.bind(Messages.exception_productParse, location), e));
+ // } catch (FileNotFoundException e) {
+ // throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FILE, NLS.bind(Messages.exception_missingElement, location), null));
+ // } catch (IOException e) {
+ // throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FORMAT, NLS.bind(Messages.exception_productParse, location), e));
+ // }
+ }
+
+ public String getLauncherName() {
+ return launcherName;
+ }
+
+ public List getPlugins() {
+ return getPlugins(true);
+ }
+
+ public List getPlugins(boolean includeFragments) {
+ List p = plugins != null ? plugins : Collections.EMPTY_LIST;
+ if (!includeFragments)
+ return p;
+
+ List f = fragments != null ? fragments : Collections.EMPTY_LIST;
+ int size = p.size() + f.size();
+ if (size == 0)
+ return Collections.EMPTY_LIST;
+
+ List both = new ArrayList(size);
+ both.addAll(p);
+ both.addAll(f);
+ return both;
+ }
+
+ public List getFragments() {
+ if (fragments == null)
+ return Collections.EMPTY_LIST;
+ return fragments;
+ }
+
+ public List getFeatures() {
+ if (features == null)
+ return Collections.EMPTY_LIST;
+ return features;
+ }
+
+ public boolean containsPlugin(String plugin) {
+ return (plugins != null && plugins.contains(plugin)) || (fragments != null && fragments.contains(plugin));
+ }
+
+ /**
+ * Parses the specified url and constructs a feature
+ */
+ public String[] getIcons() {
+ if (icons != null)
+ return icons;
+ String[] temp = new String[result.size()];
+ int i = 0;
+ for (Iterator iter = result.iterator(); iter.hasNext();) {
+ String element = (String) iter.next();
+ if (element != null)
+ temp[i++] = element;
+ }
+ icons = new String[i];
+ System.arraycopy(temp, 0, icons, 0, i);
+ return icons;
+ }
+
+ public String getConfigIniPath() {
+ return configPath;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public String getSplashLocation() {
+ return splashLocation;
+ }
+
+ public String getProductName() {
+ return productName;
+ }
+
+ public String getApplication() {
+ return application;
+ }
+
+ public boolean useFeatures() {
+ return useFeatures;
+ }
+
+ public String getVersion() {
+ return (version == null) ? "0.0.0" : version; //$NON-NLS-1$
+ }
+
+ public String getVMArguments(String os) {
+ String key = null;
+ if (os.equals(OS_WIN32)) {
+ key = VM_ARGS_WIN;
+ } else if (os.equals(OS_LINUX)) {
+ key = VM_ARGS_LINUX;
+ } else if (os.equals(OS_MACOSX)) {
+ key = VM_ARGS_MAC;
+ } else if (os.equals(OS_SOLARIS)) {
+ key = VM_ARGS_SOLARIS;
+ }
+
+ String prefix = launcherArgs.getProperty(VM_ARGS);
+ String platform = null, args = null;
+ if (key != null)
+ platform = launcherArgs.getProperty(key);
+ if (prefix != null)
+ args = platform != null ? prefix + " " + platform : prefix; //$NON-NLS-1$
+ else
+ args = platform != null ? platform : ""; //$NON-NLS-1$
+ return normalize(args);
+ }
+
+ public String getProgramArguments(String os) {
+ String key = null;
+ if (os.equals(OS_WIN32)) {
+ key = PROGRAM_ARGS_WIN;
+ } else if (os.equals(OS_LINUX)) {
+ key = PROGRAM_ARGS_LINUX;
+ } else if (os.equals(OS_MACOSX)) {
+ key = PROGRAM_ARGS_MAC;
+ } else if (os.equals(OS_SOLARIS)) {
+ key = PROGRAM_ARGS_SOLARIS;
+ }
+
+ String prefix = launcherArgs.getProperty(PROGRAM_ARGS);
+ String platform = null, args = null;
+ if (key != null)
+ platform = launcherArgs.getProperty(key);
+ if (prefix != null)
+ args = platform != null ? prefix + " " + platform : prefix; //$NON-NLS-1$
+ else
+ args = platform != null ? platform : ""; //$NON-NLS-1$
+ return normalize(args);
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+ switch (state) {
+ case STATE_START :
+ if (PRODUCT.equals(localName)) {
+ processProduct(attributes);
+ state = STATE_PRODUCT;
+ }
+ break;
+
+ case STATE_PRODUCT :
+ if (CONFIG_INI.equals(localName)) {
+ processConfigIni(attributes);
+ } else if (LAUNCHER.equals(localName)) {
+ processLauncher(attributes);
+ state = STATE_LAUNCHER;
+ } else if (PLUGINS.equals(localName)) {
+ state = STATE_PLUGINS;
+ } else if (FEATURES.equals(localName)) {
+ state = STATE_FEATURES;
+ } else if (LAUNCHER_ARGS.equals(localName)) {
+ state = STATE_LAUNCHER_ARGS;
+ } else if (SPLASH.equals(localName)) {
+ splashLocation = attributes.getValue("location"); //$NON-NLS-1$
+ }
+ break;
+
+ case STATE_LAUNCHER :
+ if (OS_SOLARIS.equals(localName)) {
+ processSolaris(attributes);
+ } else if ("win".equals(localName)) { //$NON-NLS-1$
+ processWin(attributes);
+ } else if (OS_LINUX.equals(localName)) {
+ processLinux(attributes);
+ } else if (OS_MACOSX.equals(localName)) {
+ processMac(attributes);
+ }
+ if ("ico".equals(localName)) { //$NON-NLS-1$
+ processIco(attributes);
+ } else if ("bmp".equals(localName)) { //$NON-NLS-1$
+ processBmp(attributes);
+ }
+ break;
+
+ case STATE_LAUNCHER_ARGS :
+ if (PROGRAM_ARGS.equals(localName)) {
+ state = STATE_PROGRAM_ARGS;
+ } else if (PROGRAM_ARGS_LINUX.equals(localName)) {
+ state = STATE_PROGRAM_ARGS_LINUX;
+ } else if (PROGRAM_ARGS_MAC.equals(localName)) {
+ state = STATE_PROGRAM_ARGS_MAC;
+ } else if (PROGRAM_ARGS_SOLARIS.equals(localName)) {
+ state = STATE_PROGRAM_ARGS_SOLARIS;
+ } else if (PROGRAM_ARGS_WIN.equals(localName)) {
+ state = STATE_PROGRAM_ARGS_WIN;
+ } else if (VM_ARGS.equals(localName)) {
+ state = STATE_VM_ARGS;
+ } else if (VM_ARGS_LINUX.equals(localName)) {
+ state = STATE_VM_ARGS_LINUX;
+ } else if (VM_ARGS_MAC.equals(localName)) {
+ state = STATE_VM_ARGS_MAC;
+ } else if (VM_ARGS_SOLARIS.equals(localName)) {
+ state = STATE_VM_ARGS_SOLARIS;
+ } else if (VM_ARGS_WIN.equals(localName)) {
+ state = STATE_VM_ARGS_WIN;
+ }
+ break;
+
+ case STATE_PLUGINS :
+ if ("plugin".equals(localName)) { //$NON-NLS-1$
+ processPlugin(attributes);
+ }
+ break;
+
+ case STATE_FEATURES :
+ if ("feature".equals(localName)) { //$NON-NLS-1$
+ processFeature(attributes);
+ }
+ break;
+ }
+ }
+
+ public void endElement(String uri, String localName, String qName) {
+ switch (state) {
+ case STATE_PLUGINS :
+ if (PLUGINS.equals(localName))
+ state = STATE_PRODUCT;
+ break;
+ case STATE_FEATURES :
+ if (FEATURES.equals(localName))
+ state = STATE_PRODUCT;
+ break;
+ case STATE_LAUNCHER_ARGS :
+ if (LAUNCHER_ARGS.equals(localName))
+ state = STATE_PRODUCT;
+ break;
+ case STATE_LAUNCHER :
+ if (LAUNCHER.equals(localName))
+ state = STATE_PRODUCT;
+ break;
+
+ case STATE_PROGRAM_ARGS :
+ case STATE_PROGRAM_ARGS_LINUX :
+ case STATE_PROGRAM_ARGS_MAC :
+ case STATE_PROGRAM_ARGS_SOLARIS :
+ case STATE_PROGRAM_ARGS_WIN :
+ case STATE_VM_ARGS :
+ case STATE_VM_ARGS_LINUX :
+ case STATE_VM_ARGS_MAC :
+ case STATE_VM_ARGS_SOLARIS :
+ case STATE_VM_ARGS_WIN :
+ state = STATE_LAUNCHER_ARGS;
+ break;
+ }
+ }
+
+ public void characters(char[] ch, int start, int length) {
+ switch (state) {
+ case STATE_PROGRAM_ARGS :
+ addLaunchArgumentToMap(PROGRAM_ARGS, String.valueOf(ch, start, length));
+ break;
+ case STATE_PROGRAM_ARGS_LINUX :
+ addLaunchArgumentToMap(PROGRAM_ARGS_LINUX, String.valueOf(ch, start, length));
+ break;
+ case STATE_PROGRAM_ARGS_MAC :
+ addLaunchArgumentToMap(PROGRAM_ARGS_MAC, String.valueOf(ch, start, length));
+ break;
+ case STATE_PROGRAM_ARGS_SOLARIS :
+ addLaunchArgumentToMap(PROGRAM_ARGS_SOLARIS, String.valueOf(ch, start, length));
+ break;
+ case STATE_PROGRAM_ARGS_WIN :
+ addLaunchArgumentToMap(PROGRAM_ARGS_WIN, String.valueOf(ch, start, length));
+ break;
+ case STATE_VM_ARGS :
+ addLaunchArgumentToMap(VM_ARGS, String.valueOf(ch, start, length));
+ break;
+ case STATE_VM_ARGS_LINUX :
+ addLaunchArgumentToMap(VM_ARGS_LINUX, String.valueOf(ch, start, length));
+ break;
+ case STATE_VM_ARGS_MAC :
+ addLaunchArgumentToMap(VM_ARGS_MAC, String.valueOf(ch, start, length));
+ break;
+ case STATE_VM_ARGS_SOLARIS :
+ addLaunchArgumentToMap(VM_ARGS_SOLARIS, String.valueOf(ch, start, length));
+ break;
+ case STATE_VM_ARGS_WIN :
+ addLaunchArgumentToMap(VM_ARGS_WIN, String.valueOf(ch, start, length));
+ break;
+ }
+ }
+
+ private void addLaunchArgumentToMap(String key, String value) {
+ if (launcherArgs == null)
+ launcherArgs = new Properties();
+
+ String oldValue = launcherArgs.getProperty(key);
+ if (oldValue != null)
+ launcherArgs.setProperty(key, oldValue + value);
+ else
+ launcherArgs.setProperty(key, value);
+ }
+
+ private void processPlugin(Attributes attributes) {
+ String fragment = attributes.getValue("fragment"); //$NON-NLS-1$
+ if (fragment != null && new Boolean(fragment).booleanValue()) {
+ if (fragments == null)
+ fragments = new ArrayList();
+ fragments.add(attributes.getValue("id")); //$NON-NLS-1$
+ } else {
+ if (plugins == null)
+ plugins = new ArrayList();
+ plugins.add(attributes.getValue("id")); //$NON-NLS-1$
+ }
+ }
+
+ private void processFeature(Attributes attributes) {
+ if (features == null)
+ features = new ArrayList();
+ features.add(attributes.getValue("id")); //$NON-NLS-1$
+ }
+
+ private void processProduct(Attributes attributes) {
+ id = attributes.getValue("id"); //$NON-NLS-1$
+ productName = attributes.getValue("name"); //$NON-NLS-1$
+ application = attributes.getValue("application"); //$NON-NLS-1$
+ String use = attributes.getValue("useFeatures"); //$NON-NLS-1$
+ if (use != null)
+ useFeatures = Boolean.valueOf(use).booleanValue();
+ version = attributes.getValue("version"); //$NON-NLS-1$
+ }
+
+ private void processConfigIni(Attributes attributes) {
+ if (attributes.getValue("use").equals("custom")) { //$NON-NLS-1$//$NON-NLS-2$
+ configPath = attributes.getValue("path"); //$NON-NLS-1$
+ }
+ }
+
+ private void processLauncher(Attributes attributes) {
+ launcherName = attributes.getValue("name"); //$NON-NLS-1$
+ }
+
+ private boolean osMatch(String os) {
+ if (os == currentOS)
+ return true;
+ if (os == null)
+ return false;
+ return os.equals(currentOS);
+ }
+
+ private void processSolaris(Attributes attributes) {
+ if (!osMatch(OS_SOLARIS))
+ return;
+ result.add(attributes.getValue(SOLARIS_LARGE));
+ result.add(attributes.getValue(SOLARIS_MEDIUM));
+ result.add(attributes.getValue(SOLARIS_SMALL));
+ result.add(attributes.getValue(SOLARIS_TINY));
+ }
+
+ private void processWin(Attributes attributes) {
+ if (!osMatch(OS_WIN32))
+ return;
+ useIco = Boolean.valueOf(attributes.getValue(P_USE_ICO)).booleanValue();
+ }
+
+ private void processIco(Attributes attributes) {
+ if (!osMatch(OS_WIN32) || !useIco)
+ return;
+ result.add(attributes.getValue("path")); //$NON-NLS-1$
+ }
+
+ private void processBmp(Attributes attributes) {
+ if (!osMatch(OS_WIN32) || useIco)
+ return;
+ result.add(attributes.getValue(WIN32_16_HIGH));
+ result.add(attributes.getValue(WIN32_16_LOW));
+ result.add(attributes.getValue(WIN32_24_LOW));
+ result.add(attributes.getValue(WIN32_32_HIGH));
+ result.add(attributes.getValue(WIN32_32_LOW));
+ result.add(attributes.getValue(WIN32_48_HIGH));
+ result.add(attributes.getValue(WIN32_48_LOW));
+ }
+
+ private void processLinux(Attributes attributes) {
+ if (!osMatch(OS_LINUX))
+ return;
+ result.add(attributes.getValue("icon")); //$NON-NLS-1$
+ }
+
+ private void processMac(Attributes attributes) {
+ if (!osMatch(OS_MACOSX))
+ return;
+ result.add(attributes.getValue("icon")); //$NON-NLS-1$
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteCategory.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteCategory.java
new file mode 100644
index 000000000..18e75f4f7
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteCategory.java
@@ -0,0 +1,175 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Comparator;
+
+/**
+ * A category in an update site.
+ *
+ * Based on org.eclipse.update.core.model.CategoryModel.
+ */
+public class SiteCategory {
+
+ private static Comparator comp;
+ private String description;
+ private String label;
+ private String name;
+
+ /**
+ * Returns a comparator for category models.
+ *
+ * @return comparator
+ * @since 2.0
+ */
+ public static Comparator getComparator() {
+ if (comp == null) {
+ comp = new Comparator() {
+ /*
+ * @see Comparator#compare(Object,Object)
+ * Returns 0 if versions are equal.
+ * Returns -1 if object1 is after than object2.
+ * Returns +1 if object1 is before than object2.
+ */
+ public int compare(Object o1, Object o2) {
+
+ SiteCategory cat1 = (SiteCategory) o1;
+ SiteCategory cat2 = (SiteCategory) o2;
+
+ if (cat1.equals(cat2))
+ return 0;
+ return cat1.getName().compareTo(cat2.getName());
+ }
+ };
+ }
+ return comp;
+ }
+
+ /**
+ * Creates an uninitialized model object.
+ *
+ * @since 2.0
+ */
+ public SiteCategory() {
+ super();
+ }
+
+ /**
+ * Compare two category models for equality.
+ *
+ * @see Object#equals(Object)
+ * @since 2.0
+ */
+ public boolean equals(Object obj) {
+ boolean result = false;
+ if (obj instanceof SiteCategory) {
+ SiteCategory otherCategory = (SiteCategory) obj;
+ result = getName().equalsIgnoreCase(otherCategory.getName());
+ }
+ return result;
+ }
+
+ /**
+ * Retrieve the detailed category description
+ *
+ * @return category description, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Retrieve the non-localized displayable label for the category.
+ *
+ * @return non-localized displayable label, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Retrieve the name of the category.
+ *
+ * @return category name, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Compute hash code for category model.
+ *
+ * @see Object#hashCode()
+ * @since 2.0
+ */
+ public int hashCode() {
+ return getName().hashCode();
+ }
+
+ /**
+ * Resolve the model object.
+ * Any URL strings in the model are resolved relative to the
+ * base URL argument. Any translatable strings in the model that are
+ * specified as translation keys are localized using the supplied
+ * resource bundle.
+ *
+ * @param base URL
+ * @param bundleURL resource bundle URL
+ * @exception MalformedURLException
+ * @since 2.0
+ */
+ public void resolve(URL base, URL bundleURL) throws MalformedURLException {
+ // resolve local elements
+ // localizedLabel = resolveNLString(bundleURL, label);
+
+ // delegate to references
+ // resolveReference(getDescriptionModel(), base, bundleURL);
+ }
+
+ /**
+ * Sets the category description.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param description category description
+ * @since 2.0
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Sets the category displayable label.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param label displayable label, or resource key
+ * @since 2.0
+ */
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Sets the category name.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param name category name
+ * @since 2.0
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteFeature.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteFeature.java
new file mode 100644
index 000000000..a9f43a016
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteFeature.java
@@ -0,0 +1,408 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * James D Miles (IBM Corp.) - bug 191783, NullPointerException in FeatureDownloader
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * A reference to a feature in an update site.xml file.
+ *
+ * Based on org.eclipse.update.core.model.FeatureReferenceModel.
+ */
+public class SiteFeature {
+
+ private String arch;
+ // performance
+ private URL base;
+ private List /* of String*/categoryNames;
+ private String featureId;
+ private String featureVersion;
+ private String label;
+ private String nl;
+
+ private String os;
+ private String patch;
+ private final boolean resolved = false;
+ private SiteModel site;
+ private String type;
+ private URL url;
+ private String urlString;
+ private String ws;
+
+ /*
+ * Compares two URL for equality
+ * Return false if one of them is null
+ */
+ public static boolean sameURL(URL url1, URL url2) {
+
+ if (url1 == null || url2 == null)
+ return false;
+ if (url1 == url2)
+ return true;
+ if (url1.equals(url2))
+ return true;
+
+ // check if URL are file: URL as we may
+ // have 2 URL pointing to the same featureReference
+ // but with different representation
+ // (i.e. file:/C;/ and file:C:/)
+ if (!"file".equalsIgnoreCase(url1.getProtocol())) //$NON-NLS-1$
+ return false;
+ if (!"file".equalsIgnoreCase(url2.getProtocol())) //$NON-NLS-1$
+ return false;
+
+ File file1 = new File(url1.getFile());
+ File file2 = new File(url2.getFile());
+
+ if (file1 == null)
+ return false;
+
+ return (file1.equals(file2));
+ }
+
+ /**
+ * Creates an uninitialized feature reference model object.
+ */
+ public SiteFeature() {
+ super();
+ }
+
+ /**
+ * Adds the name of a category this feature belongs to.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param categoryName category name
+ */
+ public void addCategoryName(String categoryName) {
+ if (this.categoryNames == null)
+ this.categoryNames = new ArrayList();
+ if (!this.categoryNames.contains(categoryName))
+ this.categoryNames.add(categoryName);
+ }
+
+ private void delayedResolve() {
+
+ // PERF: delay resolution
+ if (resolved)
+ return;
+
+ // resolve local elements
+ try {
+ url = new URL(base, urlString);
+ } catch (MalformedURLException e) {
+ // UpdateCore.warn("", e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Compares 2 feature reference models for equality
+ *
+ * @param object feature reference model to compare with
+ * @return <code>true</code> if the two models are equal,
+ * <code>false</code> otherwise
+ */
+ public boolean equals(Object object) {
+
+ if (object == null)
+ return false;
+ if (getURL() == null)
+ return false;
+
+ if (!(object instanceof SiteFeature))
+ return false;
+
+ SiteFeature f = (SiteFeature) object;
+
+ return sameURL(getURL(), f.getURL());
+ }
+
+ /**
+ * Returns the names of categories the referenced feature belongs to.
+ *
+ * @return an array of names, or an empty array.
+ */
+ public String[] getCategoryNames() {
+ if (categoryNames == null)
+ return new String[0];
+
+ return (String[]) categoryNames.toArray(new String[0]);
+ }
+
+ /**
+ * Returns the feature identifier as a string
+ *
+ * @return feature identifier
+ */
+ public String getFeatureIdentifier() {
+ return featureId;
+ }
+
+ /**
+ * Returns the feature version as a string
+ *
+ * @return feature version
+ */
+ public String getFeatureVersion() {
+ return featureVersion;
+ }
+
+ /**
+ * Retrieve the displayable label for the feature reference. If the model
+ * object has been resolved, the label is localized.
+ *
+ * @return displayable label, or <code>null</code>.
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Retrieve the non-localized displayable label for the feature reference.
+ *
+ * @return non-localized displayable label, or <code>null</code>.
+ */
+ public String getLabelNonLocalized() {
+ return label;
+ }
+
+ /**
+ * Get optional locale specification as a comma-separated string.
+ *
+ * @return the locale specification string, or <code>null</code>.
+ */
+ public String getNL() {
+ return nl;
+ }
+
+ /**
+ * Get optional operating system specification as a comma-separated string.
+ *
+ * @return the operating system specification string, or <code>null</code>.
+ */
+ public String getOS() {
+ return os;
+ }
+
+ /**
+ * Get optional system architecture specification as a comma-separated string.
+ *
+ * @return the system architecture specification string, or <code>null</code>.
+ */
+ public String getOSArch() {
+ return arch;
+ }
+
+ /**
+ * Returns the patch mode.
+ */
+ public String getPatch() {
+ return patch;
+ }
+
+ /**
+ * Returns the site model for the reference.
+ *
+ * @return site model
+ * @since 2.0
+ */
+ public SiteModel getSiteModel() {
+ return site;
+ }
+
+ /**
+ * Returns the referenced feature type.
+ *
+ * @return feature type, or <code>null</code> representing the default
+ * feature type for the site
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the resolved URL for the feature reference.
+ *
+ * @return url string
+ */
+ public URL getURL() {
+ delayedResolve();
+ return url;
+ }
+
+ /**
+ * Returns the unresolved URL string for the reference.
+ *
+ * @return url string
+ */
+ public String getURLString() {
+ return urlString;
+ }
+
+ /**
+ * Get optional windowing system specification as a comma-separated string.
+ *
+ * @return the windowing system specification string, or <code>null</code>.
+ */
+ public String getWS() {
+ return ws;
+ }
+
+ /**
+ * Resolve the model object.
+ * Any URL strings in the model are resolved relative to the
+ * base URL argument. Any translatable strings in the model that are
+ * specified as translation keys are localized using the supplied
+ * resource bundle.
+ *
+ * @param resolveBase URL
+ * @param bundleURL resource bundle URL
+ * @exception MalformedURLException
+ */
+ public void resolve(URL resolveBase, URL bundleURL) throws MalformedURLException {
+ this.base = resolveBase;
+ }
+
+ /**
+ * Sets the system architecture specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param arch system architecture specification as a comma-separated list
+ */
+ public void setArch(String arch) {
+ this.arch = arch;
+ }
+
+ /**
+ * Sets the names of categories this feature belongs to.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param categoryNames an array of category names
+ */
+ public void setCategoryNames(String[] categoryNames) {
+ if (categoryNames == null)
+ this.categoryNames = null;
+ else
+ this.categoryNames = new ArrayList(Arrays.asList(categoryNames));
+ }
+
+ /**
+ * Sets the feature identifier.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param featureId feature identifier
+ */
+ public void setFeatureIdentifier(String featureId) {
+ this.featureId = featureId;
+ }
+
+ /**
+ * Sets the feature version.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param featureVersion feature version
+ */
+ public void setFeatureVersion(String featureVersion) {
+ this.featureVersion = featureVersion;
+ }
+
+ /**
+ * Sets the label.
+ * @param label The label to set
+ */
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Sets the locale specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param nl locale specification as a comma-separated list
+ */
+ public void setNL(String nl) {
+ this.nl = nl;
+ }
+
+ /**
+ * Sets the operating system specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param os operating system specification as a comma-separated list
+ */
+ public void setOS(String os) {
+ this.os = os;
+ }
+
+ /**
+ * Sets the patch mode.
+ */
+ public void setPatch(String patch) {
+ this.patch = patch;
+ }
+
+ /**
+ * Sets the site for the referenced.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param site site for the reference
+ */
+ public void setSiteModel(SiteModel site) {
+ this.site = site;
+ }
+
+ /**
+ * Sets the referenced feature type.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param type referenced feature type
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Sets the unresolved URL for the feature reference.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param urlString unresolved URL string
+ */
+ public void setURLString(String urlString) {
+ this.urlString = urlString;
+ this.url = null;
+ }
+
+ /**
+ * Sets the windowing system specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param ws windowing system specification as a comma-separated list
+ */
+ public void setWS(String ws) {
+ this.ws = ws;
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(getClass().toString() + " :"); //$NON-NLS-1$
+ buffer.append(" at "); //$NON-NLS-1$
+ if (url != null)
+ buffer.append(url.toExternalForm());
+ return buffer.toString();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteModel.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteModel.java
new file mode 100644
index 000000000..8d5da13da
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/SiteModel.java
@@ -0,0 +1,312 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * A model of an update site.
+ *
+ * Copied from org.eclipse.update.core.model.SiteModel.
+ */
+public class SiteModel {
+
+ private List /*of ArchiveReferenceModel*/archiveReferences;
+ /**
+ * Map of String (category id) -> SiteCategory
+ */
+ private Map categories;
+ private URLEntry description;
+ /**
+ * Map of String (feature id) -> SiteFeature
+ */
+ private List features;
+ private URL locationURL;
+ private String locationURLString;
+ private List /* of URLEntry */mirrors;
+ private String mirrorsURLString;
+ private boolean supportsPack200;
+ private String type;
+
+ /**
+ * Creates an uninitialized site model object.
+ *
+ * @since 2.0
+ */
+ public SiteModel() {
+ super();
+ }
+
+ /**
+ * Adds an archive reference model to site.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param archiveReference archive reference model
+ * @since 2.0
+ */
+ public void addArchive(URLEntry archiveReference) {
+ if (this.archiveReferences == null)
+ this.archiveReferences = new ArrayList();
+ if (!this.archiveReferences.contains(archiveReference))
+ this.archiveReferences.add(archiveReference);
+ }
+
+ /**
+ * Adds a category to the site.
+ *
+ * @param category category model
+ */
+ public void addCategory(SiteCategory category) {
+ if (categories == null)
+ categories = new HashMap();
+ if (!categories.containsKey(category.getName()))
+ categories.put(category.getName(), category);
+ }
+
+ /**
+ * Adds a feature reference model to site.
+ *
+ * @param featureReference feature reference model
+ */
+ public void addFeature(SiteFeature featureReference) {
+ if (this.features == null)
+ this.features = new ArrayList();
+ this.features.add(featureReference);
+ }
+
+ /**
+ * Adds a mirror site.
+ *
+ * @param mirror mirror model
+ * @since 3.1
+ */
+ public void addMirror(URLEntry mirror) {
+ if (this.mirrors == null)
+ this.mirrors = new ArrayList();
+ if (!this.mirrors.contains(mirror))
+ this.mirrors.add(mirror);
+ }
+
+ private void doSetMirrorSiteEntryModels(URLEntry[] newMirrors) {
+ if (newMirrors == null || newMirrors.length == 0)
+ this.mirrors = null;
+ else
+ this.mirrors = new ArrayList(Arrays.asList(newMirrors));
+ }
+
+ /**
+ * Returns an array of plug-in and non-plug-in archive reference models
+ * on this site
+ *
+ * @return an array of archive reference models, or an empty array if there are
+ * no archives known to this site.
+ * @since 2.0
+ */
+ public URLEntry[] getArchives() {
+ if (archiveReferences == null || archiveReferences.size() == 0)
+ return new URLEntry[0];
+
+ return (URLEntry[]) archiveReferences.toArray(new URLEntry[0]);
+ }
+
+ /**
+ * Returns an array of category models for this site.
+ *
+ * @return array of site category models, or an empty array.
+ * @since 2.0
+ */
+ public SiteCategory[] getCategories() {
+ if (categories == null || categories.size() == 0)
+ return new SiteCategory[0];
+ return (SiteCategory[]) categories.values().toArray(new SiteCategory[0]);
+ }
+
+ /**
+ * Returns the category with the given name.
+ * @return the category with the given name, or <code>null</code>
+ */
+ public SiteCategory getCategory(String name) {
+ return (SiteCategory) (categories == null ? null : categories.get(name));
+ }
+
+ /**
+ * Returns the site description.
+ *
+ * @return site description, or <code>null</code>.
+ */
+ public URLEntry getDescription() {
+ return description;
+ }
+
+ /**
+ * Returns an array of feature reference models on this site.
+ *
+ * @return an array of feature reference models, or an empty array.
+ */
+ public SiteFeature[] getFeatures() {
+ if (features == null || features.size() == 0)
+ return new SiteFeature[0];
+ return (SiteFeature[]) features.toArray(new SiteFeature[0]);
+ }
+
+ /**
+ * Returns the resolved URL for the site.
+ *
+ * @return url, or <code>null</code>
+ */
+ public URL getLocationURL() {
+ return locationURL;
+ }
+
+ /**
+ * Returns the unresolved URL string for the site.
+ *
+ * @return url string, or <code>null</code>
+ */
+ public String getLocationURLString() {
+ return locationURLString;
+ }
+
+ /**
+ * Return an array of update site mirrors
+ *
+ * @return an array of mirror entries, or an empty array.
+ * @since 3.1
+ */
+ public URLEntry[] getMirrors() {
+ //delayedResolve(); no delay;
+ if (mirrors == null || mirrors.size() == 0)
+ // see if we can get mirrors from the provided url
+ if (mirrorsURLString != null)
+ doSetMirrorSiteEntryModels(DefaultSiteParser.getMirrors(mirrorsURLString));
+
+ if (mirrors == null || mirrors.size() == 0)
+ return new URLEntry[0];
+ return (URLEntry[]) mirrors.toArray(new URLEntry[0]);
+ }
+
+ /**
+ * Returns the URL from which the list of mirrors of this site can be retrieved.
+ *
+ * @since org.eclipse.equinox.p2.metadata.generator 1.0
+ */
+ public String getMirrorsURL() {
+ return mirrorsURLString;
+ }
+
+ /**
+ * Returns the site type.
+ *
+ * @return site type, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getType() {
+ return type;
+ }
+
+ public boolean isPack200Supported() {
+ return supportsPack200;
+ }
+
+ /**
+ * Resolve the model object.
+ * Any URL strings in the model are resolved relative to the
+ * base URL argument. Any translatable strings in the model that are
+ * specified as translation keys are localized using the supplied
+ * resource bundle.
+ *
+ * @param base URL
+ * @param bundleURL resource bundle URL
+ * @exception MalformedURLException
+ * @since 2.0
+ */
+ public void resolve(URL base, URL bundleURL) throws MalformedURLException {
+
+ // Archives and feature are relative to location URL
+ // if the Site element has a URL tag: see spec
+ // locationURL = resolveURL(base, bundleURL, getLocationURLString());
+ // if (locationURL == null)
+ // locationURL = base;
+ // resolveListReference(getFeatureReferenceModels(), locationURL, bundleURL);
+ // resolveListReference(getArchiveReferenceModels(), locationURL, bundleURL);
+ //
+ // resolveReference(getDescriptionModel(), base, bundleURL);
+ // resolveListReference(getCategoryModels(), base, bundleURL);
+ //
+ // URL url = resolveURL(base, bundleURL, mirrorsURLString);
+ // if (url != null)
+ // mirrorsURLString = url.toString();
+ //
+ // if ((this instanceof ExtendedSite) && ((ExtendedSite) this).isDigestExist()) {
+ // ExtendedSite extendedSite = (ExtendedSite) this;
+ // extendedSite.setLiteFeatures(UpdateManagerUtils.getLightFeatures(extendedSite));
+ // }
+ }
+
+ /**
+ * Sets the site description.
+ *
+ * @param description site description
+ * @since 2.0
+ */
+ public void setDescription(URLEntry description) {
+ this.description = description;
+ }
+
+ /**
+ * Sets the unresolved URL for the site.
+ *
+ * @param locationURLString url for the site (as a string)
+ * @since 2.0
+ */
+ public void setLocationURLString(String locationURLString) {
+ this.locationURLString = locationURLString;
+ }
+
+ /**
+ * Sets additional mirror sites
+ *
+ * @param mirrors additional update site mirrors
+ * @since 3.1
+ */
+ public void setMirrors(URLEntry[] mirrors) {
+ doSetMirrorSiteEntryModels(mirrors);
+ }
+
+ /**
+ * Sets the mirrors url. Mirror sites will then be obtained from this mirror url later.
+ * This method is complementary to setMirrorsiteEntryModels(), and only one of these
+ * methods should be called.
+ *
+ * @param mirrorsURL additional update site mirrors
+ * @since 3.1
+ */
+ public void setMirrorsURLString(String mirrorsURL) {
+ this.mirrorsURLString = mirrorsURL;
+ }
+
+ public void setSupportsPack200(boolean value) {
+ this.supportsPack200 = value;
+ }
+
+ /**
+ * Sets the site type.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param type site type
+ * @since 2.0
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/URLEntry.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/URLEntry.java
new file mode 100644
index 000000000..343222328
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/URLEntry.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.equinox.internal.p2.publisher.features;
+
+public class URLEntry {
+ private String annotation;
+ private String url;
+
+ public URLEntry() {
+ }
+
+ public URLEntry(String url, String annotation) {
+ this.url = url;
+ this.annotation = annotation;
+ }
+
+ public void setAnnotation(String annotation) {
+ this.annotation = annotation;
+ }
+
+ public String getAnnotation() {
+ return annotation;
+ }
+
+ public void setURL(String url) {
+ this.url = url;
+ }
+
+ public String getURL() {
+ return url;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/messages.properties b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/messages.properties
new file mode 100644
index 000000000..052ad26c2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/messages.properties
@@ -0,0 +1,30 @@
+###############################################################################
+# Copyright (c) 2000, 2007 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+# Install Update Core Properties File
+#
+
+DefaultFeatureParser_IdOrVersionInvalid= Error parsing feature stream. The unique identifier or the version is null or empty for the State: \"{2}\": unique identifier=\"{0}\" version=\"{1}\".
+DefaultSiteParser_NoSiteTag= Error parsing site stream. Unable to find root element \"site\" in the stream.
+DefaultSiteParser_WrongParsingStack= Internal Error parsing site stream. Unexpected Parsing Stack: \"{0}\"
+DefaultSiteParser_UnknownElement= Error parsing site stream. Unknown element \"{0}\" in parsing state \"{1}\". Check the validity of the XML file.
+DefaultSiteParser_UnknownStartState= Internal Error parsing site stream. Unknown start state \"{0}\".
+DefaultSiteParser_Missing= Error parsing site stream. The \"{0}\" tag of the element \"{1}\" is null or empty. Value is required.
+DefaultSiteParser_ParsingStackBackToInitialState= Internal Error parsing site stream. Parsing stack back to Initial State.
+DefaultSiteParser_ElementAlreadySet= Error parsing site stream. Element: \"{0}\" already set for the Site.
+DefaultSiteParser_CategoryAlreadySet= Error parsing site stream. Element: \"{0}\": \"{1}\" already set for the Site.
+DefaultSiteParser_UnknownEndState= Internal Error parsing site stream. Unknown end state \"{0}\".
+DefaultSiteParser_ErrorParsing= Error Parsing site stream. Error: \"{0}\"
+DefaultSiteParser_ErrorlineColumnMessage= Error Parsing site stream. Element \"{0}\" line: \"{1}\" column:\"{2}\". Error: \"{3}\".
+DefaultSiteParser_ErrorParsingSite= Error Parsing site stream.
+DefaultSiteParser_UnknownState= Unknown State \"{0}\".
+DefaultSiteParser_InvalidXMLStream= The XML stream is not a valid default \"site.xml\" file. The root tag is not site.
+DefaultSiteParser_mirrors = Error processing update site mirror.
+
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties
new file mode 100644
index 000000000..08affcbdc
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/messages.properties
@@ -0,0 +1,23 @@
+###############################################################################
+# Copyright (c) 2007, 2008 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+# IBM Corporation - initial API and implementation
+###############################################################################
+exception_errorConverting = An error occurred while generating manifest for {0}.
+exception_outputStream = Unable to open output stream for {0}.
+exception_errorParsingUpdateSite = Error parsing update site: {0}.
+exception_stateAddition = An error has occurred while adding the bundle {0}.
+exception_sourceDirectoryInvalid = Source directory is invalid: {0}.
+exception_artifactRepoLocationURL = Artifact repository location is not a valid URL: {0}.
+exception_artifactRepoNotWritable = Artifact repository is not writable: {0}.
+exception_metadataRepoLocationURL = Metadata repository location is not a valid URL: {0}.
+exception_metadataRepoNotWritable = Metadata repository not writable: {0}.
+exception_baseLocationNotSpecified = Eclipse base location not specified.
+
+message_generatingMetadata = Generating metadata for {0}.
+message_generationCompleted = Generation completed with success [{0} seconds]. \ No newline at end of file

Back to the top