Skip to content

Commit

Permalink
Merge pull request #413 from wttech/fix-if-modified
Browse files Browse the repository at this point in the history
fixed handling of ifModified property
  • Loading branch information
dprzybyl authored Oct 19, 2023
2 parents 1b95451 + 788b048 commit 0d237d5
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
import com.day.cq.commons.jcr.JcrConstants;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import javax.annotation.PostConstruct;
Expand Down Expand Up @@ -260,4 +262,29 @@ public static boolean isScript(Resource resource) {
private static List<String> getArrayProperty(Resource resource, String name) {
return Lists.newArrayList(resource.getValueMap().get(name, new String[]{}));
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj instanceof ScriptModel) {
ScriptModel that = (ScriptModel) obj;
return Objects.equals(path, that.path)
&& Objects.equals(launchEnabled, that.launchEnabled)
&& Objects.equals(launchMode, that.launchMode)
&& Objects.equals(launchEnvironment, that.launchEnvironment)
&& Arrays.equals(launchRunModes, that.launchRunModes)
&& Objects.equals(launchHook, that.launchHook)
&& Objects.equals(launchSchedule, that.launchSchedule)
&& Objects.equals(checksum, that.checksum)
&& Objects.equals(verified, that.verified);
}
return false;
}

@Override
public int hashCode() {
return Objects.hashCode(path);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,19 @@
*/
package com.cognifide.apm.core.utils;

import java.lang.management.ManagementFactory;
import javax.jcr.Node;
import javax.jcr.Session;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.ResourceResolver;

@NoArgsConstructor(access = AccessLevel.PRIVATE)
public final class RuntimeUtils {

private static final String AEM_MUTABLE_CONTENT_INSTANCE = "aem-install-mutable-content";

public static boolean determineCompositeNodeStore(ResourceResolver resolver) {
boolean result;
try {
Expand All @@ -43,4 +47,9 @@ public static boolean determineCompositeNodeStore(ResourceResolver resolver) {
return result;
}

public static boolean isMutableContentInstance(ResourceResolver resolver) {
boolean compositeNodeStore = RuntimeUtils.determineCompositeNodeStore(resolver);
String instanceName = ManagementFactory.getRuntimeMXBean().getName();
return !compositeNodeStore || StringUtils.contains(instanceName, AEM_MUTABLE_CONTENT_INSTANCE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,29 @@
import com.cognifide.apm.core.services.version.VersionService;
import com.cognifide.apm.core.utils.RuntimeUtils;
import com.cognifide.apm.core.utils.sling.SlingHelper;
import java.lang.management.ManagementFactory;
import java.util.Arrays;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.observation.ResourceChange;
import org.apache.sling.api.resource.observation.ResourceChangeListener;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.AttributeDefinition;
import org.osgi.service.metatype.annotations.Designate;
import org.osgi.service.metatype.annotations.ObjectClassDefinition;

@Component(
service = {ApmInstallService.class, Runnable.class},
immediate = true,
property = {
Property.DESCRIPTION + "APM Launches configured scripts",
Expand All @@ -58,8 +64,6 @@
@Designate(ocd = ApmInstallService.Configuration.class, factory = true)
public class ApmInstallService extends AbstractLauncher implements Runnable {

private static final String AEM_MUTABLE_CONTENT_INSTANCE = "aem-install-mutable-content";

@Reference
private ResourceResolverProvider resolverProvider;

Expand All @@ -75,53 +79,106 @@ public class ApmInstallService extends AbstractLauncher implements Runnable {
@Reference
private History history;

private Configuration config;
private List<String> scriptPaths;

private boolean ifModified;

private Set<ServiceRegistration<ResourceChangeListener>> registrations;

@Activate
public void activate(Configuration config) {
this.config = config;
process();
public void activate(Configuration config, BundleContext bundleContext) {
scriptPaths = Arrays.asList(config.scriptPaths());
ifModified = config.ifModified();
processAllScripts();
registerScripts(bundleContext);
}

@Deactivate
public void deactivate() {
registrations.forEach(ServiceRegistration::unregister);
registrations.clear();
}

@Override
public void run() {
process();
processAllScripts();
}

private void process() {
private void processAllScripts() {
SlingHelper.operateTraced(resolverProvider, resolver -> {
boolean compositeNodeStore = RuntimeUtils.determineCompositeNodeStore(resolver);
String instanceName = ManagementFactory.getRuntimeMXBean().getName();
if (!compositeNodeStore || StringUtils.contains(instanceName, AEM_MUTABLE_CONTENT_INSTANCE)) {
processScripts(config, resolver);
if (RuntimeUtils.isMutableContentInstance(resolver)) {
List<Script> scripts = determineScripts(scriptPaths, resolver);
processScripts(scripts, resolver);
}
});
}

private void processScripts(Configuration config, ResourceResolver resolver) throws PersistenceException {
private List<Script> determineScripts(List<String> scriptPaths, ResourceResolver resolver) {
ReferenceFinder referenceFinder = new ReferenceFinder(scriptFinder, resolver);
List<Script> scripts = Arrays.stream(config.scriptPaths())
return scriptPaths.stream()
.map(scriptPath -> scriptFinder.find(scriptPath, resolver))
.filter(Objects::nonNull)
.filter(script -> {
List<Script> subtree = referenceFinder.findReferences(script);
String checksum = versionService.countChecksum(subtree);
ScriptVersion scriptVersion = versionService.getScriptVersion(resolver, script);
HistoryEntry lastLocalRun = history.findScriptHistory(resolver, script).getLastLocalRun();
return !config.ifModified()
return !ifModified
|| !checksum.equals(scriptVersion.getLastChecksum())
|| lastLocalRun == null
|| !checksum.equals(lastLocalRun.getChecksum());
})
.collect(Collectors.toList());
processScripts(scripts, resolver);
}

private void registerScripts(BundleContext bundleContext) {
registrations = new HashSet<>();
SlingHelper.operateTraced(resolverProvider, resolver -> {
if (ifModified && RuntimeUtils.isMutableContentInstance(resolver)) {
scriptPaths.forEach(scriptPath -> registerScript(scriptPath, resolver, bundleContext));
}
});
}

private void registerScript(String scriptPath, ResourceResolver resolver, BundleContext bundleContext) {
Script script = scriptFinder.find(scriptPath, resolver);
ScriptResourceChangeListener service = new ScriptResourceChangeListener(script, scriptPath);
Dictionary<String, Object> dictionary = new Hashtable<>();
dictionary.put(ResourceChangeListener.CHANGES, new String[]{"ADDED", "CHANGED", "REMOVED"});
dictionary.put(ResourceChangeListener.PATHS, scriptPath);
ServiceRegistration<ResourceChangeListener> registration = bundleContext.registerService(ResourceChangeListener.class, service, dictionary);
registrations.add(registration);
}

@Override
protected ScriptManager getScriptManager() {
return scriptManager;
}

private class ScriptResourceChangeListener implements ResourceChangeListener {

private Script script;

private final String scriptPath;

public ScriptResourceChangeListener(Script script, String scriptPath) {
this.script = script;
this.scriptPath = scriptPath;
}

@Override
public void onChange(List<ResourceChange> changes) {
SlingHelper.operateTraced(resolverProvider, resolver -> {
Script newScript = scriptFinder.find(scriptPath, resolver);
if (!Objects.equals(script, newScript)) {
script = newScript;
List<Script> scripts = determineScripts(Collections.singletonList(scriptPath), resolver);
processScripts(scripts, resolver);
}
});
}
}

@ObjectClassDefinition(name = "AEM Permission Management - Install Launcher Configuration")
public @interface Configuration {

Expand Down

0 comments on commit 0d237d5

Please sign in to comment.