From 4089917696fffbd4b818fb90958d20f0714f93fb Mon Sep 17 00:00:00 2001 From: LexManos Date: Sun, 17 Jan 2021 17:35:01 -0800 Subject: Move to net.minecraftforge package, and update license headers. --- .../artifactural/base/artifact/ArtifactBase.java | 72 ---------- .../base/artifact/SimpleArtifactIdentifier.java | 70 --------- .../base/artifact/SimpleArtifactMetadata.java | 86 ----------- .../base/artifact/StreamableArtifact.java | 111 -------------- .../artifactural/base/cache/ArtifactCacheBase.java | 129 ----------------- .../base/cache/LocatedArtifactCache.java | 69 --------- .../base/repository/ArtifactProviderBuilder.java | 100 ------------- .../base/repository/SimpleRepository.java | 44 ------ .../artifactural/base/util/HashFunction.java | 135 ----------------- .../artifactural/base/util/PatternReplace.java | 159 --------------------- .../artifactural/base/artifact/ArtifactBase.java | 72 ++++++++++ .../base/artifact/SimpleArtifactIdentifier.java | 70 +++++++++ .../base/artifact/SimpleArtifactMetadata.java | 86 +++++++++++ .../base/artifact/StreamableArtifact.java | 111 ++++++++++++++ .../artifactural/base/cache/ArtifactCacheBase.java | 129 +++++++++++++++++ .../base/cache/LocatedArtifactCache.java | 69 +++++++++ .../base/repository/ArtifactProviderBuilder.java | 100 +++++++++++++ .../base/repository/SimpleRepository.java | 44 ++++++ .../artifactural/base/util/HashFunction.java | 135 +++++++++++++++++ .../artifactural/base/util/PatternReplace.java | 159 +++++++++++++++++++++ 20 files changed, 975 insertions(+), 975 deletions(-) delete mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactIdentifier.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/repository/SimpleRepository.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/util/HashFunction.java delete mode 100644 src/shared/java/com/amadornes/artifactural/base/util/PatternReplace.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/artifact/ArtifactBase.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactIdentifier.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactMetadata.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/artifact/StreamableArtifact.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/cache/ArtifactCacheBase.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/cache/LocatedArtifactCache.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/repository/ArtifactProviderBuilder.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/repository/SimpleRepository.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/util/HashFunction.java create mode 100644 src/shared/java/net/minecraftforge/artifactural/base/util/PatternReplace.java (limited to 'src/shared/java') diff --git a/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java b/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java deleted file mode 100644 index 0eaa66d..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/artifact/ArtifactBase.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -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; - - public 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.Cached cache(ArtifactCache cache) { - return cache.store(this); - } - - @Override - public String toString() { - return getClass().getSimpleName() + "(" + identifier + ", " + type +", " + metadata; - } - -} diff --git a/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactIdentifier.java b/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactIdentifier.java deleted file mode 100644 index f0a4189..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactIdentifier.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package com.amadornes.artifactural.base.artifact; - -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; - -public class SimpleArtifactIdentifier implements ArtifactIdentifier { - - private final String group, name, version, classifier, extension; - - public SimpleArtifactIdentifier(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; - } - - @Override - public String toString() { - String ret = getGroup() + ':' + getName() + ':' + getVersion(); - if (classifier != null) - ret += ':' + getClassifier(); - if ("jar".equals(extension)) - ret += '@' + getExtension(); - return ret; - } -} diff --git a/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java b/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java deleted file mode 100644 index a42894b..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/artifact/SimpleArtifactMetadata.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package com.amadornes.artifactural.base.artifact; - -import com.amadornes.artifactural.api.artifact.ArtifactMetadata; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Collectors; - -public class SimpleArtifactMetadata implements ArtifactMetadata { - - private final List entries = new LinkedList<>(); - private String hash = null; - - 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() { - if (hash != null) return hash; - try { - String str = entries.stream().map(Entry::toString).collect(Collectors.joining("\n")); - MessageDigest digest = MessageDigest.getInstance("SHA-1"); - byte[] hashBytes = digest.digest(str.getBytes()); - StringBuilder hashBuilder = new StringBuilder(); - for (byte b : hashBytes) { - hashBuilder.append(String.format("%02x", b)); - } - return hash = hashBuilder.toString(); - } catch (NoSuchAlgorithmException ex) { - throw new RuntimeException(ex); - } - } - - @Override - public String toString() { - return "SimpleArtifactMetadata(" + entries.toString() + ", " + getHash() + ")"; - } - - 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 deleted file mode 100644 index e43b7c9..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/artifact/StreamableArtifact.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package com.amadornes.artifactural.base.artifact; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; -import com.amadornes.artifactural.api.artifact.ArtifactMetadata; -import com.amadornes.artifactural.api.artifact.ArtifactType; -import com.amadornes.artifactural.api.artifact.MissingArtifactException; -import com.amadornes.artifactural.api.artifact.Streamable; - -import java.io.ByteArrayInputStream; -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 ofFile(ArtifactIdentifier identifier, ArtifactType type, File file) { - return new StreamableFileArtifact(identifier, type, file); - } - - public static Artifact ofURL(ArtifactIdentifier identifier, ArtifactType type, URL url) { - return new StreamableArtifact(identifier, type, url::openStream); - } - - public static Artifact ofBytes(ArtifactIdentifier identifier, ArtifactType type, byte[] bytes) { - return new StreamableArtifact(identifier, type, () -> new ByteArrayInputStream(bytes)); - } - - 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, new SimpleArtifactMetadata(), 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(); - } - - private static class StreamableFileArtifact extends StreamableArtifact implements Artifact.Cached { - - private final File file; - - private StreamableFileArtifact(ArtifactIdentifier identifier, ArtifactType type, File file) { - super(identifier, type, () -> new FileInputStream(file)); - this.file = file; - } - - @Override - public File asFile() throws MissingArtifactException { - return file; - } - - @Override - public File getFileLocation() throws MissingArtifactException { - return file; - } - - @Override - public String toString() { - return "StreamableFileArtifact(" + file + ")"; - } - - } - -} diff --git a/src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java b/src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java deleted file mode 100644 index 08a2840..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/cache/ArtifactCacheBase.java +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package com.amadornes.artifactural.base.cache; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; -import com.amadornes.artifactural.api.artifact.ArtifactMetadata; -import com.amadornes.artifactural.api.artifact.ArtifactType; -import com.amadornes.artifactural.api.artifact.MissingArtifactException; -import com.amadornes.artifactural.api.cache.ArtifactCache; -import com.amadornes.artifactural.api.transform.ArtifactTransformer; -import com.amadornes.artifactural.base.artifact.StreamableArtifact; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; - -public abstract class ArtifactCacheBase implements ArtifactCache { - - Artifact.Cached doStore(File path, Artifact artifact) { - return wrap( - StreamableArtifact.ofStreamable( - artifact.getIdentifier(), - artifact.getType(), - () -> stream(path, artifact) - ).withMetadata(artifact.getMetadata()), - path - ); - } - - 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); - } - - public static Artifact.Cached wrap(Artifact artifact, File file) { - return new Artifact.Cached() { - - @Override - public ArtifactIdentifier getIdentifier() { - return artifact.getIdentifier(); - } - - @Override - public ArtifactMetadata getMetadata() { - return artifact.getMetadata(); - } - - @Override - public ArtifactType getType() { - return artifact.getType(); - } - - @Override - public Artifact withMetadata(ArtifactMetadata metadata) { - return artifact.withMetadata(metadata); - } - - @Override - public Artifact apply(ArtifactTransformer transformer) { - return artifact.apply(transformer); - } - - @Override - public Artifact.Cached cache(ArtifactCache cache) { - return artifact.cache(cache); - } - - @Override - public boolean isPresent() { - return artifact.isPresent(); - } - - @Override - public InputStream openStream() throws IOException, MissingArtifactException { - return artifact.openStream(); - } - - @Override - public File asFile() throws IOException, MissingArtifactException { - if(!file.exists()) { - artifact.openStream().close(); - } - return file; - } - - @Override - public File getFileLocation() throws MissingArtifactException { - return file; - } - @Override - public String toString() { - return "wrapped(" + artifact + ", " + file + ")"; - } - }; - } - -} diff --git a/src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java b/src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java deleted file mode 100644 index 0aeab9c..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/cache/LocatedArtifactCache.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package com.amadornes.artifactural.base.cache; - -import com.amadornes.artifactural.api.artifact.Artifact; -import com.amadornes.artifactural.api.artifact.ArtifactIdentifier; -import com.amadornes.artifactural.base.util.PatternReplace; - -import java.io.File; -import java.util.AbstractMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class LocatedArtifactCache extends ArtifactCacheBase { - private static final String PATTERN = "[group]/[name](/[meta_hash])/[version]/[name]-[version](-[classifier])(-[specifier]).[extension]"; - private final File path; - - public LocatedArtifactCache(File path) { - this.path = path; - } - - @Override - public Artifact.Cached store(Artifact artifact) { - return doStore(getPath(artifact), artifact); - } - - public File getPath(Artifact artifact) { - ArtifactIdentifier identifier = artifact.getIdentifier(); - Map names = Stream.of( - entry("group", identifier.getGroup()), - entry("name", identifier.getName()), - entry("version", identifier.getVersion()), - entry("classifier", identifier.getClassifier()), - entry("extension", identifier.getExtension()), - //entry("specifier", specifier), /? - entry("meta_hash", artifact.getMetadata().getHash()) - ).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - return new File(path, PatternReplace.replace(PATTERN, names)); - } - - private static Entry entry(K key, V value) { - return new AbstractMap.SimpleEntry<>(key, value); - } - - @Override - public String toString() { - return "LocatedArtifactCache(" + path + ")"; - } - -} diff --git a/src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java b/src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java deleted file mode 100644 index 638ed9d..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/repository/ArtifactProviderBuilder.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -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 deleted file mode 100644 index 060780a..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/repository/SimpleRepository.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -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/util/HashFunction.java b/src/shared/java/com/amadornes/artifactural/base/util/HashFunction.java deleted file mode 100644 index 9fe4ea9..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/util/HashFunction.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package com.amadornes.artifactural.base.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Locale; - -//These are all standard hashing functions the JRE is REQUIRED to have, so add a nice factory that doesnt require catching annoying exceptions; -public enum HashFunction { - MD5("md5", 32), - SHA1("SHA-1", 40), - SHA256("SHA-256", 64); - - private String algo; - private String pad; - - private HashFunction(String algo, int length) { - this.algo = algo; - // must specify locale to get correct number formatting - this.pad = String.format(Locale.ENGLISH, "%0" + length + "d", 0); - } - - public String getExtension() { - return this.name().toLowerCase(Locale.ENGLISH); - } - - public Instance create() { - return new Instance(); - } - - public MessageDigest get() { - try { - return MessageDigest.getInstance(algo); - } catch (NoSuchAlgorithmException e) { - throw new RuntimeException(e); //Never happens - } - } - - public String hash(File file) throws IOException { - try (FileInputStream fin = new FileInputStream(file)) { - return hash(fin); - } - } - - public String hash(Iterable files) throws IOException { - MessageDigest hash = get(); - byte[] buf = new byte[1024]; - - for (File file : files) { - if (!file.exists()) - continue; - - try (FileInputStream fin = new FileInputStream(file)) { - int count = -1; - while ((count = fin.read(buf)) != -1) - hash.update(buf, 0, count); - } - } - return pad(new BigInteger(1, hash.digest()).toString(16)); - } - - public String hash(String data) { - return hash(data.getBytes(StandardCharsets.UTF_8)); - } - - public String hash(InputStream stream) throws IOException { - MessageDigest hash = get(); - byte[] buf = new byte[1024]; - int count = -1; - while ((count = stream.read(buf)) != -1) - hash.update(buf, 0, count); - return pad(new BigInteger(1, hash.digest()).toString(16)); - } - - public String hash(byte[] data) { - return pad(new BigInteger(1, get().digest(data)).toString(16)); - } - - public String pad(String hash) { - return (pad + hash).substring(hash.length()); - } - - public class Instance { - private MessageDigest digest = HashFunction.this.get(); - public void update(byte input) { - digest.update(input); - } - public void update(byte[] input) { - digest.update(input); - } - public void update(byte[] input, int offset, int length) { - digest.update(input, offset, length); - } - public void update(ByteBuffer input) { - digest.update(input); - } - public void update(String input) { - update(input.getBytes(StandardCharsets.UTF_8)); - } - public void update(int input) { - update(new byte[] { (byte)((input & 0xFF000000) >> 24), (byte)((input & 0xFF000000) >> 16), (byte)((input & 0xFF000000) >> 8), (byte)((input & 0xFF000000))}); - } - public byte[] digest() { - return digest.digest(); - } - public String finish() { - return pad(new BigInteger(1, digest()).toString(16)); - } - } -} diff --git a/src/shared/java/com/amadornes/artifactural/base/util/PatternReplace.java b/src/shared/java/com/amadornes/artifactural/base/util/PatternReplace.java deleted file mode 100644 index e81bd36..0000000 --- a/src/shared/java/com/amadornes/artifactural/base/util/PatternReplace.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Artifactural - * Copyright (c) 2018. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation version 2.1 - * of the License. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -package com.amadornes.artifactural.base.util; - -import java.util.Map; - -public class PatternReplace { - /* - * Replaces a patterened string, with support for optional groups. - * Example: - * Values: - * group: net/minecraftforge - * name: forge - * version: 1.0 - * ext: jar - * - * Example: [group]/[name]/[version]/[name]-[version](-[classifier]).[ext] - * {classifier: test} net/minecraftforge/forge/1.0/forge-1.0-test.jar - * {classifier: null} net/minecraftforge/forge/1.0/forge-1.0.jar - * - * Nested Optionals are supported: - * Example: [group]/[name]/[version]/[name]-[version](-[classifier](-[suffix])).[ext] - * {classifier: test, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0-test-foo.jar - * {classifier: test, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0-test.jar - * {classifier: null, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0.jar - * - * Compound optionals are supported: - * Example: [group]/[name]/[version]/[name]-[version](-[classifier]-[suffix]).[ext] - * {classifier: test, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0-test-foo.jar - * {classifier: test, suffix: null} net/minecraftforge/forge/1.0/forge-1.0.jar - * {classifier: null, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0.jar - * - * - * TODO: Support nested names? - * Example: [group]/[name]/[version]/[name]-[version](-[classifier[suffix]]).[ext] - * {classifierFoo: test, suffix: Foo} net/minecraftforge/forge/1.0/forge-1.0-test.jar - * {classifierFoo: null, suffix: Foo} net/minecraftforge/forge/1.0/forge-1.0.jar - */ - public static String replace(String pattern, Map values) { - if (pattern == null) return null; - if (pattern.isEmpty()) return ""; - - Optional optional = null; - StringBuffer name = null; - StringBuffer ret = new StringBuffer(); - - char[] chars = pattern.toCharArray(); - for (int x = 0; x < chars.length; x++) { - char c = chars[x]; - if (c == '\\') { - if (x == chars.length -1) - throw new IllegalArgumentException("Escape character can not be end of pattern: " + pattern); - x++; - ret.append(chars[x]); - continue; - } - switch (c) { - case '[': - if (name != null) - throw new IllegalArgumentException("Nested names are not supported @ " + x + " : " + pattern); - name = new StringBuffer(); - break; - case ']': - if (name == null) - throw new IllegalArgumentException("Name closing found without opening @ " + x + " : " + pattern); - String key = name.toString(); - if (key.isEmpty()) - throw new IllegalArgumentException("Name can not be empty @ " + x + ": " + pattern); - if (optional != null) - optional.setKey(key, values); - else - ret.append(values.get(key)); // appends 'null' if missing, if you want "" then use ([name]) - // Should we have this default to not replacing at all if value is not set to allow chaining? - // Meaning: '[key]' == '[key]' if 'key' is not set. - // Current: '[key]' == 'null' - name = null; - break; - case '(': - optional = new Optional(optional); - break; - case ')': - if (optional == null) - throw new IllegalArgumentException("Optional closing found without opening @ " + x + ": " + pattern); - optional = optional.finish(x, pattern, ret); - break; - default: - if (name != null) - name.append(c); - else if (optional != null) - optional.append(c); - else - ret.append(c); - } - } - if (optional != null) - throw new IllegalArgumentException("Missing closing of optional value: " + pattern); - if (name != null) - throw new IllegalArgumentException("Missing closing of name entry: " + pattern); - return ret.toString(); - } - - public static String quote(String value) { - return value.replaceAll("\\", "\\\\") - .replaceAll("(", "\\(") - .replaceAll(")", "\\)") - .replaceAll("[", "\\[") - .replaceAll("]", "\\]"); - } - - private static class Optional { - private final Optional parent; - private final StringBuffer buf = new StringBuffer(); - private boolean hadAll = true; - private boolean hadValue = false; - - private Optional(Optional parent) { - this.parent = parent; - } - - public void append(char c) { - buf.append(c); - } - - private void setKey(String key, Map values) { - hadValue = true; - String value = values.get(key); - if (value != null && !value.isEmpty()) { - hadAll &= true; - buf.append(value); - } else - hadAll = false; - } - - public Optional finish(int position, String pattern, StringBuffer ret) { - if (!hadValue) - throw new IllegalArgumentException("Invalid optional, missing inner name @ " + position +": " + pattern); - if (hadAll) - (parent == null ? ret : parent.buf).append(buf); - return parent; - } - } -} diff --git a/src/shared/java/net/minecraftforge/artifactural/base/artifact/ArtifactBase.java b/src/shared/java/net/minecraftforge/artifactural/base/artifact/ArtifactBase.java new file mode 100644 index 0000000..ddcc8a5 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/artifact/ArtifactBase.java @@ -0,0 +1,72 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.artifact; + +import net.minecraftforge.artifactural.api.artifact.Artifact; +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier; +import net.minecraftforge.artifactural.api.artifact.ArtifactMetadata; +import net.minecraftforge.artifactural.api.artifact.ArtifactType; +import net.minecraftforge.artifactural.api.cache.ArtifactCache; +import net.minecraftforge.artifactural.api.transform.ArtifactTransformer; + +public abstract class ArtifactBase implements Artifact { + + private final ArtifactIdentifier identifier; + private final ArtifactType type; + private final ArtifactMetadata metadata; + + public 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.Cached cache(ArtifactCache cache) { + return cache.store(this); + } + + @Override + public String toString() { + return getClass().getSimpleName() + "(" + identifier + ", " + type +", " + metadata; + } + +} diff --git a/src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactIdentifier.java b/src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactIdentifier.java new file mode 100644 index 0000000..5ab60f6 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactIdentifier.java @@ -0,0 +1,70 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.artifact; + +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier; + +public class SimpleArtifactIdentifier implements ArtifactIdentifier { + + private final String group, name, version, classifier, extension; + + public SimpleArtifactIdentifier(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; + } + + @Override + public String toString() { + String ret = getGroup() + ':' + getName() + ':' + getVersion(); + if (classifier != null) + ret += ':' + getClassifier(); + if ("jar".equals(extension)) + ret += '@' + getExtension(); + return ret; + } +} diff --git a/src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactMetadata.java b/src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactMetadata.java new file mode 100644 index 0000000..21a1f20 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/artifact/SimpleArtifactMetadata.java @@ -0,0 +1,86 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.artifact; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import net.minecraftforge.artifactural.api.artifact.ArtifactMetadata; + +public class SimpleArtifactMetadata implements ArtifactMetadata { + + private final List entries = new LinkedList<>(); + private String hash = null; + + 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() { + if (hash != null) return hash; + try { + String str = entries.stream().map(Entry::toString).collect(Collectors.joining("\n")); + MessageDigest digest = MessageDigest.getInstance("SHA-1"); + byte[] hashBytes = digest.digest(str.getBytes()); + StringBuilder hashBuilder = new StringBuilder(); + for (byte b : hashBytes) { + hashBuilder.append(String.format("%02x", b)); + } + return hash = hashBuilder.toString(); + } catch (NoSuchAlgorithmException ex) { + throw new RuntimeException(ex); + } + } + + @Override + public String toString() { + return "SimpleArtifactMetadata(" + entries.toString() + ", " + getHash() + ")"; + } + + 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/net/minecraftforge/artifactural/base/artifact/StreamableArtifact.java b/src/shared/java/net/minecraftforge/artifactural/base/artifact/StreamableArtifact.java new file mode 100644 index 0000000..0428572 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/artifact/StreamableArtifact.java @@ -0,0 +1,111 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.artifact; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import net.minecraftforge.artifactural.api.artifact.Artifact; +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier; +import net.minecraftforge.artifactural.api.artifact.ArtifactMetadata; +import net.minecraftforge.artifactural.api.artifact.ArtifactType; +import net.minecraftforge.artifactural.api.artifact.MissingArtifactException; +import net.minecraftforge.artifactural.api.artifact.Streamable; + +public class StreamableArtifact extends ArtifactBase { + + public static Artifact ofFile(ArtifactIdentifier identifier, ArtifactType type, File file) { + return new StreamableFileArtifact(identifier, type, file); + } + + public static Artifact ofURL(ArtifactIdentifier identifier, ArtifactType type, URL url) { + return new StreamableArtifact(identifier, type, url::openStream); + } + + public static Artifact ofBytes(ArtifactIdentifier identifier, ArtifactType type, byte[] bytes) { + return new StreamableArtifact(identifier, type, () -> new ByteArrayInputStream(bytes)); + } + + 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, new SimpleArtifactMetadata(), 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(); + } + + private static class StreamableFileArtifact extends StreamableArtifact implements Artifact.Cached { + + private final File file; + + private StreamableFileArtifact(ArtifactIdentifier identifier, ArtifactType type, File file) { + super(identifier, type, () -> new FileInputStream(file)); + this.file = file; + } + + @Override + public File asFile() throws MissingArtifactException { + return file; + } + + @Override + public File getFileLocation() throws MissingArtifactException { + return file; + } + + @Override + public String toString() { + return "StreamableFileArtifact(" + file + ")"; + } + + } + +} diff --git a/src/shared/java/net/minecraftforge/artifactural/base/cache/ArtifactCacheBase.java b/src/shared/java/net/minecraftforge/artifactural/base/cache/ArtifactCacheBase.java new file mode 100644 index 0000000..3268871 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/cache/ArtifactCacheBase.java @@ -0,0 +1,129 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.cache; + +import net.minecraftforge.artifactural.api.artifact.Artifact; +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier; +import net.minecraftforge.artifactural.api.artifact.ArtifactMetadata; +import net.minecraftforge.artifactural.api.artifact.ArtifactType; +import net.minecraftforge.artifactural.api.artifact.MissingArtifactException; +import net.minecraftforge.artifactural.api.cache.ArtifactCache; +import net.minecraftforge.artifactural.api.transform.ArtifactTransformer; +import net.minecraftforge.artifactural.base.artifact.StreamableArtifact; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public abstract class ArtifactCacheBase implements ArtifactCache { + + Artifact.Cached doStore(File path, Artifact artifact) { + return wrap( + StreamableArtifact.ofStreamable( + artifact.getIdentifier(), + artifact.getType(), + () -> stream(path, artifact) + ).withMetadata(artifact.getMetadata()), + path + ); + } + + 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); + } + + public static Artifact.Cached wrap(Artifact artifact, File file) { + return new Artifact.Cached() { + + @Override + public ArtifactIdentifier getIdentifier() { + return artifact.getIdentifier(); + } + + @Override + public ArtifactMetadata getMetadata() { + return artifact.getMetadata(); + } + + @Override + public ArtifactType getType() { + return artifact.getType(); + } + + @Override + public Artifact withMetadata(ArtifactMetadata metadata) { + return artifact.withMetadata(metadata); + } + + @Override + public Artifact apply(ArtifactTransformer transformer) { + return artifact.apply(transformer); + } + + @Override + public Artifact.Cached cache(ArtifactCache cache) { + return artifact.cache(cache); + } + + @Override + public boolean isPresent() { + return artifact.isPresent(); + } + + @Override + public InputStream openStream() throws IOException, MissingArtifactException { + return artifact.openStream(); + } + + @Override + public File asFile() throws IOException, MissingArtifactException { + if(!file.exists()) { + artifact.openStream().close(); + } + return file; + } + + @Override + public File getFileLocation() throws MissingArtifactException { + return file; + } + @Override + public String toString() { + return "wrapped(" + artifact + ", " + file + ")"; + } + }; + } + +} diff --git a/src/shared/java/net/minecraftforge/artifactural/base/cache/LocatedArtifactCache.java b/src/shared/java/net/minecraftforge/artifactural/base/cache/LocatedArtifactCache.java new file mode 100644 index 0000000..5627b50 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/cache/LocatedArtifactCache.java @@ -0,0 +1,69 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.cache; + +import net.minecraftforge.artifactural.api.artifact.Artifact; +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier; +import net.minecraftforge.artifactural.base.util.PatternReplace; + +import java.io.File; +import java.util.AbstractMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class LocatedArtifactCache extends ArtifactCacheBase { + private static final String PATTERN = "[group]/[name](/[meta_hash])/[version]/[name]-[version](-[classifier])(-[specifier]).[extension]"; + private final File path; + + public LocatedArtifactCache(File path) { + this.path = path; + } + + @Override + public Artifact.Cached store(Artifact artifact) { + return doStore(getPath(artifact), artifact); + } + + public File getPath(Artifact artifact) { + ArtifactIdentifier identifier = artifact.getIdentifier(); + Map names = Stream.of( + entry("group", identifier.getGroup()), + entry("name", identifier.getName()), + entry("version", identifier.getVersion()), + entry("classifier", identifier.getClassifier()), + entry("extension", identifier.getExtension()), + //entry("specifier", specifier), /? + entry("meta_hash", artifact.getMetadata().getHash()) + ).collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + return new File(path, PatternReplace.replace(PATTERN, names)); + } + + private static Entry entry(K key, V value) { + return new AbstractMap.SimpleEntry<>(key, value); + } + + @Override + public String toString() { + return "LocatedArtifactCache(" + path + ")"; + } + +} diff --git a/src/shared/java/net/minecraftforge/artifactural/base/repository/ArtifactProviderBuilder.java b/src/shared/java/net/minecraftforge/artifactural/base/repository/ArtifactProviderBuilder.java new file mode 100644 index 0000000..282f9b4 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/repository/ArtifactProviderBuilder.java @@ -0,0 +1,100 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.repository; + +import java.util.HashSet; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Predicate; + +import net.minecraftforge.artifactural.api.artifact.Artifact; +import net.minecraftforge.artifactural.api.repository.ArtifactProvider; + +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/net/minecraftforge/artifactural/base/repository/SimpleRepository.java b/src/shared/java/net/minecraftforge/artifactural/base/repository/SimpleRepository.java new file mode 100644 index 0000000..3076b08 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/repository/SimpleRepository.java @@ -0,0 +1,44 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.repository; + +import net.minecraftforge.artifactural.api.artifact.Artifact; +import net.minecraftforge.artifactural.api.artifact.ArtifactIdentifier; +import net.minecraftforge.artifactural.api.repository.ArtifactProvider; +import net.minecraftforge.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/net/minecraftforge/artifactural/base/util/HashFunction.java b/src/shared/java/net/minecraftforge/artifactural/base/util/HashFunction.java new file mode 100644 index 0000000..bcf00f9 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/util/HashFunction.java @@ -0,0 +1,135 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Locale; + +//These are all standard hashing functions the JRE is REQUIRED to have, so add a nice factory that doesnt require catching annoying exceptions; +public enum HashFunction { + MD5("md5", 32), + SHA1("SHA-1", 40), + SHA256("SHA-256", 64); + + private String algo; + private String pad; + + private HashFunction(String algo, int length) { + this.algo = algo; + // must specify locale to get correct number formatting + this.pad = String.format(Locale.ENGLISH, "%0" + length + "d", 0); + } + + public String getExtension() { + return this.name().toLowerCase(Locale.ENGLISH); + } + + public Instance create() { + return new Instance(); + } + + public MessageDigest get() { + try { + return MessageDigest.getInstance(algo); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); //Never happens + } + } + + public String hash(File file) throws IOException { + try (FileInputStream fin = new FileInputStream(file)) { + return hash(fin); + } + } + + public String hash(Iterable files) throws IOException { + MessageDigest hash = get(); + byte[] buf = new byte[1024]; + + for (File file : files) { + if (!file.exists()) + continue; + + try (FileInputStream fin = new FileInputStream(file)) { + int count = -1; + while ((count = fin.read(buf)) != -1) + hash.update(buf, 0, count); + } + } + return pad(new BigInteger(1, hash.digest()).toString(16)); + } + + public String hash(String data) { + return hash(data.getBytes(StandardCharsets.UTF_8)); + } + + public String hash(InputStream stream) throws IOException { + MessageDigest hash = get(); + byte[] buf = new byte[1024]; + int count = -1; + while ((count = stream.read(buf)) != -1) + hash.update(buf, 0, count); + return pad(new BigInteger(1, hash.digest()).toString(16)); + } + + public String hash(byte[] data) { + return pad(new BigInteger(1, get().digest(data)).toString(16)); + } + + public String pad(String hash) { + return (pad + hash).substring(hash.length()); + } + + public class Instance { + private MessageDigest digest = HashFunction.this.get(); + public void update(byte input) { + digest.update(input); + } + public void update(byte[] input) { + digest.update(input); + } + public void update(byte[] input, int offset, int length) { + digest.update(input, offset, length); + } + public void update(ByteBuffer input) { + digest.update(input); + } + public void update(String input) { + update(input.getBytes(StandardCharsets.UTF_8)); + } + public void update(int input) { + update(new byte[] { (byte)((input & 0xFF000000) >> 24), (byte)((input & 0xFF000000) >> 16), (byte)((input & 0xFF000000) >> 8), (byte)((input & 0xFF000000))}); + } + public byte[] digest() { + return digest.digest(); + } + public String finish() { + return pad(new BigInteger(1, digest()).toString(16)); + } + } +} diff --git a/src/shared/java/net/minecraftforge/artifactural/base/util/PatternReplace.java b/src/shared/java/net/minecraftforge/artifactural/base/util/PatternReplace.java new file mode 100644 index 0000000..6d3cf86 --- /dev/null +++ b/src/shared/java/net/minecraftforge/artifactural/base/util/PatternReplace.java @@ -0,0 +1,159 @@ +/* + * Artifactural + * Copyright (c) 2018-2021. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.artifactural.base.util; + +import java.util.Map; + +public class PatternReplace { + /* + * Replaces a patterened string, with support for optional groups. + * Example: + * Values: + * group: net/minecraftforge + * name: forge + * version: 1.0 + * ext: jar + * + * Example: [group]/[name]/[version]/[name]-[version](-[classifier]).[ext] + * {classifier: test} net/minecraftforge/forge/1.0/forge-1.0-test.jar + * {classifier: null} net/minecraftforge/forge/1.0/forge-1.0.jar + * + * Nested Optionals are supported: + * Example: [group]/[name]/[version]/[name]-[version](-[classifier](-[suffix])).[ext] + * {classifier: test, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0-test-foo.jar + * {classifier: test, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0-test.jar + * {classifier: null, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0.jar + * + * Compound optionals are supported: + * Example: [group]/[name]/[version]/[name]-[version](-[classifier]-[suffix]).[ext] + * {classifier: test, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0-test-foo.jar + * {classifier: test, suffix: null} net/minecraftforge/forge/1.0/forge-1.0.jar + * {classifier: null, suffix: foo} net/minecraftforge/forge/1.0/forge-1.0.jar + * + * + * TODO: Support nested names? + * Example: [group]/[name]/[version]/[name]-[version](-[classifier[suffix]]).[ext] + * {classifierFoo: test, suffix: Foo} net/minecraftforge/forge/1.0/forge-1.0-test.jar + * {classifierFoo: null, suffix: Foo} net/minecraftforge/forge/1.0/forge-1.0.jar + */ + public static String replace(String pattern, Map values) { + if (pattern == null) return null; + if (pattern.isEmpty()) return ""; + + Optional optional = null; + StringBuffer name = null; + StringBuffer ret = new StringBuffer(); + + char[] chars = pattern.toCharArray(); + for (int x = 0; x < chars.length; x++) { + char c = chars[x]; + if (c == '\\') { + if (x == chars.length -1) + throw new IllegalArgumentException("Escape character can not be end of pattern: " + pattern); + x++; + ret.append(chars[x]); + continue; + } + switch (c) { + case '[': + if (name != null) + throw new IllegalArgumentException("Nested names are not supported @ " + x + " : " + pattern); + name = new StringBuffer(); + break; + case ']': + if (name == null) + throw new IllegalArgumentException("Name closing found without opening @ " + x + " : " + pattern); + String key = name.toString(); + if (key.isEmpty()) + throw new IllegalArgumentException("Name can not be empty @ " + x + ": " + pattern); + if (optional != null) + optional.setKey(key, values); + else + ret.append(values.get(key)); // appends 'null' if missing, if you want "" then use ([name]) + // Should we have this default to not replacing at all if value is not set to allow chaining? + // Meaning: '[key]' == '[key]' if 'key' is not set. + // Current: '[key]' == 'null' + name = null; + break; + case '(': + optional = new Optional(optional); + break; + case ')': + if (optional == null) + throw new IllegalArgumentException("Optional closing found without opening @ " + x + ": " + pattern); + optional = optional.finish(x, pattern, ret); + break; + default: + if (name != null) + name.append(c); + else if (optional != null) + optional.append(c); + else + ret.append(c); + } + } + if (optional != null) + throw new IllegalArgumentException("Missing closing of optional value: " + pattern); + if (name != null) + throw new IllegalArgumentException("Missing closing of name entry: " + pattern); + return ret.toString(); + } + + public static String quote(String value) { + return value.replaceAll("\\", "\\\\") + .replaceAll("(", "\\(") + .replaceAll(")", "\\)") + .replaceAll("[", "\\[") + .replaceAll("]", "\\]"); + } + + private static class Optional { + private final Optional parent; + private final StringBuffer buf = new StringBuffer(); + private boolean hadAll = true; + private boolean hadValue = false; + + private Optional(Optional parent) { + this.parent = parent; + } + + public void append(char c) { + buf.append(c); + } + + private void setKey(String key, Map values) { + hadValue = true; + String value = values.get(key); + if (value != null && !value.isEmpty()) { + hadAll &= true; + buf.append(value); + } else + hadAll = false; + } + + public Optional finish(int position, String pattern, StringBuffer ret) { + if (!hadValue) + throw new IllegalArgumentException("Invalid optional, missing inner name @ " + position +": " + pattern); + if (hadAll) + (parent == null ? ret : parent.buf).append(buf); + return parent; + } + } +} -- cgit