Integrating changes for adopting the publisher
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.directorywatcher/META-INF/MANIFEST.MF
index db569a4..88746d4 100644
--- a/bundles/org.eclipse.equinox.p2.directorywatcher/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/META-INF/MANIFEST.MF
@@ -6,16 +6,18 @@
Bundle-Localization: plugin
Bundle-Version: 1.0.100.qualifier
Import-Package: org.eclipse.equinox.internal.p2.core.helpers,
- org.eclipse.equinox.internal.p2.metadata.generator.features,
+ org.eclipse.equinox.internal.p2.metadata,
org.eclipse.equinox.internal.provisional.p2.artifact.repository,
org.eclipse.equinox.internal.provisional.p2.core,
org.eclipse.equinox.internal.provisional.p2.core.eventbus,
org.eclipse.equinox.internal.provisional.p2.core.repository,
org.eclipse.equinox.internal.provisional.p2.metadata,
- org.eclipse.equinox.internal.provisional.p2.metadata.generator,
org.eclipse.equinox.internal.provisional.p2.metadata.query,
org.eclipse.equinox.internal.provisional.p2.metadata.repository,
org.eclipse.equinox.internal.provisional.p2.query,
+ org.eclipse.equinox.p2.publisher,
+ org.eclipse.equinox.p2.publisher.actions,
+ org.eclipse.equinox.p2.publisher.eclipse,
org.eclipse.osgi.service.resolver;version="1.1.0",
org.eclipse.osgi.util,
org.osgi.framework;version="1.4.0",
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/Activator.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/Activator.java
index e3bf2c4..63f3ad8 100644
--- a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/Activator.java
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/Activator.java
@@ -7,11 +7,18 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.provisional.p2.directorywatcher;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepositoryManager;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
+import org.osgi.framework.*;
+import org.osgi.service.packageadmin.PackageAdmin;
/**
* Bundle activator for directory watcher bundle.
@@ -25,18 +32,33 @@
return context;
}
- /* (non-Javadoc)
- * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
- */
public void start(BundleContext aContext) throws Exception {
context = aContext;
}
- /* (non-Javadoc)
- * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
- */
public void stop(BundleContext aContext) throws Exception {
context = null;
}
+ public static IArtifactRepositoryManager getArtifactRepositoryManager() {
+ return (IArtifactRepositoryManager) ServiceHelper.getService(context, IArtifactRepositoryManager.class.getName());
+ }
+
+ public static IMetadataRepositoryManager getMetadataRepositoryManager() {
+ return (IMetadataRepositoryManager) ServiceHelper.getService(context, IMetadataRepositoryManager.class.getName());
+ }
+
+ public static URL getDefaultRepositoryLocation(Object object, String repositoryName) {
+ PackageAdmin packageAdmin = (PackageAdmin) ServiceHelper.getService(context, PackageAdmin.class.getName());
+ Bundle bundle = packageAdmin.getBundle(object.getClass());
+ BundleContext context = bundle.getBundleContext();
+ File base = context.getDataFile(""); //$NON-NLS-1$
+ File result = new File(base, "listener_" + repositoryName.hashCode()); //$NON-NLS-1$
+ result.mkdirs();
+ try {
+ return result.toURL();
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java
new file mode 100644
index 0000000..0c52b62
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/CachingArtifactRepository.java
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * 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.provisional.p2.directorywatcher;
+
+import java.io.File;
+import java.io.OutputStream;
+import java.net.URL;
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
+
+public class CachingArtifactRepository implements IArtifactRepository, IFileArtifactRepository {
+
+ private static final String NULL = ""; //$NON-NLS-1$
+ private IArtifactRepository innerRepo;
+ private Set descriptorsToAdd = new HashSet();
+ private Map artifactMap = new HashMap();
+ private Set descriptorsToRemove = new HashSet();
+ private Map propertyChanges = new HashMap();
+
+ protected CachingArtifactRepository(IArtifactRepository innerRepo) {
+ this.innerRepo = innerRepo;
+ }
+
+ public void save() {
+ savePropertyChanges();
+ saveAdditions();
+ saveRemovals();
+ }
+
+ private void saveRemovals() {
+ for (Iterator i = descriptorsToRemove.iterator(); i.hasNext();)
+ innerRepo.removeDescriptor((IArtifactDescriptor) i.next());
+ descriptorsToRemove.clear();
+ }
+
+ private void saveAdditions() {
+ if (descriptorsToAdd.isEmpty())
+ return;
+ innerRepo.addDescriptors((IArtifactDescriptor[]) descriptorsToAdd.toArray(new IArtifactDescriptor[descriptorsToAdd.size()]));
+ descriptorsToAdd.clear();
+ artifactMap.clear();
+ }
+
+ private void savePropertyChanges() {
+ for (Iterator i = propertyChanges.keySet().iterator(); i.hasNext();) {
+ String key = (String) i.next();
+ String value = (String) propertyChanges.get(key);
+ innerRepo.setProperty(key, value == NULL ? null : value);
+ }
+ propertyChanges.clear();
+ }
+
+ private void mapDescriptor(IArtifactDescriptor descriptor) {
+ IArtifactKey key = descriptor.getArtifactKey();
+ Collection descriptors = (Collection) artifactMap.get(key);
+ if (descriptors == null) {
+ descriptors = new ArrayList();
+ artifactMap.put(key, descriptors);
+ }
+ descriptors.add(descriptor);
+ }
+
+ private void unmapDescriptor(IArtifactDescriptor descriptor) {
+ IArtifactKey key = descriptor.getArtifactKey();
+ Collection descriptors = (Collection) artifactMap.get(key);
+ if (descriptors == null) {
+ // we do not have the descriptor locally so remember it to be removed from
+ // the inner repo on save.
+ descriptorsToRemove.add(descriptor);
+ return;
+ }
+
+ descriptors.remove(descriptor);
+ if (descriptors.isEmpty())
+ artifactMap.remove(key);
+ }
+
+ public synchronized void addDescriptors(IArtifactDescriptor[] descriptors) {
+ for (int i = 0; i < descriptors.length; i++) {
+ ((ArtifactDescriptor) descriptors[i]).setRepository(this);
+ descriptorsToAdd.add(descriptors[i]);
+ mapDescriptor(descriptors[i]);
+ }
+ }
+
+ public synchronized void addDescriptor(IArtifactDescriptor toAdd) {
+ ((ArtifactDescriptor) toAdd).setRepository(this);
+ descriptorsToAdd.add(toAdd);
+ mapDescriptor(toAdd);
+ }
+
+ public synchronized IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) {
+ Collection result = (Collection) artifactMap.get(key);
+ if (result == null)
+ return innerRepo.getArtifactDescriptors(key);
+ result.addAll(Arrays.asList(innerRepo.getArtifactDescriptors(key)));
+ return (IArtifactDescriptor[]) result.toArray(new IArtifactDescriptor[result.size()]);
+ }
+
+ public synchronized IArtifactKey[] getArtifactKeys() {
+ // there may be more descriptors than keys to collect up the unique keys
+ HashSet result = new HashSet();
+ result.addAll(artifactMap.keySet());
+ result.addAll(Arrays.asList(innerRepo.getArtifactKeys()));
+ return (IArtifactKey[]) result.toArray(new IArtifactKey[result.size()]);
+ }
+
+ public synchronized boolean contains(IArtifactDescriptor descriptor) {
+ return descriptorsToAdd.contains(descriptor) || innerRepo.contains(descriptor);
+ }
+
+ public synchronized boolean contains(IArtifactKey key) {
+ return artifactMap.containsKey(key) || innerRepo.contains(key);
+ }
+
+ public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
+ return innerRepo.getArtifact(descriptor, destination, monitor);
+ }
+
+ public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) {
+ return Status.OK_STATUS;
+ }
+
+ public OutputStream getOutputStream(IArtifactDescriptor descriptor) {
+ return null;
+ }
+
+ public synchronized void removeAll() {
+ IArtifactDescriptor[] toRemove = (IArtifactDescriptor[]) descriptorsToAdd.toArray(new IArtifactDescriptor[descriptorsToAdd.size()]);
+ for (int i = 0; i < toRemove.length; i++)
+ doRemoveArtifact(toRemove[i]);
+ }
+
+ public synchronized void removeDescriptor(IArtifactDescriptor descriptor) {
+ doRemoveArtifact(descriptor);
+ }
+
+ public synchronized void removeDescriptor(IArtifactKey key) {
+ IArtifactDescriptor[] toRemove = getArtifactDescriptors(key);
+ for (int i = 0; i < toRemove.length; i++)
+ doRemoveArtifact(toRemove[i]);
+ }
+
+ /**
+ * Removes the given descriptor and returns <code>true</code> if and only if the
+ * descriptor existed in the repository, and was successfully removed.
+ */
+ private boolean doRemoveArtifact(IArtifactDescriptor descriptor) {
+ // if the descriptor is already in the pending additoins, remove it
+ boolean result = descriptorsToAdd.remove(descriptor);
+ if (result)
+ unmapDescriptor(descriptor);
+ // either way, note this as a descriptor to remove from the inner repo
+ descriptorsToRemove.add(descriptor);
+ return result;
+ }
+
+ public String getDescription() {
+ return innerRepo.getDescription();
+ }
+
+ public URL getLocation() {
+ return innerRepo.getLocation();
+ }
+
+ public String getName() {
+ return innerRepo.getName();
+ }
+
+ public Map getProperties() {
+ // TODO need to combine the local and inner properties
+ return innerRepo.getProperties();
+ }
+
+ public String getProvider() {
+ return innerRepo.getProvider();
+ }
+
+ public String getType() {
+ return innerRepo.getType();
+ }
+
+ public String getVersion() {
+ return innerRepo.getVersion();
+ }
+
+ public boolean isModifiable() {
+ return innerRepo.isModifiable();
+ }
+
+ public void setDescription(String description) {
+ innerRepo.setDescription(description);
+ }
+
+ public void setName(String name) {
+ innerRepo.setName(name);
+ }
+
+ public String setProperty(String key, String value) {
+ String result = (String) getProperties().get(key);
+ propertyChanges.put(key, value == null ? NULL : value);
+ return result;
+ }
+
+ public void setProvider(String provider) {
+ innerRepo.setProvider(provider);
+ }
+
+ public Object getAdapter(Class adapter) {
+ return innerRepo.getAdapter(adapter);
+ }
+
+ public File getArtifactFile(IArtifactKey key) {
+ if (innerRepo instanceof IFileArtifactRepository)
+ return ((IFileArtifactRepository) innerRepo).getArtifactFile(key);
+ return null;
+ }
+
+ public File getArtifactFile(IArtifactDescriptor descriptor) {
+ if (innerRepo instanceof IFileArtifactRepository)
+ return ((IFileArtifactRepository) innerRepo).getArtifactFile(descriptor);
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/DirectoryChangeListener.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/DirectoryChangeListener.java
index 295d1b6..515e19d 100644
--- a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/DirectoryChangeListener.java
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/DirectoryChangeListener.java
@@ -42,6 +42,7 @@
return false;
}
+ //TODO this method name needs to be more descriptive. getLastModified?
public Long getSeenFile(File file) {
return null;
}
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/EntryAdvice.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/EntryAdvice.java
new file mode 100644
index 0000000..68bdf31
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/EntryAdvice.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * 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.provisional.p2.directorywatcher;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Map;
+import java.util.Properties;
+import org.eclipse.equinox.p2.publisher.eclipse.*;
+import org.osgi.framework.Version;
+
+/**
+ * Entry advice captures the name, location, modified time, shape etc of something
+ * discovered by the repository listener. It is a simplified structure intended to represent
+ * only one entry at a time and that entry is the the only entry being published.
+ */
+public class EntryAdvice implements IFeatureAdvice, IBundleAdvice {
+ private Properties metadataProps = new Properties();
+ private Properties artifactProps = new Properties();
+
+ public Properties getProperties(Feature feature, File location) {
+ return metadataProps;
+ }
+
+ public boolean isApplicable(String configSpec, boolean includeDefault, String id, Version version) {
+ return true;
+ }
+
+ public Properties getIUProperties(File location) {
+ return metadataProps;
+ }
+
+ public Properties getArtifactProperties(File location) {
+ return artifactProps;
+ }
+
+ void setProperties(File location, long timestamp, URL reference) {
+ if (reference == null)
+ artifactProps.remove(RepositoryListener.ARTIFACT_REFERENCE);
+ else
+ artifactProps.setProperty(RepositoryListener.ARTIFACT_REFERENCE, reference.toExternalForm());
+ if (location.isDirectory())
+ artifactProps.setProperty(RepositoryListener.ARTIFACT_FOLDER, Boolean.TRUE.toString());
+ else
+ artifactProps.remove(RepositoryListener.ARTIFACT_FOLDER);
+ artifactProps.setProperty(RepositoryListener.FILE_NAME, location.getAbsolutePath());
+ metadataProps.setProperty(RepositoryListener.FILE_NAME, location.getAbsolutePath());
+ metadataProps.setProperty(RepositoryListener.FILE_LAST_MODIFIED, Long.toString(timestamp));
+ }
+
+ public Map getInstructions(File location) {
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java
index 04132b7..af5484a 100644
--- a/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java
+++ b/bundles/org.eclipse.equinox.p2.directorywatcher/src/org/eclipse/equinox/internal/provisional/p2/directorywatcher/RepositoryListener.java
@@ -5,7 +5,8 @@
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
- * IBM Corporation - initial implementation and ideas
+ * IBM Corporation - initial implementation and ideas
+ * Code 9 - ongoing development
******************************************************************************/
package org.eclipse.equinox.internal.provisional.p2.directorywatcher;
@@ -13,42 +14,38 @@
import java.net.MalformedURLException;
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.equinox.internal.p2.core.helpers.ServiceHelper;
-import org.eclipse.equinox.internal.p2.metadata.generator.features.FeatureParser;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
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.core.repository.RepositoryEvent;
import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.query.InstallableUnitQuery;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.query.Collector;
import org.eclipse.equinox.internal.provisional.p2.query.Query;
-import org.eclipse.osgi.service.resolver.*;
+import org.eclipse.equinox.p2.publisher.*;
+import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
+import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction;
+import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.util.NLS;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
public class RepositoryListener extends DirectoryChangeListener {
- private static final String ARTIFACT_FOLDER = "artifact.folder"; //$NON-NLS-1$
- private static final String ARTIFACT_REFERENCE = "artifact.reference"; //$NON-NLS-1$
- private static final String FILE_LAST_MODIFIED = "file.lastModified"; //$NON-NLS-1$
- private static final String FILE_NAME = "file.name"; //$NON-NLS-1$
+ public static final String ARTIFACT_FOLDER = "artifact.folder"; //$NON-NLS-1$
+ public static final String ARTIFACT_REFERENCE = "artifact.reference"; //$NON-NLS-1$
+ public static final String FILE_LAST_MODIFIED = "file.lastModified"; //$NON-NLS-1$
+ public static final String FILE_NAME = "file.name"; //$NON-NLS-1$
private final IMetadataRepository metadataRepository;
- private final IArtifactRepository artifactRepository;
- private final BundleDescriptionFactory bundleDescriptionFactory;
- private final Map currentFiles = new HashMap();
-
- private Collection polledSeenFiles = new HashSet();
- private Collection polledIUsToAdd = new ArrayList();
- private Collection polledArtifactsToAdd = new ArrayList();
+ private final CachingArtifactRepository artifactRepository;
+ // at any point in time currentFiles is the list of files/dirs that the watcher has seen and
+ // believes to be on disk.
+ private Map currentFiles;
+ private Collection filesToRemove;
+ private EntryAdvice advice = new EntryAdvice();
+ private PublisherInfo info;
+ private IPublisherResult iusToAdd;
+ private IPublisherResult iusToChange;
/**
* Create a repository listener that watches the specified folder and generates repositories
@@ -59,351 +56,215 @@
* bundle's data location should be used.
* @param hidden <code>true</code> if the repository should be hidden, <code>false</code> if not.
*/
- public RepositoryListener(BundleContext context, String repositoryName, File repositoryFolder, boolean hidden) {
- File stateDir;
- if (repositoryFolder == null) {
- String stateDirName = "listener_" + repositoryName.hashCode(); //$NON-NLS-1$
- stateDir = context.getDataFile(stateDirName);
- stateDir.mkdirs();
- } else {
- stateDir = repositoryFolder;
- }
-
- URL stateDirURL;
- try {
- stateDirURL = stateDir.toURL();
- } catch (MalformedURLException e) {
- throw new IllegalStateException(e.getMessage());
- }
-
- metadataRepository = initializeMetadataRepository(context, repositoryName, stateDirURL, hidden);
- artifactRepository = initializeArtifactRepository(context, repositoryName, stateDirURL, hidden);
- bundleDescriptionFactory = initializeBundleDescriptionFactory(context);
- synchronizeCurrentFiles();
+ public RepositoryListener(String repositoryName, boolean hidden) {
+ URL location = Activator.getDefaultRepositoryLocation(this, repositoryName);
+ metadataRepository = initiailzeMetadataRepository(repositoryName, location, hidden);
+ artifactRepository = initializeArtifactRepository(repositoryName, location, hidden);
+ initializePublisher();
}
- public RepositoryListener(BundleContext context, IMetadataRepository metadataRepository, IArtifactRepository artifactRepository) {
- this.artifactRepository = artifactRepository;
+ public RepositoryListener(IMetadataRepository metadataRepository, IArtifactRepository artifactRepository) {
+ this.artifactRepository = new CachingArtifactRepository(artifactRepository);
this.metadataRepository = metadataRepository;
- bundleDescriptionFactory = initializeBundleDescriptionFactory(context);
- synchronizeCurrentFiles();
+ initializePublisher();
}
- /**
- * Broadcast events for any discovery sites associated with the feature
- * so the repository managers add them to their list of known repositories.
- */
- private void publishSites(Feature feature) {
- IProvisioningEventBus bus = (IProvisioningEventBus) ServiceHelper.getService(Activator.getContext(), IProvisioningEventBus.SERVICE_NAME);
- if (bus == null)
- return;
- URLEntry[] discoverySites = feature.getDiscoverySites();
- for (int i = 0; i < discoverySites.length; i++)
- publishSite(feature, bus, discoverySites[i].getURL(), false);
- String updateSite = feature.getUpdateSiteURL();
- if (updateSite != null)
- publishSite(feature, bus, updateSite, true);
+ private void initializePublisher() {
+ info = new PublisherInfo();
+ info.setArtifactRepository(artifactRepository);
+ info.setMetadataRepository(metadataRepository);
+ info.addAdvice(advice);
+ info.setArtifactOptions(IPublisherInfo.A_INDEX);
}
- /**
- * Broadcast a discovery event for the given repository location.
- */
- private void publishSite(Feature feature, IProvisioningEventBus bus, String locationString, boolean isEnabled) {
- try {
- URL location = new URL(locationString);
- bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED, isEnabled));
- bus.publishEvent(new RepositoryEvent(location, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED, isEnabled));
- } catch (MalformedURLException e) {
- LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "Feature references invalid site: " + feature.getId(), e)); //$NON-NLS-1$
- }
- }
-
- private BundleDescriptionFactory initializeBundleDescriptionFactory(BundleContext context) {
- ServiceReference reference = context.getServiceReference(PlatformAdmin.class.getName());
- if (reference == null)
- throw new IllegalStateException(Messages.platformadmin_not_registered);
- PlatformAdmin platformAdmin = (PlatformAdmin) context.getService(reference);
- if (platformAdmin == null)
- throw new IllegalStateException(Messages.platformadmin_not_registered);
-
- try {
- StateObjectFactory stateObjectFactory = platformAdmin.getFactory();
- return new BundleDescriptionFactory(stateObjectFactory, null);
- } finally {
- context.ungetService(reference);
- }
- }
-
- private IArtifactRepository initializeArtifactRepository(BundleContext context, String repositoryName, URL stateDirURL, boolean hidden) {
- ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
- IArtifactRepositoryManager manager = null;
- if (reference != null)
- manager = (IArtifactRepositoryManager) context.getService(reference);
+ protected CachingArtifactRepository initializeArtifactRepository(String repositoryName, URL repositoryLocation, boolean hidden) {
+ IArtifactRepositoryManager manager = Activator.getArtifactRepositoryManager();
if (manager == null)
throw new IllegalStateException(Messages.artifact_repo_manager_not_registered);
try {
- try {
- return manager.loadRepository(stateDirURL, null);
- } catch (ProvisionException e) {
- //fall through and create a new repository
+ IArtifactRepository result = manager.loadRepository(repositoryLocation, null);
+ return result == null ? null : new CachingArtifactRepository(result);
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+ try {
+ String name = repositoryName;
+ Map properties = new HashMap(1);
+ if (hidden) {
+ properties.put(IRepository.PROP_SYSTEM, Boolean.TRUE.toString());
+ name = "artifact listener " + repositoryName; //$NON-NLS-1$
}
- try {
- String name = repositoryName;
- Map properties = new HashMap(1);
- if (hidden) {
- properties.put(IRepository.PROP_SYSTEM, Boolean.TRUE.toString());
- name = "artifact listener " + repositoryName; //$NON-NLS-1$
- }
- return manager.createRepository(stateDirURL, name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
- } catch (ProvisionException e) {
- LogHelper.log(e);
- throw new IllegalStateException(NLS.bind(Messages.failed_create_artifact_repo, stateDirURL));
- }
- } finally {
- context.ungetService(reference);
+ IArtifactRepository result = manager.createRepository(repositoryLocation, name, IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ return result == null ? null : new CachingArtifactRepository(result);
+ } catch (ProvisionException e) {
+ LogHelper.log(e);
+ throw new IllegalStateException(NLS.bind(Messages.failed_create_artifact_repo, repositoryLocation));
}
}
- private IMetadataRepository initializeMetadataRepository(BundleContext context, String repositoryName, URL stateDirURL, boolean hidden) {
- ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
- IMetadataRepositoryManager manager = null;
- if (reference != null)
- manager = (IMetadataRepositoryManager) context.getService(reference);
+ protected IMetadataRepository initiailzeMetadataRepository(String repositoryName, URL repositoryLocation, boolean hidden) {
+ IMetadataRepositoryManager manager = Activator.getMetadataRepositoryManager();
if (manager == null)
throw new IllegalStateException(Messages.metadata_repo_manager_not_registered);
try {
- try {
- return manager.loadRepository(stateDirURL, null);
- } catch (ProvisionException e) {
- //fall through and create new repository
- }
+ return manager.loadRepository(repositoryLocation, null);
+ } catch (ProvisionException e) {
+ //fall through and create new repository
+ }
+ try {
String name = repositoryName;
Map properties = new HashMap(1);
if (hidden) {
properties.put(IRepository.PROP_SYSTEM, Boolean.TRUE.toString());
name = "metadata listener " + repositoryName; //$NON-NLS-1$
}
- return manager.createRepository(stateDirURL, name, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+ return manager.createRepository(repositoryLocation, name, IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
} catch (ProvisionException e) {
LogHelper.log(e);
- throw new IllegalStateException(NLS.bind(Messages.failed_create_metadata_repo, stateDirURL));
- } finally {
- context.ungetService(reference);
+ throw new IllegalStateException(NLS.bind(Messages.failed_create_metadata_repo, repositoryLocation));
}
}
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#added(java.io.File)
- */
public boolean added(File file) {
- return process(file);
+ return process(file, true);
}
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#changed(java.io.File)
- */
public boolean changed(File file) {
- // this sequence will trigger removal and then addition during stopPoll
- polledSeenFiles.remove(file);
- return process(file);
+ return process(file, false);
}
public boolean removed(File file) {
- // this file will get removed in stopPoll
- return currentFiles.containsKey(file);
+ filesToRemove.add(file);
+ return true;
}
- private boolean process(File file) {
+ private boolean process(File file, boolean isAddition) {
boolean isDirectory = file.isDirectory();
// is it a feature ?
if (isDirectory && file.getParentFile() != null && file.getParentFile().getName().equals("features") && new File(file, "feature.xml").exists()) //$NON-NLS-1$ //$NON-NLS-2$)
- return processFeature(file);
-
- // is it a bundle ?
+ return processFeature(file, isAddition);
+ // could it be a bundle ?
if (isDirectory || file.getName().endsWith(".jar")) //$NON-NLS-1$
- return processBundle(file, isDirectory);
-
+ return processBundle(file, isDirectory, isAddition);
return false;
}
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#removed(java.io.File)
- */
-
- private boolean processBundle(File file, boolean isDirectory) {
- BundleDescription bundleDescription = bundleDescriptionFactory.getBundleDescription(file);
+ private boolean processBundle(File file, boolean isDirectory, boolean isAddition) {
+ BundleDescription bundleDescription = BundlesAction.createBundleDescription(file);
if (bundleDescription == null)
return false;
-
- String fileName = file.getAbsolutePath();
- String lastModified = Long.toString(file.lastModified());
-
- // Add Bundle IU
- Properties props = new Properties();
- props.setProperty(FILE_NAME, fileName);
- props.setProperty(FILE_LAST_MODIFIED, lastModified);
-
- IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(bundleDescription.getSymbolicName(), bundleDescription.getVersion().toString());
- IInstallableUnit[] ius = MetadataGeneratorHelper.createEclipseIU(bundleDescription, (Map) bundleDescription.getUserObject(), isDirectory, key, props);
-
- // see bug 222370
+ try {
+ advice.setProperties(file, file.lastModified(), file.toURL());
+ } catch (MalformedURLException e) {
+ // should never happen
+ }
+ return publish(new BundlesAction(new BundleDescription[] {bundleDescription}), isAddition);
+ // TODO see bug 222370
// we only want to return the bundle IU so must exclude all fragment IUs
- IInstallableUnit bundleIU = null;
- for (int i = 0; i < ius.length; i++) {
- if (!ius[i].isFragment()) {
- bundleIU = ius[i];
- break;
- }
- }
-
- if (bundleIU == null) {
- if (ius.length == 0)
- return false;
- throw new IllegalStateException(Messages.multiple_bundle_ius);
- }
- polledIUsToAdd.add(bundleIU);
-
- // Add Bundle Artifact
- ArtifactDescriptor descriptor = new ArtifactDescriptor(MetadataGeneratorHelper.createArtifactDescriptor(key, file, true, false));
- try {
- descriptor.setRepositoryProperty(ARTIFACT_REFERENCE, file.toURL().toExternalForm());
- } catch (MalformedURLException e) {
- // unexpected
- e.printStackTrace();
- return false;
- }
- if (isDirectory)
- descriptor.setRepositoryProperty(ARTIFACT_FOLDER, Boolean.TRUE.toString());
- descriptor.setRepositoryProperty(FILE_NAME, fileName);
- descriptor.setRepositoryProperty(FILE_LAST_MODIFIED, lastModified);
-
- polledArtifactsToAdd.add(descriptor);
- return true;
+ // not sure if this is still relevant but we should investigate.
}
- private boolean processFeature(File file) {
- FeatureParser parser = new FeatureParser();
- Feature feature = parser.parse(file);
- if (feature == null)
- return false;
-
- publishSites(feature);
-
- String fileName = file.getAbsolutePath();
- String lastModified = Long.toString(file.lastModified());
-
- // Add Feature IUs
- Properties props = new Properties();
- props.setProperty(FILE_NAME, fileName);
- props.setProperty(FILE_LAST_MODIFIED, lastModified);
-
- IInstallableUnit featureIU = MetadataGeneratorHelper.createFeatureJarIU(feature, true, props);
- IInstallableUnit groupIU = MetadataGeneratorHelper.createGroupIU(feature, featureIU, props);
-
- polledIUsToAdd.add(featureIU);
- polledIUsToAdd.add(groupIU);
-
- // Add Feature Artifact
- IArtifactKey featureKey = MetadataGeneratorHelper.createFeatureArtifactKey(feature.getId(), feature.getVersion());
- ArtifactDescriptor descriptor = new ArtifactDescriptor(featureKey);
-
+ private boolean processFeature(File file, boolean isAddition) {
try {
- descriptor.setRepositoryProperty(ARTIFACT_REFERENCE, file.toURL().toExternalForm());
+ advice.setProperties(file, file.lastModified(), file.toURL());
} catch (MalformedURLException e) {
- // unexpected
- e.printStackTrace();
- return false;
+ // should never happen
}
- descriptor.setRepositoryProperty(ARTIFACT_FOLDER, Boolean.TRUE.toString());
- descriptor.setRepositoryProperty(FILE_NAME, fileName);
- descriptor.setRepositoryProperty(FILE_LAST_MODIFIED, lastModified);
-
- polledArtifactsToAdd.add(descriptor);
- return true;
+ return publish(new FeaturesAction(new File[] {file}), isAddition);
}
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.DirectoryChangeListener#isInterested(java.io.File)
- */
+ private boolean publish(IPublisherAction action, boolean isAddition) {
+ IPublisherResult result = isAddition ? iusToAdd : iusToChange;
+ return action.perform(info, result).isOK();
+ }
+
public boolean isInterested(File file) {
return true;
}
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#getSeenFile(java.io.File)
- */
public Long getSeenFile(File file) {
- Long lastSeen = (Long) currentFiles.get(file);
- if (lastSeen != null)
- polledSeenFiles.add(file);
- return lastSeen;
+ return (Long) currentFiles.get(file);
}
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#startPoll()
- */
public void startPoll() {
- // do nothing
- }
-
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.p2.directorywatcher.IDirectoryChangeListener#stopPoll()
- */
- public void stopPoll() {
- final Set removedFiles = new HashSet(currentFiles.keySet());
- removedFiles.removeAll(polledSeenFiles);
- polledSeenFiles.clear();
-
- if (removedFiles.isEmpty() && polledIUsToAdd.isEmpty() && polledArtifactsToAdd.isEmpty())
- return;
-
- if (metadataRepository != null)
- synchronizeMetadataRepository(removedFiles);
-
- if (artifactRepository != null)
- synchronizeArtifactRepository(removedFiles);
-
+ filesToRemove = new HashSet();
+ iusToAdd = new PublisherResult();
+ iusToChange = new PublisherResult();
+ // TODO investigate why we do this here? Suspect it is to clean up the currentFiles collection
+ // for removed entries. This may be a performance opportunity
+ currentFiles = new HashMap();
synchronizeCurrentFiles();
-
- polledIUsToAdd.clear();
- polledArtifactsToAdd.clear();
}
- private void synchronizeMetadataRepository(final Set removedFiles) {
- Query removeQuery = new Query() {
- public boolean isMatch(Object candidate) {
- if (!(candidate instanceof IInstallableUnit))
- return false;
- IInstallableUnit iu = (IInstallableUnit) candidate;
- File iuFile = new File(iu.getProperty(FILE_NAME));
- return removedFiles.contains(iuFile);
- }
- };
- metadataRepository.removeInstallableUnits(removeQuery, null);
-
- if (!polledIUsToAdd.isEmpty())
- metadataRepository.addInstallableUnits((IInstallableUnit[]) polledIUsToAdd.toArray(new IInstallableUnit[polledIUsToAdd.size()]));
+ public void stopPoll() {
+ synchronizeMetadataRepository(filesToRemove);
+ synchronizeArtifactRepository(filesToRemove);
+ filesToRemove.clear();
+ iusToAdd = null;
+ iusToChange = null;
+ currentFiles = null;
}
- private void synchronizeArtifactRepository(final Set removedFiles) {
- final List keys = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
- for (Iterator it = keys.iterator(); it.hasNext();) {
- IArtifactKey key = (IArtifactKey) it.next();
- IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key);
- for (int i = 0; i < descriptors.length; i++) {
- ArtifactDescriptor descriptor = (ArtifactDescriptor) descriptors[i];
- File artifactFile = new File(descriptor.getRepositoryProperty(FILE_NAME));
- if (removedFiles.contains(artifactFile))
- artifactRepository.removeDescriptor(descriptor);
+ /**
+ * Flush all the pending changes to the metadata repository.
+ */
+ private void synchronizeMetadataRepository(final Collection removedFiles) {
+ if (metadataRepository == null)
+ return;
+ final Collection changes = iusToChange.getIUs(null, null);
+ // first remove any IUs that have changed or that are associated with removed files
+ if (!removedFiles.isEmpty() || !changes.isEmpty()) {
+ // create a query that will identify all ius related to removed files or ius that have changed
+ Query removeQuery = new Query() {
+ public boolean isMatch(Object candidate) {
+ if (!(candidate instanceof IInstallableUnit))
+ return false;
+ IInstallableUnit iu = (IInstallableUnit) candidate;
+ if (changes.contains(iu))
+ return true;
+ File iuFile = new File(iu.getProperty(FILE_NAME));
+ return removedFiles.contains(iuFile);
+ }
+ };
+ metadataRepository.removeInstallableUnits(removeQuery, null);
+ }
+ // Then add all the new IUs as well as the new copies of the ones that have changed
+ Collection additions = iusToAdd.getIUs(null, null);
+ additions.addAll(changes);
+ if (!additions.isEmpty())
+ metadataRepository.addInstallableUnits((IInstallableUnit[]) additions.toArray(new IInstallableUnit[additions.size()]));
+ }
+
+ /**
+ * Here the artifacts have all been added to the artifact repo. Remove the
+ * descriptors related to any file that has been removed and flush the repo
+ * to ensure that all the additions and removals have been completed.
+ */
+ private void synchronizeArtifactRepository(final Collection removedFiles) {
+ if (artifactRepository == null)
+ return;
+ if (!removedFiles.isEmpty()) {
+ final List keys = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
+ for (Iterator it = keys.iterator(); it.hasNext();) {
+ IArtifactKey key = (IArtifactKey) it.next();
+ IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key);
+ for (int i = 0; i < descriptors.length; i++) {
+ ArtifactDescriptor descriptor = (ArtifactDescriptor) descriptors[i];
+ File artifactFile = new File(descriptor.getRepositoryProperty(FILE_NAME));
+ if (removedFiles.contains(artifactFile))
+ artifactRepository.removeDescriptor(descriptor);
+ }
}
}
-
- if (!polledArtifactsToAdd.isEmpty())
- artifactRepository.addDescriptors((IArtifactDescriptor[]) polledArtifactsToAdd.toArray(new IArtifactDescriptor[polledArtifactsToAdd.size()]));
+ artifactRepository.save();
}
+ /**
+ * Prime the list of current files that the listener knows about. This traverses the
+ * repos and looks for the related filename and modified timestamp information.
+ */
private void synchronizeCurrentFiles() {
currentFiles.clear();
if (metadataRepository != null) {
@@ -415,20 +276,22 @@
currentFiles.put(iuFile, iuLastModified);
}
}
-
- if (artifactRepository != null) {
- final List keys = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
- for (Iterator it = keys.iterator(); it.hasNext();) {
- IArtifactKey key = (IArtifactKey) it.next();
- IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key);
- for (int i = 0; i < descriptors.length; i++) {
- ArtifactDescriptor descriptor = (ArtifactDescriptor) descriptors[i];
- File artifactFile = new File(descriptor.getRepositoryProperty(FILE_NAME));
- Long artifactLastModified = new Long(descriptor.getRepositoryProperty(FILE_LAST_MODIFIED));
- currentFiles.put(artifactFile, artifactLastModified);
- }
- }
- }
+ //
+ // // TODO should we be doing this for the artifact repo? the metadata repo should
+ // // be the main driver here.
+ // if (artifactRepository != null) {
+ // final List keys = new ArrayList(Arrays.asList(artifactRepository.getArtifactKeys()));
+ // for (Iterator it = keys.iterator(); it.hasNext();) {
+ // IArtifactKey key = (IArtifactKey) it.next();
+ // IArtifactDescriptor[] descriptors = artifactRepository.getArtifactDescriptors(key);
+ // for (int i = 0; i < descriptors.length; i++) {
+ // ArtifactDescriptor descriptor = (ArtifactDescriptor) descriptors[i];
+ // File artifactFile = new File(descriptor.getRepositoryProperty(FILE_NAME));
+ // Long artifactLastModified = new Long(descriptor.getRepositoryProperty(FILE_LAST_MODIFIED));
+ // currentFiles.put(artifactFile, artifactLastModified);
+ // }
+ // }
+ // }
}
public IMetadataRepository getMetadataRepository() {
diff --git a/bundles/org.eclipse.equinox.p2.extensionlocation/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.extensionlocation/META-INF/MANIFEST.MF
index 3342328..ca104ad 100644
--- a/bundles/org.eclipse.equinox.p2.extensionlocation/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.extensionlocation/META-INF/MANIFEST.MF
@@ -10,7 +10,7 @@
CDC-1.1/Foundation-1.1
Export-Package: org.eclipse.equinox.internal.p2.extensionlocation;x-friends:="org.eclipse.equinox.p2.reconciler.dropins"
Import-Package: org.eclipse.equinox.internal.p2.core.helpers,
- org.eclipse.equinox.internal.p2.metadata.generator.features,
+ org.eclipse.equinox.internal.p2.publisher.eclipse,
org.eclipse.equinox.internal.p2.touchpoint.eclipse,
org.eclipse.equinox.internal.p2.update,
org.eclipse.equinox.internal.provisional.p2.artifact.repository,
@@ -19,12 +19,12 @@
org.eclipse.equinox.internal.provisional.p2.directorywatcher,
org.eclipse.equinox.internal.provisional.p2.engine,
org.eclipse.equinox.internal.provisional.p2.metadata,
- org.eclipse.equinox.internal.provisional.p2.metadata.generator,
org.eclipse.equinox.internal.provisional.p2.metadata.repository,
org.eclipse.equinox.internal.provisional.p2.query,
org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository,
org.eclipse.equinox.internal.provisional.spi.p2.core.repository,
org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository,
+ org.eclipse.equinox.p2.publisher.eclipse,
org.eclipse.osgi.service.datalocation;version="1.1.0",
org.eclipse.osgi.service.resolver;version="1.2.0",
org.eclipse.osgi.util,
diff --git a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
index aee3fcd..81117f4 100644
--- a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationArtifactRepository.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.extensionlocation;
@@ -18,7 +19,6 @@
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
import org.eclipse.equinox.internal.provisional.spi.p2.core.repository.AbstractRepository;
import org.eclipse.osgi.util.NLS;
@@ -28,9 +28,10 @@
public static final String TYPE = "org.eclipse.equinox.p2.extensionlocation.artifactRepository"; //$NON-NLS-1$
public static final Integer VERSION = new Integer(1);
- private final IFileArtifactRepository artifactRepository;
- private boolean initialized = false;
+
+ final IFileArtifactRepository artifactRepository;
private File base;
+ private Object state = SiteListener.UNINITIALIZED;
/*
* Return the location of a local repository based on
@@ -60,15 +61,14 @@
}
public synchronized void ensureInitialized() {
- if (initialized)
+ if (state == SiteListener.INITIALIZED || state == SiteListener.INITIALIZING)
return;
- File plugins = new File(base, PLUGINS);
- File features = new File(base, FEATURES);
- DirectoryWatcher watcher = new DirectoryWatcher(new File[] {plugins, features});
- DirectoryChangeListener listener = new RepositoryListener(Activator.getContext(), null, artifactRepository);
- watcher.addListener(listener);
- watcher.poll();
- initialized = true;
+ // if the repo has not been synchronized for us already, synchronize it.
+ SiteListener.synchronizeRepositories(null, this, base);
+ }
+
+ void state(Object value) {
+ state = value;
}
public static void validate(URL location, IProgressMonitor monitor) throws ProvisionException {
diff --git a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java
index 13c6b48..5cc250e 100644
--- a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java
+++ b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/ExtensionLocationMetadataRepository.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.extensionlocation;
@@ -16,7 +17,6 @@
import java.util.Map;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.*;
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.query.Collector;
@@ -29,9 +29,10 @@
public static final String TYPE = "org.eclipse.equinox.p2.extensionlocation.metadataRepository"; //$NON-NLS-1$
public static final Integer VERSION = new Integer(1);
- private final IMetadataRepository metadataRepository;
- private boolean initialized = false;
+
+ final IMetadataRepository metadataRepository;
private File base;
+ private Object state = SiteListener.UNINITIALIZED;
/*
* Return the URL for this repo's nested local repository.
@@ -60,17 +61,14 @@
}
public synchronized void ensureInitialized() {
- if (initialized)
+ if (state == SiteListener.INITIALIZED || state == SiteListener.INITIALIZING)
return;
- File plugins = new File(base, PLUGINS);
- File features = new File(base, FEATURES);
- DirectoryWatcher watcher = new DirectoryWatcher(new File[] {plugins, features});
- DirectoryChangeListener listener = new RepositoryListener(Activator.getContext(), metadataRepository, null);
- if (getProperties().get(SiteListener.SITE_POLICY) != null)
- listener = new SiteListener(getProperties(), location.toExternalForm(), new BundlePoolFilteredListener(listener));
- watcher.addListener(listener);
- watcher.poll();
- initialized = true;
+ // if the repo has not been synchronized for us already, synchronize it.
+ SiteListener.synchronizeRepositories(this, null, base);
+ }
+
+ void state(Object value) {
+ state = value;
}
/* (non-Javadoc)
diff --git a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/SiteListener.java b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/SiteListener.java
index 0f1fdab..41c85d9 100644
--- a/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/SiteListener.java
+++ b/bundles/org.eclipse.equinox.p2.extensionlocation/src/org/eclipse/equinox/internal/p2/extensionlocation/SiteListener.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.extensionlocation;
@@ -18,24 +19,27 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.URLUtil;
-import org.eclipse.equinox.internal.p2.metadata.generator.features.FeatureParser;
+import org.eclipse.equinox.internal.p2.publisher.eclipse.FeatureParser;
import org.eclipse.equinox.internal.p2.update.Site;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.*;
-import org.eclipse.equinox.internal.provisional.p2.directorywatcher.Messages;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
-import org.eclipse.osgi.service.resolver.*;
-import org.osgi.framework.ServiceReference;
+import org.eclipse.equinox.p2.publisher.eclipse.*;
+import org.eclipse.osgi.service.resolver.BundleDescription;
/**
* @since 1.0
*/
-public class SiteListener extends RepositoryListener {
+public class SiteListener extends DirectoryChangeListener {
public static final String SITE_POLICY = "org.eclipse.update.site.policy"; //$NON-NLS-1$
public static final String SITE_LIST = "org.eclipse.update.site.list"; //$NON-NLS-1$
private static final String FEATURES = "features"; //$NON-NLS-1$
private static final String PLUGINS = "plugins"; //$NON-NLS-1$
private static final String FEATURE_MANIFEST = "feature.xml"; //$NON-NLS-1$
+ public static final Object UNINITIALIZED = "uninitialized"; //$NON-NLS-1$
+ public static final Object INITIALIZING = "initializing"; //$NON-NLS-1$
+ public static final Object INITIALIZED = "initialized"; //$NON-NLS-1$
+
private String policy;
private String[] list;
private String url;
@@ -55,11 +59,53 @@
return false;
}
+ /**
+ * Given one repo and a base location, ensure cause the other repo to be loaded and then
+ * poll the base location once updating the repositories accordingly. This method is used to
+ * ensure that both the metadata and artifact repos corresponding to one location are
+ * synchronized in one go. It is expected that both repos have been previously created
+ * so simply loading them here will work and that all their properties etc have been configured
+ * previously.
+ * @param metadataRepository
+ * @param artifactRepository
+ * @param base
+ */
+ public static synchronized void synchronizeRepositories(ExtensionLocationMetadataRepository metadataRepository, ExtensionLocationArtifactRepository artifactRepository, File base) {
+ try {
+ if (metadataRepository == null) {
+ ExtensionLocationMetadataRepositoryFactory factory = new ExtensionLocationMetadataRepositoryFactory();
+ metadataRepository = (ExtensionLocationMetadataRepository) factory.load(artifactRepository.getLocation(), null);
+ } else if (artifactRepository == null) {
+ ExtensionLocationArtifactRepositoryFactory factory = new ExtensionLocationArtifactRepositoryFactory();
+ artifactRepository = (ExtensionLocationArtifactRepository) factory.load(metadataRepository.getLocation(), null);
+ }
+ } catch (ProvisionException e) {
+ // TODO need proper error handling here. What should we do if there is a failure
+ // when loading "the other" repo?
+ e.printStackTrace();
+ return;
+ }
+
+ artifactRepository.state(INITIALIZING);
+ metadataRepository.state(INITIALIZING);
+ File plugins = new File(base, PLUGINS);
+ File features = new File(base, FEATURES);
+ DirectoryWatcher watcher = new DirectoryWatcher(new File[] {plugins, features});
+ // here we have to sync with the inner repos as the extension location repos are
+ // read-only wrappers.
+ DirectoryChangeListener listener = new RepositoryListener(metadataRepository.metadataRepository, artifactRepository.artifactRepository);
+ if (metadataRepository.getProperties().get(SiteListener.SITE_POLICY) != null)
+ listener = new SiteListener(metadataRepository.getProperties(), metadataRepository.getLocation().toExternalForm(), new BundlePoolFilteredListener(listener));
+ watcher.addListener(listener);
+ watcher.poll();
+ artifactRepository.state(INITIALIZED);
+ metadataRepository.state(INITIALIZED);
+ }
+
/*
* Create a new site listener on the given site.
*/
public SiteListener(Map properties, String url, DirectoryChangeListener delegate) {
- super(Activator.getContext(), url, null, true);
this.url = url;
this.delegate = delegate;
this.policy = (String) properties.get(SITE_POLICY);
@@ -77,7 +123,7 @@
public boolean isInterested(File file) {
// make sure that our delegate and super-class are both interested in
// the file before we consider it
- if (!delegate.isInterested(file) || !super.isInterested(file))
+ if (!delegate.isInterested(file))
return false;
if (Site.POLICY_MANAGED_ONLY.equals(policy)) {
// we only want plug-ins referenced by features
@@ -209,7 +255,7 @@
File featureFile = (File) iter.next();
// add the feature path
result.add(featureFile.toString());
- org.eclipse.equinox.internal.provisional.p2.metadata.generator.Feature feature = (org.eclipse.equinox.internal.provisional.p2.metadata.generator.Feature) featureCache.get(featureFile);
+ Feature feature = (Feature) featureCache.get(featureFile);
FeatureEntry[] entries = feature.getEntries();
for (int inner = 0; inner < entries.length; inner++) {
FeatureEntry entry = entries[inner];
@@ -249,32 +295,20 @@
* plug-in id/version to File locations.
*/
private Map getPlugins(File siteLocation) {
- ServiceReference reference = Activator.getContext().getServiceReference(PlatformAdmin.class.getName());
- if (reference == null)
- throw new IllegalStateException(Messages.platformadmin_not_registered);
- try {
- PlatformAdmin platformAdmin = (PlatformAdmin) Activator.getContext().getService(reference);
- if (platformAdmin == null)
- throw new IllegalStateException(Messages.platformadmin_not_registered);
- StateObjectFactory stateObjectFactory = platformAdmin.getFactory();
- BundleDescriptionFactory factory = new BundleDescriptionFactory(stateObjectFactory, null);
- File[] plugins = new File(siteLocation, PLUGINS).listFiles();
- Map result = new HashMap();
- for (int i = 0; plugins != null && i < plugins.length; i++) {
- File bundleLocation = plugins[i];
- if (bundleLocation.isDirectory() || bundleLocation.getName().endsWith(".jar")) {
- BundleDescription description = factory.getBundleDescription(bundleLocation);
- if (description != null) {
- String id = description.getSymbolicName();
- String version = description.getVersion().toString();
- result.put(id + '/' + version, bundleLocation);
- }
+ File[] plugins = new File(siteLocation, PLUGINS).listFiles();
+ Map result = new HashMap();
+ for (int i = 0; plugins != null && i < plugins.length; i++) {
+ File bundleLocation = plugins[i];
+ if (bundleLocation.isDirectory() || bundleLocation.getName().endsWith(".jar")) { //$NON-NLS-1$
+ BundleDescription description = BundlesAction.createBundleDescription(bundleLocation);
+ if (description != null) {
+ String id = description.getSymbolicName();
+ String version = description.getVersion().toString();
+ result.put(id + '/' + version, bundleLocation);
}
}
- return result;
- } finally {
- Activator.getContext().ungetService(reference);
}
+ return result;
}
/* (non-Javadoc)
@@ -318,5 +352,4 @@
public void stopPoll() {
delegate.stopPoll();
}
-
}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
index 6c6ce1f..6bb464a 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/Activator.java
@@ -462,7 +462,7 @@
if (directories.isEmpty())
return;
- DropinsRepositoryListener listener = new DropinsRepositoryListener(Activator.getContext(), DROPINS);
+ DropinsRepositoryListener listener = new DropinsRepositoryListener(DROPINS);
DirectoryWatcher watcher = new DirectoryWatcher((File[]) directories.toArray(new File[directories.size()]));
watcher.addListener(listener);
watcher.poll();
@@ -634,4 +634,15 @@
}
return null;
}
+
+ // TODO Fix this up to get the services in a better way
+ public static IArtifactRepositoryManager getArtifactRepositoryManager() {
+ return (IArtifactRepositoryManager) ServiceHelper.getService(bundleContext, IArtifactRepositoryManager.class.getName());
+ }
+
+ // TODO Fix this up to get the services in a better way
+ public static IMetadataRepositoryManager getMetadataRepositoryManager() {
+ return (IMetadataRepositoryManager) ServiceHelper.getService(bundleContext, IMetadataRepositoryManager.class.getName());
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java
index 8771e00..4f2fba7 100644
--- a/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java
+++ b/bundles/org.eclipse.equinox.p2.reconciler.dropins/src/org/eclipse/equinox/internal/p2/reconciler/dropins/DropinsRepositoryListener.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.reconciler.dropins;
@@ -26,11 +27,8 @@
import org.eclipse.equinox.internal.provisional.p2.directorywatcher.RepositoryListener;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
public class DropinsRepositoryListener extends RepositoryListener {
-
private static final String PLUGINS = "plugins"; //$NON-NLS-1$
private static final String FEATURES = "features"; //$NON-NLS-1$
private static final String JAR = ".jar"; //$NON-NLS-1$
@@ -40,13 +38,11 @@
private static final String DROPIN_ARTIFACT_REPOSITORIES = "dropin.artifactRepositories"; //$NON-NLS-1$
private static final String DROPIN_METADATA_REPOSITORIES = "dropin.metadataRepositories"; //$NON-NLS-1$
private static final String PIPE = "|"; //$NON-NLS-1$
- private BundleContext context;
private List metadataRepositories = new ArrayList();
private List artifactRepositories = new ArrayList();
- public DropinsRepositoryListener(BundleContext context, String repositoryName) {
- super(context, repositoryName, null, true);
- this.context = context;
+ public DropinsRepositoryListener(String repositoryName) {
+ super(repositoryName, true);
}
public boolean isInterested(File file) {
@@ -217,19 +213,13 @@
}
private void removeMetadataRepository(String urlString) {
- ServiceReference reference = context.getServiceReference(IMetadataRepositoryManager.class.getName());
- IMetadataRepositoryManager manager = null;
- if (reference != null)
- manager = (IMetadataRepositoryManager) context.getService(reference);
+ IMetadataRepositoryManager manager = Activator.getMetadataRepositoryManager();
if (manager == null)
throw new IllegalStateException(Messages.metadata_repo_manager_not_registered);
-
try {
manager.removeRepository(new URL(urlString));
} catch (MalformedURLException e) {
LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error occurred while creating URL from: " + urlString, e)); //$NON-NLS-1$
- } finally {
- context.ungetService(reference);
}
}
@@ -250,19 +240,13 @@
}
public void removeArtifactRepository(String urlString) {
- ServiceReference reference = context.getServiceReference(IArtifactRepositoryManager.class.getName());
- IArtifactRepositoryManager manager = null;
- if (reference != null)
- manager = (IArtifactRepositoryManager) context.getService(reference);
+ IArtifactRepositoryManager manager = Activator.getArtifactRepositoryManager();
if (manager == null)
throw new IllegalStateException(Messages.artifact_repo_manager_not_registered);
-
try {
manager.removeRepository(new URL(urlString));
} catch (MalformedURLException e) {
LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Error occurred while creating URL from: " + urlString, e)); //$NON-NLS-1$
- } finally {
- context.ungetService(reference);
}
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/.classpath b/bundles/org.eclipse.equinox.p2.tests/.classpath
index ce73933..2fbb7a2 100644
--- a/bundles/org.eclipse.equinox.p2.tests/.classpath
+++ b/bundles/org.eclipse.equinox.p2.tests/.classpath
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
- <classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.4"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/bundles/org.eclipse.equinox.p2.tests/.settings/org.eclipse.jdt.core.prefs b/bundles/org.eclipse.equinox.p2.tests/.settings/org.eclipse.jdt.core.prefs
index 20b2cd0..b4fdaeb 100644
--- a/bundles/org.eclipse.equinox.p2.tests/.settings/org.eclipse.jdt.core.prefs
+++ b/bundles/org.eclipse.equinox.p2.tests/.settings/org.eclipse.jdt.core.prefs
@@ -1,4 +1,4 @@
-#Fri Apr 25 12:15:58 EDT 2008
+#Tue Aug 19 22:58:53 EDT 2008
eclipse.preferences.version=1
instance/org.eclipse.core.net/org.eclipse.core.net.hasMigrated=true
org.eclipse.jdt.core.builder.cleanOutputFolder=clean
@@ -157,7 +157,6 @@
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=true
org.eclipse.jdt.core.formatter.indentation.size=4
-org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert
org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
diff --git a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF
index 4af2c5f..2edc3ec 100644
--- a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF
@@ -15,6 +15,7 @@
org.eclipse.equinox.internal.p2.metadata.repository,
org.eclipse.equinox.internal.p2.metadata.repository.io,
org.eclipse.equinox.internal.p2.persistence,
+ org.eclipse.equinox.internal.p2.publisher.eclipse,
org.eclipse.equinox.internal.p2.resolution,
org.eclipse.equinox.internal.p2.touchpoint.eclipse,
org.eclipse.equinox.internal.p2.updatesite,
@@ -37,6 +38,7 @@
org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository,
org.eclipse.equinox.internal.provisional.spi.p2.core.repository,
org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository,
+ org.eclipse.equinox.spi.p2.publisher,
org.eclipse.osgi.service.environment;version="1.0.0",
org.eclipse.osgi.service.resolver;version="1.1.0",
org.eclipse.osgi.service.urlconversion;version="1.0.0",
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java
index a0eac7f..cb4d5a6 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/repository/SimpleArtifactRepositoryTest.java
@@ -7,6 +7,7 @@
*
* Contributors:
* compeople AG (Stefan Liebig) - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.p2.tests.artifact.repository;
@@ -18,13 +19,13 @@
import junit.framework.TestCase;
import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
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.artifact.repository.*;
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.generator.EclipseInstallGeneratorInfoProvider;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.Generator;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.tests.TestActivator;
+import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
+import org.osgi.framework.Version;
public class SimpleArtifactRepositoryTest extends TestCase {
//artifact repository to remove on tear down
@@ -87,13 +88,11 @@
Map properties = new HashMap();
properties.put(IRepository.PROP_COMPRESSED, "true");
IArtifactRepository repo = artifactRepositoryManager.createRepository(repositoryURL, "artifact name", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
- EclipseInstallGeneratorInfoProvider provider = new EclipseInstallGeneratorInfoProvider();
- provider.setArtifactRepository(repo);
- provider.initialize(repositoryFile);
- provider.setRootVersion("3.3");
- provider.setRootId("sdk");
- provider.setFlavor("tooling");
- new Generator(provider).generate();
+
+ IArtifactKey key = PublisherHelper.createBinaryArtifactKey("testKeyId", new Version("1.2.3"));
+ IArtifactDescriptor descriptor = PublisherHelper.createArtifactDescriptor(key, null);
+ repo.addDescriptor(descriptor);
+
File files[] = repositoryFile.listFiles();
boolean jarFilePresent = false;
boolean artifactFilePresent = false;
@@ -105,6 +104,8 @@
artifactFilePresent = false;
}
}
+ delete(repositoryFile);
+
if (!jarFilePresent)
fail("Repository should create JAR for artifact.xml");
if (artifactFilePresent)
@@ -120,13 +121,11 @@
Map properties = new HashMap();
properties.put(IRepository.PROP_COMPRESSED, "false");
IArtifactRepository repo = artifactRepositoryManager.createRepository(repositoryURL, "artifact name", IArtifactRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
- EclipseInstallGeneratorInfoProvider provider = new EclipseInstallGeneratorInfoProvider();
- provider.setArtifactRepository(repo);
- provider.initialize(repositoryFile);
- provider.setRootVersion("3.3");
- provider.setRootId("sdk");
- provider.setFlavor("tooling");
- new Generator(provider).generate();
+
+ IArtifactKey key = PublisherHelper.createBinaryArtifactKey("testKeyId", new Version("1.2.3"));
+ IArtifactDescriptor descriptor = PublisherHelper.createArtifactDescriptor(key, null);
+ repo.addDescriptor(descriptor);
+
File files[] = repositoryFile.listFiles();
boolean jarFilePresent = false;
boolean artifactFilePresent = false;
@@ -138,6 +137,8 @@
artifactFilePresent = true;
}
}
+ delete(repositoryFile);
+
if (jarFilePresent)
fail("Repository should not create JAR for artifact.xml");
if (!artifactFilePresent)
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/TestRepositoryWatcher.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/TestRepositoryWatcher.java
index 321612b..8ce3f70 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/TestRepositoryWatcher.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/directorywatcher/TestRepositoryWatcher.java
@@ -36,7 +36,7 @@
* Create and return a new test directory watcher class which will listen on the given folder.
*/
public static TestRepositoryWatcher createWatcher(File folder) {
- RepositoryListener listener = new RepositoryListener(TestActivator.getContext(), AbstractProvisioningTest.getUniqueString(), null, false);
+ RepositoryListener listener = new RepositoryListener(AbstractProvisioningTest.getUniqueString(), false);
Dictionary props = new Hashtable();
props.put(DirectoryWatcher.DIR, folder.getAbsolutePath());
props.put(DirectoryWatcher.POLL, "500");
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/JarURLRepositoryTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/JarURLRepositoryTest.java
index 4e3b996..3701411 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/JarURLRepositoryTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/JarURLRepositoryTest.java
@@ -7,24 +7,29 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.p2.tests.metadata.repository;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
import junit.framework.TestCase;
-import org.eclipse.core.runtime.FileLocator;
import org.eclipse.equinox.internal.p2.core.helpers.FileUtils;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.EclipseInstallGeneratorInfoProvider;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.Generator;
+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.MetadataFactory;
+import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
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.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.equinox.internal.provisional.p2.query.Collector;
import org.eclipse.equinox.p2.tests.TestActivator;
import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
public class JarURLRepositoryTest extends TestCase {
@@ -40,44 +45,32 @@
this("");
}
- private static boolean deleteDirectory(File directory) {
- if (directory.exists() && directory.isDirectory()) {
- File[] files = directory.listFiles();
- for (int i = 0; i < files.length; i++) {
- if (files[i].isDirectory()) {
- deleteDirectory(files[i]);
- } else {
- files[i].delete();
- }
- }
- }
- return directory.delete();
- }
-
protected void setUp() throws Exception {
managerRef = TestActivator.getContext().getServiceReference(IMetadataRepositoryManager.class.getName());
manager = (IMetadataRepositoryManager) TestActivator.getContext().getService(managerRef);
- EclipseInstallGeneratorInfoProvider provider = new EclipseInstallGeneratorInfoProvider();
- URL base = TestActivator.getContext().getBundle().getEntry("/testData/generator/eclipse3.3");
- provider.initialize(new File(FileLocator.toFileURL(base).getPath()));
String tempDir = System.getProperty("java.io.tmpdir");
File testRepo = new File(tempDir, "testRepo");
- deleteDirectory(testRepo);
+ FileUtils.deleteAll(testRepo);
testRepo.mkdir();
- provider.setFlavor("jartest");
- IMetadataRepository repository = manager.createRepository(testRepo.toURL(), "testRepo", IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, null);
- provider.setMetadataRepository(repository);
- new Generator(provider).generate();
- testRepoJar = new File(tempDir, "testRepo.jar");
- FileUtils.zip(new File[] {testRepo}, null, testRepoJar, FileUtils.createDynamicPathComputer(1));
+ Map properties = new HashMap();
+ properties.put(IRepository.PROP_COMPRESSED, "true");
+ IMetadataRepository repo = manager.createRepository(testRepo.toURL(), "TestRepo", IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
+
+ InstallableUnitDescription descriptor = new MetadataFactory.InstallableUnitDescription();
+ descriptor.setId("testIuId");
+ descriptor.setVersion(new Version("3.2.1"));
+ IInstallableUnit iu = MetadataFactory.createInstallableUnit(descriptor);
+ repo.addInstallableUnits(new IInstallableUnit[] {iu});
+
+ testRepoJar = new File(testRepo, "content.jar");
assertTrue(testRepoJar.exists());
testRepoJar.deleteOnExit();
- deleteDirectory(testRepo);
}
protected void tearDown() throws Exception {
manager = null;
+ FileUtils.deleteAll(testRepoJar.getParentFile());
TestActivator.getContext().ungetService(managerRef);
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/LocalMetadataRepositoryTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/LocalMetadataRepositoryTest.java
index 24e1407..df79929 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/LocalMetadataRepositoryTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/metadata/repository/LocalMetadataRepositoryTest.java
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.p2.tests.metadata.repository;
@@ -19,12 +20,14 @@
import org.eclipse.equinox.internal.provisional.p2.core.eventbus.*;
import org.eclipse.equinox.internal.provisional.p2.core.repository.IRepository;
import org.eclipse.equinox.internal.provisional.p2.core.repository.RepositoryEvent;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.EclipseInstallGeneratorInfoProvider;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.Generator;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory;
+import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepositoryManager;
import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
import org.eclipse.equinox.p2.tests.TestActivator;
+import org.osgi.framework.Version;
/**
* Test API of the local metadata repository implementation.
@@ -57,14 +60,13 @@
Map properties = new HashMap();
properties.put(IRepository.PROP_COMPRESSED, "true");
IMetadataRepository repo = manager.createRepository(repoLocation.toURL(), "TestRepo", IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
- EclipseInstallGeneratorInfoProvider provider = new EclipseInstallGeneratorInfoProvider();
- provider.setMetadataRepository(repo);
- provider.initialize(repoLocation);
- provider.setRootVersion("3.3");
- provider.setRootId("sdk");
- provider.setFlavor("tooling");
- // Generate the repository
- new Generator(provider).generate();
+
+ InstallableUnitDescription descriptor = new MetadataFactory.InstallableUnitDescription();
+ descriptor.setId("testIuId");
+ descriptor.setVersion(new Version("3.2.1"));
+ IInstallableUnit iu = MetadataFactory.createInstallableUnit(descriptor);
+ repo.addInstallableUnits(new IInstallableUnit[] {iu});
+
File[] files = repoLocation.listFiles();
boolean jarFilePresent = false;
boolean xmlFilePresent = false;
@@ -126,14 +128,13 @@
Map properties = new HashMap();
properties.put(IRepository.PROP_COMPRESSED, "false");
IMetadataRepository repo = manager.createRepository(repoLocation.toURL(), "TestRepo", IMetadataRepositoryManager.TYPE_SIMPLE_REPOSITORY, properties);
- EclipseInstallGeneratorInfoProvider provider = new EclipseInstallGeneratorInfoProvider();
- provider.setMetadataRepository(repo);
- provider.initialize(repoLocation);
- provider.setRootVersion("3.3");
- provider.setRootId("sdk");
- provider.setFlavor("tooling");
- // Generate the repository
- new Generator(provider).generate();
+
+ InstallableUnitDescription descriptor = new MetadataFactory.InstallableUnitDescription();
+ descriptor.setId("testIuId");
+ descriptor.setVersion(new Version("3.2.1"));
+ IInstallableUnit iu = MetadataFactory.createInstallableUnit(descriptor);
+ repo.addInstallableUnits(new IInstallableUnit[] {iu});
+
File[] files = repoLocation.listFiles();
boolean jarFilePresent = false;
// none of the files in the repository should be the content.xml.jar
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/updatesite/UpdateSiteTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/updatesite/UpdateSiteTest.java
index ba9f4d7..7b767d5 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/updatesite/UpdateSiteTest.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/updatesite/UpdateSiteTest.java
@@ -10,7 +10,8 @@
*******************************************************************************/
package org.eclipse.equinox.p2.tests.updatesite;
-import java.io.*;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import junit.framework.Test;
@@ -456,27 +457,9 @@
IArtifactKey[] keys = artifactRepo.getArtifactKeys();
for (int i = 0; i < keys.length; i++) {
if (keys[i].getId().equals("Plugin240121")) {
- FileOutputStream fos = null;
- try {
- File tmp;
- try {
- tmp = File.createTempFile("p2.test", "test");
- tmp.deleteOnExit();
- fos = new FileOutputStream(tmp);
- } catch (IOException e1) {
- fail("Can't create temp file");
- }
- IStatus status = artifactRepo.getArtifact(artifactRepo.getArtifactDescriptors(keys[i])[0], fos, new NullProgressMonitor());
- if (!status.isOK())
- fail("Can't get the expected artifact:" + keys[i]);
- } finally {
- if (fos != null)
- try {
- fos.close();
- } catch (IOException e) {
- //ignore
- }
- }
+ IStatus status = artifactRepo.getArtifact(artifactRepo.getArtifactDescriptors(keys[i])[0], new ByteArrayOutputStream(500), new NullProgressMonitor());
+ if (!status.isOK())
+ fail("Can't get the expected artifact:" + keys[i]);
}
}
}
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/META-INF/MANIFEST.MF
index 5ea562a..00a219c 100644
--- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/META-INF/MANIFEST.MF
@@ -17,11 +17,12 @@
org.eclipse.equinox.internal.provisional.p2.core.repository,
org.eclipse.equinox.internal.provisional.p2.engine,
org.eclipse.equinox.internal.provisional.p2.metadata,
- org.eclipse.equinox.internal.provisional.p2.metadata.generator;resolution:=optional,
org.eclipse.equinox.internal.provisional.p2.metadata.query,
org.eclipse.equinox.internal.provisional.p2.query,
org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository,
org.eclipse.equinox.internal.simpleconfigurator.manipulator,
+ org.eclipse.equinox.p2.publisher.eclipse;resolution:=optional,
+ org.eclipse.equinox.spi.p2.publisher;resolution:=optional,
org.eclipse.osgi.service.datalocation;version="1.0.0",
org.eclipse.osgi.service.environment;version="1.0.0",
org.eclipse.osgi.service.resolver;version="1.2.0";resolution:=optional,
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java
index dda2c4f..611e902 100644
--- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java
+++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/EclipseTouchpoint.java
@@ -4,7 +4,9 @@
* 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
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
******************************************************************************/
package org.eclipse.equinox.internal.p2.touchpoint.eclipse;
@@ -20,6 +22,9 @@
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.engine.*;
import org.eclipse.equinox.internal.provisional.p2.metadata.*;
+import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
+import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
+import org.eclipse.osgi.service.resolver.BundleDescription;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.Version;
@@ -103,7 +108,7 @@
Class c = null;
try {
- c = Class.forName("org.eclipse.equinox.internal.provisional.p2.metadata.generator.MetadataGeneratorHelper"); //$NON-NLS-1$
+ c = Class.forName("org.eclipse.equinox.spi.p2.publisher.PublisherHelper"); //$NON-NLS-1$
if (c != null)
c = Class.forName("org.eclipse.osgi.service.resolver.PlatformAdmin"); //$NON-NLS-1$
} catch (ClassNotFoundException e) {
@@ -124,13 +129,18 @@
LogHelper.log(Util.createError(NLS.bind(Messages.artifact_file_not_found, artifactKey.toString())));
return null;
}
- return MetadataGeneratorUtils.createBundleIU(artifactKey, bundleFile);
+ return createBundleIU(artifactKey, bundleFile);
}
// should not occur
throw new IllegalStateException(Messages.unexpected_prepareiu_error);
}
+ private IInstallableUnit createBundleIU(IArtifactKey artifactKey, File bundleFile) {
+ BundleDescription bundleDescription = BundlesAction.createBundleDescription(bundleFile);
+ return PublisherHelper.createBundleIU(bundleDescription, (Map) bundleDescription.getUserObject(), bundleFile.isDirectory(), artifactKey);
+ }
+
public static IStatus loadManipulator(Manipulator manipulator) {
try {
manipulator.load();
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/MetadataGeneratorUtils.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/MetadataGeneratorUtils.java
deleted file mode 100644
index e5fe603..0000000
--- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/MetadataGeneratorUtils.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*******************************************************************************
- * 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.touchpoint.eclipse;
-
-import java.io.File;
-import java.util.Map;
-import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
-import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.BundleDescriptionFactory;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.MetadataGeneratorHelper;
-import org.eclipse.osgi.service.resolver.*;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public class MetadataGeneratorUtils {
-
- public static IInstallableUnit createBundleIU(IArtifactKey artifactKey, File bundleFile) {
- BundleDescriptionFactory factory = initializeBundleDescriptionFactory(Activator.getContext());
- BundleDescription bundleDescription = factory.getBundleDescription(bundleFile);
- if (bundleDescription == null)
- return null;
- return MetadataGeneratorHelper.createBundleIU(bundleDescription, (Map) bundleDescription.getUserObject(), bundleFile.isDirectory(), artifactKey);
- }
-
- private static BundleDescriptionFactory initializeBundleDescriptionFactory(BundleContext context) {
-
- ServiceReference reference = context.getServiceReference(PlatformAdmin.class.getName());
- if (reference == null)
- throw new IllegalStateException(Messages.platformadmin_not_registered);
- PlatformAdmin platformAdmin = (PlatformAdmin) context.getService(reference);
- if (platformAdmin == null)
- throw new IllegalStateException(Messages.platformadmin_not_registered);
-
- try {
- StateObjectFactory stateObjectFactory = platformAdmin.getFactory();
- return new BundleDescriptionFactory(stateObjectFactory, null);
- } finally {
- context.ungetService(reference);
- }
- }
-
-}
diff --git a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java
index 83fea97..1fbcf5a 100644
--- a/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java
+++ b/bundles/org.eclipse.equinox.p2.touchpoint.eclipse/src/org/eclipse/equinox/internal/p2/touchpoint/eclipse/Util.java
@@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Red Hat Incorporated - fix for bug 225145
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.touchpoint.eclipse;
@@ -260,9 +261,15 @@
if (name == null)
name = "eclipse"; //$NON-NLS-1$
+ if (os.equals(org.eclipse.osgi.service.environment.Constants.OS_WIN32)) {
+ IPath path = new Path(name);
+ if ("exe".equals(path.getFileExtension())) //$NON-NLS-1$
+ return name;
+ return name + ".exe";
+ }
if (os.equals(org.eclipse.osgi.service.environment.Constants.OS_MACOSX)) {
IPath path = new Path(name);
- if (path.segment(0).endsWith(".app")) //$NON-NLS-1$
+ if ("app".equals(path.getFileExtension())) //$NON-NLS-1$
return name;
StringBuffer buffer = new StringBuffer();
buffer.append(name.substring(0, 1).toUpperCase());
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF
index ce312f6..29694dc 100644
--- a/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.updatesite/META-INF/MANIFEST.MF
@@ -8,19 +8,22 @@
Bundle-Activator: org.eclipse.equinox.internal.p2.updatesite.Activator
Eclipse-LazyStart: true
Import-Package: org.eclipse.equinox.internal.p2.core.helpers,
- org.eclipse.equinox.internal.p2.metadata.generator.features,
+ org.eclipse.equinox.internal.p2.publisher.eclipse,
org.eclipse.equinox.internal.provisional.p2.artifact.repository,
org.eclipse.equinox.internal.provisional.p2.core,
org.eclipse.equinox.internal.provisional.p2.core.eventbus,
org.eclipse.equinox.internal.provisional.p2.core.repository,
org.eclipse.equinox.internal.provisional.p2.metadata,
- org.eclipse.equinox.internal.provisional.p2.metadata.generator,
org.eclipse.equinox.internal.provisional.p2.metadata.repository,
org.eclipse.equinox.internal.provisional.p2.query,
org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository,
org.eclipse.equinox.internal.provisional.spi.p2.core.repository,
org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository,
+ org.eclipse.equinox.p2.publisher,
+ org.eclipse.equinox.p2.publisher.actions,
+ org.eclipse.equinox.p2.publisher.eclipse,
org.eclipse.equinox.security.storage,
+ org.eclipse.equinox.spi.p2.publisher,
org.eclipse.osgi.service.resolver;version="1.2.0",
org.eclipse.osgi.signedcontent;version="1.0.0",
org.eclipse.osgi.util;version="1.1.0",
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/DefaultSiteParser.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/DefaultSiteParser.java
new file mode 100644
index 0000000..659c047
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/DefaultSiteParser.java
@@ -0,0 +1,859 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.updatesite;
+
+import java.io.*;
+import java.util.*;
+import javax.xml.parsers.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+import org.eclipse.equinox.internal.p2.core.helpers.Tracing;
+import org.eclipse.equinox.p2.publisher.eclipse.URLEntry;
+import org.eclipse.osgi.util.NLS;
+import org.w3c.dom.*;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Parses a site.xml file.
+ * This class was initially copied from org.eclipse.update.core.model.DefaultSiteParser.
+ */
+public class DefaultSiteParser extends DefaultHandler {
+
+ private static final String ARCHIVE = "archive"; //$NON-NLS-1$
+ private static final String CATEGORY = "category"; //$NON-NLS-1$
+ private static final String CATEGORY_DEF = "category-def"; //$NON-NLS-1$
+
+ private static final String ASSOCIATE_SITES_URL = "associateSitesURL"; //$NON-NLS-1$
+ private static final String ASSOCIATE_SITE = "associateSite"; //$NON-NLS-1$
+ private static final String DEFAULT_INFO_URL = "index.html"; //$NON-NLS-1$
+ private static final String DESCRIPTION = "description"; //$NON-NLS-1$
+ private static final String FEATURE = "feature"; //$NON-NLS-1$
+ private static final String FEATURES = "features/"; //$NON-NLS-1$
+ private static final String MIRROR = "mirror"; //$NON-NLS-1$
+ private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ private static final String PLUGIN_ID = Activator.ID;
+ private static final String SITE = "site"; //$NON-NLS-1$
+
+ private static final int STATE_ARCHIVE = 3;
+ private static final int STATE_CATEGORY = 4;
+ private static final int STATE_CATEGORY_DEF = 5;
+ private static final int STATE_DESCRIPTION_CATEGORY_DEF = 7;
+ private static final int STATE_DESCRIPTION_SITE = 6;
+ private static final int STATE_FEATURE = 2;
+ private static final int STATE_IGNORED_ELEMENT = -1;
+ private static final int STATE_INITIAL = 0;
+ private static final int STATE_SITE = 1;
+
+ private int currentState;
+
+ private boolean DESCRIPTION_SITE_ALREADY_SEEN = false;
+ // Current object stack (used to hold the current object we are
+ // populating in this plugin descriptor
+ Stack objectStack = new Stack();
+
+ private SAXParser parser;
+
+ // Current State Information
+ Stack stateStack = new Stack();
+
+ // List of string keys for translated strings
+ private final List messageKeys = new ArrayList(4);
+
+ private MultiStatus status;
+
+ /*
+ *
+ */
+ private static void debug(String s) {
+ Tracing.debug("DefaultSiteParser: " + s); //$NON-NLS-1$
+ }
+
+ private static URLEntry[] getAssociateSites(String associateSitesURL) {
+
+ try {
+ DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = domFactory.newDocumentBuilder();
+ Document document = builder.parse(associateSitesURL);
+ if (document == null)
+ return null;
+ NodeList mirrorNodes = document.getElementsByTagName(ASSOCIATE_SITE);
+ URLEntry[] mirrors = new URLEntry[mirrorNodes.getLength()];
+ for (int i = 0; i < mirrorNodes.getLength(); i++) {
+ Element mirrorNode = (Element) mirrorNodes.item(i);
+ mirrors[i] = new URLEntry();
+ String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
+ String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$
+ mirrors[i].setURL(infoURL);
+ mirrors[i].setAnnotation(label);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return mirrors;
+ } catch (Exception e) {
+ // log if absolute url
+ if (associateSitesURL != null && (associateSitesURL.startsWith("http://") //$NON-NLS-1$
+ || associateSitesURL.startsWith("https://") //$NON-NLS-1$
+ || associateSitesURL.startsWith("file://") //$NON-NLS-1$
+ || associateSitesURL.startsWith("ftp://") //$NON-NLS-1$
+ || associateSitesURL.startsWith("jar://"))) //$NON-NLS-1$
+ log(Messages.DefaultSiteParser_mirrors, e);
+ return null;
+ }
+ }
+
+ static URLEntry[] getMirrors(String mirrorsURL) {
+
+ try {
+ String countryCode = Locale.getDefault().getCountry().toLowerCase();
+ int timeZone = (new GregorianCalendar()).get(Calendar.ZONE_OFFSET) / (60 * 60 * 1000);
+
+ if (mirrorsURL.indexOf("?") != -1) { //$NON-NLS-1$
+ mirrorsURL = mirrorsURL + "&"; //$NON-NLS-1$
+ } else {
+ mirrorsURL = mirrorsURL + "?"; //$NON-NLS-1$
+ }
+ mirrorsURL = mirrorsURL + "countryCode=" + countryCode + "&timeZone=" + timeZone + "&responseType=xml"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = domFactory.newDocumentBuilder();
+ Document document = builder.parse(mirrorsURL);
+ if (document == null)
+ return null;
+ NodeList mirrorNodes = document.getElementsByTagName(MIRROR);
+ URLEntry[] mirrors = new URLEntry[mirrorNodes.getLength()];
+ for (int i = 0; i < mirrorNodes.getLength(); i++) {
+ Element mirrorNode = (Element) mirrorNodes.item(i);
+ mirrors[i] = new URLEntry();
+ String infoURL = mirrorNode.getAttribute("url"); //$NON-NLS-1$
+ String label = mirrorNode.getAttribute("label"); //$NON-NLS-1$
+ mirrors[i].setURL(infoURL);
+ mirrors[i].setAnnotation(label);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("Processed mirror: url:" + infoURL + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ return mirrors;
+ } catch (Exception e) {
+ // log if absolute url
+ if (mirrorsURL != null && (mirrorsURL.startsWith("http://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("https://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("file://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("ftp://") //$NON-NLS-1$
+ || mirrorsURL.startsWith("jar://"))) //$NON-NLS-1$
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, Messages.DefaultSiteParser_mirrors, e));
+ return null;
+ }
+ }
+
+ static void log(Exception e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, "Internal Error", e)); //$NON-NLS-1$
+ }
+
+ static void log(IStatus error) {
+ LogHelper.log(error);
+ }
+
+ static void log(String message) {
+ LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, null));
+ }
+
+ static void log(String message, Exception e) {
+ LogHelper.log(new Status(IStatus.WARNING, Activator.ID, message, e));
+ }
+
+ /**
+ * Constructs a site parser.
+ */
+ public DefaultSiteParser() {
+ super();
+ stateStack = new Stack();
+ objectStack = new Stack();
+ status = null;
+ DESCRIPTION_SITE_ALREADY_SEEN = false;
+ try {
+ parserFactory.setNamespaceAware(true);
+ this.parser = parserFactory.newSAXParser();
+ } catch (ParserConfigurationException e) {
+ log(e);
+ } catch (SAXException e) {
+ log(e);
+ }
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("Created"); //$NON-NLS-1$
+ }
+
+ /**
+ * Handle character text
+ * @see DefaultHandler#characters(char[], int, int)
+ * @since 2.0
+ */
+ public void characters(char[] ch, int start, int length) {
+ String text = new String(ch, start, length);
+ //only push if description
+ int state = ((Integer) stateStack.peek()).intValue();
+ if (state == STATE_DESCRIPTION_SITE || state == STATE_DESCRIPTION_CATEGORY_DEF)
+ objectStack.push(text);
+
+ }
+
+ /**
+ * Handle end of element tags
+ * @see DefaultHandler#endElement(String, String, String)
+ * @since 2.0
+ */
+ public void endElement(String uri, String localName, String qName) {
+
+ String text = null;
+ URLEntry info = null;
+
+ int state = ((Integer) stateStack.peek()).intValue();
+ switch (state) {
+ case STATE_IGNORED_ELEMENT :
+ case STATE_ARCHIVE :
+ case STATE_CATEGORY :
+ stateStack.pop();
+ break;
+
+ case STATE_INITIAL :
+ internalError(Messages.DefaultSiteParser_ParsingStackBackToInitialState);
+ break;
+
+ case STATE_SITE :
+ stateStack.pop();
+ if (objectStack.peek() instanceof String) {
+ text = (String) objectStack.pop();
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.getDescription().setAnnotation(text);
+ }
+ //do not pop the object
+ break;
+
+ case STATE_FEATURE :
+ stateStack.pop();
+ objectStack.pop();
+ break;
+
+ case STATE_CATEGORY_DEF :
+ stateStack.pop();
+ if (objectStack.peek() instanceof String) {
+ text = (String) objectStack.pop();
+ SiteCategory category = (SiteCategory) objectStack.peek();
+ category.setDescription(text);
+ }
+ objectStack.pop();
+ break;
+
+ case STATE_DESCRIPTION_SITE :
+ stateStack.pop();
+ text = ""; //$NON-NLS-1$
+ while (objectStack.peek() instanceof String) {
+ // add text, preserving at most one space between text fragments
+ String newText = (String) objectStack.pop();
+ if (trailingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ text = newText.trim() + text;
+ if (leadingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ }
+ text = text.trim();
+
+ info = (URLEntry) objectStack.pop();
+ if (text != null)
+ info.setAnnotation(text);
+
+ SiteModel siteModel = (SiteModel) objectStack.peek();
+ // override description.
+ // do not raise error as previous description may be default one
+ // when parsing site tag
+ if (DESCRIPTION_SITE_ALREADY_SEEN)
+ debug(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] {getState(state)})));
+ siteModel.setDescription(info);
+ DESCRIPTION_SITE_ALREADY_SEEN = true;
+ break;
+
+ case STATE_DESCRIPTION_CATEGORY_DEF :
+ stateStack.pop();
+ text = ""; //$NON-NLS-1$
+ while (objectStack.peek() instanceof String) {
+ // add text, preserving at most one space between text fragments
+ String newText = (String) objectStack.pop();
+ if (trailingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ text = newText.trim() + text;
+ if (leadingSpace(newText) && !leadingSpace(text)) {
+ text = " " + text; //$NON-NLS-1$
+ }
+ }
+ text = text.trim();
+
+ info = (URLEntry) objectStack.pop();
+ if (text != null)
+ info.setAnnotation(text);
+
+ SiteCategory category = (SiteCategory) objectStack.peek();
+ if (category.getDescription() != null)
+ internalError(NLS.bind(Messages.DefaultSiteParser_ElementAlreadySet, (new String[] {getState(state), category.getLabel()})));
+ else
+ category.setDescription(info.getAnnotation());
+ break;
+
+ default :
+ internalError(NLS.bind(Messages.DefaultSiteParser_UnknownEndState, (new String[] {getState(state)})));
+ break;
+ }
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End Element:" + uri + ":" + localName + ":" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ /*
+ * Handles an error state specified by the status. The collection of all logged status
+ * objects can be accessed using <code>getStatus()</code>.
+ *
+ * @param error a status detailing the error condition
+ */
+ private void error(IStatus error) {
+
+ if (status == null) {
+ status = new MultiStatus(PLUGIN_ID, 0, Messages.DefaultSiteParser_ErrorParsingSite, null);
+ }
+
+ status.add(error);
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ LogHelper.log(error);
+ }
+
+ /**
+ * Handle errors
+ * @see DefaultHandler#error(SAXParseException)
+ * @since 2.0
+ */
+ public void error(SAXParseException ex) {
+ logStatus(ex);
+ }
+
+ /**
+ * Handle fatal errors
+ * @see DefaultHandler#fatalError(SAXParseException)
+ * @exception SAXException
+ * @since 2.0
+ */
+ public void fatalError(SAXParseException ex) throws SAXException {
+ logStatus(ex);
+ throw ex;
+ }
+
+ /*
+ * return the state as String
+ */
+ private String getState(int state) {
+
+ switch (state) {
+ case STATE_IGNORED_ELEMENT :
+ return "Ignored"; //$NON-NLS-1$
+
+ case STATE_INITIAL :
+ return "Initial"; //$NON-NLS-1$
+
+ case STATE_SITE :
+ return "Site"; //$NON-NLS-1$
+
+ case STATE_FEATURE :
+ return "Feature"; //$NON-NLS-1$
+
+ case STATE_ARCHIVE :
+ return "Archive"; //$NON-NLS-1$
+
+ case STATE_CATEGORY :
+ return "Category"; //$NON-NLS-1$
+
+ case STATE_CATEGORY_DEF :
+ return "Category Def"; //$NON-NLS-1$
+
+ case STATE_DESCRIPTION_CATEGORY_DEF :
+ return "Description / Category Def"; //$NON-NLS-1$
+
+ case STATE_DESCRIPTION_SITE :
+ return "Description / Site"; //$NON-NLS-1$
+
+ default :
+ return Messages.DefaultSiteParser_UnknownState;
+ }
+ }
+
+ /**
+ * Returns all status objects accumulated by the parser.
+ *
+ * @return multi-status containing accumulated status, or <code>null</code>.
+ * @since 2.0
+ */
+ public MultiStatus getStatus() {
+ return status;
+ }
+
+ private void handleCategoryDefState(String elementName, Attributes attributes) {
+ if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_CATEGORY_DEF));
+ processInfo(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ private void handleCategoryState(String elementName, Attributes attributes) {
+ if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
+ processInfo(attributes);
+ } else if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else if (elementName.equals(CATEGORY)) {
+ stateStack.push(new Integer(STATE_CATEGORY));
+ processCategory(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ private void handleFeatureState(String elementName, Attributes attributes) {
+ if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
+ processInfo(attributes);
+ } else if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else if (elementName.equals(CATEGORY)) {
+ stateStack.push(new Integer(STATE_CATEGORY));
+ processCategory(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ private void handleInitialState(String elementName, Attributes attributes) throws SAXException {
+ if (elementName.equals(SITE)) {
+ stateStack.push(new Integer(STATE_SITE));
+ processSite(attributes);
+ } else {
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ // what we received was not a site.xml, no need to continue
+ throw new SAXException(Messages.DefaultSiteParser_InvalidXMLStream);
+ }
+
+ }
+
+ private void handleSiteState(String elementName, Attributes attributes) {
+ if (elementName.equals(DESCRIPTION)) {
+ stateStack.push(new Integer(STATE_DESCRIPTION_SITE));
+ processInfo(attributes);
+ } else if (elementName.equals(FEATURE)) {
+ stateStack.push(new Integer(STATE_FEATURE));
+ processFeature(attributes);
+ } else if (elementName.equals(ARCHIVE)) {
+ stateStack.push(new Integer(STATE_ARCHIVE));
+ processArchive(attributes);
+ } else if (elementName.equals(CATEGORY_DEF)) {
+ stateStack.push(new Integer(STATE_CATEGORY_DEF));
+ processCategoryDef(attributes);
+ } else
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {elementName, getState(currentState)})));
+ }
+
+ /*
+ *
+ */
+ private void internalError(String message) {
+ error(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, null));
+ }
+
+ /*
+ *
+ */
+ private void internalErrorUnknownTag(String msg) {
+ stateStack.push(new Integer(STATE_IGNORED_ELEMENT));
+ internalError(msg);
+ }
+
+ private boolean leadingSpace(String str) {
+ if (str.length() <= 0) {
+ return false;
+ }
+ return Character.isWhitespace(str.charAt(0));
+ }
+
+ /*
+ *
+ */
+ private void logStatus(SAXParseException ex) {
+ String name = ex.getSystemId();
+ if (name == null)
+ name = ""; //$NON-NLS-1$
+ else
+ name = name.substring(1 + name.lastIndexOf("/")); //$NON-NLS-1$
+
+ String msg;
+ if (name.equals("")) //$NON-NLS-1$
+ msg = NLS.bind(Messages.DefaultSiteParser_ErrorParsing, (new String[] {ex.getMessage()}));
+ else {
+ String[] values = new String[] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()};
+ msg = NLS.bind(Messages.DefaultSiteParser_ErrorlineColumnMessage, values);
+ }
+ error(new Status(IStatus.ERROR, PLUGIN_ID, msg, ex));
+ }
+
+ /**
+ * Parses the specified input steam and constructs a site model.
+ * The input stream is not closed as part of this operation.
+ *
+ * @param in input stream
+ * @return site model
+ * @exception SAXException
+ * @exception IOException
+ * @since 2.0
+ */
+ public SiteModel parse(InputStream in) throws SAXException, IOException {
+ stateStack.push(new Integer(STATE_INITIAL));
+ currentState = ((Integer) stateStack.peek()).intValue();
+ parser.parse(new InputSource(in), this);
+ if (objectStack.isEmpty())
+ throw new SAXException(Messages.DefaultSiteParser_NoSiteTag);
+ if (objectStack.peek() instanceof SiteModel) {
+ SiteModel site = (SiteModel) objectStack.pop();
+ site.setMessageKeys(messageKeys);
+ return site;
+ }
+ String stack = ""; //$NON-NLS-1$
+ Iterator iter = objectStack.iterator();
+ while (iter.hasNext()) {
+ stack = stack + iter.next().toString() + "\r\n"; //$NON-NLS-1$
+ }
+ throw new SAXException(NLS.bind(Messages.DefaultSiteParser_WrongParsingStack, (new String[] {stack})));
+ }
+
+ /*
+ * process archive info
+ */
+ private void processArchive(Attributes attributes) {
+ URLEntry archive = new URLEntry();
+ String id = attributes.getValue("path"); //$NON-NLS-1$
+ if (id == null || id.trim().equals("")) { //$NON-NLS-1$
+ internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"path", getState(currentState)}))); //$NON-NLS-1$
+ }
+
+ archive.setAnnotation(id);
+
+ String url = attributes.getValue("url"); //$NON-NLS-1$
+ if (url == null || url.trim().equals("")) { //$NON-NLS-1$
+ internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"archive", getState(currentState)}))); //$NON-NLS-1$
+ } else {
+ archive.setURL(url);
+
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.addArchive(archive);
+ }
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End processing Archive: path:" + id + " url:" + url);//$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ /*
+ * process the Category info
+ */
+ private void processCategory(Attributes attributes) {
+ String category = attributes.getValue("name"); //$NON-NLS-1$
+ SiteFeature feature = (SiteFeature) objectStack.peek();
+ feature.addCategoryName(category);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End processing Category: name:" + category); //$NON-NLS-1$
+ }
+
+ /*
+ * process category def info
+ */
+ private void processCategoryDef(Attributes attributes) {
+ SiteCategory category = new SiteCategory();
+ String name = attributes.getValue("name"); //$NON-NLS-1$
+ String label = attributes.getValue("label"); //$NON-NLS-1$
+ checkTranslated(label);
+ category.setName(name);
+ category.setLabel(label);
+
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.addCategory(category);
+ objectStack.push(category);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End processing CategoryDef: name:" + name + " label:" + label); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /*
+ * process feature info
+ */
+ private void processFeature(Attributes attributes) {
+ SiteFeature feature = new SiteFeature();
+
+ // feature location on the site
+ String urlInfo = attributes.getValue("url"); //$NON-NLS-1$
+ // identifier and version
+ String id = attributes.getValue("id"); //$NON-NLS-1$
+ String ver = attributes.getValue("version"); //$NON-NLS-1$
+
+ boolean noURL = (urlInfo == null || urlInfo.trim().equals("")); //$NON-NLS-1$
+ boolean noId = (id == null || id.trim().equals("")); //$NON-NLS-1$
+ boolean noVersion = (ver == null || ver.trim().equals("")); //$NON-NLS-1$
+
+ // We need to have id and version, or the url, or both.
+ if (noURL) {
+ if (noId || noVersion)
+ internalError(NLS.bind(Messages.DefaultSiteParser_Missing, (new String[] {"url", getState(currentState)}))); //$NON-NLS-1$
+ else
+ // default url
+ urlInfo = FEATURES + id + '_' + ver; //
+ }
+
+ feature.setURLString(urlInfo);
+
+ String type = attributes.getValue("type"); //$NON-NLS-1$
+ feature.setType(type);
+
+ // if one is null, and not the other
+ if (noId ^ noVersion) {
+ String[] values = new String[] {id, ver, getState(currentState)};
+ log(NLS.bind(Messages.DefaultFeatureParser_IdOrVersionInvalid, values));
+ } else {
+ feature.setFeatureIdentifier(id);
+ feature.setFeatureVersion(ver);
+ }
+
+ // get label if it exists
+ String label = attributes.getValue("label"); //$NON-NLS-1$
+ if (label != null) {
+ if ("".equals(label.trim())) //$NON-NLS-1$
+ label = null;
+ checkTranslated(label);
+ }
+ feature.setLabel(label);
+
+ // OS
+ String os = attributes.getValue("os"); //$NON-NLS-1$
+ feature.setOS(os);
+
+ // WS
+ String ws = attributes.getValue("ws"); //$NON-NLS-1$
+ feature.setWS(ws);
+
+ // NL
+ String nl = attributes.getValue("nl"); //$NON-NLS-1$
+ feature.setNL(nl);
+
+ // arch
+ String arch = attributes.getValue("arch"); //$NON-NLS-1$
+ feature.setArch(arch);
+
+ //patch
+ String patch = attributes.getValue("patch"); //$NON-NLS-1$
+ feature.setPatch(patch);
+
+ SiteModel site = (SiteModel) objectStack.peek();
+ site.addFeature(feature);
+ feature.setSiteModel(site);
+
+ objectStack.push(feature);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End Processing DefaultFeature Tag: url:" + urlInfo + " type:" + type); //$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ /*
+ * process URL info with element text
+ */
+ private void processInfo(Attributes attributes) {
+ URLEntry inf = new URLEntry();
+ String infoURL = attributes.getValue("url"); //$NON-NLS-1$
+ inf.setURL(infoURL);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("Processed Info: url:" + infoURL); //$NON-NLS-1$
+
+ objectStack.push(inf);
+ }
+
+ /*
+ * process site info
+ */
+ private void processSite(Attributes attributes) {
+ // create site map
+ SiteModel site = new SiteModel();
+
+ // if URL is specified, it replaces the URL of the site
+ // used to calculate the location of features and archives
+ String siteURL = attributes.getValue("url"); //$NON-NLS-1$
+ if (siteURL != null && !("".equals(siteURL.trim()))) { //$NON-NLS-1$
+ if (!siteURL.endsWith("/") && !siteURL.endsWith(File.separator)) { //$NON-NLS-1$
+ siteURL += "/"; //$NON-NLS-1$
+ }
+ site.setLocationURLString(siteURL);
+ }
+
+ // provide default description URL
+ // If <description> is specified, for the site, it takes precedence
+ URLEntry description = new URLEntry();
+ description.setURL(DEFAULT_INFO_URL);
+ site.setDescription(description);
+
+ // verify we can parse the site ...if the site has
+ // a different type throw an exception to force reparsing
+ // with the matching parser
+ String type = attributes.getValue("type"); //$NON-NLS-1$
+ site.setType(type);
+
+ // get mirrors, if any
+ String mirrorsURL = attributes.getValue("mirrorsURL"); //$NON-NLS-1$
+ if (mirrorsURL != null && mirrorsURL.trim().length() > 0) {
+ // URLEntry[] mirrors = getMirrors(mirrorsURL);
+ // if (mirrors != null)
+ // site.setMirrors(mirrors);
+ // else
+
+ //Since we are parsing the site at p2 generation time and the
+ //mirrors may change, there is no point doing the mirror expansion now
+ site.setMirrorsURLString(mirrorsURL);
+ }
+
+ String pack200 = attributes.getValue("pack200"); //$NON-NLS-1$
+ if (pack200 != null && new Boolean(pack200).booleanValue()) {
+ site.setSupportsPack200(true);
+ }
+
+ String digestURL = attributes.getValue("digestURL"); //$NON-NLS-1$
+ if (digestURL != null)
+ site.setDigestURLString(digestURL);
+
+ // TODO: Digest locales
+ // if ((attributes.getValue("availableLocales") != null) && (!attributes.getValue("availableLocales").trim().equals(""))) { //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
+ // StringTokenizer locals = new StringTokenizer(attributes.getValue("availableLocales"), ","); //$NON-NLS-1$//$NON-NLS-2$
+ // String[] availableLocals = new String[locals.countTokens()];
+ // int i = 0;
+ // while (locals.hasMoreTokens()) {
+ // availableLocals[i++] = locals.nextToken();
+ // }
+ // extendedSite.setAvailableLocals(availableLocals);
+ // }
+ // }
+ //
+ if (attributes.getValue(ASSOCIATE_SITES_URL) != null)
+ site.setAssociateSites(getAssociateSites(attributes.getValue(ASSOCIATE_SITES_URL)));
+
+ objectStack.push(site);
+
+ if (Tracing.DEBUG_GENERATOR_PARSING)
+ debug("End process Site tag: siteURL:" + siteURL + " type:" + type);//$NON-NLS-1$ //$NON-NLS-2$
+
+ }
+
+ /**
+ * Handle start of element tags
+ * @see DefaultHandler#startElement(String, String, String, Attributes)
+ * @since 2.0
+ */
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+
+ if (Tracing.DEBUG_GENERATOR_PARSING) {
+ debug("State: " + currentState); //$NON-NLS-1$
+ debug("Start Element: uri:" + uri + " local Name:" + localName + " qName:" + qName);//$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+ }
+
+ switch (currentState) {
+ case STATE_IGNORED_ELEMENT :
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownElement, (new String[] {localName, getState(currentState)})));
+ break;
+ case STATE_INITIAL :
+ handleInitialState(localName, attributes);
+ break;
+
+ case STATE_SITE :
+ handleSiteState(localName, attributes);
+ break;
+
+ case STATE_FEATURE :
+ handleFeatureState(localName, attributes);
+ break;
+
+ case STATE_ARCHIVE :
+ handleSiteState(localName, attributes);
+ break;
+
+ case STATE_CATEGORY :
+ handleCategoryState(localName, attributes);
+ break;
+
+ case STATE_CATEGORY_DEF :
+ handleCategoryDefState(localName, attributes);
+ break;
+
+ case STATE_DESCRIPTION_SITE :
+ handleSiteState(localName, attributes);
+ break;
+
+ case STATE_DESCRIPTION_CATEGORY_DEF :
+ handleSiteState(localName, attributes);
+ break;
+
+ default :
+ internalErrorUnknownTag(NLS.bind(Messages.DefaultSiteParser_UnknownStartState, (new String[] {getState(currentState)})));
+ break;
+ }
+ int newState = ((Integer) stateStack.peek()).intValue();
+ if (newState != STATE_IGNORED_ELEMENT)
+ currentState = newState;
+
+ }
+
+ private boolean trailingSpace(String str) {
+ if (str.length() <= 0) {
+ return false;
+ }
+ return Character.isWhitespace(str.charAt(str.length() - 1));
+ }
+
+ // Add translatable strings from the site.xml
+ // to the list of message keys.
+ private void checkTranslated(String value) {
+ if (value != null && value.length() > 1 && value.startsWith("%")) //$NON-NLS-1$
+ messageKeys.add(value.substring(1));
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/DigestParser.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/DigestParser.java
new file mode 100644
index 0000000..cbe9fea
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/DigestParser.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.updatesite;
+
+import org.eclipse.equinox.internal.p2.publisher.eclipse.FeatureParser;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import javax.xml.parsers.*;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+import org.eclipse.equinox.p2.publisher.eclipse.Feature;
+import org.eclipse.osgi.util.NLS;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ * Default feature parser.
+ * Parses the feature manifest file as defined by the platform.
+ *
+ * @since 3.0
+ */
+public class DigestParser extends DefaultHandler {
+
+ private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+ private SAXParser parser;
+ private final List features = new ArrayList();
+ private final FeatureParser featureHandler = new FeatureParser(false);
+
+ public DigestParser() {
+ super();
+ try {
+ parserFactory.setNamespaceAware(true);
+ this.parser = parserFactory.newSAXParser();
+ } catch (ParserConfigurationException e) {
+ System.out.println(e);
+ } catch (SAXException e) {
+ System.out.println(e);
+ }
+ }
+
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ featureHandler.characters(ch, start, length);
+ }
+
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ if ("digest".equals(localName)) { //$NON-NLS-1$
+ return;
+ }
+ if ("feature".equals(localName)) { //$NON-NLS-1$
+ Feature feature = featureHandler.getResult();
+ features.add(feature);
+ } else
+ featureHandler.endElement(uri, localName, qName);
+ }
+
+ public Feature[] parse(File location) {
+ if (!location.exists())
+ return null;
+
+ JarFile jar = null;
+ InputStream is = null;
+ try {
+ jar = new JarFile(location);
+ JarEntry entry = jar.getJarEntry("digest.xml"); //$NON-NLS-1$
+ if (entry == null)
+ return null;
+ is = new BufferedInputStream(jar.getInputStream(entry));
+ parser.parse(new InputSource(is), this);
+ return (Feature[]) features.toArray(new Feature[features.size()]);
+ } catch (IOException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingDigest, location), e));
+ } catch (SAXException e) {
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.ErrorReadingDigest, location), e));
+ } finally {
+ try {
+ if (is != null)
+ is.close();
+ } catch (IOException e1) {
+ //
+ }
+ try {
+ if (jar != null)
+ jar.close();
+ } catch (IOException e) {
+ //
+ }
+ }
+ return null;
+ }
+
+ public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+ if ("digest".equals(localName)) { //$NON-NLS-1$
+ return;
+ }
+ featureHandler.startElement(uri, localName, qName, attributes);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/LocalUpdateSiteAction.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/LocalUpdateSiteAction.java
new file mode 100644
index 0000000..dc1ae33
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/LocalUpdateSiteAction.java
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * 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.updatesite;
+
+import org.eclipse.equinox.p2.publisher.actions.MergeResultsAction;
+
+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.p2.publisher.*;
+import org.eclipse.equinox.p2.publisher.eclipse.BundlesAction;
+import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction;
+
+/**
+ * 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 IPublisherAction {
+ 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) {
+ IPublisherAction[] actions = createActions();
+ for (int i = 0; i < actions.length; i++)
+ actions[i].perform(info, results);
+ return Status.OK_STATUS;
+ }
+
+ protected IPublisherAction[] createActions() {
+ createAdvice();
+ ArrayList result = new ArrayList();
+ // create an action that just publishes the raw bundles and features
+ IPublisherAction action = new MergeResultsAction(new IPublisherAction[] {createFeaturesAction(), createBundlesAction()}, IPublisherResult.MERGE_ALL_NON_ROOT);
+ result.add(action);
+ result.add(createSiteXMLAction());
+ return (IPublisherAction[]) result.toArray(new IPublisherAction[result.size()]);
+ }
+
+ private IPublisherAction 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 IPublisherAction createFeaturesAction() {
+ return new FeaturesAction(new File[] {new File(source, "features")}); //$NON-NLS-1$
+ }
+
+ protected IPublisherAction createBundlesAction() {
+ return new BundlesAction(new File[] {new File(source, "plugins")}); //$NON-NLS-1$
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/Messages.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/Messages.java
index a32485c..2ba0c6a 100644
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/Messages.java
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/Messages.java
@@ -32,6 +32,23 @@
public static String repoMan_internalError;
+ public static String DefaultFeatureParser_IdOrVersionInvalid;
+ public static String DefaultSiteParser_NoSiteTag;
+ public static String DefaultSiteParser_WrongParsingStack;
+ public static String DefaultSiteParser_UnknownElement;
+ public static String DefaultSiteParser_UnknownStartState;
+ public static String DefaultSiteParser_Missing;
+ public static String DefaultSiteParser_ParsingStackBackToInitialState;
+ public static String DefaultSiteParser_ElementAlreadySet;
+ public static String DefaultSiteParser_CategoryAlreadySet;
+ public static String DefaultSiteParser_UnknownEndState;
+ public static String DefaultSiteParser_ErrorParsing;
+ public static String DefaultSiteParser_ErrorlineColumnMessage;
+ public static String DefaultSiteParser_ErrorParsingSite;
+ public static String DefaultSiteParser_UnknownState;
+ public static String DefaultSiteParser_InvalidXMLStream;
+ public static String DefaultSiteParser_mirrors;
+
static {
// initialize resource bundle
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/RemoteFeaturesAction.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/RemoteFeaturesAction.java
new file mode 100644
index 0000000..3d1fc52
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/RemoteFeaturesAction.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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.updatesite;
+
+import java.util.Dictionary;
+import java.util.Properties;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.publisher.IPublisherInfo;
+import org.eclipse.equinox.p2.publisher.IPublisherResult;
+import org.eclipse.equinox.p2.publisher.eclipse.*;
+import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
+import org.eclipse.osgi.service.resolver.BundleDescription;
+
+public class RemoteFeaturesAction extends FeaturesAction {
+
+ public RemoteFeaturesAction(Feature[] features) {
+ super(features);
+ }
+
+ protected void generateFeatureIUs(Feature[] features, IPublisherResult result, IPublisherInfo info) {
+ Properties extraProperties = new Properties();
+ extraProperties.put(IInstallableUnit.PROP_PARTIAL_IU, Boolean.TRUE.toString());
+ for (int i = 0; i < features.length; i++) {
+ Feature feature = features[i];
+ FeatureEntry[] featureEntries = feature.getEntries();
+ for (int j = 0; j < featureEntries.length; j++) {
+ FeatureEntry entry = featureEntries[j];
+ if (entry.isPlugin() && !entry.isRequires()) {
+ Dictionary mockManifest = new Properties();
+ mockManifest.put("Manifest-Version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
+ mockManifest.put("Bundle-ManifestVersion", "2"); //$NON-NLS-1$ //$NON-NLS-2$
+ mockManifest.put("Bundle-SymbolicName", entry.getId()); //$NON-NLS-1$
+ mockManifest.put("Bundle-Version", entry.getVersion()); //$NON-NLS-1$
+ BundleDescription bundleDescription = BundlesAction.createBundleDescription(mockManifest, null);
+ IArtifactKey key = BundlesAction.createBundleArtifactKey(entry.getId(), entry.getVersion());
+ IInstallableUnit[] bundleIUs = PublisherHelper.createEclipseIU(bundleDescription, null, entry.isUnpack(), key, extraProperties);
+ for (int n = 0; n < bundleIUs.length; n++)
+ result.addIU(bundleIUs[n], IPublisherResult.ROOT);
+ }
+ }
+ IInstallableUnit featureIU = createFeatureJarIU(feature, null, null);
+ IInstallableUnit groupIU = createGroupIU(feature, featureIU, null);
+ result.addIU(featureIU, IPublisherResult.ROOT);
+ result.addIU(groupIU, IPublisherResult.ROOT);
+ }
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/RemoteUpdateSiteAction.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/RemoteUpdateSiteAction.java
new file mode 100644
index 0000000..d53c747
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/RemoteUpdateSiteAction.java
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * 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.updatesite;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.p2.publisher.*;
+
+/**
+ * A publishing action that processes a remote (URL-based) update site and generates
+ * metadata and artifacts for the features, bundles and site index (categories etc). The
+ * IUs generated for the bundles are "partial" as the bundles themselves are not downloaded.
+ */
+public class RemoteUpdateSiteAction implements IPublisherAction {
+ protected String source;
+ private UpdateSite updateSite;
+
+ public RemoteUpdateSiteAction(UpdateSite updateSite) {
+ this.updateSite = updateSite;
+ }
+
+ public RemoteUpdateSiteAction(String source) {
+ this.source = source;
+ }
+
+ public IStatus perform(IPublisherInfo info, IPublisherResult results) {
+ IPublisherAction[] actions = createActions();
+ for (int i = 0; i < actions.length; i++)
+ actions[i].perform(info, results);
+ return Status.OK_STATUS;
+ }
+
+ protected IPublisherAction[] createActions() {
+ try {
+ ArrayList result = new ArrayList();
+ result.add(new RemoteFeaturesAction(updateSite.loadFeatures()));
+ result.add(createSiteXMLAction());
+ return (IPublisherAction[]) result.toArray(new IPublisherAction[result.size()]);
+ } catch (ProvisionException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return new IPublisherAction[0];
+ }
+
+ private IPublisherAction createSiteXMLAction() {
+ if (updateSite != null)
+ return new SiteXMLAction(updateSite);
+ if (source != null) {
+ try {
+ return new SiteXMLAction(new URL(source + "/site.xml")); //$NON-NLS-1$
+ } catch (MalformedURLException e) {
+ // never happens
+ return null;
+ }
+ }
+ return null;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteCategory.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteCategory.java
new file mode 100644
index 0000000..d78efa1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteCategory.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.updatesite;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Comparator;
+import java.util.Map;
+
+/**
+ * A category in an update site.
+ *
+ * Based on org.eclipse.update.core.model.CategoryModel.
+ */
+public class SiteCategory {
+
+ private static Comparator comp;
+ private String description;
+ private String label;
+ private String name;
+ private Map localizations;
+
+ /**
+ * Returns a comparator for category models.
+ *
+ * @return comparator
+ * @since 2.0
+ */
+ public static Comparator getComparator() {
+ if (comp == null) {
+ comp = new Comparator() {
+ /*
+ * @see Comparator#compare(Object,Object)
+ * Returns 0 if versions are equal.
+ * Returns -1 if object1 is after than object2.
+ * Returns +1 if object1 is before than object2.
+ */
+ public int compare(Object o1, Object o2) {
+
+ SiteCategory cat1 = (SiteCategory) o1;
+ SiteCategory cat2 = (SiteCategory) o2;
+
+ if (cat1.equals(cat2))
+ return 0;
+ return cat1.getName().compareTo(cat2.getName());
+ }
+ };
+ }
+ return comp;
+ }
+
+ /**
+ * Creates an uninitialized model object.
+ *
+ * @since 2.0
+ */
+ public SiteCategory() {
+ super();
+ }
+
+ /**
+ * Compare two category models for equality.
+ *
+ * @see Object#equals(Object)
+ * @since 2.0
+ */
+ public boolean equals(Object obj) {
+ boolean result = false;
+ if (obj instanceof SiteCategory) {
+ SiteCategory otherCategory = (SiteCategory) obj;
+ result = getName().equalsIgnoreCase(otherCategory.getName());
+ }
+ return result;
+ }
+
+ /**
+ * Retrieve the detailed category description
+ *
+ * @return category description, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * Retrieve the non-localized displayable label for the category.
+ *
+ * @return non-localized displayable label, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Gets the localizations for the site as a map from locale
+ * to the set of translated properties for that locale.
+ *
+ * @return a map from locale to property set
+ * @since 3.4
+ */
+ public Map getLocalizations() {
+ return this.localizations;
+ }
+
+ /**
+ * Retrieve the name of the category.
+ *
+ * @return category name, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Compute hash code for category model.
+ *
+ * @see Object#hashCode()
+ * @since 2.0
+ */
+ public int hashCode() {
+ return getName().hashCode();
+ }
+
+ /**
+ * Resolve the model object.
+ * Any URL strings in the model are resolved relative to the
+ * base URL argument. Any translatable strings in the model that are
+ * specified as translation keys are localized using the supplied
+ * resource bundle.
+ *
+ * @param base URL
+ * @param bundleURL resource bundle URL
+ * @exception MalformedURLException
+ * @since 2.0
+ */
+ public void resolve(URL base, URL bundleURL) throws MalformedURLException {
+ // resolve local elements
+ // localizedLabel = resolveNLString(bundleURL, label);
+
+ // delegate to references
+ // resolveReference(getDescriptionModel(), base, bundleURL);
+ }
+
+ /**
+ * Sets the category description.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param description category description
+ * @since 2.0
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * Sets the category displayable label.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param label displayable label, or resource key
+ * @since 2.0
+ */
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Sets the localizations for the site as a map from locale
+ * to the set of translated properties for that locale.
+ *
+ * @param localizations as a map from locale to property set
+ * @since 3.4
+ */
+ public void setLocalizations(Map localizations) {
+ this.localizations = localizations;
+ }
+
+ /**
+ * Sets the category name.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param name category name
+ * @since 2.0
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteFeature.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteFeature.java
new file mode 100644
index 0000000..626e4b1
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteFeature.java
@@ -0,0 +1,408 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * James D Miles (IBM Corp.) - bug 191783, NullPointerException in FeatureDownloader
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.updatesite;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * A reference to a feature in an update site.xml file.
+ *
+ * Based on org.eclipse.update.core.model.FeatureReferenceModel.
+ */
+public class SiteFeature {
+
+ private String arch;
+ // performance
+ private URL base;
+ private List /* of String*/categoryNames;
+ private String featureId;
+ private String featureVersion;
+ private String label;
+ private String nl;
+
+ private String os;
+ private String patch;
+ private final boolean resolved = false;
+ private SiteModel site;
+ private String type;
+ private URL url;
+ private String urlString;
+ private String ws;
+
+ /*
+ * Compares two URL for equality
+ * Return false if one of them is null
+ */
+ public static boolean sameURL(URL url1, URL url2) {
+
+ if (url1 == null || url2 == null)
+ return false;
+ if (url1 == url2)
+ return true;
+ if (url1.equals(url2))
+ return true;
+
+ // check if URL are file: URL as we may
+ // have 2 URL pointing to the same featureReference
+ // but with different representation
+ // (i.e. file:/C;/ and file:C:/)
+ if (!"file".equalsIgnoreCase(url1.getProtocol())) //$NON-NLS-1$
+ return false;
+ if (!"file".equalsIgnoreCase(url2.getProtocol())) //$NON-NLS-1$
+ return false;
+
+ File file1 = new File(url1.getFile());
+ File file2 = new File(url2.getFile());
+
+ if (file1 == null)
+ return false;
+
+ return (file1.equals(file2));
+ }
+
+ /**
+ * Creates an uninitialized feature reference model object.
+ */
+ public SiteFeature() {
+ super();
+ }
+
+ /**
+ * Adds the name of a category this feature belongs to.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param categoryName category name
+ */
+ public void addCategoryName(String categoryName) {
+ if (this.categoryNames == null)
+ this.categoryNames = new ArrayList();
+ if (!this.categoryNames.contains(categoryName))
+ this.categoryNames.add(categoryName);
+ }
+
+ private void delayedResolve() {
+
+ // PERF: delay resolution
+ if (resolved)
+ return;
+
+ // resolve local elements
+ try {
+ url = new URL(base, urlString);
+ } catch (MalformedURLException e) {
+ // UpdateCore.warn("", e); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Compares 2 feature reference models for equality
+ *
+ * @param object feature reference model to compare with
+ * @return <code>true</code> if the two models are equal,
+ * <code>false</code> otherwise
+ */
+ public boolean equals(Object object) {
+
+ if (object == null)
+ return false;
+ if (getURL() == null)
+ return false;
+
+ if (!(object instanceof SiteFeature))
+ return false;
+
+ SiteFeature f = (SiteFeature) object;
+
+ return sameURL(getURL(), f.getURL());
+ }
+
+ /**
+ * Returns the names of categories the referenced feature belongs to.
+ *
+ * @return an array of names, or an empty array.
+ */
+ public String[] getCategoryNames() {
+ if (categoryNames == null)
+ return new String[0];
+
+ return (String[]) categoryNames.toArray(new String[0]);
+ }
+
+ /**
+ * Returns the feature identifier as a string
+ *
+ * @return feature identifier
+ */
+ public String getFeatureIdentifier() {
+ return featureId;
+ }
+
+ /**
+ * Returns the feature version as a string
+ *
+ * @return feature version
+ */
+ public String getFeatureVersion() {
+ return featureVersion;
+ }
+
+ /**
+ * Retrieve the displayable label for the feature reference. If the model
+ * object has been resolved, the label is localized.
+ *
+ * @return displayable label, or <code>null</code>.
+ */
+ public String getLabel() {
+ return label;
+ }
+
+ /**
+ * Retrieve the non-localized displayable label for the feature reference.
+ *
+ * @return non-localized displayable label, or <code>null</code>.
+ */
+ public String getLabelNonLocalized() {
+ return label;
+ }
+
+ /**
+ * Get optional locale specification as a comma-separated string.
+ *
+ * @return the locale specification string, or <code>null</code>.
+ */
+ public String getNL() {
+ return nl;
+ }
+
+ /**
+ * Get optional operating system specification as a comma-separated string.
+ *
+ * @return the operating system specification string, or <code>null</code>.
+ */
+ public String getOS() {
+ return os;
+ }
+
+ /**
+ * Get optional system architecture specification as a comma-separated string.
+ *
+ * @return the system architecture specification string, or <code>null</code>.
+ */
+ public String getOSArch() {
+ return arch;
+ }
+
+ /**
+ * Returns the patch mode.
+ */
+ public String getPatch() {
+ return patch;
+ }
+
+ /**
+ * Returns the site model for the reference.
+ *
+ * @return site model
+ * @since 2.0
+ */
+ public SiteModel getSiteModel() {
+ return site;
+ }
+
+ /**
+ * Returns the referenced feature type.
+ *
+ * @return feature type, or <code>null</code> representing the default
+ * feature type for the site
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Returns the resolved URL for the feature reference.
+ *
+ * @return url string
+ */
+ public URL getURL() {
+ delayedResolve();
+ return url;
+ }
+
+ /**
+ * Returns the unresolved URL string for the reference.
+ *
+ * @return url string
+ */
+ public String getURLString() {
+ return urlString;
+ }
+
+ /**
+ * Get optional windowing system specification as a comma-separated string.
+ *
+ * @return the windowing system specification string, or <code>null</code>.
+ */
+ public String getWS() {
+ return ws;
+ }
+
+ /**
+ * Resolve the model object.
+ * Any URL strings in the model are resolved relative to the
+ * base URL argument. Any translatable strings in the model that are
+ * specified as translation keys are localized using the supplied
+ * resource bundle.
+ *
+ * @param resolveBase URL
+ * @param bundleURL resource bundle URL
+ * @exception MalformedURLException
+ */
+ public void resolve(URL resolveBase, URL bundleURL) throws MalformedURLException {
+ this.base = resolveBase;
+ }
+
+ /**
+ * Sets the system architecture specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param arch system architecture specification as a comma-separated list
+ */
+ public void setArch(String arch) {
+ this.arch = arch;
+ }
+
+ /**
+ * Sets the names of categories this feature belongs to.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param categoryNames an array of category names
+ */
+ public void setCategoryNames(String[] categoryNames) {
+ if (categoryNames == null)
+ this.categoryNames = null;
+ else
+ this.categoryNames = new ArrayList(Arrays.asList(categoryNames));
+ }
+
+ /**
+ * Sets the feature identifier.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param featureId feature identifier
+ */
+ public void setFeatureIdentifier(String featureId) {
+ this.featureId = featureId;
+ }
+
+ /**
+ * Sets the feature version.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param featureVersion feature version
+ */
+ public void setFeatureVersion(String featureVersion) {
+ this.featureVersion = featureVersion;
+ }
+
+ /**
+ * Sets the label.
+ * @param label The label to set
+ */
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ /**
+ * Sets the locale specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param nl locale specification as a comma-separated list
+ */
+ public void setNL(String nl) {
+ this.nl = nl;
+ }
+
+ /**
+ * Sets the operating system specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param os operating system specification as a comma-separated list
+ */
+ public void setOS(String os) {
+ this.os = os;
+ }
+
+ /**
+ * Sets the patch mode.
+ */
+ public void setPatch(String patch) {
+ this.patch = patch;
+ }
+
+ /**
+ * Sets the site for the referenced.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param site site for the reference
+ */
+ public void setSiteModel(SiteModel site) {
+ this.site = site;
+ }
+
+ /**
+ * Sets the referenced feature type.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param type referenced feature type
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Sets the unresolved URL for the feature reference.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param urlString unresolved URL string
+ */
+ public void setURLString(String urlString) {
+ this.urlString = urlString;
+ this.url = null;
+ }
+
+ /**
+ * Sets the windowing system specification.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param ws windowing system specification as a comma-separated list
+ */
+ public void setWS(String ws) {
+ this.ws = ws;
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append(getClass().toString() + " :"); //$NON-NLS-1$
+ buffer.append(" at "); //$NON-NLS-1$
+ if (url != null)
+ buffer.append(url.toExternalForm());
+ return buffer.toString();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteModel.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteModel.java
new file mode 100644
index 0000000..3db8a96
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteModel.java
@@ -0,0 +1,399 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.updatesite;
+
+import org.eclipse.equinox.p2.publisher.eclipse.URLEntry;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * A model of an update site.
+ *
+ * Copied from org.eclipse.update.core.model.SiteModel.
+ */
+public class SiteModel {
+
+ private List /*of ArchiveReferenceModel*/archiveReferences;
+ /**
+ * Map of String (category id) -> SiteCategory
+ */
+ private Map categories;
+ private URLEntry description;
+ /**
+ * Map of String (feature id) -> SiteFeature
+ */
+ private List features;
+ private URL locationURL;
+ private String locationURLString;
+ private List /* of URLEntry */mirrors;
+ private String mirrorsURLString;
+ private boolean supportsPack200;
+ private String type;
+ private URLEntry[] associateSites;
+ private String digestURLString;
+ private List messageKeys;
+ private Map localizations;
+
+ /**
+ * Creates an uninitialized site model object.
+ *
+ * @since 2.0
+ */
+ public SiteModel() {
+ super();
+ }
+
+ /**
+ * Adds an archive reference model to site.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param archiveReference archive reference model
+ * @since 2.0
+ */
+ public void addArchive(URLEntry archiveReference) {
+ if (this.archiveReferences == null)
+ this.archiveReferences = new ArrayList();
+ if (!this.archiveReferences.contains(archiveReference))
+ this.archiveReferences.add(archiveReference);
+ }
+
+ /**
+ * Adds a category to the site.
+ *
+ * @param category category model
+ */
+ public void addCategory(SiteCategory category) {
+ if (categories == null)
+ categories = new HashMap();
+ if (!categories.containsKey(category.getName())) {
+ categories.put(category.getName(), category);
+ if (localizations != null && !localizations.isEmpty())
+ category.setLocalizations(localizations);
+ }
+ }
+
+ /**
+ * Adds a feature reference model to site.
+ *
+ * @param featureReference feature reference model
+ */
+ public void addFeature(SiteFeature featureReference) {
+ if (this.features == null)
+ this.features = new ArrayList();
+ this.features.add(featureReference);
+ }
+
+ /**
+ * Adds a mirror site.
+ *
+ * @param mirror mirror model
+ * @since 3.1
+ */
+ public void addMirror(URLEntry mirror) {
+ if (this.mirrors == null)
+ this.mirrors = new ArrayList();
+ if (!this.mirrors.contains(mirror))
+ this.mirrors.add(mirror);
+ }
+
+ private void doSetMirrorSiteEntryModels(URLEntry[] newMirrors) {
+ if (newMirrors == null || newMirrors.length == 0)
+ this.mirrors = null;
+ else
+ this.mirrors = new ArrayList(Arrays.asList(newMirrors));
+ }
+
+ /**
+ * Returns an array of plug-in and non-plug-in archive reference models
+ * on this site
+ *
+ * @return an array of archive reference models, or an empty array if there are
+ * no archives known to this site.
+ * @since 2.0
+ */
+ public URLEntry[] getArchives() {
+ if (archiveReferences == null || archiveReferences.size() == 0)
+ return new URLEntry[0];
+
+ return (URLEntry[]) archiveReferences.toArray(new URLEntry[0]);
+ }
+
+ public URLEntry[] getAssociatedSites() {
+ return associateSites;
+ }
+
+ /**
+ * Returns an array of category models for this site.
+ *
+ * @return array of site category models, or an empty array.
+ * @since 2.0
+ */
+ public SiteCategory[] getCategories() {
+ if (categories == null || categories.size() == 0)
+ return new SiteCategory[0];
+ return (SiteCategory[]) categories.values().toArray(new SiteCategory[0]);
+ }
+
+ /**
+ * Returns the category with the given name.
+ * @return the category with the given name, or <code>null</code>
+ */
+ public SiteCategory getCategory(String name) {
+ return (SiteCategory) (categories == null ? null : categories.get(name));
+ }
+
+ /**
+ * Returns the site description.
+ *
+ * @return site description, or <code>null</code>.
+ */
+ public URLEntry getDescription() {
+ return description;
+ }
+
+ /**
+ * Returns an array of feature reference models on this site.
+ *
+ * @return an array of feature reference models, or an empty array.
+ */
+ public SiteFeature[] getFeatures() {
+ if (features == null || features.size() == 0)
+ return new SiteFeature[0];
+ return (SiteFeature[]) features.toArray(new SiteFeature[0]);
+ }
+
+ /**
+ * Gets the localizations for the site as a map from locale
+ * to the set of translated properties for that locale.
+ *
+ * @return a map from locale to property set
+ * @since 3.4
+ */
+ public Map getLocalizations() {
+ return this.localizations;
+ }
+
+ /**
+ * Returns the resolved URL for the site.
+ *
+ * @return url, or <code>null</code>
+ */
+ public URL getLocationURL() {
+ if (locationURL == null && locationURLString != null) {
+ try {
+ locationURL = new URL(locationURLString);
+ } catch (MalformedURLException e) {
+ //ignore and return null
+ }
+ }
+ return locationURL;
+ }
+
+ /**
+ * Returns the unresolved URL string for the site.
+ *
+ * @return url string, or <code>null</code>
+ */
+ public String getLocationURLString() {
+ return locationURLString;
+ }
+
+ /**
+ * Return the keys for translatable strings
+ *
+ * @return the list of keys for translatable strings; may be null
+ * @since 3.4
+ */
+ public List getMessageKeys() {
+ return messageKeys;
+ }
+
+ /**
+ * Return an array of update site mirrors
+ *
+ * @return an array of mirror entries, or an empty array.
+ * @since 3.1
+ */
+ public URLEntry[] getMirrors() {
+ //delayedResolve(); no delay;
+ if (mirrors == null || mirrors.size() == 0)
+ // see if we can get mirrors from the provided url
+ if (mirrorsURLString != null)
+ doSetMirrorSiteEntryModels(DefaultSiteParser.getMirrors(mirrorsURLString));
+
+ if (mirrors == null || mirrors.size() == 0)
+ return new URLEntry[0];
+ return (URLEntry[]) mirrors.toArray(new URLEntry[0]);
+ }
+
+ /**
+ * Returns the URL from which the list of mirrors of this site can be retrieved.
+ *
+ * @since org.eclipse.equinox.p2.metadata.generator 1.0
+ */
+ public String getMirrorsURL() {
+ return mirrorsURLString;
+ }
+
+ /**
+ * Returns the site type.
+ *
+ * @return site type, or <code>null</code>.
+ * @since 2.0
+ */
+ public String getType() {
+ return type;
+ }
+
+ public boolean isPack200Supported() {
+ return supportsPack200;
+ }
+
+ /**
+ * Resolve the model object.
+ * Any URL strings in the model are resolved relative to the
+ * base URL argument. Any translatable strings in the model that are
+ * specified as translation keys are localized using the supplied
+ * resource bundle.
+ *
+ * @param base URL
+ * @param bundleURL resource bundle URL
+ * @exception MalformedURLException
+ * @since 2.0
+ */
+ public void resolve(URL base, URL bundleURL) throws MalformedURLException {
+
+ // Archives and feature are relative to location URL
+ // if the Site element has a URL tag: see spec
+ // locationURL = resolveURL(base, bundleURL, getLocationURLString());
+ // if (locationURL == null)
+ // locationURL = base;
+ // resolveListReference(getFeatureReferenceModels(), locationURL, bundleURL);
+ // resolveListReference(getArchiveReferenceModels(), locationURL, bundleURL);
+ //
+ // resolveReference(getDescriptionModel(), base, bundleURL);
+ // resolveListReference(getCategoryModels(), base, bundleURL);
+ //
+ // URL url = resolveURL(base, bundleURL, mirrorsURLString);
+ // if (url != null)
+ // mirrorsURLString = url.toString();
+ //
+ // if ((this instanceof ExtendedSite) && ((ExtendedSite) this).isDigestExist()) {
+ // ExtendedSite extendedSite = (ExtendedSite) this;
+ // extendedSite.setLiteFeatures(UpdateManagerUtils.getLightFeatures(extendedSite));
+ // }
+ }
+
+ /**
+ * Sets the site description.
+ *
+ * @param description site description
+ * @since 2.0
+ */
+ public void setDescription(URLEntry description) {
+ this.description = description;
+ }
+
+ /**
+ * Sets the localizations for the site as a map from locale
+ * to the set of translated properties for that locale.
+ *
+ * @param localizations as a map from locale to property set
+ * @since 3.4
+ */
+ public void setLocalizations(Map localizations) {
+ this.localizations = localizations;
+ if (localizations != null && !localizations.isEmpty() && //
+ categories != null && !categories.isEmpty()) {
+ for (Iterator catIter = categories.entrySet().iterator(); catIter.hasNext();) {
+ Map.Entry entry = (Map.Entry) catIter.next();
+ SiteCategory category = (SiteCategory) entry.getValue();
+ category.setLocalizations(localizations);
+ }
+ }
+ }
+
+ /**
+ * Sets the unresolved URL for the site.
+ *
+ * @param locationURLString url for the site (as a string)
+ * @since 2.0
+ */
+ public void setLocationURLString(String locationURLString) {
+ this.locationURLString = locationURLString;
+ }
+
+ /**
+ * Sets keys for translatable strings
+ *
+ * @param keys for translatable strings
+ * @since 3.4
+ */
+ public void setMessageKeys(List keys) {
+ this.messageKeys = keys;
+ }
+
+ /**
+ * Sets additional mirror sites
+ *
+ * @param mirrors additional update site mirrors
+ * @since 3.1
+ */
+ public void setMirrors(URLEntry[] mirrors) {
+ doSetMirrorSiteEntryModels(mirrors);
+ }
+
+ /**
+ * Sets the mirrors url. Mirror sites will then be obtained from this mirror url later.
+ * This method is complementary to setMirrorsiteEntryModels(), and only one of these
+ * methods should be called.
+ *
+ * @param mirrorsURL additional update site mirrors
+ * @since 3.1
+ */
+ public void setMirrorsURLString(String mirrorsURL) {
+ this.mirrorsURLString = mirrorsURL;
+ }
+
+ public void setSupportsPack200(boolean value) {
+ this.supportsPack200 = value;
+ }
+
+ /**
+ * Sets the site type.
+ * Throws a runtime exception if this object is marked read-only.
+ *
+ * @param type site type
+ * @since 2.0
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Sets the associated sites for this update site.
+ *
+ * @param associateSites the associated sites
+ */
+ public void setAssociateSites(URLEntry[] associateSites) {
+ this.associateSites = associateSites;
+ }
+
+ public void setDigestURLString(String digestURLString) {
+ this.digestURLString = digestURLString;
+ }
+
+ public String getDigestURLString() {
+ return digestURLString;
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteXMLAction.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteXMLAction.java
new file mode 100644
index 0000000..4cd7247
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/SiteXMLAction.java
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * 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.updatesite;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
+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.*;
+import org.eclipse.equinox.internal.provisional.p2.metadata.MetadataFactory.InstallableUnitDescription;
+import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
+import org.eclipse.equinox.p2.publisher.*;
+import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction;
+import org.eclipse.equinox.p2.publisher.eclipse.URLEntry;
+import org.eclipse.equinox.spi.p2.publisher.LocalizationHelper;
+import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
+import org.eclipse.osgi.service.resolver.VersionRange;
+import org.osgi.framework.Version;
+
+/**
+ * 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 AbstractPublisherAction {
+
+ private static final String PROTOCOL_FILE = "file"; //$NON-NLS-1$
+ private UpdateSite updateSite;
+ private SiteCategory defaultCategory;
+ private HashSet defaultCategorySet;
+
+ 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();
+ }
+
+ private void initialize() {
+ defaultCategory = new SiteCategory();
+ defaultCategory.setDescription("Default category for otherwise uncategorized features"); //$NON-NLS-1$
+ defaultCategory.setLabel("Uncategorized"); //$NON-NLS-1$
+ defaultCategory.setName("Default"); //$NON-NLS-1$
+ defaultCategorySet = new HashSet(1);
+ defaultCategorySet.add(defaultCategory);
+ }
+
+ public IStatus perform(IPublisherInfo info, IPublisherResult results) {
+ generateCategories(info, results);
+ return Status.OK_STATUS;
+ }
+
+ private void generateCategories(IPublisherInfo info, IPublisherResult results) {
+ Map categoriesToFeatureIUs = new HashMap();
+ Map featuresToCategories = getFeatureToCategoryMappings(info);
+ for (Iterator i = featuresToCategories.keySet().iterator(); i.hasNext();) {
+ SiteFeature feature = (SiteFeature) i.next();
+ IInstallableUnit iu = getFeatureIU(feature, results);
+ Set categories = (Set) featuresToCategories.get(feature);
+ // if there are no categories for this feature then add it to the default category.
+ if (categories == null || categories.isEmpty())
+ categories = defaultCategorySet;
+ for (Iterator it = categories.iterator(); it.hasNext();) {
+ SiteCategory category = (SiteCategory) it.next();
+ Set featureIUs = (Set) categoriesToFeatureIUs.get(category);
+ if (featureIUs == null) {
+ featureIUs = new HashSet();
+ categoriesToFeatureIUs.put(category, featureIUs);
+ }
+ featureIUs.add(iu);
+ }
+ }
+ generateCategoryIUs(categoriesToFeatureIUs, results);
+ }
+
+ private IInstallableUnit getFeatureIU(SiteFeature feature, IPublisherResult results) {
+ String id = FeaturesAction.getTransformedId(feature.getFeatureIdentifier(), false, true);
+ Version version = new Version(feature.getFeatureVersion());
+ // 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();
+ if (iu.getVersion().equals(version))
+ return iu;
+ }
+ return null;
+ }
+
+ /**
+ * Computes the mapping of features to categories as defined in the site.xml,
+ * 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(IPublisherInfo info) {
+ HashMap mappings = new HashMap();
+ if (updateSite == null)
+ return mappings;
+ SiteModel site = updateSite.getSite();
+ if (site == null)
+ return mappings;
+
+ //copy mirror information from update site to p2 repositories
+ String mirrors = site.getMirrorsURL();
+ if (mirrors != null) {
+ //remove site.xml file reference
+ int index = mirrors.indexOf("site.xml"); //$NON-NLS-1$
+ if (index != -1)
+ mirrors = mirrors.substring(0, index) + mirrors.substring(index + "site.xml".length()); //$NON-NLS-1$
+ info.getMetadataRepository().setProperty(IRepository.PROP_MIRRORS_URL, mirrors);
+ info.getArtifactRepository().setProperty(IRepository.PROP_MIRRORS_URL, mirrors);
+ }
+
+ //publish associate sites as repository references
+ URLEntry[] associatedSites = site.getAssociatedSites();
+ if (associatedSites != null)
+ for (int i = 0; i < associatedSites.length; i++)
+ generateSiteReference(associatedSites[i].getURL(), null, info.getMetadataRepository());
+
+ if (PROTOCOL_FILE.equals(updateSite.getLocation().getProtocol())) {
+ File siteFile = new File(updateSite.getLocation().getFile());
+ if (siteFile.exists()) {
+ File siteParent = siteFile.getParentFile();
+
+ List messageKeys = site.getMessageKeys();
+ if (siteParent.isDirectory()) {
+ String[] keyStrings = (String[]) messageKeys.toArray(new String[messageKeys.size()]);
+ site.setLocalizations(LocalizationHelper.getDirPropertyLocalizations(siteParent, "site", null, keyStrings)); //$NON-NLS-1$
+ } else if (siteFile.getName().endsWith(".jar")) { //$NON-NLS-1$
+ String[] keyStrings = (String[]) messageKeys.toArray(new String[messageKeys.size()]);
+ site.setLocalizations(LocalizationHelper.getJarPropertyLocalizations(siteParent, "site", null, keyStrings)); //$NON-NLS-1$
+ }
+ }
+ }
+
+ SiteFeature[] features = site.getFeatures();
+ for (int i = 0; i < features.length; i++) {
+ //add a mapping for each category this feature belongs to
+ String[] categoryNames = features[i].getCategoryNames();
+ Set categories = new HashSet();
+ mappings.put(features[i], categories);
+ for (int j = 0; j < categoryNames.length; j++) {
+ SiteCategory category = site.getCategory(categoryNames[j]);
+ if (category != null)
+ categories.add(category);
+ }
+ }
+ return mappings;
+ }
+
+ /**
+ * Generates and publishes a reference to an update site location
+ * @param location The update site location
+ * @param featureId the identifier of the feature where the error occurred, or null
+ * @param metadataRepo The repo into which the references are added
+ */
+ private void generateSiteReference(String location, String featureId, IMetadataRepository metadataRepo) {
+ try {
+ URL associateLocation = new URL(location);
+ metadataRepo.addReference(associateLocation, IRepository.TYPE_METADATA, IRepository.ENABLED);
+ metadataRepo.addReference(associateLocation, IRepository.TYPE_ARTIFACT, IRepository.ENABLED);
+ } catch (MalformedURLException e) {
+ String message = "Invalid site reference: " + location; //$NON-NLS-1$
+ if (featureId != null)
+ message = message + " in feature: " + featureId; //$NON-NLS-1$
+ LogHelper.log(new Status(IStatus.ERROR, Activator.ID, message));
+ }
+ }
+
+ /**
+ * Generates IUs corresponding to update site categories.
+ * @param categoriesToFeatures Map of SiteCategory ->Set (Feature IUs in that category).
+ * @param result The generator result being built
+ */
+ protected void generateCategoryIUs(Map categoriesToFeatures, IPublisherResult result) {
+ for (Iterator it = categoriesToFeatures.keySet().iterator(); it.hasNext();) {
+ SiteCategory category = (SiteCategory) it.next();
+ result.addIU(createCategoryIU(category, (Set) categoriesToFeatures.get(category), null), IPublisherResult.NON_ROOT);
+ }
+ }
+
+ /**
+ * Creates an IU corresponding to an update site category
+ * @param category The category descriptor
+ * @param featureIUs The IUs of the features that belong to the category
+ * @param parentCategory The parent category, or <code>null</code>
+ * @return an IU representing the category
+ */
+ public static IInstallableUnit createCategoryIU(SiteCategory category, Set featureIUs, IInstallableUnit parentCategory) {
+ InstallableUnitDescription cat = new MetadataFactory.InstallableUnitDescription();
+ cat.setSingleton(true);
+ String categoryId = category.getName();
+ cat.setId(categoryId);
+ cat.setVersion(Version.emptyVersion);
+ cat.setProperty(IInstallableUnit.PROP_NAME, category.getLabel());
+ cat.setProperty(IInstallableUnit.PROP_DESCRIPTION, category.getDescription());
+
+ ArrayList reqsConfigurationUnits = new ArrayList(featureIUs.size());
+ for (Iterator iterator = featureIUs.iterator(); iterator.hasNext();) {
+ IInstallableUnit iu = (IInstallableUnit) iterator.next();
+ VersionRange range = new VersionRange(iu.getVersion(), true, iu.getVersion(), true);
+ reqsConfigurationUnits.add(MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, iu.getId(), range, iu.getFilter(), false, false));
+ }
+ //note that update sites don't currently support nested categories, but it may be useful to add in the future
+ if (parentCategory != null) {
+ reqsConfigurationUnits.add(MetadataFactory.createRequiredCapability(IInstallableUnit.NAMESPACE_IU_ID, parentCategory.getId(), VersionRange.emptyRange, parentCategory.getFilter(), false, false));
+ }
+ cat.setRequiredCapabilities((RequiredCapability[]) reqsConfigurationUnits.toArray(new RequiredCapability[reqsConfigurationUnits.size()]));
+
+ // Create set of provided capabilities
+ ArrayList providedCapabilities = new ArrayList();
+ providedCapabilities.add(PublisherHelper.createSelfCapability(categoryId, Version.emptyVersion));
+
+ Map localizations = category.getLocalizations();
+ if (localizations != null) {
+ for (Iterator iter = localizations.keySet().iterator(); iter.hasNext();) {
+ Locale locale = (Locale) iter.next();
+ Properties translatedStrings = (Properties) localizations.get(locale);
+ Enumeration propertyKeys = translatedStrings.propertyNames();
+ while (propertyKeys.hasMoreElements()) {
+ String nextKey = (String) propertyKeys.nextElement();
+ cat.setProperty(locale.toString() + '.' + nextKey, translatedStrings.getProperty(nextKey));
+ }
+ providedCapabilities.add(PublisherHelper.makeTranslationCapability(categoryId, locale));
+ }
+ }
+
+ cat.setCapabilities((ProvidedCapability[]) providedCapabilities.toArray(new ProvidedCapability[providedCapabilities.size()]));
+
+ cat.setArtifacts(new IArtifactKey[0]);
+ cat.setProperty(IInstallableUnit.PROP_TYPE_CATEGORY, "true"); //$NON-NLS-1$
+ return MetadataFactory.createInstallableUnit(cat);
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/UpdateSite.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/UpdateSite.java
index d36aa15..0eda749 100644
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/UpdateSite.java
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/UpdateSite.java
@@ -19,9 +19,9 @@
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.core.helpers.URLUtil;
-import org.eclipse.equinox.internal.p2.metadata.generator.features.*;
+import org.eclipse.equinox.internal.p2.publisher.eclipse.FeatureParser;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
+import org.eclipse.equinox.p2.publisher.eclipse.*;
import org.eclipse.osgi.util.NLS;
import org.xml.sax.SAXException;
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java
deleted file mode 100644
index 6b66e66..0000000
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepository.java
+++ /dev/null
@@ -1,177 +0,0 @@
-/*******************************************************************************
- * 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.updatesite.artifact;
-
-import java.io.File;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.*;
-import org.eclipse.core.runtime.*;
-import org.eclipse.equinox.internal.p2.updatesite.*;
-import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
-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.IArtifactKey;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
-import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.SimpleArtifactRepositoryFactory;
-import org.eclipse.equinox.internal.provisional.spi.p2.core.repository.AbstractRepository;
-import org.osgi.framework.BundleContext;
-
-public class UpdateSiteArtifactRepository extends AbstractRepository implements IArtifactRepository {
-
- public static final String TYPE = "org.eclipse.equinox.p2.updatesite.artifactRepository"; //$NON-NLS-1$
- public static final Integer VERSION = new Integer(1);
- private static final String PROP_ARTIFACT_REFERENCE = "artifact.reference"; //$NON-NLS-1$
- private static final String PROP_FORCE_THREADING = "eclipse.p2.force.threading"; //$NON-NLS-1$
- private static final String PROP_SITE_CHECKSUM = "site.checksum"; //$NON-NLS-1$
- private static final String PROTOCOL_FILE = "file"; //$NON-NLS-1$
-
- private final IArtifactRepository artifactRepository;
-
- public UpdateSiteArtifactRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
- super(Activator.getRepositoryName(location), TYPE, VERSION.toString(), location, null, null, null);
-
- // todo progress monitoring
- // loading validates before we create repositories
- UpdateSite updateSite = UpdateSite.load(location, null);
-
- BundleContext context = Activator.getBundleContext();
- URL localRepositoryURL = null;
- try {
- String stateDirName = Integer.toString(location.toExternalForm().hashCode());
- File bundleData = context.getDataFile(null);
- File stateDir = new File(bundleData, stateDirName);
- localRepositoryURL = stateDir.toURL();
- } catch (MalformedURLException e) {
- throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, Messages.ErrorCreatingRepository, e));
- }
- artifactRepository = initializeArtifactRepository(context, localRepositoryURL, "update site implementation - " + location.toExternalForm(), updateSite); //$NON-NLS-1$
-
- String savedChecksum = (String) artifactRepository.getProperties().get(PROP_SITE_CHECKSUM);
- if (savedChecksum != null && savedChecksum.equals(updateSite.getChecksum()))
- return;
-
- if (!location.getProtocol().equals(PROTOCOL_FILE))
- artifactRepository.setProperty(PROP_FORCE_THREADING, "true"); //$NON-NLS-1$
- artifactRepository.removeAll();
- generateArtifacts(updateSite);
- artifactRepository.setProperty(PROP_SITE_CHECKSUM, updateSite.getChecksum());
- }
-
- private void generateArtifacts(UpdateSite updateSite) throws ProvisionException {
- Feature[] features = updateSite.loadFeatures();
-
- Set allSiteArtifacts = new HashSet();
- for (int i = 0; i < features.length; i++) {
- Feature feature = features[i];
- IArtifactKey featureKey = MetadataGeneratorHelper.createFeatureArtifactKey(feature.getId(), feature.getVersion());
- ArtifactDescriptor featureArtifactDescriptor = new ArtifactDescriptor(featureKey);
- URL featureURL = updateSite.getFeatureURL(feature.getId(), feature.getVersion());
- featureArtifactDescriptor.setRepositoryProperty(PROP_ARTIFACT_REFERENCE, featureURL.toExternalForm());
- featureArtifactDescriptor.setProperty(IArtifactDescriptor.DOWNLOAD_CONTENTTYPE, IArtifactDescriptor.TYPE_ZIP);
- allSiteArtifacts.add(featureArtifactDescriptor);
-
- FeatureEntry[] featureEntries = feature.getEntries();
- for (int j = 0; j < featureEntries.length; j++) {
- FeatureEntry entry = featureEntries[j];
- if (entry.isPlugin() && !entry.isRequires()) {
- IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(entry.getId(), entry.getVersion());
- ArtifactDescriptor artifactDescriptor = new ArtifactDescriptor(key);
- URL pluginURL = updateSite.getPluginURL(entry);
- artifactDescriptor.setRepositoryProperty(PROP_ARTIFACT_REFERENCE, pluginURL.toExternalForm());
- artifactDescriptor.setProperty(IArtifactDescriptor.DOWNLOAD_CONTENTTYPE, IArtifactDescriptor.TYPE_ZIP);
- allSiteArtifacts.add(artifactDescriptor);
- }
- }
- }
-
- IArtifactDescriptor[] descriptors = (IArtifactDescriptor[]) allSiteArtifacts.toArray(new IArtifactDescriptor[allSiteArtifacts.size()]);
- artifactRepository.addDescriptors(descriptors);
- }
-
- public static void validate(URL url, IProgressMonitor monitor) throws ProvisionException {
- UpdateSite.validate(url, monitor);
- }
-
- private IArtifactRepository initializeArtifactRepository(BundleContext context, URL stateDirURL, String repositoryName, UpdateSite updateSite) {
- SimpleArtifactRepositoryFactory factory = new SimpleArtifactRepositoryFactory();
- try {
- return factory.load(stateDirURL, null);
- } catch (ProvisionException e) {
- //fall through and create a new repository
- }
- Map props = new HashMap(5);
- String mirrors = updateSite.getMirrorsURL();
- if (mirrors != null) {
- props.put(IRepository.PROP_MIRRORS_URL, mirrors);
- //set the mirror base URL relative to the real remote repository rather than our local cache
- props.put(IRepository.PROP_MIRRORS_BASE_URL, getLocation().toExternalForm());
- }
- return factory.create(stateDirURL, repositoryName, null, props);
- }
-
- public Map getProperties() {
- return artifactRepository.getProperties();
- }
-
- public String setProperty(String key, String value) {
- return artifactRepository.setProperty(key, value);
- }
-
- public void addDescriptor(IArtifactDescriptor descriptor) {
- artifactRepository.addDescriptor(descriptor);
- }
-
- public boolean contains(IArtifactDescriptor descriptor) {
- return artifactRepository.contains(descriptor);
- }
-
- public boolean contains(IArtifactKey key) {
- return artifactRepository.contains(key);
- }
-
- public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
- return artifactRepository.getArtifact(descriptor, destination, monitor);
- }
-
- public IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) {
- return artifactRepository.getArtifactDescriptors(key);
- }
-
- public IArtifactKey[] getArtifactKeys() {
- return artifactRepository.getArtifactKeys();
- }
-
- public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) {
- return artifactRepository.getArtifacts(requests, monitor);
- }
-
- public OutputStream getOutputStream(IArtifactDescriptor descriptor) throws ProvisionException {
- return artifactRepository.getOutputStream(descriptor);
- }
-
- public void removeAll() {
- artifactRepository.removeAll();
- }
-
- public void removeDescriptor(IArtifactDescriptor descriptor) {
- artifactRepository.removeDescriptor(descriptor);
- }
-
- public void removeDescriptor(IArtifactKey key) {
- artifactRepository.removeDescriptor(key);
- }
-
- public void addDescriptors(IArtifactDescriptor[] descriptors) {
- artifactRepository.addDescriptors(descriptors);
- }
-}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepositoryFactory.java
index ef3ecd1..3a21558 100644
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepositoryFactory.java
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/artifact/UpdateSiteArtifactRepositoryFactory.java
@@ -7,15 +7,27 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.updatesite.artifact;
+import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
+
+import org.eclipse.equinox.p2.publisher.eclipse.Feature;
+import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry;
+
+import org.eclipse.equinox.p2.publisher.eclipse.FeaturesAction;
+
import java.net.URL;
-import java.util.Map;
+import java.util.*;
import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository;
+import org.eclipse.equinox.internal.p2.updatesite.UpdateSite;
+import org.eclipse.equinox.internal.p2.updatesite.metadata.UpdateSiteMetadataRepositoryFactory;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
+import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.IArtifactRepositoryFactory;
+import org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.SimpleArtifactRepositoryFactory;
public class UpdateSiteArtifactRepositoryFactory implements IArtifactRepositoryFactory {
@@ -26,10 +38,70 @@
return null;
}
+ private static final String PROP_ARTIFACT_REFERENCE = "artifact.reference"; //$NON-NLS-1$
+ private static final String PROP_FORCE_THREADING = "eclipse.p2.force.threading"; //$NON-NLS-1$
+ private static final String PROP_SITE_CHECKSUM = "site.checksum"; //$NON-NLS-1$
+ private static final String PROTOCOL_FILE = "file"; //$NON-NLS-1$
+
/* (non-Javadoc)
* @see org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository.IArtifactRepositoryFactory#load(java.net.URL, org.eclipse.core.runtime.IProgressMonitor)
*/
public IArtifactRepository load(URL location, IProgressMonitor monitor) throws ProvisionException {
- return new UpdateSiteArtifactRepository(location, monitor);
+ IArtifactRepository repository = loadRepository(location, monitor);
+ initializeRepository(repository, location, monitor);
+ return repository;
+ }
+
+ public IArtifactRepository loadRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
+ URL localRepositoryURL = UpdateSiteMetadataRepositoryFactory.getLocalRepositoryLocation(location);
+ SimpleArtifactRepositoryFactory factory = new SimpleArtifactRepositoryFactory();
+ try {
+ return factory.load(localRepositoryURL, null);
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+ String repositoryName = "update site: " + location.toExternalForm(); //$NON-NLS-1$
+ return factory.create(localRepositoryURL, repositoryName, null, null);
+ }
+
+ public void initializeRepository(IArtifactRepository repository, URL location, IProgressMonitor monitor) throws ProvisionException {
+ UpdateSite updateSite = UpdateSite.load(location, null);
+ String savedChecksum = (String) repository.getProperties().get(PROP_SITE_CHECKSUM);
+ if (savedChecksum != null && savedChecksum.equals(updateSite.getChecksum()))
+ return;
+
+ if (!location.getProtocol().equals(PROTOCOL_FILE))
+ repository.setProperty(PROP_FORCE_THREADING, "true"); //$NON-NLS-1$
+ repository.setProperty(PROP_SITE_CHECKSUM, updateSite.getChecksum());
+ repository.removeAll();
+ generateMetadata(updateSite, repository);
+ }
+
+ private void generateMetadata(UpdateSite updateSite, IArtifactRepository repository) throws ProvisionException {
+ Feature[] features = updateSite.loadFeatures();
+ Set allSiteArtifacts = new HashSet();
+ for (int i = 0; i < features.length; i++) {
+ Feature feature = features[i];
+ IArtifactKey featureKey = FeaturesAction.createFeatureArtifactKey(feature.getId(), feature.getVersion());
+ ArtifactDescriptor featureArtifactDescriptor = new ArtifactDescriptor(featureKey);
+ URL featureURL = updateSite.getFeatureURL(feature.getId(), feature.getVersion());
+ featureArtifactDescriptor.setRepositoryProperty(PROP_ARTIFACT_REFERENCE, featureURL.toExternalForm());
+ allSiteArtifacts.add(featureArtifactDescriptor);
+
+ FeatureEntry[] featureEntries = feature.getEntries();
+ for (int j = 0; j < featureEntries.length; j++) {
+ FeatureEntry entry = featureEntries[j];
+ if (entry.isPlugin() && !entry.isRequires()) {
+ IArtifactKey key = PublisherHelper.createBundleArtifactKey(entry.getId(), entry.getVersion());
+ ArtifactDescriptor artifactDescriptor = new ArtifactDescriptor(key);
+ URL pluginURL = updateSite.getPluginURL(entry);
+ artifactDescriptor.setRepositoryProperty(PROP_ARTIFACT_REFERENCE, pluginURL.toExternalForm());
+ allSiteArtifacts.add(artifactDescriptor);
+ }
+ }
+ }
+
+ IArtifactDescriptor[] descriptors = (IArtifactDescriptor[]) allSiteArtifacts.toArray(new IArtifactDescriptor[allSiteArtifacts.size()]);
+ repository.addDescriptors(descriptors);
}
}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/messages.properties b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/messages.properties
index e3d734a..c6def23 100644
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/messages.properties
@@ -18,3 +18,20 @@
io_failedRead=Unable to read repository at {0}.
repoMan_internalError=Internal error.
repo_loading = Loading the repository {0}
+
+DefaultFeatureParser_IdOrVersionInvalid= Error parsing feature stream. The unique identifier or the version is null or empty for the State: \"{2}\": unique identifier=\"{0}\" version=\"{1}\".
+DefaultSiteParser_NoSiteTag= Error parsing site stream. Unable to find root element \"site\" in the stream.
+DefaultSiteParser_WrongParsingStack= Internal Error parsing site stream. Unexpected Parsing Stack: \"{0}\"
+DefaultSiteParser_UnknownElement= Error parsing site stream. Unknown element \"{0}\" in parsing state \"{1}\". Check the validity of the XML file.
+DefaultSiteParser_UnknownStartState= Internal Error parsing site stream. Unknown start state \"{0}\".
+DefaultSiteParser_Missing= Error parsing site stream. The \"{0}\" tag of the element \"{1}\" is null or empty. Value is required.
+DefaultSiteParser_ParsingStackBackToInitialState= Internal Error parsing site stream. Parsing stack back to Initial State.
+DefaultSiteParser_ElementAlreadySet= Error parsing site stream. Element: \"{0}\" already set for the Site.
+DefaultSiteParser_CategoryAlreadySet= Error parsing site stream. Element: \"{0}\": \"{1}\" already set for the Site.
+DefaultSiteParser_UnknownEndState= Internal Error parsing site stream. Unknown end state \"{0}\".
+DefaultSiteParser_ErrorParsing= Error Parsing site stream. Error: \"{0}\"
+DefaultSiteParser_ErrorlineColumnMessage= Error Parsing site stream. Element \"{0}\" line: \"{1}\" column:\"{2}\". Error: \"{3}\".
+DefaultSiteParser_ErrorParsingSite= Error Parsing site stream.
+DefaultSiteParser_UnknownState= Unknown State \"{0}\".
+DefaultSiteParser_InvalidXMLStream= The XML stream is not a valid default \"site.xml\" file. The root tag is not site.
+DefaultSiteParser_mirrors = Error processing update site mirror.
\ No newline at end of file
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java
deleted file mode 100644
index ff8b9b2..0000000
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepository.java
+++ /dev/null
@@ -1,274 +0,0 @@
-/*******************************************************************************
- * 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
- * Ray Braithwood (ray@genuitec.com) - fix for bug 220605
- *******************************************************************************/
-package org.eclipse.equinox.internal.p2.updatesite.metadata;
-
-import java.io.File;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.*;
-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.generator.features.*;
-import org.eclipse.equinox.internal.p2.updatesite.*;
-import org.eclipse.equinox.internal.p2.updatesite.Messages;
-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.core.repository.RepositoryEvent;
-import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey;
-import org.eclipse.equinox.internal.provisional.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.internal.provisional.p2.metadata.generator.*;
-import org.eclipse.equinox.internal.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.equinox.internal.provisional.spi.p2.metadata.repository.AbstractMetadataRepository;
-import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.SimpleMetadataRepositoryFactory;
-import org.eclipse.osgi.service.resolver.*;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-
-public class UpdateSiteMetadataRepository extends AbstractMetadataRepository {
-
- public static final String TYPE = "org.eclipse.equinox.p2.updatesite.metadataRepository"; //$NON-NLS-1$
- public static final Integer VERSION = new Integer(1);
- private final IMetadataRepository metadataRepository;
- private static final String FEATURE_VERSION_SEPARATOR = "_"; //$NON-NLS-1$
- private static final String PROP_SITE_CHECKSUM = "site.checksum"; //$NON-NLS-1$
-
- public UpdateSiteMetadataRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
- super(Activator.getRepositoryName(location), TYPE, VERSION.toString(), location, null, null, null);
- // todo progress monitoring
- // loading validates before we create repositories
- UpdateSite updateSite = UpdateSite.load(location, null);
- broadcastAssociateSites(updateSite);
-
- BundleContext context = Activator.getBundleContext();
- String stateDirName = Integer.toString(location.toExternalForm().hashCode());
- File bundleData = context.getDataFile(null);
- File stateDir = new File(bundleData, stateDirName);
- URL localRepositoryURL;
- try {
- localRepositoryURL = stateDir.toURL();
- } catch (MalformedURLException e) {
- // unexpected
- throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, Messages.ErrorCreatingRepository, e));
- }
-
- metadataRepository = initializeMetadataRepository(context, localRepositoryURL, "update site implementation - " + location.toExternalForm(), updateSite); //$NON-NLS-1$
-
- String savedChecksum = (String) metadataRepository.getProperties().get(PROP_SITE_CHECKSUM);
- if (savedChecksum != null && savedChecksum.equals(updateSite.getChecksum()))
- return;
- metadataRepository.removeAll();
- generateMetadata(updateSite);
- metadataRepository.setProperty(PROP_SITE_CHECKSUM, updateSite.getChecksum());
- }
-
- /**
- * Broadcast events for any associated sites for this repository so repository
- * managers are aware of them.
- */
- private void broadcastAssociateSites(UpdateSite baseSite) {
- if (baseSite == null)
- return;
- URLEntry[] sites = baseSite.getSite().getAssociatedSites();
- if (sites == null || sites.length == 0)
- return;
-
- IProvisioningEventBus bus = (IProvisioningEventBus) ServiceHelper.getService(Activator.getBundleContext(), IProvisioningEventBus.SERVICE_NAME);
- if (bus == null)
- return;
- for (int i = 0; i < sites.length; i++) {
- try {
- URL siteLocation = new URL(sites[i].getURL());
- bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED, true));
- bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED, true));
- } catch (MalformedURLException e) {
- LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "Site has invalid associate site: " + baseSite.getLocation(), e)); //$NON-NLS-1$
- }
- }
-
- }
-
- private void generateMetadata(UpdateSite updateSite) throws ProvisionException {
- SiteModel siteModel = updateSite.getSite();
-
- // we load the features here to ensure that all site features are fully populated with
- // id and version information before looking at category information
- Feature[] features = updateSite.loadFeatures();
-
- SiteCategory[] siteCategories = siteModel.getCategories();
- Map categoryNameToFeatureIUs = new HashMap();
- for (int i = 0; i < siteCategories.length; i++)
- categoryNameToFeatureIUs.put(siteCategories[i].getName(), new HashSet());
-
- SiteFeature[] siteFeatures = siteModel.getFeatures();
- Map featureKeyToCategoryNames = new HashMap();
- for (int i = 0; i < siteFeatures.length; i++) {
- SiteFeature siteFeature = siteFeatures[i];
- String featureKey = siteFeature.getFeatureIdentifier() + FEATURE_VERSION_SEPARATOR + siteFeature.getFeatureVersion();
- featureKeyToCategoryNames.put(featureKey, siteFeature.getCategoryNames());
- }
-
- Properties extraProperties = new Properties();
- extraProperties.put(IInstallableUnit.PROP_PARTIAL_IU, Boolean.TRUE.toString());
- Set allSiteIUs = new HashSet();
- BundleDescriptionFactory bundleDesciptionFactory = initializeBundleDescriptionFactory(Activator.getBundleContext());
-
- for (int i = 0; i < features.length; i++) {
- Feature feature = features[i];
- FeatureEntry[] featureEntries = feature.getEntries();
- for (int j = 0; j < featureEntries.length; j++) {
- FeatureEntry entry = featureEntries[j];
- if (entry.isPlugin() && !entry.isRequires()) {
- Dictionary mockManifest = new Properties();
- mockManifest.put("Manifest-Version", "1.0"); //$NON-NLS-1$ //$NON-NLS-2$
- mockManifest.put("Bundle-ManifestVersion", "2"); //$NON-NLS-1$ //$NON-NLS-2$
- mockManifest.put("Bundle-SymbolicName", entry.getId()); //$NON-NLS-1$
- mockManifest.put("Bundle-Version", entry.getVersion()); //$NON-NLS-1$
- BundleDescription bundleDescription = bundleDesciptionFactory.getBundleDescription(mockManifest, null);
- IArtifactKey key = MetadataGeneratorHelper.createBundleArtifactKey(entry.getId(), entry.getVersion());
- IInstallableUnit[] bundleIUs = MetadataGeneratorHelper.createEclipseIU(bundleDescription, null, entry.isUnpack(), key, extraProperties);
- for (int n = 0; n < bundleIUs.length; n++) {
- allSiteIUs.add(bundleIUs[n]);
- }
- }
- }
-
- IInstallableUnit featureIU = MetadataGeneratorHelper.createFeatureJarIU(feature, true);
- IInstallableUnit groupIU = MetadataGeneratorHelper.createGroupIU(feature, featureIU);
-
- String featureKey = feature.getId() + FEATURE_VERSION_SEPARATOR + feature.getVersion();
- String[] categoryNames = (String[]) featureKeyToCategoryNames.get(featureKey);
- if (categoryNames != null) {
- for (int j = 0; j < categoryNames.length; j++) {
- Set featureIUList = (Set) categoryNameToFeatureIUs.get(categoryNames[j]);
- if (featureIUList != null) {
- featureIUList.add(groupIU);
- }
- }
- }
- allSiteIUs.add(featureIU);
- allSiteIUs.add(groupIU);
- publishSites(feature);
- }
-
- for (int i = 0; i < siteCategories.length; i++) {
- SiteCategory category = siteCategories[i];
- Set featureIUs = (Set) categoryNameToFeatureIUs.get(category.getName());
- IInstallableUnit categoryIU = MetadataGeneratorHelper.createCategoryIU(category, featureIUs, null);
- allSiteIUs.add(categoryIU);
- }
-
- IInstallableUnit[] ius = (IInstallableUnit[]) allSiteIUs.toArray(new IInstallableUnit[allSiteIUs.size()]);
- metadataRepository.addInstallableUnits(ius);
- }
-
- /*(non-Javadoc)
- * @see IMetadataRepositoryFactory#validate(URL, IProgressMonitor)
- */
- public static void validate(URL url, IProgressMonitor monitor) throws ProvisionException {
- UpdateSite.validate(url, monitor);
- }
-
- private IMetadataRepository initializeMetadataRepository(BundleContext context, URL stateDirURL, String repositoryName, UpdateSite updateSite) {
- SimpleMetadataRepositoryFactory factory = new SimpleMetadataRepositoryFactory();
- try {
- return factory.load(stateDirURL, null);
- } catch (ProvisionException e) {
- //fall through and create a new repository
- }
- Map props = new HashMap(5);
- String mirrors = updateSite.getMirrorsURL();
- if (mirrors != null) {
- props.put(IRepository.PROP_MIRRORS_URL, mirrors);
- //set the mirror base URL relative to the real remote repository rather than our local cache
- props.put(IRepository.PROP_MIRRORS_BASE_URL, getLocation().toExternalForm());
- }
- return factory.create(stateDirURL, repositoryName, null, props);
- }
-
- private BundleDescriptionFactory initializeBundleDescriptionFactory(BundleContext context) {
- ServiceReference reference = context.getServiceReference(PlatformAdmin.class.getName());
- if (reference == null)
- throw new IllegalStateException(Messages.PlatformAdminNotRegistered);
- PlatformAdmin platformAdmin = (PlatformAdmin) context.getService(reference);
- if (platformAdmin == null)
- throw new IllegalStateException(Messages.PlatformAdminNotRegistered);
-
- try {
- StateObjectFactory stateObjectFactory = platformAdmin.getFactory();
- return new BundleDescriptionFactory(stateObjectFactory, null);
- } finally {
- context.ungetService(reference);
- }
- }
-
- public Map getProperties() {
- return metadataRepository.getProperties();
- }
-
- public String setProperty(String key, String value) {
- return metadataRepository.setProperty(key, value);
- }
-
- public Collector query(Query query, Collector collector, IProgressMonitor monitor) {
- return metadataRepository.query(query, collector, monitor);
- }
-
- public void removeAll() {
- metadataRepository.removeAll();
- }
-
- public void addInstallableUnits(IInstallableUnit[] installableUnits) {
- metadataRepository.addInstallableUnits(installableUnits);
- }
-
- public boolean removeInstallableUnits(Query query, IProgressMonitor monitor) {
- return metadataRepository.removeInstallableUnits(query, monitor);
- }
-
- public void initialize(RepositoryState state) {
- //nothing to do
- }
-
- /**
- * Broadcast events for any discovery sites associated with the feature
- * so the repository managers add them to their list of known repositories.
- */
- private void publishSites(Feature feature) {
- IProvisioningEventBus bus = (IProvisioningEventBus) ServiceHelper.getService(Activator.getBundleContext(), IProvisioningEventBus.SERVICE_NAME);
- if (bus == null)
- return;
- URLEntry[] discoverySites = feature.getDiscoverySites();
- for (int i = 0; i < discoverySites.length; i++)
- publishSite(feature, bus, discoverySites[i].getURL(), false);
- String updateSite = feature.getUpdateSiteURL();
- if (updateSite != null)
- publishSite(feature, bus, updateSite, true);
- }
-
- /**
- * Broadcast a discovery event for the given repository location.
- */
- private void publishSite(Feature feature, IProvisioningEventBus bus, String locationString, boolean isEnabled) {
- try {
- URL siteLocation = new URL(locationString);
- bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_METADATA, RepositoryEvent.DISCOVERED, isEnabled));
- bus.publishEvent(new RepositoryEvent(siteLocation, IRepository.TYPE_ARTIFACT, RepositoryEvent.DISCOVERED, isEnabled));
- } catch (MalformedURLException e) {
- LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "Feature references invalid site: " + feature.getId(), e)); //$NON-NLS-1$
- }
- }
-
-}
diff --git a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepositoryFactory.java
index 2be0d50..5a7f78d 100644
--- a/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepositoryFactory.java
+++ b/bundles/org.eclipse.equinox.p2.updatesite/src/org/eclipse/equinox/internal/p2/updatesite/metadata/UpdateSiteMetadataRepositoryFactory.java
@@ -8,17 +8,37 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Ray Braithwood (ray@genuitec.com) - fix for bug 220605
+ * Code 9 - ongoing development
*******************************************************************************/
package org.eclipse.equinox.internal.p2.updatesite.metadata;
+import java.io.File;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;
import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.updatesite.*;
import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException;
import org.eclipse.equinox.internal.provisional.p2.metadata.repository.IMetadataRepository;
import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.IMetadataRepositoryFactory;
+import org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.SimpleMetadataRepositoryFactory;
+import org.eclipse.equinox.p2.publisher.*;
public class UpdateSiteMetadataRepositoryFactory implements IMetadataRepositoryFactory {
+ private static final String PROP_SITE_CHECKSUM = "site.checksum"; //$NON-NLS-1$
+
+ public static URL getLocalRepositoryLocation(URL location) throws ProvisionException {
+ URL localRepositoryURL = null;
+ try {
+ String stateDirName = Integer.toString(location.toExternalForm().hashCode());
+ File bundleData = Activator.getBundleContext().getDataFile(null);
+ File stateDir = new File(bundleData, stateDirName);
+ localRepositoryURL = stateDir.toURL();
+ } catch (MalformedURLException e) {
+ throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, Messages.ErrorCreatingRepository, e));
+ }
+ return localRepositoryURL;
+ }
/* (non-Javadoc)
* @see org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.IMetadataRepositoryFactory#create(java.net.URL, java.lang.String, java.lang.String, java.util.Map)
@@ -27,24 +47,49 @@
return null;
}
- /*
- * (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.IMetadataRepositoryFactory#validate(java.net.URL, org.eclipse.core.runtime.IProgressMonitor)
- */
-
public IStatus validate(URL location, IProgressMonitor monitor) {
try {
- UpdateSiteMetadataRepository.validate(location, monitor);
+ UpdateSite.validate(location, monitor);
} catch (ProvisionException e) {
return e.getStatus();
}
return Status.OK_STATUS;
}
- /* (non-Javadoc)
- * @see org.eclipse.equinox.internal.provisional.spi.p2.metadata.repository.IMetadataRepositoryFactory#load(java.net.URL, org.eclipse.core.runtime.IProgressMonitor)
- */
public IMetadataRepository load(URL location, IProgressMonitor monitor) throws ProvisionException {
- return new UpdateSiteMetadataRepository(location, monitor);
+ IMetadataRepository repository = loadRepository(location, monitor);
+ initializeRepository(repository, location, monitor);
+ return repository;
}
+
+ public IMetadataRepository loadRepository(URL location, IProgressMonitor monitor) throws ProvisionException {
+ URL localRepositoryURL = getLocalRepositoryLocation(location);
+ SimpleMetadataRepositoryFactory factory = new SimpleMetadataRepositoryFactory();
+ try {
+ return factory.load(localRepositoryURL, null);
+ } catch (ProvisionException e) {
+ //fall through and create a new repository
+ }
+ String repositoryName = "update site: " + location.toExternalForm(); //$NON-NLS-1$
+ return factory.create(localRepositoryURL, repositoryName, null, null);
+ }
+
+ public void initializeRepository(IMetadataRepository repository, URL location, IProgressMonitor monitor) throws ProvisionException {
+ UpdateSite updateSite = UpdateSite.load(location, null);
+ String savedChecksum = (String) repository.getProperties().get(PROP_SITE_CHECKSUM);
+ if (savedChecksum != null && savedChecksum.equals(updateSite.getChecksum()))
+ return;
+ repository.setProperty(PROP_SITE_CHECKSUM, updateSite.getChecksum());
+ repository.removeAll();
+ generateMetadata(updateSite, repository);
+ }
+
+ private void generateMetadata(UpdateSite updateSite, IMetadataRepository repository) {
+ PublisherInfo info = new PublisherInfo();
+ info.setMetadataRepository(repository);
+ IPublisherAction[] actions = new IPublisherAction[] {new RemoteUpdateSiteAction(updateSite)};
+ Publisher publisher = new Publisher(info);
+ IStatus result = publisher.publish(actions);
+ }
+
}