Migrated common artifact repo funtions into abstract class. (#666)

* Migrated common art repo funtions into abstract class.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Remove dead code from permission util.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Remove dead code.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix typo.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix typo.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix test.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>

* Fix stats resource.

Signed-off-by: kaizimmerm <kai.zimmermann@bosch-si.com>
This commit is contained in:
Kai Zimmermann
2018-03-27 12:04:16 +02:00
committed by GitHub
parent d9fc3c0e31
commit 8fd601f8b9
13 changed files with 170 additions and 253 deletions

View File

@@ -8,29 +8,18 @@
*/
package org.eclipse.hawkbit.artifact.repository;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.eclipse.hawkbit.artifact.repository.model.AbstractDbArtifact;
import org.eclipse.hawkbit.artifact.repository.model.DbArtifactHash;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.annotation.Validated;
import com.google.common.base.Splitter;
import com.google.common.io.BaseEncoding;
import com.google.common.io.ByteStreams;
import com.google.common.io.Files;
/**
@@ -46,12 +35,8 @@ import com.google.common.io.Files;
* SHA1-hash {@code (/basepath/[two digit sha1]/[two digit sha1])}.
*/
@Validated
public class ArtifactFilesystemRepository implements ArtifactRepository {
public class ArtifactFilesystemRepository extends AbstractArtifactRepository {
private static final Logger LOG = LoggerFactory.getLogger(ArtifactFilesystemRepository.class);
private static final String TEMP_FILE_PREFIX = "tmp";
private static final String TEMP_FILE_SUFFIX = "artifactrepo";
private final ArtifactFilesystemProperties artifactResourceProperties;
/**
@@ -65,33 +50,6 @@ public class ArtifactFilesystemRepository implements ArtifactRepository {
this.artifactResourceProperties = artifactResourceProperties;
}
@Override
public ArtifactFilesystem store(final String tenant, final InputStream content, final String filename,
final String contentType) {
return store(tenant, content, filename, contentType, null);
}
@Override
// suppress warning, of not strong enough hashing algorithm, SHA-1 and MD5
// is not used security related
@SuppressWarnings("squid:S2070")
public ArtifactFilesystem store(final String tenant, final InputStream content, final String filename,
final String contentType, final DbArtifactHash hash) {
final MessageDigest mdSHA1;
final MessageDigest mdMD5;
try {
mdSHA1 = MessageDigest.getInstance("SHA1");
mdMD5 = MessageDigest.getInstance("MD5");
} catch (final NoSuchAlgorithmException e) {
throw new ArtifactStoreException(e.getMessage(), e);
}
final File file = createTempFile();
final AbstractDbArtifact artifact = store(content, contentType, hash, mdSHA1, mdMD5, file);
return renameFileToSHA1Naming(tenant, file, artifact);
}
@Override
public void deleteBySha1(final String tenant, final String sha1Hash) {
FileUtils.deleteQuietly(getFile(tenant, sha1Hash));
@@ -107,75 +65,24 @@ public class ArtifactFilesystemRepository implements ArtifactRepository {
return new ArtifactFilesystem(file, sha1, new DbArtifactHash(sha1, null), file.length(), null);
}
private AbstractDbArtifact store(final InputStream content, final String contentType, final DbArtifactHash hash,
final MessageDigest mdSHA1, final MessageDigest mdMD5, final File file) {
AbstractDbArtifact artifact;
try (final DigestOutputStream outputstream = openFileOutputStream(file, mdSHA1, mdMD5)) {
final long artifactSize = ByteStreams.copy(content, outputstream);
outputstream.flush();
final String sha1Hash = BaseEncoding.base16().lowerCase().encode(mdSHA1.digest());
final String md5Hash = BaseEncoding.base16().lowerCase().encode(mdMD5.digest());
artifact = new ArtifactFilesystem(file, sha1Hash, new DbArtifactHash(sha1Hash, md5Hash), artifactSize,
contentType);
checkHashes(artifact, hash);
} catch (final IOException e) {
throw new ArtifactStoreException(e.getMessage(), e);
} catch (final HashNotMatchException e) {
if (!file.delete()) {
LOG.error("Could not delete temp file {}", file);
}
throw e;
}
return artifact;
@Override
protected AbstractDbArtifact store(final String tenant, final String sha1Hash16, final String mdMD5Hash16,
final String contentType, final File file) throws IOException {
return renameFileToSHA1Naming(tenant, file, new ArtifactFilesystem(file, sha1Hash16,
new DbArtifactHash(sha1Hash16, mdMD5Hash16), file.length(), contentType));
}
private ArtifactFilesystem renameFileToSHA1Naming(final String tenant, final File file,
final AbstractDbArtifact artifact) {
final AbstractDbArtifact artifact) throws IOException {
final File fileSHA1Naming = getFile(tenant, artifact.getHashes().getSha1());
final ArtifactFilesystem fileSystemArtifact = new ArtifactFilesystem(fileSHA1Naming, artifact.getArtifactId(),
artifact.getHashes(), artifact.getSize(), artifact.getContentType());
if (fileSHA1Naming.exists()) {
FileUtils.deleteQuietly(file);
} else {
try {
Files.move(file, fileSHA1Naming);
} catch (final IOException e) {
throw new ArtifactStoreException("Could not store the file " + fileSHA1Naming, e);
}
Files.move(file, fileSHA1Naming);
}
if (!file.delete()) {
LOG.debug("Could not delete temp file {}", file);
}
return fileSystemArtifact;
}
private AbstractDbArtifact checkHashes(final AbstractDbArtifact artifact, final DbArtifactHash hash) {
if (hash == null) {
return artifact;
}
if (hash.getSha1() != null && !artifact.getHashes().getSha1().equals(hash.getSha1())) {
throw new HashNotMatchException("The given sha1 hash " + hash.getSha1()
+ " does not match with the calcualted sha1 hash " + artifact.getHashes().getSha1(),
HashNotMatchException.SHA1);
}
if (hash.getMd5() != null && !artifact.getHashes().getMd5().equals(hash.getMd5())) {
throw new HashNotMatchException("The given md5 hash " + hash.getMd5()
+ " does not match with the calcualted md5 hash " + artifact.getHashes().getMd5(),
HashNotMatchException.MD5);
}
return artifact;
}
private File createTempFile() {
try {
return File.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX);
} catch (final IOException e) {
throw new ArtifactStoreException("Cannot create tempfile", e);
}
return new ArtifactFilesystem(fileSHA1Naming, artifact.getArtifactId(), artifact.getHashes(),
artifact.getSize(), artifact.getContentType());
}
private File getFile(final String tenant, final String sha1) {
@@ -192,18 +99,9 @@ public class ArtifactFilesystemRepository implements ArtifactRepository {
return Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant), folder1, folder2);
}
private DigestOutputStream openFileOutputStream(final File file, final MessageDigest mdSHA1,
final MessageDigest mdMD5) throws FileNotFoundException {
return new DigestOutputStream(
new DigestOutputStream(new BufferedOutputStream(new FileOutputStream(file)), mdMD5), mdSHA1);
}
@Override
public void deleteByTenant(final String tenant) {
FileUtils.deleteQuietly(Paths.get(artifactResourceProperties.getPath(), sanitizeTenant(tenant)).toFile());
}
private static String sanitizeTenant(final String tenant) {
return tenant.trim().toUpperCase();
}
}

View File

@@ -37,7 +37,7 @@ public class ArtifactFilesystemRepositoryTest {
@Description("Verfies that an artifact can be successfully stored in the file-system repository")
public void storeSuccessfully() throws IOException {
final byte[] fileContent = randomBytes();
final ArtifactFilesystem artifact = storeRandomArtifact(fileContent);
final AbstractDbArtifact artifact = storeRandomArtifact(fileContent);
final byte[] readContent = new byte[fileContent.length];
IOUtils.read(artifact.getFileInputStream(), readContent);
@@ -50,7 +50,7 @@ public class ArtifactFilesystemRepositoryTest {
public void getStoredArtifactBasedOnSHA1Hash() {
final byte[] fileContent = randomBytes();
final ArtifactFilesystem artifact = storeRandomArtifact(fileContent);
final AbstractDbArtifact artifact = storeRandomArtifact(fileContent);
final AbstractDbArtifact artifactBySha1 = artifactFilesystemRepository.getArtifactBySha1(TENANT,
artifact.getHashes().getSha1());
@@ -60,7 +60,7 @@ public class ArtifactFilesystemRepositoryTest {
@Test
@Description("Verfies that an artifact can be deleted in the file-system repository")
public void deleteStoredArtifactBySHA1Hash() {
final ArtifactFilesystem artifact = storeRandomArtifact(randomBytes());
final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes());
artifactFilesystemRepository.deleteBySha1(TENANT, artifact.getHashes().getSha1());
@@ -70,7 +70,7 @@ public class ArtifactFilesystemRepositoryTest {
@Test
@Description("Verfies that all artifacts of a tenant can be deleted in the file-system repository")
public void deleteStoredArtifactOfTenant() {
final ArtifactFilesystem artifact = storeRandomArtifact(randomBytes());
final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes());
artifactFilesystemRepository.deleteByTenant(TENANT);
@@ -86,7 +86,7 @@ public class ArtifactFilesystemRepositoryTest {
Assertions.fail("did not expect an exception while deleting a file which does not exists");
}
final ArtifactFilesystem artifact = storeRandomArtifact(randomBytes());
final AbstractDbArtifact artifact = storeRandomArtifact(randomBytes());
try {
artifactFilesystemRepository.deleteBySha1("tenantWhichDoesNotExist", artifact.getHashes().getSha1());
} catch (final Exception e) {
@@ -94,12 +94,10 @@ public class ArtifactFilesystemRepositoryTest {
}
}
private ArtifactFilesystem storeRandomArtifact(final byte[] fileContent) {
private AbstractDbArtifact storeRandomArtifact(final byte[] fileContent) {
final String fileName = "filename.tmp";
final ByteArrayInputStream inputStream = new ByteArrayInputStream(fileContent);
final ArtifactFilesystem store = artifactFilesystemRepository.store(TENANT, inputStream, fileName,
"application/txt");
return store;
return artifactFilesystemRepository.store(TENANT, inputStream, fileName, "application/txt", null);
}
private static byte[] randomBytes() {