Skip to content

Commit b5e4cca

Browse files
committed
conga-aem-maven-plugin: Fix problem with container packages contained in "all" package that contain nested sub packages - add sub packages in the dependency chain instead of the container package which get's eliminated in the cp2fm process.
1 parent 0920a9a commit b5e4cca

8 files changed

Lines changed: 167 additions & 35 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.14.6" date="not released">
27+
<action type="fix" dev="sseifert">
28+
conga-aem-maven-plugin: Fix problem with container packages contained in "all" package that contain nested sub packages - add sub packages in the dependency chain instead of the container package which get's eliminated in the cp2fm process.
29+
</action>
30+
</release>
31+
2632
<release version="1.14.4" date="2021-06-08">
2733
<action type="update" dev="sseifert">
2834
Update to latest AEM Content Package Builder.

tooling/conga-aem-maven-plugin/src/main/java/io/wcm/devops/conga/plugins/aem/maven/allpackage/AllPackageBuilder.java

Lines changed: 95 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import java.io.FileOutputStream;
3030
import java.io.IOException;
3131
import java.io.InputStream;
32+
import java.nio.file.Files;
3233
import java.util.ArrayList;
3334
import java.util.Arrays;
3435
import java.util.Enumeration;
@@ -48,17 +49,22 @@
4849
import org.apache.commons.lang3.StringUtils;
4950
import org.apache.jackrabbit.vault.packaging.Dependency;
5051
import org.apache.jackrabbit.vault.packaging.DependencyUtil;
52+
import org.apache.jackrabbit.vault.packaging.PackageType;
5153
import org.apache.jackrabbit.vault.packaging.VersionRange;
5254
import org.apache.maven.plugin.logging.Log;
5355
import org.apache.maven.plugin.logging.SystemStreamLog;
56+
import org.jetbrains.annotations.NotNull;
5457

58+
import com.google.common.collect.ImmutableMap;
5559
import com.google.common.collect.ImmutableSet;
5660

5761
import io.wcm.devops.conga.plugins.aem.maven.AutoDependenciesMode;
5862
import io.wcm.devops.conga.plugins.aem.maven.model.ContentPackageFile;
63+
import io.wcm.devops.conga.plugins.aem.postprocessor.ContentPackagePropertiesPostProcessor;
5964
import io.wcm.tooling.commons.contentpackagebuilder.ContentPackage;
6065
import io.wcm.tooling.commons.contentpackagebuilder.ContentPackageBuilder;
6166
import io.wcm.tooling.commons.contentpackagebuilder.PackageFilter;
67+
import io.wcm.tooling.commons.packmgr.util.ContentPackageProperties;
6268

6369
/**
6470
* Builds "all" package based on given set of content packages.
@@ -73,7 +79,10 @@ public final class AllPackageBuilder {
7379
private Log log;
7480

7581
private static final String RUNMODE_DEFAULT = "$default$";
76-
private static final Set<String> ALLOWED_PACKAGE_TYPES = ImmutableSet.of("application", "container", "content");
82+
private static final Set<String> ALLOWED_PACKAGE_TYPES = ImmutableSet.of(
83+
PackageType.APPLICATION.name().toLowerCase(),
84+
PackageType.CONTAINER.name().toLowerCase(),
85+
PackageType.CONTENT.name().toLowerCase());
7786

7887
private final List<ContentPackageFileSet> fileSets = new ArrayList<>();
7988

@@ -376,9 +385,10 @@ private void addFileWithDependency(ContentPackage contentPackage, String path,
376385
* @param props Properties
377386
* @param dependencyFile Dependency package
378387
* @param allPackagesFromFileSets Set with all packages from all file sets as dependency instances
388+
* @throws IOException I/O exception
379389
*/
380390
private static void updateDependencies(Properties props, ContentPackageFile dependencyFile, String environmentRunMode,
381-
Set<Dependency> allPackagesFromFileSets) {
391+
Set<Dependency> allPackagesFromFileSets) throws IOException {
382392
String[] existingDepsStrings = StringUtils.split(props.getProperty(NAME_DEPENDENCIES), ",");
383393
Dependency[] existingDeps = null;
384394
if (existingDepsStrings != null && existingDepsStrings.length > 0) {
@@ -388,28 +398,99 @@ private static void updateDependencies(Properties props, ContentPackageFile depe
388398
existingDeps = removeReferencesToManagedPackages(existingDeps, allPackagesFromFileSets);
389399
}
390400

391-
Dependency[] deps;
392-
if (dependencyFile != null) {
393-
String runModeSuffix = buildRunModeSuffix(dependencyFile, environmentRunMode);
394-
Dependency newDependency = new Dependency(dependencyFile.getGroup(),
395-
dependencyFile.getName() + runModeSuffix,
396-
VersionRange.fromString(dependencyFile.getVersion()));
397-
if (existingDeps != null) {
398-
deps = DependencyUtil.add(existingDeps, newDependency);
401+
Dependency[] deps = null;
402+
if (dependencyFile == null) {
403+
deps = existingDeps;
404+
}
405+
else {
406+
// if package is container package: check for embedded sub packages
407+
List<ContentPackageFile> containerSubPackageFiles = null;
408+
if (isContainerPackage(dependencyFile)) {
409+
containerSubPackageFiles = getContainerSubPackageFiles(dependencyFile);
399410
}
411+
// if sub packages are present: add dependencies to sub packages instead of the container package
412+
// nested sub packages are referenced without any runmode suffix
413+
if (containerSubPackageFiles != null) {
414+
for (ContentPackageFile subPackageFileItem : containerSubPackageFiles) {
415+
Dependency newDependency = new Dependency(subPackageFileItem.getGroup(),
416+
subPackageFileItem.getName(),
417+
VersionRange.fromString(subPackageFileItem.getVersion()));
418+
deps = addDependency(existingDeps, newDependency);
419+
}
420+
}
421+
// otherwise add dependency to package itself
400422
else {
401-
deps = new Dependency[] { newDependency };
423+
String runModeSuffix = buildRunModeSuffix(dependencyFile, environmentRunMode);
424+
Dependency newDependency = new Dependency(dependencyFile.getGroup(),
425+
dependencyFile.getName() + runModeSuffix,
426+
VersionRange.fromString(dependencyFile.getVersion()));
427+
deps = addDependency(existingDeps, newDependency);
402428
}
403429
}
404-
else {
405-
deps = existingDeps;
406-
}
407430

408431
if (deps != null) {
409432
props.put(NAME_DEPENDENCIES, Dependency.toString(deps));
410433
}
411434
}
412435

436+
private static Dependency[] addDependency(Dependency[] existingDeps, Dependency newDependency) {
437+
if (existingDeps != null) {
438+
return DependencyUtil.add(existingDeps, newDependency);
439+
}
440+
else {
441+
return new Dependency[] { newDependency };
442+
}
443+
}
444+
445+
/**
446+
* If the content package is a container package that contains sub packages (that are sub packages in sub packages),
447+
* the cp2fm conversion eliminates the nested package container "in the middle", leading to unresolveable
448+
* dependencies. So, if the dependency content package contains sub packages, we add dependencies
449+
* to the contained sub packages instead.
450+
* @param dependencyFile Dependency package
451+
* @return List of dependency packages or null if none exist
452+
* @throws IOException I/O exception
453+
*/
454+
private static List<ContentPackageFile> getContainerSubPackageFiles(@NotNull ContentPackageFile dependencyFile) throws IOException {
455+
// introspect container package file - check for sub packages
456+
List<ContentPackageFile> dependencyFiles = new ArrayList<>();
457+
try (ZipFile zipFileIn = new ZipFile(dependencyFile.getFile())) {
458+
Enumeration<? extends ZipEntry> zipInEntries = zipFileIn.entries();
459+
while (zipInEntries.hasMoreElements()) {
460+
ZipEntry zipInEntry = zipInEntries.nextElement();
461+
if (StringUtils.equals("zip", FilenameUtils.getExtension(zipInEntry.getName()))) {
462+
File tempFile = File.createTempFile(zipInEntry.getName() + "-subpackage-", ".zip");
463+
try {
464+
try (FileOutputStream fos = new FileOutputStream(tempFile);
465+
InputStream zis = zipFileIn.getInputStream(zipInEntry)) {
466+
IOUtils.copy(zis, fos);
467+
}
468+
Map<String, Object> props = ContentPackageProperties.get(tempFile);
469+
ContentPackageFile subPackageFile = new ContentPackageFile(tempFile,
470+
ImmutableMap.of(ContentPackagePropertiesPostProcessor.MODEL_OPTIONS_PROPERTY, props),
471+
ImmutableMap.of("variants", dependencyFile.getVariants()));
472+
if (StringUtils.isNoneBlank(subPackageFile.getGroup(), subPackageFile.getName(), subPackageFile.getVersion())) {
473+
dependencyFiles.add(subPackageFile);
474+
}
475+
}
476+
finally {
477+
Files.delete(tempFile.toPath());
478+
}
479+
}
480+
}
481+
}
482+
if (dependencyFiles.isEmpty()) {
483+
return null;
484+
}
485+
else {
486+
return dependencyFiles;
487+
}
488+
}
489+
490+
private static boolean isContainerPackage(@NotNull ContentPackageFile packageFile) {
491+
return StringUtils.equals(packageFile.getPackageType(), PackageType.CONTAINER.name().toLowerCase());
492+
}
493+
413494
private static void addSuffixToPackageName(Properties props, ContentPackageFile pkg, String environmentRunMode) {
414495
String runModeSuffix = buildRunModeSuffix(pkg, environmentRunMode);
415496
String packageName = props.getProperty(NAME_NAME) + runModeSuffix;

tooling/conga-aem-maven-plugin/src/main/java/io/wcm/devops/conga/plugins/aem/maven/model/ContentPackageFile.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,13 @@ public final class ContentPackageFile {
5252

5353
private final List<String> variants;
5454

55+
/**
56+
* @param file Content package file
57+
* @param fileData File data
58+
* @param roleData Role data
59+
*/
5560
@SuppressWarnings("unchecked")
56-
ContentPackageFile(File file, Map<String, Object> fileData, Map<String, Object> roleData) {
61+
public ContentPackageFile(File file, Map<String, Object> fileData, Map<String, Object> roleData) {
5762
this.file = file;
5863

5964
this.install = (Boolean)fileData.get("install");

tooling/conga-aem-maven-plugin/src/test/java/io/wcm/devops/conga/plugins/aem/maven/allpackage/AllPackageBuilderTest.java

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ void testBuild(Set<String> cloudManagerTarget, List<String> runmodeSuffixes) thr
9494

9595
for (String runmodeSuffix : runmodeSuffixes) {
9696
File applicationInstallDir = new File(applicationDir, "install" + runmodeSuffix);
97-
assertFiles(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
97+
assertFiles(applicationInstallDir, "accesscontroltool-oakindex-package" + runmodeSuffix + "-3.0.0.zip",
98+
"acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
9899
"aem-cms-system-config" + runmodeSuffix + ".zip");
99100
assertNameDependencies(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
100101
"acs-aem-commons-ui.apps" + runmodeSuffix,
@@ -127,7 +128,8 @@ void testBuild(Set<String> cloudManagerTarget, List<String> runmodeSuffixes) thr
127128

128129
for (String runmodeSuffix : runmodeSuffixes) {
129130
File containerInstallDir = new File(containerDir, "install" + runmodeSuffix);
130-
assertFiles(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
131+
assertFiles(containerInstallDir, "accesscontroltool-package" + runmodeSuffix + "-3.0.0.zip",
132+
"wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
131133
"wcm-io-samples-complete" + runmodeSuffix + "-1.3.1-SNAPSHOT.zip");
132134
assertNameDependencies(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
133135
"wcm-io-samples-aem-cms-config" + runmodeSuffix);
@@ -157,8 +159,12 @@ void testBuild_IMMUTABLE_MUTABLE_COMBINED(Set<String> cloudManagerTarget, List<S
157159

158160
for (String runmodeSuffix : runmodeSuffixes) {
159161
File applicationInstallDir = new File(applicationDir, "install" + runmodeSuffix);
160-
assertFiles(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
162+
assertFiles(applicationInstallDir, "accesscontroltool-oakindex-package" + runmodeSuffix + "-3.0.0.zip",
163+
"acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
161164
"aem-cms-system-config" + runmodeSuffix + ".zip");
165+
assertNameDependencies(applicationInstallDir, "accesscontroltool-oakindex-package" + runmodeSuffix + "-3.0.0.zip",
166+
"accesscontroltool-oakindex-package" + runmodeSuffix,
167+
"Netcentric:accesscontroltool-apps-package:3.0.0");
162168
assertNameDependencies(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
163169
"acs-aem-commons-ui.apps" + runmodeSuffix,
164170
"day/cq60/product:cq-content:6.3.64");
@@ -182,7 +188,7 @@ void testBuild_IMMUTABLE_MUTABLE_COMBINED(Set<String> cloudManagerTarget, List<S
182188
"adobe/consulting:acs-aem-commons-ui.apps" + runmodeSuffix + ":4.10.0");
183189
assertNameDependencies(contentInstallDir, "aem-cms-author-replicationagents" + runmodeSuffix + ".zip",
184190
"aem-cms-author-replicationagents" + runmodeSuffix,
185-
"adobe/consulting:acs-aem-commons-ui.content" + runmodeSuffix + ":4.10.0");
191+
"Netcentric:accesscontroltool-oakindex-package" + runmodeSuffix + ":3.0.0");
186192
assertNameDependencies(contentInstallDir, "wcm-io-samples-sample-content" + runmodeSuffix + "-1.3.1-SNAPSHOT.zip",
187193
"wcm-io-samples-sample-content" + runmodeSuffix,
188194
"wcm-io-samples:wcm-io-samples-complete" + runmodeSuffix + ":1.3.1-SNAPSHOT");
@@ -193,8 +199,12 @@ void testBuild_IMMUTABLE_MUTABLE_COMBINED(Set<String> cloudManagerTarget, List<S
193199

194200
for (String runmodeSuffix : runmodeSuffixes) {
195201
File containerInstallDir = new File(containerDir, "install" + runmodeSuffix);
196-
assertFiles(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
202+
assertFiles(containerInstallDir, "accesscontroltool-package" + runmodeSuffix + "-3.0.0.zip",
203+
"wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
197204
"wcm-io-samples-complete" + runmodeSuffix + "-1.3.1-SNAPSHOT.zip");
205+
assertNameDependencies(containerInstallDir, "accesscontroltool-package" + runmodeSuffix + "-3.0.0.zip",
206+
"accesscontroltool-package" + runmodeSuffix,
207+
"adobe/consulting:acs-aem-commons-ui.content" + runmodeSuffix + ":4.10.0");
198208
assertNameDependencies(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
199209
"wcm-io-samples-aem-cms-config" + runmodeSuffix,
200210
"wcm-io-samples:aem-cms-system-config" + runmodeSuffix + ":1.3.1-SNAPSHOT");
@@ -225,16 +235,20 @@ void testBuild_IMMUTABLE_MUTABLE_SEPARATE(Set<String> cloudManagerTarget, List<S
225235

226236
for (String runmodeSuffix : runmodeSuffixes) {
227237
File applicationInstallDir = new File(applicationDir, "install" + runmodeSuffix);
228-
assertFiles(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
238+
assertFiles(applicationInstallDir, "accesscontroltool-oakindex-package" + runmodeSuffix + "-3.0.0.zip",
239+
"acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
229240
"aem-cms-system-config" + runmodeSuffix + ".zip");
241+
assertNameDependencies(applicationInstallDir, "accesscontroltool-oakindex-package" + runmodeSuffix + "-3.0.0.zip",
242+
"accesscontroltool-oakindex-package" + runmodeSuffix,
243+
"Netcentric:accesscontroltool-apps-package:3.0.0");
230244
assertNameDependencies(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
231245
"acs-aem-commons-ui.apps" + runmodeSuffix,
232246
"day/cq60/product:cq-content:6.3.64");
233247
assertNameDependencies(applicationInstallDir, "aem-cms-system-config" + runmodeSuffix + ".zip",
234248
"aem-cms-system-config" + runmodeSuffix,
235249
"day/cq60/product:cq-ui-wcm-editor-content:1.1.224",
236250
"adobe/cq/product:cq-remotedam-client-ui-components:1.1.6",
237-
"adobe/consulting:acs-aem-commons-ui.apps" + runmodeSuffix + ":4.10.0");
251+
"Netcentric:accesscontroltool-oakindex-package" + runmodeSuffix + ":3.0.0");
238252
}
239253

240254
File contentDir = new File(appsDir, "content");
@@ -260,8 +274,12 @@ void testBuild_IMMUTABLE_MUTABLE_SEPARATE(Set<String> cloudManagerTarget, List<S
260274

261275
for (String runmodeSuffix : runmodeSuffixes) {
262276
File containerInstallDir = new File(containerDir, "install" + runmodeSuffix);
263-
assertFiles(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
277+
assertFiles(containerInstallDir, "accesscontroltool-package" + runmodeSuffix + "-3.0.0.zip",
278+
"wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
264279
"wcm-io-samples-complete" + runmodeSuffix + "-1.3.1-SNAPSHOT.zip");
280+
assertNameDependencies(containerInstallDir, "accesscontroltool-package" + runmodeSuffix + "-3.0.0.zip",
281+
"accesscontroltool-package" + runmodeSuffix,
282+
"adobe/consulting:acs-aem-commons-ui.apps" + runmodeSuffix + ":4.10.0");
265283
assertNameDependencies(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
266284
"wcm-io-samples-aem-cms-config" + runmodeSuffix,
267285
"wcm-io-samples:aem-cms-system-config" + runmodeSuffix + ":1.3.1-SNAPSHOT");
@@ -292,16 +310,20 @@ void testBuild_IMMUTABLE_ONLY(Set<String> cloudManagerTarget, List<String> runmo
292310

293311
for (String runmodeSuffix : runmodeSuffixes) {
294312
File applicationInstallDir = new File(applicationDir, "install" + runmodeSuffix);
295-
assertFiles(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
313+
assertFiles(applicationInstallDir, "accesscontroltool-oakindex-package" + runmodeSuffix + "-3.0.0.zip",
314+
"acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
296315
"aem-cms-system-config" + runmodeSuffix + ".zip");
316+
assertNameDependencies(applicationInstallDir, "accesscontroltool-oakindex-package" + runmodeSuffix + "-3.0.0.zip",
317+
"accesscontroltool-oakindex-package" + runmodeSuffix,
318+
"Netcentric:accesscontroltool-apps-package:3.0.0");
297319
assertNameDependencies(applicationInstallDir, "acs-aem-commons-ui.apps" + runmodeSuffix + "-4.10.0.zip",
298320
"acs-aem-commons-ui.apps" + runmodeSuffix,
299321
"day/cq60/product:cq-content:6.3.64");
300322
assertNameDependencies(applicationInstallDir, "aem-cms-system-config" + runmodeSuffix + ".zip",
301323
"aem-cms-system-config" + runmodeSuffix,
302324
"day/cq60/product:cq-ui-wcm-editor-content:1.1.224",
303325
"adobe/cq/product:cq-remotedam-client-ui-components:1.1.6",
304-
"adobe/consulting:acs-aem-commons-ui.apps" + runmodeSuffix + ":4.10.0");
326+
"Netcentric:accesscontroltool-oakindex-package" + runmodeSuffix + ":3.0.0");
305327
}
306328

307329
File contentDir = new File(appsDir, "content");
@@ -325,8 +347,12 @@ void testBuild_IMMUTABLE_ONLY(Set<String> cloudManagerTarget, List<String> runmo
325347

326348
for (String runmodeSuffix : runmodeSuffixes) {
327349
File containerInstallDir = new File(containerDir, "install" + runmodeSuffix);
328-
assertFiles(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
350+
assertFiles(containerInstallDir, "accesscontroltool-package" + runmodeSuffix + "-3.0.0.zip",
351+
"wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
329352
"wcm-io-samples-complete" + runmodeSuffix + "-1.3.1-SNAPSHOT.zip");
353+
assertNameDependencies(containerInstallDir, "accesscontroltool-package" + runmodeSuffix + "-3.0.0.zip",
354+
"accesscontroltool-package" + runmodeSuffix,
355+
"adobe/consulting:acs-aem-commons-ui.apps" + runmodeSuffix + ":4.10.0");
330356
assertNameDependencies(containerInstallDir, "wcm-io-samples-aem-cms-config" + runmodeSuffix + ".zip",
331357
"wcm-io-samples-aem-cms-config" + runmodeSuffix,
332358
"wcm-io-samples:aem-cms-system-config" + runmodeSuffix + ":1.3.1-SNAPSHOT");

0 commit comments

Comments
 (0)