Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/mirroring/Mirroring.java')
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/mirroring/Mirroring.java291
1 files changed, 291 insertions, 0 deletions
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/mirroring/Mirroring.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/mirroring/Mirroring.java
new file mode 100644
index 000000000..8d2b993ad
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/mirroring/Mirroring.java
@@ -0,0 +1,291 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2009 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
+ * Compeople AG (Stefan Liebig) - various ongoing maintenance
+ *******************************************************************************/
+package org.eclipse.equinox.p2.internal.repository.mirroring;
+
+import org.eclipse.equinox.p2.repository.tools.comparator.ArtifactComparatorFactory;
+import org.eclipse.equinox.p2.repository.tools.comparator.IArtifactComparator;
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.artifact.repository.RawMirrorRequest;
+import org.eclipse.equinox.p2.core.ProvisionException;
+import org.eclipse.equinox.p2.internal.repository.tools.Activator;
+import org.eclipse.equinox.p2.internal.repository.tools.Messages;
+import org.eclipse.equinox.p2.metadata.IArtifactKey;
+import org.eclipse.equinox.p2.query.IQueryResult;
+import org.eclipse.equinox.p2.repository.artifact.*;
+import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * A utility class that performs mirroring of artifacts between repositories.
+ */
+public class Mirroring {
+ private IArtifactRepository source;
+ private IArtifactRepository destination;
+ private IArtifactRepository baseline;
+ private boolean raw;
+ private boolean compare = false;
+ private boolean validate = false;
+ private IArtifactComparator comparator;
+ private String comparatorID;
+ private List<IArtifactKey> keysToMirror;
+ private IArtifactMirrorLog comparatorLog;
+
+ private IArtifactComparator getComparator() {
+ if (comparator == null)
+ comparator = ArtifactComparatorFactory.getArtifactComparator(comparatorID);
+ return comparator;
+ }
+
+ public Mirroring(IArtifactRepository source, IArtifactRepository destination, boolean raw) {
+ this.source = source;
+ this.destination = destination;
+ this.raw = raw;
+ }
+
+ public void setCompare(boolean compare) {
+ this.compare = compare;
+ }
+
+ public void setComparatorId(String id) {
+ this.comparatorID = id;
+ }
+
+ public void setComparatorLog(IArtifactMirrorLog comparatorLog) {
+ this.comparatorLog = comparatorLog;
+ }
+
+ public void setBaseline(IArtifactRepository baseline) {
+ this.baseline = baseline;
+ }
+
+ public void setValidate(boolean validate) {
+ this.validate = validate;
+ }
+
+ public MultiStatus run(boolean failOnError, boolean verbose) {
+ if (!destination.isModifiable())
+ throw new IllegalStateException(NLS.bind(Messages.exception_destinationNotModifiable, destination.getLocation()));
+ if (compare)
+ getComparator(); //initialize the comparator. Only needed if we're comparing. Used to force error if comparatorID is invalid.
+ MultiStatus multiStatus = new MultiStatus(Activator.ID, IStatus.OK, Messages.message_mirroringStatus, null);
+ Iterator<IArtifactKey> keys = null;
+ if (keysToMirror != null)
+ keys = keysToMirror.iterator();
+ else {
+ IQueryResult<IArtifactKey> result = source.query(ArtifactKeyQuery.ALL_KEYS, null);
+ keys = result.iterator();
+ }
+ while (keys.hasNext()) {
+ IArtifactKey key = keys.next();
+ IArtifactDescriptor[] descriptors = source.getArtifactDescriptors(key);
+ for (int j = 0; j < descriptors.length; j++) {
+ IStatus result = mirror(descriptors[j], verbose);
+ //Only log INFO and WARNING if we want verbose logging. Always log ERRORs
+ if (!result.isOK() && (verbose || result.getSeverity() == IStatus.ERROR))
+ multiStatus.add(result);
+ //stop mirroring as soon as we have an error
+ if (failOnError && multiStatus.getSeverity() == IStatus.ERROR)
+ return multiStatus;
+ }
+ }
+ if (validate) {
+ // Simple validation of the mirror
+ IStatus validation = validateMirror(verbose);
+ if (!validation.isOK() && (verbose || validation.getSeverity() == IStatus.ERROR))
+ multiStatus.add(validation);
+ }
+ return multiStatus;
+ }
+
+ private IStatus mirror(IArtifactDescriptor descriptor, boolean verbose) {
+ IArtifactDescriptor newDescriptor = raw ? descriptor : new ArtifactDescriptor(descriptor);
+
+ if (verbose)
+ System.out.println("Mirroring: " + descriptor.getArtifactKey() + " (Descriptor: " + descriptor + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+
+ if (compare && baseline != null)
+ if (baseline.contains(descriptor)) {
+ // we have to create an output stream based on the descriptor found in the baseline otherwise all
+ // the properties will be copied over from the wrong descriptor and our repository will be inconsistent.
+ IArtifactDescriptor baselineDescriptor = getBaselineDescriptor(descriptor);
+
+ // if we found a descriptor in the baseline then we'll use it to copy the artifact
+ if (baselineDescriptor != null) {
+ MultiStatus status = new MultiStatus(Activator.ID, IStatus.OK, NLS.bind(Messages.Mirroring_compareAndDownload, descriptor), null);
+ //Compare source against baseline
+ IStatus comparison = getComparator().compare(baseline, baselineDescriptor, source, descriptor);
+ if (comparatorLog != null)
+ comparatorLog.log(baselineDescriptor, comparison);
+ status.add(comparison);
+ if (destination.contains(baselineDescriptor))
+ return compareToDestination(baselineDescriptor);
+
+ //download artifact from baseline
+ status.add(downloadArtifact(baseline, baselineDescriptor, baselineDescriptor));
+ return status;
+ }
+ }
+
+ // Check if the destination already contains the file.
+ if (destination.contains(newDescriptor)) {
+ if (compare)
+ return compareToDestination(descriptor);
+ String message = NLS.bind(Messages.mirror_alreadyExists, descriptor, destination);
+ return new Status(IStatus.INFO, Activator.ID, ProvisionException.ARTIFACT_EXISTS, message, null);
+ }
+
+ return downloadArtifact(source, newDescriptor, descriptor);
+ }
+
+ /**
+ * Takes an IArtifactDescriptor descriptor and the ProvisionException that was thrown when destination.getOutputStream(descriptor)
+ * and compares descriptor to the duplicate descriptor in the destination.
+ *
+ * Callers should verify the ProvisionException was thrown due to the artifact existing in the destination before invoking this method.
+ * @param descriptor
+ * @return the status of the compare
+ */
+ private IStatus compareToDestination(IArtifactDescriptor descriptor) {
+ IArtifactDescriptor[] destDescriptors = destination.getArtifactDescriptors(descriptor.getArtifactKey());
+ IArtifactDescriptor destDescriptor = null;
+ for (int i = 0; destDescriptor == null && i < destDescriptors.length; i++) {
+ if (destDescriptors[i].equals(descriptor))
+ destDescriptor = destDescriptors[i];
+ }
+ if (destDescriptor == null)
+ return new Status(IStatus.INFO, Activator.ID, ProvisionException.ARTIFACT_EXISTS, Messages.Mirroring_noMatchingDescriptor, null);
+ return compare(source, descriptor, destination, destDescriptor);
+ }
+
+ private IStatus compare(IArtifactRepository sourceRepository, IArtifactDescriptor sourceDescriptor, IArtifactRepository destRepository, IArtifactDescriptor destDescriptor) {
+ IStatus comparison = getComparator().compare(sourceRepository, sourceDescriptor, destRepository, destDescriptor);
+ if (comparatorLog != null)
+ comparatorLog.log(sourceDescriptor, comparison);
+ return comparison;
+ }
+
+ /*
+ * Create, and execute a MirrorRequest for a given descriptor.
+ */
+ private IStatus downloadArtifact(IArtifactRepository sourceRepo, IArtifactDescriptor destDescriptor, IArtifactDescriptor srcDescriptor) {
+ RawMirrorRequest request = new RawMirrorRequest(srcDescriptor, destDescriptor, destination);
+ request.setSourceRepository(sourceRepo);
+
+ request.perform(new NullProgressMonitor());
+
+ return request.getResult();
+ }
+
+ public void setArtifactKeys(IArtifactKey[] keys) {
+ this.keysToMirror = Arrays.asList(keys);
+ }
+
+ /*
+ * Get the equivalent descriptor from the baseline repository
+ */
+ private IArtifactDescriptor getBaselineDescriptor(IArtifactDescriptor descriptor) {
+ IArtifactDescriptor[] baselineDescriptors = baseline.getArtifactDescriptors(descriptor.getArtifactKey());
+ for (int i = 0; i < baselineDescriptors.length; i++) {
+ if (baselineDescriptors[i].equals(descriptor))
+ return baselineDescriptors[i];
+ }
+ return null;
+ }
+
+ /*
+ * Simple validation of a mirror to see if all source descriptors are present in the destination
+ */
+ private IStatus validateMirror(boolean verbose) {
+ MultiStatus status = new MultiStatus(Activator.ID, 0, Messages.Mirroring_ValidationError, null);
+
+ // The keys that were mirrored in this session
+ Iterator<IArtifactKey> keys = null;
+ if (keysToMirror != null) {
+ keys = keysToMirror.iterator();
+ } else {
+ IQueryResult<IArtifactKey> result = source.query(ArtifactKeyQuery.ALL_KEYS, null);
+ keys = result.iterator();
+ }
+ while (keys.hasNext()) {
+ IArtifactKey artifactKey = keys.next();
+ IArtifactDescriptor[] srcDescriptors = source.getArtifactDescriptors(artifactKey);
+ IArtifactDescriptor[] destDescriptors = destination.getArtifactDescriptors(artifactKey);
+
+ Arrays.sort(srcDescriptors, new ArtifactDescriptorComparator());
+ Arrays.sort(destDescriptors, new ArtifactDescriptorComparator());
+
+ int src = 0;
+ int dest = 0;
+ while (src < srcDescriptors.length && dest < destDescriptors.length) {
+ if (!destDescriptors[dest].equals(srcDescriptors[src])) {
+ if (destDescriptors[dest].toString().compareTo((srcDescriptors[src].toString())) > 0) {
+ // Missing an artifact
+ if (verbose)
+ System.out.println(NLS.bind(Messages.Mirroring_missingDescriptor, srcDescriptors[src]));
+ status.add(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.Mirroring_missingDescriptor, srcDescriptors[src++])));
+ } else {
+ // Its okay if there are extra descriptors in the destination
+ dest++;
+ }
+ } else {
+ // check properties for differences
+ Map<String, String> destMap = destDescriptors[dest].getProperties();
+ Map<String, String> srcProperties = null;
+ if (baseline != null) {
+ IArtifactDescriptor baselineDescriptor = getBaselineDescriptor(destDescriptors[dest]);
+ if (baselineDescriptor != null)
+ srcProperties = baselineDescriptor.getProperties();
+ }
+ // Baseline not set, or could not find descriptor so we'll use the source descriptor
+ if (srcProperties == null)
+ srcProperties = srcDescriptors[src].getProperties();
+
+ // Cycle through properties of the originating descriptor & compare
+ for (String key : srcProperties.keySet()) {
+ if (!srcProperties.get(key).equals(destMap.get(key))) {
+ if (verbose)
+ System.out.println(NLS.bind(Messages.Mirroring_differentDescriptorProperty, new Object[] {destDescriptors[dest], key, srcProperties.get(key), destMap.get(key)}));
+ status.add(new Status(IStatus.WARNING, Activator.ID, NLS.bind(Messages.Mirroring_differentDescriptorProperty, new Object[] {destDescriptors[dest], key, srcProperties.get(key), destMap.get(key)})));
+ }
+ }
+ src++;
+ dest++;
+ }
+ }
+
+ // If there are still source descriptors they're missing from the destination repository
+ while (src < srcDescriptors.length) {
+ if (verbose)
+ System.out.println(NLS.bind(Messages.Mirroring_missingDescriptor, srcDescriptors[src]));
+ status.add(new Status(IStatus.ERROR, Activator.ID, NLS.bind(Messages.Mirroring_missingDescriptor, srcDescriptors[src++])));
+ }
+ }
+
+ return status;
+ }
+
+ // Simple comparator for ArtifactDescriptors
+ protected class ArtifactDescriptorComparator implements Comparator<IArtifactDescriptor> {
+
+ public int compare(IArtifactDescriptor arg0, IArtifactDescriptor arg1) {
+ if (arg0 != null && arg1 != null)
+ return arg0.toString().compareTo(arg1.toString());
+ else if (arg1 == null && arg0 == null)
+ return 0;
+ else if (arg1 == null)
+ return 1;
+ return -1;
+ }
+ }
+}

Back to the top