Skip to content

Commit 582523d

Browse files
Eric Dallo and Gabriel Lima Gomesericdallo
authored andcommitted
First Commit
0 parents  commit 582523d

File tree

8 files changed

+252
-0
lines changed

8 files changed

+252
-0
lines changed

.gitignore

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
.classpath
2+
.settings
3+
.project
4+
.class
5+
.bin
6+
.lock
7+
.gradle
8+
target/
9+
build/
10+
bin/

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Spring S3 Property Loader #
2+
3+
S3 Property Loader has the aim of allowing loading of Spring property files from S3 bucket, in order to guarantee stateless machine configuration.
4+
5+
Spring PropertyConfigurer replaces standard PropertyConfigurer to load property files from AWS S3 bucket. S3 path could be specified directly into spring beans.
6+

build.gradle

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
apply plugin: 'java'
2+
apply plugin: 'eclipse'
3+
apply plugin: 'application'
4+
apply plugin: 'net.researchgate.release'
5+
apply plugin: 'maven-publish'
6+
apply plugin: 'maven'
7+
apply plugin: 'signing'
8+
9+
compileJava.options.encoding = 'UTF-8'
10+
11+
group = 'com.spring.loader'
12+
archivesBaseName = 's3-property-loader'
13+
14+
buildscript {
15+
repositories {
16+
mavenLocal()
17+
mavenCentral()
18+
}
19+
20+
dependencies {
21+
classpath 'net.researchgate:gradle-release:2.3.5'
22+
}
23+
}
24+
25+
eclipse {
26+
classpath {
27+
downloadJavadoc = true
28+
downloadSources = true
29+
}
30+
}
31+
32+
release {
33+
failOnCommitNeeded = false
34+
failOnPublishNeeded = true
35+
failOnSnapshotDependencies = true
36+
failOnUnversionedFiles = true
37+
failOnUpdateNeeded = true
38+
revertOnFail = true
39+
}
40+
41+
afterReleaseBuild.dependsOn publish
42+
43+
repositories {
44+
mavenCentral()
45+
mavenLocal()
46+
}
47+
48+
dependencies {
49+
compile "org.springframework:spring-core:3.0.5.RELEASE"
50+
compile "org.springframework:spring-beans:3.0.5.RELEASE"
51+
compile "org.springframework.cloud:spring-cloud-aws-autoconfigure:1.0.4.RELEASE"
52+
53+
testCompile "junit:junit:4.12"
54+
testCompile "org.mockito:mockito-core:1.10.19"
55+
testCompile "org.assertj:assertj-core:1.0.0"
56+
}
57+
58+
task sourcesJar(type: Jar) {
59+
from sourceSets.main.allSource
60+
classifier = 'sources'
61+
}
62+
63+
artifacts {
64+
archives jar
65+
66+
archives sourcesJar
67+
}
68+
69+
mainClassName = ''

gradle.properties

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
version=1.0.1-SNAPSHOT
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.spring.loader;
2+
3+
class S3Path {
4+
5+
private final String bucketName;
6+
private final String keyName;
7+
8+
public S3Path(String bucketName, String keyName) {
9+
this.bucketName = bucketName;
10+
this.keyName = keyName;
11+
}
12+
13+
public String getBucketName() {
14+
return bucketName;
15+
}
16+
17+
public String getKeyName() {
18+
return keyName;
19+
}
20+
21+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package com.spring.loader;
2+
3+
import java.util.ArrayList;
4+
import java.util.HashSet;
5+
import java.util.List;
6+
import java.util.Properties;
7+
8+
import org.springframework.beans.BeansException;
9+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
10+
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
11+
import org.springframework.core.io.Resource;
12+
13+
public class S3PropertyPlaceholderConfigurer extends PropertyPlaceholderConfigurer {
14+
15+
private S3ResourceLoader resourceLoader;
16+
private String[] s3Locations = new String[0];
17+
private Resource[] conventionalResources = new Resource[0];
18+
private boolean ignoreS3resourceNotFound = false;
19+
20+
public S3PropertyPlaceholderConfigurer(S3ResourceLoader resourceLoader) {
21+
this.resourceLoader = resourceLoader;
22+
}
23+
24+
@Override
25+
public void setLocations(Resource... locations) {
26+
this.conventionalResources = locations;
27+
}
28+
29+
@SuppressWarnings("deprecation")
30+
public void setS3Locations(String[] s3Locations) {
31+
this.s3Locations = new String[s3Locations.length];
32+
for (int i = 0; i < s3Locations.length; i++) {
33+
this.s3Locations[i] = parseStringValue(s3Locations[i], new Properties(), new HashSet<>());
34+
}
35+
36+
}
37+
38+
@Override
39+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
40+
injectS3Resources();
41+
super.postProcessBeanFactory(beanFactory);
42+
}
43+
44+
private void injectS3Resources() {
45+
46+
int total = conventionalResources.length + s3Locations.length;
47+
48+
if (total > 0) {
49+
List<Resource> allResources = new ArrayList<>();
50+
for (String s3Location : s3Locations) {
51+
try {
52+
allResources.add(resourceLoader.getResource(s3Location));
53+
} catch (S3ResourceException exp) {
54+
if (!ignoreS3resourceNotFound) {
55+
throw exp;
56+
}
57+
}
58+
}
59+
for (Resource conventionalResource : conventionalResources) {
60+
allResources.add(conventionalResource);
61+
}
62+
63+
super.setLocations(allResources.toArray(new Resource[0]));
64+
}
65+
66+
}
67+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.spring.loader;
2+
3+
public class S3ResourceException extends RuntimeException {
4+
private static final long serialVersionUID = 8310280589629514933L;
5+
6+
public S3ResourceException(String msg) {
7+
super(msg);
8+
}
9+
10+
public S3ResourceException(String msg, Throwable cause) {
11+
super(msg, cause);
12+
}
13+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package com.spring.loader;
2+
3+
import org.springframework.core.io.InputStreamResource;
4+
import org.springframework.core.io.Resource;
5+
import org.springframework.core.io.ResourceLoader;
6+
7+
import com.amazonaws.auth.AWSCredentials;
8+
import com.amazonaws.services.s3.AmazonS3;
9+
import com.amazonaws.services.s3.AmazonS3Client;
10+
import com.amazonaws.services.s3.model.S3Object;
11+
12+
public class S3ResourceLoader implements ResourceLoader {
13+
14+
private static final String S3_PROTOCOL_PREFIX = "s3://";
15+
16+
private AmazonS3 s3;
17+
18+
public S3ResourceLoader(AWSCredentials credentials) {
19+
this(new AmazonS3Client(credentials));
20+
}
21+
22+
public S3ResourceLoader(AmazonS3 s3) {
23+
this.s3 = s3;
24+
}
25+
26+
@Override
27+
public ClassLoader getClassLoader() {
28+
return this.getClassLoader();
29+
}
30+
31+
@Override
32+
public Resource getResource(String location) {
33+
try {
34+
S3Path s3Path = parseS3Path(location);
35+
S3Object s3Object = s3.getObject(s3Path.getBucketName(), s3Path.getKeyName());
36+
return new InputStreamResource(s3Object.getObjectContent(), location);
37+
38+
} catch (Exception e) {
39+
throw new S3ResourceException("Could not load resource from " + location, e);
40+
}
41+
}
42+
43+
private static S3Path parseS3Path(String location) {
44+
45+
String path = getLocationPath(location);
46+
String bucketName = path.substring(0, path.indexOf("/"));
47+
String keyName = path.substring(path.indexOf("/") + 1);
48+
49+
return new S3Path(bucketName, keyName);
50+
}
51+
52+
private static String getLocationPath(String location) {
53+
54+
if (location == null || "".equals(location.trim())) {
55+
throw new S3ResourceException("Location cannot be empty or null");
56+
}
57+
58+
if (location.startsWith(S3_PROTOCOL_PREFIX)) {
59+
return location.substring(S3_PROTOCOL_PREFIX.length(), location.length());
60+
}
61+
62+
throw new S3ResourceException(location + " does not begin with '" + S3_PROTOCOL_PREFIX + "'");
63+
}
64+
65+
}

0 commit comments

Comments
 (0)