From 2e2018dbacab91af76b4fb340f902d0a02d5f4e0 Mon Sep 17 00:00:00 2001
From: Martin Stockhammer
Date: Sat, 4 May 2019 21:18:26 +0200
Subject: [PATCH] Improving checksum implementation. Adding multiple
algorithms.
---
.../org/apache/archiva/checksum/Checksum.java | 58 --------
.../archiva/checksum/ChecksumAlgorithm.java | 40 ++++--
.../apache/archiva/checksum/ChecksumUtil.java | 100 +++++++++++++
.../archiva/checksum/ChecksummedFile.java | 134 +++++++++---------
.../apache/archiva/checksum/UpdateStatus.java | 89 ++++++++++++
.../archiva/checksum/UpdateStatusList.java | 87 ++++++++++++
.../apache/archiva/checksum/ChecksumTest.java | 5 +-
.../archiva/checksum/ChecksummedFileTest.java | 8 +-
.../ArchivaRuntimeConfiguration.java | 54 +++++++
.../registry/ConfigurationRegistryReader.java | 3 +
.../registry/ConfigurationRegistryWriter.java | 16 +++
.../archiva/configuration/default-archiva.xml | 8 ++
.../ArtifactMissingChecksumsConsumer.java | 79 +++++------
.../core/ValidateChecksumConsumer.java | 2 +-
.../core/AbstractArtifactConsumerTest.java | 3 +
.../archiva/policies/ChecksumPolicy.java | 3 +-
.../web/api/DefaultFileUploadService.java | 29 +++-
.../archiva/upload/UploadArtifactsTest.java | 23 +++
18 files changed, 548 insertions(+), 193 deletions(-)
create mode 100644 archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java
create mode 100644 archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatus.java
create mode 100644 archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatusList.java
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/Checksum.java b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/Checksum.java
index 5dd05d582..2a198877e 100644
--- a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/Checksum.java
+++ b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/Checksum.java
@@ -19,60 +19,22 @@ package org.apache.archiva.checksum;
* under the License.
*/
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.io.output.NullOutputStream;
-
-import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
-import java.security.DigestInputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
-import java.util.List;
/**
* Checksum - simple checksum hashing routines.
*/
public class Checksum
{
- private static final int BUFFER_SIZE = 32768;
private byte[] result = new byte[0];
- public static void update( List checksums, Path file )
- throws ChecksumValidationException
- {
- long fileSize;
- try (FileChannel channel = FileChannel.open(file, StandardOpenOption.READ )) {
- fileSize = channel.size();
- long pos = 0;
- while (pos getExtensions() {
+ public static Set getAllExtensions() {
return extensionMap.keySet();
}
@@ -74,7 +78,7 @@ public enum ChecksumAlgorithm {
private final String algorithm;
/**
- * The file extension for this ChecksumAlgorithm.
+ * The file extensions for this ChecksumAlgorithm.
*/
private final List ext;
@@ -87,8 +91,8 @@ public enum ChecksumAlgorithm {
* Construct a ChecksumAlgorithm
*
* @param algorithm the MessageDigest algorithm
- * @param ext the file extension.
- * @param type the checksum type.
+ * @param type a unique identifier for the type
+ * @param ext the list of file extensions
*/
private ChecksumAlgorithm( String algorithm, String type, String... ext )
{
@@ -98,20 +102,40 @@ public enum ChecksumAlgorithm {
}
+ /**
+ * Returns the message digest algorithm identifier
+ * @return
+ */
public String getAlgorithm()
{
return algorithm;
}
+ /**
+ * Returns the list of extensions
+ * @return
+ */
public List getExt()
{
return ext;
}
+ /**
+ * Returns the checksum identifier
+ * @return
+ */
public String getType()
{
return type;
}
+
+ /**
+ * Returns the default extension of the current algorithm
+ * @return
+ */
+ public String getDefaultExtension() {
+ return ext.get(0);
+ }
}
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java
new file mode 100644
index 000000000..5a11b910f
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksumUtil.java
@@ -0,0 +1,100 @@
+package org.apache.archiva.checksum;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Utility class that handles multiple checksums for a single file.
+ */
+public class ChecksumUtil {
+
+
+ static final int BUFFER_SIZE = 32768;
+
+ public static void update(List checksumList, Path file ) throws IOException {
+ long fileSize;
+ try (FileChannel channel = FileChannel.open(file, StandardOpenOption.READ )) {
+ fileSize = channel.size();
+ long pos = 0;
+ while (pos < fileSize) {
+ long bufferSize = Math.min(BUFFER_SIZE, fileSize - pos);
+ MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, pos, bufferSize);
+ for (Checksum checksum : checksumList) {
+ checksum.update(buffer);
+ buffer.rewind();
+ }
+ fileSize = channel.size();
+ pos += BUFFER_SIZE;
+ }
+ for (Checksum checksum : checksumList) {
+ checksum.finish();
+ }
+ }
+ }
+
+ public static void update(Checksum checksum, Path file)
+ throws IOException
+ {
+ long fileSize;
+ try (FileChannel channel = FileChannel.open(file, StandardOpenOption.READ )) {
+ fileSize = channel.size();
+ long pos = 0;
+ while (pos initializeChecksums(Path file, List checksumAlgorithms) throws IOException {
+ final List checksums = newChecksums(checksumAlgorithms);
+ update(checksums, file);
+ return checksums;
+ }
+
+ /**
+ * Returns the list of configured checksum types.
+ *
+ * @param checksumTypes The list of checksum strings
+ * @return The list of checksum objects
+ */
+ public static List getAlgorithms(List checksumTypes) {
+ return checksumTypes.stream().map(ca ->
+ ChecksumAlgorithm.valueOf(ca.toUpperCase())).collect(Collectors.toList());
+ }
+
+ public static List newChecksums(List checksumAlgorithms) {
+ return checksumAlgorithms.stream().map( a -> new Checksum(a)).collect(Collectors.toList());
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksummedFile.java b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksummedFile.java
index b8ff4e338..1279bdcd5 100644
--- a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksummedFile.java
+++ b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/ChecksummedFile.java
@@ -23,7 +23,7 @@ import org.apache.archiva.common.utils.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.xml.bind.ValidationException;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
@@ -98,21 +98,21 @@ public class ChecksummedFile
{
Checksum checksum = new Checksum( checksumAlgorithm );
- checksum.update( referenceFile );
+ ChecksumUtil.update(checksum, referenceFile );
return checksum.getChecksum( );
}
/**
- * Creates a checksum file of the provided referenceFile.
+ * Writes a checksum file for the referenceFile.
*
* @param checksumAlgorithm the hash to use.
* @return the checksum File that was created.
* @throws IOException if there was a problem either reading the referenceFile, or writing the checksum file.
*/
- public Path createChecksum( ChecksumAlgorithm checksumAlgorithm )
+ public Path writeFile(ChecksumAlgorithm checksumAlgorithm )
throws IOException
{
- Path checksumFile = referenceFile.resolveSibling( referenceFile.getFileName( ) + "." + checksumAlgorithm.getExt( ).get( 0 ) );
+ Path checksumFile = referenceFile.resolveSibling( referenceFile.getFileName( ) + "." + checksumAlgorithm.getDefaultExtension() );
Files.deleteIfExists( checksumFile );
String checksum = calculateChecksum( checksumAlgorithm );
Files.write( checksumFile, //
@@ -123,6 +123,8 @@ public class ChecksummedFile
/**
* Get the checksum file for the reference file and hash.
+ * It returns a file for the given checksum, if one exists with one of the possible extensions.
+ * If it does not exist, a default path will be returned.
*
* @param checksumAlgorithm the hash that we are interested in.
* @return the checksum file to return
@@ -137,7 +139,7 @@ public class ChecksummedFile
return file;
}
}
- return referenceFile.resolveSibling( referenceFile.getFileName( ) + "." + checksumAlgorithm.getExt( ).get( 0 ) );
+ return referenceFile.resolveSibling( referenceFile.getFileName( ) + "." + checksumAlgorithm.getDefaultExtension() );
}
/**
@@ -175,66 +177,65 @@ public class ChecksummedFile
}
/**
- * Checks if the checksums are valid for the referenced file.
+ * Checks if the checksum files are valid for the referenced file.
+ * It tries to find a checksum file for each algorithm in the same directory as the referenceFile.
+ * The method returns true, if at least one checksum file exists for one of the given algorithms
+ * and all existing checksum files are valid.
+ *
* This method throws only exceptions, if throwExceptions is true. Otherwise false will be returned instead.
+ *
+ * It verifies only the existing checksum files. If the checksum file for a particular algorithm does not exist,
+ * but others exist and are valid, it will return true.
+ *
* @param algorithms The algorithms to verify
* @param throwExceptions If true, exceptions will be thrown, otherwise false will be returned, if a exception occurred.
- * @return True, if it is valid, otherwise false.
+ * @return True, if it is valid for all existing checksum files, otherwise false.
* @throws ChecksumValidationException
*/
public boolean isValidChecksums( List algorithms, boolean throwExceptions) throws ChecksumValidationException
{
- List checksums = new ArrayList<>( algorithms.size() );
- // Create checksum object for each algorithm.
- for ( ChecksumAlgorithm checksumAlgorithm : algorithms )
- {
- Path checksumFile = getChecksumFile( checksumAlgorithm );
-
- // Only add algorithm if checksum file exists.
- if ( Files.exists( checksumFile ) )
- {
- checksums.add( new Checksum( checksumAlgorithm ) );
- }
- }
-
- // Any checksums?
- if ( checksums.isEmpty( ) )
- {
- // No checksum objects, no checksum files, default to is invalid.
- return false;
- }
-
+ List checksums;
// Parse file once, for all checksums.
try
{
- Checksum.update( checksums, referenceFile );
+ checksums = ChecksumUtil.initializeChecksums( referenceFile, algorithms );
}
- catch ( ChecksumValidationException e )
+ catch (IOException e )
{
log.warn( "Unable to update checksum:{}", e.getMessage( ) );
if (throwExceptions) {
- throw e;
+ if (e instanceof FileNotFoundException) {
+ throw new ChecksumValidationException(ChecksumValidationException.ValidationError.FILE_NOT_FOUND, e);
+ } else {
+ throw new ChecksumValidationException(ChecksumValidationException.ValidationError.READ_ERROR, e);
+ }
} else {
return false;
}
}
boolean valid = true;
+ boolean fileExists = false;
+
+ // No file exists -> return false
+ // if at least one file exists:
+ // -> all existing files must be valid
// check the checksum files
try
{
+
for ( Checksum checksum : checksums )
{
ChecksumAlgorithm checksumAlgorithm = checksum.getAlgorithm( );
Path checksumFile = getChecksumFile( checksumAlgorithm );
- String expectedChecksum = parseChecksum( checksumFile, checksumAlgorithm, referenceFile.getFileName( ).toString( ), FILE_ENCODING );
+ if (Files.exists(checksumFile)) {
+ fileExists = true;
+ String expectedChecksum = parseChecksum(checksumFile, checksumAlgorithm, referenceFile.getFileName().toString(), FILE_ENCODING);
- if ( !checksum.compare( expectedChecksum ) )
- {
- valid = false;
+ valid &= checksum.compare(expectedChecksum);
}
}
}
@@ -249,7 +250,7 @@ public class ChecksummedFile
}
}
- return valid;
+ return fileExists && valid;
}
public Path getReferenceFile( )
@@ -259,40 +260,39 @@ public class ChecksummedFile
- public boolean fixChecksum(ChecksumAlgorithm algorithm) {
+ public UpdateStatusList fixChecksum(ChecksumAlgorithm algorithm) {
return fixChecksums( Arrays.asList(algorithm) );
}
+
/**
- * Fix or create checksum files for the reference file.
+ * Writes a checksum file, if it does not exist or if it exists and has a different
+ * checksum value.
*
* @param algorithms the hashes to check for.
* @return true if checksums were created successfully.
*/
- public boolean fixChecksums( List algorithms )
+ public UpdateStatusList fixChecksums( List algorithms )
{
- List checksums = new ArrayList<>( algorithms.size() );
- // Create checksum object for each algorithm.
- for ( ChecksumAlgorithm checksumAlgorithm : algorithms )
- {
- checksums.add( new Checksum( checksumAlgorithm ) );
- }
+ UpdateStatusList result = UpdateStatusList.INITIALIZE(algorithms);
+ List checksums;
- // Any checksums?
- if ( checksums.isEmpty( ) )
- {
- // No checksum objects, no checksum files, default to is valid.
- return true;
- }
try
{
// Parse file once, for all checksums.
- Checksum.update( checksums, referenceFile );
+ checksums = ChecksumUtil.initializeChecksums(getReferenceFile(), algorithms);
}
- catch ( ChecksumValidationException e )
+ catch (IOException e )
{
log.warn( e.getMessage( ), e );
- return false;
+ result.setTotalError(e);
+ return result;
+ }
+ // Any checksums?
+ if ( checksums.isEmpty( ) )
+ {
+ // No checksum objects, no checksum files, default to is valid.
+ return result;
}
boolean valid = true;
@@ -316,23 +316,25 @@ public class ChecksummedFile
if ( !checksum.compare( expectedChecksum ) )
{
- // create checksum (again)
+ // overwrite checksum file
writeChecksumFile( checksumFile, FILE_ENCODING, checksum.getChecksum( ) );
+ result.setStatus(checksumAlgorithm,UpdateStatus.UPDATED);
}
}
else
{
writeChecksumFile( checksumFile, FILE_ENCODING, checksum.getChecksum( ) );
+ result.setStatus(checksumAlgorithm, UpdateStatus.CREATED);
}
}
catch ( ChecksumValidationException e )
{
log.warn( e.getMessage( ), e );
- valid = false;
+ result.setErrorStatus(checksumAlgorithm, e);
}
}
- return valid;
+ return result;
}
@@ -362,33 +364,33 @@ public class ChecksummedFile
*
*
* @param checksumFile The file where the checksum is stored
- * @param expectedHash The checksum algorithm to check
- * @param expectedPath The filename of the reference file
+ * @param checksumAlgorithm The checksum algorithm to check
+ * @param fileName The filename of the reference file
* @return
* @throws IOException
*/
- public String parseChecksum( Path checksumFile, ChecksumAlgorithm expectedHash, String expectedPath, Charset encoding )
+ public String parseChecksum( Path checksumFile, ChecksumAlgorithm checksumAlgorithm, String fileName, Charset encoding )
throws ChecksumValidationException
{
- ChecksumFileContent fc = parseChecksumFile( checksumFile, expectedHash, encoding );
- if ( fc.isFormatMatch() && !isValidChecksumPattern( fc.getFileReference( ), expectedPath ) )
+ ChecksumFileContent fc = parseChecksumFile( checksumFile, checksumAlgorithm, encoding );
+ if ( fc.isFormatMatch() && !isValidChecksumPattern( fc.getFileReference( ), fileName ) )
{
throw new ChecksumValidationException(BAD_CHECKSUM_FILE_REF,
- "The file reference '" + fc.getFileReference( ) + "' in the checksum file does not match expected file: '" + expectedPath + "'" );
+ "The file reference '" + fc.getFileReference( ) + "' in the checksum file does not match expected file: '" + fileName + "'" );
} else if (!fc.isFormatMatch()) {
throw new ChecksumValidationException( BAD_CHECKSUM_FILE, "The checksum file content could not be parsed: "+checksumFile );
}
return fc.getChecksum( );
- }
- public ChecksumFileContent parseChecksumFile( Path checksumFile, ChecksumAlgorithm expectedHash, Charset encoding )
+ }
+ public ChecksumFileContent parseChecksumFile( Path checksumFile, ChecksumAlgorithm checksumAlgorithm, Charset encoding )
{
ChecksumFileContent fc = new ChecksumFileContent( );
String rawChecksumString = FileUtils.readFileToString( checksumFile, encoding );
String trimmedChecksum = rawChecksumString.replace( '\n', ' ' ).trim( );
// Free-BSD / openssl
- String regex = expectedHash.getType( ) + "\\s*\\(([^)]*)\\)\\s*=\\s*([a-fA-F0-9]+)";
+ String regex = checksumAlgorithm.getType( ) + "\\s*\\(([^)]*)\\)\\s*=\\s*([a-fA-F0-9]+)";
Matcher m = Pattern.compile( regex ).matcher( trimmedChecksum );
if ( m.matches( ) )
{
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatus.java b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatus.java
new file mode 100644
index 000000000..038732b18
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatus.java
@@ -0,0 +1,89 @@
+package org.apache.archiva.checksum;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Status of checksum update for specific algorithm.
+ */
+public class UpdateStatus {
+
+ /**
+ * Checksum file did not exist before and was created
+ */
+ public static final int CREATED = 1;
+ /**
+ * Checksum file existed, but content differed
+ */
+ public static final int UPDATED = 2;
+ /**
+ * Nothing changed
+ */
+ public static final int NONE = 0;
+ /**
+ * Error occured during update/creation of the checksum file
+ */
+ public static final int ERROR = -1;
+
+ private final ChecksumAlgorithm algorithm;
+ private final int status;
+ private final Throwable error;
+
+ public UpdateStatus(ChecksumAlgorithm algorithm) {
+ this.algorithm = algorithm;
+ status = NONE;
+ error = null;
+ }
+
+ public UpdateStatus(ChecksumAlgorithm algorithm, int status) {
+ this.algorithm = algorithm;
+ this.status = status;
+ error = null;
+ }
+
+ public UpdateStatus(ChecksumAlgorithm algorithm, Throwable error) {
+ this.algorithm = algorithm;
+ this.status = ERROR;
+ this.error = error;
+ }
+
+ /**
+ * Return the status value.
+ * @return The value
+ */
+ public int getValue() {
+ return status;
+ }
+
+ /**
+ * Return error, if exists, otherwise null
will be returned.
+ * @return
+ */
+ public Throwable getError() {
+ return error;
+ }
+
+ /**
+ * Return the algorithm, this status is assigned to.
+ * @return The checksum algorithm
+ */
+ public ChecksumAlgorithm getAlgorithm() {
+ return algorithm;
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatusList.java b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatusList.java
new file mode 100644
index 000000000..cf3325a37
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-checksum/src/main/java/org/apache/archiva/checksum/UpdateStatusList.java
@@ -0,0 +1,87 @@
+package org.apache.archiva.checksum;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Container for a list of update status objects.
+ *
+ * If there is a overall error that is not specific to a algorithm, the total status
+ * flag is set to error.
+ */
+public class UpdateStatusList {
+
+ private int totalStatus = UpdateStatus.NONE;
+ private Throwable error;
+ private Map statusList = new TreeMap<>();
+
+ public UpdateStatusList() {
+
+ }
+
+ public void addStatus(UpdateStatus status) {
+ statusList.put(status.getAlgorithm(), status);
+ }
+
+ public static UpdateStatusList INITIALIZE(List algorithms) {
+ final UpdateStatusList list = new UpdateStatusList();
+ for(ChecksumAlgorithm algorithm : algorithms) {
+ list.addStatus(new UpdateStatus(algorithm));
+ }
+ return list;
+ }
+
+ public int getTotalStatus() {
+ return totalStatus;
+ }
+
+ public void setTotalError(Throwable e) {
+ this.error = e;
+ this.totalStatus = UpdateStatus.ERROR;
+ }
+
+ public Throwable getTotalError() {
+ return error;
+ }
+
+ public List getStatusList() {
+ return new ArrayList(statusList.values());
+ }
+
+ public void setStatus(ChecksumAlgorithm algorithm, UpdateStatus status) {
+ statusList.put(algorithm, status);
+ }
+
+ public void setStatus(ChecksumAlgorithm algorithm, int status) {
+ statusList.put(algorithm, new UpdateStatus(algorithm, status));
+ }
+
+ public void setErrorStatus(ChecksumAlgorithm algorithm, Throwable e) {
+ statusList.put(algorithm, new UpdateStatus(algorithm,e));
+ }
+
+ public UpdateStatus getStatus(ChecksumAlgorithm algorithm) {
+ return statusList.get(algorithm);
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksumTest.java b/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksumTest.java
index 55746f6b9..ca3dab891 100644
--- a/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksumTest.java
+++ b/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksumTest.java
@@ -19,15 +19,12 @@ package org.apache.archiva.checksum;
* under the License.
*/
-import junit.framework.TestCase;
import org.apache.archiva.common.utils.FileUtils;
import org.apache.archiva.test.utils.ArchivaBlockJUnit4ClassRunner;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
-import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -85,7 +82,7 @@ public class ChecksumTest
FileUtils.writeStringToFile( checkFile, FILE_ENCODING, "You know, I'm sick of following my dreams, man. "
+ "I'm just going to ask where they're going and hook up with 'em later. - Mitch Hedberg");
- Checksum.update( checksums, checkFile );
+ ChecksumUtil.update( checksums, checkFile );
assertEquals( "Checksum SHA1", "e396119ae0542e85a74759602fd2f81e5d36d762", checksumSha1.getChecksum() );
assertEquals( "Checksum MD5", "21c2c5ca87ec018adacb2e2fb3432219", checksumMd5.getChecksum() );
diff --git a/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksummedFileTest.java b/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksummedFileTest.java
index 727953ec9..33c7416ee 100644
--- a/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksummedFileTest.java
+++ b/archiva-modules/archiva-base/archiva-checksum/src/test/java/org/apache/archiva/checksum/ChecksummedFileTest.java
@@ -130,7 +130,7 @@ public class ChecksummedFileTest
{
Path testableJar = createTestableJar( "examples/redback-authz-open.jar" );
ChecksummedFile checksummedFile = new ChecksummedFile( testableJar );
- checksummedFile.createChecksum( ChecksumAlgorithm.SHA1 );
+ checksummedFile.writeFile( ChecksumAlgorithm.SHA1 );
Path hashFile = checksummedFile.getChecksumFile( ChecksumAlgorithm.SHA1 );
assertTrue( "ChecksumAlgorithm file should exist.", Files.exists(hashFile) );
String hashContents = org.apache.commons.io.FileUtils.readFileToString( hashFile.toFile(), "UTF-8" );
@@ -152,8 +152,10 @@ public class ChecksummedFileTest
assertFalse( "ChecksummedFile.isValid(SHA1) == false",
checksummedFile.isValidChecksum( ChecksumAlgorithm.SHA1 ) );
- boolean fixed = checksummedFile.fixChecksums( Arrays.asList( ChecksumAlgorithm.SHA1 ) );
- assertTrue( "ChecksummedFile.fixChecksums() == true", fixed );
+ UpdateStatusList fixed = checksummedFile.fixChecksums( Arrays.asList( ChecksumAlgorithm.SHA1 ) );
+ assertEquals(1, fixed.getStatusList().size());
+ assertFalse(fixed.getTotalStatus()==UpdateStatus.ERROR);
+ assertTrue( "ChecksummedFile.fixChecksums() == true", fixed.getStatusList().get(0).getValue()==UpdateStatus.UPDATED );
assertTrue( "ChecksummedFile.isValid(SHA1) == true",
checksummedFile.isValidChecksum( ChecksumAlgorithm.SHA1 ) );
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaRuntimeConfiguration.java b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaRuntimeConfiguration.java
index 7d6f5d38a..ae9b9bb90 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaRuntimeConfiguration.java
+++ b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/ArchivaRuntimeConfiguration.java
@@ -19,6 +19,10 @@ package org.apache.archiva.configuration;
* under the License.
*/
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
/**
*
* The runtime configuration.
@@ -76,6 +80,11 @@ public class ArchivaRuntimeConfiguration
*/
private String languageRange = "en,fr,de";
+ /**
+ * List of checksum types (algorithms) that should be applied to repository artifacts.
+ */
+ private List checksumTypes = new ArrayList(Arrays.asList("MD5","SHA1","SHA256"));
+
//-----------/
//- Methods -/
@@ -233,4 +242,49 @@ public class ArchivaRuntimeConfiguration
this.urlFailureCacheConfiguration = urlFailureCacheConfiguration;
} //-- void setUrlFailureCacheConfiguration( CacheConfiguration )
+
+ /**
+ * Returns the list of checksum types to generate
+ * @return
+ */
+ public List getChecksumTypes()
+ {
+ if ( this.checksumTypes == null )
+ {
+ this.checksumTypes = new java.util.ArrayList();
+ }
+
+ return this.checksumTypes;
+ }
+
+ /**
+ * Adds a checksum type
+ * @param type
+ */
+ public void addChecksumType(String type) {
+
+ if (!getChecksumTypes().contains(type)) {
+ getChecksumTypes().add(type);
+ }
+ }
+
+ /**
+ * Removes a checksum type
+ * @param type
+ */
+ public void removeChecksumType(String type) {
+ getChecksumTypes().remove(type);
+ }
+
+ /**
+ * Set all checksum types
+ * @param checksumTypes
+ */
+ public void setChecksumTypes(List checksumTypes) {
+ if (checksumTypes!=null) {
+ getChecksumTypes().clear();
+ getChecksumTypes().addAll(checksumTypes);
+ }
+ }
+
}
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryReader.java b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryReader.java
index 0abe06aa9..d8783453e 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryReader.java
+++ b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryReader.java
@@ -1423,6 +1423,9 @@ public class ConfigurationRegistryReader {
value.setLanguageRange(languageRange);
+ List checksumTypeList = registry.getList(prefix + "checksumTypes.type");
+ value.setChecksumTypes(checksumTypeList);
+
return value;
}
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryWriter.java b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryWriter.java
index bb94913c0..31ffc6b9d 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryWriter.java
+++ b/archiva-modules/archiva-base/archiva-configuration/src/main/java/org/apache/archiva/configuration/io/registry/ConfigurationRegistryWriter.java
@@ -24,6 +24,7 @@ import org.apache.archiva.configuration.*;
import org.apache.archiva.redback.components.registry.Registry;
import java.util.Iterator;
+import java.util.List;
// Util imports
// Model class imports
@@ -37,6 +38,20 @@ public class ConfigurationRegistryWriter {
writeConfiguration("", model, registry);
}
+ private void writeList(Registry registry, List subList, String subsetPath, String elementName) {
+ if (subList != null && subList.size() > 0
+ ) {
+ registry.removeSubset(subsetPath);
+
+ int count = 0;
+ for (Iterator iter = subList.iterator(); iter.hasNext(); count++) {
+ String name = subsetPath + "." + elementName + "(" + count + ")";
+ String value = iter.next();
+ registry.setString(name, value);
+ }
+ }
+ }
+
private void writeConfiguration(String prefix, Configuration value, Registry registry) {
if (value != null) {
if (value.getVersion() != null
@@ -882,6 +897,7 @@ public class ConfigurationRegistryWriter {
String languageRange = "languageRange";
registry.setString(prefix + languageRange, value.getLanguageRange());
}
+ writeList(registry, value.getChecksumTypes(), prefix+"checksumTypes", "type");
}
}
diff --git a/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml b/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml
index c5acb803d..5f3731dab 100644
--- a/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml
+++ b/archiva-modules/archiva-base/archiva-configuration/src/main/resources/org/apache/archiva/configuration/default-archiva.xml
@@ -142,6 +142,14 @@
+
+
+ MD5
+ SHA1
+ SHA256
+
+
+
jpa
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java
index f90fb10c6..559de35e0 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ArtifactMissingChecksumsConsumer.java
@@ -19,8 +19,7 @@ package org.apache.archiva.consumers.core;
* under the License.
*/
-import org.apache.archiva.checksum.ChecksumAlgorithm;
-import org.apache.archiva.checksum.ChecksummedFile;
+import org.apache.archiva.checksum.*;
import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.configuration.FileTypes;
import org.apache.archiva.consumers.AbstractMonitoredConsumer;
@@ -58,14 +57,12 @@ public class ArtifactMissingChecksumsConsumer
private String id = "create-missing-checksums";
- private String description = "Create Missing and/or Fix Invalid Checksums (.sha1, .md5)";
+ private String description = "Create Missing and/or Fix Invalid Checksum files.";
private ArchivaConfiguration configuration;
private FileTypes filetypes;
- private ChecksummedFile checksum;
-
private static final String TYPE_CHECKSUM_NOT_FILE = "checksum-bad-not-file";
private static final String TYPE_CHECKSUM_CANNOT_CALC = "checksum-calc-failure";
@@ -75,6 +72,7 @@ public class ArtifactMissingChecksumsConsumer
private Path repositoryDir;
private List includes = new ArrayList<>( 0 );
+ private List algorithms;
@Inject
public ArtifactMissingChecksumsConsumer( ArchivaConfiguration configuration, FileTypes filetypes )
@@ -141,8 +139,36 @@ public class ArtifactMissingChecksumsConsumer
public void processFile( String path )
throws ConsumerException
{
- createFixChecksum( path, ChecksumAlgorithm.SHA1 );
- createFixChecksum( path, ChecksumAlgorithm.MD5 );
+ Path artifactPath = repositoryDir.resolve(path);
+ ChecksummedFile csFile = new ChecksummedFile(artifactPath);
+ UpdateStatusList result = csFile.fixChecksums(algorithms);
+ if (result.getTotalStatus()== UpdateStatus.ERROR) {
+ log.warn( "Error accessing file {}. ", path );
+ triggerConsumerWarning( TYPE_CHECKSUM_NOT_FILE,
+ "Error accessing file " + path + "." );
+ } else {
+ result.getStatusList().stream().forEach(st ->
+ triggerInfo(path, st));
+ }
+ }
+
+ private void triggerInfo(String path, UpdateStatus status) {
+ switch (status.getValue()) {
+ case UpdateStatus.ERROR:
+ log.error( "Cannot create checksum for file {} :", path, status.getError() );
+ triggerConsumerError( TYPE_CHECKSUM_CANNOT_CREATE, "Cannot create checksum for file " + path +
+ ": " + status.getError().getMessage( ) );
+ break;
+ case UpdateStatus.CREATED:
+ log.info( "Created missing checksum file {}", path );
+ triggerConsumerInfo( "Created missing checksum file " + path );
+ break;
+ case UpdateStatus.UPDATED:
+ log.info( "Fixed checksum file {}", path );
+ triggerConsumerInfo( "Fixed checksum file " + path );
+ break;
+
+ }
}
@Override
@@ -152,44 +178,6 @@ public class ArtifactMissingChecksumsConsumer
processFile( path );
}
- private void createFixChecksum( String path, ChecksumAlgorithm checksumAlgorithm )
- {
- Path artifactFile = repositoryDir.resolve(path);
- Path checksumFile = repositoryDir.resolve(path + "." + checksumAlgorithm.getExt( ).get(0) );
-
- if ( Files.exists(checksumFile) )
- {
- checksum = new ChecksummedFile( artifactFile);
- if ( !checksum.isValidChecksum( checksumAlgorithm ) )
- {
- checksum.fixChecksum( checksumAlgorithm );
- log.info( "Fixed checksum file {}", checksumFile.toAbsolutePath( ) );
- triggerConsumerInfo( "Fixed checksum file " + checksumFile.toAbsolutePath( ) );
- }
- }
- else if ( !Files.exists(checksumFile) )
- {
- checksum = new ChecksummedFile( artifactFile);
- try
- {
- checksum.createChecksum( checksumAlgorithm );
- log.info( "Created missing checksum file {}", checksumFile.toAbsolutePath( ) );
- triggerConsumerInfo( "Created missing checksum file " + checksumFile.toAbsolutePath( ) );
- }
- catch ( IOException e )
- {
- log.error( "Cannot create checksum for file {} :", checksumFile, e );
- triggerConsumerError( TYPE_CHECKSUM_CANNOT_CREATE, "Cannot create checksum for file " + checksumFile +
- ": " + e.getMessage( ) );
- }
- }
- else
- {
- log.warn( "Checksum file {} is not a file. ", checksumFile.toAbsolutePath( ) );
- triggerConsumerWarning( TYPE_CHECKSUM_NOT_FILE,
- "Checksum file " + checksumFile.toAbsolutePath( ) + " is not a file." );
- }
- }
/*
@Override
@@ -222,5 +210,6 @@ public class ArtifactMissingChecksumsConsumer
//configuration.addChangeListener( this );
initIncludes( );
+ algorithms = ChecksumUtil.getAlgorithms(configuration.getConfiguration().getArchivaRuntimeConfiguration().getChecksumTypes());
}
}
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ValidateChecksumConsumer.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ValidateChecksumConsumer.java
index e4648a8a7..2121fd355 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ValidateChecksumConsumer.java
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/main/java/org/apache/archiva/consumers/core/ValidateChecksumConsumer.java
@@ -159,7 +159,7 @@ public class ValidateChecksumConsumer
@PostConstruct
public void initialize( )
{
- Set extensions = ChecksumAlgorithm.getExtensions();
+ Set extensions = ChecksumAlgorithm.getAllExtensions();
includes = new ArrayList<>( extensions.size() );
for ( String ext : extensions )
{
diff --git a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java
index 4d50b8ce0..f06a67649 100644
--- a/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java
+++ b/archiva-modules/archiva-base/archiva-consumers/archiva-core-consumers/src/test/java/org/apache/archiva/consumers/core/AbstractArtifactConsumerTest.java
@@ -63,6 +63,9 @@ public abstract class AbstractArtifactConsumerTest
(FileType) archivaConfiguration.getConfiguration().getRepositoryScanning().getFileTypes().get( 0 );
assertEquals( FileTypes.ARTIFACTS, fileType.getId() );
fileType.addPattern( "**/*.xml" );
+ archivaConfiguration.getConfiguration().getArchivaRuntimeConfiguration().addChecksumType("MD5");
+ archivaConfiguration.getConfiguration().getArchivaRuntimeConfiguration().addChecksumType("SHA1");
+ archivaConfiguration.getConfiguration().getArchivaRuntimeConfiguration().addChecksumType("SHA256");
repoLocation = Paths.get( "target/test-" + getName() + "/test-repo" );
}
diff --git a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java
index c2004d139..82d4d3da4 100644
--- a/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java
+++ b/archiva-modules/archiva-base/archiva-policies/src/main/java/org/apache/archiva/policies/ChecksumPolicy.java
@@ -21,6 +21,7 @@ package org.apache.archiva.policies;
import org.apache.archiva.checksum.ChecksumAlgorithm;
import org.apache.archiva.checksum.ChecksummedFile;
+import org.apache.archiva.checksum.UpdateStatus;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -146,7 +147,7 @@ public class ChecksumPolicy
if ( FIX.equals( policySetting ) )
{
ChecksummedFile checksum = new ChecksummedFile( localFile );
- if ( checksum.fixChecksums( algorithms ) )
+ if ( checksum.fixChecksums( algorithms ).getTotalStatus() != UpdateStatus.ERROR )
{
log.debug( "Checksum policy set to FIX, checksum files have been updated." );
return;
diff --git a/archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/api/DefaultFileUploadService.java b/archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/api/DefaultFileUploadService.java
index 934da8097..afe40d285 100644
--- a/archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/api/DefaultFileUploadService.java
+++ b/archiva-modules/archiva-web/archiva-web-common/src/main/java/org/apache/archiva/web/api/DefaultFileUploadService.java
@@ -25,9 +25,11 @@ import org.apache.archiva.admin.model.admin.ArchivaAdministration;
import org.apache.archiva.admin.model.beans.ManagedRepository;
import org.apache.archiva.admin.model.managed.ManagedRepositoryAdmin;
import org.apache.archiva.checksum.ChecksumAlgorithm;
+import org.apache.archiva.checksum.ChecksumUtil;
import org.apache.archiva.checksum.ChecksummedFile;
import org.apache.archiva.common.utils.VersionComparator;
import org.apache.archiva.common.utils.VersionUtil;
+import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.maven2.metadata.MavenMetadataReader;
import org.apache.archiva.metadata.model.facets.AuditEvent;
import org.apache.archiva.model.ArchivaRepositoryMetadata;
@@ -59,6 +61,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
+import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
@@ -74,9 +77,14 @@ import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.stream.Collectors;
/**
+ *
+ * Service for uploading files to the repository.
+ *
* @author Olivier Lamy
+ * @author Martin Stockhammer
*/
@Service("fileUploadService#rest")
public class DefaultFileUploadService
@@ -96,7 +104,10 @@ public class DefaultFileUploadService
@Inject
private ArchivaAdministration archivaAdministration;
- private List algorithms = Arrays.asList(ChecksumAlgorithm.SHA1, ChecksumAlgorithm.MD5);
+ @Inject
+ ArchivaConfiguration configuration;
+
+ private List algorithms;
private final String FS = FileSystems.getDefault().getSeparator();
@@ -111,6 +122,11 @@ public class DefaultFileUploadService
StringUtils.trim(URLDecoder.decode(IOUtils.toString(attachment.getDataHandler().getInputStream(), "UTF-8"), "UTF-8"));
}
+ @PostConstruct
+ private void initialize() {
+ algorithms = ChecksumUtil.getAlgorithms(configuration.getConfiguration().getArchivaRuntimeConfiguration().getChecksumTypes());
+ }
+
@Override
public FileMetadata post(MultipartBody multipartBody)
throws ArchivaRestServiceException {
@@ -233,12 +249,10 @@ public class DefaultFileUploadService
@Override
public List getSessionFileMetadatas()
throws ArchivaRestServiceException {
- @SuppressWarnings("unchecked") List fileMetadatas =
- (List) httpServletRequest.getSession().getAttribute(FILES_SESSION_KEY);
-
- return fileMetadatas == null ? Collections.emptyList() : fileMetadatas;
+ return getSessionFilesList();
}
+
private boolean hasValidChars(String checkString) {
if (checkString.contains(FS)) {
return false;
@@ -427,8 +441,9 @@ public class DefaultFileUploadService
filename = filename.replaceAll(VersionUtil.SNAPSHOT, timestamp + "-" + newBuildNumber);
}
- boolean fixChecksums =
- !(archivaAdministration.getKnownContentConsumers().contains("create-missing-checksums"));
+ // We always fix checksums for newly uploaded files, even if the content consumer is active.
+ boolean fixChecksums = true;
+ // !(archivaAdministration.getKnownContentConsumers().contains("create-missing-checksums"));
try {
Path targetFile = targetPath.resolve(filename);
diff --git a/archiva-modules/archiva-web/archiva-web-common/src/test/java/org/apache/archiva/upload/UploadArtifactsTest.java b/archiva-modules/archiva-web/archiva-web-common/src/test/java/org/apache/archiva/upload/UploadArtifactsTest.java
index 78debb1e0..e501d1cdf 100644
--- a/archiva-modules/archiva-web/archiva-web-common/src/test/java/org/apache/archiva/upload/UploadArtifactsTest.java
+++ b/archiva-modules/archiva-web/archiva-web-common/src/test/java/org/apache/archiva/upload/UploadArtifactsTest.java
@@ -21,6 +21,7 @@ package org.apache.archiva.upload;
import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.apache.archiva.configuration.ArchivaConfiguration;
import org.apache.archiva.redback.rest.services.AbstractRestServicesTest;
+import org.apache.archiva.redback.rest.services.FakeCreateAdminService;
import org.apache.archiva.rest.api.services.ArchivaRestServiceException;
import org.apache.archiva.test.utils.ArchivaBlockJUnit4ClassRunner;
import org.apache.archiva.web.api.FileUploadService;
@@ -248,4 +249,26 @@ public class UploadArtifactsTest
service.post(body);
service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "jar", true);
}
+
+ @Test
+ public void saveFileWithOtherExtension() throws IOException, ArchivaRestServiceException {
+ log.debug("Starting saveFileWithOtherExtension()");
+
+ Path path = Paths.get("target/appserver-base/repositories/internal/data/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.bin");
+ log.debug("Jar exists: {}",Files.exists(path));
+ Files.deleteIfExists(path);
+ Path pomPath = Paths.get("target/appserver-base/repositories/internal/data/repositories/internal/org/apache/archiva/archiva-model/1.2/archiva-model-1.2.pom");
+ Files.deleteIfExists(pomPath);
+ FileUploadService service = getUploadService();
+ service.clearUploadedFiles();
+ Path file = Paths.get("src/test/repositories/snapshot-repo/org/apache/archiva/archiva-model/1.4-M4-SNAPSHOT/archiva-model-1.4-M4-20130425.081822-1.jar");
+ log.debug("Upload file exists: {}", Files.exists(file));
+ final Attachment fileAttachment = new AttachmentBuilder().object(Files.newInputStream(file)).contentDisposition(new ContentDisposition("form-data; filename=\"archiva-model.bin\"; name=\"files[]\"")).build();
+ MultipartBody body = new MultipartBody(fileAttachment);
+ service.post(body);
+ assertTrue(service.save("internal", "org.apache.archiva", "archiva-model", "1.2", "bin", false));
+ assertTrue(Files.exists(path));
+ }
+
+
}
--
2.39.5