1 package org.metricshub.wmi.windows.remote;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.io.IOException;
24 import java.nio.charset.Charset;
25 import java.nio.charset.StandardCharsets;
26 import java.nio.file.Files;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.nio.file.StandardCopyOption;
30 import java.nio.file.attribute.FileTime;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import java.util.Objects;
36 import java.util.concurrent.TimeoutException;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
39 import org.metricshub.wmi.Utils;
40 import org.metricshub.wmi.exceptions.WindowsRemoteException;
41 import org.metricshub.wmi.exceptions.WqlQuerySyntaxException;
42
43 public class WindowsRemoteProcessUtils {
44
45 private WindowsRemoteProcessUtils() {}
46
47 private static final String DEFAULT_CODESET = "1252";
48 private static final Charset DEFAULT_CHARSET = Charset.forName("windows-1252");
49
50
51
52
53
54
55
56
57
58 private static final Map<String, Charset> CODESET_MAP;
59
60 static {
61 final Map<String, Charset> map = new HashMap<>();
62 addToCharsetMap(map, "1250", "windows-1250");
63 addToCharsetMap(map, "1251", "windows-1251");
64 map.put("1252", DEFAULT_CHARSET);
65 addToCharsetMap(map, "1253", "windows-1253");
66 addToCharsetMap(map, "1254", "windows-1254");
67 addToCharsetMap(map, "1255", "windows-1255");
68 addToCharsetMap(map, "1256", "windows-1256");
69 addToCharsetMap(map, "1257", "windows-1257");
70 addToCharsetMap(map, "1258", "windows-1258");
71 addToCharsetMap(map, "874", "x-windows-874");
72 addToCharsetMap(map, "932", "Shift_JIS");
73 addToCharsetMap(map, "936", "GBK");
74 if (!addToCharsetMap(map, "949", "EUC-KR")) {
75 addToCharsetMap(map, "949", "x-windows-949");
76 }
77 if (!addToCharsetMap(map, "950", "Big5")) {
78 addToCharsetMap(map, "950", "x-windows-950");
79 }
80 addToCharsetMap(map, "951", "Big5-HKSCS");
81 map.put("28591", StandardCharsets.ISO_8859_1);
82 map.put("20127", StandardCharsets.US_ASCII);
83 map.put("65001", StandardCharsets.UTF_8);
84 map.put("1200", StandardCharsets.UTF_16LE);
85 map.put("1201", StandardCharsets.UTF_16BE);
86
87 CODESET_MAP = Collections.unmodifiableMap(map);
88 }
89
90
91
92
93
94
95
96
97
98
99 private static boolean addToCharsetMap(Map<String, Charset> map, String key, String charsetName) {
100 if (Charset.isSupported(charsetName)) {
101 map.put(key, Charset.forName(charsetName));
102 return true;
103 }
104 return false;
105 }
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120 public static Charset getWindowsEncodingCharset(
121 final WindowsRemoteExecutor windowsRemoteExecutor,
122 final long timeout
123 ) throws TimeoutException, WqlQuerySyntaxException, WindowsRemoteException {
124 if (windowsRemoteExecutor == null || timeout < 1) {
125 return DEFAULT_CHARSET;
126 }
127
128 final List<Map<String, Object>> result = windowsRemoteExecutor.executeWql(
129 "SELECT CodeSet FROM Win32_OperatingSystem",
130 timeout
131 );
132
133 final String codeSet = result
134 .stream()
135 .map(row -> (String) row.get("CodeSet"))
136 .filter(Objects::nonNull)
137 .findFirst()
138 .orElse(DEFAULT_CODESET);
139
140 return CODESET_MAP.getOrDefault(codeSet, DEFAULT_CHARSET);
141 }
142
143
144
145
146
147
148 public static String buildNewOutputFileName() {
149 return String.format(
150 "SEN_%s_%d_%d",
151 Utils.getComputerName(),
152 Utils.getCurrentTimeMillis(),
153 (long) (Math.random() * 1000000)
154 );
155 }
156
157
158
159
160
161
162
163
164
165
166
167 public static String copyLocalFilesToShare(
168 final String command,
169 final List<String> localFiles,
170 final String uncSharePath,
171 final String remotePath
172 ) throws IOException {
173 Utils.checkNonNull(command, "command");
174
175 if (localFiles == null || localFiles.isEmpty()) {
176 return command;
177 }
178
179 Utils.checkNonNull(uncSharePath, "uncSharePath");
180 Utils.checkNonNull(remotePath, "remotePath");
181
182 try {
183 return localFiles
184 .stream()
185 .reduce(
186 command,
187 (cmd, localFile) -> {
188 try {
189 final Path localFilePath = Paths.get(localFile);
190 final Path remoteFilePath = copyToShare(localFilePath, uncSharePath, remotePath);
191
192 return caseInsensitiveReplace(cmd, localFile, remoteFilePath.toString());
193 } catch (final IOException e) {
194 throw new RuntimeException(e);
195 }
196 }
197 );
198 } catch (final Exception e) {
199 if (e.getCause() instanceof IOException) {
200 throw (IOException) e.getCause();
201 }
202 throw e;
203 }
204 }
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 static Path copyToShare(final Path localFilePath, final String uncSharePath, final String remotePath)
220 throws IOException {
221 final Path targetUncPath = Paths.get(uncSharePath, localFilePath.getFileName().toString());
222 final Path targetRemotePath = Paths.get(remotePath, localFilePath.getFileName().toString());
223
224 if (Files.exists(targetUncPath)) {
225 final FileTime sourceFileTime = Files.getLastModifiedTime(localFilePath);
226 final FileTime targetFileTime = Files.getLastModifiedTime(targetUncPath);
227 if (sourceFileTime.compareTo(targetFileTime) <= 0) {
228
229 return targetRemotePath;
230 }
231 }
232
233
234 Files.copy(localFilePath, targetUncPath, StandardCopyOption.COPY_ATTRIBUTES, StandardCopyOption.REPLACE_EXISTING);
235
236
237 return targetRemotePath;
238 }
239
240
241
242
243
244
245
246
247
248
249
250
251
252 static String caseInsensitiveReplace(final String string, final String target, final String replacement) {
253 return string == null || target == null
254 ? string
255 : Pattern
256 .compile(target, Pattern.LITERAL | Pattern.CASE_INSENSITIVE)
257 .matcher(string)
258 .replaceAll(Matcher.quoteReplacement(replacement == null ? Utils.EMPTY : replacement));
259 }
260 }