From 5bdc425b044246521849e902290ec8e65812f7be Mon Sep 17 00:00:00 2001 From: Amadornes Date: Wed, 11 Jul 2018 19:49:47 +0200 Subject: Fixed gradle setup for better dependency handling --- build.gradle | 15 ++-- .../artifactural/base/artifact/ArtifactBase.java | 48 ------------- .../base/artifact/ArtifactIdentifierImpl.java | 42 ----------- .../base/artifact/SimpleArtifactMetadata.java | 57 --------------- .../base/artifact/StreamableArtifact.java | 56 --------------- .../artifactural/base/cache/ArtifactCacheBase.java | 33 --------- .../base/cache/LocatedArtifactCache.java | 31 --------- .../base/repository/ArtifactProviderBuilder.java | 81 ---------------------- .../base/repository/SimpleRepository.java | 25 ------- .../base/transform/ExclusiveTransformer.java | 77 -------------------- .../base/transform/SimpleArtifactPipeline.java | 46 ------------ .../artifactural/base/artifact/ArtifactBase.java | 48 +++++++++++++ .../base/artifact/ArtifactIdentifierImpl.java | 42 +++++++++++ .../base/artifact/SimpleArtifactMetadata.java | 57 +++++++++++++++ .../base/artifact/StreamableArtifact.java | 56 +++++++++++++++ .../artifactural/base/cache/ArtifactCacheBase.java | 33 +++++++++ .../base/cache/LocatedArtifactCache.java | 31 +++++++++ .../base/repository/ArtifactProviderBuilder.java | 81 ++++++++++++++++++++++ .../base/repository/SimpleRepository.java | 25 +++++++ .../base/transform/ExclusiveTransformer.java | 77 ++++++++++++++++++++ .../base/transform/SimpleArtifactPipeline.java | 46 ++++++++++++ 21 files changed, 503 insertions(+), 504 deletions(-) delete mode 100644 src/main/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/repository/SimpleRepository.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java delete mode 100644 src/main/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/repository/SimpleRepository.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java create mode 100644 src/shared/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java diff --git a/build.gradle b/build.gradle index 43e053e..64c4c30 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ version = '1.0.0' sourceSets { api - main + shared gradlecomp } @@ -16,15 +16,14 @@ repositories { } dependencies { - implementation sourceSets.api.output + sharedImplementation sourceSets.api.output gradlecompImplementation sourceSets.api.output - gradlecompImplementation sourceSets.main.output + gradlecompImplementation sourceSets.shared.output gradlecompImplementation gradleApi() + + compile sourceSets.api.output + compile sourceSets.shared.output + compile sourceSets.gradlecomp.output } -jar { - from sourceSets.api.output - from sourceSets.main.output - from sourceSets.gradlecomp.output -} diff --git a/src/main/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java b/src/main/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java deleted file mode 100644 index 4656285..0000000 --- a/src/main/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.amadornes.artifactural.base.artifact; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactMetadata; -import com.amadornes.artifactural.api.artifact.ArtifactType; -import com.amadornes.artifactural.api.cache.ArtifactCache; -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; -import com.amadornes.artifactural.api.transform.ArtifactTransformer; - -public abstract class ArtifactBase implements Artifact { - - private final ArtifactIdentifier identifier; - private final ArtifactType type; - private final ArtifactMetadata metadata; - - ArtifactBase(ArtifactIdentifier identifier, ArtifactType type, ArtifactMetadata metadata) { - this.identifier = identifier; - this.type = type; - this.metadata = metadata; - } - - @Override - public ArtifactIdentifier getIdentifier() { - return identifier; - } - - @Override - public ArtifactType getType() { - return type; - } - - @Override - public ArtifactMetadata getMetadata() { - return metadata; - } - - @Override - public Artifact apply(ArtifactTransformer transformer) { - if (!transformer.appliesTo(this)) return this; - return transformer.transform(this); - } - - @Override - public Artifact cache(ArtifactCache cache, String specifier) { - return cache.store(this, specifier); - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java b/src/main/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java deleted file mode 100644 index 26acd29..0000000 --- a/src/main/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.amadornes.artifactural.base.artifact; - -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; - -public class ArtifactIdentifierImpl implements ArtifactIdentifier { - - private final String group, name, version, classifier, extension; - - public ArtifactIdentifierImpl(String group, String name, String version, String classifier, String extension) { - this.group = group; - this.name = name; - this.version = version; - this.classifier = classifier; - this.extension = extension; - } - - @Override - public String getGroup() { - return group; - } - - @Override - public String getName() { - return name; - } - - @Override - public String getVersion() { - return version; - } - - @Override - public String getClassifier() { - return classifier; - } - - @Override - public String getExtension() { - return extension; - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java b/src/main/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java deleted file mode 100644 index e08cd7b..0000000 --- a/src/main/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java +++ /dev/null @@ -1,57 +0,0 @@ -package com.amadornes.artifactural.base.artifact; - -import com.amadornes.artifactural.api.artifact.ArtifactMetadata; - -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Base64; -import java.util.LinkedList; -import java.util.stream.Collectors; - -public class SimpleArtifactMetadata implements ArtifactMetadata { - - private final LinkedList entries = new LinkedList<>(); - - public SimpleArtifactMetadata() { - } - - private SimpleArtifactMetadata(SimpleArtifactMetadata parent, Entry entry) { - this.entries.addAll(parent.entries); - this.entries.add(entry); - } - - @Override - public ArtifactMetadata with(String key, String value) { - return new SimpleArtifactMetadata(this, new Entry(key, value)); - } - - @Override - public String getHash() { - try { - String str = entries.stream().map(Entry::toString).collect(Collectors.joining(";;")); - MessageDigest digest = MessageDigest.getInstance("SHA-256"); - byte[] hash = digest.digest(str.getBytes(StandardCharsets.UTF_8)); - return Base64.getEncoder().encodeToString(hash); - } catch (NoSuchAlgorithmException ex) { - throw new RuntimeException(ex); - } - } - - private static class Entry { - - private final String key, value; - - private Entry(String key, String value) { - this.key = key; - this.value = value; - } - - @Override - public String toString() { - return '[' + key + ',' + value + ']'; - } - - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java b/src/main/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java deleted file mode 100644 index 4f3df7a..0000000 --- a/src/main/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java +++ /dev/null @@ -1,56 +0,0 @@ -package com.amadornes.artifactural.base.artifact; - -import com.amadornes.artifactural.api.artifact.*; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; - -public class StreamableArtifact extends ArtifactBase { - - public static Artifact ofJar(ArtifactIdentifier identifier, ArtifactType type, File file) { - return ofStreamable(identifier, type, () -> new FileInputStream(file)); - } - - public static Artifact ofURL(ArtifactIdentifier identifier, ArtifactType type, URL url) { - return ofStreamable(identifier, type, url::openStream); - } - - public static Artifact ofStreamable(ArtifactIdentifier identifier, ArtifactType type, Streamable streamable) { - return new StreamableArtifact(identifier, type, streamable); - } - - private final Streamable streamable; - - private StreamableArtifact(ArtifactIdentifier identifier, ArtifactType type, Streamable streamable) { - this(identifier, type, ArtifactMetadata.empty(), streamable); - } - - private StreamableArtifact(ArtifactIdentifier identifier, ArtifactType type, ArtifactMetadata metadata, Streamable streamable) { - super(identifier, type, metadata); - this.streamable = streamable; - } - - @Override - public Artifact withMetadata(ArtifactMetadata metadata) { - return new StreamableArtifact(getIdentifier(), getType(), metadata, streamable); - } - - @Override - public boolean isPresent() { - try (InputStream is = openStream()) { - is.close(); - return true; - } catch (IOException ex) { - return false; - } - } - - @Override - public InputStream openStream() throws IOException { - return streamable.openStream(); - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java b/src/main/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java deleted file mode 100644 index 5f1c240..0000000 --- a/src/main/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.amadornes.artifactural.base.cache; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.cache.ArtifactCache; -import com.amadornes.artifactural.base.artifact.StreamableArtifact; - -import java.io.*; - -abstract class ArtifactCacheBase implements ArtifactCache { - - Artifact doStore(File path, Artifact artifact) { - return StreamableArtifact.ofStreamable(artifact.getIdentifier(), artifact.getType(), () -> stream(path, artifact)) - .withMetadata(artifact.getMetadata()); - } - - private InputStream stream(File path, Artifact artifact) throws IOException { - if (!path.exists()) { - path.getParentFile().mkdirs(); - path.createNewFile(); - FileOutputStream fos = new FileOutputStream(path); - InputStream is = artifact.openStream(); - int read; - byte[] bytes = new byte[256]; - while ((read = is.read(bytes)) > 0) { - fos.write(bytes, 0, read); - } - fos.close(); - is.close(); - } - return new FileInputStream(path); - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java b/src/main/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java deleted file mode 100644 index caa5de7..0000000 --- a/src/main/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.amadornes.artifactural.base.cache; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; - -import java.io.File; - -public class LocatedArtifactCache extends ArtifactCacheBase { - - private final File path; - - public LocatedArtifactCache(File path) { - this.path = path; - } - - @Override - public Artifact store(Artifact artifact, String specifier) { - ArtifactIdentifier identifier = artifact.getIdentifier(); - File cachePath = new File(path.getAbsolutePath() - .replace("${GROUP}", identifier.getGroup()) - .replace("${NAME}", identifier.getName()) - .replace("${VERSION}", identifier.getVersion()) - .replace("${CLASSIFIER}", identifier.getClassifier()) - .replace("${EXTENSION}", identifier.getExtension()) - .replace("${SPECIFIER}", specifier) - .replace("${META_HASH}", artifact.getMetadata().getHash()) - ); - return doStore(cachePath, artifact); - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java b/src/main/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java deleted file mode 100644 index 1f756ec..0000000 --- a/src/main/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.amadornes.artifactural.base.repository; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.repository.ArtifactProvider; - -import java.util.HashSet; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; - -public class ArtifactProviderBuilder implements ArtifactProvider.Builder { - - public static ArtifactProviderBuilder begin(Class type) { - return new ArtifactProviderBuilder<>(Function.identity()); - } - - private final Function mapper; - private final Set> filters = new HashSet<>(); - - private ArtifactProviderBuilder(Function mapper) { - this.mapper = mapper; - } - - @Override - public ArtifactProvider.Builder filter(Predicate filter) { - filters.add(filter); - return this; - } - - @Override - public ArtifactProvider.Builder mapInfo(Function mapper) { - if (filters.isEmpty()) { - return new ArtifactProviderBuilder<>(this.mapper.andThen(mapper)); - } - return new ArtifactProviderBuilder<>((S info) -> { - I localInfo = this.mapper.apply(info); - if (localInfo == null) return null; - for (Predicate filter : filters) { - if (!filter.test(localInfo)) { - return null; - } - } - return mapper.apply(localInfo); - }); - } - - @Override - public ArtifactProvider.Builder.Complete provide(ArtifactProvider provider) { - return new Complete<>(mapper).provide(provider); - } - - private static class Complete implements ArtifactProvider.Builder.Complete { - - private final Set> providers = new HashSet<>(); - private final Function mapper; - - private Complete(Function mapper) { - this.mapper = mapper; - } - - @Override - public Builder.Complete provide(ArtifactProvider provider) { - providers.add(provider); - return this; - } - - @Override - public Artifact getArtifact(S info) { - I localInfo = mapper.apply(info); - if (localInfo == null) return Artifact.none(); - - for (ArtifactProvider provider : providers) { - Artifact artifact = provider.getArtifact(localInfo); - if (artifact.isPresent()) return artifact; - } - return Artifact.none(); - } - - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/repository/SimpleRepository.java b/src/main/java/com/amadornes/artifactural/base/repository/SimpleRepository.java deleted file mode 100644 index 7f437f8..0000000 --- a/src/main/java/com/amadornes/artifactural/base/repository/SimpleRepository.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.amadornes.artifactural.base.repository; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; -import com.amadornes.artifactural.api.repository.ArtifactProvider; -import com.amadornes.artifactural.api.repository.Repository; - -public class SimpleRepository implements Repository { - - public static Repository of(ArtifactProvider provider) { - return new SimpleRepository(provider); - } - - private final ArtifactProvider provider; - - private SimpleRepository(ArtifactProvider provider) { - this.provider = provider; - } - - @Override - public Artifact getArtifact(ArtifactIdentifier identifier) { - return provider.getArtifact(identifier); - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java b/src/main/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java deleted file mode 100644 index e16be1f..0000000 --- a/src/main/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java +++ /dev/null @@ -1,77 +0,0 @@ -package com.amadornes.artifactural.base.transform; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactMetadata; -import com.amadornes.artifactural.api.artifact.ArtifactType; -import com.amadornes.artifactural.api.transform.ArtifactTransformer; -import com.amadornes.artifactural.base.artifact.StreamableArtifact; - -import java.io.IOException; -import java.util.HashSet; -import java.util.Set; -import java.util.function.Predicate; -import java.util.regex.Pattern; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -public class ExclusiveTransformer implements ArtifactTransformer { - - public static ExclusiveTransformer of(boolean whitelist, String... filters) { - return new ExclusiveTransformer(whitelist, filters); - } - - private final Set filters = new HashSet<>(); - private final boolean whitelist; - - private ExclusiveTransformer(boolean whitelist, String... filters) { - this.whitelist = whitelist; - for (String s : filters) { - String regex = s - .replaceAll("(?:(^|[^\\w\\*])\\*\\*([^\\w\\*]|$))", "$1.*$2") // ** matches anything - .replaceAll("(?:(^|[^\\w\\*])\\*([^\\w\\*]|$))", "$1[^\\/]*$2"); // * matches anything but / - this.filters.add(Pattern.compile(regex)); - } - } - - @Override - public Artifact transform(Artifact artifact) { - if (!artifact.isPresent()) return Artifact.none(); - - if (artifact.getType() == ArtifactType.BINARY || artifact.getType() == ArtifactType.SOURCE) { - return exclude(artifact); - } else { - return Artifact.none(); - } - } - - @Override - public ArtifactMetadata withInfo(ArtifactMetadata metadata) { - return metadata.with("EXCLUDE", filters.stream().map(Pattern::pattern).collect(Collectors.joining(";"))); - } - - private Artifact exclude(Artifact artifact) { - return StreamableArtifact.ofStreamable(artifact.getIdentifier(), artifact.getType(), - () -> new ZipInputStream(artifact.openStream()) { - @Override - public ZipEntry getNextEntry() throws IOException { - ZipEntry next; - while ((next = super.getNextEntry()) != null) { - if (isAllowed(next.getName())) { - return next; - } - } - return null; - } - }); - } - - private boolean isAllowed(String name) { - if (whitelist) { - return filters.stream().anyMatch(p -> p.asPredicate().test(name)); - } else { - return filters.stream().noneMatch(p -> p.asPredicate().test(name)); - } - } - -} diff --git a/src/main/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java b/src/main/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java deleted file mode 100644 index 625b2e9..0000000 --- a/src/main/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.amadornes.artifactural.base.transform; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactMetadata; -import com.amadornes.artifactural.api.cache.ArtifactCache; -import com.amadornes.artifactural.api.transform.ArtifactPipeline; -import com.amadornes.artifactural.api.transform.ArtifactTransformer; - -import java.util.function.UnaryOperator; - -public class SimpleArtifactPipeline implements ArtifactPipeline { - - public static ArtifactPipeline create() { - return new SimpleArtifactPipeline(); - } - - private static final ArtifactTransformer IDENTITY = ArtifactTransformer.of(UnaryOperator.identity()); - - private ArtifactTransformer transformer = IDENTITY; - - private SimpleArtifactPipeline() { - } - - @Override - public ArtifactPipeline apply(ArtifactTransformer transformer) { - this.transformer = this.transformer.andThen(transformer); - return this; - } - - @Override - public ArtifactPipeline cache(ArtifactCache cache, String specifier) { - transformer = transformer.andThen(ArtifactTransformer.of(artifact -> cache.store(artifact, specifier))); - return this; - } - - @Override - public Artifact transform(Artifact artifact) { - return transformer.transform(artifact); - } - - @Override - public ArtifactMetadata withInfo(ArtifactMetadata metadata) { - return transformer.withInfo(metadata); - } - -} diff --git a/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java b/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java new file mode 100644 index 0000000..4656285 --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java @@ -0,0 +1,48 @@ +package com.amadornes.artifactural.base.artifact; + +import com.amadornes.artifactural.api.artifact.Artifact; +import com.amadornes.artifactural.api.artifact.ArtifactMetadata; +import com.amadornes.artifactural.api.artifact.ArtifactType; +import com.amadornes.artifactural.api.cache.ArtifactCache; +import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; +import com.amadornes.artifactural.api.transform.ArtifactTransformer; + +public abstract class ArtifactBase implements Artifact { + + private final ArtifactIdentifier identifier; + private final ArtifactType type; + private final ArtifactMetadata metadata; + + ArtifactBase(ArtifactIdentifier identifier, ArtifactType type, ArtifactMetadata metadata) { + this.identifier = identifier; + this.type = type; + this.metadata = metadata; + } + + @Override + public ArtifactIdentifier getIdentifier() { + return identifier; + } + + @Override + public ArtifactType getType() { + return type; + } + + @Override + public ArtifactMetadata getMetadata() { + return metadata; + } + + @Override + public Artifact apply(ArtifactTransformer transformer) { + if (!transformer.appliesTo(this)) return this; + return transformer.transform(this); + } + + @Override + public Artifact cache(ArtifactCache cache, String specifier) { + return cache.store(this, specifier); + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java b/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java new file mode 100644 index 0000000..26acd29 --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactIdentifierImpl.java @@ -0,0 +1,42 @@ +package com.amadornes.artifactural.base.artifact; + +import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; + +public class ArtifactIdentifierImpl implements ArtifactIdentifier { + + private final String group, name, version, classifier, extension; + + public ArtifactIdentifierImpl(String group, String name, String version, String classifier, String extension) { + this.group = group; + this.name = name; + this.version = version; + this.classifier = classifier; + this.extension = extension; + } + + @Override + public String getGroup() { + return group; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getVersion() { + return version; + } + + @Override + public String getClassifier() { + return classifier; + } + + @Override + public String getExtension() { + return extension; + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java b/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java new file mode 100644 index 0000000..e08cd7b --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java @@ -0,0 +1,57 @@ +package com.amadornes.artifactural.base.artifact; + +import com.amadornes.artifactural.api.artifact.ArtifactMetadata; + +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Base64; +import java.util.LinkedList; +import java.util.stream.Collectors; + +public class SimpleArtifactMetadata implements ArtifactMetadata { + + private final LinkedList entries = new LinkedList<>(); + + public SimpleArtifactMetadata() { + } + + private SimpleArtifactMetadata(SimpleArtifactMetadata parent, Entry entry) { + this.entries.addAll(parent.entries); + this.entries.add(entry); + } + + @Override + public ArtifactMetadata with(String key, String value) { + return new SimpleArtifactMetadata(this, new Entry(key, value)); + } + + @Override + public String getHash() { + try { + String str = entries.stream().map(Entry::toString).collect(Collectors.joining(";;")); + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] hash = digest.digest(str.getBytes(StandardCharsets.UTF_8)); + return Base64.getEncoder().encodeToString(hash); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } + + private static class Entry { + + private final String key, value; + + private Entry(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public String toString() { + return '[' + key + ',' + value + ']'; + } + + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java b/src/shared/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java new file mode 100644 index 0000000..4f3df7a --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java @@ -0,0 +1,56 @@ +package com.amadornes.artifactural.base.artifact; + +import com.amadornes.artifactural.api.artifact.*; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +public class StreamableArtifact extends ArtifactBase { + + public static Artifact ofJar(ArtifactIdentifier identifier, ArtifactType type, File file) { + return ofStreamable(identifier, type, () -> new FileInputStream(file)); + } + + public static Artifact ofURL(ArtifactIdentifier identifier, ArtifactType type, URL url) { + return ofStreamable(identifier, type, url::openStream); + } + + public static Artifact ofStreamable(ArtifactIdentifier identifier, ArtifactType type, Streamable streamable) { + return new StreamableArtifact(identifier, type, streamable); + } + + private final Streamable streamable; + + private StreamableArtifact(ArtifactIdentifier identifier, ArtifactType type, Streamable streamable) { + this(identifier, type, ArtifactMetadata.empty(), streamable); + } + + private StreamableArtifact(ArtifactIdentifier identifier, ArtifactType type, ArtifactMetadata metadata, Streamable streamable) { + super(identifier, type, metadata); + this.streamable = streamable; + } + + @Override + public Artifact withMetadata(ArtifactMetadata metadata) { + return new StreamableArtifact(getIdentifier(), getType(), metadata, streamable); + } + + @Override + public boolean isPresent() { + try (InputStream is = openStream()) { + is.close(); + return true; + } catch (IOException ex) { + return false; + } + } + + @Override + public InputStream openStream() throws IOException { + return streamable.openStream(); + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java b/src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java new file mode 100644 index 0000000..5f1c240 --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java @@ -0,0 +1,33 @@ +package com.amadornes.artifactural.base.cache; + +import com.amadornes.artifactural.api.artifact.Artifact; +import com.amadornes.artifactural.api.cache.ArtifactCache; +import com.amadornes.artifactural.base.artifact.StreamableArtifact; + +import java.io.*; + +abstract class ArtifactCacheBase implements ArtifactCache { + + Artifact doStore(File path, Artifact artifact) { + return StreamableArtifact.ofStreamable(artifact.getIdentifier(), artifact.getType(), () -> stream(path, artifact)) + .withMetadata(artifact.getMetadata()); + } + + private InputStream stream(File path, Artifact artifact) throws IOException { + if (!path.exists()) { + path.getParentFile().mkdirs(); + path.createNewFile(); + FileOutputStream fos = new FileOutputStream(path); + InputStream is = artifact.openStream(); + int read; + byte[] bytes = new byte[256]; + while ((read = is.read(bytes)) > 0) { + fos.write(bytes, 0, read); + } + fos.close(); + is.close(); + } + return new FileInputStream(path); + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java b/src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java new file mode 100644 index 0000000..caa5de7 --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java @@ -0,0 +1,31 @@ +package com.amadornes.artifactural.base.cache; + +import com.amadornes.artifactural.api.artifact.Artifact; +import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; + +import java.io.File; + +public class LocatedArtifactCache extends ArtifactCacheBase { + + private final File path; + + public LocatedArtifactCache(File path) { + this.path = path; + } + + @Override + public Artifact store(Artifact artifact, String specifier) { + ArtifactIdentifier identifier = artifact.getIdentifier(); + File cachePath = new File(path.getAbsolutePath() + .replace("${GROUP}", identifier.getGroup()) + .replace("${NAME}", identifier.getName()) + .replace("${VERSION}", identifier.getVersion()) + .replace("${CLASSIFIER}", identifier.getClassifier()) + .replace("${EXTENSION}", identifier.getExtension()) + .replace("${SPECIFIER}", specifier) + .replace("${META_HASH}", artifact.getMetadata().getHash()) + ); + return doStore(cachePath, artifact); + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java b/src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java new file mode 100644 index 0000000..1f756ec --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java @@ -0,0 +1,81 @@ +package com.amadornes.artifactural.base.repository; + +import com.amadornes.artifactural.api.artifact.Artifact; +import com.amadornes.artifactural.api.repository.ArtifactProvider; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; + +public class ArtifactProviderBuilder implements ArtifactProvider.Builder { + + public static ArtifactProviderBuilder begin(Class type) { + return new ArtifactProviderBuilder<>(Function.identity()); + } + + private final Function mapper; + private final Set> filters = new HashSet<>(); + + private ArtifactProviderBuilder(Function mapper) { + this.mapper = mapper; + } + + @Override + public ArtifactProvider.Builder filter(Predicate filter) { + filters.add(filter); + return this; + } + + @Override + public ArtifactProvider.Builder mapInfo(Function mapper) { + if (filters.isEmpty()) { + return new ArtifactProviderBuilder<>(this.mapper.andThen(mapper)); + } + return new ArtifactProviderBuilder<>((S info) -> { + I localInfo = this.mapper.apply(info); + if (localInfo == null) return null; + for (Predicate filter : filters) { + if (!filter.test(localInfo)) { + return null; + } + } + return mapper.apply(localInfo); + }); + } + + @Override + public ArtifactProvider.Builder.Complete provide(ArtifactProvider provider) { + return new Complete<>(mapper).provide(provider); + } + + private static class Complete implements ArtifactProvider.Builder.Complete { + + private final Set> providers = new HashSet<>(); + private final Function mapper; + + private Complete(Function mapper) { + this.mapper = mapper; + } + + @Override + public Builder.Complete provide(ArtifactProvider provider) { + providers.add(provider); + return this; + } + + @Override + public Artifact getArtifact(S info) { + I localInfo = mapper.apply(info); + if (localInfo == null) return Artifact.none(); + + for (ArtifactProvider provider : providers) { + Artifact artifact = provider.getArtifact(localInfo); + if (artifact.isPresent()) return artifact; + } + return Artifact.none(); + } + + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/repository/SimpleRepository.java b/src/shared/java/com/amadornes/artifactural/base/repository/SimpleRepository.java new file mode 100644 index 0000000..7f437f8 --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/repository/SimpleRepository.java @@ -0,0 +1,25 @@ +package com.amadornes.artifactural.base.repository; + +import com.amadornes.artifactural.api.artifact.Artifact; +import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; +import com.amadornes.artifactural.api.repository.ArtifactProvider; +import com.amadornes.artifactural.api.repository.Repository; + +public class SimpleRepository implements Repository { + + public static Repository of(ArtifactProvider provider) { + return new SimpleRepository(provider); + } + + private final ArtifactProvider provider; + + private SimpleRepository(ArtifactProvider provider) { + this.provider = provider; + } + + @Override + public Artifact getArtifact(ArtifactIdentifier identifier) { + return provider.getArtifact(identifier); + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java b/src/shared/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java new file mode 100644 index 0000000..e16be1f --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/transform/ExclusiveTransformer.java @@ -0,0 +1,77 @@ +package com.amadornes.artifactural.base.transform; + +import com.amadornes.artifactural.api.artifact.Artifact; +import com.amadornes.artifactural.api.artifact.ArtifactMetadata; +import com.amadornes.artifactural.api.artifact.ArtifactType; +import com.amadornes.artifactural.api.transform.ArtifactTransformer; +import com.amadornes.artifactural.base.artifact.StreamableArtifact; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.function.Predicate; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +public class ExclusiveTransformer implements ArtifactTransformer { + + public static ExclusiveTransformer of(boolean whitelist, String... filters) { + return new ExclusiveTransformer(whitelist, filters); + } + + private final Set filters = new HashSet<>(); + private final boolean whitelist; + + private ExclusiveTransformer(boolean whitelist, String... filters) { + this.whitelist = whitelist; + for (String s : filters) { + String regex = s + .replaceAll("(?:(^|[^\\w\\*])\\*\\*([^\\w\\*]|$))", "$1.*$2") // ** matches anything + .replaceAll("(?:(^|[^\\w\\*])\\*([^\\w\\*]|$))", "$1[^\\/]*$2"); // * matches anything but / + this.filters.add(Pattern.compile(regex)); + } + } + + @Override + public Artifact transform(Artifact artifact) { + if (!artifact.isPresent()) return Artifact.none(); + + if (artifact.getType() == ArtifactType.BINARY || artifact.getType() == ArtifactType.SOURCE) { + return exclude(artifact); + } else { + return Artifact.none(); + } + } + + @Override + public ArtifactMetadata withInfo(ArtifactMetadata metadata) { + return metadata.with("EXCLUDE", filters.stream().map(Pattern::pattern).collect(Collectors.joining(";"))); + } + + private Artifact exclude(Artifact artifact) { + return StreamableArtifact.ofStreamable(artifact.getIdentifier(), artifact.getType(), + () -> new ZipInputStream(artifact.openStream()) { + @Override + public ZipEntry getNextEntry() throws IOException { + ZipEntry next; + while ((next = super.getNextEntry()) != null) { + if (isAllowed(next.getName())) { + return next; + } + } + return null; + } + }); + } + + private boolean isAllowed(String name) { + if (whitelist) { + return filters.stream().anyMatch(p -> p.asPredicate().test(name)); + } else { + return filters.stream().noneMatch(p -> p.asPredicate().test(name)); + } + } + +} diff --git a/src/shared/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java b/src/shared/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java new file mode 100644 index 0000000..625b2e9 --- /dev/null +++ b/src/shared/java/com/amadornes/artifactural/base/transform/SimpleArtifactPipeline.java @@ -0,0 +1,46 @@ +package com.amadornes.artifactural.base.transform; + +import com.amadornes.artifactural.api.artifact.Artifact; +import com.amadornes.artifactural.api.artifact.ArtifactMetadata; +import com.amadornes.artifactural.api.cache.ArtifactCache; +import com.amadornes.artifactural.api.transform.ArtifactPipeline; +import com.amadornes.artifactural.api.transform.ArtifactTransformer; + +import java.util.function.UnaryOperator; + +public class SimpleArtifactPipeline implements ArtifactPipeline { + + public static ArtifactPipeline create() { + return new SimpleArtifactPipeline(); + } + + private static final ArtifactTransformer IDENTITY = ArtifactTransformer.of(UnaryOperator.identity()); + + private ArtifactTransformer transformer = IDENTITY; + + private SimpleArtifactPipeline() { + } + + @Override + public ArtifactPipeline apply(ArtifactTransformer transformer) { + this.transformer = this.transformer.andThen(transformer); + return this; + } + + @Override + public ArtifactPipeline cache(ArtifactCache cache, String specifier) { + transformer = transformer.andThen(ArtifactTransformer.of(artifact -> cache.store(artifact, specifier))); + return this; + } + + @Override + public Artifact transform(Artifact artifact) { + return transformer.transform(artifact); + } + + @Override + public ArtifactMetadata withInfo(ArtifactMetadata metadata) { + return transformer.withInfo(metadata); + } + +} -- cgit