diff options
author | John Arthorne | 2008-02-10 22:46:21 +0000 |
---|---|---|
committer | John Arthorne | 2008-02-10 22:46:21 +0000 |
commit | fa3dae8f4fb19d14dd04f4e00669a215cc6a13c8 (patch) | |
tree | cbc0dd1a91f0f6079e9b8397e6e169c79490e40e /bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional | |
parent | e615dae2244101e844d0851f3d9c8c754ffaffe0 (diff) | |
download | rt.equinox.p2-fa3dae8f4fb19d14dd04f4e00669a215cc6a13c8.tar.gz rt.equinox.p2-fa3dae8f4fb19d14dd04f4e00669a215cc6a13c8.tar.xz rt.equinox.p2-fa3dae8f4fb19d14dd04f4e00669a215cc6a13c8.zip |
Bug 218451 [prov] Rename API packages to provisional API
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional')
13 files changed, 1191 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/ArtifactDescriptor.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/ArtifactDescriptor.java new file mode 100644 index 000000000..2de893a4f --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/ArtifactDescriptor.java @@ -0,0 +1,178 @@ +/******************************************************************************* + * 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.provisional.p2.artifact.repository; + +import java.util.Arrays; +import java.util.Map; +import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStepDescriptor; +import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey; + +/** + * This represents information about a given artifact stored on a particular byte server. + */ +public class ArtifactDescriptor implements IArtifactDescriptor { + + private static final ProcessingStepDescriptor[] EMPTY_STEPS = new ProcessingStepDescriptor[0]; + + protected IArtifactKey key; // The key associated with this artifact + + // The list of post processing steps that must be applied one the artifact once it + // has been downloaded (e.g, unpack, then md5 checksum, then...) + protected ProcessingStepDescriptor[] processingSteps = EMPTY_STEPS; + + protected Map properties = new OrderedProperties(); + protected Map repositoryProperties = new OrderedProperties(); + + protected transient IArtifactRepository repository; + + // QUESTION: Do we need any description or user readable name + + public ArtifactDescriptor(IArtifactDescriptor base) { + super(); + key = base.getArtifactKey(); + processingSteps = base.getProcessingSteps(); + properties.putAll(base.getProperties()); + repository = base.getRepository(); + // TODO this property is hardcoded for the blob store. + // setProperty("artifact.uuid", base.getProperty("artifact.uuid")); + } + + public ArtifactDescriptor(ArtifactDescriptor base) { + super(); + key = base.key; + processingSteps = base.processingSteps; + properties = base.properties; + repository = base.repository; + } + + public ArtifactDescriptor(IArtifactKey key) { + super(); + this.key = key; + } + + public IArtifactKey getArtifactKey() { + return key; + } + + public String getProperty(String propertyKey) { + return (String) properties.get(propertyKey); + } + + public void setProperty(String key, String value) { + if (value == null) + properties.remove(key); + else + properties.put(key, value); + } + + public void addProperties(Map additionalProperties) { + properties.putAll(additionalProperties); + } + + /** + * Returns a read-only collection of the properties of the artifact descriptor. + * @return the properties of this artifact descriptor. + */ + public Map getProperties() { + return OrderedProperties.unmodifiableProperties(properties); + } + + public String getRepositoryProperty(String propertyKey) { + return (String) repositoryProperties.get(propertyKey); + } + + public void setRepositoryProperty(String key, String value) { + if (value == null) + repositoryProperties.remove(key); + else + repositoryProperties.put(key, value); + } + + public void addRepositoryProperties(Map additionalProperties) { + repositoryProperties.putAll(additionalProperties); + } + + /** + * Returns a read-only collection of the repository properties of the artifact descriptor. + * @return the repository properties of this artifact descriptor. + */ + public Map getRepositoryProperties() { + return OrderedProperties.unmodifiableProperties(repositoryProperties); + } + + public ProcessingStepDescriptor[] getProcessingSteps() { + return processingSteps; + } + + public void setProcessingSteps(ProcessingStepDescriptor[] value) { + processingSteps = value == null ? EMPTY_STEPS : value; + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ArtifactDescriptor other = (ArtifactDescriptor) obj; + if (key == null) { + if (other.key != null) + return false; + } else if (!key.equals(other.key)) + return false; + if (!Arrays.equals(processingSteps, other.processingSteps)) + return false; + if (properties == null) { + if (other.properties != null) + return false; + } else if (!properties.equals(other.properties)) + return false; + return true; + } + + private int hashCode(Object[] array) { + int prime = 31; + if (array == null) + return 0; + int result = 1; + for (int index = 0; index < array.length; index++) { + result = prime * result + (array[index] == null ? 0 : array[index].hashCode()); + } + return result; + } + + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((key == null) ? 0 : key.hashCode()); + result = prime * result + hashCode(processingSteps); + result = prime * result + ((properties == null) ? 0 : properties.hashCode()); + return result; + } + + public IArtifactRepository getRepository() { + return repository; + } + + public void setRepository(IArtifactRepository value) { + repository = value; + } + + public String toString() { + String format = getProperty(IArtifactDescriptor.FORMAT); + if (format == null) + return "canonical: " + key.toString(); //$NON-NLS-1$ + return format + ": " + key.toString(); //$NON-NLS-1$ + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactDescriptor.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactDescriptor.java new file mode 100644 index 000000000..f6c1b9167 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactDescriptor.java @@ -0,0 +1,60 @@ +/******************************************************************************* + * 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.provisional.p2.artifact.repository; + +import java.util.Map; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStepDescriptor; +import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey; + +public interface IArtifactDescriptor { + + public static final String DOWNLOAD_SIZE = "download.size"; //$NON-NLS-1$ + public static final String ARTIFACT_SIZE = "artifact.size"; //$NON-NLS-1$ + public static final String DOWNLOAD_MD5 = "download.md5"; //$NON-NLS-1$ + public static final String ARTIFACT_MD5 = "artifact.md5"; //$NON-NLS-1$ + public static final String FORMAT = "format"; //$NON-NLS-1$ + + /** + * Return the key for the artifact described by this descriptor. + * @return the key associated with this descriptor + */ + public abstract IArtifactKey getArtifactKey(); + + /** + * Return the value of the given property in this descriptor <code>null</code> + * is returned if no such property exists + * @param key the property key to look for + * @return the value of the given property or <code>null</code> + */ + public abstract String getProperty(String key); + + /** + * Returns a read-only collection of the properties of the artifact descriptor. + * @return the properties of this artifact descriptor. + */ + public Map getProperties(); + + /** + * Return the list of processing steps associated with this descriptor. + * An empty set of steps implies that this descriptor describes a complete + * copy of the artifact in its native form. + * @return the list of processing steps for this descriptor + */ + public abstract ProcessingStepDescriptor[] getProcessingSteps(); + + /** + * Return the artifact repository that holds the artifact described by this descriptor. + * <code>null</code> is returned if this descriptor is not held in a repository. + * + * @return the repository holding this artifact or <code>null</code> if none. + */ + public abstract IArtifactRepository getRepository(); +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepository.java new file mode 100644 index 000000000..f3560cda4 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepository.java @@ -0,0 +1,114 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.artifact.repository; + +import java.io.OutputStream; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +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.spi.p2.artifact.repository.AbstractArtifactRepository; + +/** + * A repository containing artifacts. + * <p> + * This interface is not intended to be implemented by clients. Artifact repository + * implementations must subclass {@link AbstractArtifactRepository} rather than + * implementing this interface directly. + * </p> + */ +public interface IArtifactRepository extends IRepository { + /** + * Add the given descriptor to the set of descriptors in this repository. This is + * a relatively low-level operation that should be used only when the actual related + * content is in this repository and the given descriptor accurately describes + * that content. + * @param descriptor the descriptor to add. + */ + public void addDescriptor(IArtifactDescriptor descriptor); + + /** + * Add the given arifact descriptors to this repository + * @param descriptors the artifact descriptors to add + */ + public void addDescriptors(IArtifactDescriptor[] descriptors); + + /** + * Returns true if this repository contains the given descriptor. + * @param descriptor the descriptor to query + * @return true if the given descriptor is already in this repository + */ + public boolean contains(IArtifactDescriptor descriptor); + + /** + * Returns true if this repository contains the given artifact key. + * @param key the key to query + * @return true if the given key is already in this repository + */ + public boolean contains(IArtifactKey key); + + /** + * Fill the given stream with the described artifact. Sets status accordingly. + */ + public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor); + + /** + * Return the set of artifact descriptors describing the ways that this repository + * can supply the artifact associated with the given artifact key + * @param key the artifact key to lookup + * @return the descriptors associated with the given key + */ + public IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key); + + /** + * Returns the list of artifact keys managed by this repository + * @return list of artifact keys + */ + public IArtifactKey[] getArtifactKeys(); + + /** + * Executes the given artifact requests on this byte server. + * @param requests The artifact requests + * @param monitor + * @return a status object that is <code>OK</code> if requests were + * processed successfully. Otherwise, a status indicating information, + * warnings, or errors that occurred while executing the artifact requests + */ + public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor); + + /** + * Open an output stream to which a client can write the data for the given + * artifact descriptor. + * @param descriptor the descriptor describing the artifact data to be written to the + * resultant stream + * @return the stream to which the artifact content can be written. The returned output + * stream may implement <code>IStateful</code>. + */ + public OutputStream getOutputStream(IArtifactDescriptor descriptor); + + /** + * Remove the all keys, descriptors, and contents from this repository. + */ + public void removeAll(); + + /** + * Remove the given descriptor and its corresponding content in this repository. + * @param descriptor the descriptor to remove. + */ + public void removeDescriptor(IArtifactDescriptor descriptor); + + /** + * Remove the given key and all related content and descriptors from this repository. + * @param key the key to remove. + */ + public void removeDescriptor(IArtifactKey key); + +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepositoryManager.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepositoryManager.java new file mode 100644 index 000000000..f63b327f9 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRepositoryManager.java @@ -0,0 +1,186 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.artifact.repository; + +import java.net.URL; +import java.util.Properties; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +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; + +public interface IArtifactRepositoryManager { + /** + * Constant used to indicate that all repositories are of interest. + */ + public static final int REPOSITORIES_ALL = 0; + + /** + * Constant used to indicate that system repositories are of interest. + * @see IRepository#PROP_SYSTEM + * @see #getKnownRepositories(int) + */ + public static final int REPOSITORIES_SYSTEM = 1 << 0; + + /** + * Constant used to indicate that non-system repositories are of interest + * @see IRepository#PROP_SYSTEM + * @see #getKnownRepositories(int) + */ + public static final int REPOSITORIES_NON_SYSTEM = 1 << 1; + + /** + * Constant used to indicate that local repositories are of interest. + * @see #getKnownRepositories(int) + */ + public static final int REPOSITORIES_LOCAL = 1 << 2; + + /** + * Property key used to query a repository's name without loading the repository first. + */ + public static final String PROP_NAME = "name"; //$NON-NLS-1$ + /** + * Property key used to query a repository's description without loading the repository first. + */ + public static final String PROP_DESCRIPTION = "description"; //$NON-NLS-1$ + + /** + * Repository type for a simple repository based on a URL or local file system location. + */ + public static final String TYPE_SIMPLE_REPOSITORY = "org.eclipse.equinox.p2.artifact.repository.simpleRepository"; //$NON-NLS-1$ + + public static final IArtifactRequest[] NO_ARTIFACT_REQUEST = new IArtifactRequest[0]; + + /** + * Adds a repository to the list of artifact repositories tracked by the repository + * manager. + * + * @param location The location of the artifact repository to add + */ + public void addRepository(URL location); + + /** + * Return a new request to download the given artifact and store it at the given destination. + * @param key the artifact to download + * @param destination the destination where the artifact will be stored + * @return the newly created request object + */ + public IArtifactRequest createDownloadRequest(IArtifactKey key, IPath destination); + + /** + * Return a new request to mirror the given artifact into the destination repository. + * @param key the artifact to mirror + * @param destination the destination where the artifact will be mirrored + * @return the newly created request object + */ + public IArtifactRequest createMirrorRequest(IArtifactKey key, IArtifactRepository destination); + + /** + * Return a new request to mirror the given artifact into the destination repository. + * @param key the artifact to mirror + * @param destination the destination where the artifact will be mirrored + * @param destinationDescriptorProperties additional properties for use in creating the repositor's ArtifactDescriptor + * @param destinationRepositoryProperties additional repository specific properties for use in creating the repositor's ArtifactDescriptor + * @return the newly created request object + */ + public IArtifactRequest createMirrorRequest(IArtifactKey key, IArtifactRepository destination, Properties destinationDescriptorProperties, Properties destinationRepositoryProperties); + + /** + * Creates and returns a new empty artifact repository of the given type at + * the given location. + * + * @param location the location for the new repository + * @param name the name of the new repository + * @param type the kind of repository to create + * @return the newly created repository + * @throws ProvisionException if the repository could not be created. Reasons include: + * <ul> + * <li>The repository type is unknown.</li> + * <li>There was an error writing to the given repository location.</li> + * <li>A repository already exists at that location.</li> + * </ul> + */ + public IArtifactRepository createRepository(URL location, String name, String type) throws ProvisionException; + + /** + * Returns the artifact repository locations known to the repository manager. + * <p> + * Note that the repository manager does not guarantee that a valid repository + * exists at any of the returned locations at any particular moment in time. + * A subsequent attempt to load a repository at any of the given locations may + * or may not succeed. + * + * @param flags an integer bit-mask indicating which repositories should be + * returned. <code>REPOSITORIES_ALL</code> can be used as the mask when + * all repositories should be returned. + * + * @return the locations of the repositories managed by this repository manager. + * + * @see #REPOSITORIES_ALL + * @see #REPOSITORIES_SYSTEM + * @see #REPOSITORIES_NON_SYSTEM + * @see #REPOSITORIES_LOCAL + */ + public URL[] getKnownRepositories(int flags); + + /** + * Returns the property associated with the repository at the given URL, + * without loading the repository. + * <p> + * Note that some properties for a repository can only be + * determined when that repository is loaded. This method will return <code>null</code> + * for such properties. Only values for the properties that are already + * known by a repository manager will be returned. + * <p> + * If a client wishes to retrieve a property value from a repository + * regardless of the cost of retrieving it, the client should load the + * repository and then retrieve the property from the repository itself. + * + * @param location the URL of the repository in question + * @param key the String key of the property desired + * @return the value of the property, or <code>null</code> if the repository + * does not exist, the value does not exist, or the property value + * could not be determined without loading the repository. + * + * @see #loadRepository(URL, IProgressMonitor) + * @see IRepository#getProperties() + * + */ + public String getRepositoryProperty(URL location, String key); + + /** + * Loads the repository at the given location. The location is expected to contain + * data that describes a valid artifact repository of a known type. If this manager + * already knows a repository at the given location then that repository is returned. + * + * @param location the location in which to look for a repository description + * @param monitor a progress monitor, or <code>null</code> if progress + * reporting is not desired + * @return a repository object for the given location + * @throws ProvisionException if the repository could not be created. Reasons include: + * <ul> + * <li>There is no existing repository at that location.</li> + * <li>The repository at that location could not be read.</li> + * </ul> + */ + public IArtifactRepository loadRepository(URL location, IProgressMonitor monitor) throws ProvisionException; + + /** + * Remove the given repository from this manager. Do nothing if the repository + * is not currently managed. + * + * @param location the location of the repository to remove + * @return <code>true</code> if a repository was removed, and + * <code>false</code> otherwise. + */ + public boolean removeRepository(URL location); +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRequest.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRequest.java new file mode 100644 index 000000000..16c039e9f --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IArtifactRequest.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * 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.provisional.p2.artifact.repository; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRequest; +import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey; + +/** + * This interface is not intended to be implemented by clients + */ +public interface IArtifactRequest { + + public IArtifactKey getArtifactKey(); + + /** + * Returns the result of the previous call to {@link ArtifactRequest#perform(IProgressMonitor)}, + * or <code>null</code> if perform has never been called. + * + * @return The result of the previous perform call. + */ + public IStatus getResult(); + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IFileArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IFileArtifactRepository.java new file mode 100644 index 000000000..c69754679 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IFileArtifactRepository.java @@ -0,0 +1,32 @@ +/******************************************************************************* + * Copyright (c) 2005, 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.provisional.p2.artifact.repository; + +import java.io.File; +import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey; + +public interface IFileArtifactRepository extends IArtifactRepository { + /** + * Return the location of the full local file corresponding to the given + * artifact key to the given key, or <code>null</code> if not available. + * + * @return the location of the requested artifact or<code>null</code> if not available + */ + public File getArtifactFile(IArtifactKey key); + + /** + * Return the location of the local file corresponding to the given + * artifact descriptor, or <code>null</code> if not available. + * + * @return the location of the requested descriptor or<code>null</code> if not available + */ + public File getArtifactFile(IArtifactDescriptor descriptor); +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IStateful.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IStateful.java new file mode 100644 index 000000000..5d8d255c3 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/IStateful.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2007 compeople AG 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: + * compeople AG (Stefan Liebig) - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.artifact.repository; + +import org.eclipse.core.runtime.IStatus; + +/** + * Implementing <code>IStateful</code> adds the ability to store state information. + */ +public interface IStateful { + + void setStatus(IStatus status); + + public IStatus getStatus(); + +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStep.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStep.java new file mode 100644 index 000000000..a9634f845 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStep.java @@ -0,0 +1,128 @@ +/******************************************************************************* +* Copyright (c) 2007 compeople AG 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: +* compeople AG (Stefan Liebig) - initial API and implementation +* IBM Corporation - continuing development +*******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.artifact.repository.Activator; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IStateful; + +/** + * ProcessingSteps process the data written to them and pass the resultant data on + * to a configured destination stream. Steps may monitor (e.g., count) the data, compute information + * about the data (e.g., checksum or hash) or transform the data (e.g., unpack200). + */ +public abstract class ProcessingStep extends OutputStream implements IStateful { + //TODO It's generally not good to expose fields as API. It raises difficulties about + //when the subclass should be writing the fields, when the fields will have + //meaningful values, etc. It's generally better to pass values as parameters + //in a hook method rather than letting the subclass access this state directly. + protected OutputStream destination; + protected IProgressMonitor monitor; + protected IStatus status = Status.OK_STATUS; + + protected ProcessingStep() { + super(); + } + + /** + * Initialize this processing step according to the information in the given + * descriptor and context. After initialization, this step is ready for linking + * with other steps or output streams + * @param descriptor description of the step + * @param context the context in which the step is being used + */ + public void initialize(ProcessingStepDescriptor descriptor, IArtifactDescriptor context) { + } + + /** + * Link this step with the given output stream and configure the step to use the given + * progress monitor. After linking the step is ready to have data written to it. + * @param destination the stream into which to write the processed data + * @param monitor the progress monitor to use for reporting activity + */ + public void link(OutputStream destination, IProgressMonitor monitor) { + this.destination = destination; + this.monitor = monitor; + } + + /** + * Process the given byte and pass the result on to the configured destination stream + * @param b the byte being written + */ + public void write(int b) throws IOException { + } + + /** + * Flush any unwritten data from this stream. + */ + public void flush() throws IOException { + super.flush(); + if (destination != null) + destination.flush(); + } + + /** + * Close this stream and, if the configured destination is a ProcessingStep, + * close it as well. Typically a chain of steps terminates in a conventional + * output stream. Implementors of this method should ensure they set the + * status of the step. + */ + public void close() throws IOException { + super.close(); + if (destination instanceof ProcessingStep) + destination.close(); + monitor = null; + } + + public IStatus getStatus() { + return status; + } + + public void setStatus(IStatus status) { + this.status = status; + } + + /** + * Return the status of this step. The status will be <code>null</code> if the + * step has not yet executed. If the step has executed the returned status + * indicates the success or failure of the step. + * @param deep whether or not to aggregate the status of any linked steps + * @return the requested status + */ + public IStatus getStatus(boolean deep) { + if (!deep) + return getStatus(); + ArrayList list = new ArrayList(); + int severity = collectStatus(list); + if (severity == IStatus.OK) + return Status.OK_STATUS; + IStatus[] result = (IStatus[]) list.toArray(new IStatus[list.size()]); + return new MultiStatus(Activator.ID, severity, result, "Result of processing steps", null); + } + + private int collectStatus(ArrayList list) { + list.add(getStatus()); + if (!(destination instanceof ProcessingStep)) + return getStatus().getSeverity(); + int result = ((ProcessingStep) destination).collectStatus(list); + // TODO greater than test here is a little brittle but it is very unlikely that we will add + // a new status severity. + if (getStatus().getSeverity() > result) + return getStatus().getSeverity(); + return result; + + } +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStepDescriptor.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStepDescriptor.java new file mode 100644 index 000000000..4320fb00b --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStepDescriptor.java @@ -0,0 +1,86 @@ +/******************************************************************************* +* Copyright (c) 2007 compeople AG 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: +* compeople AG (Stefan Liebig) - initial API and implementation +*******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing; + +/** + * The description of a processor step. + */ +public class ProcessingStepDescriptor { + + private final String processorId; //the operation to be applied (e.g: unpack, md5, signature verification, etc.) + private final String data; //data requested for the processing (eg. expected checksum) + private final boolean required; //whether the step is optional or not + + /** + * Create a processing step description. + * + * @param processorId + * @param data + * @param required + */ + public ProcessingStepDescriptor(String processorId, String data, boolean required) { + super(); + this.processorId = processorId; + this.data = data; + this.required = required; + } + + public String getProcessorId() { + return processorId; + } + + public String getData() { + return data; + } + + public boolean isRequired() { + return required; + } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((data == null) ? 0 : data.hashCode()); + result = prime * result + ((processorId == null) ? 0 : processorId.hashCode()); + result = prime * result + (required ? 1231 : 1237); + return result; + } + + /* (non-Javadoc) + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (!(obj instanceof ProcessingStepDescriptor)) + return false; + final ProcessingStepDescriptor other = (ProcessingStepDescriptor) obj; + if (data == null) { + if (other.data != null) + return false; + } else if (!data.equals(other.data)) + return false; + if (processorId == null) { + if (other.processorId != null) + return false; + } else if (!processorId.equals(other.processorId)) + return false; + if (required != other.required) + return false; + return true; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStepHandler.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStepHandler.java new file mode 100644 index 000000000..bdf0a41ff --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/p2/artifact/repository/processing/ProcessingStepHandler.java @@ -0,0 +1,106 @@ +/******************************************************************************* +* Copyright (c) 2007, 2008 compeople AG 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: +* compeople AG (Stefan Liebig) - initial API and implementation +* IBM - continuing development +*******************************************************************************/ +package org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing; + +import java.io.OutputStream; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.artifact.repository.Activator; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactDescriptor; + +/** + * Creates processing step instances from extensions and executes them. + */ +public class ProcessingStepHandler { + + private static final String PROCESSING_STEPS_EXTENSION_ID = "org.eclipse.equinox.p2.artifact.repository.processingSteps"; //$NON-NLS-1$ + + public static IStatus checkStatus(OutputStream output) { + if (!(output instanceof ProcessingStep)) + return Status.OK_STATUS; + return ((ProcessingStep) output).getStatus(true); + } + + /** + * Check to see that we have processors for all the steps in the given descriptor + * @param descriptor the descriptor to check + * @return whether or not processors for all the descriptor's steps are installed + */ + public static boolean canProcess(IArtifactDescriptor descriptor) { + IExtensionRegistry registry = RegistryFactory.getRegistry(); + IExtensionPoint point = registry.getExtensionPoint(PROCESSING_STEPS_EXTENSION_ID); + if (point == null) + return false; + ProcessingStepDescriptor[] steps = descriptor.getProcessingSteps(); + for (int i = 0; i < steps.length; i++) { + if (point.getExtension(steps[i].getProcessorId()) == null) + return false; + } + return true; + } + + public ProcessingStep[] create(ProcessingStepDescriptor[] descriptors, IArtifactDescriptor context) { + ProcessingStep[] result = new ProcessingStep[descriptors.length]; + for (int i = 0; i < descriptors.length; i++) + result[i] = create(descriptors[i], context); + return result; + } + + public ProcessingStep create(ProcessingStepDescriptor descriptor, IArtifactDescriptor context) { + IExtensionRegistry registry = RegistryFactory.getRegistry(); + IExtension extension = registry.getExtension(PROCESSING_STEPS_EXTENSION_ID, descriptor.getProcessorId()); + Exception error; + if (extension != null) { + IConfigurationElement[] config = extension.getConfigurationElements(); + try { + Object object = config[0].createExecutableExtension("class"); //$NON-NLS-1$ + ProcessingStep step = (ProcessingStep) object; + step.initialize(descriptor, context); + return step; + } catch (Exception e) { + error = e; + } + } else + error = new ProcessingStepHandlerException("Could not get extension " + PROCESSING_STEPS_EXTENSION_ID + " for desriptor id " + descriptor.getProcessorId()); + + int severity = descriptor.isRequired() ? IStatus.ERROR : IStatus.INFO; + ProcessingStep result = new EmptyProcessingStep(); + result.setStatus(new Status(severity, Activator.ID, "Could not instantiate step:" + descriptor.getProcessorId(), error)); + return result; + } + + public OutputStream createAndLink(ProcessingStepDescriptor[] descriptors, IArtifactDescriptor context, OutputStream output, IProgressMonitor monitor) { + if (descriptors == null) + return output; + ProcessingStep[] steps = create(descriptors, context); + return link(steps, output, monitor); + } + + public OutputStream link(ProcessingStep[] steps, OutputStream output, IProgressMonitor monitor) { + OutputStream previous = output; + for (int i = steps.length - 1; i >= 0; i--) { + ProcessingStep step = steps[i]; + step.link(previous, monitor); + previous = step; + } + return previous; + } + + protected static final class EmptyProcessingStep extends ProcessingStep { + // Just to hold the status + } + + protected static final class ProcessingStepHandlerException extends Exception { + public ProcessingStepHandlerException(String message) { + super(message); + } + } +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/AbstractArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/AbstractArtifactRepository.java new file mode 100644 index 000000000..832c0a301 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/AbstractArtifactRepository.java @@ -0,0 +1,87 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository; + +import java.io.OutputStream; +import java.net.URL; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.equinox.internal.p2.core.helpers.URLUtil; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.*; +import org.eclipse.equinox.internal.provisional.p2.metadata.IArtifactKey; +import org.eclipse.equinox.internal.provisional.spi.p2.core.repository.AbstractRepository; + +public abstract class AbstractArtifactRepository extends AbstractRepository implements IArtifactRepository { + + protected AbstractArtifactRepository(String name, String type, String version, URL location, String description, String provider) { + super(name, type, version, location, description, provider); + } + + public abstract boolean contains(IArtifactDescriptor descriptor); + + public abstract boolean contains(IArtifactKey key); + + public abstract IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor); + + public abstract IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key); + + public abstract IArtifactKey[] getArtifactKeys(); + + public abstract IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor); + + public OutputStream getOutputStream(IArtifactDescriptor descriptor) { + if (!isModifiable()) + throw new UnsupportedOperationException("Repository not modifiable"); + return null; + } + + public void addDescriptor(IArtifactDescriptor descriptor) { + if (!isModifiable()) + throw new UnsupportedOperationException("Repository not modifiable"); + } + + public void addDescriptors(IArtifactDescriptor[] descriptors) { + if (!isModifiable()) + throw new UnsupportedOperationException("Repository not modifiable"); + } + + public void removeDescriptor(IArtifactDescriptor descriptor) { + if (!isModifiable()) + throw new UnsupportedOperationException("Repository not modifiable"); + } + + public void removeDescriptor(IArtifactKey key) { + if (!isModifiable()) + throw new UnsupportedOperationException("Repository not modifiable"); + } + + public void removeAll() { + if (!isModifiable()) + throw new UnsupportedOperationException("Repository not modifiable"); + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (!(o instanceof AbstractArtifactRepository)) { + return false; + } + if (URLUtil.sameURL(getLocation(), ((AbstractArtifactRepository) o).getLocation())) + return true; + return false; + } + + public int hashCode() { + return (this.getLocation().toString().hashCode()) * 87; + } + +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/IArtifactRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/IArtifactRepositoryFactory.java new file mode 100644 index 000000000..21e4f8b48 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/IArtifactRepositoryFactory.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository; + +import java.net.URL; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository; +import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException; + +public interface IArtifactRepositoryFactory { + + /** + * Creates and returns a new empty artifact repository of the given type at + * the given location. + * + * @param location the location for the new repository + * @param name the name of the new repository + * @param type the kind of repository to create + * @return the newly created repository + * @throws ProvisionException if the repository could not be created. Reasons include: + * <ul> + * <li>The repository type is unknown.</li> + * <li>There was an error writing to the given repository location.</li> + * <li>A repository already exists at that location.</li> + * </ul> + */ + public IArtifactRepository create(URL location, String name, String type) throws ProvisionException; + + /** + * Loads the repository at the given location. The location is expected to contain + * data that describes a valid artifact repository of a known type. If this manager + * already knows a repository at the given location then that repository is returned. + * + * @param location the location in which to look for a repository description + * @param monitor a progress monitor, or <code>null</code> if progress + * reporting is not desired + * @return a repository object for the given location + * @throws ProvisionException if the repository could not be created. Reasons include: + * <ul> + * <li>There is no existing repository at that location.</li> + * <li>The repository at that location could not be read.</li> + * </ul> + */ + public IArtifactRepository load(URL location, IProgressMonitor monitor) throws ProvisionException; +} diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/SimpleArtifactRepositoryFactory.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/SimpleArtifactRepositoryFactory.java new file mode 100644 index 000000000..ca4279e53 --- /dev/null +++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/provisional/spi/p2/artifact/repository/SimpleArtifactRepositoryFactory.java @@ -0,0 +1,104 @@ +/******************************************************************************* + * Copyright (c) 2007, 2008 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.equinox.internal.provisional.spi.p2.artifact.repository; + +import java.io.*; +import java.net.URL; +import java.util.jar.JarEntry; +import java.util.jar.JarInputStream; +import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.artifact.repository.*; +import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository; +import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepositoryIO; +import org.eclipse.equinox.internal.p2.core.helpers.Tracing; +import org.eclipse.equinox.internal.provisional.p2.artifact.repository.IArtifactRepository; +import org.eclipse.equinox.internal.provisional.p2.core.ProvisionException; +import org.eclipse.osgi.util.NLS; + +public class SimpleArtifactRepositoryFactory implements IArtifactRepositoryFactory { + + public IArtifactRepository load(URL location, IProgressMonitor monitor) throws ProvisionException { + long time = 0; + final String debugMsg = "Restoring artifact repository "; //$NON-NLS-1$ + if (Tracing.DEBUG_METADATA_PARSING) { + Tracing.debug(debugMsg + location); + time = -System.currentTimeMillis(); + } + File temp = null; + try { + SubMonitor sub = SubMonitor.convert(monitor, 300); + // TODO This temporary file stuff is not very elegant. + OutputStream artifacts = null; + temp = File.createTempFile("artifacts", ".xml"); //$NON-NLS-1$ //$NON-NLS-2$ + // try with compressed + boolean compress = true; + try { + artifacts = new BufferedOutputStream(new FileOutputStream(temp)); + IStatus status = getTransport().download(SimpleArtifactRepository.getActualLocation(location, compress).toExternalForm(), artifacts, sub.newChild(100)); + if (!status.isOK()) { + // retry uncompressed + compress = false; + status = getTransport().download(SimpleArtifactRepository.getActualLocation(location, compress).toExternalForm(), artifacts, sub.newChild(100)); + if (!status.isOK()) + throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, status.getMessage(), null)); + } + } finally { + if (artifacts != null) + artifacts.close(); + } + InputStream descriptorStream = null; + try { + descriptorStream = new BufferedInputStream(new FileInputStream(temp)); + if (compress) { + URL actualFile = SimpleArtifactRepository.getActualLocation(location, false); + JarInputStream jInStream = new JarInputStream(descriptorStream); + JarEntry jarEntry = jInStream.getNextJarEntry(); + String filename = new Path(actualFile.getFile()).lastSegment(); + while (jarEntry != null && !(filename.equals(jarEntry.getName()))) { + jarEntry = jInStream.getNextJarEntry(); + } + if (jarEntry == null) { + throw new FileNotFoundException("Repository not found in " + actualFile.getPath()); //$NON-NLS-1$ + } + descriptorStream = jInStream; + } + SimpleArtifactRepositoryIO io = new SimpleArtifactRepositoryIO(); + SimpleArtifactRepository result = (SimpleArtifactRepository) io.read(temp.toURL(), descriptorStream, sub.newChild(100)); + result.initializeAfterLoad(location); + if (Tracing.DEBUG_METADATA_PARSING) { + time += System.currentTimeMillis(); + Tracing.debug(debugMsg + "time (ms): " + time); //$NON-NLS-1$ + } + return result; + } finally { + if (descriptorStream != null) + descriptorStream.close(); + } + } catch (FileNotFoundException e) { + String msg = NLS.bind(Messages.io_failedRead, location); + throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_NOT_FOUND, msg, e)); + } catch (IOException e) { + String msg = NLS.bind(Messages.io_failedRead, location); + throw new ProvisionException(new Status(IStatus.ERROR, Activator.ID, ProvisionException.REPOSITORY_FAILED_READ, msg, e)); + } finally { + if (temp != null && !temp.delete()) + temp.deleteOnExit(); + } + } + + public IArtifactRepository create(URL location, String name, String type) { + return new SimpleArtifactRepository(name, location); + } + + private Transport getTransport() { + return ECFTransport.getInstance(); + } +} |