Blame view

src/main/java/pl/labno/bernard/htmlunified/WebClientUtils.java 5.42 KB
bernard authored
1 2 3
package pl.labno.bernard.htmlunified;

import com.gargoylesoftware.htmlunit.WebClient;
bernard authored
4
import com.gargoylesoftware.htmlunit.html.DomNode;
bernard authored
5 6
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
bernard authored
7
import com.gargoylesoftware.htmlunit.html.HtmlPage;
bernard authored
8 9
import com.gargoylesoftware.htmlunit.html.HtmlTableCell;
bernard authored
10
import java.util.ArrayList;
bernard authored
11
import java.util.HashMap;
bernard authored
12
import java.util.List;
bernard authored
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
import java.util.Map;

public class WebClientUtils {

    private static long defaultCheckInterval = 500;
    private static long defaultTimeout = 10000;

    public static long getDefaultCheckInterval() {
        return defaultCheckInterval;
    }

    public static void setDefaultCheckInterval(long defaultCheckInterval) {
        WebClientUtils.defaultCheckInterval = defaultCheckInterval;
    }

    public static long getDefaultTimeout() {
        return defaultTimeout;
    }

    public static void setDefaultTimeout(long defaultTimeout) {
        WebClientUtils.defaultTimeout = defaultTimeout;
    }
bernard authored
36 37
    public static int waitForJSJob(String message, WebClient webClient) {
        return waitForJSJob(message, webClient, webClient.waitForBackgroundJavaScript(10) - 1);
bernard authored
38 39
    }
bernard authored
40 41
    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount) {
        return waitForJSJob(message, webClient, initialJobCount, defaultTimeout);
bernard authored
42 43
    }
bernard authored
44 45
    public static int waitForJSJob(WebClient webClient, int initialJobCount, int timeout) {
        return waitForJSJob(null, webClient, initialJobCount, timeout);
bernard authored
46 47
    }
bernard authored
48 49 50 51 52 53 54 55 56
    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, long timeout) {
        return waitForJSJob(message, webClient, initialJobCount, timeout, defaultCheckInterval);
    }

    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, int timeout) {
        return waitForJSJob(message, webClient, initialJobCount, timeout, defaultCheckInterval);
    }

    public static int waitForJSJob(String message, WebClient webClient, int initialJobCount, long timeout, long checkInterval) {
bernard authored
57 58 59 60 61
        int jobs;
        long startTime = System.currentTimeMillis();
        do {
            jobs = webClient.waitForBackgroundJavaScript(checkInterval);
            if (startTime + timeout < System.currentTimeMillis()) {
bernard authored
62
                throw new RuntimeException("Number of JavaScript jobs doesn't drop to initial level for " + timeout + " seconds. It's memory leak in your JavaScript rather then request taking so long!");
bernard authored
63 64
            }
        } while (jobs > initialJobCount);
bernard authored
65
        System.out.println("Waiting" + (message == null ? "" : " for " + message) + " took: " + (System.currentTimeMillis() - startTime) + "ms");
bernard authored
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
        return jobs;
    }

    /**
     * Returns list of suggestions from rich:suggestionBox
     *
     * @param suggestion suggestionBox element
     * @param column     column of suggestionBox to extract text from
     * @return list of suggestions
     */
    public static Map<String, HtmlTableCell> getSuggestions(HtmlElement suggestion, int column) {
        final Map<String, HtmlTableCell> suggestions = new HashMap<String, HtmlTableCell>();
        final HtmlElement suggestElement = suggestion.getElementById(suggestion.getId() + ":suggest");
        @SuppressWarnings("unchecked")
        final DomNodeList<HtmlElement> suggestionRows = suggestElement.getElementsByTagName("tr");
        for (HtmlElement row : suggestionRows) {
            @SuppressWarnings("unchecked")
            final DomNodeList<HtmlElement> cells = row.getElementsByTagName("td");
            final HtmlTableCell cell = (HtmlTableCell) cells.get(column + 1);
            suggestions.put(cell.asText(), cell);
        }
        return suggestions;
    }
bernard authored
89 90 91 92 93 94 95 96 97 98 99 100 101 102

    public static void forceWait(int timeout) {
        final long startTime = System.currentTimeMillis();
        do {
            try {
                final long millis = startTime + timeout - System.currentTimeMillis();
                if (millis > 0) {
                    Thread.sleep(millis);
                }
            } catch (InterruptedException ignore) {
            } catch (IllegalArgumentException ignore) {
            }
        } while (startTime + timeout > System.currentTimeMillis());
    }
bernard authored
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130

    public static void executeAjaxReRenderedScripts(HtmlPage page) {
        final DomNodeList<HtmlElement> scripts = page.getElementsByTagName("script");
        /**
         * We cannot iterate over html DomNodeList cause it depends on sibling relationship which we will modify.
         */
        final List<HtmlElement> scriptsList = new ArrayList<HtmlElement>();
        for (HtmlElement element : scripts) {
            scriptsList.add(element);
        }
        for (HtmlElement element : scriptsList) {
            if (element.getChildNodes().size() > 1) {
                element.removeChild(element.getFirstChild());
                final DomNode sibling = element.getNextSibling();
                final DomNode parentNode = element.getParentNode();
                /**
                 * Script will be executed upon inserting into DOM tree, so we removed and add it again.
                 */
                if (sibling != null) {
                    parentNode.removeChild(element);
                    sibling.insertBefore(element);
                } else {
                    parentNode.removeChild(element);
                    parentNode.appendChild(element);
                }
            }
        }
    }
bernard authored
131
}