229042b8138515f5326f6d6601f8848029802fbe
[public/netxms.git] / src / java / netxms-client / src / main / java / org / netxms / client / NXCSession.java
1 /**
2 * NetXMS - open source network management system
3 * Copyright (C) 2003-2013 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.client;
20
21 import java.io.BufferedInputStream;
22 import java.io.ByteArrayInputStream;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileNotFoundException;
26 import java.io.IOException;
27 import java.io.InputStream;
28 import java.io.OutputStream;
29 import java.net.InetAddress;
30 import java.net.Socket;
31 import java.net.UnknownHostException;
32 import java.security.GeneralSecurityException;
33 import java.util.ArrayList;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.Comparator;
37 import java.util.Date;
38 import java.util.HashMap;
39 import java.util.HashSet;
40 import java.util.Iterator;
41 import java.util.List;
42 import java.util.Locale;
43 import java.util.Map;
44 import java.util.Map.Entry;
45 import java.util.Set;
46 import java.util.UUID;
47 import java.util.concurrent.Semaphore;
48 import java.util.concurrent.TimeUnit;
49 import java.util.concurrent.atomic.AtomicLong;
50 import java.util.regex.Matcher;
51 import java.util.regex.Pattern;
52 import org.netxms.api.client.NetXMSClientException;
53 import org.netxms.api.client.ProgressListener;
54 import org.netxms.api.client.Session;
55 import org.netxms.api.client.SessionListener;
56 import org.netxms.api.client.images.ImageLibraryManager;
57 import org.netxms.api.client.images.LibraryImage;
58 import org.netxms.api.client.mt.MappingTable;
59 import org.netxms.api.client.mt.MappingTableDescriptor;
60 import org.netxms.api.client.reporting.ReportDefinition;
61 import org.netxms.api.client.reporting.ReportParameter;
62 import org.netxms.api.client.reporting.ReportRenderFormat;
63 import org.netxms.api.client.reporting.ReportResult;
64 import org.netxms.api.client.reporting.ReportingServerManager;
65 import org.netxms.api.client.scripts.Script;
66 import org.netxms.api.client.scripts.ScriptLibraryManager;
67 import org.netxms.api.client.servermanager.ServerManager;
68 import org.netxms.api.client.servermanager.ServerVariable;
69 import org.netxms.api.client.users.AbstractUserObject;
70 import org.netxms.api.client.users.User;
71 import org.netxms.api.client.users.UserGroup;
72 import org.netxms.api.client.users.UserManager;
73 import org.netxms.base.CompatTools;
74 import org.netxms.base.EncryptionContext;
75 import org.netxms.base.GeoLocation;
76 import org.netxms.base.Logger;
77 import org.netxms.base.NXCPCodes;
78 import org.netxms.base.NXCPDataInputStream;
79 import org.netxms.base.NXCPException;
80 import org.netxms.base.NXCPMessage;
81 import org.netxms.base.NXCPMessageReceiver;
82 import org.netxms.base.NXCPMsgWaitQueue;
83 import org.netxms.base.NXCommon;
84 import org.netxms.client.constants.RCC;
85 import org.netxms.client.dashboards.DashboardElement;
86 import org.netxms.client.datacollection.ConditionDciInfo;
87 import org.netxms.client.datacollection.DataCollectionConfiguration;
88 import org.netxms.client.datacollection.DataCollectionItem;
89 import org.netxms.client.datacollection.DciData;
90 import org.netxms.client.datacollection.DciDataRow;
91 import org.netxms.client.datacollection.DciPushData;
92 import org.netxms.client.datacollection.DciSummaryTable;
93 import org.netxms.client.datacollection.DciSummaryTableDescriptor;
94 import org.netxms.client.datacollection.DciValue;
95 import org.netxms.client.datacollection.GraphSettings;
96 import org.netxms.client.datacollection.PerfTabDci;
97 import org.netxms.client.datacollection.Threshold;
98 import org.netxms.client.datacollection.ThresholdViolationSummary;
99 import org.netxms.client.datacollection.TransformationTestResult;
100 import org.netxms.client.datacollection.WinPerfObject;
101 import org.netxms.client.events.Alarm;
102 import org.netxms.client.events.AlarmNote;
103 import org.netxms.client.events.Event;
104 import org.netxms.client.events.EventInfo;
105 import org.netxms.client.events.EventProcessingPolicy;
106 import org.netxms.client.events.EventProcessingPolicyRule;
107 import org.netxms.client.events.EventTemplate;
108 import org.netxms.client.events.SyslogRecord;
109 import org.netxms.client.log.Log;
110 import org.netxms.client.maps.NetworkMapLink;
111 import org.netxms.client.maps.NetworkMapPage;
112 import org.netxms.client.maps.elements.NetworkMapElement;
113 import org.netxms.client.maps.elements.NetworkMapObject;
114 import org.netxms.client.objects.AbstractObject;
115 import org.netxms.client.objects.AccessPoint;
116 import org.netxms.client.objects.AgentPolicy;
117 import org.netxms.client.objects.AgentPolicyConfig;
118 import org.netxms.client.objects.BusinessService;
119 import org.netxms.client.objects.BusinessServiceRoot;
120 import org.netxms.client.objects.Cluster;
121 import org.netxms.client.objects.ClusterResource;
122 import org.netxms.client.objects.ClusterSyncNetwork;
123 import org.netxms.client.objects.Condition;
124 import org.netxms.client.objects.Container;
125 import org.netxms.client.objects.Dashboard;
126 import org.netxms.client.objects.DashboardRoot;
127 import org.netxms.client.objects.EntireNetwork;
128 import org.netxms.client.objects.GenericObject;
129 import org.netxms.client.objects.Interface;
130 import org.netxms.client.objects.MobileDevice;
131 import org.netxms.client.objects.NetworkMap;
132 import org.netxms.client.objects.NetworkMapGroup;
133 import org.netxms.client.objects.NetworkMapRoot;
134 import org.netxms.client.objects.NetworkService;
135 import org.netxms.client.objects.Node;
136 import org.netxms.client.objects.NodeLink;
137 import org.netxms.client.objects.PolicyGroup;
138 import org.netxms.client.objects.PolicyRoot;
139 import org.netxms.client.objects.Rack;
140 import org.netxms.client.objects.Report;
141 import org.netxms.client.objects.ReportGroup;
142 import org.netxms.client.objects.ReportRoot;
143 import org.netxms.client.objects.ServiceCheck;
144 import org.netxms.client.objects.ServiceRoot;
145 import org.netxms.client.objects.Subnet;
146 import org.netxms.client.objects.Template;
147 import org.netxms.client.objects.TemplateGroup;
148 import org.netxms.client.objects.TemplateRoot;
149 import org.netxms.client.objects.UnknownObject;
150 import org.netxms.client.objects.Zone;
151 import org.netxms.client.objecttools.ObjectTool;
152 import org.netxms.client.objecttools.ObjectToolDetails;
153 import org.netxms.client.packages.PackageDeploymentListener;
154 import org.netxms.client.packages.PackageInfo;
155 import org.netxms.client.situations.Situation;
156 import org.netxms.client.snmp.SnmpTrap;
157 import org.netxms.client.snmp.SnmpTrapLogRecord;
158 import org.netxms.client.snmp.SnmpUsmCredential;
159 import org.netxms.client.snmp.SnmpValue;
160 import org.netxms.client.snmp.SnmpWalkListener;
161 import org.netxms.client.topology.ConnectionPoint;
162 import org.netxms.client.topology.NetworkPath;
163 import org.netxms.client.topology.VlanInfo;
164 import org.netxms.client.topology.WirelessStation;
165
166 /**
167 * Communication session with NetXMS server.
168 */
169 public class NXCSession implements Session, ScriptLibraryManager, UserManager, ServerManager, ImageLibraryManager, ReportingServerManager
170 {
171 // Various public constants
172 public static final int DEFAULT_CONN_PORT = 4701;
173 public static final int CLIENT_PROTOCOL_VERSION = 36;
174
175 // Authentication types
176 public static final int AUTH_TYPE_PASSWORD = 0;
177 public static final int AUTH_TYPE_CERTIFICATE = 1;
178 public static final int AUTH_TYPE_TOKEN = 2;
179
180 // Notification channels
181 public static final int CHANNEL_EVENTS = 0x0001;
182 public static final int CHANNEL_SYSLOG = 0x0002;
183 public static final int CHANNEL_ALARMS = 0x0004;
184 public static final int CHANNEL_OBJECTS = 0x0008;
185 public static final int CHANNEL_SNMP_TRAPS = 0x0010;
186 public static final int CHANNEL_AUDIT_LOG = 0x0020;
187 public static final int CHANNEL_SITUATIONS = 0x0040;
188
189 // Object sync options
190 public static final int OBJECT_SYNC_NOTIFY = 0x0001;
191 public static final int OBJECT_SYNC_WAIT = 0x0002;
192
193 // Configuration import options
194 public static final int CFG_IMPORT_REPLACE_EVENT_BY_CODE = 0x0001;
195 public static final int CFG_IMPORT_REPLACE_EVENT_BY_NAME = 0x0002;
196
197 // Address list IDs
198 public static final int ADDRESS_LIST_DISCOVERY_TARGETS = 1;
199 public static final int ADDRESS_LIST_DISCOVERY_FILTER = 2;
200
201 // Server components
202 public static final int SERVER_COMPONENT_DISCOVERY_MANAGER = 1;
203
204 // Client types
205 public static final int DESKTOP_CLIENT = 0;
206 public static final int WEB_CLIENT = 1;
207 public static final int MOBILE_CLIENT = 2;
208 public static final int TABLET_CLIENT = 3;
209 public static final int APPLICATION_CLIENT = 4;
210
211 // Private constants
212 private static final int CLIENT_CHALLENGE_SIZE = 256;
213 private static final int MAX_DCI_DATA_ROWS = 200000;
214 private static final int MAX_DCI_STRING_VALUE_LENGTH = 256;
215 private static final int RECEIVED_FILE_TTL = 300000; // 300 seconds
216 private static final int FILE_BUFFER_SIZE = 128 * 1024; // 128k
217
218 // Internal synchronization objects
219 private final Semaphore syncObjects = new Semaphore(1);
220 private final Semaphore syncUserDB = new Semaphore(1);
221
222 // Connection-related attributes
223 private String connAddress;
224 private int connPort;
225 private String connLoginName;
226 private String connPassword;
227 private boolean connUseEncryption;
228 private String connClientInfo = "nxjclient/" + NXCommon.VERSION;
229 private int clientType = DESKTOP_CLIENT;
230
231 // Information about logged in user
232 private int sessionId;
233 private int userId;
234 private int userSystemRights;
235 private boolean passwordExpired;
236
237 // Internal communication data
238 private Socket connSocket = null;
239 private NXCPMsgWaitQueue msgWaitQueue = null;
240 private ReceiverThread recvThread = null;
241 private HousekeeperThread housekeeperThread = null;
242 private AtomicLong requestId = new AtomicLong(1);
243 private boolean isConnected = false;
244 private boolean serverConsoleConnected = false;
245 private EncryptionContext encryptionContext = null;
246
247 // Communication parameters
248 private int recvBufferSize = 4194304; // Default is 4MB
249 private int commandTimeout = 30000; // Default is 30 sec
250
251 // Notification listeners
252 private Set<SessionListener> listeners = new HashSet<SessionListener>(0);
253 private Set<ServerConsoleListener> consoleListeners = new HashSet<ServerConsoleListener>(0);
254
255 // Received files
256 private Map<Long, NXCReceivedFile> receivedFiles = new HashMap<Long, NXCReceivedFile>();
257
258 // Server information
259 private String serverVersion = "(unknown)";
260 private byte[] serverId = new byte[8];
261 private String serverTimeZone;
262 private byte[] serverChallenge = new byte[CLIENT_CHALLENGE_SIZE];
263 private boolean zoningEnabled = false;
264 private String tileServerURL;
265 private String dateFormat;
266 private String timeFormat;
267 private int defaultDciRetentionTime;
268 private int defaultDciPollingInterval;
269
270 // Objects
271 private Map<Long, AbstractObject> objectList = new HashMap<Long, AbstractObject>();
272 private boolean objectsSynchronized = false;
273
274 // Users
275 private Map<Long, AbstractUserObject> userDB = new HashMap<Long, AbstractUserObject>();
276
277 // Event templates
278 private Map<Long, EventTemplate> eventTemplates = new HashMap<Long, EventTemplate>();
279 private boolean eventTemplatesNeedSync = false;
280
281 /**
282 * Convert IP address to 32 bit integer
283 *
284 * @param addr
285 * @return
286 */
287 private long int32FromInetAddress(InetAddress addr)
288 {
289 byte[] bytes = addr.getAddress();
290 return ((long)bytes[0] << 24) | ((long)bytes[1] << 16) | ((long)bytes[2] << 8) | (long)bytes[3];
291 }
292
293 /**
294 * Create custom object from NXCP message. May be overridden by derived classes to create custom
295 * NetXMS objects. This method called before standard object creation, so it can be used for
296 * overriding standard object classes. If this method returns null, standard object
297 * creation mechanism will be used. Default implementation will always return null.
298 *
299 * @param objectClass NetXMS object class ID
300 * @param msg Source NXCP message
301 * @return NetXMS object or null if object cannot be created
302 */
303 protected AbstractObject createCustomObjectFromMessage(int objectClass, NXCPMessage msg)
304 {
305 return null;
306 }
307
308 /**
309 * Create object from message
310 *
311 * @param msg Source NXCP message
312 * @return NetXMS object
313 */
314 private AbstractObject createObjectFromMessage(NXCPMessage msg)
315 {
316 final int objectClass = msg.getVariableAsInteger(NXCPCodes.VID_OBJECT_CLASS);
317
318 AbstractObject object = createCustomObjectFromMessage(objectClass, msg);
319 if (object != null)
320 return object;
321
322 switch(objectClass)
323 {
324 case AbstractObject.OBJECT_INTERFACE:
325 object = new Interface(msg, this);
326 break;
327 case AbstractObject.OBJECT_SUBNET:
328 object = new Subnet(msg, this);
329 break;
330 case AbstractObject.OBJECT_CONTAINER:
331 object = new Container(msg, this);
332 break;
333 case AbstractObject.OBJECT_RACK:
334 object = new Rack(msg, this);
335 break;
336 case AbstractObject.OBJECT_CONDITION:
337 object = new Condition(msg, this);
338 break;
339 case AbstractObject.OBJECT_MOBILEDEVICE:
340 object = new MobileDevice(msg, this);
341 break;
342 case AbstractObject.OBJECT_NODE:
343 object = new Node(msg, this);
344 break;
345 case AbstractObject.OBJECT_ACCESSPOINT:
346 object = new AccessPoint(msg, this);
347 break;
348 case AbstractObject.OBJECT_CLUSTER:
349 object = new Cluster(msg, this);
350 break;
351 case AbstractObject.OBJECT_TEMPLATE:
352 object = new Template(msg, this);
353 break;
354 case AbstractObject.OBJECT_TEMPLATEROOT:
355 object = new TemplateRoot(msg, this);
356 break;
357 case AbstractObject.OBJECT_TEMPLATEGROUP:
358 object = new TemplateGroup(msg, this);
359 break;
360 case AbstractObject.OBJECT_NETWORK:
361 object = new EntireNetwork(msg, this);
362 break;
363 case AbstractObject.OBJECT_SERVICEROOT:
364 object = new ServiceRoot(msg, this);
365 break;
366 case AbstractObject.OBJECT_POLICYROOT:
367 object = new PolicyRoot(msg, this);
368 break;
369 case AbstractObject.OBJECT_POLICYGROUP:
370 object = new PolicyGroup(msg, this);
371 break;
372 case AbstractObject.OBJECT_AGENTPOLICY:
373 object = new AgentPolicy(msg, this);
374 break;
375 case AbstractObject.OBJECT_AGENTPOLICY_CONFIG:
376 object = new AgentPolicyConfig(msg, this);
377 break;
378 case AbstractObject.OBJECT_NETWORKMAPROOT:
379 object = new NetworkMapRoot(msg, this);
380 break;
381 case AbstractObject.OBJECT_NETWORKMAPGROUP:
382 object = new NetworkMapGroup(msg, this);
383 break;
384 case AbstractObject.OBJECT_NETWORKMAP:
385 object = new NetworkMap(msg, this);
386 break;
387 case AbstractObject.OBJECT_DASHBOARDROOT:
388 object = new DashboardRoot(msg, this);
389 break;
390 case AbstractObject.OBJECT_DASHBOARD:
391 object = new Dashboard(msg, this);
392 break;
393 case AbstractObject.OBJECT_ZONE:
394 object = new Zone(msg, this);
395 break;
396 case AbstractObject.OBJECT_NETWORKSERVICE:
397 object = new NetworkService(msg, this);
398 break;
399 case AbstractObject.OBJECT_REPORTROOT:
400 object = new ReportRoot(msg, this);
401 break;
402 case AbstractObject.OBJECT_REPORTGROUP:
403 object = new ReportGroup(msg, this);
404 break;
405 case AbstractObject.OBJECT_REPORT:
406 object = new Report(msg, this);
407 break;
408 case AbstractObject.OBJECT_BUSINESSSERVICEROOT:
409 object = new BusinessServiceRoot(msg, this);
410 break;
411 case AbstractObject.OBJECT_BUSINESSSERVICE:
412 object = new BusinessService(msg, this);
413 break;
414 case AbstractObject.OBJECT_NODELINK:
415 object = new NodeLink(msg, this);
416 break;
417 case AbstractObject.OBJECT_SLMCHECK:
418 object = new ServiceCheck(msg, this);
419 break;
420 default:
421 object = new GenericObject(msg, this);
422 break;
423 }
424
425 return object;
426 }
427
428 /**
429 * Setup encryption
430 *
431 * @param msg CMD_REQUEST_SESSION_KEY message
432 * @throws IOException
433 * @throws NXCException
434 */
435 private void setupEncryption(NXCPMessage msg) throws IOException, NXCException
436 {
437 final NXCPMessage response = new NXCPMessage(NXCPCodes.CMD_SESSION_KEY, msg.getMessageId());
438 response.setEncryptionDisabled(true);
439
440 try
441 {
442 encryptionContext = EncryptionContext.createInstance(msg);
443 response.setVariable(NXCPCodes.VID_SESSION_KEY, encryptionContext.getEncryptedSessionKey(msg));
444 response.setVariable(NXCPCodes.VID_SESSION_IV, encryptionContext.getEncryptedIv(msg));
445 response.setVariableInt16(NXCPCodes.VID_CIPHER, encryptionContext.getCipher());
446 response.setVariableInt16(NXCPCodes.VID_KEY_LENGTH, encryptionContext.getKeyLength());
447 response.setVariableInt16(NXCPCodes.VID_IV_LENGTH, encryptionContext.getIvLength());
448 response.setVariableInt32(NXCPCodes.VID_RCC, RCC.SUCCESS);
449 }
450 catch(Exception e)
451 {
452 response.setVariableInt32(NXCPCodes.VID_RCC, RCC.NO_CIPHERS);
453 }
454
455 sendMessage(response);
456 }
457
458 /**
459 * Receiver thread for NXCSession
460 */
461 private class ReceiverThread extends Thread
462 {
463 ReceiverThread()
464 {
465 setDaemon(true);
466 start();
467 }
468
469 @Override
470 public void run()
471 {
472 final NXCPMessageReceiver receiver = new NXCPMessageReceiver(recvBufferSize);
473 InputStream in;
474
475 try
476 {
477 in = connSocket.getInputStream();
478 }
479 catch(IOException e)
480 {
481 return; // Stop receiver thread if input stream cannot be obtained
482 }
483
484 while(connSocket.isConnected())
485 {
486 try
487 {
488 final NXCPMessage msg = receiver.receiveMessage(in, encryptionContext);
489 switch(msg.getMessageCode())
490 {
491 case NXCPCodes.CMD_REQUEST_SESSION_KEY:
492 setupEncryption(msg);
493 break;
494 case NXCPCodes.CMD_OBJECT:
495 case NXCPCodes.CMD_OBJECT_UPDATE:
496 if (!msg.getVariableAsBoolean(NXCPCodes.VID_IS_DELETED))
497 {
498 final AbstractObject obj = createObjectFromMessage(msg);
499 synchronized(objectList)
500 {
501 objectList.put(obj.getObjectId(), obj);
502 }
503 if (msg.getMessageCode() == NXCPCodes.CMD_OBJECT_UPDATE)
504 {
505 sendNotification(new NXCNotification(NXCNotification.OBJECT_CHANGED, obj.getObjectId(), obj));
506 }
507 }
508 else
509 {
510 long objectId = msg.getVariableAsInteger(NXCPCodes.VID_OBJECT_ID);
511 synchronized(objectList)
512 {
513 objectList.remove(objectId);
514 }
515 sendNotification(new NXCNotification(NXCNotification.OBJECT_DELETED, objectId));
516 }
517 break;
518 case NXCPCodes.CMD_OBJECT_LIST_END:
519 completeSync(syncObjects);
520 break;
521 case NXCPCodes.CMD_USER_DATA:
522 final User user = new User(msg);
523 synchronized(userDB)
524 {
525 if (user.isDeleted())
526 userDB.remove(user.getId());
527 else
528 userDB.put(user.getId(), user);
529 }
530 break;
531 case NXCPCodes.CMD_GROUP_DATA:
532 final UserGroup group = new UserGroup(msg);
533 synchronized(userDB)
534 {
535 if (group.isDeleted())
536 userDB.remove(group.getId());
537 else
538 userDB.put(group.getId(), group);
539 }
540 break;
541 case NXCPCodes.CMD_USER_DB_EOF:
542 completeSync(syncUserDB);
543 break;
544 case NXCPCodes.CMD_USER_DB_UPDATE:
545 processUserDBUpdate(msg);
546 break;
547 case NXCPCodes.CMD_ALARM_UPDATE:
548 sendNotification(new NXCNotification(msg.getVariableAsInteger(NXCPCodes.VID_NOTIFICATION_CODE)
549 + NXCNotification.NOTIFY_BASE, new Alarm(msg)));
550 break;
551 case NXCPCodes.CMD_JOB_CHANGE_NOTIFICATION:
552 sendNotification(new NXCNotification(NXCNotification.JOB_CHANGE, new ServerJob(msg)));
553 break;
554 case NXCPCodes.CMD_FILE_DATA:
555 processFileData(msg);
556 break;
557 case NXCPCodes.CMD_ABORT_FILE_TRANSFER:
558 processFileTransferError(msg);
559 break;
560 case NXCPCodes.CMD_NOTIFY:
561 processNotificationMessage(msg);
562 break;
563 case NXCPCodes.CMD_EVENTLOG_RECORDS:
564 processNewEvents(msg);
565 break;
566 case NXCPCodes.CMD_TRAP_LOG_RECORDS:
567 processNewTraps(msg);
568 break;
569 case NXCPCodes.CMD_SYSLOG_RECORDS:
570 processSyslogRecords(msg);
571 break;
572 case NXCPCodes.CMD_ACTION_DB_UPDATE:
573 processActionConfigChange(msg);
574 break;
575 case NXCPCodes.CMD_EVENT_DB_UPDATE:
576 processEventConfigChange(msg);
577 break;
578 case NXCPCodes.CMD_TRAP_CFG_UPDATE:
579 processTrapConfigChange(msg);
580 break;
581 case NXCPCodes.CMD_SITUATION_CHANGE:
582 processSituationChange(msg);
583 break;
584 case NXCPCodes.CMD_ADM_MESSAGE:
585 processConsoleOutput(msg);
586 break;
587 case NXCPCodes.CMD_IMAGE_LIBRARY_UPDATE:
588 processImageLibraryUpdate(msg);
589 break;
590 default:
591 if (msg.getMessageCode() >= 0x1000)
592 {
593 // Custom message
594 sendNotification(new NXCNotification(NXCNotification.CUSTOM_MESSAGE, msg));
595 }
596 msgWaitQueue.putMessage(msg);
597 break;
598 }
599 }
600 catch(IOException e)
601 {
602 break; // Stop on read errors
603 }
604 catch(NXCPException e)
605 {
606 if (e.getErrorCode() == NXCPException.SESSION_CLOSED)
607 break;
608 }
609 catch(NXCException e)
610 {
611 if (e.getErrorCode() == RCC.ENCRYPTION_ERROR)
612 break;
613 }
614 }
615 }
616
617 /**
618 * Process server console output
619 *
620 * @param msg
621 * notification message
622 */
623 private void processConsoleOutput(NXCPMessage msg)
624 {
625 final String text = msg.getVariableAsString(NXCPCodes.VID_MESSAGE);
626 synchronized(consoleListeners)
627 {
628 for(ServerConsoleListener l : consoleListeners)
629 l.onConsoleOutput(text);
630 }
631 }
632
633 /**
634 * Process event notification messages.
635 *
636 * @param msg NXCP message
637 */
638 private void processNewEvents(final NXCPMessage msg)
639 {
640 int count = msg.getVariableAsInteger(NXCPCodes.VID_NUM_RECORDS);
641 int order = msg.getVariableAsInteger(NXCPCodes.VID_RECORDS_ORDER);
642 long varId = NXCPCodes.VID_EVENTLOG_MSG_BASE;
643 for(int i = 0; i < count; i++)
644 {
645 Event event = new Event(msg, varId);
646 sendNotification(new NXCNotification(NXCNotification.NEW_EVENTLOG_RECORD, order, event));
647 }
648 }
649
650 /**
651 * Process SNMP trap notification messages.
652 *
653 * @param msg NXCP message
654 */
655 private void processNewTraps(final NXCPMessage msg)
656 {
657 int count = msg.getVariableAsInteger(NXCPCodes.VID_NUM_RECORDS);
658 int order = msg.getVariableAsInteger(NXCPCodes.VID_RECORDS_ORDER);
659 long varId = NXCPCodes.VID_TRAP_LOG_MSG_BASE;
660 for(int i = 0; i < count; i++)
661 {
662 SnmpTrapLogRecord trap = new SnmpTrapLogRecord(msg, varId);
663 sendNotification(new NXCNotification(NXCNotification.NEW_SNMP_TRAP, order, trap));
664 }
665 }
666
667 /**
668 * Process syslog messages.
669 *
670 * @param msg NXCP message
671 */
672 private void processSyslogRecords(final NXCPMessage msg)
673 {
674 int count = msg.getVariableAsInteger(NXCPCodes.VID_NUM_RECORDS);
675 int order = msg.getVariableAsInteger(NXCPCodes.VID_RECORDS_ORDER);
676 long varId = NXCPCodes.VID_SYSLOG_MSG_BASE;
677 for(int i = 0; i < count; i++)
678 {
679 SyslogRecord record = new SyslogRecord(msg, varId);
680 sendNotification(new NXCNotification(NXCNotification.NEW_SYSLOG_RECORD, order, record));
681 }
682 }
683
684 /**
685 * Process CMD_NOTIFY message
686 *
687 * @param msg
688 * NXCP message
689 */
690 private void processNotificationMessage(final NXCPMessage msg)
691 {
692 int code = msg.getVariableAsInteger(NXCPCodes.VID_NOTIFICATION_CODE) + NXCNotification.NOTIFY_BASE;
693 long data = msg.getVariableAsInt64(NXCPCodes.VID_NOTIFICATION_DATA);
694 sendNotification(new NXCNotification(code, data));
695 }
696
697 /**
698 * Process file data
699 *
700 * @param msg
701 */
702 private void processFileData(final NXCPMessage msg)
703 {
704 long id = msg.getMessageId();
705 NXCReceivedFile file;
706 synchronized(receivedFiles)
707 {
708 file = receivedFiles.get(id);
709 if (file == null)
710 {
711 file = new NXCReceivedFile(id);
712 receivedFiles.put(id, file);
713 }
714 }
715 file.writeData(msg.getBinaryData());
716 if (msg.isEndOfFile())
717 {
718 file.close();
719 synchronized(receivedFiles)
720 {
721 receivedFiles.notifyAll();
722 }
723 }
724 }
725
726 /**
727 * Process file transfer error
728 *
729 * @param msg
730 */
731 private void processFileTransferError(final NXCPMessage msg)
732 {
733 long id = msg.getMessageId();
734 NXCReceivedFile file;
735 synchronized(receivedFiles)
736 {
737 file = receivedFiles.get(id);
738 if (file == null)
739 {
740 file = new NXCReceivedFile(id);
741 receivedFiles.put(id, file);
742 }
743 file.close();
744 receivedFiles.notifyAll();
745 }
746 }
747
748 /**
749 * Process updates in user database
750 *
751 * @param msg
752 * Notification message
753 */
754 private void processUserDBUpdate(final NXCPMessage msg)
755 {
756 final int code = msg.getVariableAsInteger(NXCPCodes.VID_UPDATE_TYPE);
757 final long id = msg.getVariableAsInt64(NXCPCodes.VID_USER_ID);
758
759 AbstractUserObject object = null;
760 switch(code)
761 {
762 case NXCNotification.USER_DB_OBJECT_CREATED:
763 case NXCNotification.USER_DB_OBJECT_MODIFIED:
764 object = ((id & 0x80000000) != 0) ? new UserGroup(msg) : new User(msg);
765 synchronized(userDB)
766 {
767 userDB.put(id, object);
768 }
769 break;
770 case NXCNotification.USER_DB_OBJECT_DELETED:
771 synchronized(userDB)
772 {
773 object = userDB.get(id);
774 if (object != null)
775 {
776 userDB.remove(id);
777 }
778 }
779 break;
780 }
781
782 // Send notification if changed object was found in local database copy
783 // or added to it and notification code was known
784 if (object != null)
785 sendNotification(new NXCNotification(NXCNotification.USER_DB_CHANGED, code, object));
786 }
787
788 /**
789 * Process server notification on SNMP trap configuration change
790 *
791 * @param msg
792 * notification message
793 */
794 private void processTrapConfigChange(final NXCPMessage msg)
795 {
796 int code = msg.getVariableAsInteger(NXCPCodes.VID_NOTIFICATION_CODE) + NXCNotification.NOTIFY_BASE;
797 long id = msg.getVariableAsInt64(NXCPCodes.VID_TRAP_ID);
798 SnmpTrap trap = (code != NXCNotification.TRAP_CONFIGURATION_DELETED) ? new SnmpTrap(msg) : null;
799 sendNotification(new NXCNotification(code, id, trap));
800 }
801
802 /**
803 * Process server notification on situation object change
804 *
805 * @param msg
806 * notification message
807 */
808 private void processSituationChange(final NXCPMessage msg)
809 {
810 int code = msg.getVariableAsInteger(NXCPCodes.VID_NOTIFICATION_CODE) + NXCNotification.SITUATION_BASE;
811 Situation s = new Situation(msg);
812 sendNotification(new NXCNotification(code, s.getId(), s));
813 }
814
815 /**
816 * Process server notification on action configuration change
817 *
818 * @param msg
819 * notification message
820 */
821 private void processActionConfigChange(final NXCPMessage msg)
822 {
823 int code = msg.getVariableAsInteger(NXCPCodes.VID_NOTIFICATION_CODE) + NXCNotification.NOTIFY_BASE;
824 long id = msg.getVariableAsInt64(NXCPCodes.VID_ACTION_ID);
825 ServerAction action = (code != NXCNotification.ACTION_DELETED) ? new ServerAction(msg) : null;
826 sendNotification(new NXCNotification(code, id, action));
827 }
828
829 /**
830 * Process server notification on event configuration change
831 *
832 * @param msg
833 * notification message
834 */
835 private void processEventConfigChange(final NXCPMessage msg)
836 {
837 int code = msg.getVariableAsInteger(NXCPCodes.VID_NOTIFICATION_CODE) + NXCNotification.NOTIFY_BASE;
838 long eventCode = msg.getVariableAsInt64(NXCPCodes.VID_EVENT_CODE);
839 EventTemplate et = (code != NXCNotification.EVENT_TEMPLATE_DELETED) ? new EventTemplate(msg) : null;
840 if (eventTemplatesNeedSync)
841 {
842 synchronized(eventTemplates)
843 {
844 if (code == NXCNotification.EVENT_TEMPLATE_DELETED)
845 eventTemplates.remove(eventCode);
846 else
847 eventTemplates.put(eventCode, et);
848 }
849 }
850 sendNotification(new NXCNotification(code, eventCode, et));
851 }
852
853 /**
854 * Process server notification on image library change
855 *
856 * @param msg
857 * notification message
858 */
859 public void processImageLibraryUpdate(NXCPMessage msg)
860 {
861 final UUID imageGuid = msg.getVariableAsUUID(NXCPCodes.VID_GUID);
862 final int flags = msg.getVariableAsInteger(NXCPCodes.VID_FLAGS);
863 sendNotification(new NXCNotification(NXCNotification.IMAGE_LIBRARY_CHANGED, flags == 0 ? NXCNotification.IMAGE_UPDATED
864 : NXCNotification.IMAGE_DELETED, imageGuid));
865 }
866 }
867
868 /**
869 * Housekeeper thread - cleans received files, etc.
870 *
871 * @author Victor
872 *
873 */
874 private class HousekeeperThread extends Thread
875 {
876 private boolean stopFlag = false;
877
878 HousekeeperThread()
879 {
880 setDaemon(true);
881 start();
882 }
883
884 /*
885 * (non-Javadoc)
886 *
887 * @see java.lang.Thread#run()
888 */
889 @Override
890 public void run()
891 {
892 while(!stopFlag)
893 {
894 try
895 {
896 sleep(1000);
897 }
898 catch(InterruptedException e)
899 {
900 }
901
902 // Check for old entries in received files
903 synchronized(receivedFiles)
904 {
905 long currTime = System.currentTimeMillis();
906 Iterator<NXCReceivedFile> it = receivedFiles.values().iterator();
907 while(it.hasNext())
908 {
909 NXCReceivedFile file = it.next();
910 if (file.getTimestamp() + RECEIVED_FILE_TTL < currTime)
911 {
912 file.getFile().delete();
913 it.remove();
914 }
915 }
916 }
917 }
918 }
919
920 /**
921 * @param stopFlag
922 * the stopFlag to set
923 */
924 public void setStopFlag(boolean stopFlag)
925 {
926 this.stopFlag = stopFlag;
927 }
928 }
929
930 //
931 // Constructors
932 //
933
934 /**
935 * @param connAddress
936 * @param connLoginName
937 * @param connPassword
938 */
939 public NXCSession(String connAddress, String connLoginName, String connPassword)
940 {
941 this.connAddress = connAddress;
942 this.connPort = DEFAULT_CONN_PORT;
943 this.connLoginName = connLoginName;
944 this.connPassword = connPassword;
945 this.connUseEncryption = false;
946 }
947
948 /**
949 * @param connAddress
950 * @param connPort
951 * @param connLoginName
952 * @param connPassword
953 */
954 public NXCSession(String connAddress, int connPort, String connLoginName, String connPassword)
955 {
956 this.connAddress = connAddress;
957 this.connPort = connPort;
958 this.connLoginName = connLoginName;
959 this.connPassword = connPassword;
960 this.connUseEncryption = false;
961 }
962
963 /**
964 * @param connAddress
965 * @param connPort
966 * @param connLoginName
967 * @param connPassword
968 * @param connUseEncryption
969 */
970 public NXCSession(String connAddress, int connPort, String connLoginName, String connPassword, boolean connUseEncryption)
971 {
972 this.connAddress = connAddress;
973 this.connPort = connPort;
974 this.connLoginName = connLoginName;
975 this.connPassword = connPassword;
976 this.connUseEncryption = connUseEncryption;
977 }
978
979 /*
980 * (non-Javadoc)
981 *
982 * @see java.lang.Object#finalize()
983 */
984 @Override
985 protected void finalize()
986 {
987 disconnect();
988 }
989
990 /**
991 * Wait for synchronization completion
992 */
993 private void waitForSync(final Semaphore syncObject, final int timeout) throws NXCException
994 {
995 if (timeout == 0)
996 {
997 syncObject.acquireUninterruptibly();
998 }
999 else
1000 {
1001 long actualTimeout = timeout;
1002 boolean success = false;
1003
1004 while(actualTimeout > 0)
1005 {
1006 long startTime = System.currentTimeMillis();
1007 try
1008 {
1009 if (syncObjects.tryAcquire(actualTimeout, TimeUnit.MILLISECONDS))
1010 {
1011 success = true;
1012 syncObjects.release();
1013 break;
1014 }
1015 }
1016 catch(InterruptedException e)
1017 {
1018 }
1019 actualTimeout -= System.currentTimeMillis() - startTime;
1020 }
1021 if (!success)
1022 throw new NXCException(RCC.TIMEOUT);
1023 }
1024 }
1025
1026 /**
1027 * Report synchronization completion
1028 *
1029 * @param syncObject
1030 * Synchronization object
1031 */
1032 private void completeSync(final Semaphore syncObject)
1033 {
1034 syncObject.release();
1035 }
1036
1037 /*
1038 * (non-Javadoc)
1039 *
1040 * @see org.netxms.api.client.Session#addListener(org.netxms.api.client.
1041 * SessionListener)
1042 */
1043 @Override
1044 public void addListener(SessionListener listener)
1045 {
1046 synchronized(listeners)
1047 {
1048 listeners.add(listener);
1049 }
1050 }
1051
1052 /*
1053 * (non-Javadoc)
1054 *
1055 * @see org.netxms.api.client.Session#removeListener(org.netxms.api.client.
1056 * SessionListener)
1057 */
1058 @Override
1059 public void removeListener(SessionListener listener)
1060 {
1061 synchronized(listeners)
1062 {
1063 listeners.remove(listener);
1064 }
1065 }
1066
1067 /**
1068 * Add server console listener
1069 *
1070 * @param listener
1071 */
1072 public void addConsoleListener(ServerConsoleListener listener)
1073 {
1074 synchronized(consoleListeners)
1075 {
1076 consoleListeners.add(listener);
1077 }
1078 }
1079
1080 /**
1081 * Remove server console listener
1082 *
1083 * @param listener
1084 */
1085 public void removeConsoleListener(ServerConsoleListener listener)
1086 {
1087 synchronized(consoleListeners)
1088 {
1089 consoleListeners.remove(listener);
1090 }
1091 }
1092
1093 /**
1094 * Call notification handlers on all registered listeners
1095 *
1096 * @param n
1097 * Notification object
1098 */
1099 protected void sendNotification(NXCNotification n)
1100 {
1101 synchronized(listeners)
1102 {
1103 Iterator<SessionListener> it = listeners.iterator();
1104 while(it.hasNext())
1105 {
1106 it.next().notificationHandler(n);
1107 }
1108 }
1109 }
1110
1111 /**
1112 * Send message to server
1113 *
1114 * @param msg
1115 * Message to sent
1116 * @throws IOException in case of socket communication failure
1117 * @throws NXCException in case of encryption error
1118 */
1119 public synchronized void sendMessage(final NXCPMessage msg) throws IOException, NXCException
1120 {
1121 if (connSocket == null)
1122 {
1123 throw new IllegalStateException("Not connected to the server. Did you forgot to call connect() first?");
1124 }
1125 final OutputStream outputStream = connSocket.getOutputStream();
1126 byte[] message;
1127 if ((encryptionContext != null) && !msg.isEncryptionDisabled())
1128 {
1129 try
1130 {
1131 message = encryptionContext.encryptMessage(msg);
1132 }
1133 catch(GeneralSecurityException e)
1134 {
1135 throw new NXCException(RCC.ENCRYPTION_ERROR);
1136 }
1137 }
1138 else
1139 {
1140 message = msg.createNXCPMessage();
1141 }
1142 outputStream.write(message);
1143 }
1144
1145 /**
1146 * Send file over CSCP
1147 *
1148 * @param requestId
1149 * @param file
1150 * source file to be sent
1151 * @throws IOException
1152 * @throws NXCException
1153 */
1154 protected void sendFile(final long requestId, final File file, ProgressListener listener) throws IOException, NXCException
1155 {
1156 if (listener != null)
1157 listener.setTotalWorkAmount(file.length());
1158 final InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
1159 sendFileStream(requestId, inputStream, listener);
1160 inputStream.close();
1161 }
1162
1163 /**
1164 * Send block of data as binary message
1165 *
1166 * @param requestId
1167 * @param data
1168 * @throws IOException
1169 * @throws NXCException
1170 */
1171 protected void sendFile(final long requestId, final byte[] data, ProgressListener listener) throws IOException, NXCException
1172 {
1173 if (listener != null)
1174 listener.setTotalWorkAmount(data.length);
1175 final InputStream inputStream = new ByteArrayInputStream(data);
1176 sendFileStream(requestId, inputStream, listener);
1177 inputStream.close();
1178 }
1179
1180 /**
1181 * Send binary message, data loaded from provided input stream and splitted
1182 * into chunks of {@value FILE_BUFFER_SIZE} bytes
1183 *
1184 * @param requestId
1185 * @param inputStream
1186 * @throws IOException
1187 * @throws NXCException
1188 */
1189 private void sendFileStream(final long requestId, final InputStream inputStream, ProgressListener listener) throws IOException,
1190 NXCException
1191 {
1192 NXCPMessage msg = new NXCPMessage(NXCPCodes.CMD_FILE_DATA, requestId);
1193 msg.setBinaryMessage(true);
1194
1195 boolean success = false;
1196 final byte[] buffer = new byte[FILE_BUFFER_SIZE];
1197 long bytesSent = 0;
1198 while(true)
1199 {
1200 final int bytesRead = inputStream.read(buffer);
1201 if (bytesRead < FILE_BUFFER_SIZE)
1202 {
1203 msg.setEndOfFile(true);
1204 }
1205
1206 msg.setBinaryData(CompatTools.arrayCopy(buffer, bytesRead));
1207 sendMessage(msg);
1208
1209 bytesSent += bytesRead;
1210 if (listener != null)
1211 listener.markProgress(bytesSent);
1212
1213 if (bytesRead < FILE_BUFFER_SIZE)
1214 {
1215 success = true;
1216 break;
1217 }
1218 }
1219
1220 if (!success)
1221 {
1222 NXCPMessage abortMessage = new NXCPMessage(NXCPCodes.CMD_ABORT_FILE_TRANSFER, requestId);
1223 abortMessage.setBinaryMessage(true);
1224 sendMessage(abortMessage);
1225 waitForRCC(abortMessage.getMessageId());
1226 }
1227 }
1228
1229 /*
1230 * (non-Javadoc)
1231 *
1232 * @see org.netxms.api.client.Session#waitForMessage(int, long, int)
1233 */
1234 @Override
1235 public NXCPMessage waitForMessage(final int code, final long id, final int timeout) throws NXCException
1236 {
1237 final NXCPMessage msg = msgWaitQueue.waitForMessage(code, id, timeout);
1238 if (msg == null)
1239 throw new NXCException(RCC.TIMEOUT);
1240 return msg;
1241 }
1242
1243 /*
1244 * (non-Javadoc)
1245 *
1246 * @see org.netxms.api.client.Session#waitForMessage(int, long)
1247 */
1248 @Override
1249 public NXCPMessage waitForMessage(final int code, final long id) throws NXCException
1250 {
1251 final NXCPMessage msg = msgWaitQueue.waitForMessage(code, id);
1252 if (msg == null)
1253 throw new NXCException(RCC.TIMEOUT);
1254 return msg;
1255 }
1256
1257 /*
1258 * (non-Javadoc)
1259 *
1260 * @see org.netxms.api.client.Session#waitForRCC(long)
1261 */
1262 @Override
1263 public NXCPMessage waitForRCC(final long id) throws NXCException
1264 {
1265 return waitForRCC(id, msgWaitQueue.getDefaultTimeout());
1266 }
1267
1268 /*
1269 * (non-Javadoc)
1270 *
1271 * @see org.netxms.api.client.Session#waitForRCC(long, int)
1272 */
1273 public NXCPMessage waitForRCC(final long id, final int timeout) throws NXCException
1274 {
1275 final NXCPMessage msg = waitForMessage(NXCPCodes.CMD_REQUEST_COMPLETED, id, timeout);
1276 final int rcc = msg.getVariableAsInteger(NXCPCodes.VID_RCC);
1277 if (rcc != RCC.SUCCESS)
1278 {
1279 if ((rcc == RCC.COMPONENT_LOCKED) && (msg.findVariable(NXCPCodes.VID_LOCKED_BY) != null))
1280 {
1281 throw new NXCException(rcc, "locked by " + msg.getVariableAsString(NXCPCodes.VID_LOCKED_BY));
1282 }
1283 else if (msg.findVariable(NXCPCodes.VID_ERROR_TEXT) != null)
1284 {
1285 throw new NXCException(rcc, msg.getVariableAsString(NXCPCodes.VID_ERROR_TEXT));
1286 }
1287 else
1288 {
1289 throw new NXCException(rcc);
1290 }
1291 }
1292 return msg;
1293 }
1294
1295 /*
1296 * (non-Javadoc)
1297 *
1298 * @see org.netxms.api.client.Session#newMessage(int)
1299 */
1300 @Override
1301 public final NXCPMessage newMessage(int code)
1302 {
1303 return new NXCPMessage(code, requestId.getAndIncrement());
1304 }
1305
1306 /**
1307 * Wait for specific file to arrive
1308 *
1309 * @param id
1310 * Message ID
1311 * @param timeout
1312 * Wait timeout in milliseconds
1313 * @return Received file or null in case of failure
1314 */
1315 public File waitForFile(final long id, final int timeout)
1316 {
1317 int timeRemaining = timeout;
1318 File file = null;
1319
1320 while(timeRemaining > 0)
1321 {
1322 synchronized(receivedFiles)
1323 {
1324 NXCReceivedFile rf = receivedFiles.get(id);
1325 if (rf != null)
1326 {
1327 if (rf.getStatus() != NXCReceivedFile.OPEN)
1328 {
1329 if (rf.getStatus() == NXCReceivedFile.RECEIVED)
1330 file = rf.getFile();
1331 break;
1332 }
1333 }
1334
1335 long startTime = System.currentTimeMillis();
1336 try
1337 {
1338 receivedFiles.wait(timeRemaining);
1339 }
1340 catch(InterruptedException e)
1341 {
1342 }
1343 timeRemaining -= System.currentTimeMillis() - startTime;
1344 }
1345 }
1346 return file;
1347 }
1348
1349 /**
1350 * Execute simple commands (without arguments and only returning RCC)
1351 *
1352 * @param command
1353 * Command code
1354 * @throws IOException
1355 * @throws NXCException
1356 */
1357 protected void executeSimpleCommand(int command) throws IOException, NXCException
1358 {
1359 final NXCPMessage msg = newMessage(command);
1360 sendMessage(msg);
1361 waitForRCC(msg.getMessageId());
1362 }
1363
1364 /**
1365 * Receive table from server.
1366 *
1367 * @param requestId
1368 * request ID
1369 * @param msgCode
1370 * Message code
1371 * @return Received table
1372 * @throws NXCException
1373 * if operation was timed out
1374 */
1375 public Table receiveTable(long requestId, int msgCode) throws NXCException
1376 {
1377 NXCPMessage msg = waitForMessage(msgCode, requestId);
1378 Table table = new Table(msg);
1379 while(!msg.isEndOfSequence())
1380 {
1381 msg = waitForMessage(msgCode, requestId);
1382 table.addDataFromMessage(msg);
1383 }
1384 return table;
1385 }
1386
1387 /*
1388 * (non-Javadoc)
1389 *
1390 * @see org.netxms.api.client.Session#connect()
1391 */
1392 @Override
1393 public void connect() throws IOException, UnknownHostException, NetXMSClientException
1394 {
1395 Logger.info("NXCSession.connect", "Connecting to " + connAddress + ":" + connPort);
1396 try
1397 {
1398 connSocket = new Socket(connAddress, connPort);
1399 msgWaitQueue = new NXCPMsgWaitQueue(commandTimeout);
1400 recvThread = new ReceiverThread();
1401 housekeeperThread = new HousekeeperThread();
1402
1403 // get server information
1404 Logger.debug("NXCSession.connect", "connection established, retrieving server info");
1405 NXCPMessage request = newMessage(NXCPCodes.CMD_GET_SERVER_INFO);
1406 sendMessage(request);
1407 NXCPMessage response = waitForMessage(NXCPCodes.CMD_REQUEST_COMPLETED, request.getMessageId());
1408
1409 if (response.getVariableAsInteger(NXCPCodes.VID_PROTOCOL_VERSION) != CLIENT_PROTOCOL_VERSION)
1410 {
1411 Logger.warning("NXCSession.connect",
1412 "connection failed, server protocol version is " + response.getVariableAsInteger(NXCPCodes.VID_PROTOCOL_VERSION));
1413 throw new NXCException(RCC.BAD_PROTOCOL);
1414 }
1415
1416 serverVersion = response.getVariableAsString(NXCPCodes.VID_SERVER_VERSION);
1417 serverId = response.getVariableAsBinary(NXCPCodes.VID_SERVER_ID);
1418 serverTimeZone = response.getVariableAsString(NXCPCodes.VID_TIMEZONE);
1419 serverChallenge = response.getVariableAsBinary(NXCPCodes.VID_CHALLENGE);
1420
1421 tileServerURL = response.getVariableAsString(NXCPCodes.VID_TILE_SERVER_URL);
1422 if (tileServerURL != null)
1423 {
1424 if (!tileServerURL.endsWith("/"))
1425 tileServerURL = tileServerURL.concat("/");
1426 }
1427 else
1428 {
1429 tileServerURL = "http://tile.openstreetmap.org/";
1430 }
1431
1432 dateFormat = response.getVariableAsString(NXCPCodes.VID_DATE_FORMAT);
1433 if ((dateFormat == null) || (dateFormat.length() == 0))
1434 dateFormat = "dd.MM.yyyy";
1435
1436 timeFormat = response.getVariableAsString(NXCPCodes.VID_TIME_FORMAT);
1437 if ((timeFormat == null) || (timeFormat.length() == 0))
1438 timeFormat = "HH:mm:ss";
1439
1440 // Setup encryption if required
1441 if (connUseEncryption)
1442 {
1443 request = newMessage(NXCPCodes.CMD_REQUEST_ENCRYPTION);
1444 request.setVariableInt16(NXCPCodes.VID_USE_X509_KEY_FORMAT, 1);
1445 sendMessage(request);
1446 waitForRCC(request.getMessageId());
1447 }
1448
1449 // Login to server
1450 Logger.debug("NXCSession.connect", "Connected to server version " + serverVersion + ", trying to login");
1451 request = newMessage(NXCPCodes.CMD_LOGIN);
1452 request.setVariable(NXCPCodes.VID_LOGIN_NAME, connLoginName);
1453 request.setVariable(NXCPCodes.VID_PASSWORD, connPassword);
1454 request.setVariableInt16(NXCPCodes.VID_AUTH_TYPE, AUTH_TYPE_PASSWORD);
1455 request.setVariable(NXCPCodes.VID_LIBNXCL_VERSION, NXCommon.VERSION);
1456 request.setVariable(NXCPCodes.VID_CLIENT_INFO, connClientInfo);
1457 request.setVariable(NXCPCodes.VID_OS_INFO, System.getProperty("os.name") + " " + System.getProperty("os.version"));
1458 request.setVariableInt16(NXCPCodes.VID_CLIENT_TYPE, clientType);
1459 sendMessage(request);
1460 response = waitForMessage(NXCPCodes.CMD_LOGIN_RESP, request.getMessageId());
1461 int rcc = response.getVariableAsInteger(NXCPCodes.VID_RCC);
1462 Logger.debug("NXCSession.connect", "CMD_LOGIN_RESP received, RCC=" + rcc);
1463 if (rcc != RCC.SUCCESS)
1464 {
1465 Logger.warning("NXCSession.connect", "Login failed, RCC=" + rcc);
1466 throw new NXCException(rcc);
1467 }
1468 userId = response.getVariableAsInteger(NXCPCodes.VID_USER_ID);
1469 sessionId = response.getVariableAsInteger(NXCPCodes.VID_SESSION_ID);
1470 userSystemRights = response.getVariableAsInteger(NXCPCodes.VID_USER_SYS_RIGHTS);
1471 passwordExpired = response.getVariableAsBoolean(NXCPCodes.VID_CHANGE_PASSWD_FLAG);
1472 zoningEnabled = response.getVariableAsBoolean(NXCPCodes.VID_ZONING_ENABLED);
1473
1474 defaultDciPollingInterval = response.getVariableAsInteger(NXCPCodes.VID_POLLING_INTERVAL);
1475 if (defaultDciPollingInterval == 0)
1476 defaultDciPollingInterval = 60;
1477
1478 defaultDciRetentionTime = response.getVariableAsInteger(NXCPCodes.VID_RETENTION_TIME);
1479 if (defaultDciRetentionTime == 0)
1480 defaultDciRetentionTime = 30;
1481
1482 Logger.info("NXCSession.connect", "succesfully connected and logged in, userId=" + userId);
1483 isConnected = true;
1484 }
1485 finally
1486 {
1487 if (!isConnected)
1488 disconnect();
1489 }
1490 }
1491
1492 /*
1493 * (non-Javadoc)
1494 *
1495 * @see org.netxms.client.Session#disconnect()
1496 */
1497 @Override
1498 public void disconnect()
1499 {
1500 if (connSocket != null)
1501 {
1502 try
1503 {
1504 connSocket.shutdownInput();
1505 connSocket.shutdownOutput();
1506 }
1507 catch(IOException e)
1508 {
1509 }
1510
1511 try
1512 {
1513 connSocket.close();
1514 }
1515 catch(IOException e)
1516 {
1517 }
1518 }
1519
1520 if (recvThread != null)
1521 {
1522 while(recvThread.isAlive())
1523 {
1524 try
1525 {
1526 recvThread.join();
1527 }
1528 catch(InterruptedException e)
1529 {
1530 }
1531 }
1532 recvThread = null;
1533 }
1534
1535 if (housekeeperThread != null)
1536 {
1537 housekeeperThread.setStopFlag(true);
1538 while(housekeeperThread.isAlive())
1539 {
1540 try
1541 {
1542 housekeeperThread.join();
1543 }
1544 catch(InterruptedException e)
1545 {
1546 }
1547 }
1548 housekeeperThread = null;
1549 }
1550
1551 connSocket = null;
1552
1553 if (msgWaitQueue != null)
1554 {
1555 msgWaitQueue.shutdown();
1556 msgWaitQueue = null;
1557 }
1558
1559 isConnected = false;
1560 }
1561
1562 /*
1563 * (non-Javadoc)
1564 *
1565 * @see org.netxms.api.client.Session#getRecvBufferSize()
1566 */
1567 @Override
1568 public int getRecvBufferSize()
1569 {
1570 return recvBufferSize;
1571 }
1572
1573 /*
1574 * (non-Javadoc)
1575 *
1576 * @see org.netxms.api.client.Session#setRecvBufferSize(int)
1577 */
1578 @Override
1579 public void setRecvBufferSize(int recvBufferSize)
1580 {
1581 this.recvBufferSize = recvBufferSize;
1582 }
1583
1584 /*
1585 * (non-Javadoc)
1586 *
1587 * @see org.netxms.api.client.Session#getServerAddress()
1588 */
1589 @Override
1590 public String getServerAddress()
1591 {
1592 return connAddress;
1593 }
1594
1595 /*
1596 * (non-Javadoc)
1597 *
1598 * @see org.netxms.api.client.Session#getUserName()
1599 */
1600 @Override
1601 public String getUserName()
1602 {
1603 return connLoginName;
1604 }
1605
1606 /*
1607 * (non-Javadoc)
1608 *
1609 * @see org.netxms.api.client.Session#getServerVersion()
1610 */
1611 @Override
1612 public String getServerVersion()
1613 {
1614 return serverVersion;
1615 }
1616
1617 /*
1618 * (non-Javadoc)
1619 *
1620 * @see org.netxms.api.client.Session#getServerId()
1621 */
1622 @Override
1623 public byte[] getServerId()
1624 {
1625 return serverId;
1626 }
1627
1628 /*
1629 * (non-Javadoc)
1630 *
1631 * @see org.netxms.api.client.Session#getServerTimeZone()
1632 */
1633 @Override
1634 public String getServerTimeZone()
1635 {
1636 return serverTimeZone;
1637 }
1638
1639 /**
1640 * @return the serverChallenge
1641 */
1642 public byte[] getServerChallenge()
1643 {
1644 return serverChallenge;
1645 }
1646
1647 /**
1648 * @return the tileServerURL
1649 */
1650 public String getTileServerURL()
1651 {
1652 return tileServerURL;
1653 }
1654
1655 /**
1656 * @return the zoningEnabled
1657 */
1658 public boolean isZoningEnabled()
1659 {
1660 return zoningEnabled;
1661 }
1662
1663 /*
1664 * (non-Javadoc)
1665 *
1666 * @see org.netxms.api.client.Session#getConnClientInfo()
1667 */
1668 @Override
1669 public String getConnClientInfo()
1670 {
1671 return connClientInfo;
1672 }
1673
1674 /*
1675 * (non-Javadoc)
1676 *
1677 * @see org.netxms.api.client.Session#setConnClientInfo(java.lang.String)
1678 */
1679 @Override
1680 public void setConnClientInfo(final String connClientInfo)
1681 {
1682 this.connClientInfo = connClientInfo;
1683 }
1684
1685 /*
1686 * (non-Javadoc)
1687 *
1688 * @see org.netxms.api.client.Session#setCommandTimeout(int)
1689 */
1690 @Override
1691 public void setCommandTimeout(final int commandTimeout)
1692 {
1693 this.commandTimeout = commandTimeout;
1694 }
1695
1696 /*
1697 * (non-Javadoc)
1698 *
1699 * @see org.netxms.api.client.Session#getUserId()
1700 */
1701 @Override
1702 public int getUserId()
1703 {
1704 return userId;
1705 }
1706
1707 /*
1708 * (non-Javadoc)
1709 *
1710 * @see org.netxms.api.client.Session#getUserSystemRights()
1711 */
1712 @Override
1713 public int getUserSystemRights()
1714 {
1715 return userSystemRights;
1716 }
1717
1718 /*
1719 * (non-Javadoc)
1720 *
1721 * @see org.netxms.api.client.Session#isPasswordExpired()
1722 */
1723 @Override
1724 public boolean isPasswordExpired()
1725 {
1726 return passwordExpired;
1727 }
1728
1729 /**
1730 * Synchronizes NetXMS objects between server and client. After successful
1731 * sync, subscribe client to object change notifications.
1732 *
1733 * @throws IOException
1734 * if socket I/O error occurs
1735 * @throws NXCException
1736 * if NetXMS server returns an error or operation was timed out
1737 */
1738 public synchronized void syncObjects() throws IOException, NXCException
1739 {
1740 syncObjects.acquireUninterruptibly();
1741 NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_OBJECTS);
1742 msg.setVariableInt16(NXCPCodes.VID_SYNC_COMMENTS, 1);
1743 sendMessage(msg);
1744 waitForRCC(msg.getMessageId());
1745 waitForSync(syncObjects, commandTimeout * 10);
1746 objectsSynchronized = true;
1747 sendNotification(new NXCNotification(NXCNotification.OBJECT_SYNC_COMPLETED));
1748 subscribe(CHANNEL_OBJECTS);
1749 }
1750
1751 /**
1752 * Synchronizes selected object set with the server.
1753 *
1754 * @param objects identifiers of objects need to be synchronized
1755 * @param syncComments if true, comments for objects will be synchronized as well
1756 * @throws IOException if socket I/O error occurs
1757 * @throws NXCException if NetXMS server returns an error or operation was timed out
1758 */
1759 public void syncObjectSet(long[] objects, boolean syncComments) throws IOException, NXCException
1760 {
1761 syncObjectSet(objects, syncComments, 0);
1762 }
1763
1764 /**
1765 * Synchronizes selected object set with the server. The following options are accepted:
1766 * OBJECT_SYNC_NOTIFY - send object update notification for each received object
1767 * OBJECT_SYNC_WAIT - wait until all requested objects received
1768 *
1769 * @param objects identifiers of objects need to be synchronized
1770 * @param syncComments if true, comments for objects will be synchronized as well
1771 * @param options sync options (see above)
1772 * @throws IOException if socket I/O error occurs
1773 * @throws NXCException if NetXMS server returns an error or operation was timed out
1774 */
1775 public void syncObjectSet(long[] objects, boolean syncComments, int options) throws IOException, NXCException
1776 {
1777 NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_SELECTED_OBJECTS);
1778 msg.setVariableInt16(NXCPCodes.VID_SYNC_COMMENTS, syncComments ? 1 : 0);
1779 msg.setVariableInt16(NXCPCodes.VID_FLAGS, options);
1780 msg.setVariableInt32(NXCPCodes.VID_NUM_OBJECTS, objects.length);
1781 msg.setVariable(NXCPCodes.VID_OBJECT_LIST, objects);
1782 sendMessage(msg);
1783 waitForRCC(msg.getMessageId());
1784
1785 if ((options & OBJECT_SYNC_WAIT) != 0)
1786 waitForRCC(msg.getMessageId());
1787 }
1788
1789 /**
1790 * Synchronize only those objects from given set which are not synchronized yet.
1791 *
1792 * @param objects identifiers of objects need to be synchronized
1793 * @param syncComments if true, comments for objects will be synchronized as well
1794 * @throws IOException if socket I/O error occurs
1795 * @throws NXCException if NetXMS server returns an error or operation was timed out
1796 */
1797 public void syncMissingObjects(long[] objects, boolean syncComments) throws IOException, NXCException
1798 {
1799 syncMissingObjects(objects, syncComments, 0);
1800 }
1801
1802 /**
1803 * Synchronize only those objects from given set which are not synchronized yet.
1804 * Accepts all options which are valid for syncObjectSet.
1805 *
1806 * @param objects identifiers of objects need to be synchronized
1807 * @param syncComments if true, comments for objects will be synchronized as well
1808 * @param options sync options (see comments for syncObjectSet)
1809 * @throws IOException if socket I/O error occurs
1810 * @throws NXCException if NetXMS server returns an error or operation was timed out
1811 */
1812 public void syncMissingObjects(long[] objects, boolean syncComments, int options) throws IOException, NXCException
1813 {
1814 final long[] syncList = CompatTools.arrayCopy(objects, objects.length);
1815 int count = syncList.length;
1816 synchronized(objectList)
1817 {
1818 for(int i = 0; i < syncList.length; i++)
1819 {
1820 if (objectList.containsKey(syncList[i]))
1821 {
1822 syncList[i] = 0;
1823 count--;
1824 }
1825 }
1826 }
1827
1828 if (count > 0)
1829 syncObjectSet(syncList, syncComments, options);
1830 }
1831
1832 /**
1833 * Find NetXMS object by it's identifier.
1834 *
1835 * @param id Object identifier
1836 * @return Object with given ID or null if object cannot be found
1837 */
1838 public AbstractObject findObjectById(final long id)
1839 {
1840 AbstractObject obj;
1841
1842 synchronized(objectList)
1843 {
1844 obj = objectList.get(id);
1845 }
1846 return obj;
1847 }
1848
1849 /**
1850 * Find NetXMS object by it's identifier with additional class checking.
1851 *
1852 * @param id object identifier
1853 * @param requiredClass required object class
1854 * @return Object with given ID or null if object cannot be found or is not an instance of required class
1855 */
1856 public AbstractObject findObjectById(final long id, final Class<? extends AbstractObject> requiredClass)
1857 {
1858 AbstractObject object = findObjectById(id);
1859 return requiredClass.isInstance(object) ? object : null;
1860 }
1861
1862 /**
1863 * Find multiple NetXMS objects by identifiers
1864 *
1865 * @param idList array of object identifiers
1866 * @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
1867 * @return list of found objects
1868 */
1869 public List<AbstractObject> findMultipleObjects(final long[] idList, boolean returnUnknown)
1870 {
1871 return findMultipleObjects(idList, null, returnUnknown);
1872 }
1873
1874 /**
1875 * Find multiple NetXMS objects by identifiers
1876 *
1877 * @param idList array of object identifiers
1878 * @param classFilter class filter for objects, or null to disable filtering
1879 * @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
1880 * @return list of found objects
1881 */
1882 public List<AbstractObject> findMultipleObjects(final long[] idList, Class<? extends AbstractObject> classFilter,
1883 boolean returnUnknown)
1884 {
1885 List<AbstractObject> result = new ArrayList<AbstractObject>(idList.length);
1886
1887 synchronized(objectList)
1888 {
1889 for(int i = 0; i < idList.length; i++)
1890 {
1891 final AbstractObject object = objectList.get(idList[i]);
1892 if ((object != null) && ((classFilter == null) || classFilter.isInstance(object)))
1893 {
1894 result.add(object);
1895 }
1896 else if (returnUnknown)
1897 {
1898 result.add(new UnknownObject(idList[i], this));
1899 }
1900 }
1901 }
1902
1903 return result;
1904 }
1905
1906 /**
1907 * Find multiple NetXMS objects by identifiers
1908 *
1909 * @param idList array of object identifiers
1910 * @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
1911 * @return array of found objects
1912 */
1913 public List<AbstractObject> findMultipleObjects(final Long[] idList, boolean returnUnknown)
1914 {
1915 return findMultipleObjects(idList, null, returnUnknown);
1916 }
1917
1918 /**
1919 * Find multiple NetXMS objects by identifiers
1920 *
1921 * @param idList array of object identifiers
1922 * @param classFilter class filter for objects, or null to disable filtering
1923 * @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
1924 * @return array of found objects
1925 */
1926 public List<AbstractObject> findMultipleObjects(final Long[] idList, Class<? extends AbstractObject> classFilter,
1927 boolean returnUnknown)
1928 {
1929 List<AbstractObject> result = new ArrayList<AbstractObject>(idList.length);
1930
1931 synchronized(objectList)
1932 {
1933 for(int i = 0; i < idList.length; i++)
1934 {
1935 final AbstractObject object = objectList.get(idList[i]);
1936 if ((object != null) && ((classFilter == null) || classFilter.isInstance(object)))
1937 {
1938 result.add(object);
1939 }
1940 else if (returnUnknown)
1941 {
1942 result.add(new UnknownObject(idList[i], this));
1943 }
1944 }
1945 }
1946
1947 return result;
1948 }
1949
1950 /**
1951 * Find object by name. If multiple objects with same name exist,
1952 * it is not determined what object will be returned. Name comparison
1953 * is case-insensitive.
1954 *
1955 * @param name object name to find
1956 * @return object with matching name or null
1957 */
1958 public AbstractObject findObjectByName(final String name)
1959 {
1960 AbstractObject result = null;
1961 synchronized(objectList)
1962 {
1963 for(AbstractObject object : objectList.values())
1964 {
1965 if (object.getObjectName().equalsIgnoreCase(name))
1966 {
1967 result = object;
1968 break;
1969 }
1970 }
1971 }
1972 return result;
1973 }
1974
1975 /**
1976 * Find object by name using regular expression. If multiple objects with same name exist,
1977 * it is not determined what object will be returned. Name comparison is case-insensitive.
1978 *
1979 * @param pattern regular expression for matching object name
1980 * @return object with matching name or null
1981 */
1982 public AbstractObject findObjectByNamePattern(final String pattern)
1983 {
1984 AbstractObject result = null;
1985 Matcher matcher = Pattern.compile(pattern).matcher("");
1986 synchronized(objectList)
1987 {
1988 for(AbstractObject object : objectList.values())
1989 {
1990 matcher.reset(object.getObjectName());
1991 if (matcher.matches())
1992 {
1993 result = object;
1994 break;
1995 }
1996 }
1997 }
1998 return result;
1999 }
2000
2001 /**
2002 * Get list of top-level objects matching given class filter. Class filter
2003 * may be null to ignore object class.
2004 *
2005 * @return List of all top matching level objects (either without parents or with
2006 * inaccessible parents)
2007 */
2008 public AbstractObject[] getTopLevelObjects(Set<Integer> classFilter)
2009 {
2010 HashSet<AbstractObject> list = new HashSet<AbstractObject>();
2011 synchronized(objectList)
2012 {
2013 for(AbstractObject object : objectList.values())
2014 {
2015 if ((classFilter != null) && !classFilter.contains(object.getObjectClass()))
2016 continue;
2017
2018 if (!object.hasParents())
2019 {
2020 list.add(object);
2021 }
2022 else
2023 {
2024 boolean hasParents = false;
2025 Iterator<Long> it = object.getParents();
2026 while(it.hasNext())
2027 {
2028 Long parent = it.next();
2029 if (classFilter != null)
2030 {
2031 AbstractObject p = objectList.get(parent);
2032 if ((p != null) && classFilter.contains(p.getObjectClass()))
2033 {
2034 hasParents = true;
2035 break;
2036 }
2037 }
2038 else
2039 {
2040 if (objectList.containsKey(parent))
2041 {
2042 hasParents = true;
2043 break;
2044 }
2045 }
2046 }
2047 if (!hasParents)
2048 list.add(object);
2049 }
2050 }
2051 }
2052 return list.toArray(new AbstractObject[list.size()]);
2053 }
2054
2055 /**
2056 * Get list of top-level objects.
2057 *
2058 * @return List of all top level objects (either without parents or with
2059 * inaccessible parents)
2060 */
2061 public AbstractObject[] getTopLevelObjects()
2062 {
2063 return getTopLevelObjects(null);
2064 }
2065
2066 /**
2067 * Get list of all objects
2068 *
2069 * @return List of all objects
2070 */
2071 public AbstractObject[] getAllObjects()
2072 {
2073 AbstractObject[] list;
2074
2075 synchronized(objectList)
2076 {
2077 list = objectList.values().toArray(new AbstractObject[objectList.size()]);
2078 }
2079 return list;
2080 }
2081
2082 /**
2083 * Get object name by ID.
2084 *
2085 * @param objectId object ID
2086 * @return object name if object is known, or string in form [<object_id>] for unknown objects
2087 */
2088 public String getObjectName(long objectId)
2089 {
2090 AbstractObject object = findObjectById(objectId);
2091 return (object != null) ? object.getObjectName() : ("[" + Long.toString(objectId) + "]");
2092 }
2093
2094 /**
2095 * Get list of active alarms. For accessing terminated alarms log view API should be used.
2096 *
2097 * @return Hash map containing alarms
2098 * @throws IOException if socket I/O error occurs
2099 * @throws NXCException if NetXMS server returns an error or operation was timed out
2100 */
2101 public HashMap<Long, Alarm> getAlarms() throws IOException, NXCException
2102 {
2103 NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALL_ALARMS);
2104 final long rqId = msg.getMessageId();
2105 sendMessage(msg);
2106
2107 final HashMap<Long, Alarm> alarmList = new HashMap<Long, Alarm>(0);
2108 while(true)
2109 {
2110 msg = waitForMessage(NXCPCodes.CMD_ALARM_DATA, rqId);
2111 long alarmId = msg.getVariableAsInteger(NXCPCodes.VID_ALARM_ID);
2112 if (alarmId == 0)
2113 break; // ALARM_ID == 0 indicates end of list
2114 alarmList.put(alarmId, new Alarm(msg));
2115 }
2116
2117 return alarmList;
2118 }
2119
2120 /**
2121 * Get information about single active alarm. Terminated alarms cannot be accessed with this call.
2122 *
2123 * @param alarmId alarm ID
2124 * @return alarm object
2125 * @throws IOException if socket I/O error occurs
2126 * @throws NXCException if NetXMS server returns an error or operation was timed out
2127 */
2128 public Alarm getAlarm(long alarmId) throws IOException, NXCException
2129 {
2130 NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM);
2131 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2132 sendMessage(msg);
2133 final NXCPMessage response = waitForRCC(msg.getMessageId());
2134 return new Alarm(response);
2135 }
2136
2137 /**
2138 * Get information about events related to single active alarm. Information for terminated alarms cannot be accessed with this call.
2139 * User must have "view alarms" permission on alarm's source node and "view event log" system-wide access.
2140 *
2141 * @param alarmId alarm ID
2142 * @return list of related events
2143 * @throws IOException if socket I/O error occurs
2144 * @throws NXCException if NetXMS server returns an error or operation was timed out
2145 */
2146 public List<EventInfo> getAlarmEvents(long alarmId) throws IOException, NXCException
2147 {
2148 NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM_EVENTS);
2149 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2150 sendMessage(msg);
2151 final NXCPMessage response = waitForRCC(msg.getMessageId());
2152
2153 int count = response.getVariableAsInteger(NXCPCodes.VID_NUM_ELEMENTS);
2154 List<EventInfo> list = new ArrayList<EventInfo>(count);
2155 long varId = NXCPCodes.VID_ELEMENT_LIST_BASE;
2156 for(int i = 0; i < count; i++)
2157 {
2158 EventInfo parent = null;
2159 long rootId = response.getVariableAsInt64(varId + 1);
2160 if (rootId != 0)
2161 {
2162 for(EventInfo e : list)
2163 if (e.getId() == rootId)
2164 {
2165 parent = e;
2166 break;
2167 }
2168 }
2169 list.add(new EventInfo(response, varId, parent));
2170 varId += 10;
2171 }
2172 return list;
2173 }
2174
2175 /**
2176 * Acknowledge alarm.
2177 *
2178 * @param alarmId Identifier of alarm to be acknowledged.
2179 * @param sticky if set to true, acknowledged state will be made "sticky" (duplicate alarms with same key will not revert it back to outstanding)
2180 * @throws IOException if socket I/O error occurs
2181 * @throws NXCException if NetXMS server returns an error or operation was timed out
2182 */
2183 public void acknowledgeAlarm(final long alarmId, boolean sticky) throws IOException, NXCException
2184 {
2185 NXCPMessage msg = newMessage(NXCPCodes.CMD_ACK_ALARM);
2186 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2187 msg.setVariableInt16(NXCPCodes.VID_STICKY_FLAG, sticky ? 1 : 0);
2188 sendMessage(msg);
2189 waitForRCC(msg.getMessageId());
2190 }
2191
2192 /**
2193 * Acknowledge alarm.
2194 *
2195 * @param alarmId Identifier of alarm to be acknowledged.
2196 * @throws IOException if socket I/O error occurs
2197 * @throws NXCException if NetXMS server returns an error or operation was timed out
2198 */
2199 public void acknowledgeAlarm(final long alarmId) throws IOException, NXCException
2200 {
2201 acknowledgeAlarm(alarmId, false);
2202 }
2203
2204 /**
2205 * Resolve alarm.
2206 *
2207 * @param alarmId
2208 * Identifier of alarm to be resolved.
2209 * @throws IOException
2210 * if socket I/O error occurs
2211 * @throws NXCException
2212 * if NetXMS server returns an error or operation was timed out
2213 */
2214 public void resolveAlarm(final long alarmId) throws IOException, NXCException
2215 {
2216 NXCPMessage msg = newMessage(NXCPCodes.CMD_RESOLVE_ALARM);
2217 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2218 sendMessage(msg);
2219 waitForRCC(msg.getMessageId());
2220 }
2221
2222 /**
2223 * Terminate alarm.
2224 *
2225 * @param alarmId
2226 * Identifier of alarm to be terminated.
2227 * @throws IOException
2228 * if socket I/O error occurs
2229 * @throws NXCException
2230 * if NetXMS server returns an error or operation was timed out
2231 */
2232 public void terminateAlarm(final long alarmId) throws IOException, NXCException
2233 {
2234 NXCPMessage msg = newMessage(NXCPCodes.CMD_TERMINATE_ALARM);
2235 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2236 sendMessage(msg);
2237 waitForRCC(msg.getMessageId());
2238 }
2239
2240 /**
2241 * Delete alarm.
2242 *
2243 * @param alarmId
2244 * Identifier of alarm to be deleted.
2245 * @throws IOException
2246 * if socket I/O error occurs
2247 * @throws NXCException
2248 * if NetXMS server returns an error or operation was timed out
2249 */
2250 public void deleteAlarm(final long alarmId) throws IOException, NXCException
2251 {
2252 NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_ALARM);
2253 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2254 sendMessage(msg);
2255 waitForRCC(msg.getMessageId());
2256 }
2257
2258 /**
2259 * Set alarm's helpdesk state to "Open".
2260 *
2261 * @param alarmId
2262 * Identifier of alarm to be changed.
2263 * @param reference
2264 * Helpdesk reference string.
2265 * @throws IOException
2266 * if socket I/O error occurs
2267 * @throws NXCException
2268 * if NetXMS server returns an error or operation was timed out
2269 */
2270 public void openAlarm(final long alarmId, final String reference) throws IOException, NXCException
2271 {
2272 NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_ALARM_HD_STATE);
2273 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2274 msg.setVariableInt16(NXCPCodes.VID_HELPDESK_STATE, Alarm.HELPDESK_STATE_OPEN);
2275 msg.setVariable(NXCPCodes.VID_HELPDESK_REF, reference);
2276 sendMessage(msg);
2277 waitForRCC(msg.getMessageId());
2278 }
2279
2280 /**
2281 * Set alarm's helpdesk state to "Closed".
2282 *
2283 * @param alarmId
2284 * Identifier of alarm to be changed.
2285 * @throws IOException if socket I/O error occurs
2286 * @throws NXCException if NetXMS server returns an error or operation was timed out
2287 */
2288 public void closeAlarm(final long alarmId) throws IOException, NXCException
2289 {
2290 NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_ALARM_HD_STATE);
2291 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2292 msg.setVariableInt16(NXCPCodes.VID_HELPDESK_STATE, Alarm.HELPDESK_STATE_CLOSED);
2293 sendMessage(msg);
2294 waitForRCC(msg.getMessageId());
2295 }
2296
2297 /**
2298 * Get list of notes (comments) for given alarm.
2299 *
2300 * @param alarmId alarm ID
2301 * @return list of alarm's notes
2302 * @throws IOException if socket I/O error occurs
2303 * @throws NXCException if NetXMS server returns an error or operation was timed out
2304 */
2305 public List<AlarmNote> getAlarmNotes(long alarmId) throws IOException, NXCException
2306 {
2307 NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM_NOTES);
2308 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2309 sendMessage(msg);
2310
2311 final NXCPMessage response = waitForRCC(msg.getMessageId());
2312 int count = response.getVariableAsInteger(NXCPCodes.VID_NUM_ELEMENTS);
2313 final List<AlarmNote> notes = new ArrayList<AlarmNote>(count);
2314 long varId = NXCPCodes.VID_ELEMENT_LIST_BASE;
2315 for(int i = 0; i < count; i++)
2316 {
2317 notes.add(new AlarmNote(response, varId));
2318 varId += 10;
2319 }
2320 return notes;
2321 }
2322
2323 /**
2324 * Create or update alarm's note (comment). To create new note, set nodeId to 0.
2325 *
2326 * @param alarmId alarm ID
2327 * @param noteId note ID or 0 for creating new note
2328 * @param text message text
2329 * @throws IOException if socket I/O error occurs
2330 * @throws NXCException if NetXMS server returns an error or operation was timed out
2331 */
2332 public void updateAlarmNote(long alarmId, long noteId, String text) throws IOException, NXCException
2333 {
2334 NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_ALARM_NOTE);
2335 msg.setVariableInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
2336 msg.setVariableInt32(NXCPCodes.VID_NOTE_ID, (int)noteId);
2337 msg.setVariable(NXCPCodes.VID_COMMENTS, text);
2338 sendMessage(msg);
2339 waitForRCC(msg.getMessageId());
2340 }
2341
2342 /*
2343 * (non-Javadoc)
2344 *
2345 * @see
2346 * org.netxms.api.client.servermanager.ServerManager#getServerVariables()
2347 */
2348 @Override
2349 public Map<String, ServerVariable> getServerVariables() throws IOException, NXCException
2350 {
2351 NXCPMessage request = newMessage(NXCPCodes.CMD_GET_CONFIG_VARLIST);
2352 sendMessage(request);
2353
2354 final NXCPMessage response = waitForRCC(request.getMessageId());
2355
2356 long id;
2357 int i, count = response.getVariableAsInteger(NXCPCodes.VID_NUM_VARIABLES);
2358 final HashMap<String, ServerVariable> varList = new HashMap<String, ServerVariable>(count);
2359 for(i = 0, id = NXCPCodes.VID_VARLIST_BASE; i < count; i++, id += 3)
2360 {
2361 String name = response.getVariableAsString(id);
2362 varList.put(name, new ServerVariable(name, response.getVariableAsString(id + 1), response.getVariableAsBoolean(id + 2)));
2363 }
2364
2365 return varList;
2366 }
2367
2368 /*
2369 * (non-Javadoc)
2370 *
2371 * @see
2372 * org.netxms.api.client.servermanager.ServerManager#setServerVariable(java
2373 * .lang.String, java.lang.String)
2374 */
2375 @Override
2376 public void setServerVariable(final String name, final String value) throws IOException, NXCException
2377 {
2378 NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_CONFIG_VARIABLE);
2379 msg.setVariable(NXCPCodes.VID_NAME, name);
2380 msg.setVariable(NXCPCodes.VID_VALUE, value);
2381 sendMessage(msg);
2382 waitForRCC(msg.getMessageId());
2383 }
2384
2385 /*
2386 * (non-Javadoc)
2387 *
2388 * @see
2389 * org.netxms.api.client.servermanager.ServerManager#deleteServerVariable
2390 * (java.lang.String)
2391 */
2392 @Override
2393 public void deleteServerVariable(final String name) throws IOException, NXCException
2394 {
2395 NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_CONFIG_VARIABLE);
2396 msg.setVariable(NXCPCodes.VID_NAME, name);
2397 sendMessage(msg);
2398 waitForRCC(msg.getMessageId());
2399 }
2400
2401 /**
2402 * Get server config CLOB
2403 *
2404 * @param name
2405 * @return
2406 * @throws IOException
2407 * @throws NXCException
2408 */
2409 public String getServerConfigClob(final String name) throws IOException, NXCException
2410 {
2411 final NXCPMessage msg = newMessage(NXCPCodes.CMD_CONFIG_GET_CLOB);
2412 msg.setVariable(NXCPCodes.VID_NAME, name);
2413 sendMessage(msg);
2414 final NXCPMessage response = waitForRCC(msg.getMessageId());
2415 return response.getVariableAsString(NXCPCodes.VID_VALUE);
2416 }
2417
2418 /**
2419 * Set server config CLOB
2420 *
2421 * @param name
2422 * @param value
2423 * @throws IOException
2424 * @throws NXCException
2425 */
2426 public void setServerConfigClob(final String name, final String value) throws IOException, NXCException
2427 {
2428 NXCPMessage msg = newMessage(NXCPCodes.CMD_CONFIG_SET_CLOB);
2429 msg.setVariable(NXCPCodes.VID_NAME, name);
2430 msg.setVariable(NXCPCodes.VID_VALUE, value);
2431 sendMessage(msg);
2432 waitForRCC(msg.getMessageId());
2433 }
2434
2435 /**
2436 * Subscribe to notification channel(s)
2437 *
2438 * @param channels
2439 * Notification channels to subscribe to. Multiple channels can be
2440 * specified by combining them with OR operation.
2441 * @throws IOException if socket I/O error occurs
2442 * @throws NXCException if NetXMS server returns an error or operation was timed out
2443 */
2444 public void subscribe(int channels) throws IOException, NXCException
2445 {
2446 NXCPMessage msg = newMessage(NXCPCodes.CMD_CHANGE_SUBSCRIPTION);
2447 msg.setVariableInt32(NXCPCodes.VID_FLAGS, channels);
2448 msg.setVariableInt16(NXCPCodes.VID_OPERATION, 1);
2449 sendMessage(msg);
2450 waitForRCC(msg.getMessageId());
2451 }
2452
2453 /**
2454 * Unsubscribe from notification channel(s)
2455 *
2456 * @param channels
2457 * Notification channels to unsubscribe from. Multiple channels can
2458 * be specified by combining them with OR operation.
2459 * @throws IOException
2460 * if socket I/O error occurs
2461 * @throws NXCException
2462 * if NetXMS server returns an error or operation was timed out
2463 */
2464 public void unsubscribe(int channels) throws IOException, NXCException
2465 {
2466 NXCPMessage msg = newMessage(NXCPCodes.CMD_CHANGE_SUBSCRIPTION);
2467 msg.setVariableInt32(NXCPCodes.VID_FLAGS, channels);
2468 msg.setVariableInt16(NXCPCodes.VID_OPERATION, 0);
2469 sendMessage(msg);
2470 waitForRCC(msg.getMessageId());
2471 }
2472
2473 /*
2474 * (non-Javadoc)
2475 *
2476 * @see org.netxms.api.client.users.UserManager#syncUserDatabase()
2477 */
2478 @Override
2479 public void syncUserDatabase() throws IOException, NXCException
2480 {
2481 syncUserDB.acquireUninterruptibly();
2482 NXCPMessage msg = newMessage(NXCPCodes.CMD_LOAD_USER_DB);
2483 sendMessage(msg);
2484 waitForRCC(msg.getMessageId());
2485 waitForSync(syncUserDB, commandTimeout * 10);
2486 }
2487
2488 /*
2489 * (non-Javadoc)
2490 *
2491 * @see org.netxms.api.client.users.UserManager#findUserDBObjectById(long)
2492 */
2493 @Override
2494 public AbstractUserObject findUserDBObjectById(final long id)
2495 {
2496 AbstractUserObject object;
2497
2498 synchronized(userDB)
2499 {
2500 object = userDB.get(id);
2501 }
2502 return object;
2503 }
2504
2505 /*
2506 * (non-Javadoc)
2507 *
2508 * @see org.netxms.api.client.users.UserManager#getUserDatabaseObjects()
2509 */
2510 @Override
2511 public AbstractUserObject[] getUserDatabaseObjects()
2512 {
2513 AbstractUserObject[] list;
2514
2515 synchronized(userDB)
2516 {
2517 Collection<AbstractUserObject> values = userDB.values();
2518 list = values.toArray(new AbstractUserObject[values.size()]);
2519 }
2520 return list;
2521 }
2522
2523 /**
2524 * Create user or group on server
2525 *
2526 * @param name
2527 * Login name for new user
2528 * @return ID assigned to newly created user
2529 * @throws IOException
2530 * if socket I/O error occurs
2531 * @throws NXCException
2532 * if NetXMS server returns an error or operation was timed out
2533 */
2534 private long createUserDBObject(final String name, final boolean isGroup) throws IOException, NXCException
2535 {
2536 final NXCPMessage msg = newMessage(NXCPCodes.CMD_CREATE_USER);
2537 msg.setVariable(NXCPCodes.VID_USER_NAME, name);
2538 msg.setVariableInt16(NXCPCodes.VID_IS_GROUP, isGroup ? 1 : 0);
2539 sendMessage(msg);
2540
2541 final NXCPMessage response = waitForRCC(msg.getMessageId());
2542 return response.getVariableAsInt64(NXCPCodes.VID_USER_ID);
2543 }
2544
2545 /*
2546 * (non-Javadoc)
2547 *
2548 * @see org.netxms.api.client.users.UserManager#createUser(java.lang.String)
2549 */
2550 @Override
2551 public long createUser(final String name) throws IOException, NXCException
2552 {
2553 return createUserDBObject(name, false);
2554 }
2555
2556 /*
2557 * (non-Javadoc)
2558 *
2559 * @see
2560 * org.netxms.api.client.users.UserManager#createUserGroup(java.lang.String)
2561 */
2562 @Override
2563 public long createUserGroup(final String name) throws IOException, NXCException
2564 {
2565 return createUserDBObject(name, true);
2566 }
2567
2568 /*
2569 * (non-Javadoc)
2570 *
2571 * @see org.netxms.api.client.users.UserManager#deleteUserDBObject(long)
2572 */
2573 @Override
2574 public void deleteUserDBObject(final long id) throws IOException, NXCException
2575 {
2576 NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_USER);
2577 msg.setVariableInt32(NXCPCodes.VID_USER_ID, (int)id);
2578 sendMessage(msg);
2579 waitForRCC(msg.getMessageId());
2580 }
2581
2582 /*
2583 * (non-Javadoc)
2584 *
2585 * @see org.netxms.api.client.users.UserManager#setUserPassword(long,
2586 * java.lang.String, java.lang.String)
2587 */
2588 @Override
2589 public void setUserPassword(final long id, final String newPassword, final String oldPassword) throws IOException, NXCException
2590 {
2591 NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_PASSWORD);
2592 msg.setVariableInt32(NXCPCodes.VID_USER_ID, (int)id);
2593 msg.setVariable(NXCPCodes.VID_PASSWORD, newPassword);
2594 if (oldPassword != null)
2595 msg.setVariable(NXCPCodes.VID_OLD_PASSWORD, oldPassword);
2596 sendMessage(msg);
2597 waitForRCC(msg.getMessageId());
2598 }
2599
2600 /*
2601 * (non-Javadoc)
2602 *
2603 * @see
2604 * org.netxms.api.client.users.UserManager#modifyUserDBObject(org.netxms.
2605 * api.client.users.AbstractUserObject, int)
2606 */
2607 @Override
2608 public void modifyUserDBObject(final AbstractUserObject object, final int fields) throws IOException, NXCException
2609 {
2610 NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_USER);
2611 msg.setVariableInt32(NXCPCodes.VID_FIELDS, fields);
2612 object.fillMessage(msg);
2613 sendMessage(msg);
2614 waitForRCC(msg.getMessageId());
2615 }
2616
2617 /*
2618 * (non-Javadoc)
2619 *
2620 * @see
2621 * org.netxms.api.client.users.UserManager#modifyUserDBObject(org.netxms.
2622 * api.client.users.AbstractUserObject)
2623 */
2624 @Override
2625 public void modifyUserDBObject(final AbstractUserObject object) throws IOException, NXCException
2626 {
2627 modifyUserDBObject(object, 0x7FFFFFFF);
2628 }
2629
2630 /*
2631 * (non-Javadoc)
2632 *
2633 * @see org.netxms.api.client.users.UserManager#lockUserDatabase()
2634 */
2635 @Override
2636 public void lockUserDatabase() throws IOException, NXCException
2637 {
2638 NXCPMessage msg = newMessage(NXCPCodes.CMD_LOCK_USER_DB);
2639 sendMessage(msg);
2640 waitForRCC(msg.getMessageId());
2641 }
2642
2643 /*
2644 * (non-Javadoc)
2645 *
2646 * @see org.netxms.api.client.users.UserManager#unlockUserDatabase()
2647 */
2648 @Override
2649 public void unlockUserDatabase() throws IOException, NXCException
2650 {
2651 NXCPMessage msg = newMessage(NXCPCodes.CMD_UNLOCK_USER_DB);
2652 sendMessage(msg);
2653 waitForRCC(msg.getMessageId());
2654 }
2655
2656 /*
2657 * (non-Javadoc)
2658 *
2659 * @see
2660 * org.netxms.api.client.Session#setAttributeForCurrentUser(java.lang.String,
2661 * java.lang.String)
2662 */
2663 @Override
2664 public void setAttributeForCurrentUser(final String name, final String value) throws IOException, NXCException
2665 {
2666 NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_CURRENT_USER_ATTR);
2667 msg.setVariable(NXCPCodes.VID_NAME, name);
2668 msg.setVariable(NXCPCodes.VID_VALUE, value);
2669 sendMessage(msg);
2670 waitForRCC(msg.getMessageId());
2671 }
2672
2673 /*
2674 * (non-Javadoc)
2675 *
2676 * @see
2677 * org.netxms.api.client.Session#getAttributeForCurrentUser(java.lang.String)
2678 */
2679 @Override
2680 public String getAttributeForCurrentUser(final String name) throws IOException, NXCException
2681 {
2682 NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_CURRENT_USER_ATTR);
2683 msg.setVariable(NXCPCodes.VID_NAME, name);
2684 sendMessage(msg);
2685 final NXCPMessage response = waitForRCC(msg.getMessageId());
2686 return response.getVariableAsString(NXCPCodes.VID_VALUE);
2687 }
2688
2689 /**
2690 * Get last DCI values for given node
2691 *
2692 * @param nodeId ID of the node to get DCI values for
2693 * @param objectTooltipOnly if set to true, only DCIs with DCF_SHOW_ON_OBJECT_TOOLTIP flag set are returned
2694 * @return List of DCI values
2695 * @throws IOException if socket I/O error occurs
2696 * @throws NXCException if NetXMS server returns an error or operation was timed out
2697 */
2698 public DciValue[] getLastValues(final long nodeId, boolean objectTooltipOnly) throws IOException, NXCException
2699 {
2700 final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_LAST_VALUES);
2701 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
2702 msg.setVariableInt16(NXCPCodes.VID_OBJECT_TOOLTIP_ONLY, objectTooltipOnly ? 1 : 0);
2703 sendMessage(msg);
2704
2705 final NXCPMessage response = waitForRCC(msg.getMessageId());
2706
2707 int count = response.getVariableAsInteger(NXCPCodes.VID_NUM_ITEMS);
2708 DciValue[] list = new DciValue[count];
2709 long base = NXCPCodes.VID_DCI_VALUES_BASE;
2710 for(int i = 0; i < count; i++, base += 50)
2711 list[i] = DciValue.createFromMessage(nodeId, response, base);
2712
2713 return list;
2714 }
2715
2716 /**
2717 * Get last DCI values for given node
2718 *
2719 * @param nodeId
2720 * ID of the node to get DCI values for
2721 * @return List of DCI values
2722 * @throws IOException
2723 * if socket I/O error occurs
2724 * @throws NXCException
2725 * if NetXMS server returns an error or operation was timed out
2726 */
2727 public DciValue[] getLastValues(final long nodeId) throws IOException, NXCException
2728 {
2729 return getLastValues(nodeId, false);
2730 }
2731
2732 /**
2733 * Get last values for given table DCI on given node
2734 *
2735 * @param nodeId ID of the node to get DCI values for
2736 * @param dciId DCI ID
2737 * @return Table object with last values for table DCI
2738 * @throws IOException if socket I/O error occurs
2739 * @throws NXCException if NetXMS server returns an error or operation was timed out
2740 */
2741 public Table getTableLastValues(final long nodeId, final long dciId) throws IOException, NXCException
2742 {
2743 final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_TABLE_LAST_VALUES);
2744 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
2745 msg.setVariableInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
2746 sendMessage(msg);
2747
2748 final NXCPMessage response = waitForRCC(msg.getMessageId());
2749 return new Table(response);
2750 }
2751
2752 /**
2753 * Get list of DCIs configured to be shown on performance tab in console for
2754 * given node.
2755 *
2756 * @param nodeId Node object ID
2757 * @return List of performance tab DCIs
2758 * @throws IOException if socket I/O error occurs
2759 * @throws NXCException if NetXMS server returns an error or operation was timed out
2760 */
2761 public PerfTabDci[] getPerfTabItems(final long nodeId) throws IOException, NXCException
2762 {
2763 final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_PERFTAB_DCI_LIST);
2764 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
2765 sendMessage(msg);
2766
2767 final NXCPMessage response = waitForRCC(msg.getMessageId());
2768
2769 int count = response.getVariableAsInteger(NXCPCodes.VID_NUM_ITEMS);
2770 PerfTabDci[] list = new PerfTabDci[count];
2771 long base = NXCPCodes.VID_SYSDCI_LIST_BASE;
2772 for(int i = 0; i < count; i++, base += 10)
2773 list[i] = new PerfTabDci(response, base);
2774
2775 return list;
2776 }
2777
2778 /**
2779 * Get threshold violation summary for all nodes under given parent object. Parent object could
2780 * be container, subnet, zone, entire network, or infrastructure service root.
2781 *
2782 * @param objectId parent object ID
2783 * @return list of threshold violation summary objects for all nodes below given root
2784 * @throws IOException if socket I/O error occurs
2785 * @throws NXCException if NetXMS server returns an error or operation was timed out
2786 */
2787 public List<ThresholdViolationSummary> getThresholdSummary(final long objectId) throws IOException, NXCException
2788 {
2789 final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_THRESHOLD_SUMMARY);
2790 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
2791 sendMessage(msg);
2792
2793 final NXCPMessage response = waitForRCC(msg.getMessageId());
2794
2795 List<ThresholdViolationSummary> list = new ArrayList<ThresholdViolationSummary>();
2796 long varId = NXCPCodes.VID_THRESHOLD_BASE;
2797 while(response.getVariableAsInt64(varId) != 0)
2798 {
2799 final ThresholdViolationSummary t = new ThresholdViolationSummary(response, varId);
2800 list.add(t);
2801 varId += 50 * t.getDciList().size() + 2;
2802 }
2803
2804 return list;
2805 }
2806
2807 /**
2808 * Parse data from raw message CMD_DCI_DATA
2809 *
2810 * @param input
2811 * Raw data
2812 * @param data
2813 * Data object to add rows to
2814 * @return number of received data rows
2815 */
2816 private int parseDataRows(final byte[] input, DciData data)
2817 {
2818 final NXCPDataInputStream inputStream = new NXCPDataInputStream(input);
2819 int rows = 0;
2820
2821 try
2822 {
2823 inputStream.skipBytes(4); // DCI ID
2824 rows = inputStream.readInt();
2825 final int dataType = inputStream.readInt();
2826 data.setDataType(dataType);
2827
2828 for(int i = 0; i < rows; i++)
2829 {
2830 long timestamp = inputStream.readUnsignedInt() * 1000; // convert to
2831 // milliseconds
2832
2833 switch(dataType)
2834 {
2835 case DataCollectionItem.DT_INT:
2836 data.addDataRow(new DciDataRow(new Date(timestamp), new Long(inputStream.readInt())));
2837 break;
2838 case DataCollectionItem.DT_UINT:
2839 data.addDataRow(new DciDataRow(new Date(timestamp), new Long(inputStream.readUnsignedInt())));
2840 break;
2841 case DataCollectionItem.DT_INT64:
2842 case DataCollectionItem.DT_UINT64:
2843 data.addDataRow(new DciDataRow(new Date(timestamp), new Long(inputStream.readLong())));
2844 break;
2845 case DataCollectionItem.DT_FLOAT:
2846 data.addDataRow(new DciDataRow(new Date(timestamp), new Double(inputStream.readDouble())));
2847 break;
2848 case DataCollectionItem.DT_STRING:
2849 StringBuilder sb = new StringBuilder(256);
2850 int count;
2851 for(count = MAX_DCI_STRING_VALUE_LENGTH; count > 0; count--)
2852 {
2853 char ch = inputStream.readChar();
2854 if (ch == 0)
2855 {
2856 count--;
2857 break;
2858 }
2859 sb.append(ch);
2860 }
2861 inputStream.skipBytes(count * 2);
2862 data.addDataRow(new DciDataRow(new Date(timestamp), sb.toString()));
2863 break;
2864 }
2865 }
2866 }
2867 catch(IOException e)
2868 {
2869 }
2870
2871 return rows;
2872 }
2873
2874 /**
2875 * Get collected DCI data from server. Please note that you should specify
2876 * either row count limit or time from/to limit.
2877 *
2878 * @param nodeId Node ID
2879 * @param dciId DCI ID
2880 * @param instance instance value (for table DCI only)
2881 * @param dataColumn name of column to retrieve data from (for table DCI only)
2882 * @param from Start of time range or null for no limit
2883 * @param to End of time range or null for no limit
2884 * @param maxRows Maximum number of rows to retrieve or 0 for no limit
2885 * @return DCI data set
2886 * @throws IOException if socket I/O error occurs
2887 * @throws NXCException if NetXMS server returns an error or operation was timed out
2888 */
2889 private DciData getCollectedDataInternal(long nodeId, long dciId, String instance, String dataColumn, Date from, Date to,
2890 int maxRows) throws IOException, NXCException
2891 {
2892 NXCPMessage msg;
2893 if (instance != null) // table DCI
2894 {
2895 msg = newMessage(NXCPCodes.CMD_GET_TABLE_DCI_DATA);
2896 msg.setVariable(NXCPCodes.VID_INSTANCE, instance);
2897 msg.setVariable(NXCPCodes.VID_DATA_COLUMN, dataColumn);
2898 }
2899 else
2900 {
2901 msg = newMessage(NXCPCodes.CMD_GET_DCI_DATA);
2902 }
2903 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
2904 msg.setVariableInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
2905
2906 DciData data = new DciData(nodeId, dciId);
2907
2908 int rowsReceived, rowsRemaining = maxRows;
2909 int timeFrom = (from != null) ? (int)(from.getTime() / 1000) : 0;
2910 int timeTo = (to != null) ? (int)(to.getTime() / 1000) : 0;
2911
2912 do
2913 {
2914 msg.setMessageId(requestId.getAndIncrement());
2915 msg.setVariableInt32(NXCPCodes.VID_MAX_ROWS, maxRows);
2916 msg.setVariableInt32(NXCPCodes.VID_TIME_FROM, timeFrom);
2917 msg.setVariableInt32(NXCPCodes.VID_TIME_TO, timeTo);
2918 sendMessage(msg);
2919
2920 waitForRCC(msg.getMessageId());
2921
2922 NXCPMessage response = waitForMessage(NXCPCodes.CMD_DCI_DATA, msg.getMessageId());
2923 if (!response.isBinaryMessage())
2924 throw new NXCException(RCC.INTERNAL_ERROR);
2925
2926 rowsReceived = parseDataRows(response.getBinaryData(), data);
2927 if (((rowsRemaining == 0) || (rowsRemaining > MAX_DCI_DATA_ROWS)) && (rowsReceived == MAX_DCI_DATA_ROWS))
2928 {
2929 // adjust boundaries for next request
2930 if (rowsRemaining > 0)
2931 rowsRemaining -= rowsReceived;
2932
2933 // Rows goes in newest to oldest order, so if we need to
2934 // retrieve additional data, we should update timeTo limit
2935 if (to != null)
2936 {
2937 DciDataRow row = data.getLastValue();
2938 if (row != null)
2939 {
2940 // There should be only one value per second, so we set
2941 // last row's timestamp - 1 second as new boundary
2942 timeTo = (int)(row.getTimestamp().getTime() / 1000) - 1;
2943 }
2944 }
2945 }
2946 } while(rowsReceived == MAX_DCI_DATA_ROWS);
2947
2948 return data;
2949 }
2950
2951 /**
2952 * Get collected DCI data from server. Please note that you should specify
2953 * either row count limit or time from/to limit.
2954 *
2955 * @param nodeId Node ID
2956 * @param dciId DCI ID
2957 * @param from Start of time range or null for no limit
2958 * @param to End of time range or null for no limit
2959 * @param maxRows Maximum number of rows to retrieve or 0 for no limit
2960 * @return DCI data set
2961 * @throws IOException if socket I/O error occurs
2962 * @throws NXCException if NetXMS server returns an error or operation was timed out
2963 */
2964 public DciData getCollectedData(long nodeId, long dciId, Date from, Date to, int maxRows) throws IOException, NXCException
2965 {
2966 return getCollectedDataInternal(nodeId, dciId, null, null, from, to, maxRows);
2967 }
2968
2969 /**
2970 * Get collected table DCI data from server. Please note that you should specify
2971 * either row count limit or time from/to limit.
2972 *
2973 * @param nodeId Node ID
2974 * @param dciId DCI ID
2975 * @param instance instance value
2976 * @param dataColumn name of column to retrieve data from
2977 * @param from Start of time range or null for no limit
2978 * @param to End of time range or null for no limit
2979 * @param maxRows Maximum number of rows to retrieve or 0 for no limit
2980 * @return DCI data set
2981 * @throws IOException if socket I/O error occurs
2982 * @throws NXCException if NetXMS server returns an error or operation was timed out
2983 */
2984 public DciData getCollectedTableData(long nodeId, long dciId, String instance, String dataColumn, Date from, Date to, int maxRows)
2985 throws IOException, NXCException
2986 {
2987 if (instance == null || dataColumn == null)
2988 throw new NXCException(RCC.INVALID_ARGUMENT);
2989 return getCollectedDataInternal(nodeId, dciId, instance, dataColumn, from, to, maxRows);
2990 }
2991
2992 /**
2993 * Clear collected data for given DCI
2994 *
2995 * @param nodeId Node object ID
2996 * @param dciId DCI ID
2997 * @throws IOException if socket I/O error occurs
2998 * @throws NXCException if NetXMS server returns an error or operation was timed out
2999 */
3000 public void clearCollectedData(long nodeId, long dciId) throws IOException, NXCException
3001 {
3002 final NXCPMessage msg = newMessage(NXCPCodes.CMD_CLEAR_DCI_DATA);
3003 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
3004 msg.setVariableInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
3005 sendMessage(msg);
3006 waitForRCC(msg.getMessageId());
3007 }
3008
3009 /**
3010 * Get list of thresholds configured for given DCI
3011 *
3012 * @param nodeId Node object ID
3013 * @param dciId DCI ID
3014 * @return List of configured thresholds
3015 * @throws IOException if socket I/O error occurs
3016 * @throws NXCException if NetXMS server returns an error or operation was timed out
3017 */
3018 public Threshold[] getThresholds(final long nodeId, final long dciId) throws IOException, NXCException
3019 {
3020 final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_DCI_THRESHOLDS);
3021 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
3022 msg.setVariableInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
3023 sendMessage(msg);
3024
3025 final NXCPMessage response = waitForRCC(msg.getMessageId());
3026 int count = response.getVariableAsInteger(NXCPCodes.VID_NUM_THRESHOLDS);
3027 final Threshold[] list = new Threshold[count];
3028
3029 long varId = NXCPCodes.VID_DCI_THRESHOLD_BASE;
3030 for(int i = 0; i < count; i++)
3031 {
3032 list[i] = new Threshold(response, varId);
3033 varId += 20;
3034 }
3035
3036 return list;
3037 }
3038
3039 /**
3040 * Resolve names of given DCIs
3041 *
3042 * @param nodeIds node identifiers
3043 * @param dciIds DCI identifiers (length must match length of node identifiers list)
3044 * @return array of resolved DCI names
3045 * @throws IOException if socket I/O error occurs
3046 * @throws NXCException if NetXMS server returns an error or operation was timed out
3047 */
3048 public String[] resolveDciNames(long[] nodeIds, long[] dciIds) throws IOException, NXCException
3049 {
3050 if (nodeIds.length == 0)
3051 return new String[0];
3052
3053 final NXCPMessage msg = newMessage(NXCPCodes.CMD_RESOLVE_DCI_NAMES);
3054 msg.setVariableInt32(NXCPCodes.VID_NUM_ITEMS, nodeIds.length);
3055 msg.setVariable(NXCPCodes.VID_NODE_LIST, nodeIds);
3056 msg.setVariable(NXCPCodes.VID_DCI_LIST, dciIds);
3057 sendMessage(msg);
3058
3059 final NXCPMessage response = waitForRCC(msg.getMessageId());
3060 String[] result = new String[nodeIds.length];
3061 long varId = NXCPCodes.VID_DCI_LIST_BASE;
3062 for(int i = 0; i < result.length; i++)
3063 result[i] = response.getVariableAsString(varId++);
3064 return result;
3065 }
3066
3067 /**
3068 * Resolve names of given DCIs
3069 *
3070 * @param dciList DCI list
3071 * @return array of resolved DCI names
3072 * @throws IOException if socket I/O error occurs
3073 * @throws NXCException if NetXMS server returns an error or operation was timed out
3074 */
3075 public String[] resolveDciNames(Collection<ConditionDciInfo> dciList) throws IOException, NXCException
3076 {
3077 final long[] nodeIds = new long[dciList.size()];
3078 final long[] dciIds = new long[dciList.size()];
3079 int i = 0;
3080 for(ConditionDciInfo dci : dciList)
3081 {
3082 nodeIds[i] = dci.getNodeId();
3083 dciIds[i] = dci.getDciId();
3084 i++;
3085 }
3086 return resolveDciNames(nodeIds, dciIds);
3087 }
3088
3089 /**
3090 * Query parameter immediately. This call will cause server to do actual call
3091 * to managed node and will return current value for given parameter. Result
3092 * is not cached.
3093 *
3094 * @param nodeId
3095 * node object ID
3096 * @param origin
3097 * parameter's origin (NetXMS agent, SNMP, etc.)
3098 * @param name
3099 * parameter's name
3100 * @return current parameter's value
3101 * @throws IOException
3102 * if socket I/O error occurs
3103 * @throws NXCException
3104 * if NetXMS server returns an error or operation was timed out
3105 */
3106 public String queryParameter(long nodeId, int origin, String name) throws IOException, NXCException
3107 {
3108 final NXCPMessage msg = newMessage(NXCPCodes.CMD_QUERY_PARAMETER);
3109 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
3110 msg.setVariableInt16(NXCPCodes.VID_DCI_SOURCE_TYPE, origin);
3111 msg.setVariable(NXCPCodes.VID_NAME, name);
3112 sendMessage(msg);
3113
3114 final NXCPMessage response = waitForRCC(msg.getMessageId());
3115 return response.getVariableAsString(NXCPCodes.VID_VALUE);
3116 }
3117
3118 /**
3119 * Query agent's table immediately. This call will cause server to do actual
3120 * call to managed node and will return current value for given table. Result
3121 * is not cached.
3122 *
3123 * @param nodeId
3124 * node object ID
3125 * @param name
3126 * table's name
3127 * @return current table's value
3128 * @throws IOException
3129 * if socket I/O error occurs
3130 * @throws NXCException
3131 * if NetXMS server returns an error or operation was timed out
3132 */
3133 public Table queryAgentTable(long nodeId, String name) throws IOException, NXCException
3134 {
3135 final NXCPMessage msg = newMessage(NXCPCodes.CMD_QUERY_TABLE);
3136 msg.setVariableInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
3137 msg.setVariable(NXCPCodes.VID_NAME, name);
3138 sendMessage(msg);
3139
3140 final NXCPMessage response = waitForRCC(msg.getMessageId());
3141 return new Table(response);
3142 }
3143
3144 /**
3145 * Hook method to allow adding of custom object creation data to NXCP message.
3146 * Default implementation does nothing.
3147 *
3148 * @param data object creation data passed to createObject
3149 * @param userData user-defined data for object creation passed to createObject
3150 * @param msg NXCP message that will be sent to server
3151 */
3152 protected void createCustomObject(NXCObjectCreationData data, Object userData, NXCPMessage msg)