View Javadoc
1   package org.metricshub.winrm.wql;
2   
3   /*-
4    * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
5    * WinRM Java Client
6    * ჻჻჻჻჻჻
7    * Copyright 2023 - 2024 Metricshub
8    * ჻჻჻჻჻჻
9    * Licensed under the Apache License, Version 2.0 (the "License");
10   * you may not use this file except in compliance with the License.
11   * You may obtain a copy of the License at
12   *
13   *      http://www.apache.org/licenses/LICENSE-2.0
14   *
15   * Unless required by applicable law or agreed to in writing, software
16   * distributed under the License is distributed on an "AS IS" BASIS,
17   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18   * See the License for the specific language governing permissions and
19   * limitations under the License.
20   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
21   */
22  
23  import java.nio.file.Path;
24  import java.util.List;
25  import java.util.Map;
26  import java.util.concurrent.TimeoutException;
27  import java.util.stream.Collectors;
28  import org.metricshub.winrm.Utils;
29  import org.metricshub.winrm.WinRMHttpProtocolEnum;
30  import org.metricshub.winrm.WmiHelper;
31  import org.metricshub.winrm.exceptions.WinRMException;
32  import org.metricshub.winrm.exceptions.WqlQuerySyntaxException;
33  import org.metricshub.winrm.service.WinRMEndpoint;
34  import org.metricshub.winrm.service.WinRMService;
35  import org.metricshub.winrm.service.client.auth.AuthenticationEnum;
36  
37  public class WinRMWqlExecutor {
38  
39  	private final long executionTime;
40  	private final List<String> headers;
41  	private final List<List<String>> rows;
42  
43  	/**
44  	 * The WinRMWqlExecutor constructor
45  	 *
46  	 * @param executionTime The execution time in milliseconds
47  	 * @param headers The headers list
48  	 * @param rows The value rows list
49  	 */
50  	public WinRMWqlExecutor(final long executionTime, final List<String> headers, final List<List<String>> rows) {
51  		this.executionTime = executionTime;
52  		this.headers = headers;
53  		this.rows = rows;
54  	}
55  
56  	/**
57  	 * Get the execution time of the query.
58  	 * @return
59  	 */
60  	public long getExecutionTime() {
61  		return executionTime;
62  	}
63  
64  	/**
65  	 * Get the headers of the query.
66  	 * @return
67  	 */
68  	public List<String> getHeaders() {
69  		return headers;
70  	}
71  
72  	/**
73  	 * Get the result rows of the query.
74  	 * @return
75  	 */
76  	public List<List<String>> getRows() {
77  		return rows;
78  	}
79  
80  	/**
81  	 * Execute a WQL query and process its result.
82  	 *
83  	 * @param protocol The HTTP protocol (HTTP by default)
84  	 * @param hostname Host to connect to. (Mandatory)
85  	 * @param port The port (5985 for HTPP or 5986 for HTTPS by default)
86  	 * @param username The username name. (Mandatory)
87  	 * @param password The password
88  	 * @param namespace The namespace default value: {@value WmiHelper#DEFAULT_NAMESPACE}
89  	 * @param wqlQuery The WQL query (Mandatory)
90  	 * @param timeout The timeout in milliseconds (throws an IllegalArgumentException if negative or zero)
91  	 * @param ticketCache The Ticket Cache path
92  	 * @param authentications List of authentications. only NTLM if absent
93  	 *
94  	 * @return WinRMWqlExecutor result instance with header, rows and execution time.
95  	 *
96  	 * @throws WinRMException For any problem encountered on remote
97  	 * @throws WqlQuerySyntaxException On WQL syntax errors
98  	 * @throws TimeoutException To notify userName of timeout
99  	 */
100 	public static WinRMWqlExecutor executeWql(
101 		final WinRMHttpProtocolEnum protocol,
102 		final String hostname,
103 		final Integer port,
104 		final String username,
105 		final char[] password,
106 		final String namespace,
107 		final String wqlQuery,
108 		final long timeout,
109 		final Path ticketCache,
110 		final List<AuthenticationEnum> authentications
111 	) throws WinRMException, WqlQuerySyntaxException, TimeoutException {
112 		Utils.checkNonNull(wqlQuery, "wqlQuery");
113 		Utils.checkArgumentNotZeroOrNegative(timeout, "timeout");
114 
115 		final long start = Utils.getCurrentTimeMillis();
116 
117 		final WinRMEndpoint winRMEndpoint = new WinRMEndpoint(protocol, hostname, port, username, password, namespace);
118 
119 		try (
120 			final WinRMService winRMService = WinRMService.createInstance(
121 				winRMEndpoint,
122 				timeout,
123 				ticketCache,
124 				authentications
125 			)
126 		) {
127 			final List<Map<String, Object>> result = winRMService.executeWql(wqlQuery, timeout);
128 
129 			// Extract the list of properties from the result, with same order as in the WQL query
130 			final List<String> headers = WmiHelper.extractPropertiesFromResult(result, wqlQuery);
131 
132 			final List<List<String>> rows = result
133 				.stream()
134 				.map(row -> headers.stream().map(header -> (String) row.get(header)).collect(Collectors.toList()))
135 				.collect(Collectors.toList());
136 
137 			return new WinRMWqlExecutor(Utils.getCurrentTimeMillis() - start, headers, rows);
138 		}
139 	}
140 }