001/*
002 *  Copyright 2016 Anyware Services
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 */
016package org.ametys.core.ui;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.configuration.Configuration;
024import org.apache.avalon.framework.configuration.ConfigurationException;
025import org.apache.avalon.framework.context.Context;
026import org.apache.avalon.framework.context.ContextException;
027import org.apache.avalon.framework.context.Contextualizable;
028import org.apache.avalon.framework.service.ServiceException;
029import org.apache.avalon.framework.service.ServiceManager;
030import org.apache.cocoon.components.ContextHelper;
031import org.apache.cocoon.environment.Request;
032import org.quartz.SchedulerException;
033
034import org.ametys.core.schedule.AmetysJob;
035import org.ametys.plugins.core.schedule.Scheduler;
036import org.ametys.runtime.authentication.AccessDeniedException;
037import org.ametys.runtime.workspace.WorkspaceMatcher;
038
039/**
040 * This implementation creates an element for adding a new task
041 */
042public class AddTaskClientSideElement extends StaticClientSideElement implements Contextualizable
043{
044    /** The Avalon context */
045    protected Context _context;
046    /** The Ametys scheduler */
047    protected Scheduler _scheduler;
048    private String _schedulableId;
049    
050    @Override
051    public void contextualize(Context context) throws ContextException
052    {
053        _context = context;
054    }
055    
056    @Override
057    public void service(ServiceManager smanager) throws ServiceException
058    {
059        super.service(smanager);
060        _scheduler = (Scheduler) smanager.lookup(Scheduler.ROLE);
061    }
062
063    @Override
064    protected String _configureClass(Configuration configuration) throws ConfigurationException
065    {
066        return "Ametys.plugins.coreui.schedule.AddTaskButtonController";
067    }
068    
069    @SuppressWarnings("unchecked")
070    @Override
071    protected Map<String, Object> configureInitialParameters(Configuration configuration) throws ConfigurationException
072    {
073        Map<String, Object> initialParameters = super.configureInitialParameters(configuration);
074        _schedulableId = (String) initialParameters.get("schedulable");
075        
076        initialParameters.put("action", _configureClass(configuration) + ".act");
077        
078        // Always have at least the log category 'org.ametys.plugins.core.schedule.Scheduler',
079        // because in case of error in AmetysJob during the execution of the Schedulable, it will log in that category
080        List<String> logCategories = new ArrayList<>();
081        String jobLogCategory = AmetysJob.class.getName() + "$" + _schedulableId;
082        logCategories.add(jobLogCategory);
083        if (initialParameters.containsKey("log-category"))
084        {
085            Object initialLogCategory = initialParameters.get("log-category");
086            
087            if (initialLogCategory instanceof String)
088            {
089                logCategories.add((String) initialLogCategory);
090            }
091            else if (initialLogCategory instanceof List)
092            {
093                logCategories.addAll((List<String>) initialLogCategory);
094            }
095        }
096        initialParameters.put("log-category", logCategories);
097        
098        return initialParameters;
099    }
100    
101    @Override
102    protected Script _configureScript(Configuration configuration) throws ConfigurationException
103    {
104        List<ScriptFile> scriptsImports = _configureImports(configuration.getChild("scripts"));
105        scriptsImports.add(new ScriptFile("/plugins/core-ui/resources/js/Ametys/plugins/coreui/schedule/AddTaskButtonController.js"));
106        List<ScriptFile> cssImports = _configureImports(configuration.getChild("css"));
107        String jsClassName = _configureClass(configuration.getChild("class"));
108        Map<String, Object> initialParameters = configureInitialParameters(configuration);
109        
110        return new Script(this.getId(), jsClassName, scriptsImports, cssImports, initialParameters);
111    }
112    
113    @Override
114    protected Map<String, List<String>> _configureDependencies(Configuration configuration) throws ConfigurationException
115    {
116        Map<String, List<String>> dependencies = super._configureDependencies(configuration);
117        
118        List<String> importDependencies = dependencies.computeIfAbsent("org.ametys.core.ui.StaticFileImportsManager", __ -> new ArrayList<>());
119        importDependencies.add("org.ametys.core.schedule.Scheduler");
120
121        List<String> uitoolsDependencies = dependencies.computeIfAbsent("org.ametys.core.ui.UIToolsFactoriesManager", __ -> new ArrayList<>());
122        uitoolsDependencies.add("uitool-server-logs");
123        
124        return dependencies;
125    }
126    
127    @Override
128    public Map<String, List<String>> getDependencies()
129    {
130        // RUNTIME-2913 The task scheduler is opened in the CMS while using the AddTaskButtonController
131        // Load the task scheduler only on admin context
132        Request request = ContextHelper.getRequest(_context);
133        String workspaceName = (String) request.getAttribute(WorkspaceMatcher.WORKSPACE_NAME);
134        if ("admin".equals(workspaceName))
135        {
136            Map<String, List<String>> clonedDependencies = new HashMap<>(_dependencies);
137            List<String> uitoolsDependencies = new ArrayList<>();
138            if (clonedDependencies.containsKey("org.ametys.core.ui.UIToolsFactoriesManager"))
139            {
140                uitoolsDependencies.addAll(clonedDependencies.get("org.ametys.core.ui.UIToolsFactoriesManager"));
141            }
142            uitoolsDependencies.add("uitool-scheduled-tasks");
143            clonedDependencies.put("org.ametys.core.ui.UIToolsFactoriesManager", uitoolsDependencies);
144            return clonedDependencies;
145        }
146        return _dependencies;
147    }
148    
149    /**
150     * Schedule a task
151     * @param label the task label
152     * @param description the task description
153     * @param fireProcess the fire process
154     * @param cron the cron
155     * @param schedulableId the id of the schedulable
156     * @param params the schedulable parameters
157     * @return a json
158     * @throws SchedulerException if an error occurs when scheduling the task
159     */
160    @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION)
161    public Map<String, Object> add(String label, String description, String fireProcess, String cron, String schedulableId, Map<String, Object> params) throws SchedulerException
162    {
163        if (hasRight(getRights(null)) && schedulableId.equals(_schedulableId))
164        {
165            return _scheduler.add(label, description, fireProcess, cron, schedulableId, params);
166        }
167        throw new AccessDeniedException(_currentUserProvider.getUser() + "' tried to execute schedulable '" + schedulableId + "' without any of the following rights: " + getRights(null));
168    }
169    
170    /**
171     * Get the schedulable parameters
172     * @param schedulableId the id of the schedulable
173     * @return the parameters as json
174     * @throws Exception if an error occurs
175     */
176    @Callable(rights = Callable.CHECKED_BY_IMPLEMENTATION)
177    public Map<String, Object> getParameters(String schedulableId) throws Exception
178    {
179        if (hasRight(getRights(null)) && schedulableId.equals(_schedulableId))
180        {
181            return _scheduler.getParameters(_schedulableId);
182        }
183        throw new AccessDeniedException(_currentUserProvider.getUser() + "' tried to fetch the schedulable " + _schedulableId + " parameters without any of the following rights: " + getRights(null));
184    }
185}