Skip to content

Commit 3edd2ba

Browse files
authored
Merge pull request #524 from santiagozky/limit-install-hook-files
Allow to limit which files the install hook tries to install ...
2 parents bb98209 + 9ac9c98 commit 3edd2ba

File tree

7 files changed

+177
-44
lines changed

7 files changed

+177
-44
lines changed

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/ConfigFilesRetriever.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package biz.netcentric.cq.tools.actool.configreader;
22

3+
import java.util.Collection;
34
import java.util.Map;
45

56
import javax.jcr.Session;
@@ -24,8 +25,9 @@ public interface ConfigFilesRetriever {
2425
/** Returns yaml configurations from a package. This will only return configuration entries which apply to the current run mode
2526
*
2627
* @param archive the Vault Package
28+
* @param configFilePatterns collection of regular expression to limit which configuration files are used.
2729
* @return map of yaml configurations by their path location
2830
* @throws Exception if things go wrong */
29-
Map<String, String> getConfigFileContentFromPackage(Archive archive) throws Exception;
31+
Map<String, String> getConfigFileContentFromPackage(Archive archive, Collection<String> configFilePatterns) throws Exception;
3032

3133
}

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/ConfigFilesRetrieverImpl.java

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import java.io.InputStream;
44
import java.io.StringWriter;
55
import java.util.Collection;
6+
import java.util.Collections;
67
import java.util.Iterator;
78
import java.util.LinkedList;
89
import java.util.List;
@@ -43,41 +44,53 @@ public Map<String, String> getConfigFileContentFromNode(String rootPath, Session
4344
if (rootNode == null) {
4445
throw new IllegalArgumentException("No configuration path configured! please check the configuration of AcService!");
4546
}
46-
Map<String, String> configurations = getConfigurations(new NodeInJcr(rootNode));
47+
Map<String, String> configurations = getConfigurations(new NodeInJcr(rootNode), Collections.<String> emptyList());
4748
return configurations;
4849
}
4950

5051
@Override
51-
public Map<String, String> getConfigFileContentFromPackage(Archive archive) throws Exception {
52+
public Map<String, String> getConfigFileContentFromPackage(Archive archive, Collection<String> configFilePatterns) throws Exception {
5253
Entry rootEntry = archive.getJcrRoot();
5354
if (rootEntry == null) {
5455
throw new IllegalStateException("Invalid package: It does not contain a JCR root element");
5556
}
56-
Map<String, String> configurations = getConfigurations(new EntryInPackage(archive, "", rootEntry));
57+
Map<String, String> configurations = getConfigurations(new EntryInPackage(archive, "", rootEntry), configFilePatterns);
5758
return configurations;
5859
}
5960

60-
private Map<String, String> getConfigurations(PackageEntryOrNode configFileOrDir) throws Exception {
61+
private Map<String, String> getConfigurations(PackageEntryOrNode configFileOrDir, Collection<String> configFilePatterns)
62+
throws Exception {
6163
Map<String, String> configs = new TreeMap<String, String>();
6264

6365
for (PackageEntryOrNode entry : configFileOrDir.getChildren()) {
6466
if (entry.isDirectory()) {
65-
Map<String, String> resultsFromDir = getConfigurations(entry);
67+
Map<String, String> resultsFromDir = getConfigurations(entry, configFilePatterns);
6668
configs.putAll(resultsFromDir);
6769
continue;
6870
}
69-
70-
if (isRelevantConfiguration(entry.getName(), configFileOrDir.getName(), slingSettingsService)) {
71+
if (isRelevantConfiguration(entry, configFileOrDir.getName(), slingSettingsService, configFilePatterns)) {
7172
LOG.debug("Found relevant YAML file {}", entry.getName());
7273
configs.put(entry.getPath(), entry.getContentAsString());
7374
}
74-
7575
}
7676
return configs;
7777
}
7878

79-
static boolean isRelevantConfiguration(final String entryName, final String parentName, ExtendedSlingSettingsService slingSettings) {
80-
if (!entryName.endsWith(".yaml") && !entryName.equals("config") /* name 'config' without .yaml allowed for backwards compatibility */) {
79+
static boolean isRelevantConfiguration(final PackageEntryOrNode entry, final String parentName,
80+
ExtendedSlingSettingsService slingSettings, Collection<String> configFilePatterns) throws Exception {
81+
boolean matchPattern = configFilePatterns.isEmpty();
82+
for (String pathPattern : configFilePatterns) {
83+
if (entry.getPath().matches(pathPattern)) {
84+
matchPattern = true;
85+
}
86+
}
87+
if (!matchPattern) {
88+
LOG.info("Skipped file '{}' because it didn't match any path pattern", entry.getPath());
89+
return false;
90+
}
91+
String entryName = entry.getName();
92+
// name 'config' without .yaml allowed for backwards compatibility
93+
if (!entryName.endsWith(".yaml") && !entryName.equals("config")) {
8194
return false;
8295
}
8396

@@ -105,12 +118,12 @@ static String extractRunModeSpecFromName(final String name) {
105118
if (positionDot == -1) {
106119
return "";
107120
}
108-
121+
109122
return name.substring(positionDot + 1);
110123
}
111124

112125
/** Internal representation of either a package entry or a node to be able to use one algorithm for both InstallHook/JMX scenarios. */
113-
private static interface PackageEntryOrNode {
126+
static interface PackageEntryOrNode {
114127
String getName() throws Exception;
115128

116129
String getPath() throws Exception;

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public void execute(InstallContext context) throws PackageException {
3838
switch (context.getPhase()) {
3939
case PREPARE:
4040
if (!shouldInstallInPhaseInstalled(context.getPackage())) {
41-
41+
4242
install(context);
4343
}
4444
break;
@@ -56,10 +56,11 @@ public void execute(InstallContext context) throws PackageException {
5656
private boolean shouldInstallInPhaseInstalled(PackageProperties properties) {
5757
return Boolean.parseBoolean(properties.getProperty(PROPERTY_ACTOOL_INSTALL_AT_INSTALLED_PHASE));
5858
}
59+
5960
private boolean forceInstallHookInCloud(PackageProperties properties) {
6061
return Boolean.parseBoolean(properties.getProperty(PROPERTY_ACTOOL_FORCE_INSTALLHOOK_IN_CLOUD));
6162
}
62-
63+
6364
private void install(InstallContext context) throws PackageException {
6465
final ProgressTrackerListener listener = context.getOptions().getListener();
6566
/*
@@ -72,9 +73,10 @@ private void install(InstallContext context) throws PackageException {
7273
return;
7374
}
7475
alreadyRan = true;
75-
76-
if(RuntimeHelper.isCloudReadyInstance() && !forceInstallHookInCloud(context.getPackage())) {
77-
log("InstallHook is skipped by default in cloud (use package property 'actool.forceInstallHookInCloud = true' to force run)", listener);
76+
77+
if (RuntimeHelper.isCloudReadyInstance() && !forceInstallHookInCloud(context.getPackage())) {
78+
log("InstallHook is skipped by default in cloud (use package property 'actool.forceInstallHookInCloud = true' to force run)",
79+
listener);
7880
return;
7981
}
8082

@@ -95,7 +97,7 @@ private void install(InstallContext context) throws PackageException {
9597
PersistableInstallationLogger history;
9698
try {
9799
history = acService.installYamlFilesFromPackage(context
98-
.getPackage().getArchive(), context.getSession(), context.getOptions().getListener());
100+
.getPackage(), context.getSession(), context.getOptions().getListener());
99101

100102
} catch (Exception e) {
101103
// needed as root cause of PackageException is not reliably logged in AEM 6.2
@@ -106,7 +108,7 @@ private void install(InstallContext context) throws PackageException {
106108

107109
if (!history.isSuccess()) {
108110
throw new PackageException("AC Tool installation failed with "
109-
+history.getErrors().size()+ " errors. Check log for detailed error message(s)!");
111+
+ history.getErrors().size() + " errors. Check log for detailed error message(s)!");
110112
} else {
111113
log("Installed ACLs successfully through AcToolInstallHook!", listener);
112114
}

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@
1111
import javax.jcr.Session;
1212

1313
import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
14-
import org.apache.jackrabbit.vault.fs.io.Archive;
14+
import org.apache.jackrabbit.vault.packaging.VaultPackage;
1515

1616
import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger;
1717

1818
public interface AcToolInstallHookService {
1919

20-
public PersistableInstallationLogger installYamlFilesFromPackage(Archive archive, Session session, ProgressTrackerListener progressTrackerListener)
20+
public PersistableInstallationLogger installYamlFilesFromPackage(VaultPackage archive, Session session,
21+
ProgressTrackerListener progressTrackerListener)
2122
throws Exception;
2223

2324
}

accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookServiceImpl.java

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,17 @@
88
*/
99
package biz.netcentric.cq.tools.actool.installhook.impl;
1010

11+
import java.util.ArrayList;
12+
import java.util.List;
1113
import java.util.Map;
1214
import java.util.Properties;
15+
import java.util.Set;
1316

1417
import javax.jcr.Session;
1518

1619
import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
1720
import org.apache.jackrabbit.vault.fs.io.Archive;
21+
import org.apache.jackrabbit.vault.packaging.VaultPackage;
1822
import org.osgi.service.component.annotations.Component;
1923
import org.osgi.service.component.annotations.Reference;
2024
import org.osgi.service.component.annotations.ReferencePolicyOption;
@@ -27,17 +31,33 @@
2731
@Component
2832
public class AcToolInstallHookServiceImpl implements AcToolInstallHookService {
2933

34+
public static final String ACL_HOOK_PATHS = "actool.installhook.configFilesPattern(.*)";
35+
private static final String JCR_ROOT_PREFIX="/jcr_root";
3036
@Reference(policyOption = ReferencePolicyOption.GREEDY)
3137
private AcInstallationServiceInternal acInstallationService;
3238

3339
@Reference(policyOption = ReferencePolicyOption.GREEDY)
3440
private ConfigFilesRetriever configFilesRetriever;
3541

3642
@Override
37-
public PersistableInstallationLogger installYamlFilesFromPackage(Archive archive, Session session, ProgressTrackerListener progressTrackerListener)
43+
public PersistableInstallationLogger installYamlFilesFromPackage(VaultPackage vaultPackage, Session session,
44+
ProgressTrackerListener progressTrackerListener)
3845
throws Exception {
39-
PersistableInstallationLogger history = progressTrackerListener != null ? new ProgressTrackerListenerInstallationLogger(progressTrackerListener) : new PersistableInstallationLogger();
40-
Map<String, String> configs = configFilesRetriever.getConfigFileContentFromPackage(archive);
46+
Archive archive = vaultPackage.getArchive();
47+
Properties packageProperties = vaultPackage.getMetaInf().getProperties();
48+
List<String> configPathPatterns = new ArrayList<>();
49+
Set<Object> propertiesKeys = packageProperties.keySet();
50+
for (Object property : propertiesKeys) {
51+
if (property.toString().matches(ACL_HOOK_PATHS)) {
52+
configPathPatterns.add(JCR_ROOT_PREFIX + packageProperties.getProperty(property.toString()));
53+
54+
}
55+
}
56+
57+
PersistableInstallationLogger history = progressTrackerListener != null
58+
? new ProgressTrackerListenerInstallationLogger(progressTrackerListener)
59+
: new PersistableInstallationLogger();
60+
Map<String, String> configs = configFilesRetriever.getConfigFileContentFromPackage(archive, configPathPatterns);
4161
history.setCrxPackageName(getArchiveName(archive));
4262
String[] restrictedToPaths = null; // never use path restriction for hook usage for now
4363
acInstallationService.installConfigurationFiles(history, configs, restrictedToPaths, session);

accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/ConfigFilesRetrieverImplTest.java

Lines changed: 97 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,18 @@
99
package biz.netcentric.cq.tools.actool.configreader;
1010

1111
import java.util.Arrays;
12+
import java.util.Collection;
13+
import java.util.Collections;
1214
import java.util.HashSet;
15+
import java.util.List;
1316
import java.util.Set;
1417

1518
import org.hamcrest.Matchers;
1619
import org.junit.Assert;
1720
import org.junit.Test;
1821

22+
import com.google.common.collect.ImmutableList;
23+
1924
import biz.netcentric.cq.tools.actool.slingsettings.ExtendedSlingSettingsServiceImpl;
2025

2126
public class ConfigFilesRetrieverImplTest {
@@ -38,39 +43,112 @@ public void testExtractRunModeSpecFromName() {
3843
}
3944

4045
@Test
41-
public void testIsRelevantConfiguration() {
46+
public void testIsRelevantConfiguration() throws Exception {
4247
Set<String> currentRunmodes = new HashSet<String>(
4348
Arrays.asList("samplecontent", "author", "netcentric", "crx3tar", "crx2", "local"));
4449

4550
slingSettings = new ExtendedSlingSettingsServiceImpl(currentRunmodes);
46-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("", "fragments", slingSettings)));
47-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("test", "fragments", slingSettings)));
48-
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments", slingSettings)));
49-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.publish", slingSettings)));
50-
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.author", slingSettings)));
51-
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.samplecontent", slingSettings)));
52-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yam", "fragments.samplecontent", slingSettings)));
53-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.samplecontent.publish",
54-
slingSettings)));
55-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.foo.publish", slingSettings)));
56-
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.samplecontent.local", slingSettings)));
51+
Collection<String> configFilePatterns = Collections.emptyList();
52+
Assert.assertFalse(
53+
(ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry(""), "fragments", slingSettings, configFilePatterns)));
54+
Assert.assertFalse(
55+
(ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test"), "fragments", slingSettings, configFilePatterns)));
56+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments", slingSettings,
57+
configFilePatterns)));
58+
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.publish", slingSettings,
59+
configFilePatterns)));
60+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.author", slingSettings,
61+
configFilePatterns)));
62+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.samplecontent",
63+
slingSettings, configFilePatterns)));
64+
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yam"), "fragments.samplecontent",
65+
slingSettings, configFilePatterns)));
66+
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.samplecontent.publish",
67+
slingSettings, configFilePatterns)));
68+
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.foo.publish",
69+
slingSettings, configFilePatterns)));
70+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.samplecontent.local",
71+
slingSettings, configFilePatterns)));
5772

5873
}
5974

6075
@Test
61-
public void testIsRelevantConfigurationWithOrCombinations() {
76+
public void testIsRelevantConfigurationWithOrCombinations() throws Exception {
6277
Set<String> currentRunmodes = new HashSet<String>(
6378
Arrays.asList("samplecontent", "author", "netcentric", "crx3tar", "crx2", "local"));
6479
slingSettings = new ExtendedSlingSettingsServiceImpl(currentRunmodes);
80+
Collection<String> configFilePatterns = Collections.emptyList();
6581
// testing 'or' combinations with
66-
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.dev,local", slingSettings)));
67-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.int,prod", slingSettings)));
82+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.dev,local",
83+
slingSettings, configFilePatterns)));
84+
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.int,prod",
85+
slingSettings, configFilePatterns)));
6886

6987
// combined 'and' and 'or'
70-
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.author.dev,author.local",
71-
slingSettings)));
72-
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration("test.yaml", "fragments.publish.dev,publish.local",
73-
slingSettings)));
88+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.author.dev,author.local",
89+
slingSettings, configFilePatterns)));
90+
Assert.assertFalse(
91+
(ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("test.yaml"), "fragments.publish.dev,publish.local",
92+
slingSettings, configFilePatterns)));
93+
}
94+
95+
@Test
96+
public void testIsRelevantConfigurationsFiltered() throws Exception {
97+
Set<String> currentRunmodes = new HashSet<String>(
98+
Arrays.asList("author"));
99+
slingSettings = new ExtendedSlingSettingsServiceImpl(currentRunmodes);
100+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("/conf", "file.yaml"), "config.author",
101+
slingSettings, ImmutableList.<String> of())));
102+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("/conf", "file.yaml"), "config.author",
103+
slingSettings, ImmutableList.<String> of("/noMatch", "/conf/.*"))));
104+
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("/conf", "file.yaml"), "config.author",
105+
slingSettings, ImmutableList.<String> of("/conf/test.*.yaml"))));
106+
Assert.assertTrue((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("/conf", "file.yaml"), "config.author",
107+
slingSettings, ImmutableList.<String> of("/conf/.*\\.yaml", "/noMatch"))));
108+
Assert.assertFalse((ConfigFilesRetrieverImpl.isRelevantConfiguration(new StubEntry("/conf", "file.yaml"), "config.author",
109+
slingSettings, ImmutableList.<String> of("/nonconf.*"))));
110+
111+
}
112+
113+
static class StubEntry implements ConfigFilesRetrieverImpl.PackageEntryOrNode {
114+
115+
private final String parentPath;
116+
private final String name;
117+
118+
StubEntry(String name) {
119+
this.name = name;
120+
this.parentPath = "/";
121+
}
122+
123+
StubEntry(String parentPath, String name) {
124+
this.parentPath = parentPath;
125+
this.name = name;
126+
}
127+
128+
@Override
129+
public String getName() throws Exception {
130+
return name;
131+
}
132+
133+
@Override
134+
public String getPath() throws Exception {
135+
return parentPath + "/" + name;
136+
}
137+
138+
@Override
139+
public List<ConfigFilesRetrieverImpl.PackageEntryOrNode> getChildren() throws Exception {
140+
return Collections.emptyList();
141+
}
142+
143+
@Override
144+
public boolean isDirectory() throws Exception {
145+
return false;
146+
}
147+
148+
@Override
149+
public String getContentAsString() throws Exception {
150+
throw new UnsupportedOperationException("not implemented for testing");
151+
}
74152
}
75153

76154
}

0 commit comments

Comments
 (0)