e535954dac6cd72bcdf084f6b3219e32bf573af5
[public/netxms.git] / webui / webapp / ObjectTools / src / org / netxms / ui / eclipse / objecttools / api / ObjectToolExecutor.java
1 /**
2 * NetXMS - open source network management system
3 * Copyright (C) 2003-2016 Victor Kirhenshtein
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 package org.netxms.ui.eclipse.objecttools.api;
20
21 import java.net.URLEncoder;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Comparator;
25 import java.util.HashMap;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import org.eclipse.core.runtime.IProgressMonitor;
30 import org.eclipse.jface.window.Window;
31 import org.eclipse.rap.rwt.RWT;
32 import org.eclipse.rap.rwt.client.service.UrlLauncher;
33 import org.eclipse.ui.IWorkbenchPage;
34 import org.eclipse.ui.IWorkbenchWindow;
35 import org.eclipse.ui.PartInitException;
36 import org.eclipse.ui.PlatformUI;
37 import org.netxms.client.AgentFileData;
38 import org.netxms.client.NXCSession;
39 import org.netxms.client.ProgressListener;
40 import org.netxms.client.objecttools.InputField;
41 import org.netxms.client.objecttools.InputFieldType;
42 import org.netxms.client.objecttools.ObjectTool;
43 import org.netxms.ui.eclipse.filemanager.views.AgentFileViewer;
44 import org.netxms.ui.eclipse.jobs.ConsoleJob;
45 import org.netxms.ui.eclipse.objects.ObjectContext;
46 import org.netxms.ui.eclipse.objecttools.Activator;
47 import org.netxms.ui.eclipse.objecttools.Messages;
48 import org.netxms.ui.eclipse.objecttools.dialogs.ObjectToolInputDialog;
49 import org.netxms.ui.eclipse.objecttools.views.AgentActionResults;
50 import org.netxms.ui.eclipse.objecttools.views.ServerCommandResults;
51 import org.netxms.ui.eclipse.objecttools.views.ServerScriptResults;
52 import org.netxms.ui.eclipse.objecttools.views.TableToolResults;
53 import org.netxms.ui.eclipse.shared.ConsoleSharedData;
54 import org.netxms.ui.eclipse.tools.MessageDialogHelper;
55
56 /**
57 * Executor for object tool
58 */
59 public final class ObjectToolExecutor
60 {
61 /**
62 * Private constructor to forbid instantiation
63 */
64 private ObjectToolExecutor()
65 {
66 }
67
68 /**
69 * Check if tool is allowed for execution on each node from set
70 *
71 * @param tool
72 * @param nodes
73 * @return
74 */
75 public static boolean isToolAllowed(ObjectTool tool, Set<ObjectContext> nodes)
76 {
77 if (tool.getToolType() != ObjectTool.TYPE_INTERNAL)
78 return true;
79
80 ObjectToolHandler handler = ObjectToolsCache.findHandler(tool.getData());
81 if (handler != null)
82 {
83 for(ObjectContext n : nodes)
84 if (!handler.canExecuteOnNode(n.object, tool))
85 return false;
86 return true;
87 }
88 else
89 {
90 return false;
91 }
92 }
93
94 /**
95 * Check if given tool is applicable for all nodes in set
96 *
97 * @param tool
98 * @param nodes
99 * @return
100 */
101 public static boolean isToolApplicable(ObjectTool tool, Set<ObjectContext> nodes)
102 {
103 for(ObjectContext n : nodes)
104 if (!tool.isApplicableForNode(n.object))
105 return false;
106 return true;
107 }
108
109 /**
110 * Execute object tool on node set
111 *
112 * @param tool Object tool
113 */
114 public static void execute(final Set<ObjectContext> nodes, final ObjectTool tool)
115 {
116 final Map<String, String> inputValues;
117 final InputField[] fields = tool.getInputFields();
118 if (fields.length > 0)
119 {
120 Arrays.sort(fields, new Comparator<InputField>() {
121 @Override
122 public int compare(InputField f1, InputField f2)
123 {
124 return f1.getSequence() - f2.getSequence();
125 }
126 });
127 inputValues = readInputFields(fields);
128 if (inputValues == null)
129 return; // cancelled
130 }
131 else
132 {
133 inputValues = new HashMap<String, String>(0);
134 }
135 final NXCSession session = ConsoleSharedData.getSession();
136 new ConsoleJob(Messages.get().ObjectToolExecutor_JobName, null, Activator.PLUGIN_ID, null) {
137 @Override
138 protected void runInternal(IProgressMonitor monitor) throws Exception
139 {
140 List<String> expandedText = null;
141
142 if ((tool.getFlags() & ObjectTool.ASK_CONFIRMATION) != 0)
143 {
144 String message = tool.getConfirmationText();
145 if (nodes.size() == 1)
146 {
147 //Expand message and action for 1 node, otherwise expansion occurs after confirmation
148 List<String> textToExpand = new ArrayList<String>();
149 textToExpand.add(tool.getConfirmationText());
150 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
151 {
152 textToExpand.add(tool.getData());
153 }
154 ObjectContext node = nodes.iterator().next();
155 expandedText = session.substitureMacross(node, textToExpand, inputValues);
156
157 message = expandedText.remove(0);
158 }
159 else
160 {
161 ObjectContext node = nodes.iterator().next();
162 message = node.substituteMacrosForMultiNodes(message, inputValues);
163 }
164
165 ConfirmationRunnable runnable = new ConfirmationRunnable(message);
166 getDisplay().syncExec(runnable);
167 if(!runnable.isConfirmed())
168 return;
169
170 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
171 {
172 expandedText = session.substitureMacross(nodes.toArray(new ObjectContext[nodes.size()]), tool.getData(), inputValues);
173 }
174 }
175 else
176 {
177 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
178 {
179 expandedText = session.substitureMacross(nodes.toArray(new ObjectContext[nodes.size()]), tool.getData(), inputValues);
180 }
181 }
182
183 // Check if password validation needed
184 boolean validationNeeded = false;
185 for(int i = 0; i < fields.length; i++)
186 if (fields[i].getOptions().validatePassword)
187 {
188 validationNeeded = true;
189 break;
190 }
191
192 if (validationNeeded)
193 {
194 for(int i = 0; i < fields.length; i++)
195 {
196 if ((fields[i].getType() == InputFieldType.PASSWORD) && (fields[i].getOptions().validatePassword))
197 {
198 boolean valid = session.validateUserPassword(inputValues.get(fields[i].getName()));
199 if (!valid)
200 {
201 final String fieldName = fields[i].getDisplayName();
202 getDisplay().syncExec(new Runnable() {
203 @Override
204 public void run()
205 {
206 MessageDialogHelper.openError(null, Messages.get().ObjectToolExecutor_ErrorTitle,
207 String.format(Messages.get().ObjectToolExecutor_ErrorText, fieldName));
208 }
209 });
210 return;
211 }
212 }
213 }
214 }
215
216 int i = 0;
217 for(final ObjectContext n : nodes)
218 {
219 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
220 {
221 final String tmp = expandedText.get(i++);
222 getDisplay().syncExec(new Runnable() {
223
224 @Override
225 public void run()
226 {
227 executeOnNode(n, tool, inputValues, tmp);
228 }
229 });
230 }
231 else
232 {
233 getDisplay().syncExec(new Runnable() {
234
235 @Override
236 public void run()
237 {
238 executeOnNode(n, tool, inputValues, null);
239 }
240 });
241 }
242 }
243 }
244
245 @Override
246 protected String getErrorMessage()
247 {
248 return Messages.get().ObjectToolExecutor_PasswordValidationFailed;
249 }
250
251 class ConfirmationRunnable implements Runnable
252 {
253 private boolean confirmed;
254 private String message;
255
256 public ConfirmationRunnable(String message)
257 {
258 this.message = message;
259 }
260
261 @Override
262 public void run()
263 {
264 confirmed = MessageDialogHelper.openQuestion(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
265 Messages.get().ObjectToolsDynamicMenu_ConfirmExec, message);
266 }
267
268 boolean isConfirmed()
269 {
270 return confirmed;
271 }
272 }
273
274 }.start();
275 }
276
277 /**
278 * Read input fields
279 *
280 * @param fields
281 * @return
282 */
283 private static Map<String, String> readInputFields(InputField[] fields)
284 {
285 ObjectToolInputDialog dlg = new ObjectToolInputDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), fields);
286 if (dlg.open() != Window.OK)
287 return null;
288 return dlg.getValues();
289 }
290
291 /**
292 * Execute object tool on single node
293 *
294 * @param node
295 * @param tool
296 * @param inputValues
297 */
298 private static void executeOnNode(final ObjectContext node, final ObjectTool tool, Map<String, String> inputValues, String expandedValue)
299 {
300 switch(tool.getToolType())
301 {
302 case ObjectTool.TYPE_ACTION:
303 executeAgentAction(node, tool, inputValues);
304 break;
305 case ObjectTool.TYPE_FILE_DOWNLOAD:
306 executeFileDownload(node, tool, inputValues);
307 break;
308 case ObjectTool.TYPE_INTERNAL:
309 executeInternalTool(node, tool);
310 break;
311 case ObjectTool.TYPE_SERVER_COMMAND:
312 executeServerCommand(node, tool, inputValues);
313 break;
314 case ObjectTool.TYPE_SERVER_SCRIPT:
315 executeServerScript(node, tool, inputValues);
316 break;
317 case ObjectTool.TYPE_TABLE_AGENT:
318 case ObjectTool.TYPE_TABLE_SNMP:
319 executeTableTool(node, tool);
320 break;
321 case ObjectTool.TYPE_URL:
322 openURL(node, tool, inputValues, expandedValue);
323 break;
324 }
325 }
326
327 /**
328 * Execute table tool
329 *
330 * @param node
331 * @param tool
332 */
333 private static void executeTableTool(final ObjectContext node, final ObjectTool tool)
334 {
335 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
336 try
337 {
338 final IWorkbenchPage page = window.getActivePage();
339 final TableToolResults view = (TableToolResults)page.showView(TableToolResults.ID,
340 Long.toString(tool.getId()) + "&" + Long.toString(node.object.getObjectId()), IWorkbenchPage.VIEW_ACTIVATE); //$NON-NLS-1$
341 view.refreshTable();
342 }
343 catch(PartInitException e)
344 {
345 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
346 }
347 }
348
349 /**
350 * @param node
351 * @param tool
352 * @param inputValues
353 */
354 private static void executeAgentAction(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
355 {
356 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
357
358 if ((tool.getFlags() & ObjectTool.GENERATES_OUTPUT) == 0)
359 {
360 new ConsoleJob(String.format(Messages.get().ObjectToolsDynamicMenu_ExecuteOnNode, node.object.getObjectName()), null, Activator.PLUGIN_ID, null) {
361 @Override
362 protected String getErrorMessage()
363 {
364 return String.format(Messages.get().ObjectToolsDynamicMenu_CannotExecuteOnNode, node.object.getObjectName());
365 }
366
367 @Override
368 protected void runInternal(IProgressMonitor monitor) throws Exception
369 {
370 final String action = session.executeActionWithExpansion(node.object.getObjectId(), node.getAlarmId(), tool.getData(), inputValues);
371 runInUIThread(new Runnable() {
372 @Override
373 public void run()
374 {
375 MessageDialogHelper.openInformation(null, Messages.get().ObjectToolsDynamicMenu_ToolExecution, String.format(Messages.get().ObjectToolsDynamicMenu_ExecSuccess, action, node.object.getObjectName()));
376 }
377 });
378 }
379 }.start();
380 }
381 else
382 {
383 final String secondaryId = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
384 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
385 try
386 {
387 AgentActionResults view = (AgentActionResults)window.getActivePage().showView(AgentActionResults.ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
388 view.executeAction(tool.getData(), node.getAlarmId(), inputValues);
389 }
390 catch(Exception e)
391 {
392 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
393 }
394 }
395 }
396
397 /**
398 * Execute server command
399 *
400 * @param node
401 * @param tool
402 * @param inputValues
403 */
404 private static void executeServerCommand(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
405 {
406 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
407 if ((tool.getFlags() & ObjectTool.GENERATES_OUTPUT) == 0)
408 {
409 new ConsoleJob(Messages.get().ObjectToolsDynamicMenu_ExecuteServerCmd, null, Activator.PLUGIN_ID, null) {
410 @Override
411 protected void runInternal(IProgressMonitor monitor) throws Exception
412 {
413 session.executeServerCommand(node.object.getObjectId(), tool.getData(), inputValues);
414 runInUIThread(new Runnable() {
415 @Override
416 public void run()
417 {
418 MessageDialogHelper.openInformation(null, Messages.get().ObjectToolsDynamicMenu_Information, Messages.get().ObjectToolsDynamicMenu_ServerCommandExecuted);
419 }
420 });
421 }
422
423 @Override
424 protected String getErrorMessage()
425 {
426 return Messages.get().ObjectToolsDynamicMenu_ServerCmdExecError;
427 }
428 }.start();
429 }
430 else
431 {
432 final String secondaryId = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
433 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
434 try
435 {
436 ServerCommandResults view = (ServerCommandResults)window.getActivePage().showView(ServerCommandResults.ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
437 view.executeCommand(tool.getData(), inputValues);
438 }
439 catch(Exception e)
440 {
441 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
442 }
443 }
444 }
445
446 /**
447 * Execute server script
448 *
449 * @param node
450 * @param tool
451 * @param inputValues
452 */
453 private static void executeServerScript(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
454 {
455 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
456 if ((tool.getFlags() & ObjectTool.GENERATES_OUTPUT) == 0)
457 {
458 new ConsoleJob("Execute server script", null, Activator.PLUGIN_ID, null) {
459 @Override
460 protected void runInternal(IProgressMonitor monitor) throws Exception
461 {
462 session.executeLibraryScript(node.object.getObjectId(), node.getAlarmId(), tool.getData(), inputValues, null);
463 runInUIThread(new Runnable() {
464 @Override
465 public void run()
466 {
467 MessageDialogHelper.openInformation(null, Messages.get().ObjectToolsDynamicMenu_Information, Messages.get().ObjectToolsDynamicMenu_ServerScriptExecuted);
468 }
469 });
470 }
471
472 @Override
473 protected String getErrorMessage()
474 {
475 return Messages.get().ObjectToolsDynamicMenu_ServerScriptExecError;
476 }
477 }.start();
478 }
479 else
480 {
481 final String secondaryId = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
482 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
483 try
484 {
485 ServerScriptResults view = (ServerScriptResults)window.getActivePage().showView(ServerScriptResults.ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
486 view.executeScript(tool.getData(), node.getAlarmId(), inputValues);
487 }
488 catch(Exception e)
489 {
490 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
491 }
492 }
493 }
494
495 /**
496 * @param node
497 * @param tool
498 * @param inputValues
499 * @param inputValues
500 */
501 private static void executeFileDownload(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
502 {
503 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
504 String[] parameters = tool.getData().split("\u007F"); //$NON-NLS-1$
505
506 final String fileName = parameters[0];
507 final int maxFileSize = Integer.parseInt(parameters[1]);
508 final boolean follow = parameters[2].equals("true") ? true : false; //$NON-NLS-1$
509
510 ConsoleJob job = new ConsoleJob(Messages.get().ObjectToolsDynamicMenu_DownloadFromAgent, null, Activator.PLUGIN_ID, null) {
511 @Override
512 protected String getErrorMessage()
513 {
514 return String.format(Messages.get().ObjectToolsDynamicMenu_DownloadError, fileName, node.object.getObjectName());
515 }
516
517 @Override
518 protected void runInternal(final IProgressMonitor monitor) throws Exception
519 {
520 final AgentFileData file = session.downloadFileFromAgent(node.object.getObjectId(), fileName, maxFileSize, follow, inputValues, node.getAlarmId(), new ProgressListener() {
521 @Override
522 public void setTotalWorkAmount(long workTotal)
523 {
524 monitor.beginTask("Download file " + fileName, (int)workTotal);
525 }
526
527 @Override
528 public void markProgress(long workDone)
529 {
530 monitor.worked((int)workDone);
531 }
532 });
533 runInUIThread(new Runnable() {
534 @Override
535 public void run()
536 {
537 try
538 {
539 String secondaryId = Long.toString(node.object.getObjectId()) + "&" + URLEncoder.encode(fileName, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
540 AgentFileViewer.createView(secondaryId, node.object.getObjectId(), file, follow);
541 }
542 catch(Exception e)
543 {
544 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
545 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
546 }
547 }
548 });
549 }
550 };
551 job.start();
552 }
553
554 /**
555 * @param node
556 * @param tool
557 */
558 private static void executeInternalTool(final ObjectContext node, final ObjectTool tool)
559 {
560 ObjectToolHandler handler = ObjectToolsCache.findHandler(tool.getData());
561 if (handler != null)
562 {
563 handler.execute(node.object, tool);
564 }
565 else
566 {
567 MessageDialogHelper.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), Messages.get().ObjectToolsDynamicMenu_Error, Messages.get().ObjectToolsDynamicMenu_HandlerNotDefined);
568 }
569 }
570
571 /**
572 * @param node
573 * @param tool
574 * @param inputValues
575 */
576 private static void openURL(final ObjectContext node, final ObjectTool tool, Map<String, String> inputValues, String url)
577 {
578 final UrlLauncher launcher = RWT.getClient().getService(UrlLauncher.class);
579 launcher.openURL(url);
580 }
581 }