View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.general;
16  
17  import static java.nio.charset.StandardCharsets.ISO_8859_1;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.util.Arrays;
22  import java.util.HashSet;
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.Locale;
26  import java.util.Set;
27  
28  import org.apache.commons.io.FileUtils;
29  import org.htmlunit.BrowserVersion;
30  import org.htmlunit.ProxyConfig;
31  import org.htmlunit.WebClient;
32  import org.htmlunit.html.HtmlElement;
33  import org.htmlunit.html.HtmlPage;
34  
35  /**
36   * Ensures all defined Host classes in internet references (e.g. Mozilla Developer Network)
37   * are defined in {@link HostClassNameTest}.
38   *
39   * @author Ahmed Ashour
40   */
41  public final class HostExtractor {
42  
43      /**
44       * Tests known prefixes.
45       */
46      public static final List<String> PREFIXES_ = Arrays.asList("HTML", "DOM", "SVG", "CSS", "JSON",
47              "URL", "URI", "TCP", "RTC", "IDB", "MIDI", "VR", "SIMD");
48  
49      private HostExtractor() {
50      }
51  
52      /**
53       * The entry point.
54       * @param args optional proxy hostname and port
55       * @throws Exception if an error occurs
56       */
57      public static void main(final String[] args) throws Exception {
58          final Set<String> set = new HashSet<>();
59          try (WebClient webClient = new WebClient(BrowserVersion.CHROME)) {
60              if (args.length > 1) {
61                  final ProxyConfig proxyConfig = new ProxyConfig(args[0], Integer.parseInt(args[1]), null);
62                  proxyConfig.addHostsToProxyBypass("localhost");
63                  webClient.getOptions().setProxyConfig(proxyConfig);
64              }
65              fillMDNWebAPI(webClient, set);
66              fillMDNJavaScriptGlobalObjects(webClient, set);
67              final String testRoot = "src/test/java/";
68              ensure(new File(testRoot + HostClassNameTest.class.getName().replace('.', '/') + ".java"), set);
69          }
70      }
71  
72      private static void fillMDNWebAPI(final WebClient webClient, final Set<String> set) throws Exception {
73          final HtmlPage page = webClient.getPage("https://developer.mozilla.org/en-US/docs/Web/API");
74          for (final Object o : page.getByXPath("//*[@class='indexListTerm']")) {
75              set.add(((HtmlElement) o).asNormalizedText());
76          }
77      }
78  
79      private static void fillMDNJavaScriptGlobalObjects(final WebClient webClient, final Set<String> set)
80          throws Exception {
81          final HtmlPage page
82              = webClient.getPage("https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects");
83          for (final Object o : page.getByXPath("//*[name()='code']/text()")) {
84              String value = o.toString();
85              if (!value.isEmpty()) {
86                  if (value.endsWith("()")) {
87                      value = value.substring(0, value.length() - 2);
88                  }
89  
90                  set.add(value);
91              }
92          }
93      }
94  
95      private static void ensure(final File file, final Set<String> set) throws IOException {
96          final Set<String> unusedNames = new HashSet<>(set);
97          final List<String> lines = FileUtils.readLines(file, ISO_8859_1);
98          for (final String line : lines) {
99              for (final Iterator<String> it = unusedNames.iterator(); it.hasNext();) {
100                 if (line.contains("(\"" + it.next() + "\")")) {
101                     it.remove();
102                 }
103             }
104         }
105         unusedNames.remove("this");
106         unusedNames.remove("Boolean");
107         unusedNames.remove("null");
108 
109         if (!unusedNames.isEmpty()) {
110             for (final String name : unusedNames) {
111                 if (name.contains(" ")) {
112                     continue;
113                 }
114                 System.out.println("");
115                 System.out.println("    /**");
116                 System.out.println("     * @throws Exception if the test fails");
117                 System.out.println("     */");
118                 System.out.println("    @Test");
119                 System.out.println("    @Alerts(\"exception\")");
120                 String methodName = name;
121                 for (final String prefix : PREFIXES_) {
122                     if (methodName.startsWith(prefix)) {
123                         methodName = prefix.toLowerCase(Locale.ROOT) + methodName.substring(prefix.length());
124                         break;
125                     }
126                 }
127                 if (Character.isUpperCase(methodName.charAt(0))) {
128                     methodName = Character.toLowerCase(methodName.charAt(0)) + methodName.substring(1);
129                 }
130                 methodName = methodName.replace(".", "_");
131                 System.out.println("    public void " + methodName + "() throws Exception {");
132                 System.out.println("        test(\"" + name + "\");");
133                 System.out.println("    }");
134             }
135         }
136         for (final String name : unusedNames) {
137             if (name.contains(" ")) {
138                 System.out.println("Ignoring: " + name);
139             }
140         }
141     }
142 }