Skip to content

Commit d6d3359

Browse files
committed
Merge tag 'v1.2.0'
[maven-release-plugin] copy for tag v1.2.0
2 parents 25ca3ba + 06e15f1 commit d6d3359

21 files changed

+456
-37
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ nbdist/
2424
.nb-gradle/
2525

2626
application.properties
27-
test_repository/
27+
test_repository/
28+
/pom.xml.releaseBackup
29+
/release.properties

README.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@ is repository for Vagrant's Virtual Machine boxes, which can manage box versions
88

99
By default, http server will start on port *8083*.
1010

11+
#### Build status (travis-ci)
12+
13+
devel [![Build Status](https://travis-ci.org/sparkoo/boxitory.svg?branch=devel)](https://travis-ci.org/sparkoo/boxitory)
14+
15+
master: [![Build Status](https://travis-ci.org/sparkoo/boxitory.svg?branch=master)](https://travis-ci.org/sparkoo/boxitory)
16+
1117
## How it works
1218

1319
*Boxitory* currently implements just filesystem box provider. That requires strict folder structure.
@@ -72,11 +78,26 @@ $ curl http://localhost:8083/f26
7278
* do define for example protocol or server, where boxes are placed
7379
* e.g.: `sftp://my_box_server:`
7480
* **default value**: *empty*
75-
81+
* `box.sort_desc`
82+
* boolean value `true|false`
83+
* when default or `false`, boxes are sorted by version in ascending order
84+
* when `true`, boxes are sorted by version in descending order
85+
* default value: `false`
86+
* `box.checksum`
87+
* string value: `disabled|md5|sha1|sha256`
88+
* default value: `disabled`
89+
* when default or `disabled` boxes output json not contains properties `checksumType` and `checksum`
90+
* when `md5|sha1|sha256` boxes output json contains properties `checksumType` and `checksum` with coresponding values
91+
### Advanced Options
92+
* `box.checksum_buffer_size`
93+
* Box file is loaded to this buffer to calculate box checksums
94+
* default value: `1024`
95+
96+
### How to configuration
7697
Configuration can be provided by `application.properties` file on classpath
7798
```
7899
# application.properties
79100
box.home=/tmp/test_repository
80101
box.prefix=sftp://my_box_server:
81102
```
82-
or as command line arguments `java -jar -Dbox.home=/tmp/test_repository target/boxsitory-${version}.jar`
103+
or as command line arguments `java -jar -Dbox.home=/tmp/test_repository target/boxsitory-${version}.jar`

application.properties_template

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
box.home=/custom/test/repository/path
22
box.host_prefix=sftp://localhost:
3-
server.port=8083
3+
server.port=8083
4+
box.checksum=disabled
5+
box.sort_desc=false

pom.xml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
<groupId>cz.sparko.boxitory</groupId>
66
<artifactId>boxitory</artifactId>
7-
<version>1.1.0</version>
7+
<version>1.2.0</version>
88
<packaging>jar</packaging>
99

1010
<name>boxitory</name>
@@ -34,7 +34,7 @@
3434
<url>https://github.com/sparkoo/boxitory</url>
3535
<connection>scm:git:git://github.com/sparkoo/boxitory.git</connection>
3636
<developerConnection>scm:git:[email protected]:sparkoo/boxitory.git</developerConnection>
37-
<tag>v1.1.0</tag>
37+
<tag>v1.2.0</tag>
3838
</scm>
3939

4040
<properties>
@@ -48,6 +48,10 @@
4848
<groupId>org.springframework.boot</groupId>
4949
<artifactId>spring-boot-starter-web</artifactId>
5050
</dependency>
51+
<dependency>
52+
<groupId>org.springframework.boot</groupId>
53+
<artifactId>spring-boot-starter-thymeleaf</artifactId>
54+
</dependency>
5155
<dependency>
5256
<groupId>org.springframework.boot</groupId>
5357
<artifactId>spring-boot-configuration-processor</artifactId>
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
package cz.sparko.boxitory;
22

33
import cz.sparko.boxitory.conf.AppProperties;
4+
import cz.sparko.boxitory.factory.HashServiceFactory;
45
import cz.sparko.boxitory.service.BoxRepository;
56
import cz.sparko.boxitory.service.FilesystemBoxRepository;
7+
import cz.sparko.boxitory.service.HashService;
68
import org.springframework.beans.factory.annotation.Autowired;
79
import org.springframework.boot.SpringApplication;
810
import org.springframework.boot.autoconfigure.SpringBootApplication;
911
import org.springframework.context.annotation.Bean;
1012

13+
import java.security.NoSuchAlgorithmException;
14+
1115
@SpringBootApplication
1216
public class App {
1317

@@ -17,7 +21,8 @@ public static void main(String[] args) {
1721

1822
@Bean
1923
@Autowired
20-
public BoxRepository boxRepository(AppProperties appProperties) {
21-
return new FilesystemBoxRepository(appProperties);
24+
public BoxRepository boxRepository(AppProperties appProperties) throws NoSuchAlgorithmException {
25+
HashService hashService = HashServiceFactory.createHashService(appProperties);
26+
return new FilesystemBoxRepository(appProperties, hashService);
2227
}
2328
}

src/main/java/cz/sparko/boxitory/conf/AppProperties.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
public class AppProperties {
99
private String home = ".";
1010
private String host_prefix = "";
11+
private String checksum = "disabled";
1112
private boolean sort_desc = false;
13+
private int checksum_buffer_size = 1024;
1214

1315
public String getHome() {
1416
return home;
@@ -22,6 +24,14 @@ public boolean isSort_desc() {
2224
return sort_desc;
2325
}
2426

27+
public String getChecksum() {
28+
return checksum;
29+
}
30+
31+
public int getChecksum_buffer_size() {
32+
return checksum_buffer_size;
33+
}
34+
2535
public void setSort_desc(boolean sort_desc) {
2636
this.sort_desc = sort_desc;
2737
}
@@ -33,4 +43,12 @@ public void setHome(String home) {
3343
public void setHost_prefix(String host_prefix) {
3444
this.host_prefix = host_prefix;
3545
}
46+
47+
public void setChecksum(String checksum) {
48+
this.checksum = checksum;
49+
}
50+
51+
public void setChecksum_buffer_size(int checksum_buffer_size) {
52+
this.checksum_buffer_size = checksum_buffer_size;
53+
}
3654
}

src/main/java/cz/sparko/boxitory/controller/BoxController.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
import cz.sparko.boxitory.domain.Box;
55
import cz.sparko.boxitory.service.BoxRepository;
66
import org.springframework.beans.factory.annotation.Autowired;
7+
import org.springframework.stereotype.Controller;
8+
import org.springframework.ui.Model;
79
import org.springframework.web.bind.annotation.*;
810

9-
@RestController
10-
@RequestMapping(value = "/", method = RequestMethod.GET)
11+
@Controller
1112
public class BoxController {
1213
private BoxRepository boxRepository;
1314

@@ -16,10 +17,16 @@ public BoxController(BoxRepository boxRepository) {
1617
this.boxRepository = boxRepository;
1718
}
1819

19-
@RequestMapping("{boxName}")
20+
@RequestMapping(value = "/{boxName}", method = RequestMethod.GET)
2021
@ResponseBody
21-
public Box getBoxes(@PathVariable String boxName) {
22+
public Box box(@PathVariable String boxName) {
2223
return boxRepository.getBox(boxName)
23-
.orElseThrow(() -> new NotFoundException("[" + boxName + "] does not exist"));
24+
.orElseThrow(() -> new NotFoundException("box [" + boxName + "] does not exist"));
25+
}
26+
27+
@RequestMapping(value = "/", method = RequestMethod.GET)
28+
public String index(Model model) {
29+
model.addAttribute("boxes", boxRepository.getBoxes());
30+
return "index";
2431
}
2532
}

src/main/java/cz/sparko/boxitory/domain/Box.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
import java.util.List;
44
import java.util.Objects;
55

6+
/**
7+
* Full description of Vagrant's box as needed in http API.
8+
*/
69
public class Box {
710
private final String name;
811
private final String description;

src/main/java/cz/sparko/boxitory/domain/BoxProvider.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,30 @@
11
package cz.sparko.boxitory.domain;
22

3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
35
import java.util.Objects;
46

7+
@JsonInclude(JsonInclude.Include.NON_NULL)
58
public class BoxProvider {
69
private final String url;
710
private final String name;
11+
private final String checksumType;
12+
private final String checksum;
813

9-
public BoxProvider(String url, String name) {
14+
public BoxProvider(String url, String name, String checksumType, String checksum) {
1015
this.url = url;
1116
this.name = name;
17+
this.checksumType = checksumType;
18+
this.checksum = checksum;
1219
}
1320

1421
@Override
1522
public String toString() {
1623
return "BoxProvider{" +
1724
"url='" + url + '\'' +
1825
", name='" + name + '\'' +
26+
", checksumType='" + checksumType + '\'' +
27+
", checksum='" + checksum + '\'' +
1928
'}';
2029
}
2130

@@ -25,12 +34,14 @@ public boolean equals(Object o) {
2534
if (o == null || getClass() != o.getClass()) { return false; }
2635
BoxProvider that = (BoxProvider) o;
2736
return Objects.equals(url, that.url) &&
28-
Objects.equals(name, that.name);
37+
Objects.equals(name, that.name) &&
38+
Objects.equals(checksumType, that.checksumType) &&
39+
Objects.equals(checksum, that.checksum);
2940
}
3041

3142
@Override
3243
public int hashCode() {
33-
return Objects.hash(url, name);
44+
return Objects.hash(url, name, checksumType, checksum);
3445
}
3546

3647
public String getUrl() {
@@ -40,4 +51,8 @@ public String getUrl() {
4051
public String getName() {
4152
return name;
4253
}
54+
55+
public String getChecksumType() { return checksumType; }
56+
57+
public String getChecksum() { return checksum; }
4358
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package cz.sparko.boxitory.factory;
2+
3+
import cz.sparko.boxitory.conf.AppProperties;
4+
import cz.sparko.boxitory.service.FilesystemDigestHashService;
5+
import cz.sparko.boxitory.service.NoopHashService;
6+
import cz.sparko.boxitory.service.HashService;
7+
8+
import java.security.MessageDigest;
9+
import java.security.NoSuchAlgorithmException;
10+
11+
public class HashServiceFactory {
12+
13+
public static HashService createHashService(AppProperties appProperties) throws NoSuchAlgorithmException {
14+
String algorithm = appProperties.getChecksum().toUpperCase();
15+
16+
switch (algorithm) {
17+
case "MD5":
18+
return new FilesystemDigestHashService(MessageDigest.getInstance(algorithm), appProperties);
19+
case "SHA1":
20+
return new FilesystemDigestHashService(MessageDigest.getInstance("SHA-1"), appProperties);
21+
case "SHA256":
22+
return new FilesystemDigestHashService(MessageDigest.getInstance("SHA-256"), appProperties);
23+
case "DISABLED":
24+
return new NoopHashService();
25+
default:
26+
throw new IllegalArgumentException(
27+
"Configured checksum type (box.checksum=" + algorithm + ") is not supported"
28+
);
29+
}
30+
}
31+
}

src/main/java/cz/sparko/boxitory/service/BoxRepository.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import cz.sparko.boxitory.domain.Box;
44

5+
import java.util.List;
56
import java.util.Optional;
67

78
public interface BoxRepository {
@@ -12,4 +13,12 @@ public interface BoxRepository {
1213
* @return {@link Box} when found, {@link Optional#empty()} when not found
1314
*/
1415
Optional<Box> getBox(String boxName);
16+
17+
/**
18+
* Returns {@link List} of names of available {@link Box}es. Call {@link BoxRepository#getBox(String)} with any of
19+
* returned name should get valid result.
20+
*
21+
* @return names of available {@link Box}es
22+
*/
23+
List<String> getBoxes();
1524
}

src/main/java/cz/sparko/boxitory/service/FilesystemBoxRepository.java

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,40 @@
88
import org.slf4j.LoggerFactory;
99

1010
import java.io.File;
11-
import java.util.*;
11+
import java.util.ArrayList;
12+
import java.util.Arrays;
13+
import java.util.Comparator;
14+
import java.util.HashMap;
15+
import java.util.List;
16+
import java.util.Map;
17+
import java.util.Optional;
1218
import java.util.stream.Collectors;
13-
import java.util.stream.Stream;
14-
15-
import static java.lang.Integer.compare;
16-
import static java.lang.Integer.parseInt;
17-
import static java.util.Comparator.comparingInt;
1819

1920
public class FilesystemBoxRepository implements BoxRepository {
2021
private static final Logger LOG = LoggerFactory.getLogger(FilesystemBoxRepository.class);
2122

2223
private final String hostPrefix;
2324
private final File boxHome;
25+
private final HashService hashService;
2426
private final boolean sortDesc;
2527

26-
public FilesystemBoxRepository(AppProperties appProperties) {
28+
public FilesystemBoxRepository(AppProperties appProperties, HashService hashService) {
2729
this.boxHome = new File(appProperties.getHome());
2830
this.hostPrefix = appProperties.getHost_prefix();
2931
this.sortDesc = appProperties.isSort_desc();
32+
this.hashService = hashService;
3033
LOG.info("setting BOX_HOME as [{}] and HOST_PREFIX as [{}]", boxHome.getAbsolutePath(), hostPrefix);
3134
}
3235

36+
@Override
37+
public List<String> getBoxes() {
38+
return Arrays.stream(boxHome.listFiles(File::isDirectory))
39+
.filter(this::containsValidBoxFile)
40+
.map(File::getName)
41+
.sorted()
42+
.collect(Collectors.toList());
43+
}
44+
3345
@Override
3446
public Optional<Box> getBox(String boxName) {
3547
Map<String, List<File>> groupedBoxFiles = new HashMap<>();
@@ -71,8 +83,9 @@ private Map<String, List<File>> groupBoxFilesByVersion(File boxDir) {
7183

7284
private boolean validateFilename(File boxFile) {
7385
String filename = boxFile.getName();
74-
List<String> parsedFilename = Arrays.asList(filename.split("_"));
75-
if (parsedFilename.size() != 3) {
86+
File parentDir = boxFile.getParentFile();
87+
88+
if (!filename.matches(parentDir.getName() + "_(\\d+)_(\\w+)\\.box")) {
7689
LOG.warn("box file [{}] has wrong name. must be in format ${name}_${version}_${provider}.box", filename);
7790
return false;
7891
}
@@ -109,10 +122,21 @@ private BoxVersion createBoxVersion(String version, List<File> fileList) {
109122
private BoxProvider createBoxProviderFromFile(File file) {
110123
String filename = file.getName();
111124
List<String> parsedFilename = Arrays.asList(filename.split("_"));
125+
112126
String provider = parsedFilename.get(2);
113127
if (provider.endsWith(".box")) {
114128
provider = provider.substring(0, provider.length() - 4);
115129
}
116-
return new BoxProvider(hostPrefix + file.getAbsolutePath(), provider);
130+
return new BoxProvider(
131+
hostPrefix + file.getAbsolutePath(),
132+
provider,
133+
hashService.getHashType(),
134+
hashService.getChecksum(file.getAbsolutePath())
135+
);
136+
}
137+
138+
private boolean containsValidBoxFile(File file) {
139+
File[] files = file.listFiles(this::validateFilename);
140+
return files.length > 0;
117141
}
118142
}

0 commit comments

Comments
 (0)