1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.framework.action;
35
36 import info.magnolia.cms.security.User;
37 import info.magnolia.commands.CommandsManager;
38 import info.magnolia.commands.chain.Command;
39 import info.magnolia.context.Context;
40 import info.magnolia.context.MgnlContext;
41 import info.magnolia.i18nsystem.SimpleTranslator;
42 import info.magnolia.jcr.RuntimeRepositoryException;
43 import info.magnolia.objectfactory.Components;
44 import info.magnolia.ui.api.action.ActionExecutionException;
45 import info.magnolia.ui.api.action.CommandActionDefinition;
46 import info.magnolia.ui.api.context.UiContext;
47 import info.magnolia.ui.framework.action.async.AsyncActionExecutor;
48 import info.magnolia.ui.vaadin.integration.jcr.JcrItemAdapter;
49 import info.magnolia.ui.vaadin.overlay.MessageStyleTypeEnum;
50
51 import java.util.Collections;
52 import java.util.HashMap;
53 import java.util.List;
54 import java.util.Map;
55
56 import javax.jcr.Item;
57 import javax.jcr.Node;
58 import javax.jcr.RepositoryException;
59
60 import org.slf4j.Logger;
61 import org.slf4j.LoggerFactory;
62
63 import com.google.common.collect.Lists;
64
65
66
67
68
69
70
71 public class AbstractCommandAction<D extends CommandActionDefinition> extends AbstractMultiItemAction<D> {
72
73 private static final Logger log = LoggerFactory.getLogger(AbstractCommandAction.class);
74
75 public static final String COMMAND_RESULT = "command_result";
76 public static final String LONG_RUNNING_ACTION_NOTIFICATION = "ui-framework.abstractcommand.asyncaction.long";
77 public static final String PARALLEL_EXECUTION_NOT_ALLOWED_NOTIFICATION = "ui-framework.abstractcommand.parallelExecutionNotAllowed";
78
79 private final CommandsManager commandsManager;
80 private final SimpleTranslator i18n;
81 private final User user;
82 private final Command command;
83 private final AsyncActionExecutor asyncExecutor;
84
85 private Map<String, Object> params;
86 private String successMessage;
87 private String failureMessage;
88
89 public AbstractCommandAction(final D definition, final JcrItemAdapter item, final CommandsManager commandsManager, UiContext uiContext, SimpleTranslator i18n) {
90 this(definition, Lists.newArrayList(item), commandsManager, uiContext, i18n);
91 }
92
93 public AbstractCommandAction(final D definition, final List<JcrItemAdapter> items, final CommandsManager commandsManager, UiContext uiContext, SimpleTranslator i18n) {
94 super(definition, items, uiContext);
95 this.commandsManager = commandsManager;
96 this.i18n = i18n;
97 this.user = MgnlContext.getUser();
98
99 this.command = commandsManager.getCommand(getDefinition().getCatalog(), getDefinition().getCommand());
100 this.asyncExecutor = Components.getComponentProvider().newInstance(AsyncActionExecutor.class, getDefinition(), getUiContext());
101 }
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125 protected Map<String, Object> buildParams(final Item jcrItem) {
126 Map<String, Object> params = new HashMap<String, Object>();
127 if (!getDefinition().getParams().isEmpty()) {
128 params.putAll(getDefinition().getParams());
129 }
130 try {
131 final String path = jcrItem.getPath();
132 final String workspace = jcrItem.getSession().getWorkspace().getName();
133 final String identifier = jcrItem.isNode() ? ((Node) jcrItem).getIdentifier() : jcrItem.getParent().getIdentifier();
134
135 params.put(Context.ATTRIBUTE_REPOSITORY, workspace);
136
137 params.put(Context.ATTRIBUTE_UUID, identifier);
138 params.put(Context.ATTRIBUTE_PATH, path);
139 params.put(Context.ATTRIBUTE_USERNAME, user.getName());
140 params.put(Context.ATTRIBUTE_REQUESTOR, user.getName());
141 } catch (RepositoryException e) {
142 throw new RuntimeRepositoryException(e);
143 }
144 return params;
145 }
146
147
148
149
150
151 public final Map<String, Object> getParams() {
152 return Collections.unmodifiableMap(params);
153 }
154
155 public final CommandsManager getCommandsManager() {
156 return commandsManager;
157 }
158
159
160
161
162
163
164
165 @Override
166 protected void executeOnItem(JcrItemAdapter item) throws ActionExecutionException {
167 this.failureMessage = null;
168 this.successMessage = null;
169 try {
170 onPreExecute();
171 } catch (Exception e) {
172 onError(e);
173 log.debug("Command execution failed during pre execution tasks.");
174 throw new ActionExecutionException(e);
175 }
176 if (command == null) {
177 throw new ActionExecutionException(String.format("Could not find command [%s] in any catalog", getDefinition().getCommand()));
178 }
179
180 long start = System.currentTimeMillis();
181
182
183 boolean stopProcessing = false;
184
185 try {
186 log.debug("Executing command [{}] from catalog [{}] with the following parameters [{}]...", getDefinition().getCommand(), getDefinition().getCatalog(), getParams());
187
188 if (isInvokeAsynchronously()) {
189 try {
190 boolean inBackground = asyncExecutor.execute(item, params);
191
192
193 if (inBackground) {
194 this.successMessage = i18n.translate(LONG_RUNNING_ACTION_NOTIFICATION);
195 }
196 } catch (AsyncActionExecutor.ParallelExecutionException e) {
197 this.failureMessage = i18n.translate(PARALLEL_EXECUTION_NOT_ALLOWED_NOTIFICATION);
198 stopProcessing = true;
199 }
200 } else {
201 stopProcessing = commandsManager.executeCommand(command, getParams());
202 }
203 MgnlContext.getInstance().setAttribute(COMMAND_RESULT, stopProcessing, Context.LOCAL_SCOPE);
204
205 onPostExecute();
206 log.debug("Command executed successfully in {} ms ", System.currentTimeMillis() - start);
207 } catch (Exception e) {
208 onError(e);
209 log.debug("Command execution failed after {} ms ", System.currentTimeMillis() - start);
210 log.debug(e.getMessage(), e);
211 throw new ActionExecutionException(e);
212 }
213 }
214
215 protected boolean isInvokeAsynchronously() {
216 return getDefinition().isAsynchronous();
217 }
218
219
220
221
222
223
224 protected void onPreExecute() throws Exception {
225 this.params = buildParams(getCurrentItem().getJcrItem());
226 }
227
228
229
230
231
232 protected void onPostExecute() throws Exception {
233
234 }
235
236
237
238
239
240 protected void onError(Exception e) {
241 String message = i18n.translate("ui-framework.abstractcommand.executionfailure");
242 getUiContext().openNotification(MessageStyleTypeEnum.ERROR, true, message);
243 }
244
245
246
247
248 protected Command getCommand() {
249 return this.command;
250 }
251
252 @Override
253 protected String getSuccessMessage() {
254
255 return successMessage;
256 }
257
258 @Override
259 protected String getFailureMessage() {
260
261 return failureMessage;
262 }
263
264 protected SimpleTranslator getI18n() {
265 return i18n;
266 }
267 }