org.netxms.client.NXCSession Maven / Gradle / Ivy
Show all versions of netxms-client Show documentation
/**
* NetXMS - open source network management system
* Copyright (C) 2003-2024 Victor Kirhenshtein
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.netxms.client;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Writer;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.netxms.base.EncryptionContext;
import org.netxms.base.GeoLocation;
import org.netxms.base.InetAddressEx;
import org.netxms.base.MacAddress;
import org.netxms.base.NXCPCodes;
import org.netxms.base.NXCPDataInputStream;
import org.netxms.base.NXCPException;
import org.netxms.base.NXCPMessage;
import org.netxms.base.NXCPMessageReceiver;
import org.netxms.base.NXCPMsgWaitQueue;
import org.netxms.base.VersionInfo;
import org.netxms.client.agent.config.AgentConfiguration;
import org.netxms.client.agent.config.AgentConfigurationHandle;
import org.netxms.client.asset.AssetAttribute;
import org.netxms.client.businessservices.BusinessServiceCheck;
import org.netxms.client.businessservices.BusinessServiceTicket;
import org.netxms.client.constants.AggregationFunction;
import org.netxms.client.constants.AuthenticationType;
import org.netxms.client.constants.BackgroundTaskState;
import org.netxms.client.constants.DataOrigin;
import org.netxms.client.constants.DataType;
import org.netxms.client.constants.HistoricalDataType;
import org.netxms.client.constants.ObjectPollType;
import org.netxms.client.constants.ObjectStatus;
import org.netxms.client.constants.RCC;
import org.netxms.client.dashboards.DashboardElement;
import org.netxms.client.datacollection.ChartDciConfig;
import org.netxms.client.datacollection.ConditionDciInfo;
import org.netxms.client.datacollection.DCOStatusHolder;
import org.netxms.client.datacollection.DataCollectionConfiguration;
import org.netxms.client.datacollection.DataCollectionItem;
import org.netxms.client.datacollection.DataCollectionObject;
import org.netxms.client.datacollection.DataCollectionTable;
import org.netxms.client.datacollection.DciData;
import org.netxms.client.datacollection.DciDataRow;
import org.netxms.client.datacollection.DciInfo;
import org.netxms.client.datacollection.DciLastValue;
import org.netxms.client.datacollection.DciPushData;
import org.netxms.client.datacollection.DciSummaryTable;
import org.netxms.client.datacollection.DciSummaryTableColumn;
import org.netxms.client.datacollection.DciSummaryTableDescriptor;
import org.netxms.client.datacollection.DciValue;
import org.netxms.client.datacollection.GraphDefinition;
import org.netxms.client.datacollection.GraphFolder;
import org.netxms.client.datacollection.MeasurementUnit;
import org.netxms.client.datacollection.PerfTabDci;
import org.netxms.client.datacollection.PredictionEngine;
import org.netxms.client.datacollection.RemoteChangeListener;
import org.netxms.client.datacollection.SimpleDciValue;
import org.netxms.client.datacollection.Threshold;
import org.netxms.client.datacollection.ThresholdStateChange;
import org.netxms.client.datacollection.ThresholdViolationSummary;
import org.netxms.client.datacollection.TransformationTestResult;
import org.netxms.client.datacollection.WebServiceDefinition;
import org.netxms.client.datacollection.WinPerfObject;
import org.netxms.client.events.Alarm;
import org.netxms.client.events.AlarmCategory;
import org.netxms.client.events.AlarmComment;
import org.netxms.client.events.BulkAlarmStateChangeData;
import org.netxms.client.events.Event;
import org.netxms.client.events.EventInfo;
import org.netxms.client.events.EventProcessingPolicy;
import org.netxms.client.events.EventProcessingPolicyRule;
import org.netxms.client.events.EventReference;
import org.netxms.client.events.EventTemplate;
import org.netxms.client.events.SyslogRecord;
import org.netxms.client.log.Log;
import org.netxms.client.maps.MapDCIInstance;
import org.netxms.client.maps.NetworkMapLink;
import org.netxms.client.maps.NetworkMapPage;
import org.netxms.client.maps.configs.SingleDciConfig;
import org.netxms.client.maps.elements.NetworkMapElement;
import org.netxms.client.maps.elements.NetworkMapObject;
import org.netxms.client.market.Repository;
import org.netxms.client.mt.MappingTable;
import org.netxms.client.mt.MappingTableDescriptor;
import org.netxms.client.objects.AbstractNode;
import org.netxms.client.objects.AbstractObject;
import org.netxms.client.objects.AccessPoint;
import org.netxms.client.objects.Asset;
import org.netxms.client.objects.AssetGroup;
import org.netxms.client.objects.AssetRoot;
import org.netxms.client.objects.BusinessService;
import org.netxms.client.objects.BusinessServicePrototype;
import org.netxms.client.objects.BusinessServiceRoot;
import org.netxms.client.objects.Chassis;
import org.netxms.client.objects.Cluster;
import org.netxms.client.objects.ClusterResource;
import org.netxms.client.objects.Condition;
import org.netxms.client.objects.Container;
import org.netxms.client.objects.Dashboard;
import org.netxms.client.objects.DashboardGroup;
import org.netxms.client.objects.DashboardRoot;
import org.netxms.client.objects.DependentNode;
import org.netxms.client.objects.EntireNetwork;
import org.netxms.client.objects.GenericObject;
import org.netxms.client.objects.Interface;
import org.netxms.client.objects.MobileDevice;
import org.netxms.client.objects.MutableObjectCategory;
import org.netxms.client.objects.NetworkMap;
import org.netxms.client.objects.NetworkMapGroup;
import org.netxms.client.objects.NetworkMapRoot;
import org.netxms.client.objects.NetworkService;
import org.netxms.client.objects.Node;
import org.netxms.client.objects.ObjectCategory;
import org.netxms.client.objects.Rack;
import org.netxms.client.objects.Sensor;
import org.netxms.client.objects.ServiceRoot;
import org.netxms.client.objects.Subnet;
import org.netxms.client.objects.Template;
import org.netxms.client.objects.TemplateGroup;
import org.netxms.client.objects.TemplateRoot;
import org.netxms.client.objects.UnknownObject;
import org.netxms.client.objects.VPNConnector;
import org.netxms.client.objects.Zone;
import org.netxms.client.objects.configs.CustomAttribute;
import org.netxms.client.objects.configs.PassiveRackElement;
import org.netxms.client.objects.interfaces.NodeItemPair;
import org.netxms.client.objects.queries.ObjectQuery;
import org.netxms.client.objects.queries.ObjectQueryResult;
import org.netxms.client.objecttools.ObjectContextBase;
import org.netxms.client.objecttools.ObjectTool;
import org.netxms.client.objecttools.ObjectToolDetails;
import org.netxms.client.objecttools.ObjectToolFolder;
import org.netxms.client.packages.PackageDeploymentListener;
import org.netxms.client.packages.PackageInfo;
import org.netxms.client.reporting.ReportDefinition;
import org.netxms.client.reporting.ReportRenderFormat;
import org.netxms.client.reporting.ReportResult;
import org.netxms.client.reporting.ReportingJob;
import org.netxms.client.reporting.ReportingJobConfiguration;
import org.netxms.client.server.AgentFile;
import org.netxms.client.server.ServerConsoleListener;
import org.netxms.client.server.ServerFile;
import org.netxms.client.server.ServerJob;
import org.netxms.client.server.ServerJobIdUpdater;
import org.netxms.client.server.ServerVariable;
import org.netxms.client.snmp.SnmpTrap;
import org.netxms.client.snmp.SnmpTrapLogRecord;
import org.netxms.client.snmp.SnmpUsmCredential;
import org.netxms.client.snmp.SnmpValue;
import org.netxms.client.snmp.SnmpWalkListener;
import org.netxms.client.topology.ArpCacheEntry;
import org.netxms.client.topology.ConnectionPoint;
import org.netxms.client.topology.FdbEntry;
import org.netxms.client.topology.NetworkPath;
import org.netxms.client.topology.OSPFInfo;
import org.netxms.client.topology.Route;
import org.netxms.client.topology.VlanInfo;
import org.netxms.client.topology.WirelessStation;
import org.netxms.client.users.AbstractUserObject;
import org.netxms.client.users.ResponsibleUser;
import org.netxms.client.users.TwoFactorAuthenticationMethod;
import org.netxms.client.users.User;
import org.netxms.client.users.UserGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcraft.jzlib.Deflater;
import com.jcraft.jzlib.JZlib;
/**
* Communication session with NetXMS server.
*/
public class NXCSession
{
// DCI resolve flags
public static final int DCI_RES_SEARCH_NAME = 0x01;
// Various public constants
public static final int DEFAULT_CONN_PORT = 4701;
// Core notification channels
public static final String CHANNEL_AGENT_TUNNELS = "Core.AgentTunnels";
public static final String CHANNEL_ALARMS = "Core.Alarms";
public static final String CHANNEL_AUDIT_LOG = "Core.Audit";
public static final String CHANNEL_DC_THRESHOLDS = "Core.DC.Thresholds";
public static final String CHANNEL_GEO_AREAS = "Core.GeoAreas";
public static final String CHANNEL_EVENTS = "Core.Events";
public static final String CHANNEL_OBJECTS = "Core.Objects";
public static final String CHANNEL_SNMP_TRAPS = "Core.SNMP.Traps";
public static final String CHANNEL_SYSLOG = "Core.Syslog";
public static final String CHANNEL_USERDB = "Core.UserDB";
// Object sync options
public static final int OBJECT_SYNC_NOTIFY = 0x0001;
public static final int OBJECT_SYNC_WAIT = 0x0002;
// Configuration import options
public static final int CFG_IMPORT_REPLACE_EVENTS = 0x0001;
public static final int CFG_IMPORT_REPLACE_ACTIONS = 0x0002;
public static final int CFG_IMPORT_REPLACE_TEMPLATES = 0x0004;
public static final int CFG_IMPORT_REPLACE_TRAPS = 0x0008;
public static final int CFG_IMPORT_REPLACE_SCRIPTS = 0x0010;
public static final int CFG_IMPORT_REPLACE_SUMMARY_TABLES = 0x0020;
public static final int CFG_IMPORT_REPLACE_OBJECT_TOOLS = 0x0040;
public static final int CFG_IMPORT_REPLACE_EPP_RULES = 0x0080;
public static final int CFG_IMPORT_REPLACE_TEMPLATE_NAMES_LOCATIONS = 0x0100;
public static final int CFG_IMPORT_DELETE_EMPTY_TEMPLATE_GROUPS = 0x0200;
public static final int CFG_IMPORT_REPLACE_WEB_SVCERVICE_DEFINITIONS = 0x0400;
public static final int CFG_IMPORT_REPLACE_AM_DEFINITIONS = 0x0800;
// Address list IDs
public static final int ADDRESS_LIST_DISCOVERY_TARGETS = 1;
public static final int ADDRESS_LIST_DISCOVERY_FILTER = 2;
// Server components
public static final int SERVER_COMPONENT_DISCOVERY_MANAGER = 1;
// Client types
public static final int DESKTOP_CLIENT = 0;
public static final int WEB_CLIENT = 1;
public static final int MOBILE_CLIENT = 2;
public static final int TABLET_CLIENT = 3;
public static final int APPLICATION_CLIENT = 4;
// Private constants
private static final int CLIENT_CHALLENGE_SIZE = 256;
private static final int MAX_DCI_DATA_ROWS = 200000;
private static final int MAX_DCI_STRING_VALUE_LENGTH = 256;
private static final int RECEIVED_FILE_TTL = 300000; // 300 seconds
private static final int FILE_BUFFER_SIZE = 32768; // 32KB
// Logger
private static Logger logger = LoggerFactory.getLogger(NXCSession.class);
// Internal synchronization objects
private final Semaphore syncObjects = new Semaphore(1);
private final Semaphore syncUserDB = new Semaphore(1);
// Connection-related attributes
private String connAddress;
private int connPort;
private boolean connUseEncryption;
private String connClientInfo = "nxjclient/" + VersionInfo.version();
private int clientType = DESKTOP_CLIENT;
private String clientAddress = null;
private String clientLanguage = "en";
private boolean ignoreProtocolVersion = false;
// Information about logged in user
private int sessionId;
private int userId;
private String userName;
private AuthenticationType authenticationMethod;
private long userSystemRights;
private boolean passwordExpired;
private int graceLogins;
// Internal communication data
private Socket socket = null;
private NXCPMsgWaitQueue msgWaitQueue = null;
private ReceiverThread recvThread = null;
private HousekeeperThread housekeeperThread = null;
private AtomicLong requestId = new AtomicLong(1);
private boolean connected = false;
private boolean disconnected = false;
private boolean serverConsoleConnected = false;
private Integer serverConsoleConnectionCount = 0;
private Object serverConsoleConnectionLock = new Object();
private boolean allowCompression = false;
private EncryptionContext encryptionContext = null;
private Throwable receiverStopCause = null;
// Communication parameters
private int defaultRecvBufferSize = 4194304; // Default is 4MB
private int maxRecvBufferSize = 33554432; // Max is 32MB
private int connectTimeout = 10000; // Default is 10 seconds
private int commandTimeout = 30000; // Default is 30 seconds
private int serverCommandOutputTimeout = 60000;
// Notification listeners and queue
private LinkedBlockingQueue notificationQueue = new LinkedBlockingQueue(8192);
private Set listeners = new HashSet(0);
private Set consoleListeners = new HashSet(0);
private Map progressListeners = new HashMap(0);
// Message subscriptions
private Map messageSubscriptions = new HashMap(0);
// Received files
private Map receivedFiles = new HashMap();
// Received file updates(for file monitoring)
private Map receivedFileUpdates = new HashMap();
// Server information
private ProtocolVersion protocolVersion;
private String serverVersion = "(unknown)";
private String serverBuild = "(unknown)";
private long serverId = 0;
private String serverTimeZone;
private byte[] serverChallenge = new byte[CLIENT_CHALLENGE_SIZE];
private boolean zoningEnabled = false;
private boolean helpdeskLinkActive = false;
private String tileServerURL;
private String dateFormat;
private String timeFormat;
private String shortTimeFormat;
private int defaultDciRetentionTime;
private int defaultDciPollingInterval;
private boolean strictAlarmStatusFlow;
private boolean timedAlarmAckEnabled;
private int minViewRefreshInterval;
private long serverTime = System.currentTimeMillis();
private long serverTimeRecvTime = System.currentTimeMillis();
private Set serverComponents = new HashSet(0);
private String serverName;
private String serverColor;
private String objectMaintenancePredefinedPeriods;
// Configuration hints
private Map clientConfigurationHints = new HashMap();
// Objects
private Map objectList = new HashMap();
private Map objectListGUID = new HashMap();
private Map zoneList = new HashMap();
private Map objectCategories = new HashMap();
private boolean objectsSynchronized = false;
private Set responsibleUserTags = new HashSet();
// Users
private Map userDatabase = new HashMap();
private Map userDatabaseGUID = new HashMap();
private Set missingUsers = new HashSet(); // users that cannot be synchronized
private boolean userDatabaseSynchronized = false;
private Set userSyncList = new HashSet();
private List callbackList = new ArrayList();
// Event objects
private Map eventTemplates = new HashMap();
private boolean eventTemplatesSynchronized = false;
// Alarm categories
private Map alarmCategories = new HashMap();
private boolean alarmCategoriesSynchronized = false;
// Message of the day
private String messageOfTheDay;
// Registered license problems
private LicenseProblem[] licenseProblems = null;
// Cached list of prediction engines
private List predictionEngines = null;
// TCP proxies
private Map tcpProxies = new HashMap();
private AtomicInteger tcpProxyChannelId = new AtomicInteger(1);
private boolean clientAssignedTcpProxyId = false;
// Set of objects whose child objects were already synchronized
private Set synchronizedObjectSet = new HashSet();
// OUI cache
private OUICache ouiCache;
// Asset management schema
private Map assetManagementSchema = new HashMap();
/**
* Message subscription class
*/
final protected static class MessageSubscription
{
protected int messageCode;
protected long messageId;
/**
* @param messageCode The message code
* @param messageId The message ID
*/
protected MessageSubscription(int messageCode, long messageId)
{
this.messageCode = messageCode;
this.messageId = messageId;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + messageCode;
result = prime * result + (int)(messageId ^ (messageId >>> 32));
return result;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MessageSubscription other = (MessageSubscription)obj;
if (messageCode != other.messageCode)
return false;
if (messageId != other.messageId)
return false;
return true;
}
}
/**
* Receiver thread for NXCSession
*/
private class ReceiverThread extends Thread
{
ReceiverThread()
{
super("Network Message Receiver");
setDaemon(true);
start();
}
@Override
public void run()
{
final NXCPMessageReceiver receiver = new NXCPMessageReceiver(defaultRecvBufferSize, maxRecvBufferSize);
InputStream in;
try
{
in = socket.getInputStream();
}
catch(IOException e)
{
return; // Stop receiver thread if input stream cannot be obtained
}
int errorCount = 0;
while(socket.isConnected())
{
try
{
NXCPMessage msg = receiver.receiveMessage(in, encryptionContext);
errorCount = 0;
switch(msg.getMessageCode())
{
case NXCPCodes.CMD_REQUEST_SESSION_KEY:
setupEncryption(msg);
break;
case NXCPCodes.CMD_KEEPALIVE:
serverTime = msg.getFieldAsInt64(NXCPCodes.VID_TIMESTAMP) * 1000;
serverTimeRecvTime = System.currentTimeMillis();
break;
case NXCPCodes.CMD_OBJECT:
case NXCPCodes.CMD_OBJECT_UPDATE:
if (!msg.getFieldAsBoolean(NXCPCodes.VID_IS_DELETED))
{
final AbstractObject obj = createObjectFromMessage(msg);
synchronized(objectList)
{
objectList.put(obj.getObjectId(), obj);
objectListGUID.put(obj.getGuid(), obj);
if (obj instanceof Zone)
zoneList.put(((Zone)obj).getUIN(), (Zone)obj);
}
if (msg.getMessageCode() == NXCPCodes.CMD_OBJECT_UPDATE)
{
sendNotification(new SessionNotification(SessionNotification.OBJECT_CHANGED, obj.getObjectId(), obj));
}
}
else
{
long objectId = msg.getFieldAsInt32(NXCPCodes.VID_OBJECT_ID);
synchronized(objectList)
{
AbstractObject object = objectList.get(objectId);
if (object != null)
{
objectListGUID.remove(object.getGuid());
objectList.remove(objectId);
if (object instanceof Zone)
zoneList.remove(((Zone)object).getUIN());
}
}
sendNotification(new SessionNotification(SessionNotification.OBJECT_DELETED, objectId));
}
break;
case NXCPCodes.CMD_OBJECT_LIST_END:
completeSync(syncObjects);
break;
case NXCPCodes.CMD_OBJECT_CATEGORY_UPDATE:
processObjectCategoryUpdate(msg);
break;
case NXCPCodes.CMD_GEO_AREA_UPDATE:
processGeoAreaUpdate(msg);
break;
case NXCPCodes.CMD_USER_DATA:
final User user = new User(msg);
synchronized(userDatabase)
{
if (user.isDeleted())
{
AbstractUserObject o = userDatabase.remove(user.getId());
if (o != null)
userDatabaseGUID.remove(o.getGuid());
missingUsers.add(user.getId());
}
else
{
userDatabase.put(user.getId(), user);
userDatabaseGUID.put(user.getGuid(), user);
missingUsers.remove(user.getId());
}
}
break;
case NXCPCodes.CMD_GROUP_DATA:
final UserGroup group = new UserGroup(msg);
synchronized(userDatabase)
{
if (group.isDeleted())
{
AbstractUserObject o = userDatabase.remove(group.getId());
if (o != null)
userDatabaseGUID.remove(o.getGuid());
missingUsers.add(group.getId());
}
else
{
userDatabase.put(group.getId(), group);
userDatabaseGUID.put(group.getGuid(), group);
missingUsers.add(group.getId());
}
}
break;
case NXCPCodes.CMD_USER_DB_EOF:
completeSync(syncUserDB);
break;
case NXCPCodes.CMD_USER_DB_UPDATE:
processUserDBUpdate(msg);
break;
case NXCPCodes.CMD_ALARM_UPDATE:
sendNotification(new SessionNotification(
msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE) + SessionNotification.NOTIFY_BASE, new Alarm(msg)));
break;
case NXCPCodes.CMD_BULK_ALARM_STATE_CHANGE:
processBulkAlarmStateChange(msg);
break;
case NXCPCodes.CMD_JOB_CHANGE_NOTIFICATION:
sendNotification(new SessionNotification(SessionNotification.JOB_CHANGE, new ServerJob(msg)));
break;
case NXCPCodes.CMD_FILE_DATA:
processFileData(msg);
break;
case NXCPCodes.CMD_FILE_MONITORING:
processFileUpdate(msg);
break;
case NXCPCodes.CMD_ABORT_FILE_TRANSFER:
processFileTransferError(msg);
break;
case NXCPCodes.CMD_NOTIFY:
processNotificationMessage(msg, true);
break;
case NXCPCodes.CMD_RS_NOTIFY:
processNotificationMessage(msg, false);
break;
case NXCPCodes.CMD_EVENTLOG_RECORDS:
processNewEvents(msg);
break;
case NXCPCodes.CMD_TRAP_LOG_RECORDS:
processNewTraps(msg);
break;
case NXCPCodes.CMD_SYSLOG_RECORDS:
processSyslogRecords(msg);
break;
case NXCPCodes.CMD_ACTION_DB_UPDATE:
processActionConfigChange(msg);
break;
case NXCPCodes.CMD_EVENT_DB_UPDATE:
processEventConfigChange(msg);
break;
case NXCPCodes.CMD_TRAP_CFG_UPDATE:
processTrapConfigChange(msg);
break;
case NXCPCodes.CMD_ADM_MESSAGE:
processConsoleOutput(msg);
break;
case NXCPCodes.CMD_IMAGE_LIBRARY_UPDATE:
processImageLibraryUpdate(msg);
break;
case NXCPCodes.CMD_GRAPH_UPDATE:
GraphDefinition graph = GraphDefinition.createGraphSettings(msg, NXCPCodes.VID_GRAPH_LIST_BASE);
sendNotification(new SessionNotification(SessionNotification.PREDEFINED_GRAPHS_CHANGED, graph.getId(), graph));
break;
case NXCPCodes.CMD_ALARM_CATEGORY_UPDATE:
processAlarmCategoryConfigChange(msg);
break;
case NXCPCodes.CMD_THRESHOLD_UPDATE:
processThresholdChange(msg);
break;
case NXCPCodes.CMD_TCP_PROXY_DATA:
processTcpProxyData((int)msg.getMessageId(), msg.getBinaryData());
break;
case NXCPCodes.CMD_CLOSE_TCP_PROXY:
processTcpProxyClosure(msg.getFieldAsInt32(NXCPCodes.VID_CHANNEL_ID), msg.getFieldAsInt32(NXCPCodes.VID_RCC));
break;
case NXCPCodes.CMD_MODIFY_NODE_DCI:
DataCollectionObject dco;
int type = msg.getFieldAsInt32(NXCPCodes.VID_DCOBJECT_TYPE);
switch(type)
{
case DataCollectionObject.DCO_TYPE_ITEM:
dco = new DataCollectionItem(null, msg);
break;
case DataCollectionObject.DCO_TYPE_TABLE:
dco = new DataCollectionTable(null, msg);
break;
default:
dco = null;
break;
}
sendNotification(
new SessionNotification(SessionNotification.DCI_UPDATE, msg.getFieldAsInt64(NXCPCodes.VID_OBJECT_ID),
dco));
break;
case NXCPCodes.CMD_DELETE_NODE_DCI:
sendNotification(
new SessionNotification(SessionNotification.DCI_DELETE, msg.getFieldAsInt64(NXCPCodes.VID_OBJECT_ID),
(Long)msg.getFieldAsInt64(NXCPCodes.VID_DCI_ID)));
break;
case NXCPCodes.CMD_SET_DCI_STATUS:
int itemCount = msg.getFieldAsInt32(NXCPCodes.VID_NUM_ITEMS);
final long[] itemList = new long[itemCount];
int pos = 0;
for(int i = 0; i < itemCount; i++)
{
itemList[pos++] = msg.getFieldAsInt32(NXCPCodes.VID_ITEM_LIST + i);
}
sendNotification(new SessionNotification(SessionNotification.DCI_STATE_CHANGE,
msg.getFieldAsInt64(NXCPCodes.VID_OBJECT_ID),
new DCOStatusHolder(itemList, msg.getFieldAsInt32(NXCPCodes.VID_DCI_STATUS))));
break;
case NXCPCodes.CMD_UPDATE_AGENT_POLICY:
sendNotification(new SessionNotification(SessionNotification.POLICY_MODIFIED,
msg.getFieldAsInt64(NXCPCodes.VID_TEMPLATE_ID), new AgentPolicy(msg)));
break;
case NXCPCodes.CMD_DELETE_AGENT_POLICY:
sendNotification(new SessionNotification(SessionNotification.POLICY_DELETED,
msg.getFieldAsInt64(NXCPCodes.VID_TEMPLATE_ID), msg.getFieldAsUUID(NXCPCodes.VID_GUID)));
break;
case NXCPCodes.CMD_UPDATE_SYSTEM_ACCESS_RIGHTS:
userSystemRights = msg.getFieldAsInt64(NXCPCodes.VID_USER_SYS_RIGHTS);
sendNotification(new SessionNotification(SessionNotification.SYSTEM_ACCESS_CHANGED, userSystemRights));
break;
case NXCPCodes.CMD_UPDATE_BIZSVC_CHECK:
sendNotification(
new SessionNotification(SessionNotification.BIZSVC_CHECK_MODIFIED, msg.getFieldAsInt64(NXCPCodes.VID_CHECK_LIST_BASE),
new BusinessServiceCheck(msg, NXCPCodes.VID_CHECK_LIST_BASE)));
break;
case NXCPCodes.CMD_DELETE_BIZSVC_CHECK:
sendNotification(new SessionNotification(SessionNotification.BIZSVC_CHECK_DELETED, msg.getFieldAsInt64(NXCPCodes.VID_CHECK_ID)));
break;
case NXCPCodes.CMD_AGENT_TUNNEL_UPDATE:
sendNotification(
new SessionNotification(msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE) + SessionNotification.NOTIFY_BASE, new AgentTunnel(msg, NXCPCodes.VID_ELEMENT_LIST_BASE)));
break;
case NXCPCodes.CMD_UPDATE_ASSET_ATTRIBUTE:
AssetAttribute attr = new AssetAttribute(msg, NXCPCodes.VID_AM_ATTRIBUTES_BASE);
sendNotification(new SessionNotification(SessionNotification.AM_ATTRIBUTE_UPDATED, 0, attr));
synchronized(assetManagementSchema)
{
assetManagementSchema.put(attr.getName(), attr);
}
break;
case NXCPCodes.CMD_DELETE_ASSET_ATTRIBUTE:
String attrName = msg.getFieldAsString(NXCPCodes.VID_NAME);
sendNotification(new SessionNotification(SessionNotification.AM_ATTRIBUTE_DELETED, 0, attrName));
synchronized(assetManagementSchema)
{
assetManagementSchema.remove(attrName);
}
break;
default:
// Check subscriptions
synchronized(messageSubscriptions)
{
MessageSubscription s = new MessageSubscription(msg.getMessageCode(), msg.getMessageId());
MessageHandler handler = messageSubscriptions.get(s);
if (handler != null)
{
try
{
if (handler.processMessage(msg))
msg = null;
}
catch(Exception e)
{
logger.error("Exception in message handler", e);
}
if (handler.isComplete())
messageSubscriptions.remove(s);
else
handler.setLastMessageTimestamp(System.currentTimeMillis());
}
}
if (msg != null)
{
if (msg.getMessageCode() >= 0x1000)
{
// Custom message
sendNotification(new SessionNotification(SessionNotification.CUSTOM_MESSAGE, msg));
}
msgWaitQueue.putMessage(msg);
}
break;
}
}
catch(IOException e)
{
if (!disconnected)
{
logger.debug("Receiver error", e);
receiverStopCause = e;
}
break; // Stop on read errors
}
catch(NXCPException e)
{
logger.debug("Receiver error", e);
if (e.getErrorCode() == NXCPException.SESSION_CLOSED)
{
receiverStopCause = e;
break;
}
errorCount++;
}
catch(NXCException e)
{
logger.debug("Receiver error", e);
if (e.getErrorCode() == RCC.ENCRYPTION_ERROR)
{
receiverStopCause = e;
break;
}
errorCount++;
}
if (errorCount > 100)
{
receiverStopCause = new NXCPException(NXCPException.FATAL_PROTOCOL_ERROR);
break;
}
}
synchronized(tcpProxies)
{
Throwable cause = (receiverStopCause != null) ? receiverStopCause : new NXCPException(NXCPException.SESSION_CLOSED);
for(TcpProxy p : tcpProxies.values())
p.abort(cause);
}
if (!disconnected)
disconnect(SessionNotification.CONNECTION_BROKEN);
logger.info("Network receiver thread stopped");
msgWaitQueue.shutdown();
}
/**
* Process server console output
*
* @param msg notification message
*/
private void processConsoleOutput(NXCPMessage msg)
{
final String text = msg.getFieldAsString(NXCPCodes.VID_MESSAGE);
synchronized(consoleListeners)
{
for(ServerConsoleListener l : consoleListeners)
{
l.onConsoleOutput(text);
}
}
}
/**
* Process event notification messages.
*
* @param msg NXCP message
*/
private void processNewEvents(final NXCPMessage msg)
{
int count = msg.getFieldAsInt32(NXCPCodes.VID_NUM_RECORDS);
int order = msg.getFieldAsInt32(NXCPCodes.VID_RECORDS_ORDER);
long varId = NXCPCodes.VID_EVENTLOG_MSG_BASE;
for(int i = 0; i < count; i++)
{
Event event = new Event(msg, varId);
sendNotification(new SessionNotification(SessionNotification.NEW_EVENTLOG_RECORD, order, event));
}
}
/**
* Process SNMP trap notification messages.
*
* @param msg NXCP message
*/
private void processNewTraps(final NXCPMessage msg)
{
int count = msg.getFieldAsInt32(NXCPCodes.VID_NUM_RECORDS);
int order = msg.getFieldAsInt32(NXCPCodes.VID_RECORDS_ORDER);
long varId = NXCPCodes.VID_TRAP_LOG_MSG_BASE;
for(int i = 0; i < count; i++)
{
SnmpTrapLogRecord trap = new SnmpTrapLogRecord(msg, varId);
sendNotification(new SessionNotification(SessionNotification.NEW_SNMP_TRAP, order, trap));
}
}
/**
* Process syslog messages.
*
* @param msg NXCP message
*/
private void processSyslogRecords(final NXCPMessage msg)
{
int count = msg.getFieldAsInt32(NXCPCodes.VID_NUM_RECORDS);
int order = msg.getFieldAsInt32(NXCPCodes.VID_RECORDS_ORDER);
long varId = NXCPCodes.VID_SYSLOG_MSG_BASE;
for(int i = 0; i < count; i++)
{
SyslogRecord record = new SyslogRecord(msg, varId);
sendNotification(new SessionNotification(SessionNotification.NEW_SYSLOG_RECORD, order, record));
}
}
/**
* Process CMD_BULK_ALARM_STATE_CHANGE notification message
*
* @param msg NXCP message
*/
private void processBulkAlarmStateChange(final NXCPMessage msg)
{
int code = msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE) + SessionNotification.NOTIFY_BASE;
sendNotification(new SessionNotification(code, new BulkAlarmStateChangeData(msg)));
}
/**
* Process CMD_NOTIFY message
*
* @param msg NXCP message
*/
private void processNotificationMessage(final NXCPMessage msg, boolean shiftCode)
{
int code = msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE);
if (shiftCode)
code += SessionNotification.NOTIFY_BASE;
long data = msg.getFieldAsInt64(NXCPCodes.VID_NOTIFICATION_DATA);
switch(code)
{
case SessionNotification.ALARM_STATUS_FLOW_CHANGED:
strictAlarmStatusFlow = ((int)data != 0);
break;
case SessionNotification.RELOAD_EVENT_DB:
if (eventTemplatesSynchronized)
{
resyncEventTemplates();
}
break;
case SessionNotification.SESSION_KILLED:
case SessionNotification.SERVER_SHUTDOWN:
case SessionNotification.CONNECTION_BROKEN:
backgroundDisconnect(code);
return; // backgroundDisconnect will send disconnect notification
case SessionNotification.OBJECT_CATEGORY_DELETED:
synchronized(objectCategories)
{
objectCategories.remove((int)data);
}
break;
}
sendNotification(new SessionNotification(code, data));
}
/**
* Process CMD_FILE_MONITORING message
*
* @param msg NXCP message
*/
private void processFileUpdate(final NXCPMessage msg)
{
UUID monitorId = msg.getFieldAsUUID(NXCPCodes.VID_MONITOR_ID);
String newData = msg.getFieldAsString(NXCPCodes.VID_FILE_DATA);
synchronized(receivedFileUpdates)
{
String existingData = receivedFileUpdates.get(monitorId);
receivedFileUpdates.put(monitorId, (existingData != null) ? existingData + newData : newData);
receivedFileUpdates.notifyAll();
}
}
/**
* Process file data
*
* @param msg
*/
private void processFileData(final NXCPMessage msg)
{
long id = msg.getMessageId();
NXCReceivedFile file;
synchronized(receivedFiles)
{
file = receivedFiles.get(id);
if (file == null)
{
file = new NXCReceivedFile(id);
receivedFiles.put(id, file);
}
}
int bytes = file.writeData(msg.getBinaryData(), msg.isCompressedStream());
notifyProgressListener(id, bytes);
if (msg.isEndOfFile())
{
file.close();
synchronized(receivedFiles)
{
receivedFiles.notifyAll();
}
}
}
/**
* Process file transfer error
*
* @param msg
*/
private void processFileTransferError(final NXCPMessage msg)
{
long id = msg.getMessageId();
NXCReceivedFile file;
synchronized(receivedFiles)
{
file = receivedFiles.get(id);
if (file == null)
{
file = new NXCReceivedFile(id);
receivedFiles.put(id, file);
}
file.abortTransfer(msg.getFieldAsBoolean(NXCPCodes.VID_JOB_CANCELLED));
receivedFiles.notifyAll();
}
}
/**
* Process updates in user database
*
* @param msg Notification message
*/
private void processUserDBUpdate(final NXCPMessage msg)
{
final int code = msg.getFieldAsInt32(NXCPCodes.VID_UPDATE_TYPE);
final long id = msg.getFieldAsInt64(NXCPCodes.VID_USER_ID);
AbstractUserObject object = null;
switch(code)
{
case SessionNotification.USER_DB_OBJECT_CREATED:
case SessionNotification.USER_DB_OBJECT_MODIFIED:
object = ((id & 0x40000000) != 0) ? new UserGroup(msg) : new User(msg);
synchronized(userDatabase)
{
userDatabase.put(id, object);
userDatabaseGUID.put(object.getGuid(), object);
missingUsers.remove(id);
}
break;
case SessionNotification.USER_DB_OBJECT_DELETED:
synchronized(userDatabase)
{
object = userDatabase.get(id);
if (object != null)
{
userDatabase.remove(id);
userDatabaseGUID.remove(object.getGuid());
}
missingUsers.add(id);
}
break;
}
// Send notification if changed object was found in local database copy
// or added to it and notification code was known
if (object != null)
sendNotification(new SessionNotification(SessionNotification.USER_DB_CHANGED, code, object));
}
/**
* Process server notification on SNMP trap configuration change
*
* @param msg notification message
*/
private void processTrapConfigChange(final NXCPMessage msg)
{
int code = msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE) + SessionNotification.NOTIFY_BASE;
long id = msg.getFieldAsInt64(NXCPCodes.VID_TRAP_ID);
SnmpTrap trap = (code != SessionNotification.TRAP_CONFIGURATION_DELETED) ? new SnmpTrap(msg) : null;
sendNotification(new SessionNotification(code, id, trap));
}
/**
* Process server notification on action configuration change
*
* @param msg notification message
*/
private void processActionConfigChange(final NXCPMessage msg)
{
int code = msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE) + SessionNotification.NOTIFY_BASE;
long id = msg.getFieldAsInt64(NXCPCodes.VID_ACTION_ID);
ServerAction action = (code != SessionNotification.ACTION_DELETED) ? new ServerAction(msg) : null;
sendNotification(new SessionNotification(code, id, action));
}
/**
* Process server notification on event configuration change
*
* @param msg notification message
*/
private void processEventConfigChange(final NXCPMessage msg)
{
int code = msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE) + SessionNotification.NOTIFY_BASE;
long eventCode = msg.getFieldAsInt64(NXCPCodes.VID_EVENT_CODE);
EventTemplate tmpl = (code != SessionNotification.EVENT_TEMPLATE_DELETED) ?
new EventTemplate(msg, NXCPCodes.VID_ELEMENT_LIST_BASE) :
null;
if (eventTemplatesSynchronized)
{
synchronized(eventTemplates)
{
if (code == SessionNotification.EVENT_TEMPLATE_DELETED)
{
eventTemplates.remove(eventCode);
}
else
{
eventTemplates.put(tmpl.getCode(), tmpl);
}
}
}
sendNotification(new SessionNotification(code, tmpl == null ? eventCode : tmpl.getCode(), tmpl));
}
/**
* Process server notification on image library change
*
* @param msg notification message
*/
private void processImageLibraryUpdate(NXCPMessage msg)
{
final UUID imageGuid = msg.getFieldAsUUID(NXCPCodes.VID_GUID);
final int flags = msg.getFieldAsInt32(NXCPCodes.VID_FLAGS);
sendNotification(new SessionNotification(SessionNotification.IMAGE_LIBRARY_CHANGED,
flags == 0 ? SessionNotification.IMAGE_UPDATED : SessionNotification.IMAGE_DELETED, imageGuid));
}
/**
* Process object category update
*
* @param msg notification message
*/
private void processObjectCategoryUpdate(NXCPMessage msg)
{
ObjectCategory category = new ObjectCategory(msg, NXCPCodes.VID_ELEMENT_LIST_BASE);
synchronized(objectCategories)
{
objectCategories.put(category.getId(), category);
}
sendNotification(new SessionNotification(SessionNotification.OBJECT_CATEGORY_UPDATED, category.getId(), category));
}
/**
* Process geographical area update
*
* @param msg notification message
*/
private void processGeoAreaUpdate(NXCPMessage msg)
{
GeoArea area = new GeoArea(msg, NXCPCodes.VID_ELEMENT_LIST_BASE);
sendNotification(new SessionNotification(SessionNotification.GEO_AREA_UPDATED, area.getId(), area));
}
/**
* Process server notification on threshold change
*
* @param msg notification message
*/
public void processThresholdChange(NXCPMessage msg)
{
sendNotification(new SessionNotification(SessionNotification.THRESHOLD_STATE_CHANGED,
msg.getFieldAsInt64(NXCPCodes.VID_OBJECT_ID), new ThresholdStateChange(msg)));
}
/**
* Process server notification on alarm category configuration change
*
* @param msg notification message
*/
private void processAlarmCategoryConfigChange(final NXCPMessage msg)
{
int code = msg.getFieldAsInt32(NXCPCodes.VID_NOTIFICATION_CODE) + SessionNotification.NOTIFY_BASE;
long categoryId = msg.getFieldAsInt64(NXCPCodes.VID_ELEMENT_LIST_BASE);
AlarmCategory ac = (code != SessionNotification.ALARM_CATEGORY_DELETED) ?
new AlarmCategory(msg, NXCPCodes.VID_ELEMENT_LIST_BASE) :
null;
if (alarmCategoriesSynchronized)
{
synchronized(alarmCategories)
{
if (code == SessionNotification.ALARM_CATEGORY_DELETED)
{
alarmCategories.remove(categoryId);
}
else
{
alarmCategories.put(categoryId, ac);
}
}
}
sendNotification(new SessionNotification(code, categoryId, ac));
}
/**
* Process TCP proxy data
*
* @param channelId proxy channel ID
* @param data received data block
*/
private void processTcpProxyData(int channelId, byte[] data)
{
TcpProxy proxy;
synchronized(tcpProxies)
{
proxy = tcpProxies.get(channelId);
}
if (proxy != null)
{
proxy.processRemoteData(data);
}
else
{
logger.debug("Received TCP proxy data for unknown channel ID " + channelId);
}
}
/**
* Process TCP proxy closure.
*
* @param channelId proxy channel ID
*/
private void processTcpProxyClosure(int channelId, int rcc)
{
TcpProxy proxy;
synchronized(tcpProxies)
{
proxy = tcpProxies.remove(channelId);
}
if (proxy != null)
{
if (rcc == RCC.SUCCESS)
proxy.localClose();
else
proxy.abort(new NXCException(rcc));
}
}
}
/**
* Housekeeper thread - cleans received files, etc.
*
* @author Victor
*/
private class HousekeeperThread extends Thread
{
private boolean stopFlag = false;
HousekeeperThread()
{
setDaemon(true);
start();
}
/**
* @see java.lang.Thread#run()
*/
@Override
public void run()
{
while(!stopFlag)
{
try
{
sleep(1000);
}
catch(InterruptedException e)
{
}
long currTime = System.currentTimeMillis();
// Check for old entries in received files
synchronized(receivedFiles)
{
Iterator it = receivedFiles.values().iterator();
while(it.hasNext())
{
NXCReceivedFile file = it.next();
if (file.getTimestamp() + RECEIVED_FILE_TTL < currTime)
{
file.getFile().delete();
it.remove();
}
}
}
// Check timeouts on message subscriptions
synchronized(messageSubscriptions)
{
Iterator> it = messageSubscriptions.entrySet().iterator();
while(it.hasNext())
{
Entry e = it.next();
MessageHandler h = e.getValue();
if (currTime - h.getLastMessageTimestamp() > h.getMessageWaitTimeout())
{
h.setExpired();
it.remove();
}
}
}
}
}
/**
* @param stopFlag the stopFlag to set
*/
public void setStopFlag(boolean stopFlag)
{
this.stopFlag = stopFlag;
}
}
/**
* Notification processor
*/
private class NotificationProcessor extends Thread
{
private SessionListener[] cachedListenerList = new SessionListener[0];
NotificationProcessor()
{
setName("Session Notification Processor");
setDaemon(true);
start();
}
/**
* @see java.lang.Thread#run()
*/
@Override
public void run()
{
while(true)
{
SessionNotification n;
try
{
n = notificationQueue.take();
}
catch(InterruptedException e)
{
continue;
}
if (n.getCode() == SessionNotification.STOP_PROCESSING_THREAD)
break;
if (n.getCode() == SessionNotification.UPDATE_LISTENER_LIST)
{
synchronized(listeners)
{
cachedListenerList = listeners.toArray(new SessionListener[listeners.size()]);
}
continue;
}
// loop must be on listeners set copy to prevent
// possible deadlock when one of the listeners calls
// syncExec on UI thread while UI thread trying to add
// new listener and stays locked inside addListener
for(SessionListener l : cachedListenerList)
{
try
{
l.notificationHandler(n);
}
catch(Exception e)
{
logger.error("Unhandled exception in notification handler", e);
}
}
}
cachedListenerList = null;
}
}
/**
* User synchronization thread
*/
class BackgroundUserSync extends Thread
{
public BackgroundUserSync()
{
setName("BackgroundUserSync");
setDaemon(true);
start();
}
/**
* @see java.lang.Thread#run()
*/
@Override
public void run()
{
while(true)
{
synchronized(userSyncList)
{
while(userSyncList.isEmpty())
{
try
{
userSyncList.wait();
}
catch(InterruptedException e)
{
}
}
}
// Delay actual sync in case more synchronization requests will come
try
{
Thread.sleep(200);
}
catch(InterruptedException e)
{
}
Set userSyncListCopy;
List callbackListCopy;
synchronized(userSyncList)
{
userSyncListCopy = userSyncList;
userSyncList = new HashSet();
callbackListCopy = callbackList;
callbackList = new ArrayList();
}
try
{
syncMissingUsers(userSyncListCopy);
for(Runnable cb : callbackListCopy)
cb.run();
}
catch(Exception e)
{
logger.error("Exception while synchronizing user database objects", e);
}
}
}
}
/**
* Create session object that will connect to given address on default port (4701) without encryption.
*
* @param connAddress server host name or IP address
*/
public NXCSession(String connAddress)
{
this(connAddress, DEFAULT_CONN_PORT, false);
}
/**
* Create session object that will connect to given address on given port without encryption.
*
* @param connAddress server host name or IP address
* @param connPort TCP port
*/
public NXCSession(String connAddress, int connPort)
{
this(connAddress, connPort, false);
}
/**
* Create session object that will connect to given address on given port.
*
* @param connAddress server host name or IP address
* @param connPort TCP port
* @param connUseEncryption setup encrypted session if true
*/
public NXCSession(String connAddress, int connPort, boolean connUseEncryption)
{
this.connAddress = connAddress;
this.connPort = connPort;
this.connUseEncryption = connUseEncryption;
ouiCache = new OUICache(this);
}
/**
* Create custom object from NXCP message. May be overridden by derived classes to create custom
* NetXMS objects. This method called before standard object creation, so it can be used for
* overriding standard object classes. If this method returns null, standard object
* creation mechanism will be used. Default implementation will always return null.
*
* @param objectClass NetXMS object class ID
* @param msg Source NXCP message
* @return NetXMS object or null if object cannot be created
*/
protected AbstractObject createCustomObjectFromMessage(int objectClass, NXCPMessage msg)
{
return null;
}
/**
* Create object from message
*
* @param msg Source NXCP message
* @return NetXMS object
*/
private AbstractObject createObjectFromMessage(NXCPMessage msg)
{
final int objectClass = msg.getFieldAsInt32(NXCPCodes.VID_OBJECT_CLASS);
AbstractObject object = createCustomObjectFromMessage(objectClass, msg);
if (object != null)
return object;
switch(objectClass)
{
case AbstractObject.OBJECT_ACCESSPOINT:
object = new AccessPoint(msg, this);
break;
case AbstractObject.OBJECT_ASSET:
object = new Asset(msg, this);
break;
case AbstractObject.OBJECT_ASSETGROUP:
object = new AssetGroup(msg, this);
break;
case AbstractObject.OBJECT_ASSETROOT:
object = new AssetRoot(msg, this);
break;
case AbstractObject.OBJECT_BUSINESSSERVICE:
object = new BusinessService(msg, this);
break;
case AbstractObject.OBJECT_BUSINESSSERVICEPROTOTYPE:
object = new BusinessServicePrototype(msg, this);
break;
case AbstractObject.OBJECT_BUSINESSSERVICEROOT:
object = new BusinessServiceRoot(msg, this);
break;
case AbstractObject.OBJECT_CHASSIS:
object = new Chassis(msg, this);
break;
case AbstractObject.OBJECT_CLUSTER:
object = new Cluster(msg, this);
break;
case AbstractObject.OBJECT_CONDITION:
object = new Condition(msg, this);
break;
case AbstractObject.OBJECT_CONTAINER:
object = new Container(msg, this);
break;
case AbstractObject.OBJECT_DASHBOARDGROUP:
object = new DashboardGroup(msg, this);
break;
case AbstractObject.OBJECT_DASHBOARD:
object = new Dashboard(msg, this);
break;
case AbstractObject.OBJECT_DASHBOARDROOT:
object = new DashboardRoot(msg, this);
break;
case AbstractObject.OBJECT_INTERFACE:
object = new Interface(msg, this);
break;
case AbstractObject.OBJECT_MOBILEDEVICE:
object = new MobileDevice(msg, this);
break;
case AbstractObject.OBJECT_NETWORK:
object = new EntireNetwork(msg, this);
break;
case AbstractObject.OBJECT_NETWORKMAP:
object = new NetworkMap(msg, this);
break;
case AbstractObject.OBJECT_NETWORKMAPGROUP:
object = new NetworkMapGroup(msg, this);
break;
case AbstractObject.OBJECT_NETWORKMAPROOT:
object = new NetworkMapRoot(msg, this);
break;
case AbstractObject.OBJECT_NETWORKSERVICE:
object = new NetworkService(msg, this);
break;
case AbstractObject.OBJECT_NODE:
object = new Node(msg, this);
break;
case AbstractObject.OBJECT_RACK:
object = new Rack(msg, this);
break;
case AbstractObject.OBJECT_SENSOR:
object = new Sensor(msg, this);
break;
case AbstractObject.OBJECT_SERVICEROOT:
object = new ServiceRoot(msg, this);
break;
case AbstractObject.OBJECT_SUBNET:
object = new Subnet(msg, this);
break;
case AbstractObject.OBJECT_TEMPLATE:
object = new Template(msg, this);
break;
case AbstractObject.OBJECT_TEMPLATEGROUP:
object = new TemplateGroup(msg, this);
break;
case AbstractObject.OBJECT_TEMPLATEROOT:
object = new TemplateRoot(msg, this);
break;
case AbstractObject.OBJECT_VPNCONNECTOR:
object = new VPNConnector(msg, this);
break;
case AbstractObject.OBJECT_ZONE:
object = new Zone(msg, this);
break;
default:
object = new GenericObject(msg, this);
break;
}
return object;
}
/**
* Setup encryption
*
* @param msg CMD_REQUEST_SESSION_KEY message
* @throws IOException
* @throws NXCException
*/
private void setupEncryption(NXCPMessage msg) throws IOException, NXCException
{
final NXCPMessage response = new NXCPMessage(NXCPCodes.CMD_SESSION_KEY, msg.getMessageId());
response.setEncryptionDisabled(true);
try
{
encryptionContext = EncryptionContext.createInstance(msg);
response.setField(NXCPCodes.VID_SESSION_KEY, encryptionContext.getEncryptedSessionKey());
response.setField(NXCPCodes.VID_SESSION_IV, encryptionContext.getEncryptedIv());
response.setFieldInt16(NXCPCodes.VID_CIPHER, encryptionContext.getCipher());
response.setFieldInt16(NXCPCodes.VID_KEY_LENGTH, encryptionContext.getKeyLength());
response.setFieldInt16(NXCPCodes.VID_IV_LENGTH, encryptionContext.getIvLength());
response.setFieldInt32(NXCPCodes.VID_RCC, RCC.SUCCESS);
logger.debug("Cipher selected: " + EncryptionContext.getCipherName(encryptionContext.getCipher()));
logger.debug("Server key fingerprint: " + encryptionContext.getServerKeyFingerprint());
}
catch(Exception e)
{
logger.error("Failed to create encryption context", e);
response.setFieldInt32(NXCPCodes.VID_RCC, RCC.NO_CIPHERS);
}
sendMessage(response);
}
/**
* Wait for synchronization completion
*/
private void waitForSync(final Semaphore syncObject, final int timeout) throws NXCException
{
if (timeout == 0)
{
syncObject.acquireUninterruptibly();
}
else
{
long actualTimeout = timeout;
boolean success = false;
while(actualTimeout > 0)
{
long startTime = System.currentTimeMillis();
try
{
if (syncObject.tryAcquire(actualTimeout, TimeUnit.MILLISECONDS))
{
success = true;
syncObject.release();
break;
}
}
catch(InterruptedException e)
{
}
actualTimeout -= System.currentTimeMillis() - startTime;
}
if (!success)
throw new NXCException(RCC.TIMEOUT);
}
}
/**
* Report synchronization completion
*
* @param syncObject Synchronization object
*/
private void completeSync(final Semaphore syncObject)
{
syncObject.release();
}
/**
* Add notification listener
*
* @param listener Listener to add
*/
public void addListener(SessionListener listener)
{
boolean changed;
synchronized(listeners)
{
changed = listeners.add(listener);
}
if (changed)
notificationQueue.offer(new SessionNotification(SessionNotification.UPDATE_LISTENER_LIST));
}
/**
* Remove notification listener
*
* @param listener Listener to remove
*/
public void removeListener(SessionListener listener)
{
boolean changed;
synchronized(listeners)
{
changed = listeners.remove(listener);
}
if (changed)
notificationQueue.offer(new SessionNotification(SessionNotification.UPDATE_LISTENER_LIST));
}
/**
* Add server console listener
*
* @param listener The ServerConsoleListener to add
*/
public void addConsoleListener(ServerConsoleListener listener)
{
synchronized(consoleListeners)
{
consoleListeners.add(listener);
}
}
/**
* Remove server console listener
*
* @param listener The ServerConsoleListener to remove
*/
public void removeConsoleListener(ServerConsoleListener listener)
{
synchronized(consoleListeners)
{
consoleListeners.remove(listener);
}
}
/**
* Subscribe to specific messages
*
* @param messageCode The message code
* @param messageId The message ID
* @param handler The message handler
*/
public void addMessageSubscription(int messageCode, long messageId, MessageHandler handler)
{
synchronized(messageSubscriptions)
{
messageSubscriptions.put(new MessageSubscription(messageCode, messageId), handler);
}
}
/**
* Remove message subscription
*
* @param messageCode The message code
* @param messageId The message ID
*/
public void removeMessageSubscription(int messageCode, long messageId)
{
synchronized(messageSubscriptions)
{
messageSubscriptions.remove(new MessageSubscription(messageCode, messageId));
}
}
/**
* Call notification handlers on all registered listeners
*
* @param n Notification object
*/
protected void sendNotification(SessionNotification n)
{
if (!notificationQueue.offer(n))
{
logger.warn("Notification processing queue is full");
}
}
/**
* Send message to server
*
* @param msg Message to sent
* @throws IOException in case of socket communication failure
* @throws NXCException in case of encryption error
*/
public synchronized void sendMessage(final NXCPMessage msg) throws IOException, NXCException
{
if (socket == null)
{
throw new IllegalStateException("Not connected to the server. Did you forgot to call connect() first?");
}
final OutputStream outputStream = socket.getOutputStream();
byte[] message;
if ((encryptionContext != null) && !msg.isEncryptionDisabled())
{
try
{
message = encryptionContext.encryptMessage(msg, allowCompression);
}
catch(GeneralSecurityException e)
{
throw new NXCException(RCC.ENCRYPTION_ERROR);
}
}
else
{
message = msg.createNXCPMessage(allowCompression);
}
outputStream.write(message);
}
/**
* Send "abort file transfer" message
*
* @param requestId request ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if operation was timed out
*/
private void abortFileTransfer(long requestId) throws IOException, NXCException
{
NXCPMessage msg = new NXCPMessage(NXCPCodes.CMD_ABORT_FILE_TRANSFER, requestId);
msg.setBinaryMessage(true);
msg.setBinaryData(new byte[0]);
sendMessage(msg);
}
/**
* Send file over NXCP
*
* @param requestId request ID
* @param file source file to be sent
* @param listener progress listener
* @param allowStreamCompression true if data stream compression is allowed
* @param offset offset to start data send or 0 if from the start
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
protected void sendFile(final long requestId, final File file, ProgressListener listener, boolean allowStreamCompression, long offset)
throws IOException, NXCException
{
if (listener != null)
listener.setTotalWorkAmount(file.length());
InputStream inputStream;
try
{
inputStream = new BufferedInputStream(new FileInputStream(file));
}
catch(IOException e)
{
abortFileTransfer(requestId);
throw e;
}
sendFileStream(requestId, inputStream, listener, allowStreamCompression && (file.length() > 1024), offset);
inputStream.close();
}
/**
* Send block of data as binary message
*
* @param requestId request ID
* @param data file data
* @param listener progress listener
* @param allowStreamCompression true if data stream compression is allowed
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
protected void sendFile(final long requestId, final byte[] data, ProgressListener listener, boolean allowStreamCompression)
throws IOException, NXCException
{
if (listener != null)
listener.setTotalWorkAmount(data.length);
final InputStream inputStream = new ByteArrayInputStream(data);
sendFileStream(requestId, inputStream, listener, allowStreamCompression, 0);
inputStream.close();
}
/**
* Send binary message, data loaded from provided input stream and splitted
* into chunks of {@value FILE_BUFFER_SIZE} bytes
*
* @param requestId request ID
* @param inputStream data input stream
* @param listener progress listener
* @param allowStreamCompression true if data stream compression is allowed
* @param offset offset to start data send or 0 if from the start
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private void sendFileStream(final long requestId, final InputStream inputStream, ProgressListener listener,
boolean allowStreamCompression, long offset) throws IOException, NXCException
{
NXCPMessage msg = new NXCPMessage(NXCPCodes.CMD_FILE_DATA, requestId);
msg.setBinaryMessage(true);
inputStream.skip(offset);
Deflater compressor = allowStreamCompression ? new Deflater(9) : null;
msg.setStream(true, allowStreamCompression);
final byte[] buffer = new byte[FILE_BUFFER_SIZE];
try
{
long bytesSent = 0;
while(true)
{
final int bytesRead = inputStream.read(buffer);
if (bytesRead < FILE_BUFFER_SIZE)
{
msg.setEndOfFile(true);
}
if ((compressor != null) && (bytesRead > 0))
{
byte[] compressedData = new byte[compressor.deflateBound(bytesRead) + 4];
compressor.setInput(buffer, 0, bytesRead, false);
compressor.setOutput(compressedData, 4, compressedData.length - 4);
if (compressor.deflate(JZlib.Z_SYNC_FLUSH) != JZlib.Z_OK)
throw new NXCException(RCC.IO_ERROR);
int length = compressedData.length - compressor.getAvailOut();
byte[] payload = Arrays.copyOf(compressedData, length);
payload[0] = 2; // DEFLATE method
payload[1] = 0; // reserved
payload[2] = (byte)((bytesRead >> 8) & 0xFF); // uncompressed length, high bits
payload[3] = (byte)(bytesRead & 0xFF); // uncompressed length, low bits
msg.setBinaryData(payload);
}
else
{
msg.setBinaryData((bytesRead > 0) ? Arrays.copyOf(buffer, bytesRead) : new byte[0]);
}
sendMessage(msg);
bytesSent += (bytesRead == -1) ? 0 : bytesRead;
if (listener != null)
listener.markProgress(bytesSent);
if (bytesRead < FILE_BUFFER_SIZE)
break;
}
if (compressor != null)
compressor.deflateEnd();
}
catch(Exception e)
{
abortFileTransfer(requestId);
throw e;
}
}
/**
* Wait for message with specific code and id.
*
* @param code Message code
* @param id Message id
* @param timeout Wait timeout in milliseconds
* @return Message object
* @throws NXCException if message was not arrived within timeout interval
*/
public NXCPMessage waitForMessage(final int code, final long id, final int timeout) throws NXCException
{
final NXCPMessage msg = msgWaitQueue.waitForMessage(code, id, timeout);
if (msg == null)
{
throw (receiverStopCause != null) ? new NXCException(RCC.COMM_FAILURE, receiverStopCause) : new NXCException(RCC.TIMEOUT);
}
return msg;
}
/**
* Wait for message with specific code and id.
*
* @param code Message code
* @param id Message id
* @return Message object
* @throws NXCException if message was not arrived within timeout interval
*/
public NXCPMessage waitForMessage(final int code, final long id) throws NXCException
{
return waitForMessage(code, id, msgWaitQueue.getDefaultTimeout());
}
/**
* Wait for CMD_REQUEST_COMPLETED message with given id using default timeout
*
* @param id Message id
* @return received message
* @throws NXCException if message was not arrived within timeout interval or contains RCC other than RCC.SUCCESS
*/
public NXCPMessage waitForRCC(final long id) throws NXCException
{
return waitForRCC(id, msgWaitQueue.getDefaultTimeout());
}
/**
* Wait for CMD_REQUEST_COMPLETED message with given id
*
* @param id Message id
* @param timeout Timeout in milliseconds
* @return received message
* @throws NXCException if message was not arrived within timeout interval or contains RCC other than RCC.SUCCESS
*/
public NXCPMessage waitForRCC(final long id, final int timeout) throws NXCException
{
final NXCPMessage msg = waitForMessage(NXCPCodes.CMD_REQUEST_COMPLETED, id, timeout);
final int rcc = msg.getFieldAsInt32(NXCPCodes.VID_RCC);
if (rcc != RCC.SUCCESS && rcc != RCC.FILE_APPEND_POSSIBLE)
{
long[] relatedObjects = msg.getFieldAsUInt32Array(NXCPCodes.VID_OBJECT_LIST);
String description;
if ((rcc == RCC.COMPONENT_LOCKED) && (msg.findField(NXCPCodes.VID_LOCKED_BY) != null))
{
description = msg.getFieldAsString(NXCPCodes.VID_LOCKED_BY);
}
else if (msg.findField(NXCPCodes.VID_ERROR_TEXT) != null)
{
description = msg.getFieldAsString(NXCPCodes.VID_ERROR_TEXT);
}
else if (msg.findField(NXCPCodes.VID_VALUE) != null)
{
description = msg.getFieldAsString(NXCPCodes.VID_VALUE);
}
else
{
description = null;
}
throw new NXCException(rcc, description, relatedObjects);
}
return msg;
}
/**
* Create new NXCP message with unique id
*
* @param code Message code
* @return New message object
*/
public final NXCPMessage newMessage(int code)
{
return new NXCPMessage(code, requestId.getAndIncrement());
}
/**
* Wait for specific file to arrive
*
* @param id Message ID
* @param timeout Timeout (since arrival of last received file part) in milliseconds to consider file transfer as timed out
* @return Received file or null in case of failure
*/
public ReceivedFile waitForFile(final long id, final int timeout)
{
File file = null;
int status = ReceivedFile.FAILED;
long timestamp = System.currentTimeMillis();
while(true)
{
synchronized(receivedFiles)
{
NXCReceivedFile rf = receivedFiles.get(id);
if (rf != null)
{
if (rf.getStatus() != NXCReceivedFile.OPEN)
{
if (rf.getStatus() == NXCReceivedFile.RECEIVED)
{
file = rf.getFile();
status = ReceivedFile.SUCCESS;
}
break;
}
timestamp = rf.getTimestamp();
}
if (System.currentTimeMillis() - timestamp > timeout)
{
status = ReceivedFile.TIMEOUT;
break;
}
try
{
receivedFiles.wait(timeout);
}
catch(InterruptedException e)
{
}
}
}
return new ReceivedFile(file, status);
}
/**
* Wait for update from specific file monitor.
*
* @param monitorId file monitor ID (previously returned by downloadFileFromAgent
* @param timeout Wait timeout in milliseconds
* @return Received tail string or null in case of failure
*/
public String waitForFileUpdate(UUID monitorId, final int timeout)
{
int timeRemaining = timeout;
String data = null;
while(timeRemaining > 0)
{
synchronized(receivedFileUpdates)
{
data = receivedFileUpdates.get(monitorId);
if (data != null)
{
receivedFileUpdates.remove(monitorId);
break;
}
long startTime = System.currentTimeMillis();
try
{
receivedFileUpdates.wait(timeRemaining);
}
catch(InterruptedException e)
{
}
timeRemaining -= System.currentTimeMillis() - startTime;
}
}
return data;
}
/**
* Execute simple commands (without arguments and only returning RCC)
*
* @param command Command code
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
protected void executeSimpleCommand(int command) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(command);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Receive table from server.
*
* @param requestId request ID
* @param msgCode Message code
* @return Received table
* @throws NXCException if operation was timed out
*/
public Table receiveTable(long requestId, int msgCode) throws NXCException
{
NXCPMessage msg = waitForMessage(msgCode, requestId);
Table table = new Table(msg);
while(!msg.isEndOfSequence())
{
msg = waitForMessage(msgCode, requestId);
table.addDataFromMessage(msg);
}
return table;
}
/**
* Connect to NetMS server. Establish connection with the server and set up encryption if required.
* Only base protocol version check will be performed. Login must be performed before using session
* after successful connect.
*
* @throws IOException if socket I/O error occurs
* @throws UnknownHostException if the host is unknown
* @throws NXCException if NetXMS server returns an error or operation was timed out
* @throws IllegalStateException if the state is illegal
*/
public void connect() throws IOException, UnknownHostException, NXCException, IllegalStateException
{
connect(null);
}
/**
* Connect to NetMS server. Establish connection with the server and set up encryption if required.
* Versions of protocol components given in *componentVersions* will be validated. Login must be
* performed before using session after successful connect.
*
* @param componentVersions The versions of the components
* @throws IOException if socket I/O error occurs
* @throws UnknownHostException if the host is unknown
* @throws NXCException if NetXMS server returns an error or operation was timed out
* @throws IllegalStateException if the state is illegal
*/
public void connect(int[] componentVersions) throws IOException, UnknownHostException, NXCException, IllegalStateException
{
if (connected)
throw new IllegalStateException("Session already connected");
if (disconnected)
throw new IllegalStateException("Session already disconnected and cannot be reused");
encryptionContext = null;
logger.info("Connecting to " + connAddress + ":" + connPort);
try
{
socket = new Socket();
socket.connect(new InetSocketAddress(connAddress, connPort), connectTimeout);
msgWaitQueue = new NXCPMsgWaitQueue(commandTimeout);
recvThread = new ReceiverThread();
housekeeperThread = new HousekeeperThread();
new NotificationProcessor();
new BackgroundUserSync();
// get server information
logger.debug("Connection established, retrieving server info");
NXCPMessage request = newMessage(NXCPCodes.CMD_GET_SERVER_INFO);
sendMessage(request);
NXCPMessage response = waitForMessage(NXCPCodes.CMD_REQUEST_COMPLETED, request.getMessageId());
protocolVersion = new ProtocolVersion(response);
if (!ignoreProtocolVersion)
{
if (!protocolVersion.isCorrectVersion(ProtocolVersion.INDEX_BASE) || ((componentVersions != null)
&& !validateProtocolVersions(componentVersions)))
{
logger.warn("Connection failed (" + protocolVersion.toString() + ")");
throw new NXCException(RCC.BAD_PROTOCOL, protocolVersion.toString());
}
}
else
{
logger.info("Protocol version ignored");
}
serverVersion = response.getFieldAsString(NXCPCodes.VID_SERVER_VERSION);
serverBuild = response.getFieldAsString(NXCPCodes.VID_SERVER_BUILD);
serverId = response.getFieldAsInt64(NXCPCodes.VID_SERVER_ID);
serverTimeZone = response.getFieldAsString(NXCPCodes.VID_TIMEZONE);
serverTime = response.getFieldAsInt64(NXCPCodes.VID_TIMESTAMP) * 1000;
serverTimeRecvTime = System.currentTimeMillis();
serverChallenge = response.getFieldAsBinary(NXCPCodes.VID_CHALLENGE);
tileServerURL = response.getFieldAsString(NXCPCodes.VID_TILE_SERVER_URL);
if (tileServerURL != null)
{
if (!tileServerURL.endsWith("/"))
tileServerURL = tileServerURL.concat("/");
}
else
{
tileServerURL = "http://tile.openstreetmap.org/";
}
dateFormat = response.getFieldAsString(NXCPCodes.VID_DATE_FORMAT);
if ((dateFormat == null) || (dateFormat.length() == 0))
dateFormat = "dd.MM.yyyy";
timeFormat = response.getFieldAsString(NXCPCodes.VID_TIME_FORMAT);
if ((timeFormat == null) || (timeFormat.length() == 0))
timeFormat = "HH:mm:ss";
shortTimeFormat = response.getFieldAsString(NXCPCodes.VID_SHORT_TIME_FORMAT);
if ((shortTimeFormat == null) || (shortTimeFormat.length() == 0))
shortTimeFormat = "HH:mm";
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_COMPONENTS);
long fieldId = NXCPCodes.VID_COMPONENT_LIST_BASE;
for(int i = 0; i < count; i++)
serverComponents.add(response.getFieldAsString(fieldId++));
// Setup encryption if required
if (connUseEncryption)
{
request = newMessage(NXCPCodes.CMD_REQUEST_ENCRYPTION);
request.setFieldInt16(NXCPCodes.VID_USE_X509_KEY_FORMAT, 1);
sendMessage(request);
waitForRCC(request.getMessageId());
}
logger.info("Connected to server version " + serverVersion + " (build " + serverBuild + ")");
connected = true;
}
finally
{
if (!connected)
disconnect(SessionNotification.USER_DISCONNECT);
}
}
/**
* Login to server using login name and password.
*
* @param login login name
* @param password password
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
* @throws IllegalStateException if the state is illegal
*/
public void login(String login, String password) throws NXCException, IOException, IllegalStateException
{
login(AuthenticationType.PASSWORD, login, password, null, null, null);
}
/**
* Login to server using authentication token.
*
* @param token authentication token
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
* @throws IllegalStateException if the state is illegal
*/
public void login(String token) throws NXCException, IOException, IllegalStateException
{
login(AuthenticationType.TOKEN, token, null, null, null, null);
}
/**
* Login to server using certificate.
*
* @param login login name
* @param certificate user's certificate
* @param signature user's digital signature
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
* @throws IllegalStateException if the state is illegal
*/
public void login(String login, Certificate certificate, Signature signature) throws NXCException, IOException, IllegalStateException
{
login(AuthenticationType.CERTIFICATE, login, null, certificate, signature, null);
}
/**
* Login to server.
*
* @param authType authentication type
* @param login login name
* @param password password
* @param certificate user's certificate
* @param signature user's digital signature
* @param twoFactorAuthenticationCallback callback for handling two-factor authentication if requested by server
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
* @throws IllegalStateException if the state is illegal
*/
public void login(AuthenticationType authType, String login, String password, Certificate certificate,
Signature signature, TwoFactorAuthenticationCallback twoFactorAuthenticationCallback)
throws NXCException, IOException, IllegalStateException
{
if (!connected)
throw new IllegalStateException("Session not connected");
if (disconnected)
throw new IllegalStateException("Session already disconnected and cannot be reused");
authenticationMethod = authType;
userName = login;
NXCPMessage request = newMessage(NXCPCodes.CMD_LOGIN);
request.setFieldInt16(NXCPCodes.VID_AUTH_TYPE, authType.getValue());
request.setField(NXCPCodes.VID_LOGIN_NAME, login);
if ((authType == AuthenticationType.PASSWORD) || (authType == AuthenticationType.SSO_TICKET))
{
request.setField(NXCPCodes.VID_PASSWORD, password);
}
else if (authType == AuthenticationType.CERTIFICATE)
{
if ((serverChallenge == null) || (signature == null) || (certificate == null))
{
throw new NXCException(RCC.ENCRYPTION_ERROR);
}
byte[] signedChallenge = signChallenge(signature, serverChallenge);
request.setField(NXCPCodes.VID_SIGNATURE, signedChallenge);
try
{
request.setField(NXCPCodes.VID_CERTIFICATE, certificate.getEncoded());
}
catch(CertificateEncodingException e)
{
throw new NXCException(RCC.ENCRYPTION_ERROR);
}
}
if (twoFactorAuthenticationCallback != null)
{
byte[] token = twoFactorAuthenticationCallback.getTrustedDeviceToken(serverId, login);
if ((token != null) && (token.length != 0))
request.setField(NXCPCodes.VID_TRUSTED_DEVICE_TOKEN, token);
}
request.setField(NXCPCodes.VID_LIBNXCL_VERSION, VersionInfo.version());
request.setField(NXCPCodes.VID_CLIENT_INFO, connClientInfo);
request.setField(NXCPCodes.VID_OS_INFO, System.getProperty("os.name") + " " + System.getProperty("os.version"));
request.setFieldInt16(NXCPCodes.VID_CLIENT_TYPE, clientType);
if (clientAddress != null)
{
logger.debug("Client address provided: " + clientAddress);
request.setField(NXCPCodes.VID_CLIENT_ADDRESS, clientAddress);
}
if (clientLanguage != null)
request.setField(NXCPCodes.VID_LANGUAGE, clientLanguage);
request.setFieldInt16(NXCPCodes.VID_ENABLE_COMPRESSION, 1);
sendMessage(request);
NXCPMessage response = waitForMessage(NXCPCodes.CMD_REQUEST_COMPLETED, request.getMessageId());
int rcc = response.getFieldAsInt32(NXCPCodes.VID_RCC);
logger.debug("CMD_LOGIN_RESP received, RCC=" + rcc);
if ((rcc == RCC.NEED_2FA) && (twoFactorAuthenticationCallback != null))
{
logger.info("Two factor authentication requested by server");
List methods = response.getStringListFromFields(NXCPCodes.VID_2FA_METHOD_LIST_BASE, NXCPCodes.VID_2FA_METHOD_COUNT);
boolean trustedDevicesAllowed = response.getFieldAsBoolean(NXCPCodes.VID_TRUSTED_DEVICES_ALLOWED);
int selectedMethod = twoFactorAuthenticationCallback.selectMethod(methods);
if (selectedMethod < 0)
{
logger.debug("2FA method selection cancelled by user");
throw new NXCException(RCC.OPERATION_CANCELLED);
}
logger.debug("Selected 2FA method " + selectedMethod);
if ((selectedMethod >= 0) && (selectedMethod < methods.size()))
{
request = newMessage(NXCPCodes.CMD_2FA_PREPARE_CHALLENGE);
request.setField(NXCPCodes.VID_2FA_METHOD, methods.get(selectedMethod));
sendMessage(request);
response = waitForMessage(NXCPCodes.CMD_REQUEST_COMPLETED, request.getMessageId());
rcc = response.getFieldAsInt32(NXCPCodes.VID_RCC);
logger.debug("Two factor challenge preparation completed, RCC=" + rcc);
if (rcc == RCC.SUCCESS)
{
String challenge = response.getFieldAsString(NXCPCodes.VID_CHALLENGE);
String qrLabel = response.getFieldAsString(NXCPCodes.VID_QR_LABEL);
String userResponse = twoFactorAuthenticationCallback.getUserResponse(challenge, qrLabel, trustedDevicesAllowed);
if (userResponse == null)
{
logger.debug("2FA response read cancelled by user");
throw new NXCException(RCC.OPERATION_CANCELLED);
}
request = newMessage(NXCPCodes.CMD_2FA_VALIDATE_RESPONSE);
request.setField(NXCPCodes.VID_2FA_RESPONSE, userResponse);
sendMessage(request);
response = waitForMessage(NXCPCodes.CMD_REQUEST_COMPLETED, request.getMessageId());
rcc = response.getFieldAsInt32(NXCPCodes.VID_RCC);
logger.debug("Two factor validation response received, RCC=" + rcc);
if ((rcc == RCC.SUCCESS) && trustedDevicesAllowed && response.isFieldPresent(NXCPCodes.VID_TRUSTED_DEVICE_TOKEN))
{
byte[] token = response.getFieldAsBinary(NXCPCodes.VID_TRUSTED_DEVICE_TOKEN);
if ((token != null) && (token.length > 0))
twoFactorAuthenticationCallback.saveTrustedDeviceToken(serverId, login, token);
}
}
}
}
if (rcc != RCC.SUCCESS)
{
logger.warn("Login failed, RCC=" + rcc);
throw new NXCException(rcc);
}
userId = response.getFieldAsInt32(NXCPCodes.VID_USER_ID);
sessionId = response.getFieldAsInt32(NXCPCodes.VID_SESSION_ID);
userSystemRights = response.getFieldAsInt64(NXCPCodes.VID_USER_SYS_RIGHTS);
passwordExpired = response.getFieldAsBoolean(NXCPCodes.VID_CHANGE_PASSWD_FLAG);
graceLogins = response.getFieldAsInt32(NXCPCodes.VID_GRACE_LOGINS);
zoningEnabled = response.getFieldAsBoolean(NXCPCodes.VID_ZONING_ENABLED);
helpdeskLinkActive = response.getFieldAsBoolean(NXCPCodes.VID_HELPDESK_LINK_ACTIVE);
clientAssignedTcpProxyId = response.getFieldAsBoolean(NXCPCodes.VID_TCP_PROXY_CLIENT_CID);
// Server may send updated user name
if (response.isFieldPresent(NXCPCodes.VID_USER_NAME))
userName = response.getFieldAsString(NXCPCodes.VID_USER_NAME);
defaultDciPollingInterval = response.getFieldAsInt32(NXCPCodes.VID_POLLING_INTERVAL);
if (defaultDciPollingInterval == 0)
defaultDciPollingInterval = 60;
defaultDciRetentionTime = response.getFieldAsInt32(NXCPCodes.VID_RETENTION_TIME);
if (defaultDciRetentionTime == 0)
defaultDciRetentionTime = 30;
minViewRefreshInterval = response.getFieldAsInt32(NXCPCodes.VID_VIEW_REFRESH_INTERVAL);
if (minViewRefreshInterval <= 0)
minViewRefreshInterval = 200;
strictAlarmStatusFlow = response.getFieldAsBoolean(NXCPCodes.VID_ALARM_STATUS_FLOW_STATE);
timedAlarmAckEnabled = response.getFieldAsBoolean(NXCPCodes.VID_TIMED_ALARM_ACK_ENABLED);
serverCommandOutputTimeout = response.getFieldAsInt32(NXCPCodes.VID_SERVER_COMMAND_TIMEOUT) * 1000;
serverColor = response.getFieldAsString(NXCPCodes.VID_SERVER_COLOR);
serverName = response.getFieldAsString(NXCPCodes.VID_SERVER_NAME);
if ((serverName == null) || serverName.isEmpty())
serverName = connAddress;
objectMaintenancePredefinedPeriods = response.getFieldAsString(NXCPCodes.VID_OBJ_MAINT_PREDEF_TIMES);
// compatibility with 2.2.x before 2.2.6
int count = response.getFieldAsInt32(NXCPCodes.VID_ALARM_LIST_DISP_LIMIT);
clientConfigurationHints.put("AlarmList.DisplayLimit", Integer.toString(count));
count = response.getFieldAsInt32(NXCPCodes.VID_CONFIG_HINT_COUNT);
if (count > 0)
{
long fieldId = NXCPCodes.VID_CONFIG_HINT_LIST_BASE;
for(int i = 0; i < count; i++)
{
String key = response.getFieldAsString(fieldId++);
String value = response.getFieldAsString(fieldId++);
clientConfigurationHints.put(key, value);
logger.info("Configuration hint: " + key + " = " + value);
}
}
messageOfTheDay = response.getFieldAsString(NXCPCodes.VID_MESSAGE_OF_THE_DAY);
String tags = response.getFieldAsString(NXCPCodes.VID_RESPONSIBLE_USER_TAGS);
if (tags != null)
{
String[] elements = tags.split(",");
for(String e : elements)
{
responsibleUserTags.add(e.trim());
}
}
count = response.getFieldAsInt32(NXCPCodes.VID_LICENSE_PROBLEM_COUNT);
if (count > 0)
{
licenseProblems = new LicenseProblem[count];
long fieldId = NXCPCodes.VID_LICENSE_PROBLEM_BASE;
for(int i = 0; i < count; i++)
{
licenseProblems[i] = new LicenseProblem(response, fieldId);
fieldId++;
logger.warn("License problem reported by server: " + licenseProblems[i].getDescription());
}
}
allowCompression = response.getFieldAsBoolean(NXCPCodes.VID_ENABLE_COMPRESSION);
logger.info("Succesfully logged in, userId=" + userId);
}
/**
* Disconnect session in background
*
* @param reason disconnect reason (appropriate session notification code)
*/
private void backgroundDisconnect(final int reason)
{
Thread t = new Thread(new Runnable()
{
@Override
public void run()
{
disconnect(reason);
}
}, "NXCSession disconnect");
t.setDaemon(true);
t.start();
}
/**
* Disconnect from server.
*
* @param reason disconnect reason (appropriate session notification code)
*/
synchronized private void disconnect(int reason)
{
if (disconnected)
return;
logger.debug("Session disconnect requested (reason=" + reason + ")");
disconnected = true;
if (socket != null)
{
logger.debug("Closing TCP socket");
try
{
socket.shutdownInput();
socket.shutdownOutput();
}
catch(IOException e)
{
}
try
{
socket.close();
}
catch(IOException e)
{
}
}
// cause notification processing thread to stop
notificationQueue.clear();
if (reason != SessionNotification.USER_DISCONNECT)
notificationQueue.offer(new SessionNotification(reason));
notificationQueue.offer(new SessionNotification(SessionNotification.STOP_PROCESSING_THREAD));
if (recvThread != null)
{
logger.debug("Waiting for receiver thread shutdown");
while(recvThread.isAlive())
{
try
{
recvThread.join();
}
catch(InterruptedException e)
{
}
}
recvThread = null;
}
if (housekeeperThread != null)
{
logger.debug("Waiting for housekeepeer thread shutdown");
housekeeperThread.setStopFlag(true);
while(housekeeperThread.isAlive())
{
try
{
housekeeperThread.join();
}
catch(InterruptedException e)
{
}
}
housekeeperThread = null;
}
if (msgWaitQueue != null)
{
logger.debug("Shutdown message wait queue");
msgWaitQueue.shutdown();
msgWaitQueue = null;
}
connected = false;
socket = null;
listeners.clear();
consoleListeners.clear();
messageSubscriptions.clear();
receivedFiles.clear();
receivedFileUpdates.clear();
objectList.clear();
objectListGUID.clear();
zoneList.clear();
eventTemplates.clear();
userDatabase.clear();
userDatabaseGUID.clear();
alarmCategories.clear();
tcpProxies.clear();
logger.debug("Session disconnect completed");
}
/**
* Disconnect from server.
*/
public void disconnect()
{
disconnect(SessionNotification.USER_DISCONNECT);
}
/**
* Get connection state
*
* @return connection state
*/
public boolean isConnected()
{
return connected;
}
/**
* Get encryption state for current session.
*
* @return true if session is encrypted
*/
public boolean isEncrypted()
{
return connUseEncryption;
}
/**
* Get the state of protocol version check
*
* @return true if protocol version should not be checked
*/
public boolean isIgnoreProtocolVersion()
{
return ignoreProtocolVersion;
}
/**
* If set to true, protocol version is not checked at connect.
*
* @param ignoreProtocolVersion true if protocol version should not be checked
*/
public void setIgnoreProtocolVersion(boolean ignoreProtocolVersion)
{
this.ignoreProtocolVersion = ignoreProtocolVersion;
}
/**
* Validate protocol versions
*
* @param versions the protocol versions
* @return true if protocol versions are valid
*/
public boolean validateProtocolVersions(int[] versions)
{
if (protocolVersion == null)
return false;
for(int index : versions)
if (!protocolVersion.isCorrectVersion(index))
return false;
return true;
}
/**
* Get default receiver buffer size.
*
* @return Default receiver buffer size in bytes.
*/
public int getDefaultRecvBufferSize()
{
return defaultRecvBufferSize;
}
/**
* Get max receiver buffer size.
*
* @return Max receiver buffer size in bytes.
*/
public int getMaxRecvBufferSize()
{
return maxRecvBufferSize;
}
/**
* Set receiver buffer size. This method should be called before connect(). It will not have any effect after
* connect().
*
* @param defaultBufferSize default size of receiver buffer in bytes.
* @param maxBufferSize max size of receiver buffer in bytes.
*/
public void setRecvBufferSize(int defaultBufferSize, int maxBufferSize)
{
this.defaultRecvBufferSize = defaultBufferSize;
this.maxRecvBufferSize = maxBufferSize;
}
/**
* Get server address
*
* @return Server address
*/
public String getServerAddress()
{
return connAddress;
}
/**
* Get NetXMS server version.
*
* @return Server version
*/
public String getServerVersion()
{
return serverVersion;
}
/**
* Get NetXMS server build information.
*
* @return Server version
*/
public String getServerBuild()
{
return serverBuild;
}
/**
* Get NetXMS server UID.
*
* @return Server UID
*/
public long getServerId()
{
return serverId;
}
/**
* Get server time zone.
*
* @return server's time zone string
*/
public String getServerTimeZone()
{
return serverTimeZone;
}
/**
* Get server name
*
* @return the serverName
*/
public String getServerName()
{
return serverName;
}
/**
* Get server identification colour
*
* @return the serverColor
*/
public String getServerColor()
{
return serverColor;
}
/**
* Get server time
*
* @return the serverTime
*/
public long getServerTime()
{
long offset = System.currentTimeMillis() - serverTimeRecvTime;
return serverTime + offset;
}
/**
* @return the objectMaintenancePredefinedPeriods
*/
public String getObjectMaintenancePredefinedPeriods()
{
return objectMaintenancePredefinedPeriods;
}
/**
* @return the serverChallenge
*/
public byte[] getServerChallenge()
{
return serverChallenge;
}
/**
* Check if server component with given id is registered
*
* @param componentId The component ID
* @return true if server component is registered
*/
public boolean isServerComponentRegistered(String componentId)
{
return serverComponents.contains(componentId);
}
/**
* Get list of registered server components
*
* @return Array of registered server components
*/
public String[] getRegisteredServerComponents()
{
return serverComponents.toArray(new String[serverComponents.size()]);
}
/**
* Get server URL
*
* @return the tileServerURL
*/
public String getTileServerURL()
{
return tileServerURL;
}
/**
* Get the state of zoning
*
* @return true if zoning is enabled
*/
public boolean isZoningEnabled()
{
return zoningEnabled;
}
/**
* Get status of helpdesk integration module on server.
*
* @return true if helpdesk integration module loaded on server
*/
public boolean isHelpdeskLinkActive()
{
return helpdeskLinkActive;
}
/**
* Get client information string
*
* @return The client information
*/
public String getClientInfo()
{
return connClientInfo;
}
/**
* Set client information string
*
* @param connClientInfo The client info to set
*/
public void setClientInfo(final String connClientInfo)
{
this.connClientInfo = connClientInfo;
}
/**
* Set command execution timeout.
*
* @param commandTimeout New command timeout
*/
public void setCommandTimeout(final int commandTimeout)
{
this.commandTimeout = commandTimeout;
}
/**
* Set connect call timeout (must be set before connect call)
*
* @param connectTimeout connect timeout in milliseconds
*/
public void setConnectTimeout(int connectTimeout)
{
this.connectTimeout = connectTimeout;
}
/**
* Get identifier of logged in user.
*
* @return Identifier of logged in user
*/
public int getUserId()
{
return userId;
}
/**
* Get the current user name
*
* @return the userName
*/
public String getUserName()
{
return userName;
}
/**
* Get the current authentication method
*
* @return the authenticationMethod
*/
public AuthenticationType getAuthenticationMethod()
{
return authenticationMethod;
}
/**
* Get system-wide rights of currently logged in user.
*
* @return System-wide rights of currently logged in user
*/
public long getUserSystemRights()
{
return userSystemRights;
}
/**
* Get message of the day if server config is set
*
* @return Message of the day
*/
public String getMessageOfTheDay()
{
return messageOfTheDay;
}
/**
* Get list of license problems reported by server. This method will always return null for community edition server.
*
* @return list of license problems reported by server or null if there are none
*/
public LicenseProblem[] getLicenseProblems()
{
return licenseProblems;
}
/**
* Check if server has any license problems.
*
* @return true if server has any license problems
*/
public boolean hasLicenseProblems()
{
return (licenseProblems != null) && (licenseProblems.length > 0);
}
/**
* Check if password is expired for currently logged in user.
*
* @return true if password is expired
*/
public boolean isPasswordExpired()
{
return passwordExpired;
}
/**
* Get number of remaining grace logins
*
* @return number of remaining grace logins
*/
public int getGraceLogins()
{
return graceLogins;
}
/**
* Get maximum number of records allowed to be displayed in alarm list
*
* @return The limit of alarms displayed
*/
public int getAlarmListDisplayLimit()
{
return getClientConfigurationHintAsInt("AlarmList.DisplayLimit", 4096);
}
/**
* Get client configuration hint as string
*
* @param name hint name
* @param defaultValue default value (returned if given hint was not provided by server)
* @return hint value as provided by server or default value
*/
public String getClientConfigurationHint(String name, String defaultValue)
{
String v = clientConfigurationHints.get(name);
return (v != null) ? v : defaultValue;
}
/**
* Get client configuration hint as string
*
* @param name hint name
* @return hint value as provided by server or null
*/
public String getClientConfigurationHint(String name)
{
return getClientConfigurationHint(name, null);
}
/**
* Get client configuration hint as integer
*
* @param name hint name
* @param defaultValue default value (returned if given hint was not provided by server or is not valid integer)
* @return hint value as provided by server or default value
*/
public int getClientConfigurationHintAsInt(String name, int defaultValue)
{
String v = clientConfigurationHints.get(name);
if (v == null)
return defaultValue;
try
{
return Integer.parseInt(v);
}
catch(NumberFormatException e)
{
return defaultValue;
}
}
/**
* Get client configuration hint as boolean
*
* @param name hint name
* @param defaultValue default value (returned if given hint was not provided by server or is not valid boolean)
* @return hint value as provided by server or default value
*/
public boolean getClientConfigurationHintAsBoolean(String name, boolean defaultValue)
{
String v = clientConfigurationHints.get(name);
if (v == null)
return defaultValue;
if (v.equalsIgnoreCase("true"))
return true;
if (v.equalsIgnoreCase("false"))
return false;
try
{
return Integer.parseInt(v) != 0;
}
catch(NumberFormatException e)
{
return defaultValue;
}
}
/**
* Get allowed tags for responsible users.
*
* @return allowed tags for responsible users
*/
public Set getResponsibleUserTags()
{
return new HashSet(responsibleUserTags);
}
/**
* Synchronize object categories
*
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncObjectCategories() throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_OBJECT_CATEGORIES);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
synchronized(objectCategories)
{
objectCategories.clear();
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
long fieldId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < count; i++, fieldId += 10)
{
ObjectCategory category = new ObjectCategory(response, fieldId);
objectCategories.put(category.getId(), category);
}
}
}
/**
* Get object category by ID
*
* @param categoryId object category ID
* @return object category or null
*/
public ObjectCategory getObjectCategory(int categoryId)
{
synchronized(objectCategories)
{
return objectCategories.get(categoryId);
}
}
/**
* Get all object categories.
*
* @return all object categories
*/
public List getObjectCategories()
{
synchronized(objectCategories)
{
return new ArrayList(objectCategories.values());
}
}
/**
* Modify object category.
*
* @param category updated category object
* @return ID of category object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public int modifyObjectCategory(MutableObjectCategory category) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_MODIFY_OBJECT_CATEGORY);
category.fillMessage(msg);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsInt32(NXCPCodes.VID_CATEGORY_ID);
}
/**
* Delete object category. This method will fail if category is in use (set to at least one object) unless forceDelete
* parameter set to true.
*
* @param categoryId category ID
* @param forceDelete force deletion flag - if set to true category will be deleted even if in use
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteObjectCategory(int categoryId, boolean forceDelete) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_OBJECT_CATEGORY);
msg.setFieldInt32(NXCPCodes.VID_CATEGORY_ID, categoryId);
msg.setField(NXCPCodes.VID_FORCE_DELETE, forceDelete);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Synchronizes NetXMS objects between server and client. After successful
* sync, subscribe client to object change notifications.
*
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncObjects() throws IOException, NXCException
{
syncObjects(true);
}
/**
* Synchronizes NetXMS objects between server and client. After successful
* sync, subscribe client to object change notifications.
*
* @param syncNodeComponents defines if node components should be synced
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncObjects(boolean syncNodeComponents) throws IOException, NXCException
{
syncObjectCategories();
syncObjects.acquireUninterruptibly();
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_OBJECTS);
msg.setField(NXCPCodes.VID_SYNC_NODE_COMPONENTS, syncNodeComponents);
sendMessage(msg);
waitForRCC(msg.getMessageId());
waitForSync(syncObjects, commandTimeout * 10);
objectsSynchronized = objectsSynchronized || syncNodeComponents;
sendNotification(new SessionNotification(SessionNotification.OBJECT_SYNC_COMPLETED));
subscribe(CHANNEL_OBJECTS);
}
/**
* Synchronizes selected object set with the server.
*
* @param objects identifiers of objects need to be synchronized
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncObjectSet(long[] objects) throws IOException, NXCException
{
syncObjectSet(objects, 0);
}
/**
* Synchronizes selected object set with the server. The following options are accepted:
* OBJECT_SYNC_NOTIFY - send object update notification for each received object
* OBJECT_SYNC_WAIT - wait until all requested objects received
*
* @param objects identifiers of objects need to be synchronized
* @param options sync options (see above)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncObjectSet(long[] objects, int options) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_SELECTED_OBJECTS);
msg.setFieldInt16(NXCPCodes.VID_FLAGS, options);
msg.setFieldInt32(NXCPCodes.VID_NUM_OBJECTS, objects.length);
msg.setField(NXCPCodes.VID_OBJECT_LIST, objects);
sendMessage(msg);
waitForRCC(msg.getMessageId());
if ((options & OBJECT_SYNC_WAIT) != 0)
waitForRCC(msg.getMessageId());
}
/**
* Synchronize only those objects from given set which are not synchronized yet.
*
* @param objects identifiers of objects need to be synchronized
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncMissingObjects(long[] objects) throws IOException, NXCException
{
syncMissingObjects(objects, 0);
}
/**
* Synchronize only those objects from given set which are not synchronized yet.
* Accepts all options which are valid for syncObjectSet.
*
* @param objects identifiers of objects need to be synchronized
* @param options sync options (see comments for syncObjectSet)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncMissingObjects(long[] objects, int options) throws IOException, NXCException
{
final long[] syncList = Arrays.copyOf(objects, objects.length);
int count = syncList.length;
synchronized(objectList)
{
for(int i = 0; i < syncList.length; i++)
{
if (objectList.containsKey(syncList[i]))
{
syncList[i] = 0;
count--;
}
}
}
if (count > 0)
{
syncObjectSet(syncList, options);
}
}
/**
* Synchronize only those objects from given set which are not synchronized yet.
* Accepts all options which are valid for syncObjectSet.
*
* @param objects identifiers of objects need to be synchronized
* @param options sync options (see comments for syncObjectSet)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncMissingObjects(List objects, int options) throws IOException, NXCException
{
final long[] syncList = new long[objects.size()];
for (int i = 0; i < objects.size(); i++)
syncList[i] = objects.get(i);
int count = syncList.length;
synchronized(objectList)
{
for(int i = 0; i < syncList.length; i++)
{
if (objectList.containsKey(syncList[i]))
{
syncList[i] = 0;
count--;
}
}
}
if (count > 0)
{
syncObjectSet(syncList, options);
}
}
/**
* Sync children of given object.
*
* @param object parent object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncChildren(AbstractObject object) throws NXCException, IOException
{
if (objectsSynchronized)
return;
boolean syncRequired;
synchronized(synchronizedObjectSet)
{
syncRequired = !synchronizedObjectSet.contains(object.getObjectId());
}
if (syncRequired)
{
syncMissingObjects(object.getChildIdList(), NXCSession.OBJECT_SYNC_WAIT);
synchronized(synchronizedObjectSet)
{
synchronizedObjectSet.add(object.getObjectId());
}
}
}
/**
* Returns true if children are already synchronized for given object.
*
* @param id object id
* @return true if children are synchronized
*/
public boolean areChildrenSynchronized(long id)
{
synchronized(synchronizedObjectSet)
{
return objectsSynchronized || synchronizedObjectSet.contains(id);
}
}
/**
* Find object by regex
*
* @param regex for object name
* @return list of matching objects
*/
public List findObjectByRegex(String regex)
{
List objects = new ArrayList();
Matcher matcher = Pattern.compile(regex).matcher("");
synchronized(objectList)
{
for(AbstractObject o : objectList.values())
{
matcher.reset(o.getObjectName());
if (matcher.matches())
objects.add(o);
}
}
return objects;
}
/**
* Find NetXMS object by it's identifier.
*
* @param id Object identifier
* @return Object with given ID or null if object cannot be found
*/
public AbstractObject findObjectById(final long id)
{
synchronized(objectList)
{
return objectList.get(id);
}
}
/**
* Find NetXMS object by it's identifier or return wait an object to wait on
*
* @param id Object identifier
* @return Object to wait on if object not found. If object is found it will be already set inside
*/
public FutureObject findFutureObjectById(final long id)
{
final FutureObject object;
synchronized(objectList)
{
AbstractObject result = objectList.get(id);
if (result == null)
{
object = new FutureObject();
addListener(new SessionListener() {
@Override
public void notificationHandler(SessionNotification n)
{
if (n.code == SessionNotification.OBJECT_CHANGED && n.subCode == id)
{
synchronized(object)
{
object.setObject((AbstractObject)n.object);
object.notifyAll();
}
removeListener(this);
}
}
});
}
else
{
object = new FutureObject(result);
}
}
return object;
}
/**
* Find NetXMS object by it's identifier and execute provided callback once found
*
* @param id Object identifier
* @param callback callback to be called when object is found
*/
public void findObjectAsync(final long id, ObjectCreationListener callback)
{
if (callback == null)
return;
synchronized(objectList)
{
AbstractObject object = objectList.get(id);
if (object == null)
{
addListener(new SessionListener() {
@Override
public void notificationHandler(SessionNotification n)
{
if (n.code == SessionNotification.OBJECT_CHANGED && n.subCode == id)
{
callback.objectCreated(findObjectById(id));
removeListener(this);
}
}
});
}
else
{
callback.objectCreated((AbstractObject)object);
}
}
}
/**
* Find NetXMS object by it's identifier with additional class checking.
*
* @param id object identifier
* @param requiredClass required object class
* @param Object
* @return Object with given ID or null if object cannot be found or is not an instance of required class
*/
@SuppressWarnings("unchecked")
public T findObjectById(final long id, final Class requiredClass)
{
AbstractObject object = findObjectById(id);
return requiredClass.isInstance(object) ? (T)object : null;
}
/**
* Find multiple NetXMS objects by identifiers
*
* @param idList array of object identifiers
* @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
* @return list of found objects
*/
public List findMultipleObjects(final long[] idList, boolean returnUnknown)
{
return findMultipleObjects(idList, null, returnUnknown);
}
/**
* Find multiple NetXMS objects by identifiers
*
* @param idList array of object identifiers
* @param classFilter class filter for objects, or null to disable filtering
* @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
* @return list of found objects
*/
public List findMultipleObjects(final long[] idList, Class extends AbstractObject> classFilter, boolean returnUnknown)
{
List result = new ArrayList(idList.length);
synchronized(objectList)
{
for(int i = 0; i < idList.length; i++)
{
final AbstractObject object = objectList.get(idList[i]);
if ((object != null) && ((classFilter == null) || classFilter.isInstance(object)))
{
result.add(object);
}
else if (returnUnknown)
{
result.add(new UnknownObject(idList[i], this));
}
}
}
return result;
}
/**
* Find multiple NetXMS objects by identifiers
*
* @param idList collection of object identifiers
* @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
* @return array of found objects
*/
public List findMultipleObjects(final Collection idList, boolean returnUnknown)
{
return findMultipleObjects(idList, null, returnUnknown);
}
/**
* Find multiple NetXMS objects by identifiers
*
* @param idList collection of object identifiers
* @param classFilter class filter for objects, or null to disable filtering
* @param returnUnknown if true, this method will return UnknownObject placeholders for unknown object identifiers
* @return array of found objects
*/
public List findMultipleObjects(final Collection idList, Class extends AbstractObject> classFilter, boolean returnUnknown)
{
List result = new ArrayList(idList.size());
synchronized(objectList)
{
for(Long id : idList)
{
final AbstractObject object = objectList.get(id);
if ((object != null) && ((classFilter == null) || classFilter.isInstance(object)))
{
result.add(object);
}
else if (returnUnknown)
{
result.add(new UnknownObject(id, this));
}
}
}
return result;
}
/**
* Find NetXMS object by it's GUID.
*
* @param guid Object GUID
* @return Object with given ID or null if object cannot be found
*/
public AbstractObject findObjectByGUID(final UUID guid)
{
synchronized(objectList)
{
return objectListGUID.get(guid);
}
}
/**
* Find NetXMS object by it's GUID with additional class checking.
*
* @param guid object GUID
* @param requiredClass required object class
* @param Object
* @return Object with given ID or null if object cannot be found or is not an instance of required class
*/
@SuppressWarnings("unchecked")
public T findObjectByGUID(final UUID guid, final Class requiredClass)
{
AbstractObject object = findObjectByGUID(guid);
return requiredClass.isInstance(object) ? (T)object : null;
}
/**
* Find zone object by zone UIN (unique identification number).
*
* @param zoneUIN zone UIN to find
* @return zone object or null
*/
public Zone findZone(int zoneUIN)
{
synchronized(objectList)
{
return zoneList.get(zoneUIN);
}
}
/**
* Get all accessible zone objects
*
* @return list of all accessible zone objects
*/
public List getAllZones()
{
synchronized(objectList)
{
return new ArrayList(zoneList.values());
}
}
/**
* Find object by name. If multiple objects with same name exist,
* it is not determined what object will be returned. Name comparison
* is case-insensitive.
*
* @param name object name to find
* @return object with matching name or null
*/
public AbstractObject findObjectByName(final String name)
{
AbstractObject result = null;
synchronized(objectList)
{
for(AbstractObject object : objectList.values())
{
if (object.getObjectName().equalsIgnoreCase(name))
{
result = object;
break;
}
}
}
return result;
}
/**
* Find object by name with object filter. Name comparison
* is case-insensitive.
*
* @param name object name to find
* @param filter TODO
* @return object with matching name or null
*/
public AbstractObject findObjectByName(final String name, ObjectFilter filter)
{
AbstractObject result = null;
synchronized(objectList)
{
for(AbstractObject object : objectList.values())
{
if (object.getObjectName().equalsIgnoreCase(name) && filter.filter(object))
{
result = object;
break;
}
}
}
return result;
}
/**
* Find object by name using regular expression. If multiple objects with same name exist,
* it is not determined what object will be returned. Name comparison is case-insensitive.
*
* @param pattern regular expression for matching object name
* @return object with matching name or null
*/
public AbstractObject findObjectByNamePattern(final String pattern)
{
AbstractObject result = null;
Matcher matcher = Pattern.compile(pattern).matcher("");
synchronized(objectList)
{
for(AbstractObject object : objectList.values())
{
matcher.reset(object.getObjectName());
if (matcher.matches())
{
result = object;
break;
}
}
}
return result;
}
/**
* Generic object find using filter. WIll return first object matching given filter.
*
* @param filter ObjectFilter to filter the result
* @return first matching object or null
*/
public AbstractObject findObject(ObjectFilter filter)
{
AbstractObject result = null;
synchronized(objectList)
{
for(AbstractObject object : objectList.values())
{
if (filter.filter(object))
{
result = object;
break;
}
}
}
return result;
}
/**
* Find all objects matching given filter.
*
* @param filter ObjectFilter to filter the result
* @return list of matching objects (empty list if nothing found)
*/
public List filterObjects(ObjectFilter filter)
{
List result = new ArrayList();
synchronized(objectList)
{
for(AbstractObject object : objectList.values())
{
if (filter.filter(object))
{
result.add(object);
}
}
}
return result;
}
/**
* Get list of top-level objects matching given class filter. Class filter
* may be null to ignore object class.
*
* @param classFilter To filter the classes
* @return List of all top matching level objects (either without parents or with
* inaccessible parents)
*/
public AbstractObject[] getTopLevelObjects(Set classFilter)
{
HashSet list = new HashSet();
synchronized(objectList)
{
for(AbstractObject object : objectList.values())
{
if ((classFilter != null) && !classFilter.contains(object.getObjectClass()))
continue;
if (!object.hasParents())
{
list.add(object);
}
else
{
boolean hasParents = false;
Iterator it = object.getParents();
while(it.hasNext())
{
Long parent = it.next();
if (classFilter != null)
{
AbstractObject p = objectList.get(parent);
if ((p != null) && classFilter.contains(p.getObjectClass()))
{
hasParents = true;
break;
}
}
else
{
if (objectList.containsKey(parent))
{
hasParents = true;
break;
}
}
}
if (!hasParents)
list.add(object);
}
}
}
return list.toArray(new AbstractObject[list.size()]);
}
/**
* Get list of top-level objects.
*
* @return List of all top level objects (either without parents or with
* inaccessible parents)
*/
public AbstractObject[] getTopLevelObjects()
{
return getTopLevelObjects(null);
}
/**
* Get list of all objects
*
* @return List of all objects
*/
public List getAllObjects()
{
synchronized(objectList)
{
return new ArrayList(objectList.values());
}
}
/**
* Get object name by ID.
*
* @param objectId object ID
* @return object name if object is known, or string in form [<object_id>] for unknown objects
*/
public String getObjectName(long objectId)
{
AbstractObject object = findObjectById(objectId);
return (object != null) ? object.getObjectName() : ("[" + Long.toString(objectId) + "]");
}
/**
* Get object name with alias by ID.
*
* @param objectId object ID
* @return object name with alias if object is known, or string in form [<object_id>] for unknown objects
*/
public String getObjectNameWithAlias(long objectId)
{
AbstractObject object = findObjectById(objectId);
return (object != null) ? object.getNameWithAlias() : ("[" + Long.toString(objectId) + "]");
}
/**
* Get zone name by UIN
*
* @param zoneUIN zone UIN
* @return zone name
*/
public String getZoneName(int zoneUIN)
{
Zone zone = findZone(zoneUIN);
return (zone != null) ? zone.getObjectName() : ("[" + Long.toString(zoneUIN) + "]");
}
/**
* Query objects on server side
*
* @param query query to execute
* @return list of matching objects
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List queryObjects(String query) throws IOException, NXCException
{
NXCPMessage request = newMessage(NXCPCodes.CMD_QUERY_OBJECTS);
request.setField(NXCPCodes.VID_QUERY, query);
sendMessage(request);
NXCPMessage response = waitForRCC(request.getMessageId());
return findMultipleObjects(response.getFieldAsUInt32Array(NXCPCodes.VID_OBJECT_LIST), false);
}
/**
* Query objects on server side and read certain object properties. Available properties are the same as in corresponding NXSL
* objects or computed properties set using "with" statement in query. If readAllComputedProperties
is set to
* true
then all computed properties will be retrieved in addition to those explicitly listed.
*
* @param query query to execute
* @param properties object properties to read
* @param orderBy list of properties for ordering result set (can be null)
* @param inputFields set of input fields provided by user (can be null)
* @param readAllComputedProperties if set to true
, query will return all computed properties in addition to
* properties explicitly listed in properties
parameter
* @param limit limit number of records (0 for unlimited)
* @return list of matching objects
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List queryObjectDetails(String query, List properties, List orderBy, Map inputFields, boolean readAllComputedProperties, int limit)
throws IOException, NXCException
{
NXCPMessage request = newMessage(NXCPCodes.CMD_QUERY_OBJECT_DETAILS);
request.setField(NXCPCodes.VID_QUERY, query);
if (properties != null)
request.setFieldsFromStringCollection(properties, NXCPCodes.VID_FIELD_LIST_BASE, NXCPCodes.VID_FIELDS);
if (orderBy != null)
request.setFieldsFromStringCollection(orderBy, NXCPCodes.VID_ORDER_FIELD_LIST_BASE, NXCPCodes.VID_ORDER_FIELDS);
if (inputFields != null)
request.setFieldsFromStringMap(inputFields, NXCPCodes.VID_INPUT_FIELD_BASE, NXCPCodes.VID_INPUT_FIELD_COUNT);
request.setFieldInt32(NXCPCodes.VID_RECORD_LIMIT, limit);
request.setField(NXCPCodes.VID_READ_ALL_FIELDS, readAllComputedProperties);
sendMessage(request);
NXCPMessage response = waitForRCC(request.getMessageId());
long[] objects = response.getFieldAsUInt32Array(NXCPCodes.VID_OBJECT_LIST);
List results = new ArrayList(objects.length);
long fieldId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < objects.length; i++)
{
Map values = response.getStringMapFromFields(fieldId + 1, fieldId);
AbstractObject object = findObjectById(objects[i]);
if (object != null)
{
results.add(new ObjectQueryResult(object, values));
}
fieldId += values.size() * 2 + 1;
}
return results;
}
/**
* Get list of configured object queries.
*
* @return list of configured object queries
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getObjectQueries() throws IOException, NXCException
{
NXCPMessage request = newMessage(NXCPCodes.CMD_GET_OBJECT_QUERIES);
sendMessage(request);
NXCPMessage response = waitForRCC(request.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
List queries = new ArrayList(count);
long[] fieldId = new long[] { NXCPCodes.VID_ELEMENT_LIST_BASE };
for(int i = 0; i < count; i++)
queries.add(new ObjectQuery(response, fieldId));
return queries;
}
/**
* Modify object query. If query ID is 0 new query object will be created and assigned ID will be returned.
*
* @param query query to create or modify
* @return assigned query ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public int modifyObjectQuery(ObjectQuery query) throws IOException, NXCException
{
NXCPMessage request = newMessage(NXCPCodes.CMD_MODIFY_OBJECT_QUERY);
query.fillMessage(request);
sendMessage(request);
NXCPMessage response = waitForRCC(request.getMessageId());
return response.getFieldAsInt32(NXCPCodes.VID_QUERY_ID);
}
/**
* Delete predefined object query.
*
* @param queryId query ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteObjectQuery(int queryId) throws IOException, NXCException
{
NXCPMessage request = newMessage(NXCPCodes.CMD_DELETE_OBJECT_QUERY);
request.setFieldInt32(NXCPCodes.VID_QUERY_ID, queryId);
sendMessage(request);
waitForRCC(request.getMessageId());
}
/**
* Get list of active alarms. For accessing terminated alarms log view API should be used.
*
* @return Hash map containing alarms
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public HashMap getAlarms() throws IOException, NXCException
{
NXCPMessage request = newMessage(NXCPCodes.CMD_GET_ALL_ALARMS);
final long rqId = request.getMessageId();
sendMessage(request);
final HashMap alarmList = new HashMap(0);
while(true)
{
request = waitForMessage(NXCPCodes.CMD_ALARM_DATA, rqId);
long alarmId = request.getFieldAsInt32(NXCPCodes.VID_ALARM_ID);
if (alarmId == 0)
break; // ALARM_ID == 0 indicates end of list
alarmList.put(alarmId, new Alarm(request));
}
return alarmList;
}
/**
* Get information about single active alarm. Terminated alarms cannot be accessed with this call.
*
* @param alarmId alarm ID
* @return alarm object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Alarm getAlarm(long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return new Alarm(response);
}
/**
* Get information about events related to single active alarm. Information for terminated alarms cannot be accessed with this call.
* User must have "view alarms" permission on alarm's source node and "view event log" system-wide access.
*
* @param alarmId alarm ID
* @return list of related events
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getAlarmEvents(long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM_EVENTS);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
List list = new ArrayList(count);
long varId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < count; i++)
{
EventInfo parent = null;
long rootId = response.getFieldAsInt64(varId + 1);
if (rootId != 0)
{
for(EventInfo e : list)
{
if (e.getId() == rootId)
{
parent = e;
break;
}
}
}
list.add(new EventInfo(response, varId, parent));
varId += 10;
}
return list;
}
/**
* Acknowledge alarm.
*
* @param alarmId Identifier of alarm to be acknowledged.
* @param sticky if set to true, acknowledged state will be made "sticky" (duplicate alarms with same key will not revert it back to outstanding)
* @param time timeout for sticky acknowledge in seconds (0 for infinite)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void acknowledgeAlarm(final long alarmId, boolean sticky, int time) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_ACK_ALARM);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
msg.setFieldInt16(NXCPCodes.VID_STICKY_FLAG, sticky ? 1 : 0);
msg.setFieldInt32(NXCPCodes.VID_TIMESTAMP, time);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Acknowledge alarm.
*
* @param alarmId Identifier of alarm to be acknowledged.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void acknowledgeAlarm(final long alarmId) throws IOException, NXCException
{
acknowledgeAlarm(alarmId, false, 0);
}
/**
* Acknowledge alarm by helpdesk reference.
*
* @param helpdeskReference Helpdesk issue reference (e.g. JIRA issue key)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void acknowledgeAlarm(String helpdeskReference) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_ACK_ALARM);
msg.setField(NXCPCodes.VID_HELPDESK_REF, helpdeskReference);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Resolve alarm.
*
* @param alarmId Identifier of alarm to be resolved.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void resolveAlarm(final long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_RESOLVE_ALARM);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Resolve alarm by helpdesk reference.
*
* @param helpdeskReference Identifier of alarm to be resolved.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void resolveAlarm(final String helpdeskReference) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_RESOLVE_ALARM);
msg.setField(NXCPCodes.VID_HELPDESK_REF, helpdeskReference);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Terminate alarm.
*
* @param alarmId Identifier of alarm to be terminated.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void terminateAlarm(final long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_TERMINATE_ALARM);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Terminate alarm by helpdesk reference.
*
* @param helpdeskReference Identifier of alarm to be resolved.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void terminateAlarm(final String helpdeskReference) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_TERMINATE_ALARM);
msg.setField(NXCPCodes.VID_HELPDESK_REF, helpdeskReference);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
private Map bulkAlarmOperation(int cmd, List alarmIds) throws IOException, NXCException
{
NXCPMessage msg = newMessage(cmd);
msg.setField(NXCPCodes.VID_ALARM_ID_LIST, alarmIds.toArray(new Long[alarmIds.size()]));
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
Map operationFails = new HashMap();
// Returned alarm ID`s if there were any failed operations
if (response.findField(NXCPCodes.VID_ALARM_ID_LIST) != null)
{
for(int i = 0; i < response.getFieldAsUInt32ArrayEx(NXCPCodes.VID_ALARM_ID_LIST).length; i++)
{
operationFails.put(response.getFieldAsUInt32ArrayEx(NXCPCodes.VID_ALARM_ID_LIST)[i],
(Integer)response.getFieldAsUInt32ArrayEx(NXCPCodes.VID_FAIL_CODE_LIST)[i].intValue());
}
}
return operationFails;
}
/**
* Bulk terminate alarms.
*
* @param alarmIds Identifiers of alarms to be terminated.
* @return true if all alarms were terminated, false if some, or all, were not terminated
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map bulkResolveAlarms(List alarmIds) throws IOException, NXCException
{
return bulkAlarmOperation(NXCPCodes.CMD_BULK_RESOLVE_ALARMS, alarmIds);
}
/**
* Bulk terminate alarms.
*
* @param alarmIds Identifiers of alarms to be terminated.
* @return true if all alarms were terminated, false if some, or all, were not terminated
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map bulkTerminateAlarms(List alarmIds) throws IOException, NXCException
{
return bulkAlarmOperation(NXCPCodes.CMD_BULK_TERMINATE_ALARMS, alarmIds);
}
/**
* Delete alarm.
*
* @param alarmId Identifier of alarm to be deleted.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteAlarm(final long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_ALARM);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Open issue in helpdesk system from given alarm
*
* @param alarmId alarm identifier
* @return helpdesk issue identifier
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String openHelpdeskIssue(long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_OPEN_HELPDESK_ISSUE);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
return waitForRCC(msg.getMessageId()).getFieldAsString(NXCPCodes.VID_HELPDESK_REF);
}
/**
* Get URL for helpdesk issue associated with given alarm
*
* @param alarmId The ID of alarm
* @return URL of helpdesk issue
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String getHelpdeskIssueUrl(long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_HELPDESK_URL);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
return waitForRCC(msg.getMessageId()).getFieldAsString(NXCPCodes.VID_URL);
}
/**
* Unlink helpdesk issue from alarm. User must have OBJECT_ACCESS_UPDATE_ALARMS access right
* on alarm's source object and SYSTEM_ACCESS_UNLINK_ISSUES system wide access right.
*
* @param helpdeskReference The helpdesk reference
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void unlinkHelpdeskIssue(String helpdeskReference) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UNLINK_HELPDESK_ISSUE);
msg.setField(NXCPCodes.VID_HELPDESK_REF, helpdeskReference);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Unlink helpdesk issue from alarm. User must have OBJECT_ACCESS_UPDATE_ALARMS access right
* on alarm's source object and SYSTEM_ACCESS_UNLINK_ISSUES system wide access right.
*
* @param alarmId alarm id
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void unlinkHelpdeskIssue(long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UNLINK_HELPDESK_ISSUE);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get list of comments for given alarm.
*
* @param alarmId alarm ID
* @return list of alarm comments
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getAlarmComments(long alarmId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM_COMMENTS);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
final List comments = new ArrayList(count);
long varId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < count; i++)
{
comments.add(new AlarmComment(response, varId));
varId += 10;
}
return comments;
}
/**
* Delete alarm comment.
*
* @param alarmId alarm ID
* @param commentId comment ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteAlarmComment(long alarmId, long commentId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_ALARM_COMMENT);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
msg.setFieldInt32(NXCPCodes.VID_COMMENT_ID, (int)commentId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Create alarm comment.
*
* @param alarmId The alarm ID
* @param text The comment text
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void createAlarmComment(long alarmId, String text) throws IOException, NXCException
{
updateAlarmComment(alarmId, 0, text);
}
/**
* Create alarm comment by helpdesk reference.
*
* @param helpdeskReference The helpdesk reference
* @param text The reference text
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void createAlarmComment(final String helpdeskReference, String text) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_ALARM_COMMENT);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, 0);
msg.setField(NXCPCodes.VID_HELPDESK_REF, helpdeskReference);
msg.setField(NXCPCodes.VID_COMMENTS, text);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Update alarm comment.
* If alarmId == 0 — new comment will be created.
*
* @param alarmId alarm ID
* @param commentId comment ID or 0 for creating new comment
* @param text message text
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void updateAlarmComment(long alarmId, long commentId, String text) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_ALARM_COMMENT);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
msg.setFieldInt32(NXCPCodes.VID_COMMENT_ID, (int)commentId);
msg.setField(NXCPCodes.VID_COMMENTS, text);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Changes state of alarm status flow. Strict or not - terminate state can be set only after
* resolve state or after any state.
*
* @param state state of alarm status flow - strict or not (1 or 0)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setAlarmFlowState(int state) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_ALARM_STATUS_FLOW);
msg.setFieldInt32(NXCPCodes.VID_ALARM_STATUS_FLOW_STATE, state);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get server configuration variables
*
* @return The server variables
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map getServerVariables() throws IOException, NXCException
{
NXCPMessage request = newMessage(NXCPCodes.CMD_GET_CONFIG_VARLIST);
sendMessage(request);
final NXCPMessage response = waitForRCC(request.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_VARIABLES);
final HashMap varList = new HashMap(count);
long id = NXCPCodes.VID_VARLIST_BASE;
for(int i = 0; i < count; i++, id += 10)
{
ServerVariable v = new ServerVariable(response, id);
varList.put(v.getName(), v);
}
count = response.getFieldAsInt32(NXCPCodes.VID_NUM_VALUES);
for(int i = 0; i < count; i++)
{
ServerVariable var = varList.get(response.getFieldAsString(id++));
if (var != null)
var.addPossibleValue(response, id);
id += 2;
}
return varList;
}
/**
* Get server public configuration variable
*
* @param name configuration variable name
* @return value of requested configuration variable
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String getPublicServerVariable(String name) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_PUBLIC_CONFIG_VAR);
msg.setField(NXCPCodes.VID_NAME, name);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsString(NXCPCodes.VID_VALUE);
}
/**
* Get server public configuration variable as a int
*
* @param name configuration variable name
* @return value of requested configuration variable
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public int getPublicServerVariableAsInt(String name) throws IOException, NXCException
{
return Integer.parseInt(getPublicServerVariable(name));
}
/**
* Get server public configuration variable as boolen value
*
* @param name configuration variable name
* @return value of requested configuration variable
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public boolean getPublicServerVariableAsBoolean(String name) throws IOException, NXCException
{
String value = getPublicServerVariable(name);
if ((value.equalsIgnoreCase("true")) || (value.equalsIgnoreCase("yes")))
return true;
if ((value.equalsIgnoreCase("false")) || (value.equalsIgnoreCase("no")))
return false;
try
{
int n = Integer.parseInt(value);
return n != 0;
}
catch(NumberFormatException e)
{
return false;
}
}
/**
* Set server configuration variable
*
* @param name The name of the variable
* @param value The value of the variable
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setServerVariable(final String name, final String value) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_CONFIG_VARIABLE);
msg.setField(NXCPCodes.VID_NAME, name);
msg.setField(NXCPCodes.VID_VALUE, value);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Delete server configuration variable
*
* @param name The name of the variable
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteServerVariable(final String name) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_CONFIG_VARIABLE);
msg.setField(NXCPCodes.VID_NAME, name);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Set server configuration variables to default
*
* @param varList The list of variables
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setDefaultServerValues(List varList) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_CONFIG_TO_DEFAULT);
long base = NXCPCodes.VID_VARLIST_BASE;
for(ServerVariable v : varList)
msg.setField(base++, v.getName());
msg.setFieldInt32(NXCPCodes.VID_NUM_VARIABLES, varList.size());
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get server config CLOB
*
* @param name The name of the config
* @return The config CLOB
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String getServerConfigClob(final String name) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_CONFIG_GET_CLOB);
msg.setField(NXCPCodes.VID_NAME, name);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsString(NXCPCodes.VID_VALUE);
}
/**
* Set server config CLOB
*
* @param name The name to set
* @param value The value to set
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setServerConfigClob(final String name, final String value) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_CONFIG_SET_CLOB);
msg.setField(NXCPCodes.VID_NAME, name);
msg.setField(NXCPCodes.VID_VALUE, value);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Subscribe to notification channel. Each subscribe call should be matched by unsubscribe call.
* Calling subscribe on already subscribed channel will increase internal counter, and subscription
* will be cancelled when this counter returns back to 0.
*
* @param channel Notification channel to subscribe to.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void subscribe(String channel) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_CHANGE_SUBSCRIPTION);
msg.setField(NXCPCodes.VID_NAME, channel);
msg.setFieldInt16(NXCPCodes.VID_OPERATION, 1);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Unsubscribe from notification channel.
*
* @param channel Notification channel to unsubscribe from.
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void unsubscribe(String channel) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_CHANGE_SUBSCRIPTION);
msg.setField(NXCPCodes.VID_NAME, channel);
msg.setFieldInt16(NXCPCodes.VID_OPERATION, 0);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Synchronize user database and subscribe to user change notifications
*
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncUserDatabase() throws IOException, NXCException
{
syncUserDB.acquireUninterruptibly();
NXCPMessage msg = newMessage(NXCPCodes.CMD_LOAD_USER_DB);
sendMessage(msg);
waitForRCC(msg.getMessageId());
waitForSync(syncUserDB, commandTimeout * 10);
userDatabaseSynchronized = true;
subscribe(CHANNEL_USERDB);
}
/**
* Subscribe to user change notifications
*
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void subscribeToUserDBUpdates() throws IOException, NXCException
{
subscribe(CHANNEL_USERDB);
}
/**
* Synchronize users by id if does not exist
*
* @param users list of user id's to synchronize
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncUserSet(Set users) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_SELECTED_USERS);
msg.setFieldInt32(NXCPCodes.VID_NUM_OBJECTS, users.size());
msg.setField(NXCPCodes.VID_OBJECT_LIST, users);
sendMessage(msg);
// First request completion message will indicate successful sync start
waitForRCC(msg.getMessageId());
// Server will send second completion message when all user database objects were sent back
waitForRCC(msg.getMessageId());
// Check that each user from set was synchronized and add update missing list
synchronized(userDatabase)
{
for(Long id : users)
{
if (userDatabase.containsKey(id))
missingUsers.remove(id);
else
missingUsers.add(id);
}
}
}
/**
* Synchronize only objects that were not yet synchronized
*
* @param users set of user IDs to sync
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
* @return true if synchronization was completed and false if synchronization is not needed
*/
public boolean syncMissingUsers(Set users) throws IOException, NXCException
{
if (userDatabaseSynchronized)
return false;
final Set syncSet = new HashSet();
synchronized(userDatabase)
{
for(Long id : users)
{
if (!userDatabase.containsKey(id))
syncSet.add(id);
}
}
if (!syncSet.isEmpty())
syncUserSet(syncSet);
return !syncSet.isEmpty();
}
/**
* Check if user database is synchronized with client
*
* @return true if user database is synchronized with client
*/
public boolean isUserDatabaseSynchronized()
{
return userDatabaseSynchronized;
}
/**
* Find multiple users by list of IDs
*
* @param ids of user DBObjects to find
* @return list of found users
*/
public List findUserDBObjectsByIds(final Collection ids)
{
List users = new ArrayList();
synchronized(userDatabase)
{
for(Long l : ids)
{
AbstractUserObject user = userDatabase.get(l);
if (user != null)
users.add(user);
}
}
return users;
}
/**
* Find user or group by ID. If full user database synchronization was not done this method may return null for existing user
* that is not yet synchronized with the client. In such case client library will initiate background synchronization of that
* user object. If provided callback is not null it will be executed when synchronization is complete.
*
* @param id The user database object ID
* @param callback synchronization completion callback (may be null)
* @return User object with given ID or null if such user does not exist or not synchronized with client.
*/
public AbstractUserObject findUserDBObjectById(final long id, Runnable callback)
{
AbstractUserObject object = null;
boolean needSync = false;
synchronized(userDatabase)
{
object = userDatabase.get(id);
if ((object == null) && !userDatabaseSynchronized && !missingUsers.contains(id))
needSync = true;
}
if (needSync)
{
synchronized(userSyncList)
{
userSyncList.add(id);
if (callback != null)
callbackList.add(callback);
userSyncList.notifyAll();
}
}
return object;
}
/**
* Find user or group by GUID
*
* @param guid The user DBObject GUID
* @return User object with given GUID or null if such user does not exist
*/
public AbstractUserObject findUserDBObjectByGUID(final UUID guid)
{
synchronized(userDatabase)
{
return userDatabaseGUID.get(guid);
}
}
/**
* Get list of all user database objects
*
* @return List of all user database objects
*/
public AbstractUserObject[] getUserDatabaseObjects()
{
AbstractUserObject[] list;
synchronized(userDatabase)
{
Collection values = userDatabase.values();
list = values.toArray(new AbstractUserObject[values.size()]);
}
return list;
}
/**
* Create user or group on server
*
* @param name Login name for new user
* @return ID assigned to newly created user
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private long createUserDBObject(final String name, final boolean isGroup) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_CREATE_USER);
msg.setField(NXCPCodes.VID_USER_NAME, name);
msg.setField(NXCPCodes.VID_IS_GROUP, isGroup);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsInt64(NXCPCodes.VID_USER_ID);
}
/**
* Create user on server
*
* @param name Login name for new user
* @return ID assigned to newly created user
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long createUser(final String name) throws IOException, NXCException
{
return createUserDBObject(name, false);
}
/**
* Create user group on server
*
* @param name Name for new user group
* @return ID assigned to newly created user group
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long createUserGroup(final String name) throws IOException, NXCException
{
return createUserDBObject(name, true);
}
/**
* Delete user or group on server
*
* @param id User or group ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteUserDBObject(final long id) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_USER);
msg.setFieldInt32(NXCPCodes.VID_USER_ID, (int)id);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Set password for user
*
* @param id User ID
* @param newPassword New password
* @param oldPassword Old password
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setUserPassword(final long id, final String newPassword, final String oldPassword) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_PASSWORD);
msg.setFieldInt32(NXCPCodes.VID_USER_ID, (int)id);
msg.setField(NXCPCodes.VID_PASSWORD, newPassword);
if (oldPassword != null)
msg.setField(NXCPCodes.VID_OLD_PASSWORD, oldPassword);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Validate password for currently logged in user
*
* @param password password to validate
* @return true if password is valid
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public boolean validateUserPassword(String password) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_VALIDATE_PASSWORD);
msg.setField(NXCPCodes.VID_PASSWORD, password);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsBoolean(NXCPCodes.VID_PASSWORD_IS_VALID);
}
/**
* Modify user database object
*
* @param object User data
* @param fields bit mask indicating fields to modify
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void modifyUserDBObject(final AbstractUserObject object, final int fields) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_USER);
msg.setFieldInt32(NXCPCodes.VID_FIELDS, fields);
object.fillMessage(msg);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Modify user database object
*
* @param object User data
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void modifyUserDBObject(final AbstractUserObject object) throws IOException, NXCException
{
modifyUserDBObject(object, 0x7FFFFFFF);
}
/**
* Detach user from LDAP
*
* @param userId user ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void detachUserFromLdap(long userId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DETACH_LDAP_USER);
msg.setFieldInt32(NXCPCodes.VID_USER_ID, (int)userId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Set custom attribute for currently logged in user. Server will allow to change
* only attributes whose name starts with dot.
*
* @param name Attribute's name
* @param value New attribute's value
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setAttributeForCurrentUser(final String name, final String value) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_CURRENT_USER_ATTR);
msg.setField(NXCPCodes.VID_NAME, name);
msg.setField(NXCPCodes.VID_VALUE, value);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get custom attribute for currently logged in user. If attribute is not set, empty string will
* be returned.
*
* @param name Attribute's name
* @return Attribute's value
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String getAttributeForCurrentUser(final String name) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_CURRENT_USER_ATTR);
msg.setField(NXCPCodes.VID_NAME, name);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsString(NXCPCodes.VID_VALUE);
}
/**
* Find all DCIs matching given creteria.
*
* @param objectId if specific object needed (set to 0 if match by object name is needed)
* @param objectName regular expression to match object name (not used if object ID is not 0)
* @param dciName regular expression to match DCI name
* @param flags find flags
* @return list of all found DCIs and their last values
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List findMatchingDCI(long objectId, String objectName, String dciName, int flags) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_MATCHING_DCI);
if (objectId != 0)
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
else
msg.setField(NXCPCodes.VID_OBJECT_NAME, objectName);
msg.setField(NXCPCodes.VID_DCI_NAME, dciName);
msg.setFieldInt32(NXCPCodes.VID_FLAGS, flags);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ITEMS);
List result = new ArrayList(count);
Long base = NXCPCodes.VID_DCI_VALUES_BASE;
for(int i = 0; i < count; i++, base += 50)
{
result.add(new SimpleDciValue(response, base));
}
return result;
}
/**
* Get last DCI values for given node
*
* @param nodeId ID of the node to get DCI values for
* @param objectTooltipOnly if set to true, only DCIs with DCF_SHOW_ON_OBJECT_TOOLTIP flag set are returned
* @param overviewOnly if set to true, only DCIs with DCF_SHOW_IN_OBJECT_OVERVIEW flag set are returned
* @param includeNoValueObjects if set to true, objects with no value (like instance discovery DCIs) will be returned as well
* @return List of DCI values
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DciValue[] getLastValues(final long nodeId, boolean objectTooltipOnly, boolean overviewOnly,
boolean includeNoValueObjects) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_LAST_VALUES);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setField(NXCPCodes.VID_OBJECT_TOOLTIP_ONLY, objectTooltipOnly);
msg.setField(NXCPCodes.VID_OVERVIEW_ONLY, overviewOnly);
msg.setField(NXCPCodes.VID_INCLUDE_NOVALUE_OBJECTS, includeNoValueObjects);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ITEMS);
DciValue[] list = new DciValue[count];
long base = NXCPCodes.VID_DCI_VALUES_BASE;
for(int i = 0; i < count; i++, base += 50)
{
list[i] = DciValue.createFromMessage(response, base);
}
return list;
}
/**
* Get last DCI values for given node
*
* @param nodeId ID of the node to get DCI values for
* @return List of DCI values
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DciValue[] getLastValues(final long nodeId) throws IOException, NXCException
{
return getLastValues(nodeId, false, false, false);
}
/**
* Get tooltip last values for all objects
*
* @param nodeList list of node IDs
* @return map with node id to DCI last values
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map getTooltipLastValues(Set nodeList) throws IOException, NXCException
{
Map cachedDciValues = new HashMap();
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_TOOLTIP_LAST_VALUES);
msg.setField(NXCPCodes.VID_OBJECT_LIST, nodeList.toArray(new Long[nodeList.size()]));
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ITEMS);
long base = NXCPCodes.VID_DCI_VALUES_BASE;
List values = null;
Long nodeId = 0L;
for (int i = 0; i < count; i++, base += 50)
{
DciValue v = (DciValue)new SimpleDciValue(response, base);
if(nodeId != v.getNodeId())
{
if (nodeId != 0)
{
cachedDciValues.put(nodeId, values.toArray(new DciValue[values.size()]));
}
values = new ArrayList();
nodeId = v.getNodeId();
}
values.add(v);
}
if (nodeId != 0)
{
cachedDciValues.put(nodeId, values.toArray(new DciValue[values.size()]));
}
return cachedDciValues;
}
/**
* Get last DCI values for given Map DCI Instance list
*
* @param mapDcis List with Map DCI Instances
* @return List of DCI values
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DciValue[] getLastValues(Set mapDcis) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_DCI_VALUES);
long base = NXCPCodes.VID_DCI_VALUES_BASE;
msg.setFieldInt32(NXCPCodes.VID_NUM_ITEMS, mapDcis.size());
for(MapDCIInstance item : mapDcis)
{
item.fillMessage(msg, base);
base += 10;
}
return doLastValuesRequest(msg);
}
/**
* Get last DCI values for given Single Dci Config list
*
* @param dciConfig List with Single Dci Configs
* @return List of DCI values
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DciValue[] getLastValues(List dciConfig) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_DCI_VALUES);
long base = NXCPCodes.VID_DCI_VALUES_BASE;
msg.setFieldInt32(NXCPCodes.VID_NUM_ITEMS, dciConfig.size());
for(SingleDciConfig c : dciConfig)
{
c.fillMessage(msg, base);
base += 10;
}
return doLastValuesRequest(msg);
}
/**
* Send request for last values using prepared message
*
* @param msg NXCP message to send
* @return The DCI values
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private DciValue[] doLastValuesRequest(NXCPMessage msg) throws IOException, NXCException
{
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ITEMS);
DciValue[] list = new DciValue[count];
long fieldId = NXCPCodes.VID_DCI_VALUES_BASE;
for(int i = 0; i < count; i++, fieldId += 50)
{
list[i] = (DciValue)new SimpleDciValue(response, fieldId);
}
return list;
}
/**
* Get active thresholds
*
* @param dciConfig Dci config
* @return list of active thresholds
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getActiveThresholds(List dciConfig) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ACTIVE_THRESHOLDS);
long base = NXCPCodes.VID_DCI_VALUES_BASE;
msg.setFieldInt32(NXCPCodes.VID_NUM_ITEMS, dciConfig.size());
for(SingleDciConfig c : dciConfig)
{
c.fillMessage(msg, base);
base += 10;
}
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_THRESHOLDS);
List list = new ArrayList(count);
base = NXCPCodes.VID_DCI_THRESHOLD_BASE;
for(int i = 0; i < count; i++, base += 20)
{
list.add(new Threshold(response, base));
}
return list;
}
/**
* Get last value for given table DCI on given node
*
* @param nodeId ID of the node to get DCI values for
* @param dciId DCI ID
* @return Table object with last values for table DCI
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Table getTableLastValues(final long nodeId, final long dciId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_TABLE_LAST_VALUE);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return new Table(response);
}
/**
* Get last value for given table or single valued DCI on given node
*
* @param nodeId ID of the node to get DCI values for
* @param dciId DCI ID
* @return Last value object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DciLastValue getDciLastValue(final long nodeId, final long dciId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_DCI_LAST_VALUE);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return new DciLastValue(response);
}
/**
* Get list of DCIs configured to be shown on performance tab in console for given node.
*
* @param nodeId Node object ID
* @return List of performance tab DCIs
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getPerfTabItems(final long nodeId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_PERFTAB_DCI_LIST);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ITEMS);
List list = new ArrayList(count);
long baseId = NXCPCodes.VID_SYSDCI_LIST_BASE;
for(int i = 0; i < count; i++, baseId += 50)
list.add(new PerfTabDci(response, baseId, nodeId));
return list;
}
/**
* Get threshold violation summary for all nodes under given parent object. Parent object could
* be container, subnet, zone, entire network, or infrastructure service root.
*
* @param objectId parent object ID
* @return list of threshold violation summary objects for all nodes below given root
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getThresholdSummary(final long objectId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_THRESHOLD_SUMMARY);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
List list = new ArrayList();
long varId = NXCPCodes.VID_THRESHOLD_BASE;
while(response.getFieldAsInt64(varId) != 0)
{
final ThresholdViolationSummary t = new ThresholdViolationSummary(response, varId);
list.add(t);
varId += 50 * t.getDciList().size() + 2;
}
return list;
}
/**
* Parse data from raw message CMD_DCI_DATA.
* This method is intended for calling by client internal methods only. It made public to
* allow access from client extensions.
*
* @param input Raw data
* @param data Data object to add rows to
* @return number of received data rows
*/
public int parseDataRows(final byte[] input, DciData data)
{
final NXCPDataInputStream inputStream = new NXCPDataInputStream(input);
int rows = 0;
DciDataRow row = null;
try
{
inputStream.skipBytes(4); // DCI ID
rows = inputStream.readInt();
final DataType dataType = DataType.getByValue(inputStream.readInt());
data.setDataType(dataType);
inputStream.skipBytes(4); // padding
for(int i = 0; i < rows; i++)
{
long timestamp = inputStream.readUnsignedInt() * 1000; // convert to milliseconds
Object value;
switch(dataType)
{
case INT32:
value = Long.valueOf(inputStream.readInt());
break;
case UINT32:
case COUNTER32:
value = Long.valueOf(inputStream.readUnsignedInt());
break;
case INT64:
case UINT64:
case COUNTER64:
inputStream.skipBytes(4); // padding
value = Long.valueOf(inputStream.readLong());
break;
case FLOAT:
inputStream.skipBytes(4); // padding
value = Double.valueOf(inputStream.readDouble());
break;
case STRING:
StringBuilder sb = new StringBuilder(256);
int count;
for(count = MAX_DCI_STRING_VALUE_LENGTH; count > 0; count--)
{
char ch = inputStream.readChar();
if (ch == 0)
{
count--;
break;
}
sb.append(ch);
}
inputStream.skipBytes(count * 2);
value = sb.toString();
break;
default:
value = null;
break;
}
if (timestamp > 0)
{
row = new DciDataRow(new Date(timestamp), value);
data.addDataRow(row);
}
else
{
// raw value for previous entry
if (row != null)
row.setRawValue(value);
}
}
}
catch(IOException e)
{
}
inputStream.close();
return rows;
}
/**
* Get collected DCI data from server. Please note that you should specify
* either row count limit or time from/to limit.
*
* @param nodeId Node ID
* @param dciId DCI ID
* @param instance instance value (for table DCI only)
* @param dataColumn name of column to retrieve data from (for table DCI only)
* @param from Start of time range or null for no limit
* @param to End of time range or null for no limit
* @param maxRows Maximum number of rows to retrieve or 0 for no limit
* @param valueType TODO
* @return DCI data set
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private DciData getCollectedDataInternal(long nodeId, long dciId, String instance, String dataColumn, Date from, Date to,
int maxRows, HistoricalDataType valueType) throws IOException, NXCException
{
NXCPMessage msg;
if (instance != null) // table DCI
{
msg = newMessage(NXCPCodes.CMD_GET_TABLE_DCI_DATA);
msg.setField(NXCPCodes.VID_INSTANCE, instance);
msg.setField(NXCPCodes.VID_DATA_COLUMN, dataColumn);
}
else
{
msg = newMessage((valueType == HistoricalDataType.FULL_TABLE) ? NXCPCodes.CMD_GET_TABLE_DCI_DATA : NXCPCodes.CMD_GET_DCI_DATA);
}
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
msg.setFieldInt16(NXCPCodes.VID_HISTORICAL_DATA_TYPE, valueType.getValue());
DciData data = new DciData(nodeId, dciId);
int timeFrom = (from != null) ? (int)(from.getTime() / 1000) : 0;
int timeTo = (to != null) ? (int)(to.getTime() / 1000) : 0;
// If full table values are requested, each value will be sent in separate message
if (valueType == HistoricalDataType.FULL_TABLE)
{
msg.setFieldInt32(NXCPCodes.VID_MAX_ROWS, maxRows);
msg.setFieldInt32(NXCPCodes.VID_TIME_FROM, timeFrom);
msg.setFieldInt32(NXCPCodes.VID_TIME_TO, timeTo);
sendMessage(msg);
waitForRCC(msg.getMessageId());
while(true)
{
NXCPMessage response = waitForMessage(NXCPCodes.CMD_DCI_DATA, msg.getMessageId());
long timestamp = response.getFieldAsInt64(NXCPCodes.VID_TIMESTAMP) * 1000L; // Convert to milliseconds
if (timestamp == 0)
break; // End of value list indicator
data.addDataRow(new DciDataRow(new Date(timestamp), new Table(response)));
}
}
else
{
int rowsReceived, rowsRemaining = maxRows;
do
{
msg.setMessageId(requestId.getAndIncrement());
msg.setFieldInt32(NXCPCodes.VID_MAX_ROWS, maxRows);
msg.setFieldInt32(NXCPCodes.VID_TIME_FROM, timeFrom);
msg.setFieldInt32(NXCPCodes.VID_TIME_TO, timeTo);
sendMessage(msg);
waitForRCC(msg.getMessageId());
NXCPMessage response = waitForMessage(NXCPCodes.CMD_DCI_DATA, msg.getMessageId());
if (!response.isBinaryMessage())
throw new NXCException(RCC.INTERNAL_ERROR);
rowsReceived = parseDataRows(response.getBinaryData(), data);
if (((rowsRemaining == 0) || (rowsRemaining > MAX_DCI_DATA_ROWS)) && (rowsReceived == MAX_DCI_DATA_ROWS))
{
// adjust boundaries for next request
if (rowsRemaining > 0)
rowsRemaining -= rowsReceived;
// Rows goes in newest to oldest order, so if we need to
// retrieve additional data, we should update timeTo limit
if (to != null)
{
DciDataRow row = data.getLastValue();
if (row != null)
{
// There should be only one value per second, so we set
// last row's timestamp - 1 second as new boundary
timeTo = (int)(row.getTimestamp().getTime() / 1000) - 1;
}
}
}
} while(rowsReceived == MAX_DCI_DATA_ROWS);
}
return data;
}
/**
* Get collected DCI data from server. Please note that you should specify
* either row count limit or time from/to limit.
*
* @param nodeId Node ID
* @param dciId DCI ID
* @param from Start of time range or null for no limit
* @param to End of time range or null for no limit
* @param maxRows Maximum number of rows to retrieve or 0 for no limit
* @param valueType TODO
* @return DCI data set
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DciData getCollectedData(long nodeId, long dciId, Date from, Date to, int maxRows, HistoricalDataType valueType)
throws IOException, NXCException
{
return getCollectedDataInternal(nodeId, dciId, null, null, from, to, maxRows, valueType);
}
/**
* Get collected table DCI data from server. Please note that you should specify
* either row count limit or time from/to limit.
*
* @param nodeId Node ID
* @param dciId DCI ID
* @param instance instance value
* @param dataColumn name of column to retrieve data from
* @param from Start of time range or null for no limit
* @param to End of time range or null for no limit
* @param maxRows Maximum number of rows to retrieve or 0 for no limit
* @return DCI data set
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DciData getCollectedTableData(long nodeId, long dciId, String instance, String dataColumn, Date from, Date to,
int maxRows) throws IOException, NXCException
{
if (instance == null || dataColumn == null)
throw new NXCException(RCC.INVALID_ARGUMENT);
return getCollectedDataInternal(nodeId, dciId, instance, dataColumn, from, to, maxRows, HistoricalDataType.PROCESSED);
}
/**
* Clear collected data for given DCI
*
* @param nodeId Node object ID
* @param dciId DCI ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void clearCollectedData(long nodeId, long dciId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_CLEAR_DCI_DATA);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Delete collected data entry for given DCI
*
* @param nodeId Node object ID
* @param dciId DCI ID
* @param timestamp timestamp of entry
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteDciEntry(long nodeId, long dciId, long timestamp) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_DCI_ENTRY);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
msg.setFieldInt32(NXCPCodes.VID_TIMESTAMP, (int)timestamp);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Start recalculation of DCI values using preserver raw values.
*
* @param objectId object ID
* @param dciId DCI ID
* @return assigned job ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long recalculateDCIValues(long objectId, long dciId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_RECALCULATE_DCI_VALUES);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsInt64(NXCPCodes.VID_JOB_ID);
}
/**
* Force DCI poll for given DCI
*
* @param nodeId Node object ID
* @param dciId DCI ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void forceDCIPoll(long nodeId, long dciId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_FORCE_DCI_POLL);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get list of thresholds configured for given DCI
*
* @param nodeId Node object ID
* @param dciId DCI ID
* @return List of configured thresholds
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Threshold[] getThresholds(final long nodeId, final long dciId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_DCI_THRESHOLDS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_DCI_ID, (int)dciId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_THRESHOLDS);
final Threshold[] list = new Threshold[count];
long fieldId = NXCPCodes.VID_DCI_THRESHOLD_BASE;
for(int i = 0; i < count; i++)
{
list[i] = new Threshold(response, fieldId);
fieldId += 20;
}
return list;
}
/**
* Get names for given DCI list
*
* @param nodeIds node identifiers
* @param dciIds DCI identifiers (length must match length of node identifiers list)
* @return array of resolved DCI names
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map dciIdsToNames(List nodeIds, List dciIds) throws IOException, NXCException
{
if (nodeIds.isEmpty())
return new HashMap();
final NXCPMessage msg = newMessage(NXCPCodes.CMD_RESOLVE_DCI_NAMES);
msg.setFieldInt32(NXCPCodes.VID_NUM_ITEMS, nodeIds.size());
msg.setField(NXCPCodes.VID_NODE_LIST, nodeIds);
msg.setField(NXCPCodes.VID_DCI_LIST, dciIds);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
Map result = new HashMap();
int size = response.getFieldAsInt32(NXCPCodes.VID_NUM_ITEMS);
long fieldId = NXCPCodes.VID_DCI_LIST_BASE;
for(int i = 0; i < size; i++)
{
result.put(response.getFieldAsInt64(fieldId), new DciInfo(response.getFieldAsString(fieldId + 1), response.getFieldAsString(fieldId + 2)));
fieldId += 3;
}
return result;
}
/**
* Get names for given DCI list
*
* @param itemList list of items to resolved
* @return map of DCI id to DCI description
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map dciIdsToNames(Collection extends NodeItemPair> itemList) throws IOException, NXCException
{
if (itemList.isEmpty())
return new HashMap();
List nodeIds = new ArrayList();
List dciIds = new ArrayList();
for(NodeItemPair nodeItem : itemList)
{
if (nodeItem.getNodeId() != 0 && nodeItem.getDciId() != 0)
{
nodeIds.add(nodeItem.getNodeId());
dciIds.add(nodeItem.getDciId());
}
}
return dciIdsToNames(nodeIds, dciIds);
}
/**
* Get DCI ID for given DCI name
*
* @param nodeId node object identifier
* @param dciName DCI name
* @return id of DCI with given name
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long dciNameToId(long nodeId, String dciName) throws IOException, NXCException
{
if (nodeId == 0 || dciName == null || dciName.isEmpty())
return 0;
DciValue[] list = getLastValues(nodeId);
for(DciValue dciValue : list)
{
if (dciValue.getName().equals(dciName))
return dciValue.getId();
}
return 0;
}
/**
* Query parameter immediately. This call will cause server to do actual call
* to managed node and will return current value for given parameter. Result
* is not cached.
*
* @param nodeId node object ID
* @param origin parameter's origin (NetXMS agent, SNMP, etc.)
* @param name parameter's name
* @return current parameter's value
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String queryParameter(long nodeId, DataOrigin origin, String name) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_QUERY_PARAMETER);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt16(NXCPCodes.VID_DCI_SOURCE_TYPE, origin.getValue());
msg.setField(NXCPCodes.VID_NAME, name);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsString(NXCPCodes.VID_VALUE);
}
/**
* Query agent's table immediately. This call will cause server to do actual
* call to managed node and will return current value for given table. Result
* is not cached.
*
* @param nodeId node object ID
* @param name table's name
* @return current table's value
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Table queryAgentTable(long nodeId, String name) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_QUERY_TABLE);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setField(NXCPCodes.VID_NAME, name);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return new Table(response);
}
/**
* Hook method to allow adding of custom object creation data to NXCP message.
* Default implementation does nothing.
*
* @param data object creation data passed to createObject
* @param userData user-defined data for object creation passed to createObject
* @param msg NXCP message that will be sent to server
*/
protected void createCustomObject(NXCObjectCreationData data, Object userData, NXCPMessage msg)
{
}
/**
* Create new NetXMS object.
*
* @param data Object creation data
* @param userData User-defined data for custom object creation
* @return ID of new object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long createObject(final NXCObjectCreationData data, final Object userData) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_CREATE_OBJECT);
// Common attributes
msg.setFieldInt32(NXCPCodes.VID_PARENT_ID, (int)data.getParentId());
msg.setFieldInt16(NXCPCodes.VID_OBJECT_CLASS, data.getObjectClass());
msg.setField(NXCPCodes.VID_OBJECT_NAME, data.getName());
if ((data.getObjectAlias() != null) && !data.getObjectAlias().isEmpty())
msg.setField(NXCPCodes.VID_ALIAS, data.getObjectAlias());
msg.setFieldInt32(NXCPCodes.VID_ZONE_UIN, data.getZoneUIN());
msg.setFieldInt32(NXCPCodes.VID_ASSET_ID, (int)data.getAssetId());
if (data.getComments() != null)
msg.setField(NXCPCodes.VID_COMMENTS, data.getComments());
// Class-specific attributes
switch(data.getObjectClass())
{
case AbstractObject.OBJECT_ASSET:
if (data.getAssetProperties() != null)
msg.setFieldsFromStringMap(data.getAssetProperties(), NXCPCodes.VID_ASSET_PROPERTIES_BASE, NXCPCodes.VID_NUM_ASSET_PROPERTIES);
break;
case AbstractObject.OBJECT_CHASSIS:
msg.setFieldInt32(NXCPCodes.VID_CONTROLLER_ID, (int)data.getControllerId());
break;
case AbstractObject.OBJECT_INTERFACE:
msg.setField(NXCPCodes.VID_MAC_ADDR, data.getMacAddress().getValue());
msg.setField(NXCPCodes.VID_IP_ADDRESS, data.getIpAddress());
msg.setFieldInt32(NXCPCodes.VID_IF_TYPE, data.getIfType());
msg.setFieldInt32(NXCPCodes.VID_IF_INDEX, data.getIfIndex());
msg.setFieldInt32(NXCPCodes.VID_PHY_CHASSIS, data.getChassis());
msg.setFieldInt32(NXCPCodes.VID_PHY_MODULE, data.getModule());
msg.setFieldInt32(NXCPCodes.VID_PHY_PIC, data.getPIC());
msg.setFieldInt32(NXCPCodes.VID_PHY_PORT, data.getPort());
msg.setFieldInt16(NXCPCodes.VID_IS_PHYS_PORT, data.isPhysicalPort() ? 1 : 0);
break;
case AbstractObject.OBJECT_MOBILEDEVICE:
msg.setField(NXCPCodes.VID_DEVICE_ID, data.getDeviceId());
break;
case AbstractObject.OBJECT_NODE:
if (data.getPrimaryName() != null)
msg.setField(NXCPCodes.VID_PRIMARY_NAME, data.getPrimaryName());
msg.setField(NXCPCodes.VID_IP_ADDRESS, data.getIpAddress());
msg.setFieldInt16(NXCPCodes.VID_AGENT_PORT, data.getAgentPort());
msg.setFieldInt16(NXCPCodes.VID_SNMP_PORT, data.getSnmpPort());
msg.setFieldInt16(NXCPCodes.VID_ETHERNET_IP_PORT, data.getEtherNetIpPort());
msg.setFieldInt16(NXCPCodes.VID_MODBUS_TCP_PORT, data.getModbusTcpPort());
msg.setFieldInt16(NXCPCodes.VID_MODBUS_UNIT_ID, data.getModbusUnitId());
msg.setFieldInt16(NXCPCodes.VID_SSH_PORT, data.getSshPort());
msg.setFieldInt32(NXCPCodes.VID_CREATION_FLAGS, data.getCreationFlags());
msg.setFieldInt32(NXCPCodes.VID_AGENT_PROXY, (int)data.getAgentProxyId());
msg.setFieldInt32(NXCPCodes.VID_SNMP_PROXY, (int)data.getSnmpProxyId());
msg.setFieldInt32(NXCPCodes.VID_MQTT_PROXY, (int)data.getMqttProxyId());
msg.setFieldInt32(NXCPCodes.VID_ETHERNET_IP_PROXY, (int)data.getEtherNetIpProxyId());
msg.setFieldInt32(NXCPCodes.VID_MODBUS_PROXY, (int)data.getModbusProxyId());
msg.setFieldInt32(NXCPCodes.VID_ICMP_PROXY, (int)data.getIcmpProxyId());
msg.setFieldInt32(NXCPCodes.VID_SSH_PROXY, (int)data.getSshProxyId());
msg.setField(NXCPCodes.VID_SSH_LOGIN, data.getSshLogin());
msg.setField(NXCPCodes.VID_SSH_PASSWORD, data.getSshPassword());
msg.setFieldInt32(NXCPCodes.VID_WEB_SERVICE_PROXY, (int)data.getWebServiceProxyId());
break;
case AbstractObject.OBJECT_NETWORKMAP:
msg.setFieldInt16(NXCPCodes.VID_MAP_TYPE, data.getMapType());
msg.setField(NXCPCodes.VID_SEED_OBJECTS, data.getSeedObjectIds());
msg.setFieldInt32(NXCPCodes.VID_FLAGS, (int)data.getFlags());
break;
case AbstractObject.OBJECT_NETWORKSERVICE:
msg.setFieldInt16(NXCPCodes.VID_SERVICE_TYPE, data.getServiceType());
msg.setFieldInt16(NXCPCodes.VID_IP_PROTO, data.getIpProtocol());
msg.setFieldInt16(NXCPCodes.VID_IP_PORT, data.getIpPort());
msg.setField(NXCPCodes.VID_SERVICE_REQUEST, data.getRequest());
msg.setField(NXCPCodes.VID_SERVICE_RESPONSE, data.getResponse());
msg.setFieldInt16(NXCPCodes.VID_CREATE_STATUS_DCI, data.isCreateStatusDci() ? 1 : 0);
break;
case AbstractObject.OBJECT_RACK:
msg.setFieldInt16(NXCPCodes.VID_HEIGHT, data.getHeight());
break;
case AbstractObject.OBJECT_SENSOR:
msg.setFieldInt32(NXCPCodes.VID_SENSOR_FLAGS, data.getFlags());
msg.setField(NXCPCodes.VID_MAC_ADDR, data.getMacAddress());
msg.setFieldInt32(NXCPCodes.VID_DEVICE_CLASS, data.getDeviceClass());
msg.setField(NXCPCodes.VID_VENDOR, data.getVendor());
msg.setFieldInt32(NXCPCodes.VID_COMM_PROTOCOL, data.getCommProtocol());
msg.setField(NXCPCodes.VID_XML_CONFIG, data.getXmlConfig());
msg.setField(NXCPCodes.VID_XML_REG_CONFIG, data.getXmlRegConfig());
msg.setField(NXCPCodes.VID_SERIAL_NUMBER, data.getSerialNumber());
msg.setField(NXCPCodes.VID_DEVICE_ADDRESS, data.getDeviceAddress());
msg.setField(NXCPCodes.VID_META_TYPE, data.getMetaType());
msg.setField(NXCPCodes.VID_DESCRIPTION, data.getDescription());
msg.setFieldInt32(NXCPCodes.VID_SENSOR_PROXY, (int)data.getSensorProxy());
break;
case AbstractObject.OBJECT_SUBNET:
msg.setField(NXCPCodes.VID_IP_ADDRESS, data.getIpAddress());
break;
case AbstractObject.OBJECT_BUSINESSSERVICEPROTOTYPE:
msg.setFieldInt16(NXCPCodes.VID_INSTD_METHOD, data.getInstanceDiscoveryMethod());
break;
}
if (userData != null)
createCustomObject(data, userData, msg);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsInt64(NXCPCodes.VID_OBJECT_ID);
}
/**
* Create new NetXMS object. Equivalent of calling createObject(data, null).
*
* @param data Object creation data
* @return ID of new object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long createObject(final NXCObjectCreationData data) throws IOException, NXCException
{
return createObject(data, null);
}
/**
* Create new NetXMS object in synchronous mode.
*
* @param data Object creation data
* @return newly created AbstractObject
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public AbstractObject createObjectSync(final NXCObjectCreationData data) throws IOException, NXCException
{
long id = createObject(data, null);
FutureObject object = findFutureObjectById(id);
synchronized (object)
{
while (!object.hasObject())
{
try
{
object.wait();
}
catch(InterruptedException e)
{
}
}
}
return object.getObject();
}
/**
* Create new NetXMS object and run callback once it's created.
*
* @param data Object creation data
* @param callback callback to run on object creation
* @return ID of new object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long createObjectAsync(final NXCObjectCreationData data, ObjectCreationListener callback) throws IOException, NXCException
{
long id = createObject(data, null);
findObjectAsync(id, callback);
return id;
}
/**
* Delete object
*
* @param objectId ID of an object which should be deleted
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteObject(final long objectId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_OBJECT);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
// If server reports success, delete object from cache and generate
// appropriate notification without waiting for actual server update
synchronized(objectList)
{
AbstractObject object = objectList.get(objectId);
if (object != null)
{
objectList.remove(objectId);
objectListGUID.remove(object.getGuid());
if (object instanceof Zone)
zoneList.remove(((Zone)object).getUIN());
removeOrphanedObjects(object);
}
}
sendNotification(new SessionNotification(SessionNotification.OBJECT_DELETED, objectId));
}
/**
* Remove orphaned objects (with last parent left)
*
* @param parent
*/
private void removeOrphanedObjects(AbstractObject parent)
{
Iterator it = parent.getChildren();
while(it.hasNext())
{
AbstractObject object = objectList.get(it.next());
if ((object != null) && (object.getParentCount() == 1))
{
objectList.remove(object.getObjectId());
objectListGUID.remove(object.getGuid());
if (object instanceof Zone)
zoneList.remove(((Zone)object).getUIN());
removeOrphanedObjects(object);
}
}
}
/**
* Hook method to populate NXCP message with custom object's data on object modification.
* Default implementation does nothing.
*
* @param data object modification data passed to modifyObject
* @param userData user-defined data passed to modifyObject
* @param msg NXCP message to be sent to server
*/
protected void modifyCustomObject(NXCObjectModificationData data, Object userData, NXCPMessage msg)
{
}
/**
* Modify object (generic interface, in most cases wrapper functions should
* be used instead).
*
* @param data Object modification data
* @param userData user-defined data for custom object modification
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void modifyObject(final NXCObjectModificationData data, final Object userData) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_MODIFY_OBJECT);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)data.getObjectId());
// Object name
if (data.getName() != null)
{
msg.setField(NXCPCodes.VID_OBJECT_NAME, data.getName());
}
// Object alias
if (data.getAlias() != null)
{
msg.setField(NXCPCodes.VID_ALIAS, data.getAlias());
}
// Object name on network map
if (data.getNameOnMap() != null)
{
msg.setField(NXCPCodes.VID_NAME_ON_MAP, data.getNameOnMap());
}
// Primary IP
if (data.getPrimaryIpAddress() != null)
{
msg.setField(NXCPCodes.VID_IP_ADDRESS, data.getPrimaryIpAddress());
}
// Access control list
if (data.getACL() != null)
{
if (data.isInheritAccessRights() == null)
throw new IllegalArgumentException("Access control list should be set together with inherited access rights flag");
final Collection acl = data.getACL();
msg.setFieldInt32(NXCPCodes.VID_ACL_SIZE, acl.size());
msg.setFieldInt16(NXCPCodes.VID_INHERIT_RIGHTS, data.isInheritAccessRights() ? 1 : 0);
long id1 = NXCPCodes.VID_ACL_USER_BASE;
long id2 = NXCPCodes.VID_ACL_RIGHTS_BASE;
for(AccessListElement e : acl)
{
msg.setFieldInt32(id1++, (int)e.getUserId());
msg.setFieldInt32(id2++, e.getAccessRights());
}
}
if (data.getCustomAttributes() != null)
{
Map attrList = data.getCustomAttributes();
Iterator it = attrList.keySet().iterator();
long id = NXCPCodes.VID_CUSTOM_ATTRIBUTES_BASE;
int count = 0;
while(it.hasNext())
{
String key = it.next();
CustomAttribute attr = attrList.get(key);
if (attr.getSourceObject() != 0 && !attr.isRedefined())
continue;
msg.setField(id++, key);
msg.setField(id++, attr.getValue());
msg.setFieldInt32(id++, (int)attr.getFlags());
count++;
}
msg.setFieldInt32(NXCPCodes.VID_NUM_CUSTOM_ATTRIBUTES, count);
}
if (data.getAutoBindFilter() != null)
{
msg.setField(NXCPCodes.VID_AUTOBIND_FILTER, data.getAutoBindFilter());
}
if (data.getAutoBindFilter2() != null)
{
msg.setField(NXCPCodes.VID_AUTOBIND_FILTER_2, data.getAutoBindFilter2());
}
if (data.getAutoBindFlags() != null)
{
msg.setFieldInt32(NXCPCodes.VID_AUTOBIND_FLAGS, data.getAutoBindFlags());
}
if (data.getFilter() != null)
{
msg.setField(NXCPCodes.VID_FILTER, data.getFilter());
}
if (data.getDescription() != null)
{
msg.setField(NXCPCodes.VID_DESCRIPTION, data.getDescription());
}
if (data.getVersion() != null)
{
msg.setFieldInt32(NXCPCodes.VID_VERSION, data.getVersion());
}
if (data.getAgentPort() != null)
{
msg.setFieldInt16(NXCPCodes.VID_AGENT_PORT, data.getAgentPort());
}
if (data.getAgentProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_AGENT_PROXY, data.getAgentProxy().intValue());
}
if (data.getAgentSecret() != null)
{
msg.setField(NXCPCodes.VID_SHARED_SECRET, data.getAgentSecret());
}
if (data.getTrustedObjects() != null)
{
msg.setField(NXCPCodes.VID_TRUSTED_OBJECTS, data.getTrustedObjects());
}
if (data.getSnmpVersion() != null)
{
msg.setFieldInt16(NXCPCodes.VID_SNMP_VERSION, data.getSnmpVersion().getValue());
}
if (data.getSnmpAuthName() != null || data.getSnmpAuthPassword() != null ||
data.getSnmpPrivPassword() != null || data.getSnmpAuthMethod() != null ||
data.getSnmpPrivMethod() != null)
{
if (data.getSnmpAuthName() == null || data.getSnmpAuthPassword() == null ||
data.getSnmpPrivPassword() == null || data.getSnmpAuthMethod() == null ||
data.getSnmpPrivMethod() == null)
throw new IllegalArgumentException("All SNMP fields should be set: auth name, auth password, priv password, auth method, priv method");
msg.setField(NXCPCodes.VID_SNMP_AUTH_OBJECT, data.getSnmpAuthName());
msg.setField(NXCPCodes.VID_SNMP_AUTH_PASSWORD, data.getSnmpAuthPassword());
msg.setField(NXCPCodes.VID_SNMP_PRIV_PASSWORD, data.getSnmpPrivPassword());
int methods = data.getSnmpAuthMethod() | (data.getSnmpPrivMethod() << 8);
msg.setFieldInt16(NXCPCodes.VID_SNMP_USM_METHODS, methods);
}
if (data.getSnmpProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_SNMP_PROXY, data.getSnmpProxy().intValue());
}
if (data.getSnmpPort() != null)
{
msg.setFieldInt16(NXCPCodes.VID_SNMP_PORT, data.getSnmpPort());
}
if (data.getMqttProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_MQTT_PROXY, data.getMqttProxy().intValue());
}
if (data.getIcmpProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_ICMP_PROXY, data.getIcmpProxy().intValue());
}
if (data.getGeolocation() != null)
{
final GeoLocation gl = data.getGeolocation();
msg.setFieldInt16(NXCPCodes.VID_GEOLOCATION_TYPE, gl.getType());
msg.setField(NXCPCodes.VID_LATITUDE, gl.getLatitude());
msg.setField(NXCPCodes.VID_LONGITUDE, gl.getLongitude());
msg.setFieldInt16(NXCPCodes.VID_ACCURACY, gl.getAccuracy());
if (gl.getTimestamp() != null)
{
msg.setFieldInt64(NXCPCodes.VID_GEOLOCATION_TIMESTAMP, gl.getTimestamp().getTime() / 1000);
}
}
if (data.getMapLayout() != null)
{
msg.setFieldInt16(NXCPCodes.VID_LAYOUT, data.getMapLayout().getValue());
}
if (data.getMapBackground() != null || data.getMapBackgroundLocation() != null ||
data.getMapBackgroundZoom() != null || data.getMapBackgroundColor() != null)
{
if (data.getMapBackground() == null || data.getMapBackgroundLocation() == null ||
data.getMapBackgroundZoom() == null || data.getMapBackgroundColor() == null)
throw new IllegalArgumentException("All map background attributes should be set (image ID, geolocation, zoom, and color)");
msg.setField(NXCPCodes.VID_BACKGROUND, data.getMapBackground());
msg.setField(NXCPCodes.VID_BACKGROUND_LATITUDE, data.getMapBackgroundLocation().getLatitude());
msg.setField(NXCPCodes.VID_BACKGROUND_LONGITUDE, data.getMapBackgroundLocation().getLongitude());
msg.setFieldInt16(NXCPCodes.VID_BACKGROUND_ZOOM, data.getMapBackgroundZoom());
msg.setFieldInt32(NXCPCodes.VID_BACKGROUND_COLOR, data.getMapBackgroundColor());
}
if (data.getMapImage() != null)
{
msg.setField(NXCPCodes.VID_IMAGE, data.getMapImage());
}
if (data.getMapElements() != null || data.getMapLinks() != null)
{
if (data.getMapElements() == null || data.getMapLinks() == null)
throw new IllegalArgumentException("Both map elements and map links should be set");
msg.setFieldInt32(NXCPCodes.VID_NUM_ELEMENTS, data.getMapElements().size());
long fieldId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(NetworkMapElement e : data.getMapElements())
{
e.fillMessage(msg, fieldId);
fieldId += 100;
}
msg.setFieldInt32(NXCPCodes.VID_NUM_LINKS, data.getMapLinks().size());
fieldId = NXCPCodes.VID_LINK_LIST_BASE;
for(NetworkMapLink l : data.getMapLinks())
{
l.fillMessage(msg, fieldId);
fieldId += 20;
}
}
if (data.getColumnCount() != null)
{
msg.setFieldInt16(NXCPCodes.VID_NUM_COLUMNS, data.getColumnCount());
}
if (data.getDashboardElements() != null)
{
msg.setFieldInt32(NXCPCodes.VID_NUM_ELEMENTS, data.getDashboardElements().size());
long fieldId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(DashboardElement e : data.getDashboardElements())
{
e.fillMessage(msg, fieldId);
fieldId += 10;
}
}
if (data.getUrls() != null)
{
msg.setFieldInt32(NXCPCodes.VID_NUM_URLS, data.getUrls().size());
long fieldId = NXCPCodes.VID_URL_LIST_BASE;
for(ObjectUrl u : data.getUrls())
{
u.fillMessage(msg, fieldId);
fieldId += 10;
}
}
if (data.getScript() != null)
{
msg.setField(NXCPCodes.VID_SCRIPT, data.getScript());
}
if (data.getActivationEvent() != null)
{
msg.setFieldInt32(NXCPCodes.VID_ACTIVATION_EVENT, data.getActivationEvent());
}
if (data.getDeactivationEvent() != null)
{
msg.setFieldInt32(NXCPCodes.VID_DEACTIVATION_EVENT, data.getDeactivationEvent());
}
if (data.getSourceObject() != null)
{
msg.setFieldInt32(NXCPCodes.VID_SOURCE_OBJECT, data.getSourceObject().intValue());
}
if (data.getActiveStatus() != null)
{
msg.setFieldInt16(NXCPCodes.VID_ACTIVE_STATUS, data.getActiveStatus());
}
if (data.getInactiveStatus() != null)
{
msg.setFieldInt16(NXCPCodes.VID_INACTIVE_STATUS, data.getInactiveStatus());
}
if (data.getDciList() != null)
{
List dciList = data.getDciList();
msg.setFieldInt32(NXCPCodes.VID_NUM_ITEMS, dciList.size());
long varId = NXCPCodes.VID_DCI_LIST_BASE;
for(ConditionDciInfo dci : dciList)
{
msg.setFieldInt32(varId++, (int)dci.getDciId());
msg.setFieldInt32(varId++, (int)dci.getNodeId());
msg.setFieldInt16(varId++, dci.getFunction());
msg.setFieldInt16(varId++, dci.getPolls());
varId += 6;
}
}
if (data.getDrillDownObjectId() != null)
{
msg.setFieldInt32(NXCPCodes.VID_DRILL_DOWN_OBJECT_ID, data.getDrillDownObjectId().intValue());
}
if (data.getServiceType() != null)
{
msg.setFieldInt16(NXCPCodes.VID_SERVICE_TYPE, data.getServiceType());
}
if (data.getIpAddress() != null)
{
msg.setField(NXCPCodes.VID_IP_ADDRESS, data.getIpAddress());
}
if (data.getIpProtocol() != null)
{
msg.setFieldInt16(NXCPCodes.VID_IP_PROTO, data.getIpProtocol());
}
if (data.getIpPort() != null)
{
msg.setFieldInt16(NXCPCodes.VID_IP_PORT, data.getIpPort());
}
if (data.getPollerNode() != null)
{
msg.setFieldInt32(NXCPCodes.VID_POLLER_NODE_ID, data.getPollerNode().intValue());
}
if (data.getRequiredPolls() != null)
{
msg.setFieldInt16(NXCPCodes.VID_REQUIRED_POLLS, data.getRequiredPolls());
}
if (data.getRequest() != null)
{
msg.setField(NXCPCodes.VID_SERVICE_REQUEST, data.getRequest());
}
if (data.getResponse() != null)
{
msg.setField(NXCPCodes.VID_SERVICE_RESPONSE, data.getResponse());
}
if (data.getObjectFlags() != null || data.getObjectFlagsMask() != null)
{
msg.setFieldInt32(NXCPCodes.VID_FLAGS, data.getObjectFlags());
if (data.getObjectFlagsMask() != null)
msg.setFieldInt32(NXCPCodes.VID_FLAGS_MASK, data.getObjectFlagsMask());
}
if (data.getIfXTablePolicy() != null)
{
msg.setFieldInt16(NXCPCodes.VID_USE_IFXTABLE, data.getIfXTablePolicy());
}
if (data.getReportDefinition() != null)
{
msg.setField(NXCPCodes.VID_REPORT_DEFINITION, data.getReportDefinition());
}
if (data.getResourceList() != null)
{
msg.setFieldInt32(NXCPCodes.VID_NUM_RESOURCES, data.getResourceList().size());
long varId = NXCPCodes.VID_RESOURCE_LIST_BASE;
for(ClusterResource r : data.getResourceList())
{
msg.setFieldInt32(varId++, (int)r.getId());
msg.setField(varId++, r.getName());
msg.setField(varId++, r.getVirtualAddress());
varId += 7;
}
}
if (data.getNetworkList() != null)
{
int count = data.getNetworkList().size();
msg.setFieldInt32(NXCPCodes.VID_NUM_SYNC_SUBNETS, count);
long varId = NXCPCodes.VID_SYNC_SUBNETS_BASE;
for(InetAddressEx n : data.getNetworkList())
{
msg.setField(varId++, n);
}
}
if (data.getPrimaryName() != null)
{
msg.setField(NXCPCodes.VID_PRIMARY_NAME, data.getPrimaryName());
}
if (data.getStatusCalculationMethod() != null || data.getStatusPropagationMethod() != null ||
data.getFixedPropagatedStatus() != null || data.getStatusShift() != null ||
data.getStatusTransformation() != null || data.getStatusSingleThreshold() != null ||
data.getStatusThresholds() != null)
{
msg.setFieldInt16(NXCPCodes.VID_STATUS_CALCULATION_ALG, data.getStatusCalculationMethod());
msg.setFieldInt16(NXCPCodes.VID_STATUS_PROPAGATION_ALG, data.getStatusPropagationMethod());
msg.setFieldInt16(NXCPCodes.VID_FIXED_STATUS, data.getFixedPropagatedStatus().getValue());
msg.setFieldInt16(NXCPCodes.VID_STATUS_SHIFT, data.getStatusShift());
ObjectStatus[] transformation = data.getStatusTransformation();
msg.setFieldInt16(NXCPCodes.VID_STATUS_TRANSLATION_1, transformation[0].getValue());
msg.setFieldInt16(NXCPCodes.VID_STATUS_TRANSLATION_2, transformation[1].getValue());
msg.setFieldInt16(NXCPCodes.VID_STATUS_TRANSLATION_3, transformation[2].getValue());
msg.setFieldInt16(NXCPCodes.VID_STATUS_TRANSLATION_4, transformation[3].getValue());
msg.setFieldInt16(NXCPCodes.VID_STATUS_SINGLE_THRESHOLD, data.getStatusSingleThreshold());
int[] thresholds = data.getStatusThresholds();
msg.setFieldInt16(NXCPCodes.VID_STATUS_THRESHOLD_1, thresholds[0]);
msg.setFieldInt16(NXCPCodes.VID_STATUS_THRESHOLD_2, thresholds[1]);
msg.setFieldInt16(NXCPCodes.VID_STATUS_THRESHOLD_3, thresholds[2]);
msg.setFieldInt16(NXCPCodes.VID_STATUS_THRESHOLD_4, thresholds[3]);
}
if (data.getExpectedState() != null)
{
msg.setFieldInt16(NXCPCodes.VID_EXPECTED_STATE, data.getExpectedState());
}
if (data.getLinkColor() != null)
{
msg.setFieldInt32(NXCPCodes.VID_LINK_COLOR, data.getLinkColor());
}
if (data.getConnectionRouting() != null)
{
msg.setFieldInt16(NXCPCodes.VID_LINK_ROUTING, data.getConnectionRouting());
}
if (data.getDiscoveryRadius() != null)
{
msg.setFieldInt32(NXCPCodes.VID_DISCOVERY_RADIUS, data.getDiscoveryRadius());
}
if (data.getHeight() != null)
{
msg.setFieldInt16(NXCPCodes.VID_HEIGHT, data.getHeight());
}
if (data.isRackNumberingTopBottom() != null)
{
msg.setField(NXCPCodes.VID_TOP_BOTTOM, data.isRackNumberingTopBottom());
}
if (data.getPeerGatewayId() != null)
{
msg.setFieldInt32(NXCPCodes.VID_PEER_GATEWAY, data.getPeerGatewayId().intValue());
}
if (data.getLocalNetworks() != null || data.getRemoteNetworks() != null)
{
if (data.getLocalNetworks() == null || data.getRemoteNetworks() == null)
throw new IllegalArgumentException("Both local and remote networks should be set together");
long fieldId = NXCPCodes.VID_VPN_NETWORK_BASE;
msg.setFieldInt32(NXCPCodes.VID_NUM_LOCAL_NETS, data.getLocalNetworks().size());
for(InetAddressEx a : data.getLocalNetworks())
{
msg.setField(fieldId++, a);
}
msg.setFieldInt32(NXCPCodes.VID_NUM_REMOTE_NETS, data.getRemoteNetworks().size());
for(InetAddressEx a : data.getRemoteNetworks())
{
msg.setField(fieldId++, a);
}
}
if (data.getPostalAddress() != null)
{
data.getPostalAddress().fillMessage(msg);
}
if (data.getAgentCacheMode() != null)
{
msg.setFieldInt16(NXCPCodes.VID_AGENT_CACHE_MODE, data.getAgentCacheMode().getValue());
}
if (data.getAgentCompressionMode() != null)
{
msg.setFieldInt16(NXCPCodes.VID_AGENT_COMPRESSION_MODE, data.getAgentCompressionMode().getValue());
}
if (data.getMapObjectDisplayMode() != null)
{
msg.setFieldInt16(NXCPCodes.VID_DISPLAY_MODE, data.getMapObjectDisplayMode().getValue());
}
if (data.getFrontRackImage() != null || data.getRearRackImage() != null || data.getRackPosition() != null || data.getRackHeight() != null || data.getRackOrientation() != null)
{
if (data.getFrontRackImage() == null || data.getRearRackImage() == null || data.getRackPosition() == null || data.getRackHeight() == null || data.getRackOrientation() == null)
throw new IllegalArgumentException("All rack placement attributes should be set (front image, rear image, position, height, and orientation)");
msg.setFieldInt32(NXCPCodes.VID_PHYSICAL_CONTAINER_ID, data.getPhysicalContainerObjectId()!= null ? data.getPhysicalContainerObjectId().intValue() : 0);
msg.setField(NXCPCodes.VID_RACK_IMAGE_FRONT, data.getFrontRackImage());
msg.setField(NXCPCodes.VID_RACK_IMAGE_REAR, data.getRearRackImage());
msg.setFieldInt16(NXCPCodes.VID_RACK_POSITION, data.getRackPosition());
msg.setFieldInt16(NXCPCodes.VID_RACK_HEIGHT, data.getRackHeight());
msg.setFieldInt16(NXCPCodes.VID_RACK_ORIENTATION, data.getRackOrientation().getValue());
}
if (data.getPhysicalContainerObjectId() != null || data.getChassisPlacement() != null)
{
if (data.getPhysicalContainerObjectId() == null || data.getChassisPlacement() == null)
throw new IllegalArgumentException("Both physical container object and chassis placement should be set");
msg.setFieldInt32(NXCPCodes.VID_PHYSICAL_CONTAINER_ID, data.getPhysicalContainerObjectId().intValue());
msg.setField(NXCPCodes.VID_CHASSIS_PLACEMENT_CONFIG, data.getChassisPlacement());
}
if (data.getDashboards() != null)
{
msg.setField(NXCPCodes.VID_DASHBOARDS, data.getDashboards());
}
if (data.getControllerId() != null)
{
msg.setFieldInt32(NXCPCodes.VID_CONTROLLER_ID, data.getControllerId().intValue());
}
if (data.getSshProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_SSH_PROXY, data.getSshProxy().intValue());
}
if (data.getSshKeyId() != null)
{
msg.setFieldInt32(NXCPCodes.VID_SSH_KEY_ID, data.getSshKeyId());
}
if (data.getSshLogin() != null)
{
msg.setField(NXCPCodes.VID_SSH_LOGIN, data.getSshLogin());
}
if (data.getSshPassword() != null)
{
msg.setField(NXCPCodes.VID_SSH_PASSWORD, data.getSshPassword());
}
if (data.getSshPort() != null)
{
msg.setFieldInt16(NXCPCodes.VID_SSH_PORT, data.getSshPort());
}
if (data.getZoneProxies() != null)
{
msg.setField(NXCPCodes.VID_ZONE_PROXY_LIST, data.getZoneProxies());
}
if (data.getSeedObjectIds() != null)
{
msg.setField(NXCPCodes.VID_SEED_OBJECTS, data.getSeedObjectIds());
}
if (data.getMacAddress() != null)
{
msg.setField(NXCPCodes.VID_MAC_ADDR, data.getMacAddress());
}
if (data.getDeviceClass() != null)
{
msg.setFieldInt32(NXCPCodes.VID_DEVICE_CLASS, data.getDeviceClass());
}
if (data.getVendor() != null)
{
msg.setField(NXCPCodes.VID_VENDOR, data.getVendor());
}
if (data.getSerialNumber() != null)
{
msg.setField(NXCPCodes.VID_SERIAL_NUMBER, data.getSerialNumber());
}
if (data.getDeviceAddress() != null)
{
msg.setField(NXCPCodes.VID_DEVICE_ADDRESS, data.getDeviceAddress());
}
if (data.getMetaType() != null)
{
msg.setField(NXCPCodes.VID_META_TYPE, data.getMetaType());
}
if (data.getSensorProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_SENSOR_PROXY, data.getSensorProxy().intValue());
}
if (data.getXmlConfig() != null)
{
msg.setField(NXCPCodes.VID_XML_CONFIG, data.getXmlConfig());
}
if (data.getPassiveElements() != null)
{
List elements = data.getPassiveElements();
msg.setFieldInt32(NXCPCodes.VID_NUM_ELEMENTS, elements.size());
long base = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < elements.size(); i++)
{
elements.get(i).fillMessage(msg, base);
base += 10;
}
}
if (data.getResponsibleUsers() != null)
{
msg.setFieldInt32(NXCPCodes.VID_RESPONSIBLE_USERS_COUNT, data.getResponsibleUsers().size());
long fieldId = NXCPCodes.VID_RESPONSIBLE_USERS_BASE;
for(ResponsibleUser r : data.getResponsibleUsers())
{
r.fillMessage(msg, fieldId);
fieldId += 10;
}
}
if (data.getIcmpStatCollectionMode() != null)
{
msg.setFieldInt16(NXCPCodes.VID_ICMP_COLLECTION_MODE, data.getIcmpStatCollectionMode().getValue());
}
if (data.getIcmpTargets() != null)
{
msg.setFieldInt32(NXCPCodes.VID_ICMP_TARGET_COUNT, data.getIcmpTargets().size());
long fieldId = NXCPCodes.VID_ICMP_TARGET_LIST_BASE;
for(InetAddress a : data.getIcmpTargets())
msg.setField(fieldId++, a);
}
if (data.getEtherNetIPPort() != null)
{
msg.setFieldInt16(NXCPCodes.VID_ETHERNET_IP_PORT, data.getEtherNetIPPort());
}
if (data.getEtherNetIPProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_ETHERNET_IP_PROXY, data.getEtherNetIPProxy().intValue());
}
if (data.getModbusTcpPort() != null)
{
msg.setFieldInt16(NXCPCodes.VID_MODBUS_TCP_PORT, data.getModbusTcpPort());
}
if (data.getModbusUnitId() != null)
{
msg.setFieldInt16(NXCPCodes.VID_MODBUS_UNIT_ID, data.getModbusUnitId());
}
if (data.getModbusProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_MODBUS_PROXY, data.getModbusProxy().intValue());
}
if (data.getCertificateMappingData() != null || data.getCertificateMappingMethod() != null)
{
if (data.getCertificateMappingData() == null || data.getCertificateMappingMethod() == null)
throw new IllegalArgumentException("Both certificate mapping method and certificate mapping data should be set");
msg.setFieldInt16(NXCPCodes.VID_CERT_MAPPING_METHOD, data.getCertificateMappingMethod().getValue());
msg.setField(NXCPCodes.VID_CERT_MAPPING_DATA, data.getCertificateMappingData());
}
if (data.getCategoryId() != null)
{
msg.setFieldInt32(NXCPCodes.VID_CATEGORY_ID, data.getCategoryId());
}
if (data.getGeoLocationControlMode() != null)
{
msg.setFieldInt16(NXCPCodes.VID_GEOLOCATION_CTRL_MODE, data.getGeoLocationControlMode().getValue());
}
if (data.getGeoAreas() != null)
{
msg.setField(NXCPCodes.VID_GEO_AREAS, data.getGeoAreas());
}
if (data.getInstanceDiscoveryMethod() != null)
{
msg.setFieldInt32(NXCPCodes.VID_INSTD_METHOD, data.getInstanceDiscoveryMethod());
}
if (data.getInstanceDiscoveryData() != null)
{
msg.setField(NXCPCodes.VID_INSTD_DATA, data.getInstanceDiscoveryData());
}
if (data.getInstanceDiscoveryFilter() != null)
{
msg.setField(NXCPCodes.VID_INSTD_FILTER, data.getInstanceDiscoveryFilter());
}
if (data.getObjectStatusThreshold() != null)
{
msg.setFieldInt32(NXCPCodes.VID_OBJECT_STATUS_THRESHOLD, data.getObjectStatusThreshold());
}
if (data.getDciStatusThreshold() != null)
{
msg.setFieldInt32(NXCPCodes.VID_DCI_STATUS_THRESHOLD, data.getDciStatusThreshold());
}
if (data.getSourceNode() != null)
{
msg.setFieldInt32(NXCPCodes.VID_NODE_ID, data.getSourceNode().intValue());
}
if (data.getWebServiceProxy() != null)
{
msg.setFieldInt32(NXCPCodes.VID_WEB_SERVICE_PROXY, data.getWebServiceProxy().intValue());
}
if (data.getSyslogCodepage() != null)
{
msg.setField(NXCPCodes.VID_SYSLOG_CODEPAGE, data.getSyslogCodepage());
}
if (data.getSNMPCodepage() != null)
{
msg.setField(NXCPCodes.VID_SNMP_CODEPAGE, data.getSNMPCodepage());
}
if (data.getDisplayPriority() != null)
{
msg.setFieldInt32(NXCPCodes.VID_DISPLAY_PRIORITY, data.getDisplayPriority());
}
modifyCustomObject(data, userData, msg);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Modify object (generic interface, in most cases wrapper functions should
* be used instead). Equivalent of calling modifyObject(data, null).
*
* @param data Object modification data
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void modifyObject(final NXCObjectModificationData data) throws IOException, NXCException
{
modifyObject(data, null);
}
/**
* Change object's name (wrapper for modifyObject())
*
* @param objectId ID of object to be changed
* @param name New object's name
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setObjectName(final long objectId, final String name) throws IOException, NXCException
{
NXCObjectModificationData data = new NXCObjectModificationData(objectId);
data.setName(name);
modifyObject(data);
}
/**
* Change object's custom attributes (wrapper for modifyObject())
*
* @param objectId The object ID
* @param attrList The attribute list
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setObjectCustomAttributes(final long objectId, final Map attrList) throws IOException, NXCException
{
NXCObjectModificationData data = new NXCObjectModificationData(objectId);
data.setCustomAttributes(attrList);
modifyObject(data);
}
/**
* Change object's ACL (wrapper for modifyObject())
*
* @param objectId The object id
* @param acl The AccessListElements
* @param inheritAccessRights true if access rights should be inherited
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setObjectACL(long objectId, Collection acl, boolean inheritAccessRights) throws IOException, NXCException
{
NXCObjectModificationData data = new NXCObjectModificationData(objectId);
data.setACL(acl);
data.setInheritAccessRights(inheritAccessRights);
modifyObject(data);
}
/**
* Move object to different zone. Only nodes and clusters can be moved
* between zones.
*
* @param objectId Node or cluster object ID
* @param zoneUIN The zone UIN (unique identification number)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void changeObjectZone(long objectId, int zoneUIN) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_CHANGE_ZONE);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setFieldInt32(NXCPCodes.VID_ZONE_UIN, zoneUIN);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Change object's comments.
*
* @param objectId Object's ID
* @param comments New comments
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void updateObjectComments(long objectId, String comments) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_OBJECT_COMMENTS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setField(NXCPCodes.VID_COMMENTS, comments);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Update list of responsible users for given object.
*
* @param objectId Object's ID
* @param users New list of responsible users
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void updateResponsibleUsers(long objectId, List users) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_RESPONSIBLE_USERS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setFieldInt32(NXCPCodes.VID_RESPONSIBLE_USERS_COUNT, users.size());
long fieldId = NXCPCodes.VID_RESPONSIBLE_USERS_BASE;
for(ResponsibleUser r : users)
{
r.fillMessage(msg, fieldId);
fieldId += 10;
}
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Set object's managed status.
*
* @param objectId object's identifier
* @param isManaged object's managed status
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void setObjectManaged(final long objectId, final boolean isManaged) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_OBJECT_MGMT_STATUS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setFieldInt16(NXCPCodes.VID_MGMT_STATUS, isManaged ? 1 : 0);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get effective rights of currently logged in user to given object.
*
* @param objectId The object ID
* @return The effective rights
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public int getEffectiveRights(final long objectId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_EFFECTIVE_RIGHTS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
sendMessage(msg);
return waitForRCC(msg.getMessageId()).getFieldAsInt32(NXCPCodes.VID_EFFECTIVE_RIGHTS);
}
/**
* Common internal implementation for bindObject, unbindObject, and
* removeTemplate
*
* @param parentId parent object's identifier
* @param childId Child object's identifier
* @param bind true if operation is "bind"
* @param removeDci true if DCIs created from template should be removed during
* unbind
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private void changeObjectBinding(long parentId, long childId, boolean bind, boolean removeDci) throws IOException, NXCException
{
NXCPMessage msg = newMessage(bind ? NXCPCodes.CMD_BIND_OBJECT : NXCPCodes.CMD_UNBIND_OBJECT);
msg.setFieldInt32(NXCPCodes.VID_PARENT_ID, (int)parentId);
msg.setFieldInt32(NXCPCodes.VID_CHILD_ID, (int)childId);
msg.setFieldInt16(NXCPCodes.VID_REMOVE_DCI, removeDci ? 1 : 0);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Bind object.
*
* @param parentId parent object's identifier
* @param childId Child object's identifier
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void bindObject(final long parentId, final long childId) throws IOException, NXCException
{
changeObjectBinding(parentId, childId, true, false);
}
/**
* Unbind object.
*
* @param parentId parent object's identifier
* @param childId Child object's identifier
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void unbindObject(final long parentId, final long childId) throws IOException, NXCException
{
changeObjectBinding(parentId, childId, false, false);
}
/**
* Remove data collection template from node.
*
* @param templateId template object identifier
* @param nodeId node object identifier
* @param removeDci true if DCIs created from this template should be removed
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void removeTemplate(final long templateId, final long nodeId, final boolean removeDci) throws IOException, NXCException
{
changeObjectBinding(templateId, nodeId, false, removeDci);
}
/**
* Apply data collection template to node.
*
* @param templateId template object ID
* @param nodeId node object ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void applyTemplate(long templateId, long nodeId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_APPLY_TEMPLATE);
msg.setFieldInt32(NXCPCodes.VID_SOURCE_OBJECT_ID, (int)templateId);
msg.setFieldInt32(NXCPCodes.VID_DESTINATION_OBJECT_ID, (int)nodeId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Add node to cluster.
*
* @param clusterId cluster object ID
* @param nodeId node object ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void addClusterNode(final long clusterId, final long nodeId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_ADD_CLUSTER_NODE);
msg.setFieldInt32(NXCPCodes.VID_PARENT_ID, (int)clusterId);
msg.setFieldInt32(NXCPCodes.VID_CHILD_ID, (int)nodeId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Remove node from cluster.
*
* @param clusterId cluster object ID
* @param nodeId node object ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void removeClusterNode(final long clusterId, final long nodeId) throws IOException, NXCException
{
changeObjectBinding(clusterId, nodeId, false, true);
}
/**
* Generic implementation for ad-hoc topology map requests.
*
* @param nodeId The node ID
* @param command command to send to server
* @param pageIdSuffix map page ID suffix
* @return network map page representing requested topology
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private NetworkMapPage queryAdHocTopologyMap(long nodeId, int command, String pageIdSuffix) throws IOException, NXCException
{
NXCPMessage msg = newMessage(command);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_OBJECTS);
long[] idList = response.getFieldAsUInt32Array(NXCPCodes.VID_OBJECT_LIST);
if (idList.length != count)
throw new NXCException(RCC.INTERNAL_ERROR);
NetworkMapPage page = new NetworkMapPage(msg.getMessageId() + pageIdSuffix);
for(int i = 0; i < count; i++)
page.addElement(new NetworkMapObject(page.createElementId(), idList[i]));
count = response.getFieldAsInt32(NXCPCodes.VID_NUM_LINKS);
long varId = NXCPCodes.VID_OBJECT_LINKS_BASE;
for(int i = 0; i < count; i++, varId += 3)
{
NetworkMapObject obj1 = page.findObjectElement(response.getFieldAsInt64(varId++));
NetworkMapObject obj2 = page.findObjectElement(response.getFieldAsInt64(varId++));
int type = response.getFieldAsInt32(varId++);
String port1 = response.getFieldAsString(varId++);
String port2 = response.getFieldAsString(varId++);
String name = response.getFieldAsString(varId++);
int flags = response.getFieldAsInt32(varId++);
if ((obj1 != null) && (obj2 != null))
{
page.addLink(new NetworkMapLink(page.createLinkId(), name, type, obj1.getId(), obj2.getId(), port1, port2, flags));
}
}
return page;
}
/**
* Query layer 2 topology for node
*
* @param nodeId The node ID
* @return network map page representing layer 2 topology
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public NetworkMapPage queryLayer2Topology(final long nodeId) throws IOException, NXCException
{
return queryAdHocTopologyMap(nodeId, NXCPCodes.CMD_QUERY_L2_TOPOLOGY, ".L2Topology");
}
/**
* Query OSPF topology for node
*
* @param nodeId The node ID
* @return network map page representing OSPF topology
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public NetworkMapPage queryOSPFTopology(final long nodeId) throws IOException, NXCException
{
return queryAdHocTopologyMap(nodeId, NXCPCodes.CMD_QUERY_OSPF_TOPOLOGY, ".OSPFTopology");
}
/**
* Query internal connection topology for node
*
* @param nodeId The node ID
* @return network map page representing internal communication topology
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public NetworkMapPage queryInternalConnectionTopology(final long nodeId) throws IOException, NXCException
{
return queryAdHocTopologyMap(nodeId, NXCPCodes.CMD_QUERY_INTERNAL_TOPOLOGY, ".InternalConnectionTopology");
}
/**
* Execute action on remote agent
*
* @param nodeId Node object ID
* @param alarmId Alarm ID (used for macro expansion)
* @param action Action with all arguments, that will be expanded and splitted on server side
* @param inputValues Input values provided by user for expansion
* @param maskedFields List if input fields whose content should be masked (can be null)
* @return Expanded action name
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String executeActionWithExpansion(long nodeId, long alarmId, String action,
final Map inputValues, final List maskedFields)
throws IOException, NXCException
{
return executeActionWithExpansion(nodeId, alarmId, action, false, inputValues, maskedFields, null, null);
}
/**
* Execute action on remote agent
*
* @param nodeId Node object ID
* @param alarmId Alarm ID (used for macro expansion)
* @param action Action with all arguments, that will be expanded and splitted on server side
* @param inputValues Input values provided by user for expansion
* @param maskedFields List if input fields whose content should be masked (can be null)
* @param receiveOutput true if action's output has to be read
* @param listener listener for action's output or null
* @param writer writer for action's output or null
* @return Expanded action name
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public String executeActionWithExpansion(long nodeId, long alarmId, String action, boolean receiveOutput,
final Map inputValues, final List maskedFields, final TextOutputListener listener, final Writer writer)
throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_EXECUTE_ACTION);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setField(NXCPCodes.VID_EXPAND_STRING, true);
msg.setField(NXCPCodes.VID_ACTION_NAME, action);
msg.setField(NXCPCodes.VID_RECEIVE_OUTPUT, receiveOutput);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
if (inputValues != null)
{
msg.setFieldInt32(NXCPCodes.VID_INPUT_FIELD_COUNT, inputValues.size());
long varId = NXCPCodes.VID_INPUT_FIELD_BASE;
for(Entry e : inputValues.entrySet())
{
msg.setField(varId++, e.getKey());
msg.setField(varId++, e.getValue());
}
}
else
{
msg.setFieldInt16(NXCPCodes.VID_INPUT_FIELD_COUNT, 0);
}
if ((maskedFields != null) && !maskedFields.isEmpty())
{
msg.setFieldsFromStringCollection(maskedFields, NXCPCodes.VID_MASKED_FIELD_LIST_BASE, NXCPCodes.VID_NUM_MASKED_FIELDS);
}
MessageHandler handler = receiveOutput ? new MessageHandler() {
@Override
public boolean processMessage(NXCPMessage m)
{
String text = m.getFieldAsString(NXCPCodes.VID_MESSAGE);
if (text != null)
{
if (listener != null)
listener.messageReceived(text);
if (writer != null)
{
try
{
writer.write(text);
}
catch(IOException e)
{
}
}
}
if (m.isEndOfSequence())
setComplete();
return true;
}
} : null;
if (receiveOutput)
addMessageSubscription(NXCPCodes.CMD_COMMAND_OUTPUT, msg.getMessageId(), handler);
sendMessage(msg);
NXCPMessage result = waitForRCC(msg.getMessageId());
if (receiveOutput)
{
handler.waitForCompletion();
if (handler.isExpired())
throw new NXCException(RCC.TIMEOUT);
}
return result.getFieldAsString(NXCPCodes.VID_ACTION_NAME);
}
/**
* Execute action on remote agent
*
* @param nodeId Node object ID
* @param action Action name
* @param args Action arguments
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeAction(long nodeId, String action, String[] args) throws IOException, NXCException
{
executeAction(nodeId, action, args, false, null, null);
}
/**
* Execute action on remote agent
*
* @param nodeId Node object ID
* @param action Action name
* @param args Action arguments
* @param receiveOutput true if action's output has to be read
* @param listener listener for action's output or null
* @param writer writer for action's output or null
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeAction(long nodeId, String action, String[] args, boolean receiveOutput, final TextOutputListener listener, final Writer writer) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_EXECUTE_ACTION);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setField(NXCPCodes.VID_ACTION_NAME, action);
msg.setField(NXCPCodes.VID_RECEIVE_OUTPUT, receiveOutput);
if (args != null)
{
msg.setFieldInt16(NXCPCodes.VID_NUM_ARGS, args.length);
long fieldId = NXCPCodes.VID_ACTION_ARG_BASE;
for(String a : args)
msg.setField(fieldId++, a);
}
else
{
msg.setFieldInt16(NXCPCodes.VID_NUM_ARGS, 0);
}
MessageHandler handler = receiveOutput ? new MessageHandler() {
@Override
public boolean processMessage(NXCPMessage m)
{
String text = m.getFieldAsString(NXCPCodes.VID_MESSAGE);
if (text != null)
{
if (listener != null)
listener.messageReceived(text);
if (writer != null)
{
try
{
writer.write(text);
}
catch(IOException e)
{
}
}
}
if (m.isEndOfSequence())
setComplete();
return true;
}
} : null;
if (receiveOutput)
addMessageSubscription(NXCPCodes.CMD_COMMAND_OUTPUT, msg.getMessageId(), handler);
sendMessage(msg);
waitForRCC(msg.getMessageId());
if (receiveOutput)
{
handler.waitForCompletion();
if (handler.isExpired())
throw new NXCException(RCC.TIMEOUT);
}
}
/**
* Execute SSH command on remote agent
*
* @param nodeId Node object ID
* @param alarmId Alarm ID (0 if not executed in alarm context)
* @param command Command to execute
* @param inputFields Input fields provided by user or null
* @param maskedFields List of input field names for which values should be masked (can be null)
* @param receiveOutput true if command's output has to be read
* @param listener listener for command's output or null
* @param writer writer for command's output or null
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeSshCommand(long nodeId, long alarmId, String command, Map inputFields, List maskedFields, boolean receiveOutput, final TextOutputListener listener,
final Writer writer) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_SSH_COMMAND);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
msg.setField(NXCPCodes.VID_COMMAND, command);
msg.setField(NXCPCodes.VID_RECEIVE_OUTPUT, receiveOutput);
if (inputFields != null)
{
msg.setFieldInt16(NXCPCodes.VID_NUM_FIELDS, inputFields.size());
long fieldId = NXCPCodes.VID_FIELD_LIST_BASE;
for(Entry e : inputFields.entrySet())
{
msg.setField(fieldId++, e.getKey());
msg.setField(fieldId++, e.getValue());
}
}
if ((maskedFields != null) && !maskedFields.isEmpty())
{
msg.setFieldsFromStringCollection(maskedFields, NXCPCodes.VID_MASKED_FIELD_LIST_BASE, NXCPCodes.VID_NUM_MASKED_FIELDS);
}
MessageHandler handler = receiveOutput ? new MessageHandler() {
@Override
public boolean processMessage(NXCPMessage m)
{
String text = m.getFieldAsString(NXCPCodes.VID_MESSAGE);
if (text != null)
{
if (listener != null)
listener.messageReceived(text);
if (writer != null)
{
try
{
writer.write(text);
}
catch(IOException e)
{
}
}
}
if (m.isEndOfSequence())
setComplete();
return true;
}
} : null;
if (receiveOutput)
addMessageSubscription(NXCPCodes.CMD_COMMAND_OUTPUT, msg.getMessageId(), handler);
sendMessage(msg);
waitForRCC(msg.getMessageId());
if (receiveOutput)
{
handler.waitForCompletion();
if (handler.isExpired())
throw new NXCException(RCC.TIMEOUT);
}
}
/**
* Wakeup node by sending wake-on-LAN magic packet. Either node ID or
* interface ID may be given. If node ID is given, system will send wakeup
* packets to all active interfaces with IP address.
*
* @param objectId node or interface ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void wakeupNode(final long objectId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_WAKEUP_NODE);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get node's physical components (obtained from ENTITY-MIB).
*
* @param nodeId node object identifier
* @return root component
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public PhysicalComponent getNodePhysicalComponents(long nodeId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_NODE_COMPONENTS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return new PhysicalComponent(response, NXCPCodes.VID_COMPONENT_LIST_BASE, null);
}
/**
* Get list of available Windows performance objects. Returns empty list if node
* does is not a Windows node or does not have WinPerf subagent installed.
*
* @param nodeId node object ID
* @return list of available Windows performance objects
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getNodeWinPerfObjects(long nodeId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_WINPERF_OBJECTS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return WinPerfObject.createListFromMessage(response);
}
/**
* Get list of software packages installed on node.
*
* @param nodeId node object identifier
* @return root component
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getNodeSoftwarePackages(long nodeId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_NODE_SOFTWARE);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
List packages = new ArrayList(count);
long varId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < count; i++)
{
packages.add(new SoftwarePackage(response, varId));
varId += 10;
}
return packages;
}
/**
* Get list of hardware components as reported by agent.
*
* @param nodeId node object identifier
* @return list of hardware components
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getNodeHardwareComponents(long nodeId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_NODE_HARDWARE);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
List components = new ArrayList(count);
long baseId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < count; i++)
{
components.add(new HardwareComponent(response, baseId));
baseId += 64;
}
return components;
}
/**
* Get list of user sessions on given node as reported by agent.
*
* @param nodeId node object identifier
* @return list of user sessions
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getUserSessions(long nodeId) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_USER_SESSIONS);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_SESSIONS);
List sessions = new ArrayList(count);
long baseId = NXCPCodes.VID_SESSION_DATA_BASE;
for(int i = 0; i < count; i++)
{
sessions.add(new UserSession(response, baseId));
baseId += 64;
}
return sessions;
}
/**
* Get list of dependent nodes for given node. Node is considered dependent if it use given node
* as any type of proxy or as data collection source for at least one DCI.
*
* @param nodeId node object ID
* @return list of dependent node descriptors
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getDependentNodes(long nodeId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_DEPENDENT_NODES);
msg.setFieldInt32(NXCPCodes.VID_NODE_ID, (int)nodeId);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
List nodes = new ArrayList(count);
long fieldId = NXCPCodes.VID_ELEMENT_LIST_BASE;
for(int i = 0; i < count; i++, fieldId += 10)
nodes.add(new DependentNode(msg, fieldId));
return nodes;
}
/**
* Get list of server jobs
*
* @return list of server jobs
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public ServerJob[] getServerJobList() throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_JOB_LIST);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_JOB_COUNT);
ServerJob[] jobList = new ServerJob[count];
long baseVarId = NXCPCodes.VID_JOB_LIST_BASE;
for(int i = 0; i < count; i++, baseVarId += 10)
{
jobList[i] = new ServerJob(response, baseVarId);
}
return jobList;
}
/**
* Cancel server job
*
* @param jobId Job ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void cancelServerJob(long jobId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_CANCEL_JOB);
msg.setFieldInt32(NXCPCodes.VID_JOB_ID, (int)jobId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Put server job on hold
*
* @param jobId Job ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void holdServerJob(long jobId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_HOLD_JOB);
msg.setFieldInt32(NXCPCodes.VID_JOB_ID, (int)jobId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Put server on hold job to pending state
*
* @param jobId Job ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void unholdServerJob(long jobId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UNHOLD_JOB);
msg.setFieldInt32(NXCPCodes.VID_JOB_ID, (int)jobId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get state of background task.
*
* @param taskId Task ID
* @return state of background task
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public BackgroundTaskState getBackgroundTaskState(long taskId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_BACKGROUND_TASK_STATE);
msg.setFieldInt64(NXCPCodes.VID_JOB_ID, taskId);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
return BackgroundTaskState.getByValue(response.getFieldAsInt32(NXCPCodes.VID_STATE));
}
/**
* Deploy policy on agent
*
* @param policyId Policy object ID
* @param nodeId Node object ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deployAgentPolicy(final long policyId, final long nodeId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DEPLOY_AGENT_POLICY);
msg.setFieldInt32(NXCPCodes.VID_POLICY_ID, (int)policyId);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Uninstall policy from agent
*
* @param policyId Policy object ID
* @param nodeId Node object ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void uninstallAgentPolicy(final long policyId, final long nodeId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_UNINSTALL_AGENT_POLICY);
msg.setFieldInt32(NXCPCodes.VID_POLICY_ID, (int)policyId);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Internal implementation for open/get event processing policy.
*
* @param readOnly true to get read-only copy of the policy
* @return Event processing policy
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private EventProcessingPolicy getEventProcessingPolicyInternal(boolean readOnly) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_OPEN_EPP);
msg.setFieldInt16(NXCPCodes.VID_READ_ONLY, readOnly ? 1 : 0);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
int numRules = response.getFieldAsInt32(NXCPCodes.VID_NUM_RULES);
final EventProcessingPolicy policy = new EventProcessingPolicy(numRules);
for(int i = 0; i < numRules; i++)
{
response = waitForMessage(NXCPCodes.CMD_EPP_RECORD, msg.getMessageId());
policy.addRule(new EventProcessingPolicyRule(response, i + 1));
}
return policy;
}
/**
* Get read-only copy of event processing policy.
*
* @return Event processing policy
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public EventProcessingPolicy getEventProcessingPolicy() throws IOException, NXCException
{
return getEventProcessingPolicyInternal(true);
}
/**
* Open event processing policy for editing. This call will lock event
* processing policy on server until closeEventProcessingPolicy called or
* session terminated.
*
* @return Event processing policy
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public EventProcessingPolicy openEventProcessingPolicy() throws IOException, NXCException
{
return getEventProcessingPolicyInternal(false);
}
/**
* Save event processing policy. If policy was not previously open by current
* session exception will be thrown.
*
* @param epp Modified event processing policy
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void saveEventProcessingPolicy(EventProcessingPolicy epp) throws IOException, NXCException
{
final List rules = epp.getRules();
NXCPMessage msg = newMessage(NXCPCodes.CMD_SAVE_EPP);
msg.setFieldInt32(NXCPCodes.VID_NUM_RULES, rules.size());
sendMessage(msg);
final long msgId = msg.getMessageId();
waitForRCC(msgId);
int id = 1;
for(EventProcessingPolicyRule rule : rules)
{
msg = new NXCPMessage(NXCPCodes.CMD_EPP_RECORD);
msg.setMessageId(msgId);
msg.setFieldInt32(NXCPCodes.VID_RULE_ID, id++);
rule.fillMessage(msg);
sendMessage(msg);
}
// Wait for final confirmation if there was some rules
if (rules.size() > 0)
waitForRCC(msgId);
}
/**
* Close event processing policy. This call will unlock event processing
* policy on server. If policy was not previously open by current session
* exception will be thrown.
*
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void closeEventProcessingPolicy() throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_CLOSE_EPP);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Open data collection configuration for given node. You must call
* DataCollectionConfiguration.close() to close data collection configuration
* when it is no longer needed.
*
* @param nodeId Node object identifier
* @return Data collection configuration object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DataCollectionConfiguration openDataCollectionConfiguration(long nodeId) throws IOException, NXCException
{
return openDataCollectionConfiguration(nodeId, null);
}
/**
* Open data collection configuration for given node. You must call
* DataCollectionConfiguration.close() to close data collection configuration
* when it is no longer needed.
*
* @param nodeId Node object identifier
* @param changeListener callback that will be called when DCO object is changed by server notification
* @return Data collection configuration object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public DataCollectionConfiguration openDataCollectionConfiguration(long nodeId, RemoteChangeListener changeListener)
throws IOException, NXCException
{
final DataCollectionConfiguration cfg = new DataCollectionConfiguration(this, nodeId);
cfg.open(changeListener);
return cfg;
}
/**
* Modify data collection object without opening data collection configuration.
*
* @param dcObject dcObject collection object
* @return Identifier assigned to newly created object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long modifyDataCollectionObject(DataCollectionObject dcObject) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_MODIFY_NODE_DCI);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)dcObject.getNodeId());
dcObject.fillMessage(msg);
sendMessage(msg);
return waitForRCC(msg.getMessageId()).getFieldAsInt64(NXCPCodes.VID_DCI_ID);
}
/**
* Clear data collection configuration on agent. Will wipe out all configuration and collected data.
*
* @param nodeId node object ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void clearAgentDataCollectionConfiguration(final long nodeId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_CLEAN_AGENT_DCI_CONF);
msg.setFieldInt32(NXCPCodes.VID_NODE_ID, (int)nodeId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Force re-synchronization of data collection configuration with agent.
*
* @param nodeId node object ID
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void resyncAgentDataCollectionConfiguration(final long nodeId) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_RESYNC_AGENT_DCI_CONF);
msg.setFieldInt32(NXCPCodes.VID_NODE_ID, (int)nodeId);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Test DCI transformation script.
*
* @param nodeId ID of the node object to test script on
* @param script script source code
* @param inputValue input value for the script
* @param dcObject optional data collection object data (for $dci variable in script)
* @return test execution results
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public TransformationTestResult testTransformationScript(long nodeId, String script, String inputValue,
DataCollectionObject dcObject) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_TEST_DCI_TRANSFORMATION);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setField(NXCPCodes.VID_SCRIPT, script);
msg.setField(NXCPCodes.VID_VALUE, inputValue);
if (dcObject != null)
{
dcObject.fillMessage(msg);
}
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
TransformationTestResult r = new TransformationTestResult();
r.success = response.getFieldAsBoolean(NXCPCodes.VID_EXECUTION_STATUS);
r.result = response.getFieldAsString(NXCPCodes.VID_EXECUTION_RESULT);
return r;
}
/**
* Message handler for script execution updates
*/
private static class ScriptExecutionUpdateHandler extends MessageHandler
{
private TextOutputListener listener;
private int errorCode = 0;
private String errorMessage = null;
ScriptExecutionUpdateHandler(TextOutputListener listener)
{
this.listener = listener;
}
/**
* @see org.netxms.client.MessageHandler#processMessage(org.netxms.base.NXCPMessage)
*/
@Override
public boolean processMessage(NXCPMessage m)
{
int rcc = m.getFieldAsInt32(NXCPCodes.VID_RCC);
if (rcc != RCC.SUCCESS)
{
errorCode = rcc;
errorMessage = m.getFieldAsString(NXCPCodes.VID_ERROR_TEXT);
if (errorMessage == null)
errorMessage = "Unspecified sript execution error (RCC=" + rcc + ")";
if (listener != null)
{
listener.messageReceived(errorMessage + "\n\n");
listener.onFailure(null);
}
}
else
{
String text = m.getFieldAsString(NXCPCodes.VID_MESSAGE);
if ((text != null) && (listener != null))
{
listener.messageReceived(text);
}
}
if (m.isEndOfSequence())
{
if (listener != null)
listener.onSuccess();
setComplete();
}
return true;
}
/**
* Check if error was reported
*
* @return true if error was reported
*/
public boolean isFailure()
{
return errorMessage != null;
}
/**
* Get error code.
*
* @return error code
*/
public int getErrorCode()
{
return errorCode;
}
/**
* Get execution error message.
*
* @return execution error message
*/
public String getErrorMessage()
{
return errorMessage;
}
}
/**
* Process server script execution.
*
* @param msg prepared request message
* @param listener script output listener or null if caller not interested in script output
* @param resultAsMap if true, expect script execution results to be sent as map
* @return execution result as map if resultAsMap
is set to true, and null
otherwise
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
private Map processScriptExecution(NXCPMessage msg, TextOutputListener listener, boolean resultAsMap) throws IOException, NXCException
{
msg.setField(NXCPCodes.VID_RESULT_AS_MAP, resultAsMap);
ScriptExecutionUpdateHandler handler = new ScriptExecutionUpdateHandler(listener);
handler.setMessageWaitTimeout(commandTimeout);
addMessageSubscription(NXCPCodes.CMD_EXECUTE_SCRIPT_UPDATE, msg.getMessageId(), handler);
sendMessage(msg);
waitForRCC(msg.getMessageId());
handler.waitForCompletion();
if (handler.isExpired())
throw new NXCException(RCC.TIMEOUT);
if (handler.isFailure())
throw new NXCException(handler.getErrorCode(), handler.getErrorMessage());
if (!resultAsMap)
return null;
NXCPMessage response = waitForMessage(NXCPCodes.CMD_SCRIPT_EXECUTION_RESULT, msg.getMessageId());
return response.getStringMapFromFields(NXCPCodes.VID_ELEMENT_LIST_BASE, NXCPCodes.VID_NUM_ELEMENTS);
}
/**
* Execute library script on object. Script name interpreted as command line with server-side macro substitution. Map inputValues
* can be used to pass data for %() macros.
*
* @param nodeId node ID to execute script on
* @param script script name and parameters
* @param inputFields input values map for %() macro substitution (can be null)
* @param maskedFields List of input field names for which values should be masked (can be null)
* @param listener script output listener
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeLibraryScript(long nodeId, String script, Map inputFields, List maskedFields, final TextOutputListener listener)
throws IOException, NXCException
{
executeLibraryScript(nodeId, 0, script, inputFields, maskedFields, listener);
}
/**
* Execute library script on object. Script name interpreted as command line with server-side macro substitution. Map inputValues
* can be used to pass data for %() macros.
*
* @param objectId ID of the object to execute script on
* @param alarmId alarm ID to use for expansion
* @param script script name and parameters
* @param inputFields input values map for %() macro substitution (can be null)
* @param maskedFields List of input field names for which values should be masked (can be null)
* @param listener script output listener
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeLibraryScript(long objectId, long alarmId, String script, Map inputFields, List maskedFields, final TextOutputListener listener) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_EXECUTE_LIBRARY_SCRIPT);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setField(NXCPCodes.VID_SCRIPT, script);
msg.setFieldInt32(NXCPCodes.VID_ALARM_ID, (int)alarmId);
msg.setField(NXCPCodes.VID_RECEIVE_OUTPUT, listener != null);
if (inputFields != null)
{
msg.setFieldInt16(NXCPCodes.VID_NUM_FIELDS, inputFields.size());
long fieldId = NXCPCodes.VID_FIELD_LIST_BASE;
for(Entry e : inputFields.entrySet())
{
msg.setField(fieldId++, e.getKey());
msg.setField(fieldId++, e.getValue());
}
}
if ((maskedFields != null) && !maskedFields.isEmpty())
{
msg.setFieldsFromStringCollection(maskedFields, NXCPCodes.VID_MASKED_FIELD_LIST_BASE, NXCPCodes.VID_NUM_MASKED_FIELDS);
}
processScriptExecution(msg, listener, false);
}
/**
* Execute script.
*
* @param objectId ID of the object to execute script on
* @param script script source code
* @param listener script output listener
* @param parameters script parameter list (can be null)
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeScript(long objectId, String script, String parameters, final TextOutputListener listener) throws IOException, NXCException
{
executeScript(objectId, script, parameters, listener, false);
}
/**
* Execute script.
*
* @param objectId ID of the object to execute script on
* @param script script source code
* @param listener script output listener
* @param parameters script parameter list (can be null)
* @param developmentMode true if script should be run in development mode
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeScript(long objectId, String script, String parameters, final TextOutputListener listener, boolean developmentMode) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_EXECUTE_SCRIPT);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setField(NXCPCodes.VID_SCRIPT, script);
msg.setField(NXCPCodes.VID_DEVELOPMENT_MODE, developmentMode);
if (parameters != null)
{
msg.setField(NXCPCodes.VID_PARAMETER, parameters);
}
processScriptExecution(msg, listener, false);
}
/**
* Execute script.
*
* @param objectId ID of the object to execute script on
* @param script script source code
* @param parameterList script parameter list (can be null)
* @param listener script output listener
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeScript(long objectId, String script, List parameterList, final TextOutputListener listener) throws IOException, NXCException
{
executeScript(objectId, script, parameterList, listener, false);
}
/**
* Execute script.
*
* @param objectId ID of the object to execute script on
* @param script script source code
* @param parameterList script parameter list (can be null)
* @param listener script output listener
* @param developmentMode true if script should be run in development mode
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void executeScript(long objectId, String script, List parameterList, final TextOutputListener listener, boolean developmentMode) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_EXECUTE_SCRIPT);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setField(NXCPCodes.VID_SCRIPT, script);
msg.setField(NXCPCodes.VID_DEVELOPMENT_MODE, developmentMode);
if (parameterList != null)
{
msg.setFieldInt16(NXCPCodes.VID_NUM_FIELDS, parameterList.size());
long fieldId = NXCPCodes.VID_FIELD_LIST_BASE;
for(String param : parameterList)
{
msg.setField(fieldId++, param);
}
}
processScriptExecution(msg, listener, false);
}
/**
* Execute script and get return value as map. Content of returned map depends on actual data type of script return value:
*
* - For hash map matching map will be returned;
*
- For array all elements will be returned as values and keys will be element positions starting as 1;
*
- For all other types map will consist of single element with key "1" and script return value as value.
*
*
* @param nodeId ID of the node object to test script on
* @param script script source code
* @param parameterList script parameter list can be null
* @param listener script output listener
* @return script return value as a map
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map queryScript(long nodeId, String script, List parameterList, final TextOutputListener listener) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_EXECUTE_SCRIPT);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)nodeId);
msg.setField(NXCPCodes.VID_SCRIPT, script);
if (parameterList != null)
{
msg.setFieldInt16(NXCPCodes.VID_NUM_FIELDS, parameterList.size());
long fieldId = NXCPCodes.VID_FIELD_LIST_BASE;
for(String param : parameterList)
{
msg.setField(fieldId++, param);
}
}
return processScriptExecution(msg, listener, true);
}
/**
* Compile NXSL script on server. Field *success* in compilation result object will indicate compilation status. If compilation
* fails, field *errorMessage* will contain compilation error message.
*
* @param source script source
* @param serialize flag to indicate if compiled script should be serialized and sent back to client
* @return script compilation result object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public ScriptCompilationResult compileScript(String source, boolean serialize) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_COMPILE_SCRIPT);
msg.setField(NXCPCodes.VID_SCRIPT, source);
msg.setField(NXCPCodes.VID_SERIALIZE, serialize);
sendMessage(msg);
return new ScriptCompilationResult(waitForRCC(msg.getMessageId()));
}
/**
* Open server log by name.
*
* @param logName Log name
* @return Log object
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Log openServerLog(final String logName) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_OPEN_SERVER_LOG);
msg.setField(NXCPCodes.VID_LOG_NAME, logName);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
Log log = new Log(this, response, logName);
return log;
}
/**
* Get alarm categories from server
*
* @return List of configured alarm categories
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getAlarmCategories() throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_ALARM_CATEGORIES);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
ArrayList list = new ArrayList();
long fieldId = NXCPCodes.VID_ELEMENT_LIST_BASE;
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
for(int i = 0; i < count; i++)
{
list.add(new AlarmCategory(response, fieldId));
fieldId += 10;
}
return list;
}
/**
* Add or update alarm category in DB
*
* @param object alarm category
* @return The ID of the category
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long modifyAlarmCategory(AlarmCategory object) throws IOException, NXCException
{
if (object.getName().isEmpty())
return 0;
NXCPMessage msg = newMessage(NXCPCodes.CMD_MODIFY_ALARM_CATEGORY);
object.fillMessage(msg);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsInt32(NXCPCodes.VID_CATEGORY_ID);
}
/**
* Delete alarm category in DB
*
* @param id of alarm category
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteAlarmCategory(long id) throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_ALARM_CATEGORY);
msg.setFieldInt32(NXCPCodes.VID_CATEGORY_ID, (int)id);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Synchronize alarm category configuration. After call to this method
* session object will maintain internal list of configured alarm categories
*
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncAlarmCategories() throws IOException, NXCException
{
List categories = getAlarmCategories();
synchronized(alarmCategories)
{
alarmCategories.clear();
for(AlarmCategory c : categories)
{
alarmCategories.put(c.getId(), c);
}
alarmCategoriesSynchronized = true;
}
}
/**
* Check if alarm categories are synchronized.
*
* @return true if if alarm categories are synchronized
*/
public boolean isAlarmCategoriesSynchronized()
{
return alarmCategoriesSynchronized;
}
/**
* Find alarm category by id in alarm category database internally
* maintained by session object. You must call
* NXCSession.syncAlarmCategories() first to make local copy of event template
* database.
*
* @param id alarm category id
* @return Event template object or null if not found
*/
public AlarmCategory findAlarmCategoryById(long id)
{
synchronized(alarmCategories)
{
return alarmCategories.get(id);
}
}
/**
* Find alarm category by name in alarm category database internally
* maintained by session object. You must call
* NXCSession.syncAlarmCategories() first to make local copy of event template
* database.
*
* @param name alarm category name
* @return alarm category with given name or null if not found
*/
public AlarmCategory findAlarmCategoryByName(String name)
{
synchronized(alarmCategories)
{
for(Map.Entry c : alarmCategories.entrySet())
{
if (((AlarmCategory)c.getValue()).getName().equals(name))
return (AlarmCategory)c.getValue();
}
return null;
}
}
/**
* Find multiple alarm categories by category id`s in alarm category database
* internally maintained by session object. You must call
* NXCSession.syncAlarmCategories() first to make local copy of alarm category
* database.
*
* @param ids List of alarm category id`s
* @return List of found alarm categories
*/
public List findMultipleAlarmCategories(List ids)
{
List list = new ArrayList();
synchronized(alarmCategories)
{
for(Long id : ids)
{
AlarmCategory e = alarmCategories.get(id);
if (e != null)
list.add(e);
}
}
return list;
}
/**
* Check if event configuratrion objects are synchronized.
*
* @return true if event configuratrion objects are synchronized
*/
public boolean isEventObjectsSynchronized()
{
return eventTemplatesSynchronized;
}
/**
* Synchronize event templates configuration. After call to this method
* session object will maintain internal list of configured event templates.
*
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void syncEventTemplates() throws IOException, NXCException
{
List templates = getEventTemplates();
synchronized(eventTemplates)
{
eventTemplates.clear();
for(EventTemplate t : templates)
{
eventTemplates.put(t.getCode(), t);
}
eventTemplatesSynchronized = true;
}
}
/**
* Re-synchronize event templates in background
*/
private void resyncEventTemplates()
{
new Thread(new Runnable()
{
@Override
public void run()
{
try
{
syncEventTemplates();
}
catch(Exception e)
{
logger.error("Exception in worker thread", e);
}
}
}).start();
}
/**
* Get cached list event templates
*
* @return List of event templates cached by client library
*/
public EventTemplate[] getCachedEventTemplates()
{
EventTemplate[] events = null;
synchronized(eventTemplates)
{
events = eventTemplates.values().toArray(new EventTemplate[eventTemplates.size()]);
}
return events;
}
/**
* Find event template by name in event template database internally
* maintained by session object. You must call
* NXCSession.syncEventObjects() first to make local copy of event template
* database.
*
* @param name Event name
* @return Event template object or null if not found
*/
public EventTemplate findEventTemplateByName(String name)
{
EventTemplate result = null;
synchronized(eventTemplates)
{
for(EventTemplate t : eventTemplates.values())
{
if (t.getName().equalsIgnoreCase(name))
{
result = t;
break;
}
}
}
return result;
}
/**
* Get event name from event code
*
* @param code event code
* @return event name or event code as string if event not found
*/
public String getEventName(long code)
{
synchronized(eventTemplates)
{
EventTemplate e = eventTemplates.get(code);
return (e != null) ? e.getName() : ("[" + Long.toString(code) + "]");
}
}
/**
* Find event template by code in event template database internally
* maintained by session object. You must call
* NXCSession.syncEventObjects() first to make local copy of event template
* database.
*
* @param code Event code
* @return Event template object or null if not found
*/
public EventTemplate findEventTemplateByCode(long code)
{
synchronized(eventTemplates)
{
return eventTemplates.get(code);
}
}
/**
* Find multiple event templates by event codes in event template database internally maintained by session object. You must call
* NXCSession.syncEventObjects()
first to make local copy of event template database.
*
* @param codes set of event codes
* @return List of found event templates
*/
public List findMultipleEventTemplates(Collection codes)
{
List list = new ArrayList();
synchronized(eventTemplates)
{
for(long code : codes)
{
EventTemplate t = eventTemplates.get(code);
if (t != null)
list.add(t);
}
}
return list;
}
/**
* Find multiple event templates by event codes in event template database
* internally maintained by session object. You must call
* NXCSession.syncEventObjects() first to make local copy of event template
* database.
*
* @param codes List of event codes
* @return List of found event templates
*/
public List findMultipleEventTemplates(final long[] codes)
{
List list = new ArrayList();
synchronized(eventTemplates)
{
for(long code : codes)
{
EventTemplate t = eventTemplates.get(code);
if (t != null)
list.add(t);
}
}
return list;
}
/**
* Get event objects from server
*
* @return List of configured event objects
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getEventTemplates() throws IOException, NXCException
{
NXCPMessage msg = newMessage(NXCPCodes.CMD_LOAD_EVENT_DB);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_EVENTS);
long base = NXCPCodes.VID_ELEMENT_LIST_BASE;
List objects = new ArrayList(count);
for(int i = 0; i < count; i++)
{
objects.add(new EventTemplate(response, base));
base += 10;
}
return objects;
}
/**
* Generate code for new event template.
*
* @return Code for new event template
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public long generateEventCode() throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GENERATE_EVENT_CODE);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
return response.getFieldAsInt64(NXCPCodes.VID_EVENT_CODE);
}
/**
* Delete event template.
*
* @param eventCode Event code
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void deleteEventTemplate(long eventCode) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_DELETE_EVENT_TEMPLATE);
msg.setFieldInt32(NXCPCodes.VID_EVENT_CODE, (int)eventCode);
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Modify event template.
*
* @param tmpl Event template
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void modifyEventObject(EventTemplate tmpl) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_SET_EVENT_INFO);
tmpl.fillMessage(msg);
sendMessage(msg);
tmpl.setCode(waitForRCC(msg.getMessageId()).getFieldAsInt32(NXCPCodes.VID_EVENT_CODE));
}
/**
* Send event to server. Event can be identified either by event code or event name. If event name is given, event code will be
* ignored.
*
* Node: sending events by name supported by server version 1.1.8 and higher.
*
* @param eventCode event code. Ignored if event name is not null.
* @param eventName event name. Must be set to null if event identified by code.
* @param objectId Object ID to send event on behalf of. If set to 0, server will determine object ID by client IP address.
* @param parameters event's parameters
* @param userTag event's user tag
* @param originTimestamp origin timestamp or null
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void sendEvent(long eventCode, String eventName, long objectId, String[] parameters, String userTag, Date originTimestamp)
throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_TRAP);
msg.setFieldInt32(NXCPCodes.VID_EVENT_CODE, (int)eventCode);
if (eventName != null)
msg.setField(NXCPCodes.VID_EVENT_NAME, eventName);
msg.setFieldInt32(NXCPCodes.VID_OBJECT_ID, (int)objectId);
msg.setField(NXCPCodes.VID_USER_TAG, (userTag != null) ? userTag : "");
if (originTimestamp != null)
msg.setField(NXCPCodes.VID_ORIGIN_TIMESTAMP, originTimestamp);
msg.setFieldInt16(NXCPCodes.VID_NUM_ARGS, parameters.length);
long varId = NXCPCodes.VID_EVENT_ARG_BASE;
for(int i = 0; i < parameters.length; i++)
{
msg.setField(varId++, parameters[i]);
}
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Convenience wrapper for sendEvent interface.
*
* @param eventCode event code
* @param parameters event's parameters
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void sendEvent(long eventCode, String[] parameters) throws IOException, NXCException
{
sendEvent(eventCode, null, 0, parameters, null, null);
}
/**
* Convenience wrapper for sendEvent interface.
*
* @param eventName event name
* @param parameters event's parameters
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void sendEvent(String eventName, String[] parameters) throws IOException, NXCException
{
sendEvent(0, eventName, 0, parameters, null, null);
}
/**
* Get list of well-known SNMP communities configured on server.
*
* @return map of SNMP community strings
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map> getSnmpCommunities() throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_COMMUNITY_LIST);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_STRINGS);
long stringBase = NXCPCodes.VID_COMMUNITY_STRING_LIST_BASE;
long zoneBase = NXCPCodes.VID_COMMUNITY_STRING_ZONE_LIST_BASE;
Map> map = new HashMap>(count);
List communities = new ArrayList();
int currentZoneUIN = response.getFieldAsInt32(zoneBase);
for(int i = 0; i < count; i++)
{
int zoneUIN = response.getFieldAsInt32(zoneBase++);
if (currentZoneUIN != zoneUIN)
{
map.put(currentZoneUIN, communities);
communities = new ArrayList();
currentZoneUIN = zoneUIN;
}
communities.add(response.getFieldAsString(stringBase++));
}
if (count > 0)
map.put(currentZoneUIN, communities);
return map;
}
/**
* Get list of well-known SNMP communities configured on server.
*
* @param zoneUIN Zone UIN (unique identification number)
* @return list of SNMP community strings
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getSnmpCommunities(int zoneUIN) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_COMMUNITY_LIST);
msg.setFieldInt32(NXCPCodes.VID_ZONE_UIN, zoneUIN);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_STRINGS);
long stringBase = NXCPCodes.VID_COMMUNITY_STRING_LIST_BASE;
List stringList = new ArrayList();
for(int i = 0; i < count; i++)
{
stringList.add(response.getFieldAsString(stringBase++));
}
return stringList;
}
/**
* Update list of well-known SNMP community strings on server. Existing list will be replaced by provided one.
*
* @param zoneUIN Zone UIN (unique identification number)
* @param communityStrings New list of SNMP community strings
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void updateSnmpCommunities(int zoneUIN, List communityStrings) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_COMMUNITY_LIST);
msg.setFieldInt32(NXCPCodes.VID_ZONE_UIN, zoneUIN);
long stringBase = NXCPCodes.VID_COMMUNITY_STRING_LIST_BASE;
for(String s : communityStrings)
{
msg.setField(stringBase++, s);
}
msg.setFieldInt32(NXCPCodes.VID_NUM_STRINGS, communityStrings.size());
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get list of well-known SNMP USM (user security model) credentials configured on server.
*
* @return Map of SNMP USM credentials
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map> getSnmpUsmCredentials() throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_USM_CREDENTIALS);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_RECORDS);
Map> map = new HashMap>(count);
List credentials = new ArrayList();
long fieldId = NXCPCodes.VID_USM_CRED_LIST_BASE;
int zoneId = 0;
for(int i = 0; i < count; i++, fieldId += 10)
{
SnmpUsmCredential cred = new SnmpUsmCredential(response, fieldId);
if ((i != 0) && (zoneId != cred.getZoneId()))
{
map.put(zoneId, credentials);
credentials = new ArrayList();
}
credentials.add(cred);
zoneId = cred.getZoneId();
}
if (count > 0)
map.put(zoneId, credentials);
return map;
}
/**
* Get list of well-known SNMP USM (user security model) credentials configured on server.
*
* @param zoneUIN Zone UIN (unique identification number)
* @return List of configured SNMP USM credentials
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public List getSnmpUsmCredentials(int zoneUIN) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_USM_CREDENTIALS);
msg.setFieldInt32(NXCPCodes.VID_ZONE_UIN, zoneUIN);
sendMessage(msg);
final NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_RECORDS);
List list = new ArrayList(count);
long varId = NXCPCodes.VID_USM_CRED_LIST_BASE;
for(int i = 0; i < count; i++, varId += 10)
{
list.add(new SnmpUsmCredential(response, varId));
}
return list;
}
/**
* Update list of well-known SNMP USM credentials on server. Existing list will be replaced by provided one.
*
* @param zoneUIN Zone UIN (unique identification number)
* @param usmCredentials List of SNMP credentials
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public void updateSnmpUsmCredentials(int zoneUIN, List usmCredentials) throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_UPDATE_USM_CREDENTIALS);
msg.setFieldInt32(NXCPCodes.VID_ZONE_UIN, zoneUIN);
long varId = NXCPCodes.VID_USM_CRED_LIST_BASE;
for(SnmpUsmCredential element : usmCredentials)
{
element.fillMessage(msg, varId);
varId += 10;
}
msg.setFieldInt32(NXCPCodes.VID_NUM_RECORDS, usmCredentials.size());
sendMessage(msg);
waitForRCC(msg.getMessageId());
}
/**
* Get SSH credentials for all zones.
*
* @return list of SSH credentials for all zones
* @throws IOException if socket I/O error occurs
* @throws NXCException if NetXMS server returns an error or operation was timed out
*/
public Map> getSshCredentials() throws IOException, NXCException
{
final NXCPMessage msg = newMessage(NXCPCodes.CMD_GET_SSH_CREDENTIALS);
sendMessage(msg);
NXCPMessage response = waitForRCC(msg.getMessageId());
int count = response.getFieldAsInt32(NXCPCodes.VID_NUM_ELEMENTS);
Map