001/*
002 * (C) Copyright 2015-2017 Nuxeo (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Thierry Delprat <tdelprat@nuxeo.com>
018 *     Stephane Lacoin <slacoin@nuxeo.com>
019 *     Vladimir Pasquier <vpasquier@nuxeo.com>
020 */
021package org.nuxeo.automation.scripting.internals;
022
023import java.util.ArrayList;
024import java.util.HashSet;
025import java.util.List;
026import java.util.Set;
027
028import org.apache.commons.logging.Log;
029import org.apache.commons.logging.LogFactory;
030import org.nuxeo.automation.scripting.api.AutomationScriptingService;
031import org.nuxeo.ecm.automation.AutomationService;
032import org.nuxeo.runtime.api.Framework;
033import org.nuxeo.runtime.model.ComponentContext;
034import org.nuxeo.runtime.model.ComponentInstance;
035import org.nuxeo.runtime.model.DefaultComponent;
036import org.nuxeo.runtime.services.config.ConfigurationService;
037
038/**
039 * @since 7.2
040 */
041public class AutomationScriptingComponent extends DefaultComponent {
042
043    private static final Log log = LogFactory.getLog(AutomationScriptingComponent.class);
044
045    protected static final String XP_OPERATION = "operation";
046
047    protected static final String XP_CLASSFILTER = "classFilter";
048
049    protected final AutomationScriptingServiceImpl service = new AutomationScriptingServiceImpl();
050
051    protected final AutomationScriptingRegistry registry = new AutomationScriptingRegistry();
052
053    protected final List<ClassFilterDescriptor> classFilterDescriptors = new ArrayList<>();
054
055    @Override
056    public void activate(ComponentContext context) {
057        registry.automation = Framework.getService(AutomationService.class);
058        registry.scripting = service;
059    }
060
061    @Override
062    public void start(ComponentContext context) {
063        boolean inlinedContext = Framework.getService(ConfigurationService.class)
064                                          .isBooleanTrue("nuxeo.automation.scripting.inline-context-in-params");
065
066        service.paramsInjector = AutomationScriptingParamsInjector.newInstance(inlinedContext);
067    }
068
069    @Override
070    public void registerContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
071        if (XP_OPERATION.equals(extensionPoint)) {
072            ScriptingOperationDescriptor desc = (ScriptingOperationDescriptor) contribution;
073            desc.setContributingComponent(contributor.getName().toString());
074            registry.addContribution(desc);
075        } else if (XP_CLASSFILTER.equals(extensionPoint)) {
076            registerClassFilter((ClassFilterDescriptor) contribution);
077        } else {
078            log.error("Unknown extension point " + extensionPoint);
079        }
080    }
081
082    @Override
083    public void unregisterContribution(Object contribution, String extensionPoint, ComponentInstance contributor) {
084        if (XP_OPERATION.equals(extensionPoint)) {
085            registry.removeContribution((ScriptingOperationDescriptor) contribution);
086        } else if (XP_CLASSFILTER.equals(extensionPoint)) {
087            unregisterClassFilter((ClassFilterDescriptor) contribution);
088        } else {
089            log.error("Unknown extension point " + extensionPoint);
090        }
091    }
092
093    protected void registerClassFilter(ClassFilterDescriptor desc) {
094        classFilterDescriptors.add(desc);
095        recomputeClassFilters();
096    }
097
098    protected void unregisterClassFilter(ClassFilterDescriptor desc) {
099        classFilterDescriptors.remove(desc);
100        recomputeClassFilters();
101    }
102
103    protected void recomputeClassFilters() {
104        Set<String> allowedClassNames = new HashSet<>();
105        for (ClassFilterDescriptor desc : classFilterDescriptors) {
106            if (desc.deny.contains("*")) {
107                allowedClassNames.clear();
108                allowedClassNames.addAll(desc.allow);
109            } else {
110                allowedClassNames.addAll(desc.allow);
111                allowedClassNames.removeAll(desc.deny);
112            }
113        }
114        // we don't care about update atomicity, as nothing executes concurrently with XML config
115        service.allowedClassNames.clear();
116        service.allowedClassNames.addAll(allowedClassNames);
117    }
118
119    @Override
120    public <T> T getAdapter(Class<T> adapter) {
121        if (adapter.isAssignableFrom(AutomationScriptingService.class)) {
122            return adapter.cast(service);
123        }
124        return super.getAdapter(adapter);
125    }
126
127}