Skip to content

Commit bfbde8b

Browse files
committed
[jgitflow-maven-plugin] merging 'release/1.13.0' into 'master'
2 parents cdb9a0d + 47258d5 commit bfbde8b

14 files changed

Lines changed: 162 additions & 39 deletions

File tree

changes.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@
2323
xsi:schemaLocation="http://maven.apache.org/changes/1.0.0 https://maven.apache.org/plugins/maven-changes-plugin/xsd/changes-1.0.0.xsd">
2424
<body>
2525

26+
<release version="1.13.0" date="2020-07-10">
27+
<action type="add" dev="sseifert">
28+
aem-contentpackage post processor: Add "fileMatch" property to include a list of binary files matching the pattern into a content package.
29+
</action>
30+
</release>
31+
2632
<release version="1.12.0" date="2020-06-28">
2733
<action type="add" dev="sseifert">
2834
Add httpdCloudManagerConditional and withAllCloudManagerConditional handlebars helper to build envrionment-conditional configuration for AEM cloud service..

conga-aem-plugin/pom.xml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131

3232
<groupId>io.wcm.devops.conga.plugins</groupId>
3333
<artifactId>io.wcm.devops.conga.plugins.aem</artifactId>
34-
<version>1.12.0</version>
34+
<version>1.13.0</version>
3535
<packaging>jar</packaging>
3636

3737
<name>CONGA AEM Plugin</name>
@@ -101,13 +101,13 @@
101101
<dependency>
102102
<groupId>io.wcm.tooling.commons</groupId>
103103
<artifactId>io.wcm.tooling.commons.content-package-builder</artifactId>
104-
<version>1.5.2</version>
104+
<version>1.5.4</version>
105105
<scope>compile</scope>
106106
</dependency>
107107
<dependency>
108108
<groupId>io.wcm.tooling.commons</groupId>
109109
<artifactId>io.wcm.tooling.commons.crx-packmgr-helper</artifactId>
110-
<version>1.7.0</version>
110+
<version>1.7.2</version>
111111
<scope>compile</scope>
112112
</dependency>
113113

@@ -177,13 +177,7 @@
177177
<dependency>
178178
<groupId>org.xmlunit</groupId>
179179
<artifactId>xmlunit-core</artifactId>
180-
<version>2.6.3</version>
181-
<scope>test</scope>
182-
</dependency>
183-
<dependency>
184-
<groupId>org.xmlunit</groupId>
185-
<artifactId>xmlunit-legacy</artifactId>
186-
<version>2.6.3</version>
180+
<version>2.7.0</version>
187181
<scope>test</scope>
188182
</dependency>
189183
<dependency>

conga-aem-plugin/src/main/java/io/wcm/devops/conga/plugins/aem/postprocessor/ContentPackagePostProcessor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public List<FileContext> apply(FileContext fileContext, PostProcessorContext con
9797
contentPackage.addContent(rootPath, content);
9898

9999
// add additional binary files
100-
for (ContentPackageBinaryFile binaryFile : ContentPackageUtil.getFiles(options)) {
100+
for (ContentPackageBinaryFile binaryFile : ContentPackageUtil.getFiles(options, fileContext.getTargetDir())) {
101101
String path = binaryFile.getPath();
102102
try (InputStream is = binaryFile.getInputStream(context.getUrlFileManager(), fileContext.getTargetDir())) {
103103
contentPackage.addFile(path, is);

conga-aem-plugin/src/main/java/io/wcm/devops/conga/plugins/aem/util/ContentPackageUtil.java

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,18 @@
3434
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_THUMBNAIL_IMAGE;
3535
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_VERSION;
3636

37+
import java.io.File;
3738
import java.io.IOException;
3839
import java.io.InputStream;
40+
import java.nio.file.Files;
41+
import java.nio.file.Path;
42+
import java.nio.file.Paths;
3943
import java.util.ArrayList;
4044
import java.util.List;
4145
import java.util.Map;
46+
import java.util.Objects;
47+
import java.util.regex.Matcher;
48+
import java.util.regex.Pattern;
4249
import java.util.stream.Collectors;
4350

4451
import org.apache.commons.lang3.BooleanUtils;
@@ -348,25 +355,70 @@ private static Map<String, Object> getOptionalPropMap(Map<String, Object> option
348355
/**
349356
* Get binary files to be added to package.
350357
* @param options Options
358+
* @param targetDir Target directory
351359
* @return File list
352360
* @throws IOException I/O exception
353361
*/
354-
public static List<ContentPackageBinaryFile> getFiles(Map<String, Object> options) throws IOException {
362+
public static List<ContentPackageBinaryFile> getFiles(Map<String, Object> options, File targetDir) throws IOException {
355363
List<ContentPackageBinaryFile> files = new ArrayList<>();
356364

357365
List<Map<String, Object>> fileDefinitions = getOptionalPropMapList(options, PROPERTY_PACKAGE_FILES);
358366
if (fileDefinitions != null) {
359367
for (Map<String, Object> fileDefinition : fileDefinitions) {
360368
String file = getOptionalProp(fileDefinition, "file");
369+
String fileMatch = getOptionalProp(fileDefinition, "fileMatch");
361370
String dir = getOptionalProp(fileDefinition, "dir");
362371
String url = getOptionalProp(fileDefinition, "url");
363372
String path = getMandatoryProp(fileDefinition, "path");
364373
boolean delete = BooleanUtils.toBoolean(getOptionalProp(fileDefinition, "delete"));
365-
files.add(new ContentPackageBinaryFile(file, dir, url, path, delete));
374+
375+
if (fileMatch != null && file == null && url == null) {
376+
// add multiple (local) files matching with given regex
377+
files.addAll(getMatchingFiles(targetDir, fileMatch, dir, path, delete));
378+
}
379+
else {
380+
// add single file
381+
files.add(new ContentPackageBinaryFile(file, dir, url, path, delete));
382+
}
366383
}
367384
}
368385

369386
return files;
370387
}
371388

389+
private static List<ContentPackageBinaryFile> getMatchingFiles(File targetDir, String fileMatch,
390+
String dir, String path, boolean delete) throws IOException {
391+
File fileTargetDir = targetDir;
392+
if (StringUtils.isNotEmpty(dir)) {
393+
fileTargetDir = new File(targetDir, dir);
394+
}
395+
Path fileTargetPath = Paths.get(fileTargetDir.toURI());
396+
String targetPathPrefix = normalizedAbsolutePath(fileTargetPath) + "/";
397+
Pattern pattern = Pattern.compile(fileMatch);
398+
399+
// collect all files below the target dir
400+
return Files.walk(Paths.get(fileTargetDir.toURI()))
401+
.filter(Files::isRegularFile)
402+
// strip off the target dir paths, keep only the relative path/file name
403+
.map(ContentPackageUtil::normalizedAbsolutePath)
404+
.map(file -> StringUtils.removeStart(file, targetPathPrefix))
405+
// check if file matches with the regex, apply matching input groups to path
406+
.map(file -> {
407+
Matcher matcher = pattern.matcher(file);
408+
if (matcher.matches()) {
409+
String adaptedPath = matcher.replaceAll(path);
410+
return new ContentPackageBinaryFile(file, dir, null, adaptedPath, delete);
411+
}
412+
else {
413+
return null;
414+
}
415+
})
416+
.filter(Objects::nonNull)
417+
.collect(Collectors.toList());
418+
}
419+
420+
private static String normalizedAbsolutePath(Path path) {
421+
return StringUtils.replace(path.toAbsolutePath().toString(), "\\", "/");
422+
}
423+
372424
}

conga-aem-plugin/src/test/java/io/wcm/devops/conga/plugins/aem/postprocessor/ContentPackageOsgiConfigPostProcessorTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@
2424
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_NAME;
2525
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_ROOT_PATH;
2626
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_VERSION;
27+
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageTestUtil.assertXpathEvaluatesTo;
2728
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageTestUtil.getDataFromZip;
2829
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageTestUtil.getXmlFromZip;
29-
import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo;
3030
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
3131
import static org.junit.jupiter.api.Assertions.assertEquals;
3232
import static org.junit.jupiter.api.Assertions.assertFalse;

conga-aem-plugin/src/test/java/io/wcm/devops/conga/plugins/aem/postprocessor/ContentPackagePostProcessorTest.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@
2828
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_PROPERTIES;
2929
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_ROOT_PATH;
3030
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageOptions.PROPERTY_PACKAGE_THUMBNAIL_IMAGE;
31+
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageTestUtil.assertXpathEvaluatesTo;
3132
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageTestUtil.getDataFromZip;
3233
import static io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackageTestUtil.getXmlFromZip;
33-
import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo;
3434
import static org.junit.jupiter.api.Assertions.assertFalse;
3535
import static org.junit.jupiter.api.Assertions.assertNotNull;
3636
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -88,7 +88,8 @@ public void testPostProcess() throws Exception {
8888
"my.custom.prop2", 123));
8989
options.put(PROPERTY_PACKAGE_FILES, ImmutableList.of(
9090
ImmutableMap.<String, Object>of("url", "classpath:/package/thumbnail.png", "path", "/content/image.png"),
91-
ImmutableMap.<String, Object>of("file", "README.txt", "dir", "readme", "path", "/content/README.txt", "delete", true)));
91+
ImmutableMap.<String, Object>of("file", "README.txt", "dir", "readme", "path", "/content/README.txt", "delete", true),
92+
ImmutableMap.<String, Object>of("fileMatch", "file_(.*).txt", "dir", "files", "path", "/content/files/$1.txt", "delete", true)));
9293

9394
// prepare JSON file
9495
File target = new File("target/" + ContentPackagePostProcessor.NAME + "-test");
@@ -98,12 +99,21 @@ public void testPostProcess() throws Exception {
9899
File contentPackageFile = new File(target, "test.json");
99100
FileUtils.copyFile(new File(getClass().getResource("/json/content.json").toURI()), contentPackageFile);
100101

101-
// pepare additionaly binary file
102+
// prepare additional binary files
102103
File readmeFolder = new File(target, "readme");
103104
readmeFolder.mkdir();
104105
File readmeFile = new File(readmeFolder, "README.txt");
105106
FileUtils.write(readmeFile, "readme", StandardCharsets.UTF_8);
106107

108+
File filesFolder = new File(target, "files");
109+
filesFolder.mkdir();
110+
File file_1 = new File(filesFolder, "file_1.txt");
111+
FileUtils.write(file_1, "file_1", StandardCharsets.UTF_8);
112+
File file_2 = new File(filesFolder, "file_2.txt");
113+
FileUtils.write(file_2, "file_2", StandardCharsets.UTF_8);
114+
File file_3 = new File(filesFolder, "file_3.txt");
115+
FileUtils.write(file_3, "file_3", StandardCharsets.UTF_8);
116+
107117
// post-process
108118
FileContext fileContext = new FileContext()
109119
.file(contentPackageFile)
@@ -153,6 +163,18 @@ public void testPostProcess() throws Exception {
153163
byte[] readmeText = getDataFromZip(zipFile, "jcr_root/content/README.txt");
154164
assertNotNull(readmeText);
155165
assertFalse(readmeFile.exists());
166+
167+
byte[] file_1Text = getDataFromZip(zipFile, "jcr_root/content/files/1.txt");
168+
assertNotNull(file_1Text);
169+
assertFalse(file_1.exists());
170+
171+
byte[] file_2Text = getDataFromZip(zipFile, "jcr_root/content/files/2.txt");
172+
assertNotNull(file_2Text);
173+
assertFalse(file_2.exists());
174+
175+
byte[] file_3Text = getDataFromZip(zipFile, "jcr_root/content/files/3.txt");
176+
assertNotNull(file_3Text);
177+
assertFalse(file_3.exists());
156178
}
157179

158180
}

conga-aem-plugin/src/test/java/io/wcm/devops/conga/plugins/aem/postprocessor/ContentPackageTestUtil.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,26 +19,30 @@
1919
*/
2020
package io.wcm.devops.conga.plugins.aem.postprocessor;
2121

22+
import static org.junit.jupiter.api.Assertions.assertEquals;
23+
2224
import java.io.ByteArrayInputStream;
2325
import java.io.File;
2426
import java.io.FileNotFoundException;
2527

2628
import javax.xml.parsers.DocumentBuilder;
2729
import javax.xml.parsers.DocumentBuilderFactory;
2830

29-
import org.custommonkey.xmlunit.SimpleNamespaceContext;
30-
import org.custommonkey.xmlunit.XMLUnit;
3131
import org.w3c.dom.Document;
32+
import org.w3c.dom.Node;
33+
import org.xmlunit.xpath.JAXPXPathEngine;
34+
import org.xmlunit.xpath.XPathEngine;
3235
import org.zeroturnaround.zip.ZipUtil;
3336

3437
import io.wcm.tooling.commons.contentpackagebuilder.XmlNamespaces;
3538

3639
public final class ContentPackageTestUtil {
3740

3841
private static final DocumentBuilderFactory DOCUMENT_BUILDER_FACTORY = DocumentBuilderFactory.newInstance();
42+
private static final XPathEngine XPATH_ENGINE = new JAXPXPathEngine();
3943
static {
4044
DOCUMENT_BUILDER_FACTORY.setNamespaceAware(true);
41-
XMLUnit.setXpathNamespaceContext(new SimpleNamespaceContext(XmlNamespaces.DEFAULT_NAMESPACES));
45+
XPATH_ENGINE.setNamespaceContext(XmlNamespaces.DEFAULT_NAMESPACES);
4246
}
4347

4448
private ContentPackageTestUtil() {
@@ -59,4 +63,12 @@ public static Document getXmlFromZip(File file, String path) throws Exception {
5963
return documentBuilder.parse(new ByteArrayInputStream(data));
6064
}
6165

66+
public static void assertXpathEvaluatesTo(String expected, String xpath, Node node) throws Exception {
67+
assertEquals(expected, XPATH_ENGINE.evaluate(xpath, node));
68+
}
69+
70+
public static void assertXpathEvaluatesTo(String expected, String xpath, Document doc) throws Exception {
71+
assertXpathEvaluatesTo(expected, xpath, doc.getDocumentElement());
72+
}
73+
6274
}

example/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<dependency>
6666
<groupId>io.wcm.devops.conga.plugins</groupId>
6767
<artifactId>io.wcm.devops.conga.plugins.aem</artifactId>
68-
<version>1.11.5-SNAPSHOT</version>
68+
<version>1.12.1-SNAPSHOT</version>
6969
</dependency>
7070

7171
</dependencies>

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
<groupId>io.wcm.devops.conga.plugins</groupId>
3131
<artifactId>io.wcm.devops.conga.plugins.aem.root</artifactId>
32-
<version>1.12.0</version>
32+
<version>1.13.0</version>
3333
<packaging>pom</packaging>
3434

3535
<name>CONGA AEM Plugin</name>

src/site/markdown/extensions.md

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ Both post processor plugins support a set of options that allow further configur
3939
| `contentPackage.filters` | Contains list with filter definitions, optionally with include/exclude rules. If not defined a simple filter rule is derived from the `contentPackage.rootPath` property.
4040
| `contentPackage.acHandling` | How to apply ACLs that are contained in the content package. Possible values: `ignore` (default), `overwrite`, `merge`, `merge_preserve`, `clear`.
4141
| `contentPackage.thumbnailImage` | URL to thumbnail PNG image to be used for the content package. URL file plugin prefixes can be used (e.g. `classpath:`).
42-
| `contentPackage.files` | List of additional binary files to be included in content package. For each file you have to specify a `path` property (target path), and for the source an `url` property for an external file, or a `file` and `dir` property for a file that was generated by CONGA. If the file should be deleted after the inclusion you can additionally specify `delete: true`.
42+
| `contentPackage.files` | List of additional binary files to be included in content package. For each file you have to specify a `path` property (target path), and for the source an `url` property for an external file, or a `file` and `dir` property for a file that was generated by CONGA. Instead of `file` your can also use `fileMath` to include multiple files matching this pattern. If the file should be deleted after the inclusion you can additionally specify `delete: true`.
4343
| `contentPackage.properties` | Defines map with additional custom properties for package metadata.
4444
| `contentPackage.packageType` | Defines the [packageType][jackrabbit-filevault-packagetype] for the content package. Uses for [FileVault validation][jackrabbit-filevault-validation] of the package.
4545
| `contentPackage.requiresRoot` | Package requires root.
@@ -72,6 +72,37 @@ Example for defining package properties with a set of filters:
7272
pattern: /etc/map/http/AppMeasurementBridge
7373
```
7474

75+
Example for additionally adding binary files to the content package:
76+
77+
```
78+
# Define a AEM content package with some JCR content
79+
- file: my-package.json
80+
dir: packages
81+
template: my-package.json.hbs
82+
# Post-processors apply further actions after generation the file
83+
postProcessors:
84+
- aem-contentpackage
85+
postProcessorOptions:
86+
contentPackage:
87+
name: my-package
88+
rootPath: /content/files
89+
files:
90+
# Add a static file from the class paths (or other URLs)
91+
- url: classpath:/my-resources/file1.txt
92+
path: /content/files/file1.txt
93+
# Add a file that was generated by CONGA (delete after inclusion in package)
94+
- file: generated-file.txt
95+
dir: generated-files
96+
path: /content/files/generated-file.txt
97+
delete: true
98+
# Add a set file that were generated by CONGA (delete after inclusion in package)
99+
- fileMatch: file_(.*)\.txt
100+
dir: generated-files
101+
path: /content/files/$1.txt
102+
delete: true
103+
```
104+
105+
75106

76107
### Validating AEM Content Packages
77108

0 commit comments

Comments
 (0)