• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Waffle / waffle / 6364

01 Feb 2026 02:07AM UTC coverage: 46.217%. Remained the same
6364

push

github

web-flow
Merge pull request #3206 from Waffle/renovate/checkstyle.version

Update dependency com.puppycrawl.tools:checkstyle to v13.1.0

276 of 734 branches covered (37.6%)

Branch coverage included in aggregate %.

1019 of 2068 relevant lines covered (49.27%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

52.83
/Source/JNA/waffle-jna/src/main/java/waffle/util/WaffleInfo.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2010-2026 The Waffle Project Contributors: https://github.com/Waffle/waffle/graphs/contributors
6
 */
7
package waffle.util;
8

9
import com.sun.jna.Platform;
10
import com.sun.jna.platform.WindowUtils;
11
import com.sun.jna.platform.win32.LMJoin;
12
import com.sun.jna.platform.win32.Netapi32Util;
13
import com.sun.jna.platform.win32.Win32Exception;
14

15
import java.awt.Desktop;
16
import java.io.File;
17
import java.io.IOException;
18
import java.io.StringWriter;
19
import java.nio.charset.StandardCharsets;
20
import java.nio.file.Files;
21
import java.nio.file.StandardOpenOption;
22
import java.util.ArrayList;
23
import java.util.Arrays;
24
import java.util.List;
25

26
import javax.xml.XMLConstants;
27
import javax.xml.parsers.DocumentBuilderFactory;
28
import javax.xml.parsers.ParserConfigurationException;
29
import javax.xml.transform.OutputKeys;
30
import javax.xml.transform.Transformer;
31
import javax.xml.transform.TransformerException;
32
import javax.xml.transform.TransformerFactory;
33
import javax.xml.transform.dom.DOMSource;
34
import javax.xml.transform.stream.StreamResult;
35

36
import org.slf4j.Logger;
37
import org.slf4j.LoggerFactory;
38
import org.w3c.dom.Document;
39
import org.w3c.dom.Element;
40

41
import waffle.windows.auth.IWindowsAccount;
42
import waffle.windows.auth.IWindowsAuthProvider;
43
import waffle.windows.auth.IWindowsComputer;
44
import waffle.windows.auth.IWindowsDomain;
45
import waffle.windows.auth.impl.WindowsAccountImpl;
46
import waffle.windows.auth.impl.WindowsAuthProviderImpl;
47

48
/**
49
 * A Utility class to read system info to help troubleshoot WAFFLE system configuration.
50
 *
51
 * <pre>
52
 * This utility class collects system information and returns it as an XML document.
53
 * </pre>
54
 * <p>
55
 * From the command line, you can write the info to stdout using:
56
 *
57
 * <pre>
58
 * <code>
59
 *   java -cp "jna.jar;waffle-core.jar;waffle-api.jar;jna-platform.jar;guava-21.0.jar" waffle.util.WaffleInfo
60
 * </code>
61
 * </pre>
62
 * <p>
63
 * To show this information in a browser, run:
64
 *
65
 * <pre>
66
 * <code>
67
 *   java -cp "..." waffle.util.WaffleInfo -show
68
 * </code>
69
 * </pre>
70
 * <p>
71
 * To lookup account names and return any listed info, run:
72
 *
73
 * <pre>
74
 * <code>
75
 *   java -cp "..." waffle.util.WaffleInfo -lookup AccountName
76
 * </code>
77
 * </pre>
78
 */
79
public class WaffleInfo {
2✔
80

81
    /** The Constant LOGGER. */
82
    private static final Logger LOGGER = LoggerFactory.getLogger(WaffleInfo.class);
2✔
83

84
    /**
85
     * Get a Document with basic system information.
86
     * <p>
87
     * This uses the builtin javax.xml package even though the API is quite verbose
88
     *
89
     * @return Document with waffle info.
90
     *
91
     * @throws ParserConfigurationException
92
     *             when getting new document builder.
93
     */
94
    public Document getWaffleInfo() throws ParserConfigurationException {
95
        final DocumentBuilderFactory df = DocumentBuilderFactory.newInstance();
2✔
96
        df.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
2✔
97
        df.setAttribute(XMLConstants.ACCESS_EXTERNAL_SCHEMA, "");
2✔
98
        df.setExpandEntityReferences(false);
2✔
99

100
        final Document doc = df.newDocumentBuilder().newDocument();
2✔
101

102
        // create the root element and add it to the document
103
        final Element root = doc.createElement("waffle");
2✔
104

105
        // Add Version Information as attributes
106
        String version = WaffleInfo.class.getPackage().getImplementationVersion();
2✔
107
        if (version != null) {
2!
108
            root.setAttribute("version", version);
×
109
        }
110
        version = Platform.class.getPackage().getImplementationVersion();
2✔
111
        if (version != null) {
2!
112
            root.setAttribute("jna", version);
2✔
113
        }
114
        version = WindowUtils.class.getPackage().getImplementationVersion();
2✔
115
        if (version != null) {
2!
116
            root.setAttribute("jna-platform", version);
2✔
117
        }
118

119
        doc.appendChild(root);
2✔
120
        root.appendChild(this.getAuthProviderInfo(doc));
2✔
121

122
        return doc;
2✔
123
    }
124

125
    /**
126
     * Gets the auth provider info.
127
     *
128
     * @param doc
129
     *            the doc
130
     *
131
     * @return the auth provider info
132
     */
133
    protected Element getAuthProviderInfo(final Document doc) {
134
        final IWindowsAuthProvider auth = new WindowsAuthProviderImpl();
2✔
135

136
        final Element node = doc.createElement("auth");
2✔
137
        node.setAttribute("class", auth.getClass().getName());
2✔
138

139
        // Current User
140
        Element child = doc.createElement("currentUser");
2✔
141
        node.appendChild(child);
2✔
142

143
        final String currentUsername = WindowsAccountImpl.getCurrentUsername();
2✔
144
        this.addAccountInfo(doc, child, new WindowsAccountImpl(currentUsername));
2✔
145

146
        // Computer
147
        child = doc.createElement("computer");
2✔
148
        node.appendChild(child);
2✔
149

150
        final IWindowsComputer c = auth.getCurrentComputer();
2✔
151
        Element value = doc.createElement("computerName");
2✔
152
        value.setTextContent(c.getComputerName());
2✔
153
        child.appendChild(value);
2✔
154

155
        value = doc.createElement("memberOf");
2✔
156
        value.setTextContent(c.getMemberOf());
2✔
157
        child.appendChild(value);
2✔
158

159
        value = doc.createElement("joinStatus");
2✔
160
        value.setTextContent(c.getJoinStatus());
2✔
161
        child.appendChild(value);
2✔
162

163
        value = doc.createElement("groups");
2✔
164
        Element g;
165
        for (final String s : c.getGroups()) {
2✔
166
            g = doc.createElement("group");
2✔
167
            g.setTextContent(s);
2✔
168
            value.appendChild(g);
2✔
169
        }
170
        child.appendChild(value);
2✔
171

172
        // Only Show Domains if we are in a Domain
173
        if (Netapi32Util.getJoinStatus() == LMJoin.NETSETUP_JOIN_STATUS.NetSetupDomainName) {
2!
174
            child = doc.createElement("domains");
×
175
            node.appendChild(child);
×
176

177
            Element d;
178
            for (final IWindowsDomain domain : auth.getDomains()) {
×
179
                d = doc.createElement("domain");
×
180
                node.appendChild(d);
×
181

182
                value = doc.createElement("FQN");
×
183
                value.setTextContent(domain.getFqn());
×
184
                child.appendChild(value);
×
185

186
                value = doc.createElement("TrustTypeString");
×
187
                value.setTextContent(domain.getTrustTypeString());
×
188
                child.appendChild(value);
×
189

190
                value = doc.createElement("TrustDirectionString");
×
191
                value.setTextContent(domain.getTrustDirectionString());
×
192
                child.appendChild(value);
×
193
            }
194
        }
195
        return node;
2✔
196
    }
197

198
    /**
199
     * Adds the account info.
200
     *
201
     * @param doc
202
     *            the doc
203
     * @param node
204
     *            the node
205
     * @param account
206
     *            the account
207
     */
208
    protected void addAccountInfo(final Document doc, final Element node, final IWindowsAccount account) {
209
        Element value = doc.createElement("Name");
2✔
210
        value.setTextContent(account.getName());
2✔
211
        node.appendChild(value);
2✔
212

213
        value = doc.createElement("FQN");
2✔
214
        value.setTextContent(account.getFqn());
2✔
215
        node.appendChild(value);
2✔
216

217
        value = doc.createElement("Domain");
2✔
218
        value.setTextContent(account.getDomain());
2✔
219
        node.appendChild(value);
2✔
220

221
        value = doc.createElement("SID");
2✔
222
        value.setTextContent(account.getSidString());
2✔
223
        node.appendChild(value);
2✔
224
    }
2✔
225

226
    /**
227
     * Gets the lookup info.
228
     *
229
     * @param doc
230
     *            the doc
231
     * @param lookup
232
     *            the lookup
233
     *
234
     * @return the lookup info
235
     */
236
    public Element getLookupInfo(final Document doc, final String lookup) {
237
        final IWindowsAuthProvider auth = new WindowsAuthProviderImpl();
2✔
238
        final Element node = doc.createElement("lookup");
2✔
239
        node.setAttribute("name", lookup);
2✔
240
        try {
241
            this.addAccountInfo(doc, node, auth.lookupAccount(lookup));
2✔
242
        } catch (final Win32Exception e) {
2✔
243
            node.appendChild(WaffleInfo.getException(doc, e));
2✔
244
        }
2✔
245
        return node;
2✔
246
    }
247

248
    /**
249
     * Gets the exception.
250
     *
251
     * @param doc
252
     *            the doc
253
     * @param t
254
     *            the t
255
     *
256
     * @return the exception
257
     */
258
    public static Element getException(final Document doc, final Exception t) {
259
        final Element node = doc.createElement("exception");
2✔
260
        node.setAttribute("class", t.getClass().getName());
2✔
261

262
        Element value = doc.createElement("message");
2✔
263
        if (t.getMessage() != null) {
2!
264
            value.setTextContent(t.getMessage());
2✔
265
            node.appendChild(value);
2✔
266
        }
267

268
        value = doc.createElement("trace");
2✔
269
        value.setTextContent(Arrays.toString(t.getStackTrace()));
2✔
270
        node.appendChild(value);
2✔
271
        return node;
2✔
272
    }
273

274
    /**
275
     * To pretty xml.
276
     *
277
     * @param doc
278
     *            the doc
279
     *
280
     * @return the string
281
     *
282
     * @throws TransformerException
283
     *             the transformer exception
284
     */
285
    public static String toPrettyXML(final Document doc) throws TransformerException {
286
        // set up a transformer
287
        final TransformerFactory transfac = TransformerFactory.newInstance();
×
288
        transfac.setAttribute(XMLConstants.ACCESS_EXTERNAL_DTD, "");
×
289
        transfac.setAttribute(XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "");
×
290

291
        final Transformer trans = transfac.newTransformer();
×
292
        trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
×
293
        trans.setOutputProperty(OutputKeys.INDENT, "yes");
×
294

295
        // create string from xml tree
296
        final StringWriter sw = new StringWriter();
×
297
        final StreamResult result = new StreamResult(sw);
×
298
        final DOMSource source = new DOMSource(doc);
×
299
        trans.transform(source, result);
×
300
        return sw.toString();
×
301
    }
302

303
    /**
304
     * Print system information.
305
     *
306
     * @param args
307
     *            variable arguments to pass to main. Valid values are "-show" and "-lookup".
308
     */
309
    public static void main(final String[] args) {
310
        boolean show = false;
×
311
        final List<String> lookup = new ArrayList<>();
×
312
        if (args != null) {
×
313
            String arg;
314
            for (int i = 0; i < args.length; i++) {
×
315
                arg = args[i];
×
316
                if (null != arg) {
×
317
                    switch (arg) {
×
318
                        case "-show":
319
                            show = true;
×
320
                            break;
×
321
                        case "-lookup":
322
                            lookup.add(args[++i]);
×
323
                            break;
×
324
                        default:
325
                            WaffleInfo.LOGGER.error("Unknown Argument: {}", arg);
×
326
                            throw new RuntimeException("Unknown Argument: " + arg);
×
327
                    }
328
                }
329
            }
330
        }
331

332
        final WaffleInfo helper = new WaffleInfo();
×
333
        try {
334
            final Document info = helper.getWaffleInfo();
×
335
            for (final String name : lookup) {
×
336
                info.getDocumentElement().appendChild(helper.getLookupInfo(info, name));
×
337
            }
×
338

339
            final String xml = WaffleInfo.toPrettyXML(info);
×
340
            final File f;
341
            if (show) {
×
342
                f = Files.createTempFile("waffle-info-", ".xml").toFile();
×
343
                Files.write(f.toPath(), xml.getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
×
344
                Desktop.getDesktop().open(f);
×
345
            } else {
346
                WaffleInfo.LOGGER.info(xml);
×
347
            }
348
        } catch (final IOException | TransformerException | ParserConfigurationException e) {
×
349
            WaffleInfo.LOGGER.error(e.getMessage());
×
350
            WaffleInfo.LOGGER.trace("", e);
×
351
        }
×
352
    }
×
353
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc