com.adobe.acs.commons.mcp.impl.ControlledProcessManagerImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of acs-aem-commons-bundle Show documentation
Show all versions of acs-aem-commons-bundle Show documentation
Main ACS AEM Commons OSGi Bundle. Includes commons utilities.
/*
* ACS AEM Commons
*
* Copyright (C) 2013 - 2023 Adobe
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.adobe.acs.commons.mcp.impl;
import com.adobe.acs.commons.fam.ActionManagerFactory;
import com.adobe.acs.commons.mcp.ControlledProcessManager;
import com.adobe.acs.commons.mcp.DynamicScriptResolverService;
import com.adobe.acs.commons.mcp.ProcessDefinition;
import com.adobe.acs.commons.mcp.ProcessDefinitionFactory;
import com.adobe.acs.commons.mcp.ProcessInstance;
import com.adobe.acs.commons.mcp.form.FieldComponent;
import com.adobe.acs.commons.mcp.model.impl.ArchivedProcessInstance;
import com.adobe.acs.commons.mcp.util.AnnotatedFieldDeserializer;
import com.adobe.acs.commons.util.visitors.TreeFilteringResourceVisitor;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.stream.Collectors;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.TabularDataSupport;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.ReferencePolicy;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.api.security.user.User;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.scripting.SlingScriptHelper;
import org.slf4j.LoggerFactory;
/**
* Implementation of ControlProcessManager service
*/
@Component
@Service(ControlledProcessManager.class)
@Property(name = "jmx.objectname", value = "com.adobe.acs.commons:type=Manage Controlled Processes")
public class ControlledProcessManagerImpl implements ControlledProcessManager {
private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(ControlledProcessManagerImpl.class);
private static final String SERVICE_NAME = "manage-controlled-processes";
private static final Map AUTH_INFO;
@Reference(cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, bind = "bindDefinitionFactory", unbind = "unbindDefinitionFactory", referenceInterface = ProcessDefinitionFactory.class, policy = ReferencePolicy.DYNAMIC)
private final List processDefinitionFactories = new CopyOnWriteArrayList<>();
@Reference(cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, bind = "bindScriptResolverService", unbind = "unbindScriptResolverService", referenceInterface = DynamicScriptResolverService.class, policy = ReferencePolicy.DYNAMIC)
private final List scriptResolverService = new CopyOnWriteArrayList<>();
static {
AUTH_INFO = Collections.singletonMap(ResourceResolverFactory.SUBSERVICE, (Object) SERVICE_NAME);
}
Map activeProcesses = Collections.synchronizedMap(new LinkedHashMap<>());
@Reference
ResourceResolverFactory resourceResolverFactory;
@Reference
ActionManagerFactory amf;
@Override
public ActionManagerFactory getActionManagerFactory() {
return amf;
}
protected void bindDefinitionFactory(ProcessDefinitionFactory fac) {
processDefinitionFactories.add(fac);
}
protected void unbindDefinitionFactory(ProcessDefinitionFactory fac) {
processDefinitionFactories.remove(fac);
}
protected void bindScriptResolverService(DynamicScriptResolverService dsrs) {
scriptResolverService.add(dsrs);
}
protected void unbindScriptResolverService(DynamicScriptResolverService dsrs) {
scriptResolverService.remove(dsrs);
}
@Override
public ProcessInstance getManagedProcessInstanceByPath(String path) {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public ProcessInstance getManagedProcessInstanceByIdentifier(String id) {
ProcessInstance process = activeProcesses.get(id);
if (process != null) {
process.updateProgress();
}
return process;
}
@Override
public ProcessInstance createManagedProcessInstance(ProcessDefinition definition, String description) {
ProcessInstance instance = new ProcessInstanceImpl(this, definition, description);
activeProcesses.put(instance.getId(), instance);
return instance;
}
@Override
public void haltActiveProcesses() {
Set instances = new HashSet<>(activeProcesses.values());
activeProcesses.clear();
instances.forEach(ProcessInstance::halt);
}
@Override
public void purgeCompletedProcesses() {
activeProcesses.values().removeIf(proc -> !proc.getInfo().isIsRunning());
}
@Override
public ResourceResolver getServiceResourceResolver() throws LoginException {
return resourceResolverFactory.getServiceResourceResolver(AUTH_INFO);
}
@Override
public ProcessDefinition findDefinitionByNameOrPath(String nameOrPath) throws ReflectiveOperationException {
if (nameOrPath.startsWith("/")) {
return findDefinitionByPath(nameOrPath);
} else {
return findDefinitionByName(nameOrPath);
}
}
private ProcessDefinition findDefinitionByName(String name) throws ReflectiveOperationException {
ProcessDefinitionFactory factory = processDefinitionFactories.stream()
.filter(f -> name.equals(f.getName())).findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unable to find process " + name));
return factory.createProcessDefinition();
}
private ProcessDefinition findDefinitionByPath(String path) {
if (!scriptResolverService.isEmpty()) {
try ( ResourceResolver rr = getServiceResourceResolver()) {
for (DynamicScriptResolverService dsrs : scriptResolverService) {
ProcessDefinitionFactory factory = dsrs.getScriptByIdentifier(rr, path);
if (factory != null) {
return factory.createProcessDefinition();
}
}
} catch (LoginException ex) {
LOG.error(MessageFormat.format("Error looking for definition by path: {0}", path), ex);
}
}
return null;
}
@Override
public TabularDataSupport getStatistics() throws OpenDataException {
TabularDataSupport stats = new TabularDataSupport(ProcessInstanceImpl.getStaticsTableType());
activeProcesses.values().stream().map(ProcessInstance::getStatistics).forEach(stats::put);
return stats;
}
@Override
public void haltProcessById(String id) {
getManagedProcessInstanceByIdentifier(id).halt();
}
@Override
public void haltProcessByPath(String path) {
getManagedProcessInstanceByPath(path).halt();
}
@Override
public Collection getActiveProcesses() {
activeProcesses.forEach((id, process) -> process.updateProgress());
return activeProcesses.values();
}
@Override
public Collection getInactiveProcesses() {
ArrayList processes = new ArrayList();
try ( ResourceResolver rr = getServiceResourceResolver()) {
Resource tree = rr.getResource(ProcessInstanceImpl.BASE_PATH);
TreeFilteringResourceVisitor visitor = new TreeFilteringResourceVisitor();
visitor.setLeafVisitor((r, l) -> {
if (!activeProcesses.containsKey(r.getName())) {
processes.add(r.adaptTo(ArchivedProcessInstance.class));
}
});
visitor.accept(tree);
} catch (Exception ex) {
LOG.error("Error getting inactive process list", ex);
}
return processes;
}
@Override
public Map getComponentsForProcessDefinition(String identifierOrPath, SlingScriptHelper sling) throws ReflectiveOperationException {
if (identifierOrPath == null) {
return null;
}
for (DynamicScriptResolverService dsrs : scriptResolverService) {
Map components = dsrs.geFieldComponentsForProcessDefinition(identifierOrPath, sling);
if (components != null) {
return components;
}
}
ProcessDefinition definition = findDefinitionByNameOrPath(identifierOrPath);
if (definition != null) {
return AnnotatedFieldDeserializer.getFormFields(definition.getClass(), sling);
}
return null;
}
@Override
public Map getAllProcessDefinitionsForUser(User user) {
Map availableDefinitions = processDefinitionFactories.stream().filter(o -> o.isAllowed(user))
.collect(Collectors.toMap(ProcessDefinitionFactory::getName, o -> o, (a, b) -> a, TreeMap::new));
if (!scriptResolverService.isEmpty()) {
try ( ResourceResolver rr = getServiceResourceResolver()) {
for (DynamicScriptResolverService dsrs : scriptResolverService) {
dsrs.getDetectedProcesDefinitionFactories(rr).forEach((path, factory) -> {
if (factory.isAllowed(user)) {
availableDefinitions.put(path, factory);
}
});
}
} catch (LoginException ex) {
LOG.error("Unable to look up process definitions", ex);
}
}
return availableDefinitions;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy