This is an automated email from the ASF dual-hosted git repository.
pauls pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-whiteboard.git
The following commit(s) were added to refs/heads/master by this push:
new 7b14a68 SLING-9670: add a new unpack extension for the feature model.
7b14a68 is described below
commit 7b14a68f7cba5dc541673394a603f6b91c23bed9
Author: Karl Pauls <[email protected]>
AuthorDate: Mon Aug 17 14:40:23 2020 +0200
SLING-9670: add a new unpack extension for the feature model.
---
.../sling/feature/extension/unpack/Unpack.java | 90 ++++++++++++++++++++--
1 file changed, 84 insertions(+), 6 deletions(-)
diff --git
a/featuremodel-unpack-extension/src/main/java/org/apache/sling/feature/extension/unpack/Unpack.java
b/featuremodel-unpack-extension/src/main/java/org/apache/sling/feature/extension/unpack/Unpack.java
index c066ebf..235c570 100644
---
a/featuremodel-unpack-extension/src/main/java/org/apache/sling/feature/extension/unpack/Unpack.java
+++
b/featuremodel-unpack-extension/src/main/java/org/apache/sling/feature/extension/unpack/Unpack.java
@@ -19,10 +19,20 @@
package org.apache.sling.feature.extension.unpack;
+import java.io.File;
+import java.io.IOException;
+import java.io.UncheckedIOException;
import java.net.URL;
+import java.nio.file.FileAlreadyExistsException;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Predicate;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
import org.apache.felix.utils.manifest.Clause;
import org.apache.felix.utils.manifest.Directive;
@@ -31,23 +41,38 @@ import org.apache.sling.feature.Artifact;
import org.apache.sling.feature.Extension;
import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.builder.ArtifactProvider;
+import org.apache.sling.feature.io.IOUtils;
public class Unpack
{
private final Map<String, Map<String, String>> registry;
+ private final String defaultMapping;
private Unpack(Map<String, Map<String, String>> registry) {
this.registry = registry;
+ defaultMapping = registry.entrySet().stream()
+ .filter(entry ->
Boolean.parseBoolean(entry.getValue().get("default")))
+ .findFirst()
+ .map(entry -> entry.getKey())
+ .orElse(null);
}
- public boolean handle(Extension extension, ArtifactProvider provider)
throws Exception
+ public boolean handle(Extension extension, ArtifactProvider provider) {
+ return handle(extension, provider, this::unpack);
+ }
+
+ public boolean handle(Extension extension, ArtifactProvider provider,
BiConsumer<URL, Map<String, String>> handler)
{
if (extension.getType() == ExtensionType.ARTIFACTS &&
this.registry.containsKey(extension.getName())) {
for (Artifact artifact : extension.getArtifacts()) {
- unpack(this.registry.get(extension.getName()).get("dir"),
- provider.provide(artifact.getId()),
-
Boolean.parseBoolean(this.registry.get(extension.getName()).get("override")));
+ String dir = this.registry.get(extension.getName()).get("dir");
+ boolean override =
Boolean.parseBoolean(this.registry.get(extension.getName()).get("override"));
+ URL url = provider.provide(artifact.getId());
+ Map<String, String> context = new HashMap<>();
+ context.put("dir", dir);
+ context.put("override", Boolean.toString(override));
+ handler.accept(url, context);
}
return true;
} else {
@@ -55,11 +80,27 @@ public class Unpack
}
}
+ public void unpack(URL url, Map<String, String> context) {
+ try
+ {
+ String dir = context.get("dir");
+ if (dir == null) {
+ dir = defaultMapping;
+ }
+ if (dir == null) {
+ throw new IllegalStateException("No target dir and no default
configured");
+ }
+ unpack(dir, url, Boolean.parseBoolean(context.get("override")));
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+
public static Unpack fromMapping(String mapping)
{
Map<String, Map<String, String>> registry = new HashMap<>();
- // Syntax:
system-fonts;dir:=abc;overwrite:=true,customer-fonts;dir:=eft
+ // Syntax:
system-fonts;dir:=abc;overwrite:=true,customer-fonts;dir:=eft;default=true
Clause[] extClauses = Parser.parseHeader(mapping);
for (Clause c : extClauses) {
Map<String,String> cfg = new HashMap<>();
@@ -72,7 +113,44 @@ public class Unpack
return new Unpack(registry);
}
- private void unpack(String dir, URL url, boolean override) throws
Exception {
+ private void unpack(String dir, URL url, boolean override) throws
IOException {
+ File base = new File(dir);
+ if (!base.isDirectory() && !base.mkdirs()) {
+ throw new IOException("Unable to find or created base dir: " +
base);
+ }
+ try (JarFile jarFile = IOUtils.getJarFileFromURL(url, true, null)) {
+ jarFile.stream().filter(((Predicate<JarEntry>)
JarEntry::isDirectory).negate()).forEach(entry -> {
+ File target = new File(base, entry.getName());
+ if (target.getParentFile().toPath().startsWith(base.toPath()))
{
+ if (target.getParentFile().isDirectory() ||
target.getParentFile().mkdirs()) {
+ try
+ {
+ if (override)
+ {
+ Files.copy(jarFile.getInputStream(entry),
target.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ }
+ else if (!target.exists())
+ {
+ try
+ {
+ Files.copy(jarFile.getInputStream(entry),
target.toPath());
+ } catch (FileAlreadyExistsException ex) {
+
+ }
+ }
+ } catch (IOException ex) {
+ throw new UncheckedIOException(ex);
+ }
+ }
+ else {
+ throw new IllegalStateException("Can't create parent
dir:" + target.getParentFile());
+ }
+ }
+ else {
+ throw new IllegalStateException("Zip slip detected for: "
+ entry.getName());
+ }
+ });
+ }
}
}