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

hazendaz / httpunit / 755

14 Feb 2026 07:14PM UTC coverage: 80.526%. Remained the same
755

push

github

hazendaz
[ci] Fix badge

3213 of 4105 branches covered (78.27%)

Branch coverage included in aggregate %.

8245 of 10124 relevant lines covered (81.44%)

0.81 hits per line

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

43.12
/src/main/java/com/meterware/httpunit/parsing/HTMLParserFactory.java
1
/*
2
 * SPDX-License-Identifier: MIT
3
 * See LICENSE file for details.
4
 *
5
 * Copyright 2000-2026 Russell Gold
6
 * Copyright 2021-2000 hazendaz
7
 */
8
package com.meterware.httpunit.parsing;
9

10
import java.lang.reflect.InvocationTargetException;
11
import java.util.ArrayList;
12
import java.util.List;
13

14
/**
15
 * Factory for creating HTML parsers. Parser customization properties can be specified but do not necessarily work for
16
 * every parser type.
17
 **/
18
public abstract class HTMLParserFactory {
×
19

20
    /** The listeners. */
21
    private static List<HTMLParserListener> _listeners = new ArrayList<>();
1✔
22

23
    /** The jtidy parser. */
24
    private static HTMLParser _jtidyParser;
25

26
    /** The neko parser. */
27
    private static HTMLParser _nekoParser;
28

29
    /** The html parser. */
30
    private static HTMLParser _htmlParser;
31

32
    /** The preserve tag case. */
33
    private static boolean _preserveTagCase;
34

35
    /** The return HTML document. */
36
    private static boolean _returnHTMLDocument;
37

38
    /** The parser warnings enabled. */
39
    private static boolean _parserWarningsEnabled;
40

41
    /** The force upper. */
42
    // for parsers that support forcing Case
43
    private static boolean _forceUpper;
44

45
    /** The force lower. */
46
    private static boolean _forceLower;
47

48
    /**
49
     * Resets all settings to their default values. This includes the parser selection.
50
     */
51
    public static void reset() {
52
        _preserveTagCase = false;
1✔
53
        _returnHTMLDocument = true;
1✔
54
        _parserWarningsEnabled = false;
1✔
55
        _htmlParser = null;
1✔
56
        _forceUpper = false;
1✔
57
        _forceLower = false;
1✔
58
        _listeners.clear();
1✔
59
    }
1✔
60

61
    /**
62
     * Selects the JTidy parser, if present.
63
     */
64
    public static void useJTidyParser() {
65
        if (_jtidyParser == null) {
×
66
            throw new RuntimeException("JTidy parser not available");
×
67
        }
68
        _htmlParser = _jtidyParser;
×
69
    }
×
70

71
    /**
72
     * Selects the NekoHTML parser, if present.
73
     */
74
    public static void useNekoHTMLParser() {
75
        if (_nekoParser == null) {
×
76
            throw new RuntimeException("NekoHTML parser not available");
×
77
        }
78
        _htmlParser = _nekoParser;
×
79
    }
×
80

81
    /**
82
     * Specifies the parser to use.
83
     *
84
     * @param htmlParser
85
     *            the new HTML parser
86
     */
87
    public static void setHTMLParser(HTMLParser htmlParser) {
88
        _htmlParser = htmlParser;
1✔
89
    }
1✔
90

91
    /**
92
     * Returns the current selected parser.
93
     *
94
     * @return the HTML parser
95
     */
96
    public static HTMLParser getHTMLParser() {
97
        if (_htmlParser == null) {
1✔
98
            if (_nekoParser != null) {
1!
99
                _htmlParser = _nekoParser;
1✔
100
            } else if (_jtidyParser != null) {
×
101
                _htmlParser = _jtidyParser;
×
102
            } else {
103
                throw new RuntimeException(
×
104
                        "No HTML parser found. Make sure that either nekoHTML.jar or Tidy.jar is in the in classpath");
105
            }
106
        }
107
        return _htmlParser;
1✔
108
    }
109

110
    /**
111
     * Returns true if the current parser will preserve the case of HTML tags and attributes.
112
     *
113
     * @return true, if is preserve tag case
114
     */
115
    public static boolean isPreserveTagCase() {
116
        return _preserveTagCase && getHTMLParser().supportsPreserveTagCase();
1!
117
    }
118

119
    /**
120
     * Specifies whether the parser should preserve the case of HTML tags and attributes. Not every parser can support
121
     * this capability. Note that enabling this will disable support for the HTMLDocument class. override any previous
122
     * behaviour configured by calling {@link #setForceUpperCase(boolean)} or {@link #setForceLowerCase(boolean)}
123
     *
124
     * @param preserveTagCase
125
     *            the new preserve tag case
126
     *
127
     * @see #setReturnHTMLDocument
128
     * @see #setForceUpperCase(boolean)
129
     * @see #setForceLowerCase(boolean)
130
     */
131
    public static void setPreserveTagCase(boolean preserveTagCase) {
132
        _preserveTagCase = preserveTagCase;
1✔
133
        if (preserveTagCase) {
1!
134
            _forceLower = false;
×
135
            _forceUpper = false;
×
136
        }
137
    }
1✔
138

139
    /**
140
     * Returns true if the current parser will return an HTMLDocument object rather than a Document object.
141
     *
142
     * @return true, if is return HTML document
143
     */
144
    public static boolean isReturnHTMLDocument() {
145
        return _returnHTMLDocument && !isPreserveTagCase() && getHTMLParser().supportsReturnHTMLDocument();
1!
146
    }
147

148
    /**
149
     * Specifies whether the parser should return an HTMLDocument object rather than a Document object. Not every parser
150
     * can support this capability. Note that enabling this will disable preservation of tag case. and/or the forcing of
151
     * the tag case to upper or lower case.
152
     *
153
     * @param returnHTMLDocument
154
     *            the new return HTML document
155
     *
156
     * @see #setPreserveTagCase
157
     * @see #setForceUpperCase(boolean)
158
     * @see #setForceLowerCase(boolean)
159
     */
160
    public static void setReturnHTMLDocument(boolean returnHTMLDocument) {
161
        _returnHTMLDocument = returnHTMLDocument;
×
162
        if (returnHTMLDocument) {
×
163
            _preserveTagCase = false;
×
164
            _forceLower = false;
×
165
            _forceUpper = false;
×
166
        }
167
    }
×
168

169
    /**
170
     * Specifies whether the parser should force the case of HTML tags and attributes to be upper case. Not every parser
171
     * can support this capability. Note that enabling this will disable support for the HTMLDocument class and override
172
     * any previous behaviour configured by enabling {@link #setPreserveTagCase(boolean)} or
173
     * {@link #setForceLowerCase(boolean)}
174
     *
175
     * @param forceUpper
176
     *            boolean indicating whether to enable this functionality
177
     *
178
     * @see #setReturnHTMLDocument
179
     * @see #setPreserveTagCase(boolean)
180
     * @see #setForceLowerCase(boolean)
181
     */
182
    public static void setForceUpperCase(boolean forceUpper) {
183
        _forceUpper = forceUpper;
×
184
        if (_forceUpper) {
×
185
            _forceLower = false;
×
186
            _preserveTagCase = false;
×
187
            // _returnHTMLDocument = false;
188
        }
189
    }
×
190

191
    /**
192
     * Return true if the current parser will support forcing the tags and attributes to upper case.
193
     *
194
     * @return boolean flag
195
     */
196
    public static boolean getForceUpperCase() {
197
        return _forceUpper && getHTMLParser().supportsPreserveTagCase();
1!
198
    }
199

200
    /**
201
     * Specifies whether the parser should force the case of HTML tags and attributes to lower case. Not every parser
202
     * can support this capability. Note that enabling this will disable support for the HTMLDocument class and override
203
     * any previous behaviour configured by enabling {@link #setPreserveTagCase(boolean)} or
204
     * {@link #setForceUpperCase(boolean)}
205
     *
206
     * @param forceLower
207
     *            boolean indicating whether to enable this functionality
208
     *
209
     * @see #setReturnHTMLDocument
210
     * @see #setPreserveTagCase(boolean)
211
     * @see #setForceUpperCase(boolean)
212
     */
213
    public static void setForceLowerCase(boolean forceLower) {
214
        _forceLower = forceLower;
×
215
        if (_forceLower) {
×
216
            _forceUpper = false;
×
217
            _preserveTagCase = false;
×
218
            // _returnHTMLDocument = false;
219
        }
220
    }
×
221

222
    /**
223
     * Return true if the current parser will support forcing the tags and attributes to lower case.
224
     *
225
     * @return boolean flag
226
     */
227
    public static boolean getForceLowerCase() {
228
        return _forceLower && getHTMLParser().supportsPreserveTagCase();
1!
229
    }
230

231
    /**
232
     * Returns true if parser warnings are enabled.
233
     *
234
     * @return true, if is parser warnings enabled
235
     */
236
    public static boolean isParserWarningsEnabled() {
237
        return _parserWarningsEnabled && getHTMLParser().supportsParserWarnings();
1!
238
    }
239

240
    /**
241
     * If true, tells the parser to display warning messages. The default is false (warnings are not shown).
242
     *
243
     * @param enabled
244
     *            the new parser warnings enabled
245
     */
246
    public static void setParserWarningsEnabled(boolean enabled) {
247
        _parserWarningsEnabled = enabled;
1✔
248
    }
1✔
249

250
    /**
251
     * Remove an HTML Parser listener.
252
     *
253
     * @param el
254
     *            the el
255
     */
256
    public static void removeHTMLParserListener(HTMLParserListener el) {
257
        _listeners.remove(el);
1✔
258
    }
1✔
259

260
    /**
261
     * Add an HTML Parser listener.
262
     *
263
     * @param el
264
     *            the el
265
     */
266
    public static void addHTMLParserListener(HTMLParserListener el) {
267
        _listeners.add(el);
1✔
268
    }
1✔
269

270
    // ------------------------------------- package protected members
271
    // ------------------------------------------------------
272

273
    /**
274
     * Get the list of Html Error Listeners.
275
     *
276
     * @return the HTML parser listeners
277
     */
278
    static List<HTMLParserListener> getHTMLParserListeners() {
279
        return _listeners;
1✔
280
    }
281

282
    /**
283
     * Load parser if supported.
284
     *
285
     * @param testClassName
286
     *            the test class name
287
     * @param parserClassName
288
     *            the parser class name
289
     *
290
     * @return the HTML parser
291
     */
292
    private static HTMLParser loadParserIfSupported(final String testClassName, final String parserClassName) {
293
        try {
294
            Class.forName(testClassName);
1✔
295
            return (HTMLParser) Class.forName(parserClassName).getDeclaredConstructor().newInstance();
1✔
296
        } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException
×
297
                | NoSuchMethodException | SecurityException | ClassNotFoundException e) {
298
            e.printStackTrace();
×
299
        }
300
        return null;
×
301
    }
302

303
    static {
304
        _jtidyParser = loadParserIfSupported("org.w3c.tidy.Parser", "com.meterware.httpunit.parsing.JTidyHTMLParser");
1✔
305
        _nekoParser = loadParserIfSupported("net.sourceforge.htmlunit.cyberneko.HTMLConfiguration",
1✔
306
                "com.meterware.httpunit.parsing.NekoHTMLParser");
307
        reset();
1✔
308
    }
1✔
309

310
}
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