8189ab3509960f4a863289f640b5df195eb8476d
[public/netxms.git] / src / java / netxms-eclipse / 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.io.IOException;
22 import java.net.URLEncoder;
23 import java.util.ArrayList;
24 import java.util.Arrays;
25 import java.util.Comparator;
26 import java.util.HashMap;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import org.eclipse.core.runtime.IProgressMonitor;
31 import org.eclipse.core.runtime.Platform;
32 import org.eclipse.jface.window.Window;
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.BrowserView;
51 import org.netxms.ui.eclipse.objecttools.views.LocalCommandResults;
52 import org.netxms.ui.eclipse.objecttools.views.ServerCommandResults;
53 import org.netxms.ui.eclipse.objecttools.views.ServerScriptResults;
54 import org.netxms.ui.eclipse.objecttools.views.TableToolResults;
55 import org.netxms.ui.eclipse.shared.ConsoleSharedData;
56 import org.netxms.ui.eclipse.tools.MessageDialogHelper;
57
58 /**
59 * Executor for object tool
60 */
61 public final class ObjectToolExecutor
62 {
63 /**
64 * Private constructor to forbid instantiation
65 */
66 private ObjectToolExecutor()
67 {
68 }
69
70 /**
71 * Check if tool is allowed for execution on each node from set
72 *
73 * @param tool
74 * @param nodes
75 * @return
76 */
77 public static boolean isToolAllowed(ObjectTool tool, Set<ObjectContext> nodes)
78 {
79 if (tool.getToolType() != ObjectTool.TYPE_INTERNAL)
80 return true;
81
82 ObjectToolHandler handler = ObjectToolsCache.findHandler(tool.getData());
83 if (handler != null)
84 {
85 for(ObjectContext n : nodes)
86 if (!handler.canExecuteOnNode(n.object, tool))
87 return false;
88 return true;
89 }
90 else
91 {
92 return false;
93 }
94 }
95
96 /**
97 * Check if given tool is applicable for all nodes in set
98 *
99 * @param tool
100 * @param nodes
101 * @return
102 */
103 public static boolean isToolApplicable(ObjectTool tool, Set<ObjectContext> nodes)
104 {
105 for(ObjectContext n : nodes)
106 if (!tool.isApplicableForNode(n.object))
107 return false;
108 return true;
109 }
110
111 /**
112 * Execute object tool on node set
113 *
114 * @param tool Object tool
115 */
116 public static void execute(final Set<ObjectContext> nodes, final ObjectTool tool)
117 {
118 final Map<String, String> inputValues;
119 final InputField[] fields = tool.getInputFields();
120 if (fields.length > 0)
121 {
122 Arrays.sort(fields, new Comparator<InputField>() {
123 @Override
124 public int compare(InputField f1, InputField f2)
125 {
126 return f1.getSequence() - f2.getSequence();
127 }
128 });
129 inputValues = readInputFields(fields);
130 if (inputValues == null)
131 return; // cancelled
132 }
133 else
134 {
135 inputValues = new HashMap<String, String>(0);
136 }
137 final NXCSession session = ConsoleSharedData.getSession();
138 new ConsoleJob(Messages.get().ObjectToolExecutor_JobName, null, Activator.PLUGIN_ID, null) {
139 @Override
140 protected void runInternal(IProgressMonitor monitor) throws Exception
141 {
142 List<String> expandedText = null;
143
144 if ((tool.getFlags() & ObjectTool.ASK_CONFIRMATION) != 0)
145 {
146 String message = tool.getConfirmationText();
147 if (nodes.size() == 1)
148 {
149 //Expand message and action for 1 node, otherwise expansion occurs after confirmation
150 List<String> textToExpand = new ArrayList<String>();
151 textToExpand.add(tool.getConfirmationText());
152 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
153 {
154 textToExpand.add(tool.getData());
155 }
156 ObjectContext node = nodes.iterator().next();
157 expandedText = session.substitureMacross(node, textToExpand, inputValues);
158
159 message = expandedText.remove(0);
160 }
161 else
162 {
163 ObjectContext node = nodes.iterator().next();
164 message = node.substituteMacrosForMultiNodes(message, inputValues);
165 }
166
167 ConfirmationRunnable runnable = new ConfirmationRunnable(message);
168 getDisplay().syncExec(runnable);
169 if(!runnable.isConfirmed())
170 return;
171
172 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
173 {
174 expandedText = session.substitureMacross(nodes.toArray(new ObjectContext[nodes.size()]), tool.getData(), inputValues);
175 }
176 }
177 else
178 {
179 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
180 {
181 expandedText = session.substitureMacross(nodes.toArray(new ObjectContext[nodes.size()]), tool.getData(), inputValues);
182 }
183 }
184
185 // Check if password validation needed
186 boolean validationNeeded = false;
187 for(int i = 0; i < fields.length; i++)
188 if (fields[i].getOptions().validatePassword)
189 {
190 validationNeeded = true;
191 break;
192 }
193
194 if (validationNeeded)
195 {
196 for(int i = 0; i < fields.length; i++)
197 {
198 if ((fields[i].getType() == InputFieldType.PASSWORD) && (fields[i].getOptions().validatePassword))
199 {
200 boolean valid = session.validateUserPassword(inputValues.get(fields[i].getName()));
201 if (!valid)
202 {
203 final String fieldName = fields[i].getDisplayName();
204 getDisplay().syncExec(new Runnable() {
205 @Override
206 public void run()
207 {
208 MessageDialogHelper.openError(null, Messages.get().ObjectToolExecutor_ErrorTitle,
209 String.format(Messages.get().ObjectToolExecutor_ErrorText, fieldName));
210 }
211 });
212 return;
213 }
214 }
215 }
216 }
217
218 int i = 0;
219 for(final ObjectContext n : nodes)
220 {
221 if(tool.getToolType() == ObjectTool.TYPE_URL || tool.getToolType() == ObjectTool.TYPE_LOCAL_COMMAND)
222 {
223 final String tmp = expandedText.get(i++);
224 getDisplay().syncExec(new Runnable() {
225
226 @Override
227 public void run()
228 {
229 executeOnNode(n, tool, inputValues, tmp);
230 }
231 });
232 }
233 else
234 {
235 getDisplay().syncExec(new Runnable() {
236
237 @Override
238 public void run()
239 {
240 executeOnNode(n, tool, inputValues, null);
241 }
242 });
243 }
244 }
245 }
246
247 @Override
248 protected String getErrorMessage()
249 {
250 return Messages.get().ObjectToolExecutor_PasswordValidationFailed;
251 }
252
253 class ConfirmationRunnable implements Runnable
254 {
255 private boolean confirmed;
256 private String message;
257
258 public ConfirmationRunnable(String message)
259 {
260 this.message = message;
261 }
262
263 @Override
264 public void run()
265 {
266 confirmed = MessageDialogHelper.openQuestion(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(),
267 Messages.get().ObjectToolsDynamicMenu_ConfirmExec, message);
268 }
269
270 boolean isConfirmed()
271 {
272 return confirmed;
273 }
274 }
275
276 }.start();
277 }
278
279 /**
280 * Read input fields
281 *
282 * @param fields
283 * @return
284 */
285 private static Map<String, String> readInputFields(InputField[] fields)
286 {
287 ObjectToolInputDialog dlg = new ObjectToolInputDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), fields);
288 if (dlg.open() != Window.OK)
289 return null;
290 return dlg.getValues();
291 }
292
293 /**
294 * Execute object tool on single node
295 *
296 * @param node
297 * @param tool
298 * @param inputValues
299 */
300 private static void executeOnNode(final ObjectContext node, final ObjectTool tool, Map<String, String> inputValues, String expandedValue)
301 {
302 switch(tool.getToolType())
303 {
304 case ObjectTool.TYPE_ACTION:
305 executeAgentAction(node, tool, inputValues);
306 break;
307 case ObjectTool.TYPE_FILE_DOWNLOAD:
308 executeFileDownload(node, tool, inputValues);
309 break;
310 case ObjectTool.TYPE_INTERNAL:
311 executeInternalTool(node, tool);
312 break;
313 case ObjectTool.TYPE_LOCAL_COMMAND:
314 executeLocalCommand(node, tool, inputValues, expandedValue);
315 break;
316 case ObjectTool.TYPE_SERVER_COMMAND:
317 executeServerCommand(node, tool, inputValues);
318 break;
319 case ObjectTool.TYPE_SERVER_SCRIPT:
320 executeServerScript(node, tool, inputValues);
321 break;
322 case ObjectTool.TYPE_TABLE_AGENT:
323 case ObjectTool.TYPE_TABLE_SNMP:
324 executeTableTool(node, tool);
325 break;
326 case ObjectTool.TYPE_URL:
327 openURL(node, tool, inputValues, expandedValue);
328 break;
329 }
330 }
331
332 /**
333 * Execute table tool
334 *
335 * @param node
336 * @param tool
337 */
338 private static void executeTableTool(final ObjectContext node, final ObjectTool tool)
339 {
340 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
341 try
342 {
343 final IWorkbenchPage page = window.getActivePage();
344 final TableToolResults view = (TableToolResults)page.showView(TableToolResults.ID,
345 Long.toString(tool.getId()) + "&" + Long.toString(node.object.getObjectId()), IWorkbenchPage.VIEW_ACTIVATE); //$NON-NLS-1$
346 view.refreshTable();
347 }
348 catch(PartInitException e)
349 {
350 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
351 }
352 }
353
354 /**
355 * @param node
356 * @param tool
357 * @param inputValues
358 */
359 private static void executeAgentAction(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
360 {
361 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
362
363 if ((tool.getFlags() & ObjectTool.GENERATES_OUTPUT) == 0)
364 {
365 new ConsoleJob(String.format(Messages.get().ObjectToolsDynamicMenu_ExecuteOnNode, node.object.getObjectName()), null, Activator.PLUGIN_ID, null) {
366 @Override
367 protected String getErrorMessage()
368 {
369 return String.format(Messages.get().ObjectToolsDynamicMenu_CannotExecuteOnNode, node.object.getObjectName());
370 }
371
372 @Override
373 protected void runInternal(IProgressMonitor monitor) throws Exception
374 {
375 final String action = session.executeActionWithExpansion(node.object.getObjectId(), node.getAlarmId(), tool.getData(), inputValues);
376 runInUIThread(new Runnable() {
377 @Override
378 public void run()
379 {
380 MessageDialogHelper.openInformation(null, Messages.get().ObjectToolsDynamicMenu_ToolExecution, String.format(Messages.get().ObjectToolsDynamicMenu_ExecSuccess, action, node.object.getObjectName()));
381 }
382 });
383 }
384 }.start();
385 }
386 else
387 {
388 final String secondaryId = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
389 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
390 try
391 {
392 AgentActionResults view = (AgentActionResults)window.getActivePage().showView(AgentActionResults.ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
393 view.executeAction(tool.getData(), node.getAlarmId(), inputValues);
394 }
395 catch(Exception e)
396 {
397 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
398 }
399 }
400 }
401
402 /**
403 * Execute server command
404 *
405 * @param node
406 * @param tool
407 * @param inputValues
408 */
409 private static void executeServerCommand(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
410 {
411 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
412 if ((tool.getFlags() & ObjectTool.GENERATES_OUTPUT) == 0)
413 {
414 new ConsoleJob(Messages.get().ObjectToolsDynamicMenu_ExecuteServerCmd, null, Activator.PLUGIN_ID, null) {
415 @Override
416 protected void runInternal(IProgressMonitor monitor) throws Exception
417 {
418 session.executeServerCommand(node.object.getObjectId(), tool.getData(), inputValues);
419 runInUIThread(new Runnable() {
420 @Override
421 public void run()
422 {
423 MessageDialogHelper.openInformation(null, Messages.get().ObjectToolsDynamicMenu_Information, Messages.get().ObjectToolsDynamicMenu_ServerCommandExecuted);
424 }
425 });
426 }
427
428 @Override
429 protected String getErrorMessage()
430 {
431 return Messages.get().ObjectToolsDynamicMenu_ServerCmdExecError;
432 }
433 }.start();
434 }
435 else
436 {
437 final String secondaryId = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
438 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
439 try
440 {
441 ServerCommandResults view = (ServerCommandResults)window.getActivePage().showView(ServerCommandResults.ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
442 view.executeCommand(tool.getData(), inputValues);
443 }
444 catch(Exception e)
445 {
446 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
447 }
448 }
449 }
450
451 /**
452 * Execute server script
453 *
454 * @param node
455 * @param tool
456 * @param inputValues
457 */
458 private static void executeServerScript(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
459 {
460 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
461 if ((tool.getFlags() & ObjectTool.GENERATES_OUTPUT) == 0)
462 {
463 new ConsoleJob("Execute server script", null, Activator.PLUGIN_ID, null) {
464 @Override
465 protected void runInternal(IProgressMonitor monitor) throws Exception
466 {
467 session.executeLibraryScript(node.object.getObjectId(), node.getAlarmId(), tool.getData(), inputValues, null);
468 runInUIThread(new Runnable() {
469 @Override
470 public void run()
471 {
472 MessageDialogHelper.openInformation(null, Messages.get().ObjectToolsDynamicMenu_Information, Messages.get().ObjectToolsDynamicMenu_ServerScriptExecuted);
473 }
474 });
475 }
476
477 @Override
478 protected String getErrorMessage()
479 {
480 return Messages.get().ObjectToolsDynamicMenu_ServerScriptExecError;
481 }
482 }.start();
483 }
484 else
485 {
486 final String secondaryId = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
487 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
488 try
489 {
490 ServerScriptResults view = (ServerScriptResults)window.getActivePage().showView(ServerScriptResults.ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
491 view.executeScript(tool.getData(), node.getAlarmId(), inputValues);
492 }
493 catch(Exception e)
494 {
495 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
496 }
497 }
498 }
499
500 /**
501 * Execute local command
502 *
503 * @param node
504 * @param tool
505 * @param inputValues
506 */
507 private static void executeLocalCommand(final ObjectContext node, final ObjectTool tool, Map<String, String> inputValues, String command)
508 {
509 if ((tool.getFlags() & ObjectTool.GENERATES_OUTPUT) == 0)
510 {
511 final String os = Platform.getOS();
512
513 try
514 {
515 if (os.equals(Platform.OS_WIN32))
516 {
517 command = "CMD.EXE /C START \"NetXMS\" " + command; //$NON-NLS-1$
518 Runtime.getRuntime().exec(command);
519 }
520 else
521 {
522 Runtime.getRuntime().exec(new String[] { "/bin/sh", "-c", command }); //$NON-NLS-1$ //$NON-NLS-2$
523 }
524 }
525 catch(IOException e)
526 {
527 // TODO Auto-generated catch block
528 e.printStackTrace();
529 }
530 }
531 else
532 {
533 final String secondaryId = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
534 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
535 try
536 {
537 LocalCommandResults view = (LocalCommandResults)window.getActivePage().showView(LocalCommandResults.ID, secondaryId, IWorkbenchPage.VIEW_ACTIVATE);
538 view.runCommand(command);
539 }
540 catch(Exception e)
541 {
542 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
543 }
544 }
545 }
546
547 /**
548 * @param node
549 * @param tool
550 * @param inputValues
551 */
552 private static void executeFileDownload(final ObjectContext node, final ObjectTool tool, final Map<String, String> inputValues)
553 {
554 final NXCSession session = (NXCSession)ConsoleSharedData.getSession();
555 String[] parameters = tool.getData().split("\u007F"); //$NON-NLS-1$
556
557 final String fileName = parameters[0];
558 final int maxFileSize = Integer.parseInt(parameters[1]);
559 final boolean follow = parameters[2].equals("true") ? true : false; //$NON-NLS-1$
560
561 ConsoleJob job = new ConsoleJob(Messages.get().ObjectToolsDynamicMenu_DownloadFromAgent, null, Activator.PLUGIN_ID, null) {
562 @Override
563 protected String getErrorMessage()
564 {
565 return String.format(Messages.get().ObjectToolsDynamicMenu_DownloadError, fileName, node.object.getObjectName());
566 }
567
568 @Override
569 protected void runInternal(final IProgressMonitor monitor) throws Exception
570 {
571 final AgentFileData file = session.downloadFileFromAgent(node.object.getObjectId(), fileName, maxFileSize, follow, inputValues, node.getAlarmId(), new ProgressListener() {
572 @Override
573 public void setTotalWorkAmount(long workTotal)
574 {
575 monitor.beginTask("Download file " + fileName, (int)workTotal);
576 }
577
578 @Override
579 public void markProgress(long workDone)
580 {
581 monitor.worked((int)workDone);
582 }
583 });
584 runInUIThread(new Runnable() {
585 @Override
586 public void run()
587 {
588 try
589 {
590 String secondaryId = Long.toString(node.object.getObjectId()) + "&" + URLEncoder.encode(fileName, "UTF-8"); //$NON-NLS-1$ //$NON-NLS-2$
591 AgentFileViewer.createView(secondaryId, node.object.getObjectId(), file, follow);
592 }
593 catch(Exception e)
594 {
595 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
596 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, String.format(Messages.get().ObjectToolsDynamicMenu_ErrorOpeningView, e.getLocalizedMessage()));
597 }
598 }
599 });
600 }
601 };
602 job.start();
603 }
604
605 /**
606 * @param node
607 * @param tool
608 */
609 private static void executeInternalTool(final ObjectContext node, final ObjectTool tool)
610 {
611 ObjectToolHandler handler = ObjectToolsCache.findHandler(tool.getData());
612 if (handler != null)
613 {
614 handler.execute(node.object, tool);
615 }
616 else
617 {
618 MessageDialogHelper.openError(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), Messages.get().ObjectToolsDynamicMenu_Error, Messages.get().ObjectToolsDynamicMenu_HandlerNotDefined);
619 }
620 }
621
622 /**
623 * @param node
624 * @param tool
625 * @param inputValues
626 */
627 private static void openURL(final ObjectContext node, final ObjectTool tool, Map<String, String> inputValues, String url)
628 {
629
630 final String sid = Long.toString(node.object.getObjectId()) + "&" + Long.toString(tool.getId()); //$NON-NLS-1$
631 final IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
632 try
633 {
634 BrowserView view = (BrowserView)window.getActivePage().showView(BrowserView.ID, sid, IWorkbenchPage.VIEW_ACTIVATE);
635 view.openUrl(url);
636 }
637 catch(PartInitException e)
638 {
639 MessageDialogHelper.openError(window.getShell(), Messages.get().ObjectToolsDynamicMenu_Error, Messages.get().ObjectToolsDynamicMenu_CannotOpenWebBrowser + e.getLocalizedMessage());
640 }
641 }
642 }