diff --git a/.gitignore b/.gitignore
index 65cc287..13675ca 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,4 +24,6 @@ nbdist/
.nb-gradle/
application.properties
-test_repository/
\ No newline at end of file
+test_repository/
+/pom.xml.releaseBackup
+/release.properties
diff --git a/README.md b/README.md
index f2a3045..acba8b1 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,12 @@ is repository for Vagrant's Virtual Machine boxes, which can manage box versions
By default, http server will start on port *8083*.
+#### Build status (travis-ci)
+
+devel [![Build Status](https://travis-ci.org/sparkoo/boxitory.svg?branch=devel)](https://travis-ci.org/sparkoo/boxitory)
+
+master: [![Build Status](https://travis-ci.org/sparkoo/boxitory.svg?branch=master)](https://travis-ci.org/sparkoo/boxitory)
+
## How it works
*Boxitory* currently implements just filesystem box provider. That requires strict folder structure.
@@ -72,11 +78,26 @@ $ curl http://localhost:8083/f26
* do define for example protocol or server, where boxes are placed
* e.g.: `sftp://my_box_server:`
* **default value**: *empty*
-
+ * `box.sort_desc`
+ * boolean value `true|false`
+ * when default or `false`, boxes are sorted by version in ascending order
+ * when `true`, boxes are sorted by version in descending order
+ * default value: `false`
+ * `box.checksum`
+ * string value: `disabled|md5|sha1|sha256`
+ * default value: `disabled`
+ * when default or `disabled` boxes output json not contains properties `checksumType` and `checksum`
+ * when `md5|sha1|sha256` boxes output json contains properties `checksumType` and `checksum` with coresponding values
+### Advanced Options
+ * `box.checksum_buffer_size`
+ * Box file is loaded to this buffer to calculate box checksums
+ * default value: `1024`
+
+### How to configuration
Configuration can be provided by `application.properties` file on classpath
```
# application.properties
box.home=/tmp/test_repository
box.prefix=sftp://my_box_server:
```
-or as command line arguments `java -jar -Dbox.home=/tmp/test_repository target/boxsitory-${version}.jar`
\ No newline at end of file
+or as command line arguments `java -jar -Dbox.home=/tmp/test_repository target/boxsitory-${version}.jar`
diff --git a/application.properties_template b/application.properties_template
index 77495fb..21b68a0 100644
--- a/application.properties_template
+++ b/application.properties_template
@@ -1,3 +1,5 @@
box.home=/custom/test/repository/path
box.host_prefix=sftp://localhost:
-server.port=8083
\ No newline at end of file
+server.port=8083
+box.checksum=disabled
+box.sort_desc=false
diff --git a/pom.xml b/pom.xml
index a8cb36c..3af461b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
cz.sparko.boxitory
boxitory
- 1.1.0
+ 1.2.0
jar
boxitory
@@ -34,7 +34,7 @@
https://github.com/sparkoo/boxitory
scm:git:git://github.com/sparkoo/boxitory.git
scm:git:git@github.com:sparkoo/boxitory.git
- v1.1.0
+ v1.2.0
@@ -48,6 +48,10 @@
org.springframework.boot
spring-boot-starter-web
+
+ org.springframework.boot
+ spring-boot-starter-thymeleaf
+
org.springframework.boot
spring-boot-configuration-processor
diff --git a/src/main/java/cz/sparko/boxitory/App.java b/src/main/java/cz/sparko/boxitory/App.java
index db754e8..db4acec 100644
--- a/src/main/java/cz/sparko/boxitory/App.java
+++ b/src/main/java/cz/sparko/boxitory/App.java
@@ -1,13 +1,17 @@
package cz.sparko.boxitory;
import cz.sparko.boxitory.conf.AppProperties;
+import cz.sparko.boxitory.factory.HashServiceFactory;
import cz.sparko.boxitory.service.BoxRepository;
import cz.sparko.boxitory.service.FilesystemBoxRepository;
+import cz.sparko.boxitory.service.HashService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
+import java.security.NoSuchAlgorithmException;
+
@SpringBootApplication
public class App {
@@ -17,7 +21,8 @@ public static void main(String[] args) {
@Bean
@Autowired
- public BoxRepository boxRepository(AppProperties appProperties) {
- return new FilesystemBoxRepository(appProperties);
+ public BoxRepository boxRepository(AppProperties appProperties) throws NoSuchAlgorithmException {
+ HashService hashService = HashServiceFactory.createHashService(appProperties);
+ return new FilesystemBoxRepository(appProperties, hashService);
}
}
diff --git a/src/main/java/cz/sparko/boxitory/conf/AppProperties.java b/src/main/java/cz/sparko/boxitory/conf/AppProperties.java
index f027979..5e0f01d 100644
--- a/src/main/java/cz/sparko/boxitory/conf/AppProperties.java
+++ b/src/main/java/cz/sparko/boxitory/conf/AppProperties.java
@@ -8,7 +8,9 @@
public class AppProperties {
private String home = ".";
private String host_prefix = "";
+ private String checksum = "disabled";
private boolean sort_desc = false;
+ private int checksum_buffer_size = 1024;
public String getHome() {
return home;
@@ -22,6 +24,14 @@ public boolean isSort_desc() {
return sort_desc;
}
+ public String getChecksum() {
+ return checksum;
+ }
+
+ public int getChecksum_buffer_size() {
+ return checksum_buffer_size;
+ }
+
public void setSort_desc(boolean sort_desc) {
this.sort_desc = sort_desc;
}
@@ -33,4 +43,12 @@ public void setHome(String home) {
public void setHost_prefix(String host_prefix) {
this.host_prefix = host_prefix;
}
+
+ public void setChecksum(String checksum) {
+ this.checksum = checksum;
+ }
+
+ public void setChecksum_buffer_size(int checksum_buffer_size) {
+ this.checksum_buffer_size = checksum_buffer_size;
+ }
}
diff --git a/src/main/java/cz/sparko/boxitory/controller/BoxController.java b/src/main/java/cz/sparko/boxitory/controller/BoxController.java
index e0144bc..977a939 100644
--- a/src/main/java/cz/sparko/boxitory/controller/BoxController.java
+++ b/src/main/java/cz/sparko/boxitory/controller/BoxController.java
@@ -4,10 +4,11 @@
import cz.sparko.boxitory.domain.Box;
import cz.sparko.boxitory.service.BoxRepository;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
-@RestController
-@RequestMapping(value = "/", method = RequestMethod.GET)
+@Controller
public class BoxController {
private BoxRepository boxRepository;
@@ -16,10 +17,16 @@ public BoxController(BoxRepository boxRepository) {
this.boxRepository = boxRepository;
}
- @RequestMapping("{boxName}")
+ @RequestMapping(value = "/{boxName}", method = RequestMethod.GET)
@ResponseBody
- public Box getBoxes(@PathVariable String boxName) {
+ public Box box(@PathVariable String boxName) {
return boxRepository.getBox(boxName)
- .orElseThrow(() -> new NotFoundException("[" + boxName + "] does not exist"));
+ .orElseThrow(() -> new NotFoundException("box [" + boxName + "] does not exist"));
+ }
+
+ @RequestMapping(value = "/", method = RequestMethod.GET)
+ public String index(Model model) {
+ model.addAttribute("boxes", boxRepository.getBoxes());
+ return "index";
}
}
diff --git a/src/main/java/cz/sparko/boxitory/domain/Box.java b/src/main/java/cz/sparko/boxitory/domain/Box.java
index d4c686f..75a670b 100644
--- a/src/main/java/cz/sparko/boxitory/domain/Box.java
+++ b/src/main/java/cz/sparko/boxitory/domain/Box.java
@@ -3,6 +3,9 @@
import java.util.List;
import java.util.Objects;
+/**
+ * Full description of Vagrant's box as needed in http API.
+ */
public class Box {
private final String name;
private final String description;
diff --git a/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java b/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java
index 7a96517..1901716 100644
--- a/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java
+++ b/src/main/java/cz/sparko/boxitory/domain/BoxProvider.java
@@ -1,14 +1,21 @@
package cz.sparko.boxitory.domain;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
import java.util.Objects;
+@JsonInclude(JsonInclude.Include.NON_NULL)
public class BoxProvider {
private final String url;
private final String name;
+ private final String checksumType;
+ private final String checksum;
- public BoxProvider(String url, String name) {
+ public BoxProvider(String url, String name, String checksumType, String checksum) {
this.url = url;
this.name = name;
+ this.checksumType = checksumType;
+ this.checksum = checksum;
}
@Override
@@ -16,6 +23,8 @@ public String toString() {
return "BoxProvider{" +
"url='" + url + '\'' +
", name='" + name + '\'' +
+ ", checksumType='" + checksumType + '\'' +
+ ", checksum='" + checksum + '\'' +
'}';
}
@@ -25,12 +34,14 @@ public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) { return false; }
BoxProvider that = (BoxProvider) o;
return Objects.equals(url, that.url) &&
- Objects.equals(name, that.name);
+ Objects.equals(name, that.name) &&
+ Objects.equals(checksumType, that.checksumType) &&
+ Objects.equals(checksum, that.checksum);
}
@Override
public int hashCode() {
- return Objects.hash(url, name);
+ return Objects.hash(url, name, checksumType, checksum);
}
public String getUrl() {
@@ -40,4 +51,8 @@ public String getUrl() {
public String getName() {
return name;
}
+
+ public String getChecksumType() { return checksumType; }
+
+ public String getChecksum() { return checksum; }
}
diff --git a/src/main/java/cz/sparko/boxitory/factory/HashServiceFactory.java b/src/main/java/cz/sparko/boxitory/factory/HashServiceFactory.java
new file mode 100644
index 0000000..a1e7e84
--- /dev/null
+++ b/src/main/java/cz/sparko/boxitory/factory/HashServiceFactory.java
@@ -0,0 +1,31 @@
+package cz.sparko.boxitory.factory;
+
+import cz.sparko.boxitory.conf.AppProperties;
+import cz.sparko.boxitory.service.FilesystemDigestHashService;
+import cz.sparko.boxitory.service.NoopHashService;
+import cz.sparko.boxitory.service.HashService;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class HashServiceFactory {
+
+ public static HashService createHashService(AppProperties appProperties) throws NoSuchAlgorithmException {
+ String algorithm = appProperties.getChecksum().toUpperCase();
+
+ switch (algorithm) {
+ case "MD5":
+ return new FilesystemDigestHashService(MessageDigest.getInstance(algorithm), appProperties);
+ case "SHA1":
+ return new FilesystemDigestHashService(MessageDigest.getInstance("SHA-1"), appProperties);
+ case "SHA256":
+ return new FilesystemDigestHashService(MessageDigest.getInstance("SHA-256"), appProperties);
+ case "DISABLED":
+ return new NoopHashService();
+ default:
+ throw new IllegalArgumentException(
+ "Configured checksum type (box.checksum=" + algorithm + ") is not supported"
+ );
+ }
+ }
+}
diff --git a/src/main/java/cz/sparko/boxitory/service/BoxRepository.java b/src/main/java/cz/sparko/boxitory/service/BoxRepository.java
index 6b6e061..4171661 100644
--- a/src/main/java/cz/sparko/boxitory/service/BoxRepository.java
+++ b/src/main/java/cz/sparko/boxitory/service/BoxRepository.java
@@ -2,6 +2,7 @@
import cz.sparko.boxitory.domain.Box;
+import java.util.List;
import java.util.Optional;
public interface BoxRepository {
@@ -12,4 +13,12 @@ public interface BoxRepository {
* @return {@link Box} when found, {@link Optional#empty()} when not found
*/
Optional getBox(String boxName);
+
+ /**
+ * Returns {@link List} of names of available {@link Box}es. Call {@link BoxRepository#getBox(String)} with any of
+ * returned name should get valid result.
+ *
+ * @return names of available {@link Box}es
+ */
+ List getBoxes();
}
diff --git a/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java b/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java
index 3132f92..95d1b67 100644
--- a/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java
+++ b/src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java
@@ -8,28 +8,40 @@
import org.slf4j.LoggerFactory;
import java.io.File;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static java.lang.Integer.compare;
-import static java.lang.Integer.parseInt;
-import static java.util.Comparator.comparingInt;
public class FilesystemBoxRepository implements BoxRepository {
private static final Logger LOG = LoggerFactory.getLogger(FilesystemBoxRepository.class);
private final String hostPrefix;
private final File boxHome;
+ private final HashService hashService;
private final boolean sortDesc;
- public FilesystemBoxRepository(AppProperties appProperties) {
+ public FilesystemBoxRepository(AppProperties appProperties, HashService hashService) {
this.boxHome = new File(appProperties.getHome());
this.hostPrefix = appProperties.getHost_prefix();
this.sortDesc = appProperties.isSort_desc();
+ this.hashService = hashService;
LOG.info("setting BOX_HOME as [{}] and HOST_PREFIX as [{}]", boxHome.getAbsolutePath(), hostPrefix);
}
+ @Override
+ public List getBoxes() {
+ return Arrays.stream(boxHome.listFiles(File::isDirectory))
+ .filter(this::containsValidBoxFile)
+ .map(File::getName)
+ .sorted()
+ .collect(Collectors.toList());
+ }
+
@Override
public Optional getBox(String boxName) {
Map> groupedBoxFiles = new HashMap<>();
@@ -71,8 +83,9 @@ private Map> groupBoxFilesByVersion(File boxDir) {
private boolean validateFilename(File boxFile) {
String filename = boxFile.getName();
- List parsedFilename = Arrays.asList(filename.split("_"));
- if (parsedFilename.size() != 3) {
+ File parentDir = boxFile.getParentFile();
+
+ if (!filename.matches(parentDir.getName() + "_(\\d+)_(\\w+)\\.box")) {
LOG.warn("box file [{}] has wrong name. must be in format ${name}_${version}_${provider}.box", filename);
return false;
}
@@ -109,10 +122,21 @@ private BoxVersion createBoxVersion(String version, List fileList) {
private BoxProvider createBoxProviderFromFile(File file) {
String filename = file.getName();
List parsedFilename = Arrays.asList(filename.split("_"));
+
String provider = parsedFilename.get(2);
if (provider.endsWith(".box")) {
provider = provider.substring(0, provider.length() - 4);
}
- return new BoxProvider(hostPrefix + file.getAbsolutePath(), provider);
+ return new BoxProvider(
+ hostPrefix + file.getAbsolutePath(),
+ provider,
+ hashService.getHashType(),
+ hashService.getChecksum(file.getAbsolutePath())
+ );
+ }
+
+ private boolean containsValidBoxFile(File file) {
+ File[] files = file.listFiles(this::validateFilename);
+ return files.length > 0;
}
}
diff --git a/src/main/java/cz/sparko/boxitory/service/FilesystemDigestHashService.java b/src/main/java/cz/sparko/boxitory/service/FilesystemDigestHashService.java
new file mode 100644
index 0000000..ebcfb04
--- /dev/null
+++ b/src/main/java/cz/sparko/boxitory/service/FilesystemDigestHashService.java
@@ -0,0 +1,75 @@
+package cz.sparko.boxitory.service;
+
+import cz.sparko.boxitory.conf.AppProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.xml.bind.DatatypeConverter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.security.MessageDigest;
+import java.util.Objects;
+
+public class FilesystemDigestHashService implements HashService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(FilesystemDigestHashService.class);
+ private MessageDigest messageDigest;
+ private int streamBufferLength;
+
+ public FilesystemDigestHashService(MessageDigest messageDigest, AppProperties appProperties) {
+ this.messageDigest = messageDigest;
+ streamBufferLength = appProperties.getChecksum_buffer_size();
+ }
+
+ @Override
+ public String getHashType() {
+ return messageDigest.getAlgorithm().replaceAll("-", "").toLowerCase();
+ }
+
+ @Override
+ public String getChecksum(String string) {
+ try (InputStream boxDataStream = Files.newInputStream(new File(string).toPath())) {
+ LOG.trace("buffering box data (buffer size [{}]b) ...", streamBufferLength);
+ final byte[] buffer = new byte[streamBufferLength];
+ int read = boxDataStream.read(buffer, 0, streamBufferLength);
+
+ while (read > -1) {
+ messageDigest.update(buffer, 0, read);
+ read = boxDataStream.read(buffer, 0, streamBufferLength);
+ }
+ } catch (IOException e) {
+ LOG.error("Error during processing file [{}], message: [{}]", string, e.getMessage());
+ throw new RuntimeException(
+ "Error while getting checksum for file " + string + " reason: " + e.getMessage(), e
+ );
+ }
+
+ return getHash(messageDigest.digest());
+ }
+
+ private String getHash(byte[] diggestBytes) {
+ return DatatypeConverter.printHexBinary(diggestBytes).toLowerCase();
+ }
+
+ @Override
+ public String toString() {
+ return "FilesystemDigestHashService{" +
+ "messageDigest=" + messageDigest +
+ '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) { return true; }
+ if (o == null || getClass() != o.getClass()) { return false; }
+ FilesystemDigestHashService that = (FilesystemDigestHashService) o;
+ return messageDigest.getAlgorithm().equals(that.messageDigest.getAlgorithm());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(messageDigest);
+ }
+}
diff --git a/src/main/java/cz/sparko/boxitory/service/HashService.java b/src/main/java/cz/sparko/boxitory/service/HashService.java
new file mode 100644
index 0000000..75482a1
--- /dev/null
+++ b/src/main/java/cz/sparko/boxitory/service/HashService.java
@@ -0,0 +1,7 @@
+package cz.sparko.boxitory.service;
+
+
+public interface HashService {
+ String getHashType();
+ String getChecksum(String string);
+}
diff --git a/src/main/java/cz/sparko/boxitory/service/NoopHashService.java b/src/main/java/cz/sparko/boxitory/service/NoopHashService.java
new file mode 100644
index 0000000..f3aeaa5
--- /dev/null
+++ b/src/main/java/cz/sparko/boxitory/service/NoopHashService.java
@@ -0,0 +1,20 @@
+package cz.sparko.boxitory.service;
+
+
+public class NoopHashService implements HashService {
+
+ @Override
+ public String getHashType() {
+ return null;
+ }
+
+ @Override
+ public String getChecksum(String string) {
+ return null;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ return obj.getClass().getName().equals(NoopHashService.class.getName());
+ }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 9146c65..21818de 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,4 +1,5 @@
box.home=.
box.host_prefix=
+box.checksum=disabled
server.port=8083
box.sort_desc=false
\ No newline at end of file
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
new file mode 100644
index 0000000..b9cbec6
--- /dev/null
+++ b/src/main/resources/logback.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/templates/index.html b/src/main/resources/templates/index.html
new file mode 100644
index 0000000..f951981
--- /dev/null
+++ b/src/main/resources/templates/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+Available boxes
+
+
+
\ No newline at end of file
diff --git a/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java b/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java
index 0380a4a..4198b99 100644
--- a/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java
+++ b/src/test/java/cz/sparko/boxitory/service/FilesystemBoxRepositoryTest.java
@@ -19,6 +19,8 @@
import java.util.Optional;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
@SpringBootTest
public class FilesystemBoxRepositoryTest {
@@ -82,23 +84,28 @@ public Object[][] boxes() {
{"f25", Optional.of(new Box("f25", "f25",
Arrays.asList(
new BoxVersion("1", Collections.singletonList(
- new BoxProvider(composePath("f25", "1", "virtualbox"), "virtualbox")
+ new BoxProvider(composePath("f25", "1", "virtualbox"),
+ "virtualbox", null, null)
)),
new BoxVersion("2", Collections.singletonList(
- new BoxProvider(composePath("f25", "2", "virtualbox"), "virtualbox")
+ new BoxProvider(composePath("f25", "2", "virtualbox"),
+ "virtualbox", null, null)
))
)))
},
{"f26", Optional.of(new Box("f26", "f26",
Arrays.asList(
new BoxVersion("1", Collections.singletonList(
- new BoxProvider(composePath("f26", "1", "virtualbox"), "virtualbox")
+ new BoxProvider(composePath("f26", "1", "virtualbox"),
+ "virtualbox", null, null)
)),
new BoxVersion("2", Collections.singletonList(
- new BoxProvider(composePath("f26", "2", "virtualbox"), "virtualbox")
+ new BoxProvider(composePath("f26", "2", "virtualbox"),
+ "virtualbox", null, null)
)),
new BoxVersion("3", Collections.singletonList(
- new BoxProvider(composePath("f26", "3", "virtualbox"), "virtualbox")
+ new BoxProvider(composePath("f26", "3", "virtualbox"),
+ "virtualbox", null, null)
))
)))
},
@@ -106,11 +113,14 @@ public Object[][] boxes() {
{"f28", Optional.of(new Box("f28", "f28",
Arrays.asList(
new BoxVersion("1", Arrays.asList(
- new BoxProvider(composePath("f28", "1", "virtualbox"), "virtualbox"),
- new BoxProvider(composePath("f28", "1", "vmware"), "vmware")
+ new BoxProvider(composePath("f28", "1", "virtualbox"),
+ "virtualbox", null, null),
+ new BoxProvider(composePath("f28", "1", "vmware"),
+ "vmware", null, null)
)),
new BoxVersion("2", Collections.singletonList(
- new BoxProvider(composePath("f28", "2", "virtualbox"), "virtualbox")
+ new BoxProvider(composePath("f28", "2", "virtualbox"),
+ "virtualbox", null, null)
))
)))
},
@@ -121,7 +131,7 @@ public Object[][] boxes() {
@Test(dataProvider = "boxes")
public void givenRepository_whenGetBox_thenGetWhenFound(String boxName, Optional expectedResult) {
- BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties);
+ BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService());
Optional providedBox = boxRepository.getBox(boxName);
@@ -134,7 +144,7 @@ public void givenRepository_whenGetBox_thenGetWhenFound(String boxName, Optional
public void givenSortAscending_whenGetBox_thenVersionsSortedAsc() {
testAppProperties.setSort_desc(false);
- BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties);
+ BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService());
List versions = boxRepository.getBox("f29").get().getVersions();
assertEquals(versions.get(0).getVersion(), "1");
@@ -146,7 +156,7 @@ public void givenSortAscending_whenGetBox_thenVersionsSortedAsc() {
public void givenSortDescending_whenGetBox_thenVersionsSortedDesc() {
testAppProperties.setSort_desc(true);
- BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties);
+ BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService());
List versions = boxRepository.getBox("f29").get().getVersions();
assertEquals(versions.get(0).getVersion(), "3");
@@ -154,6 +164,15 @@ public void givenSortDescending_whenGetBox_thenVersionsSortedDesc() {
assertEquals(versions.get(2).getVersion(), "1");
}
+ @Test
+ public void givenValidRepositoryWithBoxes_whenIndex_thenGetValidBoxes() {
+ BoxRepository boxRepository = new FilesystemBoxRepository(testAppProperties, new NoopHashService());
+
+ List boxes = boxRepository.getBoxes();
+ assertTrue(boxes.containsAll(Arrays.asList("f25", "f26", "f28", "f29")));
+ assertFalse(boxes.containsAll(Arrays.asList("f27")));
+ }
+
private String composePath(String boxName, String version, String provider) {
return String.format("%s%s/%s/%s_%s_%s.box", TEST_BOX_PREFIX, testHomeDir.getAbsolutePath(),
boxName, boxName, version, provider);
diff --git a/src/test/java/cz/sparko/boxitory/service/FilesystemDigestHashServiceTest.java b/src/test/java/cz/sparko/boxitory/service/FilesystemDigestHashServiceTest.java
new file mode 100644
index 0000000..c4c274d
--- /dev/null
+++ b/src/test/java/cz/sparko/boxitory/service/FilesystemDigestHashServiceTest.java
@@ -0,0 +1,85 @@
+package cz.sparko.boxitory.service;
+
+import cz.sparko.boxitory.conf.AppProperties;
+import org.apache.commons.io.FileUtils;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import static org.testng.Assert.assertEquals;
+
+@SpringBootTest
+public class FilesystemDigestHashServiceTest {
+
+ private final String TEST_HOME = "test_repository";
+ private File testHomeDir;
+
+ @BeforeClass
+ public void setUp() throws IOException {
+ testHomeDir = new File(TEST_HOME);
+
+ createTestFolderStructure();
+ }
+
+ private void createTestFolderStructure() throws IOException {
+ testHomeDir.mkdir();
+ File f25 = new File(testHomeDir.getAbsolutePath() + "/f25");
+ File f26 = new File(testHomeDir.getAbsolutePath() + "/f26");
+ File f27 = new File(testHomeDir.getAbsolutePath() + "/f27");
+
+ f25.mkdir();
+ f26.mkdir();
+ f27.mkdir();
+
+ File f25box1 = new File(f25.getAbsolutePath() + "/f25_1_virtualbox.box");
+ f25box1.createNewFile();
+ FileWriter fileWriter = new FileWriter(f25box1);
+ fileWriter.write("123456789\n987654321\nabcdefghi");
+ fileWriter.close();
+ }
+
+ @AfterClass
+ public void tearDown() throws IOException {
+ FileUtils.deleteDirectory(testHomeDir);
+ }
+
+ @DataProvider
+ public Object[][] filesAndHashes() {
+ return new Object[][]{
+ {
+ "MD5",
+ new File(testHomeDir.getAbsolutePath() + "/f25/f25_1_virtualbox.box"),
+ "86462c346f1358ddbf4f137fb5da43cf"
+ },
+ {
+ "SHA-1",
+ new File(testHomeDir.getAbsolutePath() + "/f25/f25_1_virtualbox.box"),
+ "6efeafd3d3304cf5d7fd37db2a7ddbaac09f425d"
+ },
+ {
+ "SHA-256",
+ new File(testHomeDir.getAbsolutePath() + "/f25/f25_1_virtualbox.box"),
+ "ae4fe7f29f683d3901d4c620ef2e3c7ed17ebb6813158efd6a16f81b71a0aa43"
+ }
+ };
+ }
+
+ @Test(dataProvider = "filesAndHashes")
+ public void givenHashService_whenGetChecksum_thenChecksumsAreEquals(String algorithm, File file, String
+ expectedChecksum) throws NoSuchAlgorithmException {
+ HashService hashService = new FilesystemDigestHashService(MessageDigest.getInstance(algorithm), new AppProperties());
+
+ String checksum = hashService.getChecksum(file.getAbsolutePath());
+
+ assertEquals(checksum, expectedChecksum);
+ }
+
+}
diff --git a/src/test/java/cz/sparko/boxitory/service/HashServiceFactoryTest.java b/src/test/java/cz/sparko/boxitory/service/HashServiceFactoryTest.java
new file mode 100644
index 0000000..aa0bd20
--- /dev/null
+++ b/src/test/java/cz/sparko/boxitory/service/HashServiceFactoryTest.java
@@ -0,0 +1,43 @@
+package cz.sparko.boxitory.service;
+
+import cz.sparko.boxitory.conf.AppProperties;
+import cz.sparko.boxitory.factory.HashServiceFactory;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+
+import static org.testng.Assert.assertEquals;
+
+@SpringBootTest
+public class HashServiceFactoryTest {
+
+ @DataProvider
+ public Object[][] hashServiceTypes() throws NoSuchAlgorithmException {
+ return new Object[][]{
+ {"md5", new FilesystemDigestHashService(MessageDigest.getInstance("MD5"), new AppProperties())},
+ {"sha1", new FilesystemDigestHashService(MessageDigest.getInstance("SHA-1"), new AppProperties())},
+ {"sha256", new FilesystemDigestHashService(MessageDigest.getInstance("SHA-256"), new AppProperties())},
+ {"disabled", new NoopHashService()}
+ };
+ }
+
+ @Test(dataProvider = "hashServiceTypes")
+ public void givenFactory_whenCreateHashService_thenGetExpectedInstance(String type, HashService expectedService) throws NoSuchAlgorithmException {
+ AppProperties appProperties = new AppProperties();
+ appProperties.setChecksum(type);
+ HashService hashService = HashServiceFactory.createHashService(appProperties);
+
+ assertEquals(hashService, expectedService);
+ }
+
+ @Test(expectedExceptions = IllegalArgumentException.class)
+ public void givenFactory_whenCreateUnsupportedHashService_thenExceptionIsThrown() throws NoSuchAlgorithmException {
+ AppProperties appProperties = new AppProperties();
+ appProperties.setChecksum("foo");
+ HashServiceFactory.createHashService(appProperties);
+ }
+}