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
commit 4144b034d59f9c0045051f289b1a46e2390af1c3 Author: Simo Tripodi <[email protected]> AuthorDate: Tue Jun 11 13:12:51 2019 +0200 SLING-8251 - Support checking dependencies for content packages initial checkin --- .../impl/CheckContentPackagesDependencies.java | 130 +++++++++++++++++++++ ...apache.sling.feature.analyser.task.AnalyserTask | 1 + 2 files changed, 131 insertions(+) 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 new file mode 100644 index 0000000..001fdd5 --- /dev/null +++ b/src/main/java/org/apache/sling/feature/analyser/task/impl/CheckContentPackagesDependencies.java @@ -0,0 +1,130 @@ +/* + * 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 java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Map; +import java.util.Properties; +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.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 = ","; + + @Override + public String getId() { + return "content-packages-dependencies"; + } + + @Override + public String getName() { + return "Content-packages dependencies checker"; + } + + @Override + public void execute(AnalyserTaskContext ctx) throws Exception { + Set<ArtifactDescriptor> descriptors = ctx.getFeatureDescriptor().getArtifactDescriptors(); + if (descriptors == null || descriptors.isEmpty()) { + return; + } + + Map<String, Set<String>> dependenciesMap = new HashMap<>(); + + for (ArtifactDescriptor descriptor : descriptors) { + onDescriptor(ctx, descriptor, dependenciesMap); + } + + for (String 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)); + + 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); + } + } + } + + private void verifyDependenciesTree(AnalyserTaskContext ctx, String root, Map<String, Set<String>> dependenciesMap) { + Queue<String> toBeVisited = new LinkedList<>(); + toBeVisited.add(root); + + Set<String> 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)); + } + } + } + +} diff --git a/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask b/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask index 8c8f112..4b1e59a 100644 --- a/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask +++ b/src/main/resources/META-INF/services/org.apache.sling.feature.analyser.task.AnalyserTask @@ -7,3 +7,4 @@ org.apache.sling.feature.analyser.task.impl.CheckApiRegions org.apache.sling.feature.analyser.task.impl.CheckApiRegionsDependencies org.apache.sling.feature.analyser.task.impl.CheckApiRegionsDuplicates org.apache.sling.feature.analyser.task.impl.CheckApiRegionsOrder +org.apache.sling.feature.analyser.task.impl.CheckContentPackagesDependencies \ No newline at end of file
