1 package org.metricshub.wbem.client;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.net.URL;
24 import java.util.ArrayList;
25 import java.util.LinkedHashSet;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.stream.Collectors;
31 import java.util.stream.Stream;
32 import javax.security.auth.Subject;
33 import org.metricshub.wbem.javax.cim.CIMInstance;
34 import org.metricshub.wbem.javax.cim.CIMObjectPath;
35 import org.metricshub.wbem.javax.cim.CIMProperty;
36 import org.metricshub.wbem.javax.wbem.CloseableIterator;
37 import org.metricshub.wbem.javax.wbem.WBEMException;
38 import org.metricshub.wbem.javax.wbem.client.EnumerateResponse;
39 import org.metricshub.wbem.javax.wbem.client.PasswordCredential;
40 import org.metricshub.wbem.javax.wbem.client.UserPrincipal;
41 import org.metricshub.wbem.javax.wbem.client.WBEMClient;
42 import org.metricshub.wbem.javax.wbem.client.WBEMClientConstants;
43 import org.metricshub.wbem.javax.wbem.client.WBEMClientFactory;
44
45
46
47
48
49 public class WbemClient implements AutoCloseable {
50 private static final Locale[] FIXED_AVAILABLE_LOCALES_ARRAY = { Locale.ENGLISH };
51
52 private WBEMClient client;
53
54 private CloseableIterator<CIMInstance> iterator;
55
56
57
58
59
60
61
62
63
64
65 public void connect(final URL url, final String username, final char[] password, int timeout) throws WBEMException {
66 Utils.checkNonNull(url, "url");
67 Utils.checkNonNull(username, "username");
68 Utils.checkNonNull(password, "password");
69
70 final CIMObjectPath cimObjectPath = new CIMObjectPath(
71 url.getProtocol(),
72 url.getHost(),
73 String.valueOf(url.getPort()),
74 null,
75 null,
76 null
77 );
78
79 final Subject subject = new Subject();
80 subject.getPrincipals().add(new UserPrincipal(username));
81 subject.getPrivateCredentials().add(new PasswordCredential(password));
82
83
84 client = WBEMClientFactory.getClient("CIM-XML");
85 client.setProperty(WBEMClientConstants.PROP_TIMEOUT, String.valueOf(timeout));
86 client.initialize(cimObjectPath, subject, FIXED_AVAILABLE_LOCALES_ARRAY);
87 }
88
89 @Override
90 public void close() {
91 if (iterator != null) {
92 iterator.close();
93 }
94
95 if (client != null) {
96 client.close();
97 }
98 }
99
100
101
102
103
104
105
106
107
108 public WbemQueryResult executeWql(final WqlQuery wqlQuery, final String namespace, final String arraySeparator)
109 throws WBEMException {
110 Utils.checkNonNull(wqlQuery, "wqlQuery");
111 Utils.checkNonNull(namespace, "namespace");
112
113 if (client == null) {
114 throw new IllegalStateException("client must be connected first.");
115 }
116
117 iterator =
118 client.enumerateInstances(
119 new CIMObjectPath(null, null, null, namespace, wqlQuery.getClassName(), null),
120 true,
121 false,
122 true,
123 wqlQuery.getPropertiesArray()
124 );
125
126 return enumerateInstances(wqlQuery, iterator, arraySeparator);
127 }
128
129
130
131
132
133
134
135
136
137 public WbemQueryResult getAssociators(
138 final WqlQuery wqlQuery,
139 final String objectPathAssociators,
140 final String arraySeparator
141 )
142 throws WBEMException {
143 Utils.checkNonNull(wqlQuery, "wqlQuery");
144 Utils.checkNonNull(objectPathAssociators, "objectPathAssociators");
145
146 if (client == null) {
147 throw new IllegalStateException("client must be connected first.");
148 }
149
150 final EnumerateResponse<CIMInstance> response = client.associators(
151 new CIMObjectPath(objectPathAssociators),
152 wqlQuery.getClassName(),
153 null,
154 null,
155 null,
156 false,
157 wqlQuery.getPropertiesArray(),
158 null,
159 null,
160 null,
161 false,
162 null
163 );
164 iterator = response.getResponses();
165
166 return enumerateInstances(wqlQuery, iterator, arraySeparator);
167 }
168
169 public static WbemQueryResult enumerateInstances(
170 final WqlQuery wqlQuery,
171 final CloseableIterator<CIMInstance> iterator,
172 final String arraySeparator
173 ) {
174 if (iterator == null) {
175 return new WbemQueryResult(new ArrayList<>(), new ArrayList<>());
176 }
177
178 Set<String> properties = null;
179 List<String> originalProperties = null;
180 final List<List<String>> values = new ArrayList<>();
181
182 while (iterator.hasNext()) {
183 final CIMInstance cimInstance = iterator.next();
184
185 if (properties == null) {
186 properties =
187 wqlQuery.getProperties().isEmpty()
188 ? Stream
189 .of(cimInstance.getProperties())
190 .map(CIMProperty::getName)
191 .collect(Collectors.toCollection(LinkedHashSet::new))
192 : wqlQuery.getProperties();
193 }
194
195 if (originalProperties == null) {
196 originalProperties =
197 wqlQuery.hasDuplicateProperties()
198 ? wqlQuery.getOriginalProperties()
199 : properties.stream().collect(Collectors.toList());
200 }
201
202 final List<String> row;
203 if (wqlQuery.hasDuplicateProperties()) {
204 final Map<String, String> cimProperties = properties
205 .stream()
206 .collect(
207 Collectors.toMap(
208 String::toLowerCase,
209 property -> WbemCimDataHandler.getCimPropertyAsString(property, cimInstance, arraySeparator)
210 )
211 );
212
213 row =
214 originalProperties
215 .stream()
216 .map(property -> cimProperties.get(property.toLowerCase()))
217 .collect(Collectors.toList());
218 } else {
219 row =
220 properties
221 .stream()
222 .map(property -> WbemCimDataHandler.getCimPropertyAsString(property, cimInstance, arraySeparator))
223 .collect(Collectors.toList());
224 }
225
226 values.add(row);
227 }
228
229 return new WbemQueryResult(originalProperties, values);
230 }
231 }