1 package org.metricshub.wmi.windows.remote.share;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.Objects;
24 import java.util.Optional;
25 import java.util.concurrent.TimeoutException;
26 import org.metricshub.wmi.TimeoutHelper;
27 import org.metricshub.wmi.Utils;
28 import org.metricshub.wmi.exceptions.WindowsRemoteException;
29 import org.metricshub.wmi.exceptions.WqlQuerySyntaxException;
30 import org.metricshub.wmi.windows.remote.WindowsRemoteExecutor;
31
32 public class WindowsTempShare {
33
34
35 private final String shareName;
36
37
38 private final String uncSharePath;
39
40
41 private final String remotePath;
42
43
44 private final WindowsRemoteExecutor windowsRemoteExecutor;
45
46
47
48
49
50
51
52
53 public WindowsTempShare(
54 final WindowsRemoteExecutor windowsRemoteExecutor,
55 final String shareNameOrUnc,
56 final String remotePath
57 ) {
58 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
59 Utils.checkNonNull(shareNameOrUnc, "shareNameOrUnc");
60
61 if (shareNameOrUnc.startsWith("\\\\")) {
62 this.uncSharePath = shareNameOrUnc;
63 final String[] uncElements = shareNameOrUnc.split("\\\\");
64 this.shareName = uncElements[3];
65 } else {
66 this.uncSharePath = buildUncPath(windowsRemoteExecutor.getHostname(), shareNameOrUnc);
67 this.shareName = shareNameOrUnc;
68 }
69
70 this.remotePath = remotePath;
71 this.windowsRemoteExecutor = windowsRemoteExecutor;
72 }
73
74
75
76
77
78
79
80
81
82
83
84 public static WindowsTempShare getOrCreateShare(
85 final WindowsRemoteExecutor windowsRemoteExecutor,
86 final long timeout,
87 final ShareRemoteDirectoryConsumer<WindowsRemoteExecutor, String, String, Long> shareRemoteDirectory
88 ) throws TimeoutException, WindowsRemoteException {
89 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
90 Utils.checkArgumentNotZeroOrNegative(timeout, "timeout");
91 Utils.checkNonNull(shareRemoteDirectory, "shareRemoteDirectory");
92
93 final long start = Utils.getCurrentTimeMillis();
94
95
96
97
98
99 final Optional<WindowsTempShare> clusterShare = getClusterShare(
100 windowsRemoteExecutor,
101 TimeoutHelper.getRemainingTime(timeout, start, "No time left to check for cluster share")
102 );
103
104 if (clusterShare.isPresent()) {
105 return clusterShare.get();
106 }
107
108
109 final String shareName = buildShareName();
110 final Optional<WindowsTempShare> share = getShare(
111 windowsRemoteExecutor,
112 shareName,
113 TimeoutHelper.getRemainingTime(timeout, start, "No time left to get a normal temporary share")
114 );
115 if (share.isPresent()) {
116 return share.get();
117 }
118
119 return createTempShare(
120 windowsRemoteExecutor,
121 shareName,
122 TimeoutHelper.getRemainingTime(timeout, start, "No time left to create the temporary share"),
123 shareRemoteDirectory
124 );
125 }
126
127
128
129
130
131
132
133
134
135
136
137
138
139 public static String getWindowsDirectory(final WindowsRemoteExecutor windowsRemoteExecutor, final long timeout)
140 throws WindowsRemoteException, TimeoutException {
141 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
142 Utils.checkArgumentNotZeroOrNegative(timeout, "timeout");
143
144 try {
145
146 return windowsRemoteExecutor
147 .executeWql("SELECT WindowsDirectory FROM Win32_OperatingSystem", timeout)
148 .stream()
149 .limit(1)
150 .map(row -> (String) row.get("WindowsDirectory"))
151 .filter(Objects::nonNull)
152 .findFirst()
153 .orElseThrow(() ->
154 new WindowsRemoteException(
155 String.format("Couldn't identify the Windows root directory on %s.", windowsRemoteExecutor.getHostname())
156 )
157 );
158 } catch (final WqlQuerySyntaxException e) {
159 throw new WindowsRemoteException(e);
160 }
161 }
162
163
164
165
166
167
168
169
170
171
172 public static void createRemoteDirectory(
173 final WindowsRemoteExecutor windowsRemoteExecutor,
174 final String remotePath,
175 final long timeout
176 ) throws WindowsRemoteException, TimeoutException {
177 Utils.checkNonNull(windowsRemoteExecutor, "windowsRemoteExecutor");
178
179 windowsRemoteExecutor.executeCommand(buildCreateRemoteDirectoryCommand(remotePath), null, null, timeout);
180 }
181
182
183
184
185
186
187
188
189
190
191 static String buildUncPath(final String hostname, final String share) {
192 Utils.checkNonNull(hostname, "hostname");
193
194 return hostname.contains(":")
195 ? String.format("\\\\%s.ipv6-literal.net\\%s", hostname.replace(":", "-").replace("%", "s"), share)
196 : String.format("\\\\%s\\%s", hostname, share);
197 }
198
199
200
201
202
203
204
205
206 static String buildCreateRemoteDirectoryCommand(final String remotePath) {
207 Utils.checkNonBlank(remotePath, "remotePath");
208
209 return String.format("CMD.EXE /C IF NOT EXIST \"%s\" MKDIR %s", remotePath, remotePath);
210 }
211
212
213
214
215
216
217 static String buildPathOnCluster(final String path) {
218 Utils.checkNonNull(path, "path");
219
220 return String.format("%s\\Temp\\SEN_TempFor_%s", path, Utils.getComputerName());
221 }
222
223
224
225
226
227
228
229
230
231 static String buildRemotePath(final String folder, final String shareName) {
232 Utils.checkNonNull(folder, "folder");
233 Utils.checkNonBlank(shareName, "shareName");
234
235 return String.format("%s\\Temp\\%s", folder, shareName);
236 }
237
238
239
240
241
242
243 static String buildShareName() {
244 return String.format("SEN_ShareFor_%s$", Utils.getComputerName());
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 static Optional<WindowsTempShare> getClusterShare(
261 final WindowsRemoteExecutor windowsRemoteExecutor,
262 final long timeout
263 ) throws TimeoutException, WindowsRemoteException {
264 try {
265 final Optional<WindowsTempShare> clusterShare = windowsRemoteExecutor
266 .executeWql(
267 "SELECT Name,Path FROM Win32_ClusterShare WHERE " +
268 "ServerName <> '*' AND (Type = 2147483648 OR Type = 3221225472) AND Name LIKE '%\\\\_$'",
269 timeout
270 )
271 .stream()
272 .limit(1)
273 .map(row ->
274 new WindowsTempShare(
275 windowsRemoteExecutor,
276 buildPathOnCluster((String) row.get("Name")),
277 buildPathOnCluster((String) row.get("Path"))
278 )
279 )
280 .findFirst();
281
282 if (clusterShare.isPresent()) {
283
284 createRemoteDirectory(windowsRemoteExecutor, clusterShare.get().getRemotePath(), timeout);
285 }
286
287 return clusterShare;
288 } catch (final WqlQuerySyntaxException e) {
289 throw new WindowsRemoteException(e);
290 }
291 }
292
293
294
295
296
297
298
299
300
301
302
303
304
305 static Optional<WindowsTempShare> getShare(
306 final WindowsRemoteExecutor windowsRemoteExecutor,
307 final String shareName,
308 final long timeout
309 ) throws TimeoutException, WindowsRemoteException {
310 try {
311 return windowsRemoteExecutor
312 .executeWql(String.format("SELECT Name,Path FROM Win32_Share WHERE Name = '%s'", shareName), timeout)
313 .stream()
314 .limit(1)
315 .map(row -> new WindowsTempShare(windowsRemoteExecutor, (String) row.get("Name"), (String) row.get("Path")))
316 .findFirst();
317 } catch (final WqlQuerySyntaxException e) {
318 throw new WindowsRemoteException(e);
319 }
320 }
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335 static WindowsTempShare createTempShare(
336 final WindowsRemoteExecutor windowsRemoteExecutor,
337 final String shareName,
338 final long timeout,
339 final ShareRemoteDirectoryConsumer<WindowsRemoteExecutor, String, String, Long> shareRemoteDirectory
340 ) throws WindowsRemoteException, TimeoutException {
341 final long start = Utils.getCurrentTimeMillis();
342
343
344 final String folder = getWindowsDirectory(windowsRemoteExecutor, timeout);
345
346
347 final String remotePath = buildRemotePath(folder, shareName);
348 createRemoteDirectory(
349 windowsRemoteExecutor,
350 remotePath,
351 TimeoutHelper.getRemainingTime(timeout, start, "No time left to create the temporary directory")
352 );
353
354
355 shareRemoteDirectory.apply(windowsRemoteExecutor, remotePath, shareName, timeout);
356
357 return new WindowsTempShare(windowsRemoteExecutor, shareName, remotePath);
358 }
359
360
361 public String getShareName() {
362 return shareName;
363 }
364
365
366 public String getUncSharePath() {
367 return uncSharePath;
368 }
369
370
371 public String getRemotePath() {
372 return remotePath;
373 }
374
375
376 public WindowsRemoteExecutor getWindowsRemoteExecutor() {
377 return windowsRemoteExecutor;
378 }
379 }