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