You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by si...@apache.org on 2019/06/11 15:58:33 UTC
[sling-org-apache-sling-feature-analyser] branch SLING-8251
updated: SLING-8251 - Support checking dependencies for content packages
This is an automated email from the ASF dual-hosted git repository.
simonetripodi pushed a commit to branch SLING-8251
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-analyser.git
The following commit(s) were added to refs/heads/SLING-8251 by this push:
new 23521a7 SLING-8251 - Support checking dependencies for content packages
23521a7 is described below
commit 23521a71469a259a994617f6eac35f28bebfc0b1
Author: Simo Tripodi <st...@adobe.com>
AuthorDate: Tue Jun 11 17:58:24 2019 +0200
SLING-8251 - Support checking dependencies for content packages
Implementation fixed using Jackrabbit Vault APIs
Added unit tests
---
pom.xml | 27 ++++-
.../impl/CheckContentPackagesDependencies.java | 99 +++++++---------
.../impl/CheckContentPackagesDependenciesTest.java | 126 +++++++++++++++++++++
src/test/resources/test_a-1.0.zip | Bin 0 -> 4470 bytes
src/test/resources/test_b-1.0.zip | Bin 0 -> 4442 bytes
src/test/resources/test_c-1.0.zip | Bin 0 -> 4402 bytes
src/test/resources/test_d-1.0.zip | Bin 0 -> 4450 bytes
src/test/resources/test_e-1.0.zip | Bin 0 -> 4439 bytes
8 files changed, 191 insertions(+), 61 deletions(-)
diff --git a/pom.xml b/pom.xml
index c91d51a..fbc04ae 100644
--- a/pom.xml
+++ b/pom.xml
@@ -143,7 +143,32 @@
<version>1.11.0</version>
<scope>provided</scope>
</dependency>
-
+
+ <!-- | Content-Package check -->
+ <dependency>
+ <groupId>org.apache.jackrabbit.vault</groupId>
+ <artifactId>org.apache.jackrabbit.vault</artifactId>
+ <version>3.2.6</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.jackrabbit</groupId>
+ <artifactId>jackrabbit-spi-commons</artifactId>
+ <version>2.19.1</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>javax.jcr</groupId>
+ <artifactId>jcr</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.6</version>
+ <scope>provided</scope>
+ </dependency>
+
<!-- Testing -->
<dependency>
<groupId>junit</groupId>
diff --git a/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependencies.java b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependencies.java
index 001fdd5..937472a 100644
--- a/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependencies.java
+++ b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependencies.java
@@ -20,31 +20,22 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
-import java.util.Properties;
+import java.util.Map.Entry;
import java.util.Queue;
import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.TreeSet;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
+import org.apache.jackrabbit.vault.packaging.Dependency;
+import org.apache.jackrabbit.vault.packaging.PackageId;
+import org.apache.jackrabbit.vault.packaging.PackageManager;
+import org.apache.jackrabbit.vault.packaging.VaultPackage;
+import org.apache.jackrabbit.vault.packaging.impl.PackageManagerImpl;
import org.apache.sling.feature.analyser.task.AnalyserTask;
import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
import org.apache.sling.feature.scanner.ArtifactDescriptor;
public class CheckContentPackagesDependencies implements AnalyserTask {
- private static final String VAULT_PROPERTIES_XML = "META-INF/vault/properties.xml";
-
- private static final String GROUP = "group";
-
- private static final String NAME = "name";
-
- private static final String VERSION = "version";
-
- private static final String DEPENDENCIES = "dependencies";
-
- private static final String DEPENDENCIES_DELIM = ",";
+ private final PackageManager packageManager = new PackageManagerImpl();
@Override
public String getId() {
@@ -63,68 +54,56 @@ public class CheckContentPackagesDependencies implements AnalyserTask {
return;
}
- Map<String, Set<String>> dependenciesMap = new HashMap<>();
+ Map<PackageId, Dependency[]> dependenciesMap = new HashMap<>();
for (ArtifactDescriptor descriptor : descriptors) {
onDescriptor(ctx, descriptor, dependenciesMap);
}
- for (String contentPackageId : dependenciesMap.keySet()) {
+ for (PackageId contentPackageId : dependenciesMap.keySet()) {
verifyDependenciesTree(ctx, contentPackageId, dependenciesMap);
}
}
- private void onDescriptor(AnalyserTaskContext ctx, ArtifactDescriptor descriptor, Map<String, Set<String>> dependenciesMap) throws Exception {
- try (ZipFile zipFile = new ZipFile(descriptor.getArtifactFile())) {
- ZipEntry propertiesEntry = zipFile.getEntry(VAULT_PROPERTIES_XML);
-
- if (propertiesEntry == null) {
- ctx.reportWarning("Content-package file "
- + descriptor.getArtifact().getId()
- + " does not contain the 'META-INF/vault/properties.xml' entry, skipping it");
- return;
- }
-
- Properties properties = new Properties();
- properties.load(zipFile.getInputStream(propertiesEntry));
-
- String current = String.format("%s:%s:%s",
- properties.getProperty(GROUP),
- properties.getProperty(NAME),
- properties.getProperty(VERSION));
+ private void onDescriptor(AnalyserTaskContext ctx, ArtifactDescriptor descriptor, Map<PackageId, Dependency[]> dependenciesMap) throws Exception {
+ try (VaultPackage vaultPackage = packageManager.open(descriptor.getArtifactFile(), true)) {
+ PackageId packageId = vaultPackage.getId();
- Set<String> dependenciesSet = dependenciesMap.computeIfAbsent(current, k -> new TreeSet<String>());
-
- String dependencies = properties.getProperty(DEPENDENCIES);
- if (dependencies == null || dependencies.isEmpty()) {
- return;
- }
-
- StringTokenizer tokenizer = new StringTokenizer(dependencies, DEPENDENCIES_DELIM);
- while (tokenizer.hasMoreTokens()) {
- String dependency = tokenizer.nextToken().trim();
- dependenciesSet.add(dependency);
- }
+ dependenciesMap.put(packageId, vaultPackage.getDependencies());
}
}
- private void verifyDependenciesTree(AnalyserTaskContext ctx, String root, Map<String, Set<String>> dependenciesMap) {
- Queue<String> toBeVisited = new LinkedList<>();
- toBeVisited.add(root);
+ private void verifyDependenciesTree(AnalyserTaskContext ctx, PackageId root, Map<PackageId, Dependency[]> dependenciesMap) {
+ Queue<Dependency> toBeVisited = new LinkedList<>();
+ enqueue(toBeVisited, dependenciesMap.get(root));
- Set<String> alreadyVisited = new HashSet<>();
+ Set<Dependency> alreadyVisited = new HashSet<>();
while (!toBeVisited.isEmpty()) {
- String current = toBeVisited.poll();
-
- alreadyVisited.add(current);
-
- if (!dependenciesMap.containsKey(current)) {
- ctx.reportError(current + " content-package expected, but not found, as a dependency of " + root);
- } else {
- toBeVisited.addAll(dependenciesMap.get(current));
+ Dependency current = toBeVisited.poll();
+
+ if (alreadyVisited.add(current)) {
+ boolean found = false;
+
+ for (Entry<PackageId, Dependency[]> entry : dependenciesMap.entrySet()) {
+ if (current.matches(entry.getKey())) {
+ enqueue(toBeVisited, entry.getValue());
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ ctx.reportError("Missing " + current + " dependency for " + root);
+ }
}
}
}
+ private static void enqueue(Queue<Dependency> target, Dependency...dependencies) {
+ for (Dependency dependency : dependencies) {
+ target.offer(dependency);
+ }
+ }
+
}
diff --git a/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependenciesTest.java b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependenciesTest.java
new file mode 100644
index 0000000..4d5210d
--- /dev/null
+++ b/src/test/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependenciesTest.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sling.feature.analyser.task.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.apache.sling.feature.Artifact;
+import org.apache.sling.feature.ArtifactId;
+import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.analyser.task.AnalyserTask;
+import org.apache.sling.feature.analyser.task.AnalyserTaskContext;
+import org.apache.sling.feature.scanner.ArtifactDescriptor;
+import org.apache.sling.feature.scanner.FeatureDescriptor;
+import org.apache.sling.feature.scanner.impl.FeatureDescriptorImpl;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class CheckContentPackagesDependenciesTest {
+
+ private AnalyserTask task;
+
+ @Before
+ public void setUp() {
+ task = new CheckContentPackagesDependencies();
+ }
+
+ @After
+ public void tearDown() {
+ task = null;
+ }
+
+ @Test
+ public void dependenciesNotResolvedThrowsError() throws Exception {
+ List<String> errors = execute("test_a-1.0.zip");
+
+ assertFalse(errors.isEmpty());
+
+ Iterator<String> errorsIterator = errors.iterator();
+ assertEquals("Missing my_packages:test_b dependency for my_packages:test_a:1.0", errorsIterator.next());
+ assertEquals("Missing my_packages:test_c:[1.0,2.0) dependency for my_packages:test_a:1.0", errorsIterator.next());
+ }
+
+ @Test
+ public void dependenciesResolved() throws Exception {
+ List<String> errors = execute("test_a-1.0.zip",
+ "test_b-1.0.zip",
+ "test_c-1.0.zip",
+ "test_d-1.0.zip",
+ "test_e-1.0.zip");
+ assertTrue(errors.isEmpty());
+ }
+
+ private List<String> execute(String...resources) throws Exception {
+ Feature feature = mock(Feature.class);
+ when(feature.getId()).thenReturn(new ArtifactId("org.apache.sling.testing",
+ "org.apache.sling.testing.contentpackages",
+ "1.0.0",
+ null,
+ null));
+ FeatureDescriptor featureDescriptor = new FeatureDescriptorImpl(feature);
+
+ for (String resource : resources) {
+ ArtifactId id = mock(ArtifactId.class);
+ when(id.toMvnId()).thenReturn(resource);
+ when(id.toString()).thenReturn(resource);
+
+ Artifact artifact = mock(Artifact.class);
+ when(artifact.getId()).thenReturn(id);
+
+ ArtifactDescriptor descriptor = mock(ArtifactDescriptor.class);
+
+ when(descriptor.getArtifact()).thenReturn(artifact);
+
+ URL resourceUrl = getClass().getClassLoader().getResource(resource);
+ String filename = resourceUrl.getFile().replace('/', File.separatorChar);
+ when(descriptor.getArtifactFile()).thenReturn(new File(filename));
+
+ featureDescriptor.getArtifactDescriptors().add(descriptor);
+ }
+
+ AnalyserTaskContext ctx = mock(AnalyserTaskContext.class);
+
+ when(ctx.getFeatureDescriptor()).thenReturn(featureDescriptor);
+
+ List<String> errors = new LinkedList<>();
+
+ doAnswer(invocation -> {
+ String error = invocation.getArgument(0);
+ errors.add(error);
+ return null;
+ }).when(ctx).reportError(anyString());
+
+ task.execute(ctx);
+
+ return errors;
+ }
+
+}
diff --git a/src/test/resources/test_a-1.0.zip b/src/test/resources/test_a-1.0.zip
new file mode 100644
index 0000000..08df03a
Binary files /dev/null and b/src/test/resources/test_a-1.0.zip differ
diff --git a/src/test/resources/test_b-1.0.zip b/src/test/resources/test_b-1.0.zip
new file mode 100644
index 0000000..85fac13
Binary files /dev/null and b/src/test/resources/test_b-1.0.zip differ
diff --git a/src/test/resources/test_c-1.0.zip b/src/test/resources/test_c-1.0.zip
new file mode 100644
index 0000000..245291a
Binary files /dev/null and b/src/test/resources/test_c-1.0.zip differ
diff --git a/src/test/resources/test_d-1.0.zip b/src/test/resources/test_d-1.0.zip
new file mode 100644
index 0000000..7acf3d1
Binary files /dev/null and b/src/test/resources/test_d-1.0.zip differ
diff --git a/src/test/resources/test_e-1.0.zip b/src/test/resources/test_e-1.0.zip
new file mode 100644
index 0000000..372bbb9
Binary files /dev/null and b/src/test/resources/test_e-1.0.zip differ