001/*
002 * Copyright 2008-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2019 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.unboundidds.monitors;
022
023
024
025import java.util.ArrayList;
026import java.util.Collections;
027import java.util.LinkedHashMap;
028import java.util.List;
029import java.util.Map;
030
031import com.unboundid.ldap.sdk.Entry;
032import com.unboundid.util.NotMutable;
033import com.unboundid.util.StaticUtils;
034import com.unboundid.util.ThreadSafety;
035import com.unboundid.util.ThreadSafetyLevel;
036
037import static com.unboundid.ldap.sdk.unboundidds.monitors.MonitorMessages.*;
038
039
040
041/**
042 * This class defines a monitor entry that provides information about the system
043 * and JVM on which the Directory Server is running.
044 * <BR>
045 * <BLOCKQUOTE>
046 *   <B>NOTE:</B>  This class, and other classes within the
047 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
048 *   supported for use against Ping Identity, UnboundID, and
049 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
050 *   for proprietary functionality or for external specifications that are not
051 *   considered stable or mature enough to be guaranteed to work in an
052 *   interoperable way with other types of LDAP servers.
053 * </BLOCKQUOTE>
054 * <BR>
055 * The information that may be available includes:
056 * <UL>
057 *   <LI>The name of the operating system on which the server is running.</LI>
058 *   <LI>The number of CPUs available to the JVM.</LI>
059 *   <LI>The Java classpath in use by the server.</LI>
060 *   <LI>The amount of memory currently used by the JVM.</LI>
061 *   <LI>The maximum amount of memory that the JVM will be allowed to use.</LI>
062 *   <LI>The amount of memory held by the JVM that is marked as "free" and can
063 *       be used to allocate new objects.</LI>
064 *   <LI>The hostname for the underlying system.</LI>
065 *   <LI>The location in which the server is installed on the
066 *       underlying system.</LI>
067 *   <LI>The current working directory for the server process.</LI>
068 *   <LI>The path to the Java installation being used to run the server.</LI>
069 *   <LI>The vendor that provides the Java installation being used to run the
070 *       server.</LI>
071 *   <LI>The Java version string for the Java installation being used to run
072 *       the server.</LI>
073 *   <LI>The vendor that provides the JVM being used by the Java installation
074 *       being used to run the server.</LI>
075 *   <LI>The JVM version string for the Java installation being used to run the
076 *       server.</LI>
077 *   <LI>The JVM architecture data model (i.e., whether it is a 32-bit or 64-bit
078 *       JVM).</LI>
079 *   <LI>The arguments provided to the JVM when running the server.</LI>
080 * </UL>
081 * The server should present at most one system info monitor entry.  It can be
082 * retrieved using the {@link MonitorManager#getSystemInfoMonitorEntry} method.
083 * This entry provides specific methods for accessing this system information
084 * (e.g., the {@link SystemInfoMonitorEntry#getOperatingSystem}
085 * method can be used to retrieve the name of the operating system).
086 * Alternately, this information may be accessed using the generic API.  See the
087 * {@link MonitorManager} class documentation for an example that demonstrates
088 * the use of the generic API for accessing monitor data.
089 */
090@NotMutable()
091@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
092public final class SystemInfoMonitorEntry
093       extends MonitorEntry
094{
095  /**
096   * The structural object class used in system info monitor entries.
097   */
098  static final String SYSTEM_INFO_MONITOR_OC =
099       "ds-system-info-monitor-entry";
100
101
102
103  /**
104   * The name of the attribute that provides the number of CPUs available to the
105   * JVM.
106   */
107  private static final String ATTR_AVAILABLE_CPUS = "availableCPUs";
108
109
110
111  /**
112   * The name of the attribute that provides the server Java classpath.
113   */
114  private static final String ATTR_CLASSPATH = "classPath";
115
116
117
118  /**
119   * The name of the attribute that provides the environment variables defined
120   * for the server process.
121   */
122  private static final String ATTR_ENVIRONMENT_VARIABLE = "environmentVariable";
123
124
125
126  /**
127   * The name of the attribute that provides the amount of free memory within
128   * the JVM.
129   */
130  private static final String ATTR_FREE_MEMORY = "freeUsedMemory";
131
132
133
134  /**
135   * The name of the attribute that provides the system hostname.
136   */
137  private static final String ATTR_HOSTNAME = "systemName";
138
139
140
141  /**
142   * The name of the attribute that provides the server instance root.
143   */
144  private static final String ATTR_INSTANCE_ROOT = "instanceRoot";
145
146
147
148  /**
149   * The name of the attribute that provides the server Java home.
150   */
151  private static final String ATTR_JAVA_HOME = "javaHome";
152
153
154
155  /**
156   * The name of the attribute that provides the server Java vendor.
157   */
158  private static final String ATTR_JAVA_VENDOR = "javaVendor";
159
160
161
162  /**
163   * The name of the attribute that provides the server Java version.
164   */
165  private static final String ATTR_JAVA_VERSION = "javaVersion";
166
167
168
169  /**
170   * The name of the attribute that provides the server JVM architecture (e.g.,
171   * 32-bit / 64-bit).
172   */
173  private static final String ATTR_JVM_ARCHITECTURE = "jvmArchitecture";
174
175
176
177  /**
178   * The name of the attribute that provides the set of arguments provided when
179   * starting the JVM.
180   */
181  private static final String ATTR_JVM_ARGUMENTS = "jvmArguments";
182
183
184
185  /**
186   * The name of the attribute that provides the process ID of the JVM in which
187   * the server is running.
188   */
189  private static final String ATTR_JVM_PID = "jvmPID";
190
191
192
193  /**
194   * The name of the attribute that provides the server JVM vendor.
195   */
196  private static final String ATTR_JVM_VENDOR = "jvmVendor";
197
198
199
200  /**
201   * The name of the attribute that provides the server JVM version.
202   */
203  private static final String ATTR_JVM_VERSION = "jvmVersion";
204
205
206
207  /**
208   * The name of the attribute that provides the maximum amount of memory
209   * available to the JVM.
210   */
211  private static final String ATTR_MAX_MEMORY = "maxMemory";
212
213
214
215  /**
216   * The name of the attribute that provides information about the server's
217   * operating system.
218   */
219  private static final String ATTR_OPERATING_SYSTEM = "operatingSystem";
220
221
222
223  /**
224   * The name of the attribute that provides the name of the default SSL context
225   * protocol that has been selected by the server.
226   */
227  private static final String ATTR_SSL_CONTEXT_PROTOCOL = "sslContextProtocol";
228
229
230
231  /**
232   * The name of the attribute that provides the set of system properties
233   * defined in the JVM.
234   */
235  private static final String ATTR_SYSTEM_PROPERTY = "systemProperty";
236
237
238
239  /**
240   * The name of the attribute that provides the amount of memory currently used
241   * by the JVM.
242   */
243  private static final String ATTR_USED_MEMORY = "usedMemory";
244
245
246
247  /**
248   * The name of the attribute that provides the name of the user as whom the
249   * server is running.
250   */
251  private static final String ATTR_USER_NAME = "userName";
252
253
254
255  /**
256   * The name of the attribute that provides the server working directory.
257   */
258  private static final String ATTR_WORKING_DIRECTORY = "workingDirectory";
259
260
261
262  /**
263   * The serial version UID for this serializable class.
264   */
265  private static final long serialVersionUID = 2709857663883498069L;
266
267
268
269  // The number of available CPUs.
270  private final Long availableCPUs;
271
272  // The amount of free memory held by the JVM.
273  private final Long freeMemory;
274
275  // The PID of the JVM in which the server is running.
276  private final Long jvmPID;
277
278  // The maximum amount of memory the JVM can use.
279  private final Long maxMemory;
280
281  // The amount of memory currently held by the JVM.
282  private final Long usedMemory;
283
284  // The set of environment variables defined in the server process.
285  private final Map<String,String> environmentVariables;
286
287  // The set of system properties defined in the JVM.
288  private final Map<String,String> systemProperties;
289
290  // The server's classpath.
291  private final String classpath;
292
293  // The server's hostname.
294  private final String hostname;
295
296  // The path to the server instance root.
297  private final String instanceRoot;
298
299  // The server's Java home.
300  private final String javaHome;
301
302  // The server's Java vendor string.
303  private final String javaVendor;
304
305  // The server's Java version string.
306  private final String javaVersion;
307
308  // The server's JVM architecture.
309  private final String jvmArchitecture;
310
311  // The set of arguments provided to the JVM.
312  private final String jvmArguments;
313
314  // The server's JVM vendor string.
315  private final String jvmVendor;
316
317  // The server's JVM version string.
318  private final String jvmVersion;
319
320  // The name of the operating system on which the server is running.
321  private final String operatingSystem;
322
323  // The name of the default SSL context protocol that has been selected by the
324  // server.
325  private final String sslContextProtocol;
326
327  // The name of the user as whom the server is running.
328  private final String userName;
329
330  // The path to the server's current working directory.
331  private final String workingDirectory;
332
333
334
335  /**
336   * Creates a new system info monitor entry from the provided entry.
337   *
338   * @param  entry  The entry to be parsed as a system info monitor entry.  It
339   *                must not be {@code null}.
340   */
341  public SystemInfoMonitorEntry(final Entry entry)
342  {
343    super(entry);
344
345    availableCPUs      = getLong(ATTR_AVAILABLE_CPUS);
346    classpath          = getString(ATTR_CLASSPATH);
347    freeMemory         = getLong(ATTR_FREE_MEMORY);
348    hostname           = getString(ATTR_HOSTNAME);
349    instanceRoot       = getString(ATTR_INSTANCE_ROOT);
350    javaHome           = getString(ATTR_JAVA_HOME);
351    javaVendor         = getString(ATTR_JAVA_VENDOR);
352    javaVersion        = getString(ATTR_JAVA_VERSION);
353    jvmArchitecture    = getString(ATTR_JVM_ARCHITECTURE);
354    jvmArguments       = getString(ATTR_JVM_ARGUMENTS);
355    jvmPID             = getLong(ATTR_JVM_PID);
356    jvmVendor          = getString(ATTR_JVM_VENDOR);
357    jvmVersion         = getString(ATTR_JVM_VERSION);
358    maxMemory          = getLong(ATTR_MAX_MEMORY);
359    operatingSystem    = getString(ATTR_OPERATING_SYSTEM);
360    sslContextProtocol = getString(ATTR_SSL_CONTEXT_PROTOCOL);
361    usedMemory         = getLong(ATTR_USED_MEMORY);
362    userName           = getString(ATTR_USER_NAME);
363    workingDirectory   = getString(ATTR_WORKING_DIRECTORY);
364
365    final List<String> envValues = getStrings(ATTR_ENVIRONMENT_VARIABLE);
366    final LinkedHashMap<String,String> envMap =
367         new LinkedHashMap<>(StaticUtils.computeMapCapacity(envValues.size()));
368    for (final String s : envValues)
369    {
370      final int eqPos = s.indexOf("='");
371      if (eqPos > 0)
372      {
373        final String name = s.substring(0, eqPos);
374        if (eqPos != (s.length() - 2))
375        {
376          envMap.put(name, s.substring(eqPos+2, (s.length() - 1)));
377        }
378      }
379    }
380    environmentVariables = Collections.unmodifiableMap(envMap);
381
382    final List<String> propValues = getStrings(ATTR_SYSTEM_PROPERTY);
383    final LinkedHashMap<String,String> propMap =
384         new LinkedHashMap<>(StaticUtils.computeMapCapacity(propValues.size()));
385    for (final String s : propValues)
386    {
387      final int eqPos = s.indexOf("='");
388      if (eqPos > 0)
389      {
390        final String name = s.substring(0, eqPos);
391        if (eqPos != (s.length() - 2))
392        {
393          propMap.put(name, s.substring(eqPos+2, (s.length() - 1)));
394        }
395      }
396    }
397    systemProperties = Collections.unmodifiableMap(propMap);
398  }
399
400
401
402  /**
403   * Retrieves the number of CPUs available to the JVM.
404   *
405   * @return  The number of CPUs available to the JVM, or {@code null} if it was
406   *          not included in the monitor entry.
407   */
408  public Long getAvailableCPUs()
409  {
410    return availableCPUs;
411  }
412
413
414
415  /**
416   * Retrieves the server's Java classpath.
417   *
418   * @return  The server's Java classpath, or {@code null} if it was not
419   *          included in the monitor entry.
420   */
421  public String getClassPath()
422  {
423    return classpath;
424  }
425
426
427
428  /**
429   * Retrieves the environment variables available to the server process, mapped
430   * from variable name to the corresponding value.
431   *
432   * @return  The environment variables available to the server process, or an
433   *          empty map if it was not included in the monitor entry.
434   */
435  public Map<String,String> getEnvironmentVariables()
436  {
437    return environmentVariables;
438  }
439
440
441
442  /**
443   * Retrieves the amount of memory in bytes held by the JVM that is currently
444   * marked as free.
445   *
446   * @return  The amount of memory in bytes held by the JVM that is currently
447   *          marked as free, or {@code null} if it was not included in the
448   *          monitor entry.
449   */
450  public Long getFreeMemory()
451  {
452    return freeMemory;
453  }
454
455
456
457  /**
458   * Retrieves the server's hostname.
459   *
460   * @return  The server's hostname, or {@code null} if it was not included in
461   *          the monitor entry.
462   */
463  public String getHostname()
464  {
465    return hostname;
466  }
467
468
469
470  /**
471   * Retrieves the path to the directory in which the Directory Server is
472   * installed.
473   *
474   * @return  The path to the directory in which the Directory Server is
475   *          installed, or {@code null} if it was not included in the monitor
476   *          entry.
477   */
478  public String getInstanceRoot()
479  {
480    return instanceRoot;
481  }
482
483
484
485  /**
486   * Retrieves the path to the Java installation used by the server.
487   *
488   * @return  The path to the Java installation used by the server, or
489   *          {@code null} if it was not included in the monitor entry.
490   */
491  public String getJavaHome()
492  {
493    return javaHome;
494  }
495
496
497
498  /**
499   * Retrieves the server's Java vendor string.
500   *
501   * @return  The server's Java vendor string, or {@code null} if it was not
502   *          included in the monitor entry.
503   */
504  public String getJavaVendor()
505  {
506    return javaVendor;
507  }
508
509
510
511  /**
512   * Retrieves the server's Java version string.
513   *
514   * @return  The server's Java version string, or {@code null} if it was not
515   *          included in the monitor entry.
516   */
517  public String getJavaVersion()
518  {
519    return javaVersion;
520  }
521
522
523
524  /**
525   * Retrieves the server's JVM architecture data mode, which should indicate
526   * whether the server is running a 32-bit or 64-bit JVM.
527   *
528   * @return  The server's JVM architecture data model, or {@code null} if it
529   *          was not included in the monitor entry.
530   */
531  public String getJVMArchitectureDataModel()
532  {
533    return jvmArchitecture;
534  }
535
536
537
538  /**
539   * Retrieves a list of the arguments provided to the JVM when the server was
540   * started.
541   *
542   * @return  A list of the arguments provided to the JVM when the server was
543   *          started, or {@code null} if it was not included in the monitor
544   *          entry.
545   */
546  public String getJVMArguments()
547  {
548    return jvmArguments;
549  }
550
551
552
553  /**
554   * Retrieves the process ID of the JVM in which the server is running.
555   *
556   * @return  The process ID of the JVM in which the server is running, or
557   *          {@code null} if it was not included in the monitor entry.
558   */
559  public Long getJVMPID()
560  {
561    return jvmPID;
562  }
563
564
565
566  /**
567   * Retrieves the server's JVM vendor string.
568   *
569   * @return  The server's JVM vendor string, or {@code null} if it was not
570   *          included in the monitor entry.
571   */
572  public String getJVMVendor()
573  {
574    return jvmVendor;
575  }
576
577
578
579  /**
580   * Retrieves the server's JVM version string.
581   *
582   * @return  The server's JVM version string, or {@code null} if it was not
583   *          included in the monitor entry.
584   */
585  public String getJVMVersion()
586  {
587    return jvmVersion;
588  }
589
590
591
592  /**
593   * Retrieves the maximum amount of memory in bytes that the JVM will be
594   * allowed to use.
595   *
596   * @return  The maximum amount of memory in bytes that the JVM will be allowed
597   *          to use, or {@code null} if it was not included in the monitor
598   *          entry.
599   */
600  public Long getMaxMemory()
601  {
602    return maxMemory;
603  }
604
605
606
607  /**
608   * Retrieves information about the operating system on which the server is
609   * running.
610   *
611   * @return  Information about the operating system on which the server is
612   *          running, or {@code null} if it was not included in the monitor
613   *          entry.
614   */
615  public String getOperatingSystem()
616  {
617    return operatingSystem;
618  }
619
620
621
622  /**
623   * Retrieves the name of the default SSL context protocol that has been
624   * selected by the server.
625   *
626   * @return  The name of the default SSL context protocol that has been
627   *          selected by the server.
628   */
629  public String getSSLContextProtocol()
630  {
631    return sslContextProtocol;
632  }
633
634
635
636  /**
637   * Retrieves the system properties defined in the server JVM, mapped from
638   * property name to the corresponding value.
639   *
640   * @return  The system properties defined in the server JVM, or an empty map
641   *          if it was not included in the monitor entry.
642   */
643  public Map<String,String> getSystemProperties()
644  {
645    return systemProperties;
646  }
647
648
649
650  /**
651   * Retrieves the amount of memory in bytes currently held by the JVM used to
652   * run the server.
653   *
654   * @return  The amount of memory in bytes currently held by the JVM used to
655   *          run the server, or {@code null} if it was not included in the
656   *          monitor entry
657   */
658  public Long getUsedMemory()
659  {
660    return usedMemory;
661  }
662
663
664
665  /**
666   * Retrieves the name of the user as whom the server is running.
667   *
668   * @return  The name of the user as whom the server is running, or
669   *          {@code null} if it was not included in the monitor entry.
670   */
671  public String getUserName()
672  {
673    return userName;
674  }
675
676
677
678  /**
679   * Retrieves the path to the server's current working directory.  This is
680   * generally the path to the directory from which the server was started.
681   *
682   * @return  The path to the server's current working directory, or
683   *          {@code null} if it was not included in the monitor entry.
684   */
685  public String getWorkingDirectory()
686  {
687    return workingDirectory;
688  }
689
690
691
692  /**
693   * {@inheritDoc}
694   */
695  @Override()
696  public String getMonitorDisplayName()
697  {
698    return INFO_SYSTEM_INFO_MONITOR_DISPNAME.get();
699  }
700
701
702
703  /**
704   * {@inheritDoc}
705   */
706  @Override()
707  public String getMonitorDescription()
708  {
709    return INFO_SYSTEM_INFO_MONITOR_DESC.get();
710  }
711
712
713
714  /**
715   * {@inheritDoc}
716   */
717  @Override()
718  public Map<String,MonitorAttribute> getMonitorAttributes()
719  {
720    final LinkedHashMap<String,MonitorAttribute> attrs =
721         new LinkedHashMap<>(StaticUtils.computeMapCapacity(30));
722
723    if (hostname != null)
724    {
725      addMonitorAttribute(attrs,
726           ATTR_HOSTNAME,
727           INFO_SYSTEM_INFO_DISPNAME_HOSTNAME.get(),
728           INFO_SYSTEM_INFO_DESC_HOSTNAME.get(),
729           hostname);
730    }
731
732    if (operatingSystem != null)
733    {
734      addMonitorAttribute(attrs,
735           ATTR_OPERATING_SYSTEM,
736           INFO_SYSTEM_INFO_DISPNAME_OPERATING_SYSTEM.get(),
737           INFO_SYSTEM_INFO_DESC_OPERATING_SYSTEM.get(),
738           operatingSystem);
739    }
740
741    if (jvmArchitecture != null)
742    {
743      addMonitorAttribute(attrs,
744           ATTR_JVM_ARCHITECTURE,
745           INFO_SYSTEM_INFO_DISPNAME_JVM_ARCHITECTURE.get(),
746           INFO_SYSTEM_INFO_DESC_JVM_ARCHITECTURE.get(),
747           jvmArchitecture);
748    }
749
750    if (javaHome != null)
751    {
752      addMonitorAttribute(attrs,
753           ATTR_JAVA_HOME,
754           INFO_SYSTEM_INFO_DISPNAME_JAVA_HOME.get(),
755           INFO_SYSTEM_INFO_DESC_JAVA_HOME.get(),
756           javaHome);
757    }
758
759    if (javaVersion != null)
760    {
761      addMonitorAttribute(attrs,
762           ATTR_JAVA_VERSION,
763           INFO_SYSTEM_INFO_DISPNAME_JAVA_VERSION.get(),
764           INFO_SYSTEM_INFO_DESC_JAVA_VERSION.get(),
765           javaVersion);
766    }
767
768    if (javaVendor != null)
769    {
770      addMonitorAttribute(attrs,
771           ATTR_JAVA_VENDOR,
772           INFO_SYSTEM_INFO_DISPNAME_JAVA_VENDOR.get(),
773           INFO_SYSTEM_INFO_DESC_JAVA_VENDOR.get(),
774           javaVendor);
775    }
776
777    if (jvmVersion != null)
778    {
779      addMonitorAttribute(attrs,
780           ATTR_JVM_VERSION,
781           INFO_SYSTEM_INFO_DISPNAME_JVM_VERSION.get(),
782           INFO_SYSTEM_INFO_DESC_JVM_VERSION.get(),
783           jvmVersion);
784    }
785
786    if (jvmVendor != null)
787    {
788      addMonitorAttribute(attrs,
789           ATTR_JVM_VENDOR,
790           INFO_SYSTEM_INFO_DISPNAME_JVM_VENDOR.get(),
791           INFO_SYSTEM_INFO_DESC_JVM_VENDOR.get(),
792           jvmVendor);
793    }
794
795    if (jvmArguments != null)
796    {
797      addMonitorAttribute(attrs,
798           ATTR_JVM_ARGUMENTS,
799           INFO_SYSTEM_INFO_DISPNAME_JVM_ARGUMENTS.get(),
800           INFO_SYSTEM_INFO_DESC_JVM_ARGUMENTS.get(),
801           jvmArguments);
802    }
803
804    if (jvmPID != null)
805    {
806      addMonitorAttribute(attrs,
807           ATTR_JVM_PID,
808           INFO_SYSTEM_INFO_DISPNAME_JVM_PID.get(),
809           INFO_SYSTEM_INFO_DESC_JVM_PID.get(),
810           jvmPID);
811    }
812
813    if (sslContextProtocol != null)
814    {
815      addMonitorAttribute(attrs,
816           ATTR_SSL_CONTEXT_PROTOCOL,
817           INFO_SYSTEM_INFO_DISPNAME_SSL_CONTEXT_PROTOCOL.get(),
818           INFO_SYSTEM_INFO_DESC_SSL_CONTEXT_PROTOCOL.get(),
819           sslContextProtocol);
820    }
821
822    if (classpath != null)
823    {
824      addMonitorAttribute(attrs,
825           ATTR_CLASSPATH,
826           INFO_SYSTEM_INFO_DISPNAME_CLASSPATH.get(),
827           INFO_SYSTEM_INFO_DESC_CLASSPATH.get(),
828           classpath);
829    }
830
831    if (instanceRoot != null)
832    {
833      addMonitorAttribute(attrs,
834           ATTR_INSTANCE_ROOT,
835           INFO_SYSTEM_INFO_DISPNAME_INSTANCE_ROOT.get(),
836           INFO_SYSTEM_INFO_DESC_INSTANCE_ROOT.get(),
837           instanceRoot);
838    }
839
840    if (workingDirectory != null)
841    {
842      addMonitorAttribute(attrs,
843           ATTR_WORKING_DIRECTORY,
844           INFO_SYSTEM_INFO_DISPNAME_WORKING_DIRECTORY.get(),
845           INFO_SYSTEM_INFO_DESC_WORKING_DIRECTORY.get(),
846           workingDirectory);
847    }
848
849    if (availableCPUs != null)
850    {
851      addMonitorAttribute(attrs,
852           ATTR_AVAILABLE_CPUS,
853           INFO_SYSTEM_INFO_DISPNAME_AVAILABLE_CPUS.get(),
854           INFO_SYSTEM_INFO_DESC_AVAILABLE_CPUS.get(),
855           availableCPUs);
856    }
857
858    if (usedMemory != null)
859    {
860      addMonitorAttribute(attrs,
861           ATTR_USED_MEMORY,
862           INFO_SYSTEM_INFO_DISPNAME_USED_MEMORY.get(),
863           INFO_SYSTEM_INFO_DESC_USED_MEMORY.get(),
864           usedMemory);
865    }
866
867    if (maxMemory != null)
868    {
869      addMonitorAttribute(attrs,
870           ATTR_MAX_MEMORY,
871           INFO_SYSTEM_INFO_DISPNAME_MAX_MEMORY.get(),
872           INFO_SYSTEM_INFO_DESC_MAX_MEMORY.get(),
873           maxMemory);
874    }
875
876    if (freeMemory != null)
877    {
878      addMonitorAttribute(attrs,
879           ATTR_FREE_MEMORY,
880           INFO_SYSTEM_INFO_DISPNAME_FREE_MEMORY.get(),
881           INFO_SYSTEM_INFO_DESC_FREE_MEMORY.get(),
882           freeMemory);
883    }
884
885    if (userName != null)
886    {
887      addMonitorAttribute(attrs,
888           ATTR_USER_NAME,
889           INFO_SYSTEM_INFO_DISPNAME_USER_NAME.get(),
890           INFO_SYSTEM_INFO_DESC_USER_NAME.get(),
891           userName);
892    }
893
894    if (! environmentVariables.isEmpty())
895    {
896      final ArrayList<String> envList =
897           new ArrayList<>(environmentVariables.size());
898      for (final Map.Entry<String,String> e : environmentVariables.entrySet())
899      {
900        envList.add(e.getKey() + "='" + e.getValue() + '\'');
901      }
902
903      addMonitorAttribute(attrs,
904           ATTR_ENVIRONMENT_VARIABLE,
905           INFO_SYSTEM_INFO_DISPNAME_ENV_VAR.get(),
906           INFO_SYSTEM_INFO_DESC_ENV_VAR.get(),
907           envList);
908    }
909
910    if (! systemProperties.isEmpty())
911    {
912      final ArrayList<String> propList =
913           new ArrayList<>(systemProperties.size());
914      for (final Map.Entry<String,String> e : systemProperties.entrySet())
915      {
916        propList.add(e.getKey() + "='" + e.getValue() + '\'');
917      }
918
919      addMonitorAttribute(attrs,
920           ATTR_SYSTEM_PROPERTY,
921           INFO_SYSTEM_INFO_DISPNAME_SYSTEM_PROP.get(),
922           INFO_SYSTEM_INFO_DESC_SYSTEM_PROP.get(),
923           propList);
924    }
925
926    return Collections.unmodifiableMap(attrs);
927  }
928}