Skip to content

Commit

Permalink
Merge tag 'v1.2.0'
Browse files Browse the repository at this point in the history
[maven-release-plugin] copy for tag v1.2.0
  • Loading branch information
sparkoo committed Aug 9, 2017
2 parents 25ca3ba + 06e15f1 commit d6d3359
Show file tree
Hide file tree
Showing 21 changed files with 456 additions and 37 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,6 @@ nbdist/
.nb-gradle/

application.properties
test_repository/
test_repository/
/pom.xml.releaseBackup
/release.properties
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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`
or as command line arguments `java -jar -Dbox.home=/tmp/test_repository target/boxsitory-${version}.jar`
4 changes: 3 additions & 1 deletion application.properties_template
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
box.home=/custom/test/repository/path
box.host_prefix=sftp://localhost:
server.port=8083
server.port=8083
box.checksum=disabled
box.sort_desc=false
8 changes: 6 additions & 2 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

<groupId>cz.sparko.boxitory</groupId>
<artifactId>boxitory</artifactId>
<version>1.1.0</version>
<version>1.2.0</version>
<packaging>jar</packaging>

<name>boxitory</name>
Expand Down Expand Up @@ -34,7 +34,7 @@
<url>https://github.com/sparkoo/boxitory</url>
<connection>scm:git:git://github.com/sparkoo/boxitory.git</connection>
<developerConnection>scm:git:[email protected]:sparkoo/boxitory.git</developerConnection>
<tag>v1.1.0</tag>
<tag>v1.2.0</tag>
</scm>

<properties>
Expand All @@ -48,6 +48,10 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
Expand Down
9 changes: 7 additions & 2 deletions src/main/java/cz/sparko/boxitory/App.java
Original file line number Diff line number Diff line change
@@ -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 {

Expand All @@ -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);
}
}
18 changes: 18 additions & 0 deletions src/main/java/cz/sparko/boxitory/conf/AppProperties.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
}
Expand All @@ -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;
}
}
17 changes: 12 additions & 5 deletions src/main/java/cz/sparko/boxitory/controller/BoxController.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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";
}
}
3 changes: 3 additions & 0 deletions src/main/java/cz/sparko/boxitory/domain/Box.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
21 changes: 18 additions & 3 deletions src/main/java/cz/sparko/boxitory/domain/BoxProvider.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
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
public String toString() {
return "BoxProvider{" +
"url='" + url + '\'' +
", name='" + name + '\'' +
", checksumType='" + checksumType + '\'' +
", checksum='" + checksum + '\'' +
'}';
}

Expand All @@ -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() {
Expand All @@ -40,4 +51,8 @@ public String getUrl() {
public String getName() {
return name;
}

public String getChecksumType() { return checksumType; }

public String getChecksum() { return checksum; }
}
31 changes: 31 additions & 0 deletions src/main/java/cz/sparko/boxitory/factory/HashServiceFactory.java
Original file line number Diff line number Diff line change
@@ -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"
);
}
}
}
9 changes: 9 additions & 0 deletions src/main/java/cz/sparko/boxitory/service/BoxRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import cz.sparko.boxitory.domain.Box;

import java.util.List;
import java.util.Optional;

public interface BoxRepository {
Expand All @@ -12,4 +13,12 @@ public interface BoxRepository {
* @return {@link Box} when found, {@link Optional#empty()} when not found
*/
Optional<Box> 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<String> getBoxes();
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> getBoxes() {
return Arrays.stream(boxHome.listFiles(File::isDirectory))
.filter(this::containsValidBoxFile)
.map(File::getName)
.sorted()
.collect(Collectors.toList());
}

@Override
public Optional<Box> getBox(String boxName) {
Map<String, List<File>> groupedBoxFiles = new HashMap<>();
Expand Down Expand Up @@ -71,8 +83,9 @@ private Map<String, List<File>> groupBoxFilesByVersion(File boxDir) {

private boolean validateFilename(File boxFile) {
String filename = boxFile.getName();
List<String> 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;
}
Expand Down Expand Up @@ -109,10 +122,21 @@ private BoxVersion createBoxVersion(String version, List<File> fileList) {
private BoxProvider createBoxProviderFromFile(File file) {
String filename = file.getName();
List<String> 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;
}
}
Loading

0 comments on commit d6d3359

Please sign in to comment.