Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'bundles/org.eclipse.equinox.p2.artifact.repository/src/org/eclipse/equinox/internal/p2/artifact/processors')
-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
5 files changed, 270 insertions, 16 deletions
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();
}

Back to the top