| /******************************************************************************* |
| * Copyright (c) 2008, 2017 Code 9 and others. |
| * |
| * This |
| * program and the accompanying materials are made available under the terms of |
| * the Eclipse Public License 2.0 which accompanies this distribution, and is |
| * available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Code 9 - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.equinox.p2.tests.publisher; |
| |
| import java.io.*; |
| import java.net.URI; |
| import java.util.*; |
| import java.util.zip.ZipInputStream; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.equinox.internal.p2.artifact.repository.ArtifactRequest; |
| import org.eclipse.equinox.internal.p2.artifact.repository.Messages; |
| import org.eclipse.equinox.internal.p2.core.helpers.OrderedProperties; |
| import org.eclipse.equinox.internal.p2.metadata.ArtifactKey; |
| import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStepHandler; |
| import org.eclipse.equinox.internal.provisional.p2.repository.IStateful; |
| import org.eclipse.equinox.p2.core.IProvisioningAgent; |
| import org.eclipse.equinox.p2.core.ProvisionException; |
| import org.eclipse.equinox.p2.metadata.IArtifactKey; |
| import org.eclipse.equinox.p2.metadata.Version; |
| import org.eclipse.equinox.p2.query.*; |
| import org.eclipse.equinox.p2.repository.IRunnableWithProgress; |
| import org.eclipse.equinox.p2.repository.artifact.*; |
| import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor; |
| import org.eclipse.equinox.p2.tests.TestActivator; |
| import org.eclipse.osgi.util.NLS; |
| |
| public class TestArtifactRepository implements IArtifactRepository { |
| private static String provider = null; |
| private HashMap<IArtifactDescriptor, byte[]> repo; |
| private String name; |
| private String description; |
| private String version = "1.0.0"; //$NON-NLS-1$ |
| protected Map<String, String> properties = new OrderedProperties(); |
| |
| public class ArtifactOutputStream extends OutputStream implements IStateful { |
| private boolean closed; |
| private long count = 0; |
| private IArtifactDescriptor descriptor; |
| private OutputStream destination; |
| private IStatus status = Status.OK_STATUS; |
| private OutputStream firstLink; |
| |
| public ArtifactOutputStream(OutputStream os, IArtifactDescriptor descriptor) { |
| this.destination = os; |
| this.descriptor = descriptor; |
| } |
| |
| @Override |
| public void close() throws IOException { |
| if (closed) |
| return; |
| try { |
| destination.close(); |
| closed = true; |
| } catch (IOException e) { |
| if (getStatus().isOK()) |
| throw e; |
| // if the stream has already been e.g. canceled, we can return - |
| // the status is already set correctly |
| return; |
| } |
| // if the steps ran ok and there was actual content, write the |
| // artifact descriptor |
| // TODO the count check is a bit bogus but helps in some error cases |
| // (e.g., the optimizer) |
| // where errors occurred in a processing step earlier in the chain. |
| // We likely need a better |
| // or more explicit way of handling this case. |
| OutputStream testStream = firstLink == null ? this : firstLink; |
| if (ProcessingStepHandler.checkStatus(testStream).isOK() && count > 0) { |
| ((ArtifactDescriptor) descriptor).setProperty(IArtifactDescriptor.DOWNLOAD_SIZE, Long.toString(count)); |
| addDescriptor(descriptor, ((ByteArrayOutputStream) destination).toByteArray()); |
| } |
| } |
| |
| @Override |
| public IStatus getStatus() { |
| return status; |
| } |
| |
| public OutputStream getDestination() { |
| return destination; |
| } |
| |
| @Override |
| public void setStatus(IStatus status) { |
| this.status = status == null ? Status.OK_STATUS : status; |
| } |
| |
| @Override |
| public void write(byte[] b) throws IOException { |
| destination.write(b); |
| count += b.length; |
| } |
| |
| @Override |
| public void write(byte[] b, int off, int len) throws IOException { |
| destination.write(b, off, len); |
| count += len; |
| } |
| |
| @Override |
| public void write(int b) throws IOException { |
| destination.write(b); |
| count++; |
| } |
| |
| public void setFirstLink(OutputStream value) { |
| firstLink = value; |
| } |
| } |
| |
| private final IProvisioningAgent agent; |
| |
| public TestArtifactRepository(IProvisioningAgent agent) { |
| this.agent = agent; |
| repo = new HashMap<>(); |
| } |
| |
| @Override |
| public OutputStream getOutputStream(IArtifactDescriptor descriptor) throws ProvisionException { |
| // Check if the artifact is already in this repository |
| if (contains(descriptor)) { |
| String msg = NLS.bind(Messages.available_already_in, getLocation()); |
| throw new ProvisionException(new Status(IStatus.ERROR, TestActivator.PI_PROV_TESTS, ProvisionException.ARTIFACT_EXISTS, msg, null)); |
| } |
| return new ArtifactOutputStream(new ByteArrayOutputStream(500), descriptor); |
| } |
| |
| @Override |
| public void addDescriptor(IArtifactDescriptor descriptor, IProgressMonitor monitor) { |
| addDescriptor(descriptor, new byte[0]); |
| } |
| |
| @Override |
| @Deprecated |
| public final void addDescriptor(IArtifactDescriptor descriptor) { |
| this.addDescriptor(descriptor, new NullProgressMonitor()); |
| } |
| |
| public void addDescriptor(IArtifactDescriptor descriptor, byte[] bytes) { |
| repo.put(descriptor, bytes); |
| } |
| |
| @Override |
| public void addDescriptors(IArtifactDescriptor[] descriptors, IProgressMonitor monitor) { |
| for (IArtifactDescriptor descriptor : descriptors) { |
| addDescriptor(descriptor); |
| } |
| } |
| |
| @Override |
| @Deprecated |
| public final void addDescriptors(IArtifactDescriptor[] descriptors) { |
| this.addDescriptors(descriptors, new NullProgressMonitor()); |
| } |
| |
| @Override |
| public boolean contains(IArtifactDescriptor descriptor) { |
| return repo.containsKey(descriptor); |
| } |
| |
| @Override |
| public synchronized boolean contains(IArtifactKey key) { |
| for (IArtifactDescriptor descriptor : repo.keySet()) { |
| if (descriptor.getArtifactKey().equals(key)) |
| return true; |
| } |
| return false; |
| } |
| |
| @Override |
| public IStatus getArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) { |
| try { |
| byte[] repoContents = repo.get(descriptor); |
| if (repoContents == null) |
| return new Status(IStatus.ERROR, "test", "no such artifact"); |
| destination.write(repoContents); |
| } catch (IOException e) { |
| e.printStackTrace(); |
| return new Status(IStatus.ERROR, "test", "exception occurred", e); |
| } |
| return Status.OK_STATUS; |
| } |
| |
| @Override |
| public IArtifactDescriptor[] getArtifactDescriptors(IArtifactKey key) { |
| Set<IArtifactDescriptor> result = new HashSet<>(); |
| for (IArtifactDescriptor descriptor : repo.keySet()) { |
| if (descriptor.getArtifactKey().equals(key)) |
| result.add(descriptor); |
| } |
| return result.toArray(new IArtifactDescriptor[0]); |
| } |
| |
| @Override |
| public IStatus getArtifacts(IArtifactRequest[] requests, IProgressMonitor monitor) { |
| SubMonitor subMonitor = SubMonitor.convert(monitor, requests.length); |
| try { |
| //plugin ID taken from TestActivator |
| MultiStatus overallStatus = new MultiStatus("org.eclipse.equinox.p2.test", IStatus.OK, null, null); //$NON-NLS-1$ |
| for (IArtifactRequest request : requests) { |
| overallStatus.add(getArtifact((ArtifactRequest) request, subMonitor.newChild(1))); |
| } |
| return (monitor.isCanceled() ? Status.CANCEL_STATUS : overallStatus); |
| } finally { |
| subMonitor.done(); |
| } |
| } |
| |
| private IStatus getArtifact(ArtifactRequest artifactRequest, IProgressMonitor monitor) { |
| artifactRequest.perform(this, monitor); |
| return artifactRequest.getResult(); |
| } |
| |
| @Override |
| public void removeDescriptor(IArtifactDescriptor descriptor, IProgressMonitor monitor) { |
| repo.remove(descriptor); |
| } |
| |
| @Override |
| @Deprecated |
| public final void removeDescriptor(IArtifactDescriptor descriptor) { |
| this.removeDescriptor(descriptor, new NullProgressMonitor()); |
| } |
| |
| @Override |
| public void removeDescriptor(IArtifactKey key, IProgressMonitor monitor) { |
| ArrayList<IArtifactDescriptor> removeList = new ArrayList<>(); |
| for (IArtifactDescriptor descriptor : repo.keySet()) { |
| if (descriptor.getArtifactKey().equals(key)) |
| removeList.add(descriptor); |
| } |
| for (int i = 0; i < repo.size(); i++) { |
| repo.remove(removeList.get(i)); |
| } |
| } |
| |
| @Override |
| @Deprecated |
| public final void removeDescriptor(IArtifactKey key) { |
| removeDescriptor(key, new NullProgressMonitor()); |
| } |
| |
| @Override |
| public void removeDescriptors(IArtifactDescriptor[] descriptors, IProgressMonitor monitor) { |
| for (IArtifactDescriptor descriptor : descriptors) |
| removeDescriptor(descriptor); |
| } |
| |
| @Override |
| @Deprecated |
| public final void removeDescriptors(IArtifactDescriptor[] descriptors) { |
| this.removeDescriptors(descriptors, new NullProgressMonitor()); |
| } |
| |
| @Override |
| public void removeDescriptors(IArtifactKey[] keys, IProgressMonitor monitor) { |
| for (IArtifactKey key : keys) |
| removeDescriptor(key); |
| } |
| |
| @Override |
| @Deprecated |
| public final void removeDescriptors(IArtifactKey[] keys) { |
| this.removeDescriptors(keys, new NullProgressMonitor()); |
| } |
| |
| @Override |
| public String getDescription() { |
| return description; |
| } |
| |
| @Override |
| public URI getLocation() { |
| return null; |
| } |
| |
| @Override |
| public String getName() { |
| return name; |
| } |
| |
| @Override |
| public Map<String, String> getProperties() { |
| return OrderedProperties.unmodifiableProperties(properties); |
| } |
| |
| @Override |
| public String getProperty(String key) { |
| return properties.get(key); |
| } |
| |
| @Override |
| public String getProvider() { |
| return provider; |
| } |
| |
| @Override |
| public IProvisioningAgent getProvisioningAgent() { |
| return agent; |
| } |
| |
| @Override |
| public String getType() { |
| return "memoryArtifactRepo"; //$NON-NLS-1$ |
| } |
| |
| @Override |
| public String getVersion() { |
| return version; |
| } |
| |
| @Override |
| public boolean isModifiable() { |
| return true; |
| } |
| |
| public void setDescription(String value) { |
| this.description = value; |
| } |
| |
| public void setName(String value) { |
| this.name = value; |
| } |
| |
| @Override |
| public String setProperty(String key, String value, IProgressMonitor monitor) { |
| return (value == null ? properties.remove(key) : properties.put(key, value)); |
| } |
| |
| @Override |
| public final String setProperty(String key, String value) { |
| return this.setProperty(key, value, new NullProgressMonitor()); |
| } |
| |
| public void setProvider(String value) { |
| provider = value; |
| } |
| |
| @Override |
| public void removeAll(IProgressMonitor monitor) { |
| repo.clear(); |
| } |
| |
| @Override |
| @Deprecated |
| public final void removeAll() { |
| removeAll(new NullProgressMonitor()); |
| } |
| |
| @Override |
| public <T> T getAdapter(Class<T> adapter) { |
| return null; |
| } |
| |
| public ZipInputStream getZipInputStream(IArtifactKey key) { |
| //get first descriptor with key |
| IArtifactDescriptor[] descriptor = getArtifactDescriptors(key); |
| if (descriptor == null || descriptor.length == 0 || descriptor[0] == null) |
| return null; |
| return new ZipInputStream(getRawInputStream(descriptor[0])); |
| } |
| |
| public InputStream getRawInputStream(IArtifactDescriptor descriptor) { |
| return new ByteArrayInputStream(repo.get(descriptor), 0, repo.get(descriptor).length); |
| } |
| |
| public ZipInputStream getZipInputStream(IArtifactDescriptor descriptor) { |
| return new ZipInputStream(getRawInputStream(descriptor)); |
| } |
| |
| public byte[] getBytes(IArtifactDescriptor artifactDescriptor) { |
| return repo.get(artifactDescriptor); |
| } |
| |
| @Override |
| public IStatus getRawArtifact(IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) { |
| return getArtifact(descriptor, destination, monitor); |
| } |
| |
| @Override |
| public IArtifactDescriptor createArtifactDescriptor(IArtifactKey key) { |
| return new ArtifactDescriptor(key); |
| } |
| |
| @Override |
| public IArtifactKey createArtifactKey(String classifier, String id, Version keyVersion) { |
| return new ArtifactKey(classifier, id, keyVersion); |
| } |
| |
| @Override |
| public IQueryResult<IArtifactKey> query(IQuery<IArtifactKey> query, IProgressMonitor monitor) { |
| if (monitor != null && monitor.isCanceled()) |
| return Collector.emptyCollector(); |
| |
| Collector<IArtifactKey> collector = new Collector<>(); |
| for (IArtifactDescriptor descriptor : repo.keySet()) { |
| collector.accept(descriptor.getArtifactKey()); |
| } |
| return collector; |
| } |
| |
| @Override |
| public IQueryable<IArtifactDescriptor> descriptorQueryable() { |
| final Collection<IArtifactDescriptor> descs = repo.keySet(); |
| return (query, monitor) -> query.perform(descs.iterator()); |
| } |
| |
| @Override |
| public IStatus executeBatch(IRunnableWithProgress runnable, IProgressMonitor monitor) { |
| try { |
| runnable.run(monitor); |
| } catch (OperationCanceledException oce) { |
| return new Status(IStatus.CANCEL, "org.eclipse.equinox.p2.tests.publisher", oce.getMessage(), oce); |
| } catch (Exception e) { |
| return new Status(IStatus.ERROR, "org.eclipse.equinox.p2.tests.publisher", e.getMessage(), e); |
| } |
| return Status.OK_STATUS; |
| } |
| } |