Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMykola Nikishov2015-11-03 23:01:31 +0000
committerAlexander Kurtakov2018-03-01 09:50:32 +0000
commit9e5ac9146a99bc132960034e5312f1b449a31fd6 (patch)
treea4f3008f1e9ecf7be580989a9135babc28437965
parente92e31abc7ed83117b9cd25b4026531b4ae47064 (diff)
downloadrt.equinox.p2-9e5ac9146a99bc132960034e5312f1b449a31fd6.tar.gz
rt.equinox.p2-9e5ac9146a99bc132960034e5312f1b449a31fd6.tar.xz
rt.equinox.p2-9e5ac9146a99bc132960034e5312f1b449a31fd6.zip
Bug 423715 - Support multiple algorithms for artifact checksumsI20180301-2000
Developer of p2-based software should be able to check integrity of artifact checksums using any MessageDigest implementation available, at his own discretion, without ever touching p2 internals. For the purpose of this bug, limit enabled checksum algorithms to: - MD5 (legacy one, deprecated now, for backward compatibility only) - SHA-256 (more collision-resistant than MD5) See artifactChecksums.exsd for more details. First, encode ID of the checksum algorithm into the name of the property itself so that artifact descriptor now may look like: <artifact classifier='binary' id='testKeyId' version='1.2.3'> <properties size='6'> <property name='download.md5' value='b3788632488d48b850255acf68669651'/> <property name='artifact.md5' value='b3788632488d48b850255acf68669651'/> <property name='download.checksum.sha-256' value='d594816b995d1689c2dfc97dc244859abe6bdb9ebeb4b396e401afd85a97ee16'/> <property name='download.checksum.whirlpool' value='e4f3ece3d3f289cc2686a68f0b1b5a2d03da3a8ccdc3cd6d03209e4c789af724c8fa915bb890079e1abe78df44875cec132885dd6ae1176eed7938dfb3c7b551'/> <property name='artifact.checksum.sha-256' value='d594816b995d1689c2dfc97dc244859abe6bdb9ebeb4b396e401afd85a97ee16'/> <property name='artifact.checksum.tiger' value='462a72a1a593b9e2de8721b8d79335fd03e974f2e2e1f35a'/> </properties> </artifact> Prefix helps to avoid conflicts with other, not checksum-related, properties. To find checksums of specific type, we need all properties with prefix 'artifact.checksum.', Extracting checksum id from the name of the property is also trivial. Store these prefixes in IArtifactDescriptor's DOWNLOAD_CHECKSUM and ARTIFACT_CHECKSUM. ChecksumUtilities provides internal API to deal with properties. Second, map ID of checksum algorithm to the name of MessageDigest implementation with a contribution to a new extension point org.eclipse.equinox.p2.artifact.repository.artifactChecksums: <extension point="org.eclipse.equinox.p2.artifact.repository.artifactChecksums"> <artifactChecksum algorithm="SHA-256" id="sha-256" ... /> </extension> Number of actual checksums in artifact descriptor depends on the configuration of the application that created such descriptor because p2 will: - handle MD5 checksums as usual, preserving backward compatibility - calculate other checksums using extensions that contribute to artifactChecksums extension point Last, we use id of specific checksum to get MessageDigest instance with getInstance(String). There is a number of standalone applications (like MirrorApplication) and Ant tasks (like ValidateTask) that allow user to chose specific comparator by id and ArtifactComparatorFactory is responsible for instantiating it. Legacy MD5 comparator requires no special configuration while the new ArtifactChecksumComparator is more generic and needs some parameters to instantiate. ArtifactComparatorFactory handles this by accepting fake comparator id - concatenated ArtifactChecksumComparator's id and checksum algorithm id. In other words, to compare artifacts using SHA-256 algorithm use 'org.eclipse.equinox.artifact.comparator.checksum.sha-256' as comparator id. We generate, consume and compare artifact checksums using all enabled algorithms. Ideally, configuration options should provide more control for both repository publisher and p2 client like: - a priority (compare with SHA-512 first, then SHA-256 and, finally, MD5) - skip specific checksum (do not use MD5 even if provided) - mandatory checksum (require Whirlpool and it's an error if its not available) While I have no good solution for this right now, there are some configuration options provided. Also, number of new enabled checksum algorithms is limited to SHA-256 only (more checksums = more reasons to fail = more reasons to disable). To turn checksum verification off completely: - for p2 client, use property 'eclipse.p2.checksums.disable' (see SimpleArtifactRepository.CHECKSUMS_ENABLED constant). - for p2 publisher, the old PublisherInfo's setArtifactOptions(int) and IPublisherInfo.A_NO_MD5 still could be used. To disable MD5 checksums only, existing properties 'eclipse.p2.MD5Check' and 'eclipse.p2.MD5ArtifactCheck' still can be used. Change-Id: Iacd267e13d5d096694001d34cafbaea5451e7157 Signed-off-by: Mykola Nikishov <mn@mn.com.ua>
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF1
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml13
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/schema/artifactChecksums.exsd139
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumUtilities.java142
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumVerifier.java86
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/Messages.java31
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/messages.properties14
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/md5/MD5Verifier.java13
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/Messages.java6
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/RawMirrorRequest.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/messages.properties6
-rw-r--r--bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java27
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/META-INF/MANIFEST.MF1
-rw-r--r--bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/spi/p2/publisher/PublisherHelper.java45
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/META-INF/MANIFEST.MF1
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/plugin.xml6
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/ArtifactChecksumComparator.java62
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/MD5ArtifactComparator.java9
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/Messages.java6
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/RecreateRepositoryApplication.java28
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/messages.properties8
-rw-r--r--bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/repository/tools/comparator/ArtifactComparatorFactory.java63
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumHelper.java79
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumProducer.java58
-rw-r--r--bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java25
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF1
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java3
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/ChecksumVerifierTest.java114
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java3
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/ChecksumGenerationTest.java57
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/AllTests.java3
-rw-r--r--bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/ChecksumHelperTest.java51
32 files changed, 1018 insertions, 92 deletions
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
index 4e24d6fe3..657a43558 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/META-INF/MANIFEST.MF
@@ -7,6 +7,7 @@ Bundle-Activator: org.eclipse.equinox.internal.p2.artifact.repository.Activator
Bundle-Vendor: %providerName
Bundle-Localization: plugin
Export-Package: org.eclipse.equinox.internal.p2.artifact.processing;x-friends:="org.eclipse.equinox.p2.artifact.processors,org.eclipse.equinox.p2.artifact.optimizers",
+ org.eclipse.equinox.internal.p2.artifact.processors.checksum;x-friends:="org.eclipse.equinox.p2.publisher",
org.eclipse.equinox.internal.p2.artifact.processors.md5;x-internal:=true,
org.eclipse.equinox.internal.p2.artifact.processors.pack200;x-friends:="org.eclipse.equinox.p2.artifact.processors,org.eclipse.equinox.p2.artifact.optimizers",
org.eclipse.equinox.internal.p2.artifact.repository;
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml b/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml
index fa791fe2c..6abe0c6f5 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/plugin.xml
@@ -4,6 +4,7 @@
<extension-point id="artifactRepositories" name="Artifact Repositories" schema="schema/artifactRepositories.exsd"/>
<extension-point id="processingSteps" name="Processing Steps" schema="schema/processingSteps.exsd"/>
<extension-point id="artifactComparators" name="Artifact Comparators" schema="schema/artifactComparators.exsd"/>
+ <extension-point id="artifactChecksums" name="Artifact Checksum support" schema="schema/artifactChecksums.exsd"/>
<extension
point="org.eclipse.equinox.p2.artifact.repository.processingSteps"
@@ -37,4 +38,16 @@
id="org.eclipse.equinox.p2.processing.MD5Verifier">
<step class="org.eclipse.equinox.internal.p2.artifact.processors.md5.MD5Verifier"/>
</extension>
+ <extension
+ point="org.eclipse.equinox.p2.artifact.repository.processingSteps"
+ id="org.eclipse.equinox.p2.processing.ChecksumVerifier">
+ <step class="org.eclipse.equinox.internal.p2.artifact.processors.checksum.ChecksumVerifier"/>
+ </extension>
+ <extension
+ point="org.eclipse.equinox.p2.artifact.repository.artifactChecksums">
+ <artifactChecksum
+ algorithm="SHA-256"
+ id="sha-256">
+ </artifactChecksum>
+ </extension>
</plugin>
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/schema/artifactChecksums.exsd b/bundles/org.eclipse.equinox.p2.artifact.repository/schema/artifactChecksums.exsd
new file mode 100644
index 000000000..2dc494040
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/schema/artifactChecksums.exsd
@@ -0,0 +1,139 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- Schema file written by PDE -->
+<schema targetNamespace="org.eclipse.equinox.p2.artifact.repository" xmlns="http://www.w3.org/2001/XMLSchema">
+<annotation>
+ <appInfo>
+ <meta.schema plugin="org.eclipse.equinox.p2.artifact.repository" id="artifactChecksums" name="Artifact Checksum support"/>
+ </appInfo>
+ <documentation>
+ Provides a mapping from checksum algorithm id and &lt;code&gt;java.security.MessageDigest&lt;/code&gt; implementations.
+
+&lt;p&gt;p2 detects errors which may have been introduced during artifact transmission/storage by calculating artifact checksum using MD5 hash function. As a &lt;a href=&quot;https://en.wikipedia.org/wiki/Collision_attack&quot;&gt;collision attack&lt;/a&gt; and a &lt;a href=&quot;https://en.wikipedia.org/wiki/Chosen-prefix_collision_attack&quot;&gt;chosen-prefix collision attack&lt;/a&gt; against MD5 have been demonstrated in public, it can be used but only to detect unintentional corruption. Current implementation is not extensible and doesn&apos;t allow to use other, more collision-resistant, hash functions.&lt;/p&gt;
+
+&lt;p&gt;With this extension point, any &lt;code&gt;java.security.MessageDigest&lt;/code&gt; from Java Security API can be used to check integrity of artifacts. For more information on these APIs, see &lt;a href=&quot;https://docs.oracle.com/javase/8/docs/technotes/guides/security/crypto/CryptoSpec.html&quot;&gt;Java Cryptography Architecture (JCA) Reference Guide&lt;/a&gt;.&lt;/p&gt;
+ </documentation>
+ </annotation>
+
+ <element name="extension">
+ <annotation>
+ <appInfo>
+ <meta.element />
+ </appInfo>
+ </annotation>
+ <complexType>
+ <sequence>
+ <element ref="artifactChecksum" minOccurs="1" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="point" type="string" use="required">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+
+ </documentation>
+ <appInfo>
+ <meta.attribute translatable="true"/>
+ </appInfo>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <element name="artifactChecksum">
+ <complexType>
+ <attribute name="id" type="string" use="required">
+ <annotation>
+ <documentation>
+ id of the checksum algorithm, i.e. &lt;code&gt;sha-512&lt;/code&gt;.
+
+As other tools will rely on this id, consider using some well-defined value (i.e. &lt;a href=&quot;https://www.iana.org/assignments/hash-function-text-names/hash-function-text-names.xhtml&quot;&gt;Hash Function Textual Names&lt;/a&gt; ).
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="algorithm" type="string" use="required">
+ <annotation>
+ <documentation>
+ Name of the message digest algorithm as expected by &lt;code&gt;java.security.MessageDigest&lt;/code&gt;&apos;s method &lt;code&gt;getInstance(String)&lt;/code&gt;. Also check the MessageDigest section in the Java Cryptography Architecture Standard Algorithm Name Documentation for information about standard algorithm names.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="since"/>
+ </appInfo>
+ <documentation>
+ 2.4.0
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="examples"/>
+ </appInfo>
+ <documentation>
+ To enable support for MessageDigest implementation which is provided by a statically registered Provider, contributing bundle should only register an extension:
+
+&lt;pre&gt;
+&lt;extension point=&quot;org.eclipse.equinox.p2.artifact.repository.artifactChecksums&quot;&gt;
+ &lt;artifactChecksum
+ algorithm=&quot;SHA3-512&quot;
+ id=&quot;sha3-512&quot;&gt;
+ &lt;/artifactChecksum&gt;
+&lt;/extension&gt;
+&lt;/pre&gt;
+
+If the MessageDigest implementation is provided by a custom Provider (from the contributing bundle itself or some other bundle), it should be first dynamically registered:
+
+&lt;pre&gt;
+import java.security.Security;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+public class Activator implements BundleActivator {
+
+ public void start(BundleContext context) throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+ }
+}
+&lt;/pre&gt;
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="implementation"/>
+ </appInfo>
+ <documentation>
+ Contributes a checksum algorithm with id &lt;code&gt;sha-256&lt;code&gt; and maps it to &lt;code&gt;SHA-256&lt;/code&gt; MessageDigest implementation.
+ </documentation>
+ </annotation>
+
+ <annotation>
+ <appInfo>
+ <meta.section type="copyright"/>
+ </appInfo>
+ <documentation>
+ Copyright (c) 2015, 2018 Mykola Nikishov.
+
+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
+ </documentation>
+ </annotation>
+
+</schema>
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumUtilities.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumUtilities.java
index 38635d9f2..b7f9f04fb 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumUtilities.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumUtilities.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2018 Mykola Nikishov.
+ * Copyright (c) 2015, 2018 Mykola Nikishov.
* 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
@@ -10,21 +10,147 @@
*******************************************************************************/
package org.eclipse.equinox.internal.p2.artifact.processors.checksum;
-import java.util.ArrayList;
+import java.io.File;
+import java.io.IOException;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+import java.util.Map.Entry;
+import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.artifact.processors.md5.MD5Verifier;
+import org.eclipse.equinox.internal.p2.artifact.repository.Messages;
+import org.eclipse.equinox.internal.p2.repository.Activator;
+import org.eclipse.equinox.internal.p2.repository.helpers.ChecksumHelper;
+import org.eclipse.equinox.internal.p2.repository.helpers.ChecksumProducer;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStep;
import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
+import org.eclipse.osgi.util.NLS;
public class ChecksumUtilities {
+
+ private static final String ARTIFACT_CHECKSUMS_POINT = "org.eclipse.equinox.p2.artifact.repository.artifactChecksums"; //$NON-NLS-1$
+ public static final String MD5 = "md5"; //$NON-NLS-1$
+
+ /**
+ * Instances of checksum verifiers applicable for the artifact descriptor
+ *
+ * @param descriptor
+ * @param property either {@link IArtifactDescriptor#ARTIFACT_CHECKSUM} or {@link IArtifactDescriptor#DOWNLOAD_CHECKSUM}
+ * @param checksumsToSkip
+ * @return list of checksum verifiers
+ * @throws IllegalArgumentException if property neither {@link IArtifactDescriptor#ARTIFACT_CHECKSUM} nor {@link IArtifactDescriptor#DOWNLOAD_CHECKSUM}
+ * @see ChecksumHelper#getChecksums(IArtifactDescriptor, String)
+ */
+ public static Collection<ProcessingStep> getChecksumVerifiers(IArtifactDescriptor descriptor, String property, Set<String> checksumsToSkip) throws IllegalArgumentException {
+ Collection<ProcessingStep> steps = new ArrayList<>();
+ Map<String, String> checksums = ChecksumHelper.getChecksums(descriptor, property);
+
+ IConfigurationElement[] checksumVerifierConfigurations = getChecksumComparatorConfigurations();
+
+ for (Entry<String, String> checksumEntry : checksums.entrySet()) {
+ if (checksumsToSkip.contains(checksumEntry.getKey()))
+ continue;
+
+ for (IConfigurationElement checksumVerifierConfiguration : checksumVerifierConfigurations) {
+ String checksumId = checksumVerifierConfiguration.getAttribute("id"); //$NON-NLS-1$
+ if (checksumEntry.getKey().equals(checksumId)) {
+ String checksumAlgorithm = checksumVerifierConfiguration.getAttribute("algorithm"); //$NON-NLS-1$
+ ChecksumVerifier checksumVerifier = new ChecksumVerifier(checksumAlgorithm, checksumId, checksumEntry.getValue());
+ if (checksumVerifier.getStatus().isOK())
+ steps.add(checksumVerifier);
+ else
+ // TODO log something?
+ continue;
+ }
+ }
+ }
+
+ Optional<MD5Verifier> legacyMd5Verifier = getLegacyMd5Verifier(descriptor, property);
+ legacyMd5Verifier.ifPresent(verifier -> steps.add(verifier));
+
+ return steps;
+ }
+
+ public static IConfigurationElement[] getChecksumComparatorConfigurations() {
+ return RegistryFactory.getRegistry().getConfigurationElementsFor(ARTIFACT_CHECKSUMS_POINT);
+ }
+
/**
- * When enabled, extract property from the artifact descriptor, create instance of MD5Verifier and add it to steps.
- */
- public static void addChecksumVerificationStep(boolean enabled, String property, IArtifactDescriptor descriptor, ArrayList<ProcessingStep> steps) {
- if (enabled && descriptor.getProperty(property) != null) {
- MD5Verifier checksumVerifier = new MD5Verifier(descriptor.getProperty(property));
+ * Caller is responsible for checking the returned status and decide if problems are fatal or not.
+ *
+ * @param pathOnDisk file to calculate checksums for
+ * @param checksums calculated checksums
+ * @param checksumsToSkip
+ * @return status
+ */
+ public static IStatus calculateChecksums(File pathOnDisk, Map<String, String> checksums, Collection<String> checksumsToSkip) {
+ // TODO pathOnDisk.getAbsolutePath() || pathOnDisk.getCanonicalPath()
+ MultiStatus status = new MultiStatus(Activator.ID, IStatus.OK, NLS.bind(Messages.calculateChecksum_file, pathOnDisk.getAbsolutePath()), null);
+ for (IConfigurationElement checksumVerifierConfiguration : ChecksumUtilities.getChecksumComparatorConfigurations()) {
+ String id = checksumVerifierConfiguration.getAttribute("id"); //$NON-NLS-1$
+ if (checksumsToSkip.contains(id))
+ // don't calculate checksum if algo is disabled
+ continue;
+ String algorithm = checksumVerifierConfiguration.getAttribute("algorithm"); //$NON-NLS-1$
+ try {
+ String checksum = ChecksumProducer.produce(pathOnDisk, algorithm);
+ checksums.put(id, checksum);
+ String message = NLS.bind(Messages.calculateChecksum_ok, new Object[] {id, algorithm, checksum});
+ status.add(new Status(IStatus.OK, Activator.ID, message));
+ } catch (NoSuchAlgorithmException e) {
+ String message = NLS.bind(Messages.calculateChecksum_error, id, algorithm);
+ status.add(new Status(IStatus.ERROR, Activator.ID, message, e));
+ } catch (IOException e) {
+ String message = NLS.bind(Messages.calculateChecksum_error, id, algorithm);
+ status.add(new Status(IStatus.ERROR, Activator.ID, message, e));
+ }
+ }
+ return status;
+ }
+
+ /**
+ * @param property either {@link IArtifactDescriptor#ARTIFACT_CHECKSUM} or {@link IArtifactDescriptor#DOWNLOAD_CHECKSUM}
+ * @param checksums
+ */
+ public static Map<String, String> checksumsToProperties(String property, Map<String, String> checksums) {
+ HashMap<String, String> properties = new HashMap<>();
+ for (Entry<String, String> checksum : checksums.entrySet()) {
+ properties.put(String.join(".", property, checksum.getKey()), checksum.getValue()); //$NON-NLS-1$
+ }
+
+ putLegacyMd5Property(property, checksums, properties);
+
+ return properties;
+ }
+
+ private static Optional<MD5Verifier> getLegacyMd5Verifier(IArtifactDescriptor descriptor, String propertyNamespace) {
+ String md5 = null;
+ switch (propertyNamespace) {
+ case IArtifactDescriptor.ARTIFACT_CHECKSUM :
+ md5 = descriptor.getProperty(IArtifactDescriptor.ARTIFACT_MD5);
+ break;
+ case IArtifactDescriptor.DOWNLOAD_CHECKSUM :
+ md5 = descriptor.getProperty(IArtifactDescriptor.DOWNLOAD_MD5);
+ break;
+ default :
+ throw new IllegalArgumentException(propertyNamespace);
+ }
+
+ if (md5 != null) {
+ MD5Verifier checksumVerifier = new MD5Verifier(md5);
if (checksumVerifier.getStatus().isOK())
- steps.add(checksumVerifier);
+ return Optional.of(checksumVerifier);
}
+
+ return Optional.empty();
}
+ private static void putLegacyMd5Property(String propertyNamespace, Map<String, String> checksums, HashMap<String, String> result) {
+ String md5 = checksums.get(ChecksumUtilities.MD5);
+ if (md5 != null) {
+ if (IArtifactDescriptor.ARTIFACT_CHECKSUM.equals(propertyNamespace))
+ result.put(IArtifactDescriptor.ARTIFACT_MD5, md5);
+ if (IArtifactDescriptor.DOWNLOAD_CHECKSUM.equals(propertyNamespace))
+ result.put(IArtifactDescriptor.DOWNLOAD_MD5, md5);
+ }
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumVerifier.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumVerifier.java
new file mode 100644
index 000000000..2aa55ea9c
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/ChecksumVerifier.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2018 Mykola Nikishov.
+ * 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:
+ * Mykola Nikishov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.artifact.processors.checksum;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Optional;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
+import org.eclipse.equinox.internal.p2.repository.helpers.ChecksumHelper;
+import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStep;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.core.ProvisionException;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
+import org.eclipse.equinox.p2.repository.artifact.IProcessingStepDescriptor;
+import org.eclipse.osgi.util.NLS;
+
+final public class ChecksumVerifier extends ProcessingStep {
+
+ private String expectedChecksum;
+ private MessageDigest messageDigest;
+ private String algorithmName;
+ private String algorithmId;
+
+ // public to access from tests
+ public ChecksumVerifier(String digestAlgorithm, String algorithmId, String expectedChecksum) {
+ this.algorithmName = digestAlgorithm;
+ this.algorithmId = algorithmId;
+ this.expectedChecksum = expectedChecksum;
+ basicInitialize(null);
+ }
+
+ @Override
+ public final void initialize(IProvisioningAgent agent, IProcessingStepDescriptor descriptor, IArtifactDescriptor context) {
+ super.initialize(agent, descriptor, context);
+ String data = descriptor.getData();
+ if (IArtifactDescriptor.DOWNLOAD_CHECKSUM.concat(".").concat(algorithmId).equals(data)) //$NON-NLS-1$
+ expectedChecksum = ChecksumHelper.getChecksums(context, IArtifactDescriptor.DOWNLOAD_CHECKSUM).get(algorithmId);
+ else if (IArtifactDescriptor.ARTIFACT_CHECKSUM.concat(".").concat(algorithmId).equals(data)) //$NON-NLS-1$
+ expectedChecksum = ChecksumHelper.getChecksums(context, IArtifactDescriptor.ARTIFACT_CHECKSUM).get(algorithmId);
+ else
+ expectedChecksum = data;
+
+ basicInitialize(descriptor);
+ }
+
+ private void basicInitialize(IProcessingStepDescriptor descriptor) {
+ int code = (descriptor == null) ? IStatus.ERROR : descriptor.isRequired() ? IStatus.ERROR : IStatus.INFO;
+ if (Optional.ofNullable(expectedChecksum).orElse("").isEmpty()) //$NON-NLS-1$
+ setStatus(new Status(code, Activator.ID, NLS.bind(Messages.Error_invalid_checksum, algorithmName, expectedChecksum)));
+ try {
+ messageDigest = MessageDigest.getInstance(algorithmName);
+ } catch (NoSuchAlgorithmException e) {
+ setStatus(new Status(code, Activator.ID, NLS.bind(Messages.Error_checksum_unavailable, algorithmName), e));
+ }
+ }
+
+ @Override
+ final public void write(int b) throws IOException {
+ messageDigest.update((byte) b);
+ getDestination().write(b);
+ }
+
+ @Override
+ final public void close() throws IOException {
+ byte[] hashBytes = messageDigest.digest();
+ String hash = ChecksumHelper.toHexString(hashBytes);
+
+ // if the hashes don't line up set the status to error.
+ if (!hash.equals(expectedChecksum))
+ // TODO like ProvisionException.ARTIFACT_MD5_NOT_MATCH but for any checksum
+ setStatus(new Status(IStatus.ERROR, Activator.ID, ProvisionException.ARTIFACT_MD5_NOT_MATCH, NLS.bind(Messages.Error_unexpected_checksum, new Object[] {algorithmName, expectedChecksum, hash}), null));
+ super.close();
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/Messages.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/Messages.java
new file mode 100644
index 000000000..4d48550a4
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/Messages.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2018 Mykola Nikishov.
+ * 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:
+ * Mykola Nikishov - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.equinox.internal.p2.artifact.processors.checksum;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+ private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.p2.artifact.processors.checksum.messages"; //$NON-NLS-1$
+
+ public static String Error_invalid_checksum;
+ public static String Error_checksum_unavailable;
+ public static String Error_unexpected_checksum;
+
+ static {
+ // initialize resource bundle
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+ private Messages() {
+ //empty
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/messages.properties b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/messages.properties
new file mode 100644
index 000000000..1281c9061
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/checksum/messages.properties
@@ -0,0 +1,14 @@
+###############################################################################
+# Copyright (c) 2015, 2018 Mykola Nikishov.
+# 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:
+# Mykola Nikishov - initial API and implementation
+###############################################################################
+
+Error_invalid_checksum={0} value not available or incorrect size, {1}.
+Error_checksum_unavailable=Could not create {0} algorithm.
+Error_unexpected_checksum={0} hash is not as expected. Expected: {1} and found {2}.
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/md5/MD5Verifier.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/md5/MD5Verifier.java
index f152b9997..50d2ff0d3 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/md5/MD5Verifier.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors/md5/MD5Verifier.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2017 compeople AG and others.
+ * Copyright (c) 2007, 2018 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
@@ -17,6 +17,7 @@ import java.security.NoSuchAlgorithmException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
+import org.eclipse.equinox.internal.p2.repository.helpers.ChecksumHelper;
import org.eclipse.equinox.internal.provisional.p2.artifact.repository.processing.ProcessingStep;
import org.eclipse.equinox.p2.core.IProvisioningAgent;
import org.eclipse.equinox.p2.core.ProvisionException;
@@ -24,6 +25,7 @@ import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
import org.eclipse.equinox.p2.repository.artifact.IProcessingStepDescriptor;
import org.eclipse.osgi.util.NLS;
+@Deprecated
public class MD5Verifier extends ProcessingStep {
protected String expectedMD5;
@@ -73,15 +75,10 @@ public class MD5Verifier extends ProcessingStep {
@Override
public void close() throws IOException {
byte[] digest = md5.digest();
- StringBuilder buf = new StringBuilder();
- for (byte element : digest) {
- if ((element & 0xFF) < 0x10)
- buf.append('0');
- buf.append(Integer.toHexString(element & 0xFF));
- }
+ String buf = ChecksumHelper.toHexString(digest);
// if the hashes don't line up set the status to error.
- if (!buf.toString().equals(expectedMD5))
+ if (!buf.equals(expectedMD5))
setStatus(new Status(IStatus.ERROR, Activator.ID, ProvisionException.ARTIFACT_MD5_NOT_MATCH, NLS.bind(Messages.Error_unexpected_hash, expectedMD5, buf), null));
super.close();
}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/Messages.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/Messages.java
index 4588cec90..e6a4a4091 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/Messages.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others.
+ * Copyright (c) 2007, 2018 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
@@ -64,6 +64,10 @@ public class Messages extends NLS {
public static String error_copying_local_file;
+ public static String calculateChecksum_file;
+ public static String calculateChecksum_ok;
+ public static String calculateChecksum_error;
+
static {
// initialize resource bundles
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/RawMirrorRequest.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/RawMirrorRequest.java
index 0e992ba84..cfe61e2dc 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/RawMirrorRequest.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/RawMirrorRequest.java
@@ -13,7 +13,8 @@
package org.eclipse.equinox.internal.p2.artifact.repository;
import java.io.OutputStream;
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
import org.eclipse.core.runtime.*;
import org.eclipse.equinox.internal.p2.artifact.processors.checksum.ChecksumUtilities;
import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
@@ -81,15 +82,15 @@ public class RawMirrorRequest extends MirrorRequest {
// Perform the mirror operation without any processing steps
@Override
protected IStatus getArtifact(IArtifactDescriptor artifactDescriptor, OutputStream destination, IProgressMonitor monitor) {
- ArrayList<ProcessingStep> steps = new ArrayList<>();
- ChecksumUtilities.addChecksumVerificationStep(SimpleArtifactRepository.DOWNLOAD_MD5_CHECKSUM_ENABLED, IArtifactDescriptor.DOWNLOAD_MD5, artifactDescriptor, steps);
- if (!steps.isEmpty()) {
+ if (SimpleArtifactRepository.CHECKSUMS_ENABLED) {
+ Collection<ProcessingStep> steps = ChecksumUtilities.getChecksumVerifiers(artifactDescriptor, IArtifactDescriptor.DOWNLOAD_CHECKSUM, Collections.<String> emptySet());
ProcessingStep[] stepArray = steps.toArray(new ProcessingStep[steps.size()]);
// TODO should probably be using createAndLink here
ProcessingStepHandler handler = new ProcessingStepHandler();
destination = handler.link(stepArray, destination, monitor);
}
+
return getSourceRepository().getRawArtifact(artifactDescriptor, destination, monitor);
}
}
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/messages.properties b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/messages.properties
index ada52de67..65c781144 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2007, 2010 IBM Corporation and others.
+# Copyright (c) 2007, 2018 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
@@ -51,6 +51,10 @@ exception_unsupportedAddToComposite = Cannot add descriptors to a composite repo
exception_unsupportedGetOutputStream=Cannot write artifacts to a composite repository.
exception_unsupportedRemoveFromComposite = Cannot remove descriptors from a composite repository.
+calculateChecksum_file=Calculating checksums for file {0}.
+calculateChecksum_ok=Calculated checksum using id={0} algorithm={1}: {2}.
+calculateChecksum_error=Error calculating checksum using id={0} algorithm={1}.
+
exception_unableToCreateParentDir = Unable to create parent directory.
folder_artifact_not_file_repo=Artifact {0} is a folder but the repository is an archive or remote location.
retryRequest=Download of {0} failed on repository {1}. Retrying.
diff --git a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
index 4dfdbb9ed..efdfca82b 100644
--- a/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
+++ b/bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/repository/simple/SimpleArtifactRepository.java
@@ -12,6 +12,7 @@
* Sonatype Inc - ongoing development
* EclipseSource - file locking and ongoing development
* Red Hat Inc. - Fix compiler problems from generified IAdaptable#getAdapter
+ * Mykola Nikishov - multiple artifact checksums
*******************************************************************************/
package org.eclipse.equinox.internal.p2.artifact.repository.simple;
@@ -55,8 +56,18 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
public static final boolean MIRRORS_ENABLED = !"false".equals(Activator.getContext().getProperty("eclipse.p2.mirrors")); //$NON-NLS-1$//$NON-NLS-2$
/**
+ * A boolean property controlling whether any checksums of the artifact should be checked.
+ * @see IArtifactDescriptor#DOWNLOAD_MD5
+ * @see IArtifactDescriptor#DOWNLOAD_CHECKSUM
+ * @see IArtifactDescriptor#ARTIFACT_MD5
+ * @see IArtifactDescriptor#ARTIFACT_CHECKSUM
+ */
+ public static final boolean CHECKSUMS_ENABLED = !"true".equals(Activator.getContext().getProperty("eclipse.p2.checksums.disable")); //$NON-NLS-1$//$NON-NLS-2$
+
+ /**
* A boolean property controlling whether MD5 checksum of the artifact bytes that are transferred should be checked.
* @see IArtifactDescriptor#DOWNLOAD_MD5
+ * @see IArtifactDescriptor#DOWNLOAD_CHECKSUM
*/
public static final boolean DOWNLOAD_MD5_CHECKSUM_ENABLED = !"false".equals(Activator.getContext().getProperty("eclipse.p2.MD5Check")); //$NON-NLS-1$//$NON-NLS-2$
@@ -64,6 +75,7 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
* A boolean property controlling whether MD5 checksum of the artifact bytes in its native format (after processing steps have
* been applied) should be checked.
* @see IArtifactDescriptor#ARTIFACT_MD5
+ * @see IArtifactDescriptor#ARTIFACT_CHECKSUM
*/
public static final boolean ARTIFACT_MD5_CHECKSUM_ENABLED = !"false".equals(Activator.getContext().getProperty("eclipse.p2.MD5ArtifactCheck")); //$NON-NLS-1$//$NON-NLS-2$
@@ -459,7 +471,9 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
private synchronized OutputStream addPostSteps(ProcessingStepHandler handler, IArtifactDescriptor descriptor, OutputStream destination, IProgressMonitor monitor) {
ArrayList<ProcessingStep> steps = new ArrayList<>();
steps.add(new SignatureVerifier());
- ChecksumUtilities.addChecksumVerificationStep(ARTIFACT_MD5_CHECKSUM_ENABLED, IArtifactDescriptor.ARTIFACT_MD5, descriptor, steps);
+
+ Set<String> skipChecksums = ARTIFACT_MD5_CHECKSUM_ENABLED ? Collections.emptySet() : Collections.singleton(ChecksumUtilities.MD5);
+ addChecksumVerifiers(descriptor, steps, skipChecksums, IArtifactDescriptor.ARTIFACT_CHECKSUM);
if (steps.isEmpty())
return destination;
@@ -472,7 +486,9 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
ArrayList<ProcessingStep> steps = new ArrayList<>();
if (IArtifactDescriptor.TYPE_ZIP.equals(descriptor.getProperty(IArtifactDescriptor.DOWNLOAD_CONTENTTYPE)))
steps.add(new ZipVerifierStep());
- ChecksumUtilities.addChecksumVerificationStep(DOWNLOAD_MD5_CHECKSUM_ENABLED, IArtifactDescriptor.DOWNLOAD_MD5, descriptor, steps);
+
+ Set<String> skipChecksums = DOWNLOAD_MD5_CHECKSUM_ENABLED ? Collections.emptySet() : Collections.singleton(ChecksumUtilities.MD5);
+ addChecksumVerifiers(descriptor, steps, skipChecksums, IArtifactDescriptor.DOWNLOAD_CHECKSUM);
// Add steps here if needed
if (steps.isEmpty())
@@ -482,6 +498,13 @@ public class SimpleArtifactRepository extends AbstractArtifactRepository impleme
return handler.link(stepArray, destination, monitor);
}
+ private void addChecksumVerifiers(IArtifactDescriptor descriptor, ArrayList<ProcessingStep> steps, Set<String> skipChecksums, String property) {
+ if (CHECKSUMS_ENABLED) {
+ Collection<ProcessingStep> checksumVerifiers = ChecksumUtilities.getChecksumVerifiers(descriptor, property, skipChecksums);
+ steps.addAll(checksumVerifiers);
+ }
+ }
+
private byte[] bytesFromHexString(String string) {
byte[] bytes = new byte[UniversalUniqueIdentifier.BYTES_SIZE];
for (int i = 0; i < string.length(); i += 2) {
diff --git a/bundles/org.eclipse.equinox.p2.publisher/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.publisher/META-INF/MANIFEST.MF
index e6f90ca50..f8a5e5464 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.publisher/META-INF/MANIFEST.MF
@@ -29,6 +29,7 @@ Require-Bundle: org.eclipse.equinox.common;bundle-version="[3.5.0,4.0.0)",
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Import-Package: org.eclipse.equinox.app;version="1.0.0";resolution:=optional,
+ org.eclipse.equinox.internal.p2.artifact.processors.checksum,
org.eclipse.equinox.internal.p2.artifact.repository,
org.eclipse.equinox.internal.p2.artifact.repository.simple,
org.eclipse.equinox.internal.p2.core.helpers,
diff --git a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/spi/p2/publisher/PublisherHelper.java b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/spi/p2/publisher/PublisherHelper.java
index 8fc15de68..5c9186ea8 100644
--- a/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/spi/p2/publisher/PublisherHelper.java
+++ b/bundles/org.eclipse.equinox.p2.publisher/src/org/eclipse/equinox/spi/p2/publisher/PublisherHelper.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2017 IBM Corporation and others.
+ * Copyright (c) 2007, 2018 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
@@ -10,7 +10,7 @@
* Genuitec, LLC - added license support
* Code 9 - Ongoing development
* SAP AG - consolidation of publishers for PDE formats
- * Mykola Nikishov - extract MD5 checksum calculation
+ * Mykola Nikishov - multiple artifact checksums
*******************************************************************************/
package org.eclipse.equinox.spi.p2.publisher;
@@ -19,6 +19,7 @@ import java.io.IOException;
import java.util.*;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.p2.artifact.processors.checksum.ChecksumUtilities;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
import org.eclipse.equinox.internal.p2.metadata.BasicVersion;
@@ -111,22 +112,42 @@ public class PublisherHelper {
ArtifactDescriptor descriptor = (ArtifactDescriptor) result;
descriptor.setProperty(IArtifactDescriptor.ARTIFACT_SIZE, Long.toString(pathOnDisk.length()));
descriptor.setProperty(IArtifactDescriptor.DOWNLOAD_SIZE, Long.toString(pathOnDisk.length()));
- if (info == null || (info.getArtifactOptions() & IPublisherInfo.A_NO_MD5) == 0) {
- try {
- String md5 = ChecksumProducer.computeMD5(pathOnDisk);
- if (md5 != null)
- descriptor.setProperty(IArtifactDescriptor.DOWNLOAD_MD5, md5);
- } catch (IOException e) {
- // don't care if failed to compute checksum
- // TODO provide message?
- LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "", e)); //$NON-NLS-1$
- }
+
+ boolean generateChecksums = info == null || (info.getArtifactOptions() & IPublisherInfo.A_NO_MD5) == 0;
+ if (generateChecksums) {
+ calculateLegacyMd5(pathOnDisk, descriptor);
+ calculateChecksums(pathOnDisk, descriptor);
}
}
}
return result;
}
+ private static void calculateLegacyMd5(File pathOnDisk, ArtifactDescriptor descriptor) {
+ try {
+ String md5 = ChecksumProducer.computeMD5(pathOnDisk);
+ if (md5 != null)
+ descriptor.setProperty(IArtifactDescriptor.DOWNLOAD_MD5, md5);
+ } catch (IOException e) {
+ // don't care if failed to compute checksum
+ // TODO provide message?
+ LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "", e)); //$NON-NLS-1$
+ }
+ }
+
+ private static void calculateChecksums(File pathOnDisk, ArtifactDescriptor descriptor) {
+ // TODO disable specific algorithms
+ List<String> checksumsToSkip = Collections.<String> emptyList();
+ Map<String, String> checksums = new HashMap<>();
+ IStatus status = ChecksumUtilities.calculateChecksums(pathOnDisk, checksums, checksumsToSkip);
+ if (!status.isOK()) {
+ // TODO handle errors in some way
+ LogHelper.log(status);
+ }
+ Map<String, String> checksumProperties = ChecksumUtilities.checksumsToProperties(IArtifactDescriptor.DOWNLOAD_CHECKSUM, checksums);
+ descriptor.addProperties(checksumProperties);
+ }
+
public static IProvidedCapability makeTranslationCapability(String hostId, Locale locale) {
return MetadataFactory.createProvidedCapability(NAMESPACE_IU_LOCALIZATION, locale.toString(), Version.createOSGi(1, 0, 0));
}
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.repository.tools/META-INF/MANIFEST.MF
index fd0759bc8..88e69664e 100644
--- a/bundles/org.eclipse.equinox.p2.repository.tools/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/META-INF/MANIFEST.MF
@@ -19,6 +19,7 @@ Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ActivationPolicy: lazy
Import-Package: org.eclipse.equinox.app;version="1.0.0",
org.eclipse.equinox.frameworkadmin;version="2.0.0",
+ org.eclipse.equinox.internal.p2.artifact.processors.checksum,
org.eclipse.equinox.internal.p2.artifact.repository,
org.eclipse.equinox.internal.p2.artifact.repository.simple,
org.eclipse.equinox.internal.p2.core.helpers,
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/plugin.xml b/bundles/org.eclipse.equinox.p2.repository.tools/plugin.xml
index f48caf239..09c381b47 100644
--- a/bundles/org.eclipse.equinox.p2.repository.tools/plugin.xml
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/plugin.xml
@@ -125,6 +125,12 @@
</extension>
<extension point="org.eclipse.equinox.p2.artifact.repository.artifactComparators">
<artifactComparator
+ class="org.eclipse.equinox.p2.internal.repository.comparator.ArtifactChecksumComparator"
+ id="org.eclipse.equinox.artifact.comparator.checksum">
+ </artifactComparator>
+ </extension>
+ <extension point="org.eclipse.equinox.p2.artifact.repository.artifactComparators">
+ <artifactComparator
class="org.eclipse.equinox.p2.internal.repository.comparator.JarComparator"
id="org.eclipse.equinox.p2.repository.tools.jar.comparator">
</artifactComparator>
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/ArtifactChecksumComparator.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/ArtifactChecksumComparator.java
new file mode 100644
index 000000000..0c156e0cb
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/ArtifactChecksumComparator.java
@@ -0,0 +1,62 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2018 Mykola Nikishov.
+ * 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:
+ * Mykola Nikishov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.internal.repository.comparator;
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.artifact.repository.Activator;
+import org.eclipse.equinox.internal.p2.repository.helpers.ChecksumHelper;
+import org.eclipse.equinox.p2.internal.repository.tools.Messages;
+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;
+
+/**
+ * A comparator that compares two artifacts by checking the checksum
+ * recorded in the artifact descriptor. This comparator doesn't actually compute
+ * checksums directly.
+ */
+final public class ArtifactChecksumComparator implements IArtifactComparator {
+ final public static String COMPARATOR_ID = "org.eclipse.equinox.artifact.comparator.checksum"; //$NON-NLS-1$
+
+ final private String name;
+ final private String id;
+
+ /**
+ * @param checksumId
+ * @param checksumName human-readable name of the checksum algorithm
+ */
+ public ArtifactChecksumComparator(String checksumId, String checksumName) {
+ this.name = checksumName;
+ this.id = checksumId;
+ }
+
+ @Override
+ final public IStatus compare(IArtifactRepository source, IArtifactDescriptor sourceDescriptor, IArtifactRepository destination, IArtifactDescriptor destDescriptor) {
+ String sourceChecksum = ChecksumHelper.getChecksums(sourceDescriptor, IArtifactDescriptor.DOWNLOAD_CHECKSUM).get(id);
+ String destChecksum = ChecksumHelper.getChecksums(destDescriptor, IArtifactDescriptor.DOWNLOAD_CHECKSUM).get(id);
+
+ if (sourceChecksum == null && destChecksum == null)
+ return new Status(IStatus.INFO, Activator.ID, NLS.bind(Messages.info_noChecksumInfomation, name, sourceDescriptor));
+
+ if (sourceChecksum == null)
+ return new Status(IStatus.INFO, Activator.ID, NLS.bind(Messages.info_noChecksumInRepository, new Object[] {source, name, sourceDescriptor}));
+
+ if (destChecksum == null)
+ return new Status(IStatus.INFO, Activator.ID, NLS.bind(Messages.info_noChecksumInRepository, new Object[] {destination, name, destDescriptor}));
+
+ if (sourceChecksum.equals(destChecksum))
+ return Status.OK_STATUS;
+
+ return new Status(IStatus.WARNING, Activator.ID, NLS.bind(Messages.warning_different_checksum, new Object[] {URIUtil.toUnencodedString(sourceDescriptor.getRepository().getLocation()), URIUtil.toUnencodedString(destDescriptor.getRepository().getLocation()), name, sourceDescriptor}));
+ }
+
+}
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/MD5ArtifactComparator.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/MD5ArtifactComparator.java
index a83e931f3..dc0ee1c73 100644
--- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/MD5ArtifactComparator.java
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/comparator/MD5ArtifactComparator.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2017 IBM Corporation and others.
+ * Copyright (c) 2008, 2018 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
@@ -23,7 +23,14 @@ import org.eclipse.osgi.util.NLS;
* A comparator that compares two artifacts by checking the MD5 checksum
* recorded in the artifact descriptor. This comparator doesn't actually compute MD5
* checksums directly.
+ *
+ * @deprecated
+ * @noreference
+ * @noextend
+ * @noinstantiate
+ * @see ArtifactChecksumComparator
*/
+@Deprecated
public class MD5ArtifactComparator implements IArtifactComparator {
public static String MD5_COMPARATOR_ID = "org.eclipse.equinox.artifact.md5.comparator"; //$NON-NLS-1$
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/Messages.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/Messages.java
index 47cc723c1..648cd795f 100644
--- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/Messages.java
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/Messages.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2010 IBM Corporation and others.
+ * Copyright (c) 2009, 2018 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
@@ -67,6 +67,10 @@ public class Messages extends NLS {
public static String info_noMD5InRepository;
public static String warning_differentMD5;
+ public static String info_noChecksumInfomation;
+ public static String info_noChecksumInRepository;
+ public static String warning_different_checksum;
+
static {
// initialize resource bundles
NLS.initializeMessages(BUNDLE_NAME, Messages.class);
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/RecreateRepositoryApplication.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/RecreateRepositoryApplication.java
index 0c56617b9..a56fdb73d 100644
--- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/RecreateRepositoryApplication.java
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/RecreateRepositoryApplication.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2017 IBM Corporation and others.
+ * Copyright (c) 2009, 2018 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
@@ -8,18 +8,18 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Sonatype Inc - ongoing development
+ * Mykola Nikishov - multiple artifact checksums
*******************************************************************************/
package org.eclipse.equinox.p2.internal.repository.tools;
import java.io.File;
-import java.io.IOException;
import java.net.URI;
import java.util.*;
import org.eclipse.core.runtime.*;
+import org.eclipse.equinox.internal.p2.artifact.processors.checksum.ChecksumUtilities;
import org.eclipse.equinox.internal.p2.artifact.repository.simple.SimpleArtifactRepository;
import org.eclipse.equinox.internal.p2.core.helpers.LogHelper;
-import org.eclipse.equinox.internal.p2.repository.helpers.ChecksumProducer;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.equinox.p2.metadata.IArtifactKey;
import org.eclipse.equinox.p2.query.IQueryResult;
@@ -31,6 +31,7 @@ import org.eclipse.equinox.p2.repository.artifact.spi.ProcessingStepDescriptor;
import org.eclipse.osgi.util.NLS;
public class RecreateRepositoryApplication extends AbstractApplication {
+ private static final String MD5_CHECKSUM_ID = "md5"; //$NON-NLS-1$
static final private String PUBLISH_PACK_FILES_AS_SIBLINGS = "publishPackFilesAsSiblings"; //$NON-NLS-1$
private URI repoLocation;
private String repoName = null;
@@ -121,15 +122,18 @@ public class RecreateRepositoryApplication extends AbstractApplication {
newDescriptor.setProperty(IArtifactDescriptor.ARTIFACT_SIZE, size);
newDescriptor.setProperty(IArtifactDescriptor.DOWNLOAD_SIZE, size);
- try {
- String md5 = ChecksumProducer.computeMD5(artifactFile);
- if (md5 != null)
- newDescriptor.setProperty(IArtifactDescriptor.DOWNLOAD_MD5, md5);
- } catch (IOException e) {
- // don't care if failed to compute checksum
- // TODO provide message?
- LogHelper.log(new Status(IStatus.WARNING, Activator.ID, "", e));
- }
+ Map<String, String> checksums = new HashMap<>();
+ IStatus status = ChecksumUtilities.calculateChecksums(artifactFile, checksums, Collections.emptyList());
+ if (!status.isOK())
+ // TODO handle errors in some way
+ LogHelper.log(status);
+
+ String md5 = checksums.get(MD5_CHECKSUM_ID);
+ if (md5 != null)
+ // preserve legacy MD5 checksum location
+ newDescriptor.setProperty(IArtifactDescriptor.DOWNLOAD_MD5, md5);
+
+ newDescriptor.addProperties(ChecksumUtilities.checksumsToProperties(IArtifactDescriptor.DOWNLOAD_CHECKSUM, checksums));
File temp = new File(artifactFile.getParentFile(), artifactFile.getName() + ".pack.gz"); //$NON-NLS-1$
if (temp.exists()) {
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/messages.properties b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/messages.properties
index aef9767a3..097b86b86 100644
--- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/messages.properties
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/internal/repository/tools/messages.properties
@@ -1,5 +1,5 @@
###############################################################################
-# Copyright (c) 2009, 2010 IBM Corporation and others.
+# Copyright (c) 2009, 2018 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
@@ -15,9 +15,9 @@ CompositeRepository_composite_repository_exists=Composite repository already exi
CompositeRepository_default_artifactRepo_name=Composite Artifact Repository
CompositeRepository_default_metadataRepo_name=Composite Artifact Repository
-info_noMD5Infomation=No MD5 information available for the artifact [{0}].
-info_noMD5InRepository=The repository {0} does not contain MD5 information for artifact [{1}].
-warning_differentMD5=The repositories {0} and {1} have different MD5 sums for the artifact [{2}].
+info_noChecksumInfomation=No {0} information available for the artifact [{1}].
+info_noChecksumInRepository=The repository {0} does not contain {1} information for artifact [{2}].
+warning_different_checksum=The repositories {0} and {1} have different MessageDigest={2} sums for the artifact [{3}].
no_artifactRepo_manager=Unable to acquire artifact repository manager service.
no_metadataRepo_manager=Unable to acquire metadata repository manager service.
diff --git a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/repository/tools/comparator/ArtifactComparatorFactory.java b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/repository/tools/comparator/ArtifactComparatorFactory.java
index 68a249bbc..47074aca1 100644
--- a/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/repository/tools/comparator/ArtifactComparatorFactory.java
+++ b/bundles/org.eclipse.equinox.p2.repository.tools/src/org/eclipse/equinox/p2/repository/tools/comparator/ArtifactComparatorFactory.java
@@ -8,14 +8,17 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Compeople AG (Stefan Liebig) - various ongoing maintenance
- * Mykola Nikishov - maintenance and documentation
+ * Mykola Nikishov - multiple artifact checksums
*******************************************************************************/
package org.eclipse.equinox.p2.repository.tools.comparator;
-import java.util.*;
+import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.RegistryFactory;
+import org.eclipse.equinox.internal.p2.artifact.processors.checksum.ChecksumUtilities;
import org.eclipse.equinox.internal.p2.artifact.repository.Messages;
import org.eclipse.equinox.p2.internal.repository.comparator.*;
import org.eclipse.osgi.util.NLS;
@@ -35,20 +38,43 @@ public class ArtifactComparatorFactory {
* <li><code>org.eclipse.equinox.artifact.md5.comparator</code> for {@link MD5ArtifactComparator}</li>
* </ul>
*
+ * For {@link ArtifactChecksumComparator}, there is no static id that could be used directly. Instead, its extension point id <code>org.eclipse.equinox.artifact.comparator.checksum</code> should be concatenated with id of desired checksum algorithm:
+ * <ul>
+ * <li><code>org.eclipse.equinox.artifact.comparator.checksum.sha-256</code> to use artifact checksum comparator with SHA-256 message digest</li>
+ * <li><code>org.eclipse.equinox.artifact.comparator.checksum.tiger</code> to use Tiger message digest</li>
+ * </ul>
+ *
* @param comparatorID id of the extension contributed to <code>org.eclipse.equinox.p2.artifact.repository.artifactComparators</code> extension point
* @return if found, instance of artifact comparator
* @throws {@link IllegalArgumentException} otherwise
*/
public static IArtifactComparator getArtifactComparator(String comparatorID) {
- List<IConfigurationElement> extensions = Arrays.asList(RegistryFactory.getRegistry().getConfigurationElementsFor(COMPARATOR_POINT));
+ List<IConfigurationElement> extensions = Stream.of(RegistryFactory.getRegistry().getConfigurationElementsFor(COMPARATOR_POINT))
+ .collect(Collectors.toList());
+ // exclude artifact checksum comparator, needs special care
+ extensions.removeIf(extension -> extension.getAttribute(ATTR_ID).equals(ArtifactChecksumComparator.COMPARATOR_ID));
- Optional<IArtifactComparator> artifactComparator = findComparatorConfiguration(comparatorID, extensions).map(ArtifactComparatorFactory::createArtifactComparator);
+ // handle generic artifact comparators
+ Optional<IArtifactComparator> artifactComparator = findComparatorConfiguration(comparatorID, extensions)
+ .map(ArtifactComparatorFactory::createArtifactComparator);
if (artifactComparator.isPresent())
return artifactComparator.get();
+ // handle artifact checksum comparator
+ if (comparatorID != null && comparatorID.startsWith(ArtifactChecksumComparator.COMPARATOR_ID)) {
+ Optional<ArtifactChecksumComparator> checksumComparator = getChecksumComparator(comparatorID);
+ if (checksumComparator.isPresent())
+ return checksumComparator.get();
+ }
+
if (comparatorID != null) {
- String comparators = extensions.stream().map(extension -> extension.getAttribute(ATTR_ID)).collect(Collectors.joining(", ")); //$NON-NLS-1$
- throw new IllegalArgumentException(NLS.bind(Messages.exception_comparatorNotFound, comparatorID, comparators));
+ Stream<String> checksumComparators = Stream.of(ChecksumUtilities.getChecksumComparatorConfigurations())
+ .map(element -> element.getAttribute(CHECKSUM_ID))
+ .map(checksumId -> ArtifactChecksumComparator.COMPARATOR_ID.concat(".").concat(checksumId)); //$NON-NLS-1$
+ Stream<String> comparators = extensions.stream()
+ .map(extension -> extension.getAttribute(ATTR_ID));
+ String availableComparators = Stream.concat(comparators, checksumComparators).collect(Collectors.joining(", ")); //$NON-NLS-1$
+ throw new IllegalArgumentException(NLS.bind(Messages.exception_comparatorNotFound, comparatorID, availableComparators));
}
throw new IllegalArgumentException(Messages.exception_noComparators);
}
@@ -71,4 +97,29 @@ public class ArtifactComparatorFactory {
}
return null;
}
+
+ private static final String CHECKSUM_ID = "id"; //$NON-NLS-1$
+ private static final String CHECKSUM_ALGORITHM = "algorithm"; //$NON-NLS-1$
+
+ private static Optional<ArtifactChecksumComparator> getChecksumComparator(String comparatorId) {
+ boolean hasNoChecksumId = !comparatorId.startsWith(ArtifactChecksumComparator.COMPARATOR_ID.concat(".")); //$NON-NLS-1$
+ if (hasNoChecksumId)
+ return Optional.empty();
+
+ String comparatorChecksum = Optional.ofNullable(comparatorId.substring(ArtifactChecksumComparator.COMPARATOR_ID.length() + 1))
+ .orElse(""); //$NON-NLS-1$
+ if (comparatorChecksum.isEmpty())
+ return Optional.empty();
+
+ IConfigurationElement[] comparatorConfigurations = ChecksumUtilities.getChecksumComparatorConfigurations();
+ Optional<IConfigurationElement> comparator = Stream.of(comparatorConfigurations)
+ .filter(config -> config.getAttribute(CHECKSUM_ID).equals(comparatorChecksum))
+ .findAny();
+
+ return comparator.map(c -> {
+ String checksumName = c.getAttribute(CHECKSUM_ALGORITHM);
+ String checksumId = c.getAttribute(CHECKSUM_ID);
+ return Optional.of(new ArtifactChecksumComparator(checksumId, checksumName));
+ }).orElse(Optional.empty());
+ }
}
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumHelper.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumHelper.java
new file mode 100644
index 000000000..f87747535
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumHelper.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2018 Mykola Nikishov
+ * 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:
+ * Mykola Nikishov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.internal.p2.repository.helpers;
+
+import java.util.*;
+import java.util.Map.Entry;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
+
+public class ChecksumHelper {
+
+ private static final String MD5 = "md5"; //$NON-NLS-1$
+
+ /**
+ * @param property either {@link IArtifactDescriptor#ARTIFACT_CHECKSUM} or {@link IArtifactDescriptor#DOWNLOAD_CHECKSUM}
+ * @return (mutable) map of <algorithm,checksum>
+ * @throws IllegalArgumentException if checksum property neither {@link IArtifactDescriptor#ARTIFACT_CHECKSUM} nor {@link IArtifactDescriptor#DOWNLOAD_CHECKSUM}
+ */
+ static public Map<String, String> getChecksums(IArtifactDescriptor descriptor, String property) throws IllegalArgumentException {
+ if (!IArtifactDescriptor.ARTIFACT_CHECKSUM.equals(property) && !IArtifactDescriptor.DOWNLOAD_CHECKSUM.equals(property))
+ // TODO provide more details
+ throw new IllegalArgumentException();
+
+ Map<String, String> checksumsByAlgo = new HashMap<>();
+
+ String md5Checksum = getLegacyMd5Checksum(descriptor, property);
+ if (md5Checksum != null) {
+ checksumsByAlgo.put(MD5, md5Checksum);
+ }
+
+ // get checksum properties
+ for (Entry<String, String> p : descriptor.getProperties().entrySet()) {
+ String key = p.getKey();
+ if (key.startsWith(property)) {
+ String checksumAlgorithmId = key // "artifact.checksum.sha3"
+ .substring(property.length()) // ".sha3"
+ .substring(1); // "sha3"
+ String checksumValue = Objects.requireNonNull(p.getValue());
+ String duplicatedChecksum = checksumsByAlgo.put(checksumAlgorithmId, checksumValue);
+ if (duplicatedChecksum != null)
+ // should never happen - duplicated checksum
+ ;
+ }
+ }
+
+ return checksumsByAlgo;
+ }
+
+ /**
+ * @return MD5 checksum from legacy property, either {@link IArtifactDescriptor#DOWNLOAD_MD5} or {@link IArtifactDescriptor#ARTIFACT_MD5}
+ */
+ private static String getLegacyMd5Checksum(IArtifactDescriptor descriptor, String property) {
+ switch (property) {
+ case IArtifactDescriptor.ARTIFACT_CHECKSUM :
+ return descriptor.getProperty(IArtifactDescriptor.ARTIFACT_MD5);
+ case IArtifactDescriptor.DOWNLOAD_CHECKSUM :
+ return descriptor.getProperty(IArtifactDescriptor.DOWNLOAD_MD5);
+ default :
+ return null;
+ }
+ }
+
+ public static String toHexString(byte[] digest) {
+ StringBuilder buf = new StringBuilder();
+ for (byte element : digest) {
+ if ((element & 0xFF) < 0x10)
+ buf.append('0');
+ buf.append(Integer.toHexString(element & 0xFF));
+ }
+ return buf.toString();
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumProducer.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumProducer.java
index fc8cabec6..c6616eb6c 100644
--- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumProducer.java
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/internal/p2/repository/helpers/ChecksumProducer.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2017 IBM Corporation and others.
+ * Copyright (c) 2009, 2018 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
@@ -7,51 +7,53 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
- * Mykola Nikishov - extract MD5 checksum calculation
+ * Mykola Nikishov - multiple artifact checksums
*******************************************************************************/
package org.eclipse.equinox.internal.p2.repository.helpers;
import java.io.*;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
+import java.security.*;
+/**
+ * Calculates a checksum using {@link java.security.MessageDigest}
+ */
public class ChecksumProducer {
+ private static final int BUFFER_SIZE = 4 * 1024;
+
/**
* @param file should not be <code>null</code>
* @return MD5 checksum of the file or <code>null</code> in case of NoSuchAlgorithmException
* @throws IOException
*/
+ @Deprecated
+ // bug #509401 - still here to not break x-friends like in bug #507193
public static String computeMD5(File file) throws IOException {
- InputStream fis = null;
try {
- MessageDigest md5Checker = MessageDigest.getInstance("MD5"); //$NON-NLS-1$
- fis = new BufferedInputStream(new FileInputStream(file));
- int read = -1;
- final int bufferSize = 4 * 1024;
- byte[] buffer = new byte[bufferSize];
- while ((read = fis.read(buffer, 0, bufferSize)) != -1) {
- md5Checker.update(buffer, 0, read);
- }
- byte[] digest = md5Checker.digest();
- StringBuffer buf = new StringBuffer();
- for (int i = 0; i < digest.length; i++) {
- if ((digest[i] & 0xFF) < 0x10)
- buf.append('0');
- buf.append(Integer.toHexString(digest[i] & 0xFF));
- }
- return buf.toString();
+ return produce(file, "MD5"); //$NON-NLS-1$
} catch (NoSuchAlgorithmException e) {
return null;
- } finally {
- if (fis != null)
- try {
- fis.close();
- } catch (IOException e) {
- // ignore
- }
}
}
+ /**
+ * @param file should not be <code>null</code>
+ * @param algorithm {@link java.security.MessageDigest#getInstance(String)}
+ * @return checksum of the file
+ * @throws IOException
+ * @throws NoSuchAlgorithmException
+ */
+ public static String produce(File file, String algorithm) throws IOException, NoSuchAlgorithmException {
+ MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
+ try (InputStream fis = new DigestInputStream(new BufferedInputStream(new FileInputStream(file)), messageDigest)) {
+ byte[] buffer = new byte[BUFFER_SIZE];
+ while (fis.read(buffer) != -1) {
+ // consume stream to update digest
+ }
+ }
+ byte[] digest = messageDigest.digest();
+ return ChecksumHelper.toHexString(digest);
+ }
+
}
diff --git a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java
index 81557cf03..826e17a59 100644
--- a/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java
+++ b/bundles/org.eclipse.equinox.p2.repository/src/org/eclipse/equinox/p2/repository/artifact/IArtifactDescriptor.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2010 IBM Corporation and others.
+ * Copyright (c) 2007, 2018 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
@@ -7,6 +7,7 @@
*
* Contributors:
* IBM Corporation - initial API and implementation
+ * Mykola Nikishov - multiple artifact checksums
*******************************************************************************/
package org.eclipse.equinox.p2.repository.artifact;
@@ -36,11 +37,22 @@ public interface IArtifactDescriptor {
* bytes of the artifact in its native format (after processing steps have been applied).
*/
public static final String ARTIFACT_SIZE = "artifact.size"; //$NON-NLS-1$
+
+ /**
+ * A prefix of an artifact descriptor properties (value "download.checksums") storing checksum
+ * of the artifact bytes that are transferred.
+ * @since 2.4.0
+ */
+ public static final String DOWNLOAD_CHECKSUM = "download.checksum"; //$NON-NLS-1$
+
/**
* An artifact descriptor property (value "download.md5") indicating the MD5
* checksum of the artifact bytes that are transferred.
+ * @see #DOWNLOAD_CHECKSUM
*/
+ @Deprecated
public static final String DOWNLOAD_MD5 = "download.md5"; //$NON-NLS-1$
+
/**
* An artifact descriptor property (value "download.contentType") indicating the
* content type of the artifact bytes that are transferred.
@@ -50,11 +62,22 @@ public interface IArtifactDescriptor {
* An content type (value "application/zip") indicating the content is a zip file.
*/
public static final String TYPE_ZIP = "application/zip"; //$NON-NLS-1$
+
+ /**
+ * An artifact descriptor property (value "artifact.checksums") storing list of
+ * checksums of the artifact bytes in its native format (after processing steps have
+ * been applied).
+ * @since 2.4.0
+ */
+ public static final String ARTIFACT_CHECKSUM = "artifact.checksum"; //$NON-NLS-1$
+
/**
* An artifact descriptor property (value "artifact.md5") indicating the MD5
* checksum of the artifact bytes in its native format (after processing steps have
* been applied).
+ * @see #ARTIFACT_CHECKSUM
*/
+ @Deprecated
public static final String ARTIFACT_MD5 = "artifact.md5"; //$NON-NLS-1$
/**
diff --git a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF
index 933a27c65..52d576d36 100644
--- a/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.p2.tests/META-INF/MANIFEST.MF
@@ -63,6 +63,7 @@ Import-Package: javax.xml.parsers,
org.eclipse.ant.core,
org.eclipse.core.filesystem,
org.eclipse.ecf.filetransfer,
+ org.eclipse.equinox.internal.p2.artifact.processors.checksum,
org.eclipse.equinox.internal.p2.artifact.processors.md5,
org.eclipse.equinox.internal.p2.artifact.processors.pack200,
org.eclipse.equinox.internal.p2.artifact.repository,
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java
index aeaca5a72..92dac347c 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/AllTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2008 compeople AG and others.
+ * Copyright (c) 2007, 2018 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
@@ -21,6 +21,7 @@ public class AllTests extends TestCase {
TestSuite suite = new TestSuite(AllTests.class.getName());
suite.addTestSuite(Pack200ProcessorTest.class);
suite.addTestSuite(ZipVerifierProcessorTest.class);
+ suite.addTest(new JUnit4TestAdapter(ChecksumVerifierTest.class));
return suite;
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/ChecksumVerifierTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/ChecksumVerifierTest.java
new file mode 100644
index 000000000..c71515105
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/artifact/processors/ChecksumVerifierTest.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2018 Mykola Nikishov.
+ * 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:
+ * Mykola Nikishov - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.artifact.processors;
+
+import static org.easymock.EasyMock.*;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.p2.artifact.processors.checksum.ChecksumVerifier;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
+import org.eclipse.equinox.p2.repository.artifact.IProcessingStepDescriptor;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ChecksumVerifierTest {
+ @Parameters
+ public static Collection<Object[]> generateData() {
+ return Arrays.asList(new Object[][] {
+ {"MD5", "md5", IArtifactDescriptor.DOWNLOAD_CHECKSUM.concat(".md5"), IArtifactDescriptor.ARTIFACT_CHECKSUM.concat(".md5"), "123456789_123456789_123456789_12"},
+ {"SHA-256", "sha-256", IArtifactDescriptor.DOWNLOAD_CHECKSUM.concat(".sha-256"), IArtifactDescriptor.ARTIFACT_CHECKSUM.concat(".sha-256"), "123456789_123456789_123456789_123456789_123456789_123456789_1234"}});
+ }
+
+ @Parameter(0)
+ public String digestAlgorithm;
+ @Parameter(1)
+ public String algorithmId;
+ @Parameter(2)
+ public String downloadProperty;
+ @Parameter(3)
+ public String artifactProperty;
+ @Parameter(4)
+ public String checksum;
+
+ @Test
+ public void testInitialize() throws IOException, IllegalArgumentException, SecurityException {
+ IProcessingStepDescriptor processingStepDescriptor = createMock(IProcessingStepDescriptor.class);
+ expect(processingStepDescriptor.getData()).andReturn(checksum);
+ expect(processingStepDescriptor.isRequired()).andReturn(true);
+ replay(processingStepDescriptor);
+
+ ChecksumVerifier verifier = new ChecksumVerifier(digestAlgorithm, algorithmId, checksum);
+
+ verifier.initialize(null, processingStepDescriptor, null);
+
+ Assert.assertEquals(Status.OK_STATUS, verifier.getStatus());
+
+ verifier.close();
+ verify(processingStepDescriptor);
+ }
+
+ @Test
+ public void testInitialize_DownloadChecksum() throws IOException, IllegalArgumentException, SecurityException {
+ IProcessingStepDescriptor processingStepDescriptor = createMock(IProcessingStepDescriptor.class);
+ expect(processingStepDescriptor.getData()).andReturn(downloadProperty);
+ expect(processingStepDescriptor.isRequired()).andReturn(true);
+ IArtifactDescriptor artifactDescriptor = createMock(IArtifactDescriptor.class);
+ replay(processingStepDescriptor);
+ expect(artifactDescriptor.getProperty(eq(downloadProperty))).andReturn(checksum);
+ expect(artifactDescriptor.getProperty(not(eq(downloadProperty)))).andReturn(null).times(1, 2);
+ HashMap<String, String> properties = new HashMap<>();
+ properties.put(downloadProperty, checksum);
+ expect(artifactDescriptor.getProperties()).andReturn(properties);
+ replay(artifactDescriptor);
+
+ ChecksumVerifier verifier = new ChecksumVerifier(digestAlgorithm, algorithmId, checksum);
+
+ verifier.initialize(null, processingStepDescriptor, artifactDescriptor);
+
+ Assert.assertEquals(Status.OK_STATUS, verifier.getStatus());
+
+ verifier.close();
+ verify(processingStepDescriptor);
+ }
+
+ @Test
+ public void testInitialize_ArtifactChecksum() throws IOException, IllegalArgumentException, SecurityException {
+ IProcessingStepDescriptor processingStepDescriptor = createMock(IProcessingStepDescriptor.class);
+ expect(processingStepDescriptor.getData()).andReturn(artifactProperty);
+ expect(processingStepDescriptor.isRequired()).andReturn(true);
+ IArtifactDescriptor artifactDescriptor = createMock(IArtifactDescriptor.class);
+ replay(processingStepDescriptor);
+ expect(artifactDescriptor.getProperty(eq(artifactProperty))).andReturn(checksum);
+ HashMap<String, String> properties = new HashMap<>();
+ properties.put(artifactProperty, checksum);
+ expect(artifactDescriptor.getProperties()).andReturn(properties);
+ expect(artifactDescriptor.getProperty(not(eq(artifactProperty)))).andReturn(null).times(1, 2);
+ replay(artifactDescriptor);
+
+ ChecksumVerifier verifier = new ChecksumVerifier(digestAlgorithm, algorithmId, checksum);
+
+ verifier.initialize(null, processingStepDescriptor, artifactDescriptor);
+
+ Assert.assertEquals(Status.OK_STATUS, verifier.getStatus());
+
+ verifier.close();
+ verify(processingStepDescriptor);
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java
index 348b1b170..d2697791c 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/AllTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2008, 2011 Code 9 and others. All rights reserved. This
+ * Copyright (c) 2008, 2018 Code 9 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
@@ -34,6 +34,7 @@ public class AllTests extends TestCase {
suite.addTestSuite(LocalizationTests.class);
suite.addTestSuite(LocalUpdateSiteActionTest.class);
suite.addTestSuite(MD5GenerationTest.class);
+ suite.addTest(new JUnit4TestAdapter(ChecksumGenerationTest.class));
suite.addTestSuite(ProductActionTest.class);
suite.addTestSuite(ProductActionCapturingTest.class);
suite.addTestSuite(ProductActionTestMac.class);
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/ChecksumGenerationTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/ChecksumGenerationTest.java
new file mode 100644
index 000000000..e6d3cca2e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/publisher/ChecksumGenerationTest.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2018 Mykola Nikishov.
+ * 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:
+ * Mykola Nikishov - multiple artifact checksums
+ *******************************************************************************/
+package org.eclipse.equinox.p2.tests.publisher;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
+import org.eclipse.equinox.p2.metadata.Version;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
+import org.eclipse.equinox.p2.tests.AbstractProvisioningTest;
+import org.eclipse.equinox.spi.p2.publisher.PublisherHelper;
+import org.hamcrest.CoreMatchers;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ChecksumGenerationTest extends AbstractProvisioningTest {
+ @Parameter(0)
+ public String checksumProperty;
+ @Parameter(1)
+ public String checksumValue;
+
+ @Parameters
+ public static Collection<Object[]> generateChecksums() {
+ return Arrays.asList(new Object[][] {{IArtifactDescriptor.DOWNLOAD_MD5, "50d4ea58b02706ab373a908338877e02"}, {IArtifactDescriptor.DOWNLOAD_CHECKSUM.concat(".sha-256"), "11da2dd636ab76f460513cbcbfe8c56a6e5ad47aa9b38b36c6d04f8ee7722252"}});
+ }
+
+ @Test
+ public void testGenerationFile() {
+ IArtifactDescriptor ad = PublisherHelper.createArtifactDescriptor(new ArtifactKey("classifierTest", "idTest", Version.createOSGi(1, 0, 0)), getTestData("Artifact to generate from", "testData/artifactRepo/simpleWithMD5/plugins/aaPlugin_1.0.0.jar"));
+ assertEquals(String.format("%s checksum property", checksumProperty), checksumValue, ad.getProperty(checksumProperty));
+ }
+
+ @Test
+ public void testGenerationFolder() {
+ IArtifactDescriptor ad = PublisherHelper.createArtifactDescriptor(new ArtifactKey("classifierTest", "idTest", Version.createOSGi(1, 0, 0)), getTestData("Artifact to generate from", "testData/artifactRepo/simpleWithMD5/plugins/"));
+ assertEquals(String.format("%s checksum property", checksumProperty), null, ad.getProperty(checksumProperty));
+ }
+
+ @Test
+ public void testGenerationNoFolder() {
+ IArtifactDescriptor ad = PublisherHelper.createArtifactDescriptor(new ArtifactKey("classifierTest", "idTest", Version.createOSGi(1, 0, 0)), null);
+ Assert.assertThat(ad.getProperty(checksumProperty), CoreMatchers.not(CoreMatchers.containsString(checksumValue)));
+ }
+}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/AllTests.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/AllTests.java
index f01588cda..852cb758f 100644
--- a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/AllTests.java
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/AllTests.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2009, 2012 Cloudsmith Inc and others.
+ * Copyright (c) 2009, 2018 Cloudsmith Inc 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
@@ -23,6 +23,7 @@ public class AllTests extends TestCase {
suite.addTestSuite(RepositoryHelperTest.class);
suite.addTestSuite(RepositoryExtensionPointTest.class);
suite.addTestSuite(FileReaderTest2.class);
+ suite.addTest(new JUnit4TestAdapter(ChecksumHelperTest.class));
return suite;
}
}
diff --git a/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/ChecksumHelperTest.java b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/ChecksumHelperTest.java
new file mode 100644
index 000000000..7eeddfb6e
--- /dev/null
+++ b/bundles/org.eclipse.equinox.p2.tests/src/org/eclipse/equinox/p2/tests/repository/ChecksumHelperTest.java
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * Copyright (c) 2015, 2018 Mykola Nikishov.
+ * 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:
+ * Mykola Nikishov - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.equinox.p2.tests.repository;
+
+import java.util.*;
+import org.eclipse.equinox.internal.p2.metadata.ArtifactKey;
+import org.eclipse.equinox.internal.p2.metadata.OSGiVersion;
+import org.eclipse.equinox.internal.p2.repository.helpers.ChecksumHelper;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactDescriptor;
+import org.eclipse.equinox.p2.repository.artifact.spi.ArtifactDescriptor;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameter;
+import org.junit.runners.Parameterized.Parameters;
+
+@RunWith(Parameterized.class)
+public class ChecksumHelperTest {
+ @Parameters
+ public static Collection<Object[]> generateData() {
+ return Arrays.asList(new Object[][] {{IArtifactDescriptor.ARTIFACT_CHECKSUM}, {IArtifactDescriptor.DOWNLOAD_CHECKSUM}});
+ }
+
+ @Parameter(0)
+ public String property;
+
+ @Test
+ public void testGetChecksums() {
+ String checksumId = "checksumAlgo";
+ String checksumValue = "value";
+ ArtifactDescriptor descriptor = new ArtifactDescriptor(new ArtifactKey("", "", new OSGiVersion(1, 1, 1, "")));
+ descriptor.setProperty(property.concat(".").concat(checksumId), checksumValue);
+ descriptor.setProperty("download.size", "1234");
+ Map<String, String> expectedChecksums = new HashMap<>();
+ expectedChecksums.put(checksumId, checksumValue);
+
+ Map<String, String> checksums = ChecksumHelper.getChecksums(descriptor, property);
+
+ Assert.assertEquals(expectedChecksums, checksums);
+ }
+
+}

Back to the top