Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -253,10 +253,12 @@ tasks:
- sh npmw install
- sh npmw run dev

develop:frontend:format:
develop:frontend:fix:
desc: format frontend code
dir: ui.frontend
cmd: sh npmw run format
cmds:
- sh npmw run format
- sh npmw run lint

release:
desc: Release a new version
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ private synchronized void maybeUpdateVariablesCache(ResourceResolver resolver) {
LOG.info("Variables cache - updating");
try (ExecutionContext context = executor.createContext(
ExecutionId.generate(), ExecutionMode.PARSE, Code.consoleMinimal(), resolver)) {
variablesCache = context.getBindingVariables();
variablesCache = context.getCodeContext().getBindingVariables();
variablesCacheTimestamp = currentTime;
}
LOG.info("Variables cache - updated");
Expand Down
94 changes: 94 additions & 0 deletions core/src/main/java/com/vml/es/aem/acm/core/code/CodeContext.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.vml.es.aem.acm.core.code;

import com.vml.es.aem.acm.core.acl.Acl;
import com.vml.es.aem.acm.core.code.script.ExtensionScript;
import com.vml.es.aem.acm.core.format.Formatter;
import com.vml.es.aem.acm.core.mock.MockContext;
import com.vml.es.aem.acm.core.osgi.OsgiContext;
import com.vml.es.aem.acm.core.replication.Activator;
import com.vml.es.aem.acm.core.repo.Repo;
import com.vml.es.aem.acm.core.script.ScriptRepository;
import com.vml.es.aem.acm.core.script.ScriptType;
import groovy.lang.Binding;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.sling.api.resource.ResourceResolver;
import org.slf4j.LoggerFactory;

public class CodeContext {

private final OsgiContext osgiContext;

private final ResourceResolver resourceResolver;

private final Binding binding;

private final List<ExtensionScript> extensionScripts;

public CodeContext(OsgiContext osgiContext, ResourceResolver resourceResolver) {
this.osgiContext = osgiContext;
this.resourceResolver = resourceResolver;
this.binding = createBinding(osgiContext, resourceResolver);
this.extensionScripts = findExtensionScripts(resourceResolver);
}

private List<ExtensionScript> findExtensionScripts(ResourceResolver resourceResolver) {
return new ScriptRepository(resourceResolver)
.findAll(ScriptType.EXTENSION)
.map(s -> new ExtensionScript(this, s))
.collect(Collectors.toList());
}

public Binding createBinding(OsgiContext osgiContext, ResourceResolver resourceResolver) {
Copy link
Collaborator Author

@krystian-panek-vmltech krystian-panek-vmltech May 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now we have single place to define same binding for all type of scripts (including manual/auto/mocks/extensions etc)

Binding result = new Binding();

result.setVariable("log", LoggerFactory.getLogger(getClass()));
result.setVariable("resourceResolver", resourceResolver);
result.setVariable("osgi", osgiContext);
result.setVariable("repo", new Repo(resourceResolver));
result.setVariable("acl", new Acl(resourceResolver));
result.setVariable("formatter", new Formatter());
result.setVariable("activator", new Activator(resourceResolver, osgiContext.getReplicator()));

return result;
}

public void prepareRun(ExecutionContext executionContext) {
for (ExtensionScript script : extensionScripts) {
script.prepareRun(executionContext);
}
}

public void completeRun(Execution execution) {
for (ExtensionScript script : extensionScripts) {
script.completeRun(execution);
}
}

public void prepareMock(MockContext mockContext) {
for (ExtensionScript script : extensionScripts) {
script.prepareMock(mockContext);
}
}

public Binding getBinding() {
return binding;
}

@SuppressWarnings("unchecked")
public List<Variable> getBindingVariables() {
Map<String, Object> variables = binding.getVariables();
return variables.entrySet().stream()
.map(entry -> new Variable(entry.getKey(), entry.getValue().getClass()))
.collect(Collectors.toList());
}

public ResourceResolver getResourceResolver() {
return resourceResolver;
}

public OsgiContext getOsgiContext() {
return osgiContext;
}
}
43 changes: 25 additions & 18 deletions core/src/main/java/com/vml/es/aem/acm/core/code/Condition.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.vml.es.aem.acm.core.code;

import com.vml.es.aem.acm.core.osgi.InstanceInfo;
import com.vml.es.aem.acm.core.osgi.InstanceType;
import com.vml.es.aem.acm.core.script.ScriptScheduler;
import com.vml.es.aem.acm.core.util.DateUtils;
Expand All @@ -17,7 +18,8 @@ public class Condition {

public Condition(ExecutionContext executionContext) {
this.executionContext = executionContext;
this.executionHistory = new ExecutionHistory(executionContext.getResourceResolver());
this.executionHistory =
new ExecutionHistory(executionContext.getCodeContext().getResourceResolver());
}

public boolean always() {
Expand Down Expand Up @@ -59,15 +61,11 @@ public boolean idleSelf() {
}

public Stream<Execution> queuedExecutions() {
return executionContext.getOsgiContext().getExecutionQueue().findAll().filter(e -> !isSelfExecution(e));
return getExecutionQueue().findAll().filter(e -> !isSelfExecution(e));
}

public Stream<Execution> queuedSelfExecutions() {
return executionContext
.getOsgiContext()
.getExecutionQueue()
.findAll()
.filter(e -> !isSelfExecution(e) && isSameExecutable(e));
return getExecutionQueue().findAll().filter(e -> !isSelfExecution(e) && isSameExecutable(e));
}

public boolean isSelfExecution(Execution e) {
Expand All @@ -79,6 +77,10 @@ public boolean isSameExecutable(Execution e) {
e.getExecutable().getId(), executionContext.getExecutable().getId());
}

private ExecutionQueue getExecutionQueue() {
return executionContext.getCodeContext().getOsgiContext().getExecutionQueue();
}

// Time period-based

public boolean everyMinute() {
Expand Down Expand Up @@ -319,13 +321,14 @@ public boolean isDate(ZonedDateTime zonedDateTime) {
}

public boolean isDate(LocalDateTime localDateTime) {
long intervalMillis = executionContext
.getOsgiContext()
.getService(ScriptScheduler.class)
.getIntervalMillis();
long intervalMillis = getScriptScheduler().getIntervalMillis();
return DateUtils.isInRange(localDateTime, LocalDateTime.now(), intervalMillis);
}

private ScriptScheduler getScriptScheduler() {
return executionContext.getCodeContext().getOsgiContext().getService(ScriptScheduler.class);
}

// Duration-based since the last execution

public Duration passedDuration() {
Expand Down Expand Up @@ -359,30 +362,34 @@ public boolean passedDays(long days) {
// Instance-based

public boolean isInstanceRunMode(String runMode) {
return executionContext.getOsgiContext().getInstanceInfo().isRunMode(runMode);
return getInstanceInfo().isRunMode(runMode);
}

private InstanceInfo getInstanceInfo() {
return executionContext.getCodeContext().getOsgiContext().getInstanceInfo();
}

public boolean isInstanceAuthor() {
return executionContext.getOsgiContext().getInstanceInfo().isAuthor();
return getInstanceInfo().isAuthor();
}

public boolean isInstancePublish() {
return executionContext.getOsgiContext().getInstanceInfo().isPublish();
return getInstanceInfo().isPublish();
}

public boolean isInstanceOnPrem() {
return executionContext.getOsgiContext().getInstanceInfo().getType() == InstanceType.ON_PREM;
return getInstanceInfo().getType() == InstanceType.ON_PREM;
}

public boolean isInstanceCloud() {
return executionContext.getOsgiContext().getInstanceInfo().getType().isCloud();
return getInstanceInfo().getType().isCloud();
}

public boolean isInstanceCloudContainer() {
return executionContext.getOsgiContext().getInstanceInfo().getType() == InstanceType.CLOUD_CONTAINER;
return getInstanceInfo().getType() == InstanceType.CLOUD_CONTAINER;
}

public boolean isInstanceCloudSdk() {
return executionContext.getOsgiContext().getInstanceInfo().getType() == InstanceType.CLOUD_SDK;
return getInstanceInfo().getType() == InstanceType.CLOUD_SDK;
}
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,6 @@
package com.vml.es.aem.acm.core.code;

import com.vml.es.aem.acm.core.acl.Acl;
import com.vml.es.aem.acm.core.format.Formatter;
import com.vml.es.aem.acm.core.osgi.OsgiContext;
import com.vml.es.aem.acm.core.replication.Activator;
import com.vml.es.aem.acm.core.repo.Repo;
import groovy.lang.Binding;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.apache.sling.api.resource.ResourceResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ExecutionContext implements AutoCloseable {
Expand All @@ -25,36 +15,24 @@ public class ExecutionContext implements AutoCloseable {

private final Executable executable;

private final OsgiContext osgiContext;

private final ResourceResolver resourceResolver;

private final Extender extender;
private final CodeContext codeContext;

private boolean history = true;

private boolean debug = false;

private final Arguments arguments = new Arguments();

private Binding binding = new Binding();

public ExecutionContext(
String id,
ExecutionMode mode,
Executor executor,
Executable executable,
OsgiContext osgiContext,
ResourceResolver resourceResolver) {
String id, ExecutionMode mode, Executor executor, Executable executable, CodeContext codeContext) {
this.id = id;
this.mode = mode;
this.output = mode == ExecutionMode.RUN ? new OutputFile(id) : new OutputString();
this.executor = executor;
this.executable = executable;
this.osgiContext = osgiContext;
this.resourceResolver = resourceResolver;
this.binding = createBinding(resourceResolver);
this.extender = new Extender(this);
this.codeContext = codeContext;

customizeBinding();
}

public String getId() {
Expand All @@ -73,16 +51,8 @@ public Executable getExecutable() {
return executable;
}

public Extender getExtender() {
return extender;
}

public ResourceResolver getResourceResolver() {
return resourceResolver;
}

public OsgiContext getOsgiContext() {
return osgiContext;
public CodeContext getCodeContext() {
return codeContext;
}

public ExecutionMode getMode() {
Expand All @@ -109,37 +79,15 @@ public Arguments getArguments() {
return arguments;
}

public Binding getBinding() {
return binding;
}

@SuppressWarnings("unchecked")
public List<Variable> getBindingVariables() {
Map<String, Object> variables = binding.getVariables();
return variables.entrySet().stream()
.map(entry -> new Variable(entry.getKey(), entry.getValue().getClass()))
.collect(Collectors.toList());
}

private Binding createBinding(ResourceResolver resourceResolver) {
Binding result = new Binding();

result.setVariable("args", arguments);
result.setVariable("condition", new Condition(this));
result.setVariable("log", createLogger(executable));
result.setVariable("out", new CodePrintStream(this));
result.setVariable("resourceResolver", resourceResolver);
result.setVariable("osgi", osgiContext);
result.setVariable("repo", new Repo(resourceResolver));
result.setVariable("acl", new Acl(resourceResolver));
result.setVariable("formatter", new Formatter());
result.setVariable("activator", new Activator(resourceResolver, osgiContext.getReplicator()));

return result;
}
private void customizeBinding() {
Binding binding = getCodeContext().getBinding();

private Logger createLogger(Executable executable) {
return LoggerFactory.getLogger(String.format("%s(%s)", getClass().getName(), executable.getId()));
binding.setVariable("args", arguments);
binding.setVariable("condition", new Condition(this));
binding.setVariable(
"log",
LoggerFactory.getLogger(String.format("%s(%s)", getClass().getName(), executable.getId())));
binding.setVariable("out", new CodePrintStream(this));
}

@Override
Expand All @@ -148,6 +96,6 @@ public void close() {
}

public void variable(String name, Object value) {
binding.setVariable(name, value);
codeContext.getBinding().setVariable(name, value);
}
}
9 changes: 6 additions & 3 deletions core/src/main/java/com/vml/es/aem/acm/core/code/Executor.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ protected void activate(Config config) {

public ExecutionContext createContext(
String id, ExecutionMode mode, Executable executable, ResourceResolver resourceResolver) {
ExecutionContext result = new ExecutionContext(id, mode, this, executable, osgiContext, resourceResolver);
CodeContext codeContext = new CodeContext(osgiContext, resourceResolver);
ExecutionContext result = new ExecutionContext(id, mode, this, executable, codeContext);
result.setDebug(config.debug());
result.setHistory(config.history());
return result;
Expand All @@ -69,13 +70,15 @@ public Execution execute(Executable executable, ExecutionContextOptions contextO
}

public Execution execute(ExecutionContext context) throws AcmException {
context.getCodeContext().prepareRun(context);
ImmediateExecution execution = executeImmediately(context);
if (context.getMode() == ExecutionMode.RUN) {
if (context.isHistory() && (context.isDebug() || (execution.getStatus() != ExecutionStatus.SKIPPED))) {
ExecutionHistory history = new ExecutionHistory(context.getResourceResolver());
ExecutionHistory history =
new ExecutionHistory(context.getCodeContext().getResourceResolver());
history.save(context, execution);
}
context.getExtender().complete(execution);
context.getCodeContext().completeRun(execution);
}
return execution;
}
Expand Down
Loading