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}