All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.googlecode.gwt.test.internal.patchers.dom.DocumentPatcher Maven / Gradle / Ivy

There is a newer version: 0.63
Show newest version
package com.googlecode.gwt.test.internal.patchers.dom;

import com.google.gwt.dom.client.*;
import com.googlecode.gwt.test.exceptions.GwtTestConfigurationException;
import com.googlecode.gwt.test.exceptions.GwtTestDomException;
import com.googlecode.gwt.test.exceptions.GwtTestException;
import com.googlecode.gwt.test.internal.AfterTestCallback;
import com.googlecode.gwt.test.internal.AfterTestCallbackManager;
import com.googlecode.gwt.test.internal.GwtConfig;
import com.googlecode.gwt.test.internal.utils.DoubleMap;
import com.googlecode.gwt.test.internal.utils.GwtHtmlParser;
import com.googlecode.gwt.test.internal.utils.JsoUtils;
import com.googlecode.gwt.test.patchers.PatchClass;
import com.googlecode.gwt.test.patchers.PatchMethod;
import com.googlecode.gwt.test.utils.GwtReflectionUtils;
import com.googlecode.gwt.test.utils.JavaScriptObjects;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

@PatchClass(Document.class)
class DocumentPatcher {

    private static class DocumentHolder implements AfterTestCallback {

        private Document document;

        private DocumentHolder() {
            AfterTestCallbackManager.get().registerFinalCallback(this);
        }

        public void afterTest() throws Throwable {
            document = null;

            Class documentClass = Class.forName("com.google.gwt.dom.client.Document$");
            GwtReflectionUtils.setStaticField(documentClass, "doc", null);
        }
    }

    private static final String DOCUMENT_ELEMENT = "documentElement";

    private static DocumentHolder DOCUMENT_HOLDER = new DocumentHolder();

    private static final String EMPTY_HTML = "";

    private static final DoubleMap HTML_ELEMENT_PROTOTYPES = new DoubleMap();

    private static int ID = 0;

    private static final Logger LOGGER = LoggerFactory.getLogger(DocumentPatcher.class);

    @PatchMethod
    static Text createTextNode(Document document, String data) {
        return JsoUtils.newText(data, document);
    }

    @PatchMethod
    static String createUniqueId(Document document) {
        ID++;
        return "elem_" + Long.toString(ID);
    }

    @PatchMethod
    static BodyElement getBody(Document document) {
        NodeList bodyList = getElementsByTagName(document, "body");
        if (bodyList.getLength() < 1) {
            return null;
        } else {
            return bodyList.getItem(0).cast();
        }
    }

    @PatchMethod
    static String getCompatMode(Document document) {
        return "toto";
    }

    @PatchMethod
    static String getDomain(Document document) {
        return null;
    }

    @PatchMethod
    static Element getElementById(Node document, String elementId) {
        List childs = JsoUtils.getChildNodeInnerList(document);

        for (Node n : childs) {
            if (Node.ELEMENT_NODE == n.getNodeType()) {
                Element currentElement = n.cast();
                if (elementId.equals(currentElement.getId())) {
                    return currentElement;
                }
            }
            Element result = getElementById(n, elementId);
            if (result != null) {
                return result;
            }
        }

        return null;
    }

    @PatchMethod
    static NodeList getElementsByTagName(Node node, String tagName) {
        List result = new ArrayList();
        inspectDomForTag(node, tagName, result);

        return JsoUtils.newNodeList(result);
    }

    @PatchMethod
    static String getReferrer(Document document) {
        return "";
    }

    @PatchMethod
    static Document nativeGet() {
        if (DOCUMENT_HOLDER.document == null) {
            try {
                DOCUMENT_HOLDER.document = JsoUtils.newDocument();
                Element e = parseHTMLElement(DOCUMENT_HOLDER.document);
                DOCUMENT_HOLDER.document.appendChild(e);
                JavaScriptObjects.setProperty(DOCUMENT_HOLDER.document, DOCUMENT_ELEMENT, e);
                return DOCUMENT_HOLDER.document;
            } catch (Exception e) {
                if (GwtTestException.class.isInstance(e)) {
                    throw (GwtTestException) e;
                } else {
                    throw new GwtTestDomException("Unable to create Document", e);
                }
            }
        }
        return DOCUMENT_HOLDER.document;
    }

    private static Element findHTMLElement(NodeList nodes) {
        int i = 0;
        while (i < nodes.getLength()) {
            Node node = nodes.getItem(i);
            if (Node.ELEMENT_NODE == node.getNodeType()) {
                Element e = node.cast();
                if ("html".equalsIgnoreCase(e.getTagName())) {
                    return e;
                }
            }
            i++;
        }

        return null;
    }

    private static String getHostPageHTML(String hostPagePath) {

        // try classpath relative path
        InputStream is = JavaScriptObjects.class.getClassLoader().getResourceAsStream(hostPagePath);

        if (is == null) {
            try {
                // try project relative or absolute path
                is = new FileInputStream(hostPagePath);
            } catch (FileNotFoundException e) {
                // handle just after
            }
        }

        if (is == null) {
            LOGGER.warn("Cannot find the host HTML file '"
                    + hostPagePath
                    + "', fallback to an empty HTML document instead. You may want to override "
                    + GwtConfig.get().getModuleRunner().getClass().getSimpleName()
                    + ".getHostPagePath(String moduleFullQualifiedName) method to specify the relative path of the your HTML file from the root directory of your java project");

            return EMPTY_HTML;
        }

        BufferedReader br = null;
        try {
            br = new BufferedReader(new InputStreamReader(is));
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

            return sb.toString();
        } catch (IOException e) {
            throw new GwtTestConfigurationException("Error while reading module HTML host page '"
                    + hostPagePath + "'", e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    // don't care
                }
            }
        }

    }

    private static void inspectDomForTag(Node node, String tagName, List result) {
        List childs = JsoUtils.getChildNodeInnerList(node);

        for (Node n : childs) {
            if (Node.ELEMENT_NODE == n.getNodeType()) {
                Element childElem = n.cast();
                if ("*".equals(tagName) || tagName.equalsIgnoreCase(childElem.getTagName())) {
                    result.add(childElem);
                }
            }
            inspectDomForTag(n, tagName, result);
        }
    }

    private static Element parseHTMLElement(Document document) {
        String moduleName = GwtConfig.get().getModuleAlias();
        String hostPagePath = GwtConfig.get().getModuleRunner().getHostPagePath();

        if (hostPagePath == null) {
            // return a default empty HTML element
            Element defaultHTMLElement = JsoUtils.newElement("HTML", document);
            defaultHTMLElement.appendChild(JsoUtils.newElement("body", document));
            return defaultHTMLElement;
        }

        String html = HTML_ELEMENT_PROTOTYPES.get(moduleName, hostPagePath);

        if (html == null) {
            // parsing of the host page
            html = getHostPageHTML(hostPagePath);
            HTML_ELEMENT_PROTOTYPES.put(moduleName, hostPagePath, html);
        }

        NodeList list = GwtHtmlParser.parse(html);
        Element htmlElement = findHTMLElement(list);

        if (htmlElement == null) {
            throw new GwtTestDomException("Cannot find a root  element in file '" + hostPagePath
                    + "'");
        }

        return htmlElement;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy