diff options
author | Andrew Niefer | 2010-02-10 16:19:38 +0000 |
---|---|---|
committer | Andrew Niefer | 2010-02-10 16:19:38 +0000 |
commit | 55d6e02ac89fe04a18ffc3ce62fa8bb0d7614345 (patch) | |
tree | f567bc6c17bbc28e9288b10b10179709fdb537f7 /bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal | |
parent | 47630b5366febb13438fb4a097a7dd4f39db3849 (diff) | |
download | rt.equinox.p2-55d6e02ac89fe04a18ffc3ce62fa8bb0d7614345.tar.gz rt.equinox.p2-55d6e02ac89fe04a18ffc3ce62fa8bb0d7614345.tar.xz rt.equinox.p2-55d6e02ac89fe04a18ffc3ce62fa8bb0d7614345.zip |
bug 302288 - feature comparison, *.mappings
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal')
3 files changed, 143 insertions, 45 deletions
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/JarComparator.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/JarComparator.java index 7d2b7de43..8ee9b8e28 100644 --- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/JarComparator.java +++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/JarComparator.java @@ -10,10 +10,6 @@ *******************************************************************************/ package org.eclipse.equinox.p2.internal.repository.comparator; -import org.eclipse.equinox.p2.internal.repository.comparator.java.*; - -import org.eclipse.equinox.p2.repository.tools.comparator.IArtifactComparator; - import java.io.*; import java.util.*; import java.util.Map.Entry; @@ -21,8 +17,13 @@ import java.util.jar.*; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import org.eclipse.core.runtime.*; +import org.eclipse.equinox.internal.p2.publisher.eclipse.FeatureParser; +import org.eclipse.equinox.p2.internal.repository.comparator.java.*; +import org.eclipse.equinox.p2.publisher.eclipse.Feature; +import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry; import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor; import org.eclipse.equinox.p2.repository.artifact.IArtifactRepository; +import org.eclipse.equinox.p2.repository.tools.comparator.IArtifactComparator; import org.eclipse.osgi.util.NLS; public class JarComparator implements IArtifactComparator { @@ -31,11 +32,13 @@ public class JarComparator implements IArtifactComparator { private static final String CLASS_EXTENSION = ".class"; //$NON-NLS-1$ private static final String JAR_EXTENSION = ".jar"; //$NON-NLS-1$ private static final String PROPERTIES_EXTENSION = ".properties"; //$NON-NLS-1$ + private static final String MAPPINGS_EXTENSION = ".mappings"; //$NON-NLS-1$ private static final String PLUGIN_ID = "org.eclipse.equinox.p2.repository.tools"; //$NON-NLS-1$ private static final String DESTINATION_ARTIFACT_PREFIX = "destinationartifact"; //$NON-NLS-1$ private static final String SUFFIX_JAR = ".jar"; //$NON-NLS-1$ private static final String SOURCE_ARTIFACT_PREFIX = "sourceartifact"; //$NON-NLS-1$ private static final String OSGI_BUNDLE_CLASSIFIER = "osgi.bundle"; //$NON-NLS-1$ + private static final String FEATURE_CLASSIFIER = "org.eclipse.update.feature"; //$NON-NLS-1$ private static final String META_INF = "meta-inf/"; //$NON-NLS-1$ private static final String DSA_EXT = ".dsa"; //$NON-NLS-1$ @@ -50,12 +53,9 @@ public class JarComparator implements IArtifactComparator { destinationLocation = URIUtil.toUnencodedString(destinationDescriptor.getRepository().getLocation()); descriptorString = sourceDescriptor.toString(); - String classifier = sourceDescriptor.getArtifactKey().getClassifier(); - if (!OSGI_BUNDLE_CLASSIFIER.equals(classifier)) { - return Status.OK_STATUS; - } - classifier = destinationDescriptor.getArtifactKey().getClassifier(); - if (!OSGI_BUNDLE_CLASSIFIER.equals(classifier)) { + String classifier1 = sourceDescriptor.getArtifactKey().getClassifier(); + String classifier2 = destinationDescriptor.getArtifactKey().getClassifier(); + if (!classifier1.equals(classifier2) || (!OSGI_BUNDLE_CLASSIFIER.equals(classifier1) && !FEATURE_CLASSIFIER.equals(classifier1))) { return Status.OK_STATUS; } @@ -64,7 +64,10 @@ public class JarComparator implements IArtifactComparator { try { firstTempFile = getLocalJarFile(source, sourceDescriptor, SOURCE_ARTIFACT_PREFIX); secondTempFile = getLocalJarFile(destination, destinationDescriptor, DESTINATION_ARTIFACT_PREFIX); - return compare(firstTempFile, secondTempFile); + if (classifier1.equals(OSGI_BUNDLE_CLASSIFIER)) + return compare(firstTempFile, secondTempFile); + else if (classifier1.equals(FEATURE_CLASSIFIER)) + return compareFeatures(firstTempFile, secondTempFile); } catch (CoreException e) { return e.getStatus(); } finally { @@ -73,6 +76,47 @@ public class JarComparator implements IArtifactComparator { if (secondTempFile != null) secondTempFile.delete(); } + return Status.OK_STATUS; + } + + public IStatus compareFeatures(File sourceFile, File destinationFile) { + FeatureParser parser = new FeatureParser(); + Feature feature1 = parser.parse(sourceFile); + Feature feature2 = parser.parse(destinationFile); + + MultiStatus parent = new MultiStatus(PLUGIN_ID, 0, NLS.bind(Messages.differentEntry, new String[] {descriptorString, sourceLocation, destinationLocation}), null); + + if (!feature1.getId().equals(feature2.getId())) + parent.add(newErrorStatus(NLS.bind(Messages.featureIdsDontMatch, feature1.getId(), feature2.getId()))); + if (!feature1.getVersion().equals(feature2.getVersion())) + parent.add(newErrorStatus(NLS.bind(Messages.featureVersionsDontMatch, feature1.getVersion(), feature2.getVersion()))); + + Map<FeatureEntry, FeatureEntry> entryMap = new HashMap<FeatureEntry, FeatureEntry>(); + FeatureEntry[] entries = feature1.getEntries(); + for (int i = 0; i < entries.length; i++) + entryMap.put(entries[i], entries[i]); + + entries = feature2.getEntries(); + if (entries.length != entryMap.size()) + parent.add(newErrorStatus(Messages.featureSize)); + + for (int i = 0; i < entries.length; i++) { + FeatureEntry firstEntry = entryMap.get(entries[i]); + if (firstEntry == null) + parent.add(newErrorStatus(NLS.bind(Messages.featureEntry, entries[i]))); + else { + if (firstEntry.isOptional() != entries[i].isOptional()) + parent.add(newErrorStatus(NLS.bind(Messages.featureEntryOptional, entries[i]))); + if (firstEntry.isUnpack() != entries[i].isUnpack()) + parent.add(newErrorStatus(NLS.bind(Messages.featureEntryUnpack, entries[i]))); + if (firstEntry.isRequires() && firstEntry.getMatch() != null && !firstEntry.getMatch().equals(entries[i].getMatch())) + parent.add(newErrorStatus(NLS.bind(Messages.featureEntryMatch, entries[i]))); + if (firstEntry.getFilter() != null && !firstEntry.getFilter().equals(entries[i].getFilter())) + parent.add(newErrorStatus(NLS.bind(Messages.featureEntryFilter, entries[i]))); + } + } + + return parent.getChildren().length == 0 ? Status.OK_STATUS : parent; } public IStatus compare(File sourceFile, File destinationFile) { @@ -83,13 +127,17 @@ public class JarComparator implements IArtifactComparator { secondFile = new ZipFile(destinationFile); final int firstFileSize = firstFile.size(); final int secondFileSize = secondFile.size(); + MultiStatus parent = new MultiStatus(PLUGIN_ID, 0, NLS.bind(Messages.differentEntry, new String[] {descriptorString, sourceLocation, destinationLocation}), null); + if (firstFileSize != secondFileSize) { - return newErrorStatus(NLS.bind(Messages.differentNumberOfEntries, new String[] {descriptorString, sourceLocation, Integer.toString(firstFileSize), destinationLocation, Integer.toString(secondFileSize)})); + parent.add(newErrorStatus(NLS.bind(Messages.differentNumberOfEntries, new String[] {descriptorString, sourceLocation, Integer.toString(firstFileSize), destinationLocation, Integer.toString(secondFileSize)}))); + return parent; } for (Enumeration<? extends ZipEntry> enumeration = firstFile.entries(); enumeration.hasMoreElements();) { ZipEntry entry = enumeration.nextElement(); String entryName = entry.getName(); final ZipEntry entry2 = secondFile.getEntry(entryName); + IStatus result = null; if (!entry.isDirectory() && entry2 != null) { String lowerCase = entryName.toLowerCase(); if (isSigningEntry(lowerCase)) { @@ -101,35 +149,40 @@ public class JarComparator implements IArtifactComparator { try { firstStream = new BufferedInputStream(firstFile.getInputStream(entry)); secondStream = new BufferedInputStream(secondFile.getInputStream(entry2)); - boolean result = false; if (lowerCase.endsWith(CLASS_EXTENSION)) { try { - result = compareClasses(firstStream, entry.getSize(), secondStream, entry2.getSize()); + result = compareClasses(entryName, firstStream, entry.getSize(), secondStream, entry2.getSize()); } catch (ClassFormatException e) { - return newErrorStatus(NLS.bind(Messages.differentEntry, new String[] {entryName, descriptorString, sourceLocation}), e); + result = newErrorStatus(NLS.bind(Messages.differentEntry, new String[] {entryName, descriptorString, sourceLocation}), e); } } else if (lowerCase.endsWith(JAR_EXTENSION)) { result = compareNestedJars(firstStream, entry.getSize(), secondStream, entry2.getSize(), entryName); - } else if (lowerCase.endsWith(PROPERTIES_EXTENSION)) { - result = compareProperties(firstStream, secondStream); + } else if (lowerCase.endsWith(PROPERTIES_EXTENSION) || lowerCase.endsWith(MAPPINGS_EXTENSION)) { + result = compareProperties(entryName, firstStream, secondStream); } else if (entryName.equalsIgnoreCase(JarFile.MANIFEST_NAME)) { result = compareManifest(firstStream, secondStream); //MANIFEST.MF file } else { - result = compareBytes(firstStream, entry.getSize(), secondStream, entry2.getSize()); + long size1 = entry.getSize(); + long size2 = entry2.getSize(); + if (size1 != size2) + result = newErrorStatus(NLS.bind(Messages.binaryDifferentLength, new String[] {entryName, String.valueOf(Math.abs(size1 - size2))})); + else + result = compareBytes(entryName, firstStream, entry.getSize(), secondStream, entry2.getSize()); } - if (!result) - return newErrorStatus(NLS.bind(Messages.differentEntry, new String[] {entryName, descriptorString, sourceLocation})); } finally { Utility.close(firstStream); Utility.close(secondStream); } } else if (!entry.isDirectory()) { // missing entry, entry2 == null - return newErrorStatus(NLS.bind(Messages.missingEntry, new String[] {entryName, descriptorString, sourceLocation})); + result = newErrorStatus(NLS.bind(Messages.missingEntry, new String[] {entryName, descriptorString, sourceLocation})); + } + + if (result != null && !result.isOK()) { + parent.add(result); + return parent; } } - } catch (CoreException e) { - return e.getStatus(); } catch (IOException e) { // missing entry return newErrorStatus(NLS.bind(Messages.ioexception, new String[] {sourceFile.getAbsolutePath(), destinationFile.getAbsolutePath()}), e); @@ -140,78 +193,84 @@ public class JarComparator implements IArtifactComparator { return Status.OK_STATUS; } - private boolean compareManifest(InputStream firstStream, InputStream secondStream) throws IOException { + private IStatus compareManifest(InputStream firstStream, InputStream secondStream) throws IOException { Manifest manifest = new Manifest(firstStream); Manifest manifest2 = new Manifest(secondStream); if (manifest == null || manifest2 == null) - return true; + return Status.OK_STATUS; Attributes attributes = manifest.getMainAttributes(); Attributes attributes2 = manifest2.getMainAttributes(); if (attributes.size() != attributes2.size()) - return false; + return newErrorStatus(NLS.bind(Messages.manifestDifferentSize, String.valueOf(Math.abs(attributes.size() - attributes2.size())))); for (Entry<Object, Object> entry : attributes.entrySet()) { Object value2 = attributes2.get(entry.getKey()); if (value2 == null) { - return false; + return newErrorStatus(NLS.bind(Messages.manifestMissingEntry, entry.getKey())); } if (!value2.equals(entry.getValue())) { - return false; + return newErrorStatus(NLS.bind(Messages.manifestDifferentValue, entry.getKey())); } } - return true; + return Status.OK_STATUS; } - private boolean compareClasses(InputStream stream1, long size1, InputStream stream2, long size2) throws ClassFormatException, IOException { + private IStatus compareClasses(String entryName, InputStream stream1, long size1, InputStream stream2, long size2) throws ClassFormatException, IOException { Disassembler disassembler = new Disassembler(); byte[] firstEntryClassFileBytes = Utility.getInputStreamAsByteArray(stream1, (int) size1); byte[] secondEntryClassFileBytes = Utility.getInputStreamAsByteArray(stream2, (int) size2); String contentsFile1 = disassembler.disassemble(firstEntryClassFileBytes, LINE_SEPARATOR, Disassembler.DETAILED | Disassembler.COMPACT); String contentsFile2 = disassembler.disassemble(secondEntryClassFileBytes, LINE_SEPARATOR, Disassembler.DETAILED | Disassembler.COMPACT); - return contentsFile1.equals(contentsFile2); + if (!contentsFile1.equals(contentsFile2)) + return newErrorStatus(NLS.bind(Messages.classesDifferent, entryName)); + return Status.OK_STATUS; } - private boolean compareNestedJars(InputStream stream1, long size1, InputStream stream2, long size2, String entry) throws CoreException, IOException { + private IStatus compareNestedJars(InputStream stream1, long size1, InputStream stream2, long size2, String entry) throws IOException { File firstTempFile = getLocalJarFile(stream1, entry, size1); File secondTempFile = getLocalJarFile(stream2, entry, size2); try { - IStatus status = compare(firstTempFile, secondTempFile); - if (!status.isOK()) - throw new CoreException(status); + return compare(firstTempFile, secondTempFile); } finally { if (firstTempFile != null) firstTempFile.delete(); if (secondTempFile != null) secondTempFile.delete(); } - return true; } - private boolean compareProperties(InputStream stream1, InputStream stream2) { + private IStatus compareProperties(String entryName, InputStream stream1, InputStream stream2) { Properties props1 = loadProperties(stream1); Properties props2 = loadProperties(stream2); if (props1.size() != props2.size()) - return false; + return newErrorStatus(NLS.bind(Messages.propertiesSizesDifferent, entryName, String.valueOf(Math.abs(props1.size() - props2.size())))); props1.keys(); for (Iterator<Object> iterator = props1.keySet().iterator(); iterator.hasNext();) { String key = (String) iterator.next(); if (!props2.containsKey(key)) - return false; - if (!props1.getProperty(key).equals(props2.getProperty(key))) - return false; + return newErrorStatus(NLS.bind(Messages.missingProperty, key, entryName)); + String prop1 = props1.getProperty(key); + String prop2 = props2.getProperty(key); + if (!prop1.equals(prop2)) { + if (prop1.length() < 10 && prop2.length() < 10) + return newErrorStatus(NLS.bind(Messages.differentPropertyValueFull, new String[] {entryName, key, prop1, prop2})); + return newErrorStatus(NLS.bind(Messages.differentPropertyValueFull, entryName, key)); + } } - return true; + return Status.OK_STATUS; } - private boolean compareBytes(InputStream firstStream, long size1, InputStream secondStream, long size2) throws IOException { + private IStatus compareBytes(String entryName, InputStream firstStream, long size1, InputStream secondStream, long size2) throws IOException { byte[] firstBytes = Utility.getInputStreamAsByteArray(firstStream, (int) size1); byte[] secondBytes = Utility.getInputStreamAsByteArray(secondStream, (int) size2); - return Arrays.equals(firstBytes, secondBytes); + if (!Arrays.equals(firstBytes, secondBytes)) + return newErrorStatus(NLS.bind(Messages.binaryFilesDifferent, entryName)); + return Status.OK_STATUS; } private Properties loadProperties(InputStream input) { diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Messages.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Messages.java index 7a69bbb73..198df63bb 100644 --- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Messages.java +++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/Messages.java @@ -15,9 +15,29 @@ import org.eclipse.osgi.util.NLS; public class Messages extends NLS { private static final String BUNDLE_NAME = "org.eclipse.equinox.p2.internal.repository.comparator.java.messages"; //$NON-NLS-1$ public static String differentNumberOfEntries; + public static String binaryDifferentLength; + public static String classesDifferent; + public static String propertiesSizesDifferent; + public static String differentPropertyValueShort; + public static String differentPropertyValueFull; + public static String missingProperty; + public static String manifestDifferentSize; + public static String manifestMissingEntry; + public static String manifestDifferentValue; + public static String binaryFilesDifferent; public static String differentEntry; public static String missingEntry; public static String ioexception; + + public static String featureSize; + public static String featureIdsDontMatch; + public static String featureVersionsDontMatch; + public static String featureEntry; + public static String featureEntryOptional; + public static String featureEntryUnpack; + public static String featureEntryMatch; + public static String featureEntryFilter; + public static String disassembler_opentypedeclaration; public static String disassembler_closetypedeclaration; public static String disassembler_endofmethodheader; diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/messages.properties b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/messages.properties index e8c395639..a835f6ed1 100644 --- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/messages.properties +++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/java/messages.properties @@ -9,9 +9,28 @@ # IBM Corporation - initial API and implementation ############################################################################### differentNumberOfEntries=Difference in [{0}]: {1} contains {2} files and {3} contains {4} files -differentEntry=Difference found for {0} within [{1}] from {2} +differentEntry=Difference found for {0} between {1} and {2} missingEntry=Missing {0} within [{1}] from {2} ioexception=IOException comparing {0} and {1} +binaryDifferentLength= Binary file {0}: sizes differ by {1} bytes. +classesDifferent= The class {0} is different. +propertiesSizesDifferent=The properties file {0} has a different number ({0}) of properties. +differentPropertyValueShort=In {0}, the property \"{1}\" has different values. +differentPropertyValueFull= In {0}, the property \"{1}\" has different values: \"{2}\" and \"{3}\". +missingProperty= The property \"{0}\" is not present in both properties files ({2}). +manifestDifferentSize=The Manifest file sizes differ by {0} elements. +manifestMissingEntry= The header \"{0}\" is not present in both Manifest files. +manifestDifferentValue=The manifest header \"{0}\" has different values. +binaryFilesDifferent=Binary file \"{0}\" is different. + +featureSize=The feature has a different number of entries/ +featureIdsDontMatch=Feature ids are not equal: \"{0}\" and \"{1}\" +featureVersionsDontMatch=Feature versions are not equal: \"{0}\" and \"{1}\" +featureEntry=The entry \"{0}\" is not present in both features. +featureEntryOptional=The entry \"{0}\" is not optional in both features. +featureEntryUnpack=The entry \"{0}\" has different unpack attribute values. +featureEntryMatch=The entry \"{0}\" has different match rules. +featureEntryFilter=The entry \"{0}\" has different filters. ### Disassembler messages |