1+ /*
2+ * Copyright 2016 Javier Garcia Alonso.
3+ *
4+ * Licensed under the Apache License, Version 2.0 (the "License");
5+ * you may not use this file except in compliance with the License.
6+ * You may obtain a copy of the License at
7+ *
8+ * http://www.apache.org/licenses/LICENSE-2.0
9+ *
10+ * Unless required by applicable law or agreed to in writing, software
11+ * distributed under the License is distributed on an "AS IS" BASIS,
12+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+ * See the License for the specific language governing permissions and
14+ * limitations under the License.
15+ */
16+ package com .profesorfalken .wmi4java ;
17+
18+ import java .util .ArrayList ;
19+ import java .util .Arrays ;
20+ import java .util .Collections ;
21+ import java .util .HashMap ;
22+ import java .util .HashSet ;
23+ import java .util .List ;
24+ import java .util .Map ;
25+ import java .util .Set ;
26+ import java .util .logging .Level ;
27+ import java .util .logging .Logger ;
28+
29+ /**
30+ * Class that allows to get WMI information. <br>
31+ * It should be instantiated using an static method and can be easily configured
32+ * using chained methods.<p>
33+ *
34+ * Ex:
35+ * <code>WMI4Java.get().computerName(".").namespace("root/cimv2").getWMIObject("Win32_BaseBoard");</code>
36+ * <p>
37+ * The default computername will be . and the default namespace root/cimv2<p>
38+ *
39+ * It supports two implementations: <br>
40+ * -One based on PowerShell console (see project jPowerShell)<br>
41+ * -The other based on a VB script (many thanks to Scriptomatic tool!)<p>
42+ *
43+ * But default it will use PowerShell but we can force an specific engine easily.
44+ *
45+ * @see <a href="https://github.com/profesorfalken/jPowerShell">jPowerShell</a>
46+ * @see <a href="https://technet.microsoft.com/fr-fr/scriptcenter/dd939957.aspx">Scriptomatic v2</a>
47+ *
48+ * @author Javier Garcia Alonso
49+ */
50+ public class WMI4Java {
51+ private static final String NEWLINE_REGEX = "\\ r?\\ n" ;
52+ private static final String SPACE_REGEX = "\\ s+" ;
53+
54+ private String namespace = "*" ;
55+ private String computerName = "." ;
56+ private boolean forceVBEngine = false ;
57+
58+ //Private constructor. Must be instantiated statically
59+ private WMI4Java () {
60+ }
61+
62+ //Get the engine used to retrieve WMI data
63+ private WMIStub getWMIStub () {
64+ if (this .forceVBEngine ) {
65+ return new WMIVBScript ();
66+ } else {
67+ return new WMIPowerShell ();
68+ }
69+ }
70+
71+ /**
72+ * Static creation of instance
73+ *
74+ * @return WMI4Java
75+ */
76+ public static WMI4Java get () {
77+ return new WMI4Java ();
78+ }
79+
80+ /**
81+ * Set an specific namespace <br>
82+ *
83+ * By default it uses root/cimv2 namespace
84+ *
85+ * @param namespace used namespace. Ex "root/WMI"
86+ * @return object instance used to chain calls
87+ */
88+ public WMI4Java namespace (String namespace ) {
89+ this .namespace = namespace ;
90+ return this ;
91+ }
92+
93+ /**
94+ * Set an specific computer name <br>
95+ *
96+ * By default it uses .
97+ *
98+ * @param computerName
99+ * @return object instance used to chain calls
100+ */
101+ public WMI4Java computerName (String computerName ) {
102+ this .computerName = computerName ;
103+ return this ;
104+ }
105+
106+ /**
107+ * Forces the use of PowerShell engine in order to query WMI
108+ *
109+ * @return object instance used to chain calls
110+ */
111+ public WMI4Java PowerShellEngine () {
112+ this .forceVBEngine = false ;
113+ return this ;
114+ }
115+
116+ /**
117+ * Forces the use of VBS engine in order to query WMI
118+ *
119+ * @return object instance used to chain calls
120+ */
121+ public WMI4Java VBSEngine () {
122+ this .forceVBEngine = true ;
123+ return this ;
124+ }
125+
126+ /**
127+ * Query and list the WMI classes
128+ *
129+ * @see <a href="https://msdn.microsoft.com/fr-fr/library/windows/desktop/aa394554(v=vs.85).aspx">WMI Classes - MSDN</a>
130+ * @return a list with the name of existing classes in the system
131+ */
132+ public List <String > listClasses () {
133+ List <String > wmiClasses = new ArrayList <String >();
134+ String rawData ;
135+ try {
136+ rawData = getWMIStub ().listClasses (this .namespace , this .computerName );
137+
138+ String [] dataStringLines = rawData .split (NEWLINE_REGEX );
139+
140+ for (String line : dataStringLines ) {
141+ if (!line .isEmpty () && !line .startsWith ("_" )) {
142+ String [] infos = line .split (SPACE_REGEX );
143+ wmiClasses .addAll (Arrays .asList (infos ));
144+ }
145+ }
146+
147+ //Normalize results: remove duplicates and sort the list
148+ Set <String > hs = new HashSet <String >();
149+ hs .addAll (wmiClasses );
150+ wmiClasses .clear ();
151+ wmiClasses .addAll (hs );
152+
153+ } catch (Exception ex ) {
154+ Logger .getLogger (WMI4Java .class .getName ()).log (Level .SEVERE , "Error calling WMI4Java" , ex );
155+ wmiClasses = Collections .emptyList ();
156+ }
157+
158+ return wmiClasses ;
159+ }
160+
161+ /**
162+ * Query a WMI class and return all the available properties
163+ *
164+ * @param wmiClass the WMI class to query
165+ * @return a list with the name of existing properties in the class
166+ */
167+ public List <String > listProperties (String wmiClass ) {
168+ List <String > foundPropertiesList = new ArrayList <String >();
169+ try {
170+ String rawData = getWMIStub ().listProperties (wmiClass , this .namespace , this .computerName );
171+
172+ String [] dataStringLines = rawData .split (NEWLINE_REGEX );
173+
174+ for (final String line : dataStringLines ) {
175+ if (!line .isEmpty ()) {
176+ foundPropertiesList .add (line .trim ());
177+ }
178+ }
179+
180+ List <String > notAllowed =
181+ Arrays .asList (new String [] {"Equals" , "GetHashCode" , "GetType" , "ToString" });
182+ foundPropertiesList .removeAll (notAllowed );
183+
184+ } catch (Exception ex ) {
185+ Logger .getLogger (WMI4Java .class .getName ()).log (Level .SEVERE , "Error calling WMI4Java" , ex );
186+ foundPropertiesList = Collections .emptyList ();
187+ }
188+ return foundPropertiesList ;
189+ }
190+
191+ /**
192+ * Query all the object data for an specific class
193+ *
194+ * @param wmiClass Enum that contains the most used classes (root/cimv2)
195+ * @return map with the key and the value of all the properties of the object
196+ */
197+ public Map <String , String > getWMIObject (WMIClass wmiClass ) {
198+ return getWMIObject (wmiClass .getName ());
199+ }
200+
201+ /**
202+ * Query all the object data for an specific class
203+ *
204+ * @param wmiClass string with the name of the class to query
205+ * @return map with the key and the value of all the properties of the object
206+ */
207+ public Map <String , String > getWMIObject (String wmiClass ) {
208+ Map <String , String > foundWMIClassProperties = new HashMap <>();
209+ try {
210+ String rawData = getWMIStub ().listObject (wmiClass , this .namespace , this .computerName );
211+
212+ String [] dataStringLines = rawData .split (NEWLINE_REGEX );
213+
214+ for (final String line : dataStringLines ) {
215+ if (!line .isEmpty ()) {
216+ String [] entry = line .split (":" );
217+ if (entry != null && entry .length == 2 ) {
218+ foundWMIClassProperties .put (entry [0 ].trim (), entry [1 ].trim ());
219+ }
220+ }
221+ }
222+ } catch (WMIException ex ) {
223+ Logger .getLogger (WMI4Java .class .getName ()).log (Level .SEVERE , "Error calling WMI4Java" , ex );
224+ foundWMIClassProperties = Collections .emptyMap ();
225+ }
226+ return foundWMIClassProperties ;
227+ }
228+ }
0 commit comments