diff options
author | John Arthorne | 2007-09-30 18:11:02 +0000 |
---|---|---|
committer | John Arthorne | 2007-09-30 18:11:02 +0000 |
commit | 2ccb446cc885495686cc9eb430c4a98031b3cfc5 (patch) | |
tree | 207e30d5f61856ece926ed3548297aa3958132c9 /bundles/org.eclipse.equinox.p2.metadata.repository/src | |
parent | c4f6662ccd02bb75cba95a6ae56a2da38c6cadde (diff) | |
download | rt.equinox.p2-2ccb446cc885495686cc9eb430c4a98031b3cfc5.tar.gz rt.equinox.p2-2ccb446cc885495686cc9eb430c4a98031b3cfc5.tar.xz rt.equinox.p2-2ccb446cc885495686cc9eb430c4a98031b3cfc5.zip |
Renamed prov bundles to p2
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.metadata.repository/src')
14 files changed, 1039 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/AbstractMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/AbstractMetadataRepository.java new file mode 100644 index 000000000..11600a73c --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/AbstractMetadataRepository.java @@ -0,0 +1,69 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import java.util.HashSet; +import org.eclipse.equinox.prov.core.helpers.OrderedProperties; +import org.eclipse.equinox.prov.core.helpers.UnmodifiableProperties; +import org.eclipse.equinox.prov.core.repository.IRepositoryInfo; +import org.eclipse.equinox.prov.metadata.repository.IMetadataRepository; + +public abstract class AbstractMetadataRepository implements IMetadataRepository, IRepositoryInfo { + + protected String name; + protected String type; + protected String version; + protected String description; + protected String provider; + protected OrderedProperties properties = new OrderedProperties(); + protected HashSet units = new HashSet(); + + protected AbstractMetadataRepository(String name, String type, String version) { + super(); + this.name = name; + this.type = type; + this.version = version; + this.description = ""; //$NON-NLS-1$ + this.provider = ""; //$NON-NLS-1$ + } + + public String getName() { + return name; + } + + public String getType() { + return type; + } + + public String getVersion() { + return version; + } + + public String getDescription() { + return description; + } + + public String getProvider() { + return provider; + } + + public UnmodifiableProperties getProperties() { + return new UnmodifiableProperties(properties); + } + + public Object getAdapter(Class adapter) { + if (adapter == AbstractMetadataRepository.class || adapter == IMetadataRepository.class || adapter == IRepositoryInfo.class) + return this; + else + return null; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/Activator.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/Activator.java new file mode 100644 index 000000000..7aebe0eb0 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/Activator.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + public static final String ID = "org.eclipse.equinox.prov.metadata.repository"; + public static final String REPO_PROVIDER_XPT = ID + '.' + "metadataRepositories"; + public static final String PI_METADATA_REPOSITORY = "org.eclipse.equinox.prov.metadata.repository"; //$NON-NLS-1$ + private static BundleContext context; + + public static BundleContext getContext() { + return context; + } + + public void start(BundleContext context) throws Exception { + Activator.context = context; + } + + public void stop(BundleContext context) throws Exception { + Activator.context = null; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/LocalMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/LocalMetadataRepository.java new file mode 100644 index 000000000..68b8729cd --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/LocalMetadataRepository.java @@ -0,0 +1,150 @@ +/******************************************************************************* + * Copyright (c) 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 + * Prashant Deva - Bug 194674 [prov] Provide write access to metadata repository + *******************************************************************************/ +package org.eclipse.equinox.internal.prov.metadata.repository; + +import java.io.*; +import java.net.URL; +import java.util.Arrays; +import java.util.Iterator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.prov.core.helpers.OrderedProperties; +import org.eclipse.equinox.prov.core.repository.IWritableRepositoryInfo; +import org.eclipse.equinox.prov.core.repository.RepositoryCreationException; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.metadata.RequiredCapability; +import org.eclipse.equinox.prov.metadata.repository.IWritableMetadataRepository; +import org.eclipse.equinox.prov.query.CompoundIterator; +import org.eclipse.osgi.service.resolver.VersionRange; +import org.eclipse.osgi.util.NLS; + +/** + * A metadata repository that resides in the local file system. If the repository + * location is a directory, this implementation will traverse the directory structure + * and combine any metadata repository files that are found. + */ +public class LocalMetadataRepository extends AbstractMetadataRepository implements IWritableMetadataRepository { + + static final private String REPOSITORY_TYPE = LocalMetadataRepository.class.getName(); + static final private Integer REPOSITORY_VERSION = new Integer(1); + static final private String CONTENT_FILENAME = "content.xml"; //$NON-NLS-1$ + + transient private URL location; + + public static File getActualLocation(URL location) { + String spec = location.getFile(); + if (spec.endsWith(CONTENT_FILENAME)) + return new File(spec); + if (spec.endsWith("/")) //$NON-NLS-1$ + spec += CONTENT_FILENAME; + else + spec += "/" + CONTENT_FILENAME; //$NON-NLS-1$ + return new File(spec); + } + + public LocalMetadataRepository(URL location, String name) throws RepositoryCreationException { + super(name == null ? (location != null ? location.toExternalForm() : "") : name, REPOSITORY_TYPE, REPOSITORY_VERSION.toString()); + if (!location.getProtocol().equals("file")) //$NON-NLS-1$ + throw new IllegalArgumentException("Invalid local repository location: " + location); + this.location = location; + } + + public IInstallableUnit[] getInstallableUnits(IProgressMonitor monitor) { + if (monitor == null) { + monitor = new NullProgressMonitor(); + } + monitor.beginTask(NLS.bind(Messages.REPO_LOADING, location.toExternalForm()), 5); + IInstallableUnit[] result = query(null, null, null, false, monitor); + monitor.done(); + return result; + } + + public Iterator getIterator(String id, VersionRange range, RequiredCapability[] requirements, boolean and) { + return new CompoundIterator(new Iterator[] {units.iterator()}, id, range, requirements, and); + } + + public URL getLocation() { + return location; + } + + public IInstallableUnit[] query(String id, VersionRange range, RequiredCapability[] requirements, boolean and, IProgressMonitor monitor) { + return CompoundIterator.asArray(new CompoundIterator(new Iterator[] {units.iterator()}, id, range, requirements, and), null); + } + + public void addInstallableUnits(IInstallableUnit[] installableUnits) { + units.addAll(Arrays.asList(installableUnits)); + save(); + } + + private void save() { + File file = getActualLocation(location); + try { + if (!file.exists()) { + if (!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + file.createNewFile(); + } + MetadataRepositoryIO.write(this, new FileOutputStream(file)); + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + public void removeInstallableUnits(IInstallableUnit[] installableUnits) { + units.remove(Arrays.asList(installableUnits)); + save(); + } + + public void setName(String name) { + this.name = name; + } + + public void setType(String type) throws UnsupportedOperationException { + throw new UnsupportedOperationException("The type of a local metadata repository cannot be changed."); //$NON-NLS-1$ + } + + public void setVersion(String version) { + this.version = version; + } + + public void setDescription(String description) { + this.description = description; + } + + public void setProvider(String provider) { + this.provider = provider; + } + + public OrderedProperties getModifiableProperties() { + return properties; + } + + public Object getAdapter(Class adapter) { + if (adapter == LocalMetadataRepository.class || adapter == IWritableMetadataRepository.class || adapter == IWritableRepositoryInfo.class) + return this; + return super.getAdapter(adapter); + } + + public void removeAll() { + units.clear(); + save(); + } + + // use this method to setup any transient fields etc after the object has been restored from a stream + public void initializeAfterLoad(URL location) { + this.location = location; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/Messages.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/Messages.java new file mode 100644 index 000000000..4a95ec0ce --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/Messages.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import org.eclipse.osgi.util.NLS; + +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.prov.metadata.repository.messages"; //$NON-NLS-1$ + + static { + // initialize resource bundles + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + // Do not instantiate + } + + public static String REPO_LOADING; + public static String REPOMGR_ADDING_REPO; +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataCache.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataCache.java new file mode 100644 index 000000000..f1916b8c8 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataCache.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import java.io.*; +import java.net.URL; +import java.util.EventObject; +import org.eclipse.equinox.prov.core.eventbus.ProvisioningEventBus; +import org.eclipse.equinox.prov.core.eventbus.ProvisioningListener; +import org.eclipse.equinox.prov.core.repository.RepositoryCreationException; +import org.eclipse.equinox.prov.engine.*; +import org.eclipse.equinox.prov.metadata.IResolvedInstallableUnit; +import org.osgi.framework.ServiceReference; + +public class MetadataCache extends URLMetadataRepository { + + static final private String REPOSITORY_NAME = "Agent Metadata Cache"; //$NON-NLS-1$ + static final private String REPOSITORY_TYPE = MetadataCache.class.getName(); + static final private Integer REPOSITORY_VERSION = new Integer(1); + + transient private ServiceReference busReference; + transient private ProvisioningEventBus bus; + + // These are always created with file: URLs. At least for now... + public MetadataCache(URL repoPath) throws RepositoryCreationException { + super(REPOSITORY_NAME, REPOSITORY_TYPE, REPOSITORY_VERSION.toString()); + this.location = repoPath; + content = getActualLocation(location); + new SimpleMetadataRepositoryFactory().load(location); + // Set property indicating that the metadata cache is an implementation detail. + this.properties.setProperty(IMPLEMENTATION_ONLY_KEY, Boolean.valueOf(true).toString()); + + // TODO: We should check for writing permission here, otherwise it may be too late + busReference = Activator.getContext().getServiceReference(ProvisioningEventBus.class.getName()); + bus = (ProvisioningEventBus) Activator.getContext().getService(busReference); + bus.addListener(new ProvisioningListener() { + public void notify(EventObject o) { + if (o instanceof InstallableUnitEvent) { //TODO This dependency on InstallableUnitEvent is not great + InstallableUnitEvent event = (InstallableUnitEvent) o; + if (event.isPre()) + return; + //TODO what about update and uninstall?? + if (event.isPost() && event.getResult().isOK()) { + IResolvedInstallableUnit installedIU = event.getOperand().second(); + if (installedIU != null) + units.add(installedIU.getOriginal()); + return; + } + } + if (o instanceof CommitOperationEvent) + persist(); + if (o instanceof RollbackOperationEvent) + new SimpleMetadataRepositoryFactory().restore(MetadataCache.this, location); + } + }); + } + + protected void persist() { + if (!getContentURL().getProtocol().equals("file")) + throw new IllegalStateException("only file: URLs are supported for the metadata cache"); + File contentFile = new File(getContentURL().getFile()); + if (!contentFile.getParentFile().exists() && !contentFile.getParentFile().mkdirs()) + throw new RuntimeException("can't persist the metadata cache"); + try { + OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(contentFile, false));; + MetadataRepositoryIO.write(this, outputStream); + } catch (FileNotFoundException e) { + throw new RuntimeException("can't persist the metadata cache"); + } + } + +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataRepositoryIO.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataRepositoryIO.java new file mode 100644 index 000000000..b76f1f401 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataRepositoryIO.java @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 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 + * Prashant Deva - Bug 194674 [prov] Provide write access to metadata repository + *******************************************************************************/ +package org.eclipse.equinox.internal.prov.metadata.repository; + +import com.thoughtworks.xstream.XStream; +import java.io.*; +import org.eclipse.equinox.prov.core.repository.RepositoryCreationException; +import org.eclipse.equinox.prov.metadata.repository.IMetadataRepository; + +/** + * This class reads and writes provisioning metadata. + * The implementation currently uses XStream. + */ +class MetadataRepositoryIO { + + /** + * Reads metadata from the given stream, and returns the contained array + * of abstract metadata repositories. + * This method performs buffering, and closes the stream when finished. + */ + public static IMetadataRepository read(InputStream input) throws RepositoryCreationException { + XStream stream = new XStream(); + BufferedInputStream bufferedInput = null; + try { + try { + bufferedInput = new BufferedInputStream(input); + return (IMetadataRepository) stream.fromXML(bufferedInput); + } finally { + if (bufferedInput != null) + bufferedInput.close(); + } + } catch (IOException e) { + throw new RepositoryCreationException(e); + } + } + + public static void write(AbstractMetadataRepository repository, OutputStream output) { + XStream stream = new XStream(); + OutputStream bufferedOutput = null; + try { + try { + bufferedOutput = new BufferedOutputStream(output); + stream.toXML(repository, bufferedOutput); + } finally { + if (bufferedOutput != null) + bufferedOutput.close(); + } + } catch (FileNotFoundException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } catch (IOException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataRepositoryManager.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataRepositoryManager.java new file mode 100644 index 000000000..8c9651e5f --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/MetadataRepositoryManager.java @@ -0,0 +1,294 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.*; +import org.eclipse.core.runtime.*; +import org.eclipse.core.runtime.preferences.ConfigurationScope; +import org.eclipse.equinox.prov.core.helpers.*; +import org.eclipse.equinox.prov.core.location.AgentLocation; +import org.eclipse.equinox.prov.core.repository.RepositoryCreationException; +import org.eclipse.equinox.prov.metadata.repository.*; +import org.eclipse.osgi.util.NLS; +import org.osgi.service.prefs.BackingStoreException; +import org.osgi.service.prefs.Preferences; + +public class MetadataRepositoryManager implements IMetadataRepositoryManager { + private static final String FACTORY = "factory"; //$NON-NLS-1$ + + private static final String NODE_REPOSITORIES = "repositories"; //$NON-NLS-1$ + private static final String KEY_DESCRIPTION = "description"; //$NON-NLS-1$ + private static final String KEY_NAME = "name"; //$NON-NLS-1$ + private static final String KEY_PROVIDER = "provider"; //$NON-NLS-1$ + private static final String KEY_TYPE = "type"; //$NON-NLS-1$ + private static final String KEY_URL = "url"; //$NON-NLS-1$ + private static final String KEY_VERSION = "version"; //$NON-NLS-1$ + + private List repositories = Collections.synchronizedList(new ArrayList()); + + public MetadataRepositoryManager() { + restoreRepositories(); + } + + public void addRepository(IMetadataRepository repository) { + repositories.add(repository); + // save the given repository in the preferences. + remember(repository); + } + + /* + * Restore the list of repositories from the preference store. + */ + private void restoreFromPreferences() { + // restore the list of repositories from the preference store + Preferences node = getPreferences(); + String[] children; + try { + children = node.childrenNames(); + } catch (BackingStoreException e) { + log("Error restoring repositories from preferences", e); //$NON-NLS-1$ + return; + } + for (int i = 0; i < children.length; i++) { + Preferences child = node.node(children[i]); + String url = child.get(KEY_URL, null); + if (url == null) + continue; + try { + IMetadataRepository repository = loadRepository(new URL(url), (IProgressMonitor) null); + // If we could not restore the repo then remove it from the preferences. + if (repository == null) + child.removeNode(); + } catch (MalformedURLException e) { + log("Error while restoring repository: " + url, e); //$NON-NLS-1$ + } catch (BackingStoreException e) { + log("Error while restoring repository: " + url, e); //$NON-NLS-1$ + } + } + } + + /* + * Save the list of repositories in the preference store. + */ + private void remember(IMetadataRepository repository) { + Preferences node = getPreferences().node(getKey(repository)); + String value = repository.getLocation().toExternalForm(); + node.put(KEY_URL, value); + value = repository.getDescription(); + if (value != null) + node.put(KEY_DESCRIPTION, value); + value = repository.getName(); + if (value != null) + node.put(KEY_NAME, value); + value = repository.getProvider(); + if (value != null) + node.put(KEY_PROVIDER, value); + value = repository.getType(); + if (value != null) + node.put(KEY_TYPE, value); + value = repository.getVersion(); + if (value != null) + node.put(KEY_VERSION, value); + saveRepositoryList(); + } + + /* + * Return a string key suitable based on the given repository which + * is suitable for use as a preference node name. + */ + private String getKey(IMetadataRepository repository) { + return repository.getLocation().toExternalForm().replace('/', '_'); + } + + public IMetadataRepository loadRepository(URL location, IProgressMonitor progress) { + // TODO do some thing with the monitor + IMetadataRepository result = getRepository(location); + if (result != null) + return result; + String[] suffixes = getAllSuffixes(); + if (progress == null) + progress = new NullProgressMonitor(); + progress.beginTask(NLS.bind(Messages.REPOMGR_ADDING_REPO, location.toExternalForm()), 1); + for (int i = 0; i < suffixes.length; i++) { + result = loadRepository(location, suffixes[i]); + if (result != null) { + addRepository(result); + progress.done(); + return result; + } + } + progress.done(); + return null; + } + + private String[] getAllSuffixes() { + IConfigurationElement[] elements = RegistryFactory.getRegistry().getConfigurationElementsFor(Activator.REPO_PROVIDER_XPT); + ArrayList result = new ArrayList(elements.length); + for (int i = 0; i < elements.length; i++) + if (elements[i].getName().equals("filter")) + result.add(elements[i].getAttribute("suffix")); + return (String[]) result.toArray(new String[result.size()]); + } + + // TODO This method really should not be here. There could be lots of different kinds of + // repositories and many different ways to create them. + // for now discriminate by the type of URL but this is bogus. + public IMetadataRepository createRepository(URL location, String name, String type) { + IMetadataRepository result = loadRepository(location, (IProgressMonitor) null); + if (result != null) + return result; + IExtension extension = RegistryFactory.getRegistry().getExtension(Activator.REPO_PROVIDER_XPT, type); + if (extension == null) + return null; + try { + IMetadataRepositoryFactory factory = (IMetadataRepositoryFactory) createExecutableExtension(extension, FACTORY); + if (factory == null) + return null; + result = factory.create(location, name, type); + if (result != null) + addRepository(result); + return result; + } catch (CoreException e) { + return null; + } + } + + /** + * Try to load a pre-existing repo at the given location + */ + // TODO this method should do some repo type discovery something like is done with + // the artifact repos. For now just discriminate on the type of URL + private IMetadataRepository loadRepository(URL location, String suffix) { + IExtension[] providers = findMatchingRepositoryExtensions(suffix); + // Loop over the candidates and return the first one that successfully loads + for (int i = 0; i < providers.length; i++) + try { + IMetadataRepositoryFactory factory = (IMetadataRepositoryFactory) createExecutableExtension(providers[i], FACTORY); + if (factory != null) + return factory.load(location); + } catch (CoreException e) { + log("Error loading repository extension: " + providers[i].getUniqueIdentifier(), e); //$NON-NLS-1$ + } + return null; + } + + public IMetadataRepository[] getKnownRepositories() { + return (IMetadataRepository[]) repositories.toArray(new IMetadataRepository[repositories.size()]); + } + + public IMetadataRepository getRepository(URL location) { + if (repositories == null) + restoreRepositories(); + for (Iterator iterator = repositories.iterator(); iterator.hasNext();) { + IMetadataRepository match = (IMetadataRepository) iterator.next(); + if (Utils.sameURL(match.getLocation(), location)) + return match; + } + return null; + } + + protected void log(String message, Throwable t) { + LogHelper.log(new Status(IStatus.ERROR, Activator.PI_METADATA_REPOSITORY, message, t)); + } + + public void removeRepository(IMetadataRepository toRemove) { + repositories.remove(toRemove); + // remove the repository from the preference store + try { + getPreferences().node(getKey(toRemove)).removeNode(); + saveRepositoryList(); + } catch (BackingStoreException e) { + log("Error saving preferences", e); //$NON-NLS-1$ + } + } + + public void restoreRepositories() { + //TODO we may want to have proxies on repo instead of the real repo object to limit what is activated. + URL path = null; + try { + AgentLocation location = (AgentLocation) ServiceHelper.getService(Activator.getContext(), AgentLocation.class.getName()); + if (location == null) + // TODO should do something here since we are failing to restore. + return; + path = location.getMetadataRepositoryURL(); + repositories.add(new MetadataCache(path)); + } catch (RepositoryCreationException e) { + log("Error while restoring repository " + path, e); + } + try { + String locationString = Activator.getContext().getProperty("eclipse.prov.metadataRepository"); + if (locationString != null) { + StringTokenizer tokenizer = new StringTokenizer(locationString, ","); + while (tokenizer.hasMoreTokens()) { + try { + path = new URL(tokenizer.nextToken()); + loadRepository(path, (IProgressMonitor) null); + } catch (MalformedURLException e) { + throw new RepositoryCreationException(e); + } + } + } + } catch (RepositoryCreationException e) { + log("Error while restoring repository " + path, e); + } + // load the list which is stored in the preferences + restoreFromPreferences(); + } + + /* + * Return the preference node which is the root for where we store the repository information. + */ + private Preferences getPreferences() { + return new ConfigurationScope().getNode(Activator.PI_METADATA_REPOSITORY).node(NODE_REPOSITORIES); + } + + /* + * Save the repository list in the file-system + */ + private void saveRepositoryList() { + try { + getPreferences().flush(); + } catch (BackingStoreException e) { + log("Error while saving repositories in preferences", e); + } + } + + private Object createExecutableExtension(IExtension extension, String element) throws CoreException { + IConfigurationElement[] elements = extension.getConfigurationElements(); + for (int i = 0; i < elements.length; i++) { + if (elements[i].getName().equals(element)) + return elements[i].createExecutableExtension("class"); + } + throw new CoreException(new Status(IStatus.ERROR, Activator.ID, "Malformed extension")); + } + + private IExtension[] findMatchingRepositoryExtensions(String suffix) { + IConfigurationElement[] elt = RegistryFactory.getRegistry().getConfigurationElementsFor(Activator.REPO_PROVIDER_XPT); + int count = 0; + for (int i = 0; i < elt.length; i++) { + if (elt[i].getName().equals("filter")) { + if (!elt[i].getAttribute("suffix").equals(suffix)) { + elt[i] = null; + } else { + count++; + } + } else { + elt[i] = null; + } + } + IExtension[] results = new IExtension[count]; + for (int i = 0; i < elt.length; i++) { + if (elt[i] != null) + results[--count] = elt[i].getDeclaringExtension(); + } + return results; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/SimpleMetadataRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/SimpleMetadataRepositoryFactory.java new file mode 100644 index 000000000..99a009631 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/SimpleMetadataRepositoryFactory.java @@ -0,0 +1,67 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import java.io.*; +import java.net.URL; +import org.eclipse.equinox.prov.core.repository.RepositoryCreationException; +import org.eclipse.equinox.prov.metadata.repository.IMetadataRepository; +import org.eclipse.equinox.prov.metadata.repository.IMetadataRepositoryFactory; + +public class SimpleMetadataRepositoryFactory implements IMetadataRepositoryFactory { + + public IMetadataRepository load(URL location) { + if (location == null) + return null; + try { + InputStream descriptorStream = new BufferedInputStream(URLMetadataRepository.getActualLocation(location).openStream()); + try { + IMetadataRepository result = MetadataRepositoryIO.read(descriptorStream); + if (result instanceof LocalMetadataRepository) + ((LocalMetadataRepository) result).initializeAfterLoad(location); + if (result instanceof URLMetadataRepository) + ((URLMetadataRepository) result).initializeAfterLoad(location); + return result; + } catch (RepositoryCreationException e) { + // TODO Auto-generated catch block + return null; + } finally { + if (descriptorStream != null) + descriptorStream.close(); + } + } catch (IOException e) { + //TODO: log and throw? + } + return null; + } + + public IMetadataRepository create(URL location, String name, String type) { + try { + if (location.getProtocol().equals("file")) //$NON-NLS-1$ + return new LocalMetadataRepository(location, name); + return new URLMetadataRepository(location, name); + } catch (RepositoryCreationException e) { + // if the exception has no cause then it was just a missing repo so we'll return null + return null; + } + } + + public void restore(AbstractMetadataRepository repository, URL location) { + AbstractMetadataRepository source = (AbstractMetadataRepository) load(location); + repository.description = source.description; + repository.name = source.name; + repository.properties = source.properties; + repository.provider = source.provider; + repository.type = source.type; + repository.version = source.version; + repository.units = source.units; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/URLMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/URLMetadataRepository.java new file mode 100644 index 000000000..61f5bc9a8 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/URLMetadataRepository.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) 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 + * Prashant Deva - Bug 194674 [prov] Provide write access to metadata repository + *******************************************************************************/ +package org.eclipse.equinox.internal.prov.metadata.repository; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Iterator; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.equinox.prov.core.repository.RepositoryCreationException; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.metadata.RequiredCapability; +import org.eclipse.equinox.prov.query.CompoundIterator; +import org.eclipse.osgi.service.resolver.VersionRange; +import org.eclipse.osgi.util.NLS; + +/** + * A metadata repository backed by an arbitrary URL. + */ +public class URLMetadataRepository extends AbstractMetadataRepository { + + static final private String REPOSITORY_TYPE = URLMetadataRepository.class.getName(); + static final private Integer REPOSITORY_VERSION = new Integer(1); + static final protected String CONTENT_FILENAME = "content.xml"; //$NON-NLS-1$ + + transient protected URL location; + transient protected URL content; + + public static URL getActualLocation(URL base) { + String spec = base.toExternalForm(); + if (spec.endsWith(CONTENT_FILENAME)) + return base; + if (spec.endsWith("/")) //$NON-NLS-1$ + spec += CONTENT_FILENAME; + else + spec += "/" + CONTENT_FILENAME; //$NON-NLS-1$ + try { + return new URL(spec); + } catch (MalformedURLException e) { + return null; + } + } + + protected URLMetadataRepository(String name, String type, String version) { + super(name, type, version); + } + + public URLMetadataRepository(URL location, String name) { + super(name == null ? (location != null ? location.toExternalForm() : "") : name, REPOSITORY_TYPE, REPOSITORY_VERSION.toString()); + this.location = location; + content = getActualLocation(location); + } + + protected boolean load() throws RepositoryCreationException { + return new SimpleMetadataRepositoryFactory().load(location) != null; + } + + public IInstallableUnit[] getInstallableUnits(IProgressMonitor monitor) { + if (monitor == null) + monitor = new NullProgressMonitor(); + monitor.beginTask(NLS.bind(Messages.REPO_LOADING, location.toExternalForm()), 5); + IInstallableUnit[] result = (IInstallableUnit[]) units.toArray(new IInstallableUnit[units.size()]); + monitor.done(); + return result; + } + + public URL getLocation() { + return location; + } + + protected URL getContentURL() { + return content; + } + + public Iterator getIterator(String id, VersionRange range, RequiredCapability[] requirements, boolean and) { + return new CompoundIterator(new Iterator[] {units.iterator()}, id, range, requirements, and); + } + + public IInstallableUnit[] query(String id, VersionRange range, RequiredCapability[] requirements, boolean and, IProgressMonitor progress) { + return CompoundIterator.asArray(new CompoundIterator(new Iterator[] {units.iterator()}, id, range, requirements, and), null); + } + + public Object getAdapter(Class adapter) { + if (adapter == URLMetadataRepository.class) + return this; + else + return super.getAdapter(adapter); + } + + // use this method to setup any transient fields etc after the object has been restored from a stream + public void initializeAfterLoad(URL location) { + this.location = location; + } +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/messages.properties b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/messages.properties new file mode 100644 index 000000000..fc369d7ab --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/internal/prov/metadata/repository/messages.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 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 +############################################################################### + +REPO_LOADING = Loading the repository {0} +REPOMGR_ADDING_REPO = Adding repository {0}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepository.java new file mode 100644 index 000000000..eb55c22fa --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepository.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import java.net.URL; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.prov.core.repository.IRepositoryInfo; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; +import org.eclipse.equinox.prov.query.IQueryable; + +/** + * A metadata repository stores information about a set of installable units + * <p> + * Clients may implement this interface. + * </p> + * TODO: This should be an abstract class so methods can be added in the future + * without breaking clients. + */ +public interface IMetadataRepository extends IRepositoryInfo, IQueryable { + /** + * Returns all installable units known to this repository. + * @param monitor TODO + * @return the installable units known to this repository + *TODO: Progress monitor? Is the repository expected to be local? + */ + public IInstallableUnit[] getInstallableUnits(IProgressMonitor monitor); + + /** + * Returns the URL of this repository. + * TODO: Should we use URL or URI? URL requires a protocol handler to be installed + * in Java. Can the URL have any protocol? Why are we exposing this at all? + * @return the URL of this repository. + */ + public URL getLocation(); +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepositoryFactory.java new file mode 100644 index 000000000..e5533326e --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepositoryFactory.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import java.net.URL; + +public interface IMetadataRepositoryFactory { + + public IMetadataRepository load(URL location); + + public IMetadataRepository create(URL location, String name, String type); +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepositoryManager.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepositoryManager.java new file mode 100644 index 000000000..98173d6f6 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IMetadataRepositoryManager.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 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.prov.metadata.repository; + +import java.net.URL; +import org.eclipse.core.runtime.IProgressMonitor; + +public interface IMetadataRepositoryManager { + /** + * Adds a new metadata repository to the set of known repositories. + * @param repository + */ + public void addRepository(IMetadataRepository repository); + + /** + * Adds a repository corresponding to the given URL. + * @param url The URL of the repository to add + * @param progress TODO + */ + public IMetadataRepository loadRepository(URL url, IProgressMonitor progress); + + /** + * Creates and returns a metadata repository of the given type at the given location. + * If a repository already exists at that location <code>null</code> is returned. + * @param location the location for the new repository + * @param name the name of the new repo + * @param type the kind of repository to create + * @return the discovered or created repository + */ + public IMetadataRepository createRepository(URL location, String name, String type); + + public IMetadataRepository[] getKnownRepositories(); + + public IMetadataRepository getRepository(URL repo); //TODO Should this throw an exception + + public void removeRepository(IMetadataRepository toRemove); +} diff --git a/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IWritableMetadataRepository.java b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IWritableMetadataRepository.java new file mode 100644 index 000000000..a22a6e804 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.metadata.repository/src/org/eclipse/equinox/prov/metadata/repository/IWritableMetadataRepository.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 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: + * Prashant Deva - Bug 194674 [prov] Provide write access to metadata repository + * IBM Corporation - ongoing development + *******************************************************************************/ +package org.eclipse.equinox.prov.metadata.repository; + +import org.eclipse.equinox.prov.core.repository.IWritableRepositoryInfo; +import org.eclipse.equinox.prov.metadata.IInstallableUnit; + +public interface IWritableMetadataRepository extends IMetadataRepository, IWritableRepositoryInfo { + + void addInstallableUnits(IInstallableUnit[] installableUnit); + + void removeInstallableUnits(IInstallableUnit[] installableUnit); + + /** + * Remove IUs from this repository. + */ + public void removeAll(); + +} |