You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2021/04/14 08:35:26 UTC
[sling-org-apache-sling-feature-cpconverter] branch master updated:
SLING-10127 optionally emit converted content type packages to dedicated
folder (#70)
This is an automated email from the ASF dual-hosted git repository.
kwin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-feature-cpconverter.git
The following commit(s) were added to refs/heads/master by this push:
new bacfbd7 SLING-10127 optionally emit converted content type packages to dedicated folder (#70)
bacfbd7 is described below
commit bacfbd74fad08d1e48d3e813091aac0ded62c7b3
Author: Konrad Windszus <kw...@apache.org>
AuthorDate: Wed Apr 14 10:35:17 2021 +0200
SLING-10127 optionally emit converted content type packages to dedicated folder (#70)
---
README.md | 86 ++++++++++++---
.../ContentPackage2FeatureModelConverter.java | 56 ++++++++--
.../cpconverter/artifacts/ArtifactsDeployer.java | 2 +-
... => LocalMavenRepositoryArtifactsDeployer.java} | 21 ++--
.../artifacts/SimpleFolderArtifactsDeployer.java | 61 +++++++++++
...ntentPackage2FeatureModelConverterLauncher.java | 23 +++-
.../ContentPackage2FeatureModelConverterTest.java | 121 ++++++++++++++++++---
.../artifacts/DefaultBundlesDeployerTest.java | 4 +-
.../handlers/BundleEntryHandlerTest.java | 4 +-
9 files changed, 308 insertions(+), 70 deletions(-)
diff --git a/README.md b/README.md
index 66adecf..71907f2 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,11 @@ This tool aims to provide to Apache Sling users an easy-to-use conversion tool w
## Introduction
-`content-package`s are zipped archives containing OSGi bundles, OSGi configurations and resources (and nested `content-package`s as well), aside metadata, that can be used to install content into a _JCR_ repository using the [Apache Jackrabbit FileVault](http://jackrabbit.apache.org/filevault/) packaging runtime.
+`content-package`s are zipped archives containing OSGi bundles, OSGi configurations, JCR nodes/properties and nested `content-package`s as well, aside [metadata](http://jackrabbit.apache.org/filevault/metadata.html), that can be used to install content into a _JCR_ repository using the [Apache Jackrabbit FileVault](http://jackrabbit.apache.org/filevault/) packaging runtime.
OTOH, [Apache Sling Feature](https://github.com/apache/sling-org-apache-sling-feature) allows users to describe an entire OSGi-based application based on reusable components and includes everything related to this application, including bundles, configuration, framework properties, capabilities, requirements and custom artifacts.
-The _Apache Sling Content Package to Feature Model converter_ (referred as _cp2fm_) is a tool able to extract OSGI bundles, OSGi configurations, resources and iteratively scan nested `content-package`s from an input `content-package` and create one (or more) _Apache Sling Feature_ model files and deploy the extracted OSGi bundles in a directory which structure is compliant the _Apache Maven_ repository conventions.
+The _Apache Sling Content Package to Feature Model converter_ (referred as _cp2fm_) is a tool able to extract OSGI bundles, OSGi configurations and iteratively scan nested `content-package`s from an input `content-package` and create one (or more) _Apache Sling Feature_ model files and deploy the extracted OSGi bundles in a directory which structure is compliant the _Apache Maven_ repository conventions. The remaining JCR nodes/properties are kept in content packages which are either ref [...]
## Understanding the Input
@@ -147,9 +147,14 @@ Archive: test-content.zip
39481 22 files
```
+### Package Types
+
+`content-package`s have one of [four package types](http://jackrabbit.apache.org/filevault/packagetypes.html).
+By default type `content` is never referenced inside the feature model (to work with Oak Composite Node Stores), while `application` and `mixed` type's are referenced in the generated feature models. `container` packages are dissolved and all sub packages are flattened (i.e. extracted as individual packages).
+
## Mapping and the Output
-All metadata are mainly collected inside one or more, depending by declared run modes in the installation and configuration paths, _Feature_ model files:
+All metadata are mainly collected inside one or more _Feature_ model files, depending on declared run modes in the installation and configuration paths:
```json
$ cat asd.retail.all.json
@@ -201,7 +206,9 @@ $ cat asd.retail.all-publish.json
}
```
-### Binaries
+### OSGi Bundles and Content Packages
+
+All nodes and properties which are not OSGi configurations or bundles are kept in (stripped) content packages. Usually those content packages are referenced inside the Feature Model (evaluated by [Content Handler](https://github.com/apache/sling-org-apache-sling-feature-extension-content/blob/master/src/main/java/org/apache/sling/feature/extension/content/ContentHandler.java)). For packages of type `content` the user can define what to do with those packages (reference in feature model, [...]
All detected bundles are collected in an _Apache Maven repository_ compliant directory, all other resources are collected in a new `content-package`, usually classified as `cp2fm-converted-feature`, created while scanning the packages, which contains _content only_.
@@ -232,7 +239,7 @@ artifacts/
12 directories, 8 files
```
-### Supported configurations
+### OSGi Configurations
All OSGi configuration formats are supported:
@@ -316,7 +323,7 @@ production=org.apache.test.mytest-sample-site.ui.apps-production.json,org.apache
The [org.apache.sling.feature.cpconverter.artifacts.ArtifactsDeployer](./src/main/java/org/apache/sling/feature/cpconverter/artifacts/ArtifactsDeployer.java) service is designed to let the conversion tool be integrated in external services, i.e. _Apache Maven_.
-The [default implementation](./src/main/java/org/apache/sling/feature/cpconverter/artifacts/DefaultArtifactsDeployer.java) just copies bundles in the target output directory, according to the _Apache Maven_ repository layout.
+The [default implementation](./src/main/java/org/apache/sling/feature/cpconverter/artifacts/LocalMavenRepositoryArtifactsDeployer.java) just copies bundles in the target output directory, according to the _Apache Maven_ repository layout.
Bundles are collected in an _Apache Maven repository_ compliant directory, all other resources are collected in a new `content-package` created while scanning the packages:
@@ -421,7 +428,7 @@ The `!` character is used to separate nested sub-content-packages path.
## The CLI Tool
-The tool is distributed with a commodity package containing all is needed in order to launch the `ContentPackage2FeatureModelConverter` form the shell:
+The tool is distributed with a commodity package containing all is needed in order to launch the `ContentPackage2FeatureModelConverter` from the shell:
```bash
$ unzip -l org.apache.sling.feature.cpconverter-0.0.1-SNAPSHOT.zip
@@ -484,13 +491,52 @@ once the package is decompressed, open the shell and type:
```bash
$ ./bin/cp2fm -h
-Usage: cp2fm [-hmqsvX] -a=<artifactsOutputDirectory> [-b=<bundlesStartOrder>]
- [-i=<artifactIdOverride>] -o=<featureModelsOutputDirectory>
- [-p=<fmPrefix>] [-D=<String=String>]...
- [-f=<filteringPatterns>]... [-r=<apiRegions>]...
- content-packages...
+Usage: cp2fm [-hmqsvXZ] [--disable-installer-policy]
+ [--enforce-servicemapping-by-principal] [--remove-install-hooks]
+ [--content-type-package-policy=<contentTypePackagePolicy>]
+ [--enforce-principal-based-supported-path=<enforcePrincipalBasedSup
+ portedPath>] [--seed-feature=<seedFeature>]
+ [--system-user-rel-path=<systemUserRelPath>]
+ -a=<artifactsOutputDirectory> [-b=<bundlesStartOrder>]
+ [-e=<exportsToRegion>] [-i=<artifactIdOverride>]
+ -o=<featureModelsOutputDirectory> [-p=<fmPrefix>]
+ -u=<unreferencedArtifactsOutputDirectory>
+ [--entry-handler-config=<entryHandlerConfigs>]...
+ [-D=<String=String>]... [-f=<filteringPatterns>]...
+ [-r=<apiRegions>]... content-packages...
Apache Sling Content Package to Sling Feature converter
content-packages... The content-package input file(s).
+ --content-type-package-policy=<contentTypePackagePolicy>
+ Determines what to do with converted packages of type
+ 'content'. Valid values: REFERENCE, DROP,
+ PUT_IN_DEDICATED_FOLDER.
+ Default: DROP
+ --disable-installer-policy
+ Disables enforcing that OSGi configurations are only
+ allowed below a folder called 'config' and OSGi
+ bundles are only allowed below a folder called
+ 'install'. Instead both are detected below either
+ 'install' or 'config'.
+ --enforce-principal-based-supported-path=<enforcePrincipalBasedSupportedPath>
+ Converts service user access control entries to
+ principal-based setup using the given supported path.
+ --enforce-servicemapping-by-principal
+ Converts service user mappings with the form 'service:
+ sub=userID' to 'service:sub=[principalname]'. Note,
+ this may result in group membership no longer being
+ resolved upon service login.
+ --entry-handler-config=<entryHandlerConfigs>
+ Config for entry handlers that support it (classname:
+ <config-string>
+ --remove-install-hooks
+ Removes both internal and external hooks from processed
+ packages
+ --seed-feature=<seedFeature>
+ A url pointing to a feature that can be assumed to be
+ around when the conversion result will be used
+ --system-user-rel-path=<systemUserRelPath>
+ Relative path for system user as configured with Apache
+ Jackrabbit Oak
-a, --artifacts-output-directory=<artifactsOutputDirectory>
The output directory where the artifacts will be
deployed.
@@ -498,6 +544,9 @@ Apache Sling Content Package to Sling Feature converter
The order to start detected bundles.
-D, --define=<String=String>
Define a system property
+ -e, --exports-to-region=<exportsToRegion>
+ Packages exported by bundles in the content packages are
+ exported in the named region
-f, --filtering-patterns=<filteringPatterns>
Regex based pattern(s) to reject content-package archive
entries.
@@ -518,15 +567,16 @@ Apache Sling Content Package to Sling Feature converter
The API Regions assigned to the generated features
-s, --strict-validation Flag to mark the content-package input file being strict
validated.
+ -u, --unreferenced-artifacts-output-directory=<unreferencedArtifactsOutputDirectory
+ >
+ The output directory where unreferenced artifacts will
+ be deployed.
-v, --version Display version information.
-X, --verbose Produce execution debug output.
-Z, --fail-on-mixed-packages
Fail the conversion if the resulting attached
- content-package is MIXED type.
- --enforce-principal-based-supported-path=<path>
- Converts service user access control entries to principal-based
- setup using the given supported path.
-Copyright(c) 2019 The Apache Software Foundation.
+ content-package is MIXED type
+Copyright(c) 2019-2021 The Apache Software Foundation.
```
to see all the available options; a sample execution could look like:
@@ -551,7 +601,7 @@ then execute the command
```bash
> ./bin/cp2fm @argfile
-````
+```
## Failures and Restrictions
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java b/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java
index 0a277b1..49cb21e 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverter.java
@@ -85,6 +85,8 @@ public class ContentPackage2FeatureModelConverter extends BaseVaultPackageScanne
private ArtifactsDeployer artifactsDeployer;
+ private ArtifactsDeployer unreferencedArtifactsDeployer;
+
private VaultPackageAssembler mainPackageAssembler;
private final RecollectorVaultPackageScanner recollectorVaultPackageScanner;
@@ -93,7 +95,18 @@ public class ContentPackage2FeatureModelConverter extends BaseVaultPackageScanne
private boolean failOnMixedPackages = false;
- private boolean dropContent = false;
+ public enum PackagePolicy {
+ /** References the content package in the feature model and deploys via the {@link ContentPackage2FeatureModelConverter#artifactsDeployer} */
+ REFERENCE,
+ /** Drops the content package completely (i.e. neither reference it in the feature model nor deploy anywhere)
+ * @deprecated
+ */
+ DROP,
+ /** Deploys the content package via the {@link ContentPackage2FeatureModelConverter#unreferencedArtifactsDeployer} */
+ PUT_IN_DEDICATED_FOLDER;
+ }
+
+ private PackagePolicy contentTypePackagePolicy = PackagePolicy.REFERENCE;
private boolean removeInstallHooks = false;
@@ -144,6 +157,11 @@ public class ContentPackage2FeatureModelConverter extends BaseVaultPackageScanne
return this;
}
+ public @NotNull ContentPackage2FeatureModelConverter setUnreferencedArtifactsDeployer(@Nullable ArtifactsDeployer unreferencedArtifactsDeployer) {
+ this.unreferencedArtifactsDeployer = unreferencedArtifactsDeployer;
+ return this;
+ }
+
public @Nullable AclManager getAclManager() {
return aclManager;
}
@@ -162,8 +180,8 @@ public class ContentPackage2FeatureModelConverter extends BaseVaultPackageScanne
return this;
}
- public @NotNull ContentPackage2FeatureModelConverter setDropContent(boolean dropContent) {
- this.dropContent = dropContent;
+ public @NotNull ContentPackage2FeatureModelConverter setContentTypePackagePolicy(PackagePolicy contentTypePackagePolicy) {
+ this.contentTypePackagePolicy = contentTypePackagePolicy;
return this;
}
@@ -370,15 +388,33 @@ public class ContentPackage2FeatureModelConverter extends BaseVaultPackageScanne
+ " is of MIXED type");
}
- // don't deploy & add content-packages of type content to featuremodel if dropContent is set
- if (PackageType.CONTENT != packageType || !dropContent) {
- // deploy the new content-package to the local mvn bundles dir and attach it to the feature
+
+ // special handling for converted packages of type content
+ if (PackageType.CONTENT == packageType) {
+ switch (contentTypePackagePolicy) {
+ case DROP:
+ mutableContentsIds.put(originalPackageId, getDependencies(vaultPackage));
+ logger.info("Dropping package of PackageType.CONTENT {} (content-package id: {})",
+ mvnPackageId.getArtifactId(), originalPackageId);
+ break;
+ case PUT_IN_DEDICATED_FOLDER:
+ mutableContentsIds.put(originalPackageId, getDependencies(vaultPackage));
+ // deploy the new content-package to the unreferenced artifacts deployer
+ if (unreferencedArtifactsDeployer == null) {
+ throw new IllegalStateException("ContentTypePackagePolicy PUT_IN_DEDICATED_FOLDER requires a valid deployer ");
+ }
+ unreferencedArtifactsDeployer.deploy(new FileArtifactWriter(contentPackageArchive), mvnPackageId);
+ logger.info("Put converted package of PackageType.CONTENT {} (content-package id: {}) in {} (not referenced in feature model)",
+ mvnPackageId.getArtifactId(), originalPackageId, unreferencedArtifactsDeployer.getBaseDirectory());
+ break;
+ case REFERENCE:
+ artifactsDeployer.deploy(new FileArtifactWriter(contentPackageArchive), mvnPackageId);
+ featuresManager.addArtifact(runMode, mvnPackageId);
+ }
+ } else {
+ // deploy the new content-package to the local mvn bundles dir
artifactsDeployer.deploy(new FileArtifactWriter(contentPackageArchive), mvnPackageId);
featuresManager.addArtifact(runMode, mvnPackageId);
- } else {
- mutableContentsIds.put(originalPackageId, getDependencies(vaultPackage));
- logger.info("Dropping package of PackageType.CONTENT {} (content-package id: {})",
- mvnPackageId.getArtifactId(), originalPackageId);
}
}
}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/artifacts/ArtifactsDeployer.java b/src/main/java/org/apache/sling/feature/cpconverter/artifacts/ArtifactsDeployer.java
index c94dfe9..b498945 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/artifacts/ArtifactsDeployer.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/artifacts/ArtifactsDeployer.java
@@ -24,7 +24,7 @@ import org.jetbrains.annotations.NotNull;
public interface ArtifactsDeployer {
- @NotNull File getBundlesDirectory();
+ @NotNull File getBaseDirectory();
void deploy(@NotNull ArtifactWriter artifactWriter, @NotNull ArtifactId id) throws IOException;
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/artifacts/DefaultArtifactsDeployer.java b/src/main/java/org/apache/sling/feature/cpconverter/artifacts/LocalMavenRepositoryArtifactsDeployer.java
similarity index 82%
rename from src/main/java/org/apache/sling/feature/cpconverter/artifacts/DefaultArtifactsDeployer.java
rename to src/main/java/org/apache/sling/feature/cpconverter/artifacts/LocalMavenRepositoryArtifactsDeployer.java
index eaec649..3ddd1d9 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/artifacts/DefaultArtifactsDeployer.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/artifacts/LocalMavenRepositoryArtifactsDeployer.java
@@ -28,13 +28,16 @@ import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-public final class DefaultArtifactsDeployer implements ArtifactsDeployer {
+/**
+ * Stores the deployed artifacts in a <a href="https://cwiki.apache.org/confluence/display/MAVENOLD/Repository+Layout+-+Final">local Maven repository layout</a>.
+ */
+public final class LocalMavenRepositoryArtifactsDeployer implements ArtifactsDeployer {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final File artifactsDirectory;
- public DefaultArtifactsDeployer(@NotNull File outputDirectory) {
+ public LocalMavenRepositoryArtifactsDeployer(@NotNull File outputDirectory) {
artifactsDirectory = outputDirectory;
if (!artifactsDirectory.exists()) {
artifactsDirectory.mkdirs();
@@ -42,7 +45,7 @@ public final class DefaultArtifactsDeployer implements ArtifactsDeployer {
}
@Override
- public @NotNull File getBundlesDirectory() {
+ public @NotNull File getBaseDirectory() {
return artifactsDirectory;
}
@@ -65,18 +68,8 @@ public final class DefaultArtifactsDeployer implements ArtifactsDeployer {
// deploy the main artifact
- StringBuilder nameBuilder = new StringBuilder()
- .append(id.getArtifactId())
- .append('-')
- .append(id.getVersion());
-
- if (id.getClassifier() != null) {
- nameBuilder.append('-').append(id.getClassifier());
- }
-
- nameBuilder.append('.').append(id.getType());
- File targetFile = new File(targetDir, nameBuilder.toString());
+ File targetFile = new File(targetDir, id.toMvnName());
logger.info("Writing data to {}...", targetFile);
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/artifacts/SimpleFolderArtifactsDeployer.java b/src/main/java/org/apache/sling/feature/cpconverter/artifacts/SimpleFolderArtifactsDeployer.java
new file mode 100644
index 0000000..4afb626
--- /dev/null
+++ b/src/main/java/org/apache/sling/feature/cpconverter/artifacts/SimpleFolderArtifactsDeployer.java
@@ -0,0 +1,61 @@
+/*
+ * 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.cpconverter.artifacts;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+import org.apache.sling.feature.ArtifactId;
+import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Stores the deployed artifacts as files in a flat folder structure.
+ * All deployed artifact ids must be unique among all group ids to prevent overwriting files.
+ */
+public class SimpleFolderArtifactsDeployer implements ArtifactsDeployer {
+
+ private final File artifactsDirectory;
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
+ public SimpleFolderArtifactsDeployer(@NotNull File outputDirectory) {
+ artifactsDirectory = outputDirectory;
+ if (!artifactsDirectory.exists()) {
+ artifactsDirectory.mkdirs();
+ }
+ }
+
+ @Override
+ public @NotNull File getBaseDirectory() {
+ return artifactsDirectory;
+ }
+
+ @Override
+ public void deploy(@NotNull ArtifactWriter artifactWriter, @NotNull ArtifactId id) throws IOException {
+ File targetFile = new File(artifactsDirectory, id.toMvnName());
+ logger.info("Writing data to {}...", targetFile);
+
+ try (FileOutputStream targetStream = new FileOutputStream(targetFile)) {
+ artifactWriter.write(targetStream);
+ }
+
+ logger.info("Data successfully written to {}.", targetFile);
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java b/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java
index 6fe8ca0..2503076 100644
--- a/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java
+++ b/src/main/java/org/apache/sling/feature/cpconverter/cli/ContentPackage2FeatureModelConverterLauncher.java
@@ -31,7 +31,8 @@ import org.apache.sling.feature.Feature;
import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
import org.apache.sling.feature.cpconverter.accesscontrol.AclManager;
import org.apache.sling.feature.cpconverter.accesscontrol.DefaultAclManager;
-import org.apache.sling.feature.cpconverter.artifacts.DefaultArtifactsDeployer;
+import org.apache.sling.feature.cpconverter.artifacts.LocalMavenRepositoryArtifactsDeployer;
+import org.apache.sling.feature.cpconverter.artifacts.SimpleFolderArtifactsDeployer;
import org.apache.sling.feature.cpconverter.features.DefaultFeaturesManager;
import org.apache.sling.feature.cpconverter.filtering.RegexBasedResourceFilter;
import org.apache.sling.feature.cpconverter.handlers.DefaultEntryHandlersManager;
@@ -43,13 +44,14 @@ import org.slf4j.LoggerFactory;
import picocli.CommandLine;
import picocli.CommandLine.Command;
+import picocli.CommandLine.Help.Visibility;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
@Command(
name = "cp2fm",
description = "Apache Sling Content Package to Sling Feature converter",
- footer = "Copyright(c) 2019 The Apache Software Foundation."
+ footer = "Copyright(c) 2019-2021 The Apache Software Foundation."
)
public final class ContentPackage2FeatureModelConverterLauncher implements Runnable {
@@ -125,6 +127,12 @@ public final class ContentPackage2FeatureModelConverterLauncher implements Runna
@Option(names = { "--disable-installer-policy" }, description = "Disables enforcing that OSGi configurations are only allowed below a folder called 'config' and OSGi bundles are only allowed below a folder called 'install'. Instead both are detected below either 'install' or 'config'.", required = false)
private boolean disableInstallerPolicy = false;
+ @Option(names = { "--content-type-package-policy" }, description = "Determines what to do with converted packages of type 'content'. Valid values: ${COMPLETION-CANDIDATES}.", required = false, showDefaultValue = Visibility.ALWAYS)
+ private ContentPackage2FeatureModelConverter.PackagePolicy contentTypePackagePolicy = ContentPackage2FeatureModelConverter.PackagePolicy.DROP;
+
+ @Option(names = { "-u", "--unreferenced-artifacts-output-directory" }, description = "The output directory where unreferenced artifacts will be deployed.", required = true)
+ private File unreferencedArtifactsOutputDirectory;
+
@Override
public void run() {
if (quiet) {
@@ -195,13 +203,18 @@ public final class ContentPackage2FeatureModelConverterLauncher implements Runna
ContentPackage2FeatureModelConverter converter = new ContentPackage2FeatureModelConverter(strictValidation)
.setFeaturesManager(featuresManager)
- .setBundlesDeployer(new DefaultArtifactsDeployer(artifactsOutputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(artifactsOutputDirectory))
.setEntryHandlersManager(new DefaultEntryHandlersManager(entryHandlerConfigsMap, !disableInstallerPolicy))
.setAclManager(aclManager)
.setEmitter(DefaultPackagesEventsEmitter.open(featureModelsOutputDirectory))
.setFailOnMixedPackages(failOnMixedPackages)
- .setDropContent(true);
-
+ .setContentTypePackagePolicy(contentTypePackagePolicy);
+
+ if (unreferencedArtifactsOutputDirectory != null) {
+ converter.setUnreferencedArtifactsDeployer(new SimpleFolderArtifactsDeployer(unreferencedArtifactsOutputDirectory));
+ } else if (contentTypePackagePolicy == ContentPackage2FeatureModelConverter.PackagePolicy.PUT_IN_DEDICATED_FOLDER) {
+ throw new IllegalStateException("Argument '--content-type-package-policy PUT_IN_DEDICATED_FOLDER' requires argument '--unreferenced-artifacts-output-directory' as well!");
+ }
try {
if (filteringPatterns != null && filteringPatterns.length > 0) {
RegexBasedResourceFilter filter = new RegexBasedResourceFilter();
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverterTest.java b/src/test/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverterTest.java
index 5cc4f2d..2fb623e 100644
--- a/src/test/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverterTest.java
+++ b/src/test/java/org/apache/sling/feature/cpconverter/ContentPackage2FeatureModelConverterTest.java
@@ -55,8 +55,10 @@ import org.apache.sling.feature.Configuration;
import org.apache.sling.feature.Extension;
import org.apache.sling.feature.ExtensionType;
import org.apache.sling.feature.Feature;
+import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter.PackagePolicy;
import org.apache.sling.feature.cpconverter.accesscontrol.DefaultAclManager;
-import org.apache.sling.feature.cpconverter.artifacts.DefaultArtifactsDeployer;
+import org.apache.sling.feature.cpconverter.artifacts.LocalMavenRepositoryArtifactsDeployer;
+import org.apache.sling.feature.cpconverter.artifacts.SimpleFolderArtifactsDeployer;
import org.apache.sling.feature.cpconverter.features.DefaultFeaturesManager;
import org.apache.sling.feature.cpconverter.filtering.RegexBasedResourceFilter;
import org.apache.sling.feature.cpconverter.handlers.DefaultEntryHandlersManager;
@@ -141,7 +143,7 @@ public class ContentPackage2FeatureModelConverterTest {
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
@@ -212,7 +214,7 @@ public class ContentPackage2FeatureModelConverterTest {
}
@Test
- public void convertContentPackageDropContent() throws Exception {
+ public void convertContentPackageDropContentTypePackagePolicy() throws Exception {
URL packageUrl = getClass().getResource("test-content-package.zip");
File packageFile = FileUtils.toFile(packageUrl);
@@ -221,9 +223,9 @@ public class ContentPackage2FeatureModelConverterTest {
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
- .setDropContent(true)
+ .setContentTypePackagePolicy(PackagePolicy.DROP)
.convert(packageFile);
verifyFeatureFile(outputDirectory,
@@ -282,6 +284,89 @@ public class ContentPackage2FeatureModelConverterTest {
}
@Test
+ public void convertContentPackagePutInDedicatedFolderContentTypePackagePolicy() throws Exception {
+ URL packageUrl = getClass().getResource("test-content-package.zip");
+ File packageFile = FileUtils.toFile(packageUrl);
+
+ File outputDirectory = new File(System.getProperty("java.io.tmpdir"), getClass().getName() + '_' + System.currentTimeMillis());
+ File outputDirectoryUnreferencedArtifacts = new File(System.getProperty("java.io.tmpdir"), getClass().getName() + "_unreferenced_" + System.currentTimeMillis());
+
+ try {
+
+ converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
+ .setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
+ .setContentTypePackagePolicy(PackagePolicy.PUT_IN_DEDICATED_FOLDER)
+ .setUnreferencedArtifactsDeployer(new SimpleFolderArtifactsDeployer(outputDirectoryUnreferencedArtifacts))
+ .convert(packageFile);
+
+ verifyFeatureFile(outputDirectory,
+ "asd.retail.all.json",
+ "asd.sample:asd.retail.all:slingosgifeature:0.0.1",
+ Arrays.asList("org.apache.felix:org.apache.felix.framework:6.0.1"),
+ Arrays.asList("org.apache.sling.commons.log.LogManager.factory.config~asd-retail"),
+ Arrays.asList("asd.sample:asd.retail.apps:zip:cp2fm-converted:0.0.1",
+ "asd:Asd.Retail.config:zip:cp2fm-converted:0.0.1"));
+ verifyFeatureFile(outputDirectory,
+ "asd.retail.all-author.json",
+ "asd.sample:asd.retail.all:slingosgifeature:author:0.0.1",
+ Arrays.asList("org.apache.sling:org.apache.sling.api:2.20.0"),
+ Collections.emptyList(),
+ Collections.emptyList());
+ verifyFeatureFile(outputDirectory,
+ "asd.retail.all-publish.json",
+ "asd.sample:asd.retail.all:slingosgifeature:publish:0.0.1",
+ Arrays.asList("org.apache.sling:org.apache.sling.models.api:1.3.8"),
+ Arrays.asList("org.apache.sling.serviceusermapping.impl.ServiceUserMapperImpl.amended~asd-retail"),
+ Collections.emptyList());
+
+ // verify the runmode.mapper integrity
+ File runmodeMapperFile = new File(outputDirectory, "runmode.mapping");
+ assertTrue(runmodeMapperFile.exists());
+ assertTrue(runmodeMapperFile.isFile());
+ Properties runModes = new Properties();
+ try (FileInputStream input = new FileInputStream(runmodeMapperFile)) {
+ runModes.load(input);
+ }
+ assertFalse(runModes.isEmpty());
+ assertTrue(runModes.containsKey("(default)"));
+ assertEquals("asd.retail.all.json", runModes.getProperty("(default)"));
+ assertEquals("asd.retail.all-author.json", runModes.getProperty("author"));
+ assertEquals("asd.retail.all-publish.json", runModes.getProperty("publish"));
+
+ verifyContentPackage(new File(outputDirectory, "asd/Asd.Retail.config/0.0.1/Asd.Retail.config-0.0.1-cp2fm-converted.zip"),
+ "META-INF/vault/settings.xml",
+ "META-INF/vault/properties.xml",
+ "META-INF/vault/config.xml",
+ "META-INF/vault/filter.xml",
+ "jcr_root/apps/.content.xml");
+ verifyContentPackage(new File(outputDirectoryUnreferencedArtifacts, "Asd.Retail.ui.content-0.0.1-cp2fm-converted.zip"),
+ "META-INF/vault/settings.xml",
+ "META-INF/vault/properties.xml",
+ "META-INF/vault/config.xml",
+ "META-INF/vault/filter.xml",
+ "META-INF/vault/filter-plugin-generated.xml",
+ "jcr_root/content/asd/.content.xml",
+ "jcr_root/content/asd/resources.xml");
+ verifyContentPackage(new File(outputDirectory, "asd/sample/asd.retail.apps/0.0.1/asd.retail.apps-0.0.1-cp2fm-converted.zip"),
+ "META-INF/vault/settings.xml",
+ "META-INF/vault/properties.xml",
+ "META-INF/vault/config.xml",
+ "META-INF/vault/filter.xml",
+ "META-INF/vault/filter-plugin-generated.xml");
+ verifyContentPackage(new File(outputDirectoryUnreferencedArtifacts, "asd.retail.all-0.0.1-cp2fm-converted.zip"),
+ "META-INF/vault/settings.xml",
+ "META-INF/vault/properties.xml",
+ "META-INF/vault/config.xml",
+ "META-INF/vault/filter.xml");
+
+ } finally {
+ deleteDirTree(outputDirectory);
+ deleteDirTree(outputDirectoryUnreferencedArtifacts);
+ }
+ }
+
+ @Test
public void convertContentPackageRemoveInstallHooks() throws Exception {
URL packageUrl = getClass().getResource("test-with-install-hooks.zip");
File packageFile = FileUtils.toFile(packageUrl);
@@ -290,7 +375,7 @@ public class ContentPackage2FeatureModelConverterTest {
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.setRemoveInstallHooks(true)
.convert(packageFile);
@@ -318,7 +403,7 @@ public class ContentPackage2FeatureModelConverterTest {
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
@@ -347,7 +432,7 @@ public class ContentPackage2FeatureModelConverterTest {
DefaultFeaturesManager fm = new DefaultFeaturesManager(true, 5, outDir, null, null, null, new DefaultAclManager());
fm.setAPIRegions(Arrays.asList("global", "foo.bar"));
converter.setFeaturesManager(fm)
- .setBundlesDeployer(new DefaultArtifactsDeployer(outDir))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outDir))
.setEmitter(DefaultPackagesEventsEmitter.open(outDir))
.convert(cpFile);
@@ -510,7 +595,7 @@ public class ContentPackage2FeatureModelConverterTest {
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
} finally {
@@ -532,7 +617,7 @@ public class ContentPackage2FeatureModelConverterTest {
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
@@ -563,7 +648,7 @@ public class ContentPackage2FeatureModelConverterTest {
URL packageUrl = getClass().getResource("test-content-package.zip");
File packageFile = FileUtils.toFile(packageUrl);
- converter.setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ converter.setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setFeaturesManager(new DefaultFeaturesManager(DefaultFeaturesManager.ConfigurationHandling.STRICT, 5, outputDirectory, null, null, null, new DefaultAclManager()))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
@@ -584,7 +669,7 @@ public class ContentPackage2FeatureModelConverterTest {
URL packageUrl = getClass().getResource("test-content-package.zip");
File packageFile = FileUtils.toFile(packageUrl);
- converter.setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ converter.setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setFeaturesManager(new DefaultFeaturesManager(false, 5, outputDirectory, null, null, null, new DefaultAclManager()))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
@@ -608,7 +693,7 @@ public class ContentPackage2FeatureModelConverterTest {
URL packageUrl = getClass().getResource("test-content-package.zip");
File packageFile = FileUtils.toFile(packageUrl);
- converter.setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ converter.setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setFeaturesManager(new DefaultFeaturesManager(false, 5, outputDirectory, null, null, null, new DefaultAclManager()))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
@@ -633,7 +718,7 @@ public class ContentPackage2FeatureModelConverterTest {
File outDir = Files.createTempDirectory(getClass().getSimpleName()).toFile();
try {
- converter.setBundlesDeployer(new DefaultArtifactsDeployer(outDir))
+ converter.setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outDir))
.setFeaturesManager(new DefaultFeaturesManager(false, 5, outDir, null, null, null, new DefaultAclManager())
.setAPIRegions(Arrays.asList("a.b.c")))
.setEmitter(DefaultPackagesEventsEmitter.open(outDir))
@@ -676,7 +761,7 @@ public class ContentPackage2FeatureModelConverterTest {
String overrideId = "${project.groupId}:${project.artifactId}:slingosgifeature:asd.test.all-1.0.0:${project.version}";
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, overrideId, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(packageFile);
@@ -749,7 +834,7 @@ public class ContentPackage2FeatureModelConverterTest {
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(contentPackages[0]);
@@ -794,8 +879,8 @@ public class ContentPackage2FeatureModelConverterTest {
File outputDirectory = new File(System.getProperty("java.io.tmpdir"), getClass().getName() + '_' + System.currentTimeMillis());
try {
converter.setFeaturesManager(new DefaultFeaturesManager(true, 5, outputDirectory, null, null, null, new DefaultAclManager()))
- .setDropContent(true)
- .setBundlesDeployer(new DefaultArtifactsDeployer(outputDirectory))
+ .setContentTypePackagePolicy(PackagePolicy.DROP)
+ .setBundlesDeployer(new LocalMavenRepositoryArtifactsDeployer(outputDirectory))
.setEmitter(DefaultPackagesEventsEmitter.open(outputDirectory))
.convert(contentPackages);
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/artifacts/DefaultBundlesDeployerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/artifacts/DefaultBundlesDeployerTest.java
index a7505be..0fba49c 100644
--- a/src/test/java/org/apache/sling/feature/cpconverter/artifacts/DefaultBundlesDeployerTest.java
+++ b/src/test/java/org/apache/sling/feature/cpconverter/artifacts/DefaultBundlesDeployerTest.java
@@ -39,7 +39,7 @@ public class DefaultBundlesDeployerTest {
@Before
public void setUp() {
outputDirectory = new File(System.getProperty("java.io.tmpdir"), getClass().getName() + '_' + System.currentTimeMillis());
- artifactDeployer = new DefaultArtifactsDeployer(outputDirectory);
+ artifactDeployer = new LocalMavenRepositoryArtifactsDeployer(outputDirectory);
}
@After
@@ -57,7 +57,7 @@ public class DefaultBundlesDeployerTest {
@Test
public void verifyBundlesDirectory() {
- File bundlesDirectory = artifactDeployer.getBundlesDirectory();
+ File bundlesDirectory = artifactDeployer.getBaseDirectory();
assertNotNull(bundlesDirectory);
assertTrue(bundlesDirectory.exists());
assertTrue(bundlesDirectory.isDirectory());
diff --git a/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java b/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java
index 28d1e86..1174fe5 100644
--- a/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java
+++ b/src/test/java/org/apache/sling/feature/cpconverter/handlers/BundleEntryHandlerTest.java
@@ -40,7 +40,7 @@ import org.apache.jackrabbit.vault.fs.io.Archive.Entry;
import org.apache.sling.feature.ArtifactId;
import org.apache.sling.feature.Feature;
import org.apache.sling.feature.cpconverter.ContentPackage2FeatureModelConverter;
-import org.apache.sling.feature.cpconverter.artifacts.DefaultArtifactsDeployer;
+import org.apache.sling.feature.cpconverter.artifacts.LocalMavenRepositoryArtifactsDeployer;
import org.apache.sling.feature.cpconverter.features.DefaultFeaturesManager;
import org.apache.sling.feature.cpconverter.features.FeaturesManager;
import org.junit.Test;
@@ -115,7 +115,7 @@ public final class BundleEntryHandlerTest {
File testDirectory = new File(System.getProperty("java.io.tmpdir"), getClass().getName() + '_' + System.currentTimeMillis());
try {
- when(converter.getArtifactsDeployer()).thenReturn(new DefaultArtifactsDeployer(testDirectory));
+ when(converter.getArtifactsDeployer()).thenReturn(new LocalMavenRepositoryArtifactsDeployer(testDirectory));
when(converter.getFeaturesManager()).thenReturn(featuresManager);
bundleEntryHandler.handle(bundleLocation, archive, entry, converter);