Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2')
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java114
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/BundleDescriptionFactory.java69
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherInfo.java7
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/MetadataGeneratorHelper.java206
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/Publisher.java101
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/PublisherResult.java37
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/AccumulateConfigDataAction.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/BundlesAction.java53
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/ConfigCUsAction.java23
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EclipseInstallAction.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/EquinoxExecutableAction.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/FeaturesAction.java168
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IBundleAdvice.java25
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IFeatureAdvice.java26
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/LocalUpdateSiteAction.java81
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootFilesAction.java2
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/SiteXMLAction.java (renamed from bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/UpdateSiteAction.java)54
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/Messages.java4
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/UpdateSite.java374
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/messages.properties4
21 files changed, 1006 insertions, 350 deletions
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java
index 65f75c199..1ad567f24 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/AbstractPublisherApplication.java
@@ -12,7 +12,6 @@ package org.eclipse.equinox.internal.p2.publisher;
import java.io.File;
import java.net.MalformedURLException;
-import java.net.URL;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.equinox.app.IApplicationContext;
@@ -20,12 +19,9 @@ import org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRepositoryMan
import org.eclipse.equinox.internal.p2.core.ProvisioningEventBus;
import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
import org.eclipse.equinox.internal.p2.metadata.repository.MetadataRepositoryManager;
-import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.IProvisioningEventBus;
-import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
-import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.ServiceRegistration;
@@ -56,110 +52,32 @@ public abstract class AbstractPublisherApplication implements IApplication {
protected String artifactLocation;
protected String artifactRepoName;
//whether repository xml files should be compressed
- protected String compress = "false"; //$NON-NLS-1$
+ protected boolean compress = false;
protected boolean inplace = false;
protected boolean append = false;
protected boolean reusePackedFiles = false;
protected String[] configurations;
protected void initialize(PublisherInfo info) throws ProvisionException {
- if (inplace)
- initializeForInplace(info);
- else
- info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_INDEX | IPublisherInfo.A_PUBLISH | IPublisherInfo.A_OVERWRITE);
- initializeRepositories(info);
- }
-
- protected void initializeArtifactRepository(PublisherInfo info) throws ProvisionException {
- IArtifactRepositoryManager manager = (IArtifactRepositoryManager) ServiceHelper.getService(Activator.context, IArtifactRepositoryManager.class.getName());
- URL location;
- try {
- location = new URL(artifactLocation);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(NLS.bind(Messages.exception_artifactRepoLocationURL, artifactLocation));
- }
- try {
- IArtifactRepository repository = manager.loadRepository(location, null);
- if (!repository.isModifiable())
- throw new IllegalArgumentException(NLS.bind(Messages.exception_artifactRepoNotWritable, location));
- info.setArtifactRepository(repository);
- if (reusePackedFiles)
- repository.setProperty(PUBLISH_PACK_FILES_AS_SIBLINGS, "true"); //$NON-NLS-1$
- if (!append)
- repository.removeAll();
- return;
- } catch (ProvisionException e) {
- //fall through and create a new repository
- }
-
- // the given repo location is not an existing repo so we have to create something
- // TODO for now create a Simple repo by default.
- String repositoryName = artifactRepoName != null ? artifactRepoName : artifactLocation + " - artifacts"; //$NON-NLS-1$
- IArtifactRepository result = manager.createRepository(location, repositoryName, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY);
- manager.addRepository(result.getLocation());
if (inplace) {
- // TODO there must be something we have to do to set up the mapping rules here...
- }
- result.setProperty(IRepository.PROP_COMPRESSED, compress);
- if (reusePackedFiles)
- result.setProperty(PUBLISH_PACK_FILES_AS_SIBLINGS, "true"); //$NON-NLS-1$
- if (artifactRepoName != null)
- result.setName(artifactRepoName);
- info.setArtifactRepository(result);
- }
-
- protected void initializeForInplace(PublisherInfo info) {
- File location = new File(source);
- try {
- if (metadataLocation == null)
- metadataLocation = location.toURL().toExternalForm();
- if (artifactLocation == null)
- artifactLocation = location.toURL().toExternalForm();
- } catch (MalformedURLException e) {
- // ought not happen...
- }
- info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_INDEX | IPublisherInfo.A_PUBLISH);
- }
-
- protected void initializeMetadataRepository(PublisherInfo info) throws ProvisionException {
- URL location;
- try {
- location = new URL(metadataLocation);
- } catch (MalformedURLException e) {
- throw new IllegalArgumentException(NLS.bind(Messages.exception_metadataRepoLocationURL, artifactLocation));
- }
- IMetadataRepositoryManager manager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.context, IMetadataRepositoryManager.class.getName());
- try {
- IMetadataRepository repository = manager.loadRepository(location, null);
- if (repository != null) {
- repository.setProperty(IRepository.PROP_COMPRESSED, compress);
- if (!repository.isModifiable())
- throw new IllegalArgumentException(NLS.bind(Messages.exception_metadataRepoNotWritable, location));
- info.setMetadataRepository(repository);
- if (!append)
- repository.removeAll();
- return;
+ File location = new File(source);
+ try {
+ if (metadataLocation == null)
+ metadataLocation = location.toURL().toExternalForm();
+ if (artifactLocation == null)
+ artifactLocation = location.toURL().toExternalForm();
+ } catch (MalformedURLException e) {
+ // ought not happen...
}
- } catch (ProvisionException e) {
- //fall through and create a new repository
- }
-
- // the given repo location is not an existing repo so we have to create something
- // TODO for now create a random repo by default.
- String repositoryName = metadataRepoName == null ? metadataLocation + " - metadata" : metadataRepoName; //$NON-NLS-1$
- IMetadataRepository result = manager.createRepository(location, repositoryName, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY);
- manager.addRepository(result.getLocation());
- if (result != null) {
- result.setProperty(IRepository.PROP_COMPRESSED, compress);
- if (metadataRepoName != null)
- result.setName(metadataRepoName);
- info.setMetadataRepository(result);
- }
+ info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_INDEX | IPublisherInfo.A_PUBLISH);
+ } else
+ info.setArtifactOptions(info.getArtifactOptions() | IPublisherInfo.A_INDEX | IPublisherInfo.A_PUBLISH | IPublisherInfo.A_OVERWRITE);
+ initializeRepositories(info);
}
protected void initializeRepositories(PublisherInfo info) throws ProvisionException {
- initializeArtifactRepository(info);
- initializeMetadataRepository(info);
+ info.setArtifactRepository(Publisher.createArtifactRepository(artifactLocation, artifactRepoName, append, compress, reusePackedFiles));
+ info.setMetadataRepository(Publisher.createMetadataRepository(metadataLocation, metadataRepoName, append, compress));
}
protected void processCommandLineArguments(String[] args, PublisherInfo info) throws Exception {
@@ -211,7 +129,7 @@ public abstract class AbstractPublisherApplication implements IApplication {
append = true;
if (arg.equalsIgnoreCase("-compress")) //$NON-NLS-1$
- compress = "true"; //$NON-NLS-1$
+ compress = true;
if (arg.equalsIgnoreCase("-reusePack200Files")) //$NON-NLS-1$
reusePackedFiles = true;
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
index 776e78252..6190447b8 100644
--- 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
@@ -12,17 +12,18 @@ package org.eclipse.equinox.internal.p2.publisher;
import java.io.*;
import java.util.*;
-import java.util.jar.*;
+import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
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.BundleContext;
import org.osgi.framework.BundleException;
public class BundleDescriptionFactory {
@@ -44,6 +45,13 @@ public class BundleDescriptionFactory {
StateObjectFactory factory;
State state;
+ public static BundleDescriptionFactory getBundleDescriptionFactory(BundleContext context) {
+ PlatformAdmin platformAdmin = (PlatformAdmin) ServiceHelper.getService(context, PlatformAdmin.class.getName());
+ if (platformAdmin == null)
+ throw new IllegalStateException("PlatformAdmin not registered."); //$NON-NLS-1$
+ return new BundleDescriptionFactory(platformAdmin.getFactory(), null);
+ }
+
public BundleDescriptionFactory(StateObjectFactory factory, State state) {
this.factory = factory;
this.state = state;
@@ -58,18 +66,20 @@ public class BundleDescriptionFactory {
PluginConverter converter;
try {
converter = acquirePluginConverter();
- if (converter == null)
+ if (converter == null) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Unable to aquire PluginConverter service during generation for: " + bundleLocation));
return null;
+ }
return converter.convertManifest(bundleLocation, false, null, true, null);
} catch (PluginConversionException convertException) {
+ // only log the exception if we had a plugin.xml or fragment.xml and we failed conversion
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
+ LogHelper.log(status);
}
return null;
}
@@ -81,9 +91,9 @@ public class BundleDescriptionFactory {
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));
+ String message = NLS.bind(Messages.exception_stateAddition, bundleLocation == null ? null : bundleLocation.getAbsoluteFile());
+ IStatus status = new Status(IStatus.WARNING, Activator.ID, message, e);
+ LogHelper.log(status);
return null;
}
}
@@ -101,11 +111,13 @@ public class BundleDescriptionFactory {
ManifestElement.parseBundleManifest(manifestStream, entries);
return getBundleDescription(entries, bundleLocation);
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ String message = "An error occurred while reading the bundle description.";
+ IStatus status = new Status(IStatus.ERROR, Activator.ID, message, e);
+ LogHelper.log(status);
} catch (BundleException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ String message = "An error occurred while reading the bundle description.";
+ IStatus status = new Status(IStatus.ERROR, Activator.ID, message, e);
+ LogHelper.log(status);
}
return null;
}
@@ -121,25 +133,30 @@ public class BundleDescriptionFactory {
manifestStream = jarFile.getInputStream(manifestEntry);
}
} else {
- manifestStream = new BufferedInputStream(new FileInputStream(new File(bundleLocation, JarFile.MANIFEST_NAME)));
+ File manifestFile = new File(bundleLocation, JarFile.MANIFEST_NAME);
+ if (manifestFile.exists())
+ manifestStream = new BufferedInputStream(new FileInputStream(manifestFile));
}
} catch (IOException e) {
- //ignore
+ //ignore but log
+ LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "An error occurred while loading the bundle manifest.", e));
}
Dictionary manifest = null;
if (manifestStream != null) {
try {
- manifest = manifestToProperties(new Manifest(manifestStream).getMainAttributes());
- } catch (IOException ioe) {
+ Map manifestMap = ManifestElement.parseBundleManifest(manifestStream, null);
+ // TODO temporary hack. We are reading a Map but everyone wants a Dictionary so convert.
+ // real answer is to have people expect a Map but that is a wider change.
+ manifest = new Hashtable(manifestMap);
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "An error occurred while loading the bundle manifest.", e));
+ return null;
+ } catch (BundleException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "An error occurred while loading the bundle manifest.", e));
return null;
} finally {
try {
- manifestStream.close();
- } catch (IOException e1) {
- //Ignore
- }
- try {
if (jarFile != null)
jarFile.close();
} catch (IOException e2) {
@@ -157,6 +174,8 @@ public class BundleDescriptionFactory {
if (manifest.get(org.osgi.framework.Constants.BUNDLE_SYMBOLICNAME) == null)
manifest = convertPluginManifest(bundleLocation, true);
+ if (manifest == null)
+ return null;
// 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);
@@ -344,12 +363,4 @@ public class BundleDescriptionFactory {
// 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/IPublisherInfo.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/IPublisherInfo.java
index caba82ba6..17e29827a 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
@@ -34,6 +34,13 @@ public interface IPublisherInfo {
public static final int A_OVERWRITE = 4;
/**
+ * A bitwise flag to say whether or not to leave the disk content discovered
+ * as is when publishing an artifact. That is, if a directory is discovered, it is
+ * left as a directory.
+ */
+ public static final int A_AS_IS = 8;
+
+ /**
* 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>
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java
index bc47ceec0..f2f3b276e 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/InstallPublisherApplication.java
@@ -20,7 +20,7 @@ public class InstallPublisherApplication extends AbstractPublisherApplication {
protected String flavor;
protected String[] topLevel;
protected boolean start;
- private String[] rootExclusions;
+ protected String[] rootExclusions;
public InstallPublisherApplication() {
}
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
index 583f95eb5..fb3c73aba 100644
--- 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
@@ -39,6 +39,7 @@ public class MetadataGeneratorHelper {
/**
* A capability namespace representing the type of Eclipse resource (bundle, feature, source bundle, etc)
* @see RequiredCapability#getNamespace()
+ * @see ProvidedCapability#getNamespace()
*/
public static final String NAMESPACE_ECLIPSE_TYPE = "org.eclipse.equinox.p2.eclipse.type"; //$NON-NLS-1$
@@ -46,6 +47,7 @@ public class MetadataGeneratorHelper {
* A capability name in the {@link #NAMESPACE_ECLIPSE_TYPE} namespace
* representing and OSGi bundle resource
* @see RequiredCapability#getName()
+ * @see ProvidedCapability#getName()
*/
public static final String TYPE_ECLIPSE_BUNDLE = "bundle"; //$NON-NLS-1$
/**
@@ -63,11 +65,13 @@ public class MetadataGeneratorHelper {
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()
+ * A capability namespace representing the localization (translation)
+ * of strings from a specified IU in a specified locale
+ * @see RequiredCapability#getNamespace()
+ * @see ProvidedCapability#getNamespace()
+ * TODO: this should be in API, probably in IInstallableUnit
*/
- public static final String TYPE_ECLIPSE_MANIFEST_LOCALIZATION = "manifest.localization"; //$NON-NLS-1$
+ public static final String NAMESPACE_IU_LOCALIZATION = "org.eclipse.equinox.p2.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};
@@ -79,7 +83,7 @@ public class MetadataGeneratorHelper {
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$
+ public 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$
@@ -89,11 +93,11 @@ public class MetadataGeneratorHelper {
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;
+ public 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$
+ public 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);
@@ -106,7 +110,6 @@ public class MetadataGeneratorHelper {
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$
@@ -115,7 +118,7 @@ public class MetadataGeneratorHelper {
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) {
+ public static IArtifactDescriptor createArtifactDescriptor(IArtifactKey key, File pathOnDisk) {
//TODO this size calculation is bogus
ArtifactDescriptor result = new ArtifactDescriptor(key);
if (pathOnDisk != null) {
@@ -189,23 +192,16 @@ public class MetadataGeneratorHelper {
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);
-
+ public static IInstallableUnit createBundleIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key) {
+ Map manifestLocalizations = null;
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));
- }
+ manifestLocalizations = getManifestLocalizations(manifest, new File(bd.getLocation()));
}
- return bundleIU;
+
+ return createBundleIU(bd, manifest, isFolderPlugin, key, manifestLocalizations);
}
- public static IInstallableUnit createBundleIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key) {
+ public static IInstallableUnit createBundleIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key, Map manifestLocalizations) {
boolean isBinaryBundle = true;
if (manifest != null && manifest.containsKey("Eclipse-SourceBundle")) { //$NON-NLS-1$
isBinaryBundle = false;
@@ -266,6 +262,20 @@ public class MetadataGeneratorHelper {
if (isFragment)
providedCapabilities.add(MetadataFactory.createProvidedCapability(CAPABILITY_NS_OSGI_FRAGMENT, bd.getHost().getName(), bd.getVersion()));
+
+ if (manifestLocalizations != null) {
+ for (Iterator iter = manifestLocalizations.keySet().iterator(); iter.hasNext();) {
+ Locale locale = (Locale) iter.next();
+ Properties translatedStrings = (Properties) manifestLocalizations.get(locale);
+ Enumeration propertyKeys = translatedStrings.propertyNames();
+ while (propertyKeys.hasMoreElements()) {
+ String nextKey = (String) propertyKeys.nextElement();
+ iu.setProperty(locale.toString() + '.' + nextKey, translatedStrings.getProperty(nextKey));
+ }
+ providedCapabilities.add(makeTranslationCapability(bd.getSymbolicName(), locale));
+ }
+ }
+
iu.setCapabilities((ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()]));
iu.setArtifacts(new IArtifactKey[] {key});
@@ -300,56 +310,11 @@ public class MetadataGeneratorHelper {
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) {
+ public static void createHostLocalizationFragment(IInstallableUnit bundleIU, 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);
+ if (hostLocalizations != null) {
+ IInstallableUnitFragment localizationFragment = createLocalizationFragmentOfHost(bd, hostId, hostBundleManifestValues, hostLocalizations);
+ localizationIUs.add(localizationFragment);
}
}
@@ -360,29 +325,32 @@ public class MetadataGeneratorHelper {
* @param localizedStrings
* @return installableUnitFragment
*/
- private static IInstallableUnitFragment createLocalizationFragmentOfHost(String hostId, String[] hostManifestValues, BundleDescription bd, Locale locale, Properties localizedStrings) {
+ private static IInstallableUnitFragment createLocalizationFragmentOfHost(BundleDescription bd, String hostId, String[] hostManifestValues, Map hostLocalizations) {
InstallableUnitFragmentDescription fragment = new MetadataFactory.InstallableUnitFragmentDescription();
- HostSpecification hostSpec = bd.getHost();
- String fragmentId = makeLocalizationFragmentId(hostId, locale);
+ String fragmentId = makeHostLocalizationFragmentId(bd.getSymbolicName());
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)};
+ HostSpecification hostSpec = bd.getHost();
+ RequiredCapability[] hostReqs = new RequiredCapability[] {MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, hostSpec.getName(), hostSpec.getVersionRange(), null, false, false, false)};
fragment.setHost(hostReqs);
fragment.setSingleton(true);
+ fragment.setProperty(IInstallableUnit.PROP_TYPE_FRAGMENT, Boolean.TRUE.toString());
- 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);
+ // Create a provided capability for each locale and add the translated properties.
+ ArrayList providedCapabilities = new ArrayList(hostLocalizations.keySet().size());
+ for (Iterator iter = hostLocalizations.keySet().iterator(); iter.hasNext();) {
+ Locale locale = (Locale) iter.next();
+ Properties translatedStrings = (Properties) hostLocalizations.get(locale);
+
+ Enumeration propertyKeys = translatedStrings.propertyNames();
+ while (propertyKeys.hasMoreElements()) {
+ String nextKey = (String) propertyKeys.nextElement();
+ fragment.setProperty(locale.toString() + '.' + nextKey, translatedStrings.getProperty(nextKey));
}
+ providedCapabilities.add(makeTranslationCapability(hostId, locale));
}
- // 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);
@@ -390,14 +358,23 @@ public class MetadataGeneratorHelper {
/**
* @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.
+ * @return the id for the iu fragment containing the localized properties
+ * for the bundle with the given id
*/
- 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$
+ // private static String makeBundleLocalizationFragmentId(String id) {
+ // return id + ".translated_properties"; //$NON-NLS-1$
+ // }
+ /**
+ * @param id
+ * @return the id for the iu fragment containing localized properties
+ * for the fragment with the given id.
+ */
+ private static String makeHostLocalizationFragmentId(String id) {
+ return id + ".translated_host_properties"; //$NON-NLS-1$
+ }
+
+ private static ProvidedCapability makeTranslationCapability(String hostId, Locale locale) {
+ return MetadataFactory.createProvidedCapability(NAMESPACE_IU_LOCALIZATION, locale.toString(), new Version(1, 0, 0));
}
/**
@@ -546,41 +523,25 @@ public class MetadataGeneratorHelper {
}
public static IInstallableUnit[] createEclipseIU(BundleDescription bd, Map manifest, boolean isFolderPlugin, IArtifactKey key, Properties extraProperties) {
- ArrayList iusCreated = new ArrayList(4);
+ ArrayList iusCreated = new ArrayList(1);
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()]));
}
+ /**
+ * @deprecated
+ */
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);
- }
-
+ /**
+ * @deprecated
+ */
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);
@@ -643,12 +604,16 @@ public class MetadataGeneratorHelper {
return MetadataFactory.createInstallableUnit(iu);
}
- // moved to FeaturesAction
+ /**
+ * @deprecated moved to FeaturesAction
+ */
public static IInstallableUnit createGroupIU(Feature feature, IInstallableUnit featureIU) {
return createGroupIU(feature, featureIU, null);
}
- // moved to FeaturesAction
+ /**
+ * @deprecated 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);
@@ -734,7 +699,7 @@ public class MetadataGeneratorHelper {
results.addIU(MetadataFactory.createInstallableUnit(cu), IPublisherResult.ROOT);
//Create the artifact descriptor
- return createArtifactDescriptor(key, jreLocation, false, true);
+ return createArtifactDescriptor(key, jreLocation);
}
public static ArtifactKey createLauncherArtifactKey(String id, Version version) {
@@ -792,7 +757,7 @@ public class MetadataGeneratorHelper {
resultantIUs.addIU(MetadataFactory.createInstallableUnitFragment(cu), IPublisherResult.ROOT);
//Create the artifact descriptor
- return createArtifactDescriptor(key, launcher, false, true);
+ return createArtifactDescriptor(key, launcher);
}
public static void generateLauncherSetter(String launcherName, String iuId, Version version, String configSpec, IPublisherResult result) {
@@ -934,8 +899,11 @@ public class MetadataGeneratorHelper {
// TODO should really be returning VersionRange.emptyRange here...
return null;
Version version = new Version(versionSpec);
- if (!entry.isRequires())
+ if (!entry.isRequires()) {
+ if ("0.0.0".equals(entry.getVersion())) //$NON-NLS-1$
+ return VersionRange.emptyRange;
return new VersionRange(version, true, version, true);
+ }
String match = entry.getMatch();
if (match == null)
// TODO should really be returning VersionRange.emptyRange here...
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 b84d08a14..ec9b7878f 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
@@ -9,16 +9,117 @@
******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher;
+import java.net.MalformedURLException;
+import java.net.URL;
import java.util.Collection;
import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+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.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
+import org.eclipse.osgi.util.NLS;
public class Publisher {
+ static final public String PUBLISH_PACK_FILES_AS_SIBLINGS = "publishPackFilesAsSiblings"; //$NON-NLS-1$
private IPublisherInfo info;
private IPublisherResult results;
+ /**
+ * Returns a metadata repository that corresponds to the given settings. If a repo at the
+ * given location already exists, it is updated with the settings and returned. If no repository
+ * is found then a new Simple repository is created, configured and returned
+ * @param location the URL location of the repo
+ * @param name the name of the repo
+ * @param append whether or not the repo should appended or cleared
+ * @param compress whether or not to compress the repository index
+ * @return the discovered or created repository
+ * @throws ProvisionException
+ */
+ public static IMetadataRepository createMetadataRepository(String location, String name, boolean append, boolean compress) throws ProvisionException {
+ URL url;
+ try {
+ url = new URL(location);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(NLS.bind(Messages.exception_metadataRepoLocationURL, location));
+ }
+ IMetadataRepositoryManager manager = (IMetadataRepositoryManager) ServiceHelper.getService(Activator.context, IMetadataRepositoryManager.class.getName());
+ try {
+ IMetadataRepository result = manager.loadRepository(url, null);
+ if (result != null) {
+ result.setProperty(IRepository.PROP_COMPRESSED, compress ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$
+ if (!result.isModifiable())
+ throw new IllegalArgumentException(NLS.bind(Messages.exception_metadataRepoNotWritable, url));
+ if (!append)
+ result.removeAll();
+ return result;
+ }
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+
+ // the given repo location is not an existing repo so we have to create something
+ // TODO for now create a random repo by default.
+ String repositoryName = name == null ? location + " - metadata" : name; //$NON-NLS-1$
+ IMetadataRepository result = manager.createRepository(url, repositoryName, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY);
+ manager.addRepository(result.getLocation());
+ if (result != null)
+ result.setProperty(IRepository.PROP_COMPRESSED, compress ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$
+ return result;
+ }
+
+ /**
+ * Returns an artifact repository that corresponds to the given settings. If a repo at the
+ * given location already exists, it is updated with the settings and returned. If no repository
+ * is found then a new Simple repository is created, configured and returned
+ * @param location the URL location of the repo
+ * @param name the name of the repo
+ * @param append whether or not the repo should appended or cleared
+ * @param compress whether or not to compress the repository index
+ * @param reusePackedFiles whether or not to include discovered Pack200 files in the repository
+ * @return the discovered or created repository
+ * @throws ProvisionException
+ */
+ public static IArtifactRepository createArtifactRepository(String location, String name, boolean append, boolean compress, boolean reusePackedFiles) throws ProvisionException {
+ IArtifactRepositoryManager manager = (IArtifactRepositoryManager) ServiceHelper.getService(Activator.context, IArtifactRepositoryManager.class.getName());
+ URL url;
+ try {
+ url = new URL(location);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(NLS.bind(Messages.exception_artifactRepoLocationURL, location));
+ }
+ try {
+ IArtifactRepository result = manager.loadRepository(url, null);
+ if (!result.isModifiable())
+ throw new IllegalArgumentException(NLS.bind(Messages.exception_artifactRepoNotWritable, url));
+ result.setProperty(IRepository.PROP_COMPRESSED, compress ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$
+ if (reusePackedFiles)
+ result.setProperty(PUBLISH_PACK_FILES_AS_SIBLINGS, "true"); //$NON-NLS-1$
+ if (!append)
+ result.removeAll();
+ return result;
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+
+ // the given repo location is not an existing repo so we have to create something
+ // TODO for now create a Simple repo by default.
+ String repositoryName = name != null ? name : location + " - artifacts"; //$NON-NLS-1$
+ IArtifactRepository result = manager.createRepository(url, repositoryName, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY);
+ manager.addRepository(result.getLocation());
+ // TODO there must be something we have to do to set up the mapping rules here...
+ // if (inplace) {
+ // }
+ result.setProperty(IRepository.PROP_COMPRESSED, compress ? "true" : "false"); //$NON-NLS-1$//$NON-NLS-2$
+ if (reusePackedFiles)
+ result.setProperty(PUBLISH_PACK_FILES_AS_SIBLINGS, "true"); //$NON-NLS-1$
+ return result;
+ }
+
public Publisher(IPublisherInfo info) {
this.info = info;
results = new PublisherResult();
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
index 327f502a7..92c833037 100644
--- 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
@@ -31,23 +31,17 @@ public class PublisherResult implements IPublisherResult {
}
public void addIUs(Collection ius, String type) {
- for (Iterator i = ius.iterator(); i.hasNext();) {
- IInstallableUnit iu = (IInstallableUnit) i.next();
- addIU(iu, type);
- }
+ for (Iterator i = ius.iterator(); i.hasNext();)
+ addIU((IInstallableUnit) i.next(), type);
}
private void addIU(Map map, String id, IInstallableUnit iu) {
- IInstallableUnit[] ius = (IInstallableUnit[]) map.get(id);
+ Set ius = (Set) map.get(id);
if (ius == null) {
- ius = new IInstallableUnit[] {iu};
+ ius = new HashSet(11);
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);
}
+ ius.add(iu);
}
/**
@@ -71,14 +65,14 @@ public class PublisherResult implements IPublisherResult {
// 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];
+ Collection ius = (Collection) rootIUs.get(id);
+ if (ius != null && ius.size() > 0)
+ return (IInstallableUnit) ius.iterator().next();
}
if (type == null || type == NON_ROOT) {
- IInstallableUnit[] ius = (IInstallableUnit[]) nonRootIUs.get(id);
- if (ius != null && ius.length > 0)
- return ius[0];
+ Collection ius = (Collection) nonRootIUs.get(id);
+ if (ius != null && ius.size() > 0)
+ return (IInstallableUnit) ius.iterator().next();
}
return null;
}
@@ -89,14 +83,14 @@ public class PublisherResult implements IPublisherResult {
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)));
+ result.addAll(id == null ? flatten(rootIUs.values()) : (Collection) rootIUs.get(id));
+ result.addAll(id == null ? flatten(nonRootIUs.values()) : (Collection) nonRootIUs.get(id));
return result;
}
if (type == ROOT)
- return id == null ? flatten(rootIUs.values()) : Arrays.asList((Object[]) rootIUs.get(id));
+ return id == null ? flatten(rootIUs.values()) : (Collection) rootIUs.get(id);
if (type == NON_ROOT)
- return id == null ? flatten(nonRootIUs.values()) : Arrays.asList((Object[]) nonRootIUs.get(id));
+ return id == null ? flatten(nonRootIUs.values()) : (Collection) nonRootIUs.get(id);
return null;
}
@@ -111,7 +105,6 @@ public class PublisherResult implements IPublisherResult {
}
public void merge(IPublisherResult result, int mode) {
-
if (mode == MERGE_MATCHING) {
addIUs(result.getIUs(null, ROOT), ROOT);
addIUs(result.getIUs(null, NON_ROOT), NON_ROOT);
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 872bbe63c..95cde20d4 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
@@ -37,6 +37,8 @@ public class AccumulateConfigDataAction extends AbstractPublishingAction {
return;
info.addAdvice(new ConfigAdvice(data, configSpec));
LauncherData launcherData = loader.getLauncherData();
+ if (launcherData == null)
+ return;
info.addAdvice(new LaunchingAdvice(launcherData, configSpec));
}
}
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 205f499a6..e61a7e2c5 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
@@ -16,8 +16,7 @@ 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.artifact.repository.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
import org.eclipse.osgi.service.resolver.*;
@@ -49,20 +48,26 @@ public class BundlesAction extends AbstractPublishingAction {
}
private File[] expandLocations(File[] list) {
- if (list == null)
- return new File[] {};
ArrayList result = new ArrayList();
+ expandLocations(list, result);
+ return (File[]) result.toArray(new File[result.size()]);
+ }
+
+ private void expandLocations(File[] list, ArrayList result) {
+ if (list == null)
+ return;
for (int i = 0; i < list.length; i++) {
File location = list[i];
if (location.isDirectory()) {
- File[] entries = location.listFiles();
- for (int j = 0; j < entries.length; j++)
- result.add(entries[j]);
+ // if the location is itself a bundle, just add it. Otherwise r down
+ if (!new File(location, "META-INF/MANIFEST.MF").exists()) //$NON-NLS-1$
+ expandLocations(location.listFiles(), result);
+ else
+ result.add(location);
} else {
result.add(location);
}
}
- return (File[]) result.toArray(new File[result.size()]);
}
protected void generateBundleIUs(BundleDescription[] bundles, IPublisherResult result, IPublisherInfo info) {
@@ -72,7 +77,6 @@ public class BundlesAction extends AbstractPublishingAction {
// 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++) {
@@ -90,15 +94,18 @@ public class BundlesAction extends AbstractPublishingAction {
}
} else {
IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(bd.getSymbolicName(), bd.getVersion().toString());
- IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(key, new File(bd.getLocation()), true, false);
+ File location = new File(bd.getLocation());
+ IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(key, location);
+ addProperties((ArtifactDescriptor) ad, location, info);
IArtifactRepository destination = info.getArtifactRepository();
// don't consider any advice here as we want to know about the real form on disk
boolean isDir = isDir(bd, info);
- if (isDir)
+ // if the artifact is a dir and we are not doing "AS_IS", zip it up.
+ if (isDir && !((info.getArtifactOptions() & IPublisherInfo.A_AS_IS) > 0))
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);
- IInstallableUnit bundleIU = MetadataGeneratorHelper.createBundleIU(bd, bundleManifest, isDir, key, localizationIUs);
+ IInstallableUnit bundleIU = MetadataGeneratorHelper.createBundleIU(bd, bundleManifest, isDir, key);
if (isFragment(bd)) {
// TODO: Can NL fragments be multi-host? What special handling
@@ -108,7 +115,7 @@ public class BundlesAction extends AbstractPublishingAction {
String[] cachedValues = (String[]) bundleLocalizationMap.get(hostKey);
if (cachedValues != null) {
- MetadataGeneratorHelper.createHostLocalizationFragments(bd, hostId, cachedValues, localizationIUs);
+ MetadataGeneratorHelper.createHostLocalizationFragment(bundleIU, bd, hostId, cachedValues, localizationIUs);
}
}
@@ -121,6 +128,26 @@ public class BundlesAction extends AbstractPublishingAction {
}
}
+ /**
+ * Add all of the advice for the bundle at the given location to the given descriptor.
+ * @param descriptor the descriptor to decorate
+ * @param location the location of the bundle
+ * @param info the publisher info supplying the advice
+ */
+ private void addProperties(ArtifactDescriptor descriptor, File location, IPublisherInfo info) {
+ Collection advice = info.getAdvice(null, false, null, null, IBundleAdvice.class);
+ for (Iterator i = advice.iterator(); i.hasNext();) {
+ IBundleAdvice entry = (IBundleAdvice) i.next();
+ Properties props = entry.getProperties(location);
+ if (props == null)
+ continue;
+ for (Iterator j = props.keySet().iterator(); j.hasNext();) {
+ String key = (String) j.next();
+ descriptor.setRepositoryProperty(key, props.getProperty(key));
+ }
+ }
+ }
+
private boolean isDir(BundleDescription bundle, IPublisherInfo info) {
Collection advice = info.getAdvice(null, true, bundle.getSymbolicName(), bundle.getVersion(), IBundleShapeAdvice.class);
// if the advice has a shape, use it
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 e19a287be..225f4b1c7 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
@@ -19,7 +19,10 @@ import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.provisional.frameworkadmin.BundleInfo;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.internal.provisional.p2.query.Collector;
+import org.eclipse.equinox.internal.provisional.p2.query.Query;
import org.eclipse.osgi.util.ManifestElement;
import org.osgi.framework.*;
@@ -176,7 +179,7 @@ public class ConfigCUsAction extends AbstractPublishingAction {
}
for (int i = 0; i < bundles.length; i++) {
- GeneratorBundleInfo bundle = createGeneratorBundleInfo(bundles[i], result);
+ GeneratorBundleInfo bundle = createGeneratorBundleInfo(info, bundles[i], result);
if (bundle == null)
continue;
@@ -202,7 +205,7 @@ public class ConfigCUsAction extends AbstractPublishingAction {
}
}
- protected GeneratorBundleInfo createGeneratorBundleInfo(BundleInfo bundleInfo, IPublisherResult result) {
+ protected GeneratorBundleInfo createGeneratorBundleInfo(IPublisherInfo info, BundleInfo bundleInfo, IPublisherResult result) {
if (bundleInfo.getLocation() != null)
return new GeneratorBundleInfo(bundleInfo);
@@ -230,6 +233,22 @@ public class ConfigCUsAction extends AbstractPublishingAction {
}
}
+ //Query the repo
+ Query query = new InstallableUnitQuery(name);
+ Collector collector = new Collector();
+ Iterator matches = info.getMetadataRepository().query(query, collector, null).iterator();
+ //pick the newest match
+ IInstallableUnit newest = null;
+ while (matches.hasNext()) {
+ IInstallableUnit candidate = (IInstallableUnit) matches.next();
+ if (newest == null || (newest.getVersion().compareTo(candidate.getVersion()) < 0))
+ newest = candidate;
+ }
+ if (newest != null) {
+ bundleInfo.setVersion(newest.getVersion().toString());
+ return new GeneratorBundleInfo(bundleInfo);
+ }
+
return null;
}
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 c4ec7be9d..5710edb78 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
@@ -112,7 +112,7 @@ public class EclipseInstallAction implements IPublishingAction {
}
protected IPublishingAction createFeaturesAction() {
- return new FeaturesAction(new File[] {new File(source, "features")}, info); //$NON-NLS-1$
+ return new FeaturesAction(new File[] {new File(source, "features")}); //$NON-NLS-1$
}
protected Collection createExecutablesActions(String[] configSpecs) {
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 e54faccc3..6e3a29181 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
@@ -127,7 +127,7 @@ public class EquinoxExecutableAction extends AbstractPublishingAction {
result.addIU(unit, IPublisherResult.ROOT);
//Create the artifact descriptor. we have several files so no path on disk
- IArtifactDescriptor descriptor = MetadataGeneratorHelper.createArtifactDescriptor(key, null, false, true);
+ IArtifactDescriptor descriptor = MetadataGeneratorHelper.createArtifactDescriptor(key, null);
publishArtifact(descriptor, fileList, files.getLocation(), info, INCLUDE_ROOT);
if (files.isTemporary())
FileUtils.deleteAll(files.getLocation());
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 04e0dfdae..d1bd1e37e 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
@@ -15,6 +15,7 @@ import org.eclipse.core.runtime.IStatus;
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.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.publisher.*;
import org.eclipse.equinox.internal.p2.publisher.features.*;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.ArtifactDescriptor;
@@ -29,76 +30,109 @@ import org.osgi.framework.Version;
* be actual locations of the features or folders of features.
*/
public class FeaturesAction extends AbstractPublishingAction {
-
public static final String INSTALL_FEATURES_FILTER = "(org.eclipse.update.install.features=true)"; //$NON-NLS-1$
- private File[] locations;
+ protected Feature[] featureList;
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$
}
- public FeaturesAction(File[] locations, IPublisherInfo info) {
- this.locations = expandLocations(locations);
+ public static IArtifactKey createFeatureArtifactKey(String id, String version) {
+ return new ArtifactKey(MetadataGeneratorHelper.ECLIPSE_FEATURE_CLASSIFIER, id, new Version(version));
+ }
+
+ public FeaturesAction(File[] locations) {
+ featureList = getFeatures(expandLocations(locations));
+ }
+
+ public FeaturesAction(Feature[] featureList) {
+ this.featureList = featureList;
}
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
- Feature[] features = getFeatures(locations);
- generateFeatureIUs(features, results, info);
+ generateFeatureIUs(featureList, results, info);
return Status.OK_STATUS;
}
private File[] expandLocations(File[] list) {
- if (list == null)
- return new File[] {};
ArrayList result = new ArrayList();
+ expandLocations(list, result);
+ return (File[]) result.toArray(new File[result.size()]);
+ }
+
+ private void expandLocations(File[] list, ArrayList result) {
+ if (list == null)
+ return;
for (int i = 0; i < list.length; i++) {
File location = list[i];
if (location.isDirectory()) {
- File[] entries = location.listFiles();
- for (int j = 0; j < entries.length; j++)
- result.add(entries[j]);
+ // if the location is itself a feature, just add it. Otherwise r down
+ if (!new File(location, "feature.xml").exists())
+ expandLocations(location.listFiles(), result);
+ else
+ result.add(location);
} else {
result.add(location);
}
}
- return (File[]) result.toArray(new File[result.size()]);
}
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.
+ // The IU hierarchy must be built from the bottom up so do the root files first.
ArrayList childIUs = generateRootFileIUs(feature, result, info);
+ IInstallableUnit featureIU = createFeatureJarIU(feature, childIUs, info);
+ publishFeatureArtifacts(feature, featureIU, info);
+ gatherBundleShapeAdvice(feature, info);
+ // create the associated group and register the feature and group in the result.
+ IInstallableUnit groupIU = createGroupIU(feature, featureIU, null);
+ result.addIU(groupIU, IPublisherResult.ROOT);
+ result.addIU(featureIU, IPublisherResult.ROOT);
+ }
+ }
- // create the basic feature IU with all the children
- String location = feature.getLocation();
- boolean isExploded = (location.endsWith(".jar") ? false : true); //$NON-NLS-1$
- IInstallableUnit featureIU = MetadataGeneratorHelper.createFeatureJarIU(feature, childIUs, isExploded, null);
-
- // add all the artifacts associated with the feature
- IArtifactKey[] artifacts = featureIU.getArtifacts();
- 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(), info, INCLUDE_ROOT);
- else
- publishArtifact(ad, new File[] {new File(location)}, info, AS_IS | INCLUDE_ROOT);
- }
+ protected IInstallableUnit createFeatureJarIU(Feature feature, ArrayList childIUs, IPublisherInfo info) {
+ // create the basic feature IU with all the children
+ String location = feature.getLocation();
+ boolean isExploded = (location.endsWith(".jar") ? false : true); //$NON-NLS-1$
+ Properties props = getFeatureAdvice(feature, info);
+ IInstallableUnit featureIU = createFeatureJarIU(feature, childIUs, isExploded, props);
+ return featureIU;
+ }
- gatherAdvice(feature, info);
+ protected void publishFeatureArtifacts(Feature feature, IInstallableUnit featureIU, IPublisherInfo info) {
+ // add all the artifacts associated with the feature
+ // TODO this is a little strange. If there are several artifacts, how do we know which files go with
+ // which artifacts when we publish them? For now it would be surprising to have more than one
+ // artifact per feature IU.
+ IArtifactKey[] artifacts = featureIU.getArtifacts();
+ for (int j = 0; j < artifacts.length; j++) {
+ File file = new File(feature.getLocation());
+ IArtifactDescriptor ad = MetadataGeneratorHelper.createArtifactDescriptor(artifacts[j], file);
+ // if the artifact is a dir and we are not doing "AS_IS", zip it up.
+ if (file.isDirectory() && !((info.getArtifactOptions() & IPublisherInfo.A_AS_IS) > 0))
+ publishArtifact(ad, file.listFiles(), info, INCLUDE_ROOT);
+ else
+ publishArtifact(ad, new File[] {file}, info, AS_IS | INCLUDE_ROOT);
+ }
+ }
- // create the associated group and register the feature and group in the result.
- IInstallableUnit generated = createGroupIU(feature, featureIU, null);
- result.addIU(generated, IPublisherResult.ROOT);
- result.addIU(featureIU, IPublisherResult.ROOT);
+ private Properties getFeatureAdvice(Feature feature, IPublisherInfo info) {
+ Properties result = new Properties();
+ Collection advice = info.getAdvice(null, false, null, null, IFeatureAdvice.class);
+ for (Iterator i = advice.iterator(); i.hasNext();) {
+ IFeatureAdvice entry = (IFeatureAdvice) i.next();
+ Properties props = entry.getProperties(feature, null);
+ if (props != null)
+ result.putAll(props);
}
+ return result;
}
- private ArrayList generateRootFileIUs(Feature feature, IPublisherResult result, IPublisherInfo info) {
+ protected 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);
@@ -206,7 +240,7 @@ public class FeaturesAction extends AbstractPublishingAction {
* @param feature the feature to process
* @param info the publishing info to update
*/
- public void gatherAdvice(Feature feature, IPublisherInfo info) {
+ public void gatherBundleShapeAdvice(Feature feature, IPublisherInfo info) {
FeatureEntry entries[] = feature.getEntries();
for (int i = 0; i < entries.length; i++) {
FeatureEntry entry = entries[i];
@@ -215,6 +249,68 @@ public class FeaturesAction extends AbstractPublishingAction {
}
}
+ public 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(MetadataGeneratorHelper.TOUCHPOINT_OSGI);
+ iu.setFilter(INSTALL_FEATURES_FILTER);
+ iu.setSingleton(true);
+
+ if (feature.getInstallHandler() != null && feature.getInstallHandler().trim().length() > 0) {
+ 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(MetadataGeneratorHelper.ECLIPSE_INSTALL_HANDLER_PROP, installHandlerProperty);
+ }
+
+ iu.setCapabilities(new ProvidedCapability[] {MetadataGeneratorHelper.createSelfCapability(id, version), MetadataGeneratorHelper.FEATURE_CAPABILITY, MetadataFactory.createProvidedCapability(MetadataGeneratorHelper.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(MetadataGeneratorHelper.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);
+ }
+
public IInstallableUnit createGroupIU(Feature feature, IInstallableUnit featureIU, Properties extraProperties) {
InstallableUnitDescription iu = new MetadataFactory.InstallableUnitDescription();
String id = getTransformedId(feature.getId(), /*isPlugin*/false, /*isGroup*/true);
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..0f6aa6acb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IBundleAdvice.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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
+ ******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.actions;
+
+import java.io.File;
+import java.util.Properties;
+import org.eclipse.equinox.internal.p2.publisher.IPublishingAdvice;
+
+public interface IBundleAdvice extends IPublishingAdvice {
+
+ /**
+ * Returns the set of extra properties to be associated with the IU for the bundle
+ * at the given location
+ * @param location the location of the feature to advise
+ * @return extra properties for the given feature
+ */
+ public Properties getProperties(File location);
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IFeatureAdvice.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IFeatureAdvice.java
new file mode 100644
index 000000000..d13a82db1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/IFeatureAdvice.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * 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
+ ******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.actions;
+
+import java.io.File;
+import java.util.Properties;
+import org.eclipse.equinox.internal.p2.publisher.IPublishingAdvice;
+import org.eclipse.equinox.internal.p2.publisher.features.Feature;
+
+public interface IFeatureAdvice extends IPublishingAdvice {
+
+ /**
+ * Returns the set of extra properties to be associated with the IU for the feature
+ * at the given location
+ * @param location the location of the feature to advise
+ * @return extra properties for the given feature
+ */
+ public Properties getProperties(Feature feature, File location);
+}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/LocalUpdateSiteAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/LocalUpdateSiteAction.java
new file mode 100644
index 000000000..8f8bf1403
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/LocalUpdateSiteAction.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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
+ ******************************************************************************/
+package org.eclipse.equinox.internal.p2.publisher.actions;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.util.ArrayList;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.p2.publisher.*;
+import org.eclipse.equinox.internal.p2.publisher.features.UpdateSite;
+
+/**
+ * A publishing action that processes a local (File-based) update site and generates
+ * metadata and artifacts for the features, bundles and site index (categories etc).
+ */
+public class LocalUpdateSiteAction implements IPublishingAction {
+ protected String source;
+ private UpdateSite updateSite;
+
+ protected LocalUpdateSiteAction() {
+ }
+
+ public LocalUpdateSiteAction(String source) {
+ this.source = source;
+ }
+
+ public LocalUpdateSiteAction(UpdateSite updateSite) {
+ this.updateSite = updateSite;
+ }
+
+ public IStatus perform(IPublisherInfo info, IPublisherResult results) {
+ IPublishingAction[] actions = createActions();
+ for (int i = 0; i < actions.length; i++)
+ actions[i].perform(info, results);
+ return Status.OK_STATUS;
+ }
+
+ protected IPublishingAction[] createActions() {
+ createAdvice();
+ ArrayList result = new ArrayList();
+ // create an action that just publishes the raw bundles and features
+ IPublishingAction action = new MergeResultsAction(new IPublishingAction[] {createFeaturesAction(), createBundlesAction()}, IPublisherResult.MERGE_ALL_NON_ROOT);
+ result.add(action);
+ result.add(createSiteXMLAction());
+ return (IPublishingAction[]) result.toArray(new IPublishingAction[result.size()]);
+ }
+
+ private IPublishingAction createSiteXMLAction() {
+ if (updateSite != null)
+ return new SiteXMLAction(updateSite);
+ if (source != null) {
+ try {
+ return new SiteXMLAction(new File(source, "site.xml").toURL()); //$NON-NLS-1$
+ } catch (MalformedURLException e) {
+ // never happens
+ return null;
+ }
+ }
+ return null;
+ }
+
+ private void createAdvice() {
+ }
+
+ protected IPublishingAction createFeaturesAction() {
+ return new FeaturesAction(new File[] {new File(source, "features")}); //$NON-NLS-1$
+ }
+
+ protected IPublishingAction createBundlesAction() {
+ 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/RootFilesAction.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/actions/RootFilesAction.java
index 787ad415b..cd66562c9 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
@@ -86,7 +86,7 @@ public class RootFilesAction extends AbstractPublishingAction {
result.addIU(unit, IPublisherResult.ROOT);
//Create the artifact descriptor. we have several files so no path on disk
- IArtifactDescriptor descriptor = MetadataGeneratorHelper.createArtifactDescriptor(key, null, false, true);
+ IArtifactDescriptor descriptor = MetadataGeneratorHelper.createArtifactDescriptor(key, null);
IRootFilesAdvice advice = getAdvice(configSpec, info);
publishArtifact(descriptor, filterRootFiles(advice, info), advice.getRoot(), info, INCLUDE_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/SiteXMLAction.java
index 5c452e5d0..8134daa3b 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/SiteXMLAction.java
@@ -9,30 +9,38 @@
******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher.actions;
-import java.io.*;
import java.net.URL;
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.core.runtime.*;
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.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Version;
-public class UpdateSiteAction extends AbstractPublishingAction {
+/**
+ * Action which processes a site.xml and generates categories. The categorization process
+ * relies on IUs for the various features to have already been generated.
+ */
+public class SiteXMLAction extends AbstractPublishingAction {
- private URL location;
- private IPublisherInfo info;
+ private UpdateSite updateSite;
private SiteCategory defaultCategory;
private HashSet defaultCategorySet;
- public UpdateSiteAction(URL location, IPublisherInfo info) {
- this.location = location;
- this.info = info;
+ public SiteXMLAction(URL location) {
+ try {
+ updateSite = UpdateSite.load(location, new NullProgressMonitor());
+ } catch (ProvisionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ initialize();
+ }
+
+ public SiteXMLAction(UpdateSite updateSite) {
+ this.updateSite = updateSite;
initialize();
}
@@ -46,13 +54,13 @@ public class UpdateSiteAction extends AbstractPublishingAction {
}
public IStatus perform(IPublisherInfo info, IPublisherResult results) {
- generateCategories(results);
+ generateCategories(info, results);
return Status.OK_STATUS;
}
- private void generateCategories(IPublisherResult results) {
+ private void generateCategories(IPublisherInfo info, IPublisherResult results) {
Map categoriesToFeatureIUs = new HashMap();
- Map featuresToCategories = getFeatureToCategoryMappings(location);
+ Map featuresToCategories = getFeatureToCategoryMappings(info);
for (Iterator i = featuresToCategories.keySet().iterator(); i.hasNext();) {
SiteFeature feature = (SiteFeature) i.next();
IInstallableUnit iu = getFeatureIU(feature, results);
@@ -76,6 +84,7 @@ public class UpdateSiteAction extends AbstractPublishingAction {
private IInstallableUnit getFeatureIU(SiteFeature feature, IPublisherResult results) {
String id = MetadataGeneratorHelper.getTransformedId(feature.getFeatureIdentifier(), false, true);
Version version = new Version(feature.getFeatureIdentifier());
+ // TODO look elsewhere as well. Perhaps in the metadata repos and some advice.
Collection ius = results.getIUs(id, null);
for (Iterator i = ius.iterator(); i.hasNext();) {
IInstallableUnit iu = (IInstallableUnit) i.next();
@@ -90,20 +99,11 @@ public class UpdateSiteAction extends AbstractPublishingAction {
* if available. Returns an empty map if there is not site.xml, or no categories.
* @return A map of SiteFeature -> Set<SiteCategory>.
*/
- protected Map getFeatureToCategoryMappings(URL siteLocation) {
+ protected Map getFeatureToCategoryMappings(IPublisherInfo info) {
HashMap mappings = new HashMap();
- if (siteLocation == null)
+ if (updateSite == null)
return mappings;
- InputStream input;
- SiteModel site = null;
- try {
- input = new BufferedInputStream(siteLocation.openStream());
- site = new DefaultSiteParser().parse(input);
- } catch (FileNotFoundException e) {
- //don't complain if the update site is not present
- } catch (Exception e) {
- LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.exception_errorParsingUpdateSite, siteLocation), e));
- }
+ SiteModel site = updateSite.getSite();
if (site == null)
return mappings;
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
index 104cc03bf..2a1aced0f 100644
--- 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
@@ -33,6 +33,10 @@ public final class Messages extends NLS {
public static String DefaultSiteParser_InvalidXMLStream;
public static String DefaultSiteParser_mirrors;
+ public static String ErrorReadingDigest;
+ public static String ErrorReadingFeature;
+ public static String ErrorReadingSite;
+ public static String InvalidRepositoryLocation;
static {
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
}
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/UpdateSite.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/UpdateSite.java
new file mode 100644
index 000000000..362aa2eb3
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/internal/p2/publisher/features/UpdateSite.java
@@ -0,0 +1,374 @@
+/*******************************************************************************
+ * Copyright (c) 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.MalformedURLException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.zip.*;
+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.p2.publisher.Activator;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.osgi.util.NLS;
+import org.xml.sax.SAXException;
+
+/**
+ * @since 1.0
+ */
+public class UpdateSite {
+
+ private static final String VERSION_SEPARATOR = "_"; //$NON-NLS-1$
+ private static final String JAR_EXTENSION = ".jar"; //$NON-NLS-1$
+ private static final String FEATURE_DIR = "features/"; //$NON-NLS-1$
+ private static final String PLUGIN_DIR = "plugins/"; //$NON-NLS-1$
+ private static final String FEATURE_TEMP_FILE = "feature"; //$NON-NLS-1$
+ private static final String SITE_FILE = "site.xml"; //$NON-NLS-1$
+ private static final String DIR_SEPARATOR = "/"; //$NON-NLS-1$
+ private String checksum;
+ private URL location;
+ private SiteModel site;
+
+ /*
+ * Some variables for caching.
+ */
+ // map of String (URL.toExternalForm()) to UpdateSite
+ private static Map siteCache = new HashMap();
+ // map of String (featureID_featureVersion) to Feature
+ private Map featureCache = new HashMap();
+
+ /*
+ * Return a new URL for the given file which is based from the specified root.
+ */
+ public static URL getFileURL(URL root, String fileName) throws MalformedURLException {
+ if (root.getPath().endsWith(fileName))
+ return root;
+ if (root.getPath().endsWith(SITE_FILE))
+ return new URL(root, fileName);
+ if (root.getPath().endsWith(DIR_SEPARATOR))
+ return new URL(root.toExternalForm() + fileName);
+ return new URL(root.toExternalForm() + DIR_SEPARATOR + fileName);
+ }
+
+ /*
+ * Open and return the input stream for the given URL.
+ */
+ private static InputStream getSiteInputStream(URL url) throws ProvisionException {
+ try {
+ return getSiteURL(url).openStream();
+ } catch (MalformedURLException e) {
+ String msg = NLS.bind(Messages.InvalidRepositoryLocation, url);
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION, msg, e));
+ } catch (IllegalArgumentException e) {
+ //see bug 221600 - URL.openStream can throw IllegalArgumentException
+ String msg = NLS.bind(Messages.InvalidRepositoryLocation, url);
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION, msg, e));
+ } catch (IOException e) {
+ String msg = NLS.bind(Messages.ErrorReadingSite, url);
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, msg, e));
+ }
+ }
+
+ /*
+ * Return a URL based on the given URL, which points to a site.xml file.
+ */
+ private static URL getSiteURL(URL url) throws MalformedURLException {
+ if (url.getPath().endsWith(SITE_FILE))
+ return url;
+ if (url.getPath().endsWith(DIR_SEPARATOR))
+ return new URL(url.toExternalForm() + SITE_FILE);
+ return new URL(url.toExternalForm() + DIR_SEPARATOR + SITE_FILE);
+ }
+
+ /*
+ * Load and return an update site object from the given location.
+ */
+ public static UpdateSite load(URL location, IProgressMonitor monitor) throws ProvisionException {
+ if (location == null)
+ return null;
+ UpdateSite result = (UpdateSite) siteCache.get(location.toExternalForm());
+ if (result != null)
+ return result;
+ InputStream input = getSiteInputStream(location);
+ try {
+ DefaultSiteParser siteParser = new DefaultSiteParser();
+ Checksum checksum = new CRC32();
+ input = new CheckedInputStream(new BufferedInputStream(input), checksum);
+ SiteModel siteModel = siteParser.parse(input);
+ String checksumString = Long.toString(checksum.getValue());
+ result = new UpdateSite(siteModel, location, checksumString);
+ siteCache.put(location.toExternalForm(), result);
+ return result;
+ } catch (SAXException e) {
+ String msg = NLS.bind(Messages.ErrorReadingSite, location);
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_READ, msg, e));
+ } catch (IOException e) {
+ String msg = NLS.bind(Messages.ErrorReadingSite, location);
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_READ, msg, e));
+ } finally {
+ try {
+ input.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+ }
+
+ /*
+ * Parse the feature.xml specified by the given input stream and return the feature object.
+ */
+ private static Feature parseFeature(FeatureParser featureParser, URL featureURL) throws IOException, FileNotFoundException, ProvisionException {
+ File featureFile = File.createTempFile(FEATURE_TEMP_FILE, JAR_EXTENSION);
+ try {
+ FileUtils.copyStream(featureURL.openStream(), true, new BufferedOutputStream(new FileOutputStream(featureFile)), true);
+ return featureParser.parse(featureFile);
+ } catch (IllegalArgumentException e) {
+ //see bug 221600 - URL.openStream can throw IllegalArgumentException
+ String msg = NLS.bind(Messages.InvalidRepositoryLocation, featureURL.toExternalForm());
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION, msg, e));
+ } finally {
+ featureFile.delete();
+ }
+ }
+
+ /*
+ * Throw an exception if the site pointed to by the given URL is not valid.
+ */
+ public static void validate(URL url, IProgressMonitor monitor) throws ProvisionException {
+ InputStream input = getSiteInputStream(url);
+ try {
+ input.close();
+ } catch (IOException e) {
+ // ignore
+ }
+ }
+
+ /*
+ * Constructor for the class.
+ */
+ private UpdateSite(SiteModel site, URL location, String checksum) {
+ super();
+ this.site = site;
+ this.location = location;
+ this.checksum = checksum;
+ }
+
+ /*
+ * Iterate over the archive entries in this site and return the matching URL string for
+ * the given identifier, if there is one.
+ */
+ private URL getArchiveURL(URL base, String identifier) {
+ URLEntry[] archives = site.getArchives();
+ for (int i = 0; archives != null && i < archives.length; i++) {
+ URLEntry entry = archives[i];
+ if (identifier.equals(entry.getAnnotation()))
+ return internalGetURL(base, entry.getURL());
+ }
+ return null;
+ }
+
+ /*
+ * Return the checksum for this site.
+ */
+ public String getChecksum() {
+ return checksum;
+ }
+
+ /*
+ * Return a URL which represents the location of the given feature.
+ */
+ public URL getFeatureURL(SiteFeature siteFeature, String id, String version) {
+ URL base = site.getLocationURL();
+ if (base == null)
+ base = location;
+ if (siteFeature == null) {
+ SiteFeature[] entries = site.getFeatures();
+ for (int i = 0; i < entries.length; i++) {
+ if (id.equals(entries[i].getFeatureIdentifier()) && version.equals(entries[i].getFeatureVersion())) {
+ siteFeature = entries[i];
+ break;
+ }
+ }
+ }
+ if (siteFeature != null) {
+ URL url = siteFeature.getURL();
+ if (url != null)
+ return url;
+ url = getArchiveURL(base, id);
+ if (url != null)
+ return url;
+ }
+ // fall through to default URL
+ try {
+ return getFileURL(base, FEATURE_DIR + id + VERSION_SEPARATOR + version + JAR_EXTENSION);
+ } catch (MalformedURLException e) {
+ // shouldn't happen
+ }
+ return null;
+ }
+
+ /*
+ * Return the location of this site.
+ */
+ public URL getLocation() {
+ return location;
+ }
+
+ /*
+ * Return a URL which represents the location of the given plug-in.
+ */
+ public URL getPluginURL(FeatureEntry plugin) {
+ URL base = site.getLocationURL();
+ if (base == null)
+ base = location;
+ String path = PLUGIN_DIR + plugin.getId() + VERSION_SEPARATOR + plugin.getVersion() + JAR_EXTENSION;
+ URL url = getArchiveURL(base, path);
+ if (url != null)
+ return url;
+ try {
+ return getFileURL(base, path);
+ } catch (MalformedURLException e) {
+ // shouldn't happen
+ }
+ return null;
+ }
+
+ /*
+ * Return the site model.
+ */
+ public SiteModel getSite() {
+ return site;
+ }
+
+ /*
+ * The trailing parameter can be either null, relative or absolute. If it is null,
+ * then return null. If it is absolute, then create a new url and return it. If it is
+ * relative, then make it relative to the given base url.
+ */
+ private URL internalGetURL(URL base, String trailing) {
+ if (trailing == null)
+ return null;
+ try {
+ return new URL(trailing);
+ } catch (MalformedURLException e) {
+ try {
+ return new URL(base, trailing);
+ } catch (MalformedURLException e2) {
+ // shouldn't happen
+ }
+ }
+ return null;
+ }
+
+ /*
+ * Load and return the features references in this update site.
+ */
+ public Feature[] loadFeatures() throws ProvisionException {
+ Feature[] result = loadFeaturesFromDigest();
+ return result == null ? loadFeaturesFromSite() : result;
+ }
+
+ /*
+ * Try and load the feature information from the update site's
+ * digest file, if it exists.
+ */
+ private Feature[] loadFeaturesFromDigest() throws ProvisionException {
+ if (!featureCache.isEmpty())
+ return (Feature[]) featureCache.values().toArray(new Feature[featureCache.size()]);
+ try {
+ URL digestURL = getFileURL(location, "digest.zip"); //$NON-NLS-1$
+ File digestFile = File.createTempFile("digest", ".zip"); //$NON-NLS-1$ //$NON-NLS-2$
+ try {
+ FileUtils.copyStream(digestURL.openStream(), true, new BufferedOutputStream(new FileOutputStream(digestFile)), true);
+ Feature[] result = new DigestParser().parse(digestFile);
+ if (result == null)
+ return null;
+ for (int i = 0; i < result.length; i++) {
+ String key = result[i].getId() + VERSION_SEPARATOR + result[i].getVersion();
+ featureCache.put(key, result[i]);
+ }
+ return result;
+ } catch (IllegalArgumentException e) {
+ //see bug 221600 - URL.openStream can throw IllegalArgumentException
+ String msg = NLS.bind(Messages.InvalidRepositoryLocation, digestURL.toExternalForm());
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_INVALID_LOCATION, msg, e));
+ } finally {
+ digestFile.delete();
+ }
+ } catch (MalformedURLException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingDigest, location), e));
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingDigest, location), e));
+ }
+ return null;
+ }
+
+ /*
+ * Load and return the features that are referenced by this update site. Note this
+ * requires downloading and parsing the feature manifest locally.
+ */
+ private Feature[] loadFeaturesFromSite() throws ProvisionException {
+ SiteFeature[] siteFeatures = site.getFeatures();
+ FeatureParser featureParser = new FeatureParser();
+ for (int i = 0; i < siteFeatures.length; i++) {
+ SiteFeature siteFeature = siteFeatures[i];
+ String key = siteFeature.getFeatureIdentifier() + VERSION_SEPARATOR + siteFeature.getFeatureVersion();
+ if (featureCache.containsKey(key))
+ continue;
+ URL featureURL = getFeatureURL(siteFeature, siteFeature.getFeatureIdentifier(), siteFeature.getFeatureVersion());
+ try {
+ Feature feature = parseFeature(featureParser, featureURL);
+ if (feature == null) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingFeature, featureURL)));
+ } else {
+ featureCache.put(key, feature);
+ loadIncludedFeatures(feature, featureParser);
+ }
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingFeature, featureURL), e));
+ }
+ }
+ return (Feature[]) featureCache.values().toArray(new Feature[featureCache.size()]);
+ }
+
+ /*
+ * Load the features that are included by the given feature.
+ */
+ private void loadIncludedFeatures(Feature feature, FeatureParser featureParser) throws ProvisionException {
+ FeatureEntry[] featureEntries = feature.getEntries();
+ for (int i = 0; i < featureEntries.length; i++) {
+ FeatureEntry entry = featureEntries[i];
+ if (entry.isRequires() || entry.isPlugin())
+ continue;
+ String key = entry.getId() + VERSION_SEPARATOR + entry.getVersion();
+ if (featureCache.containsKey(key))
+ continue;
+ URL featureURL = null;
+ try {
+ featureURL = getFileURL(location, FEATURE_DIR + entry.getId() + VERSION_SEPARATOR + entry.getVersion() + JAR_EXTENSION);
+ Feature includedFeature = parseFeature(featureParser, featureURL);
+ if (feature == null) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingFeature, featureURL)));
+ } else {
+ featureCache.put(key, includedFeature);
+ loadIncludedFeatures(includedFeature, featureParser);
+ }
+ } catch (MalformedURLException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingFeature, entry.getId()), e));
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingFeature, featureURL), e));
+ }
+ }
+ }
+}
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
index 052ad26c2..7ddef915a 100644
--- 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
@@ -28,3 +28,7 @@ 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.
+ErrorReadingDigest=Error reading site digest {0}.
+ErrorReadingFeature=Error reading feature {0}.
+ErrorReadingSite=Error reading update site {0}.
+InvalidRepositoryLocation=Invalid repository location {0}.

Back to the top