/* * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* @test @bug 7165725 @summary Tests if HTML parser can handle successive script tags in a line and it does not call false text callback after script tags. @run main bug7165725 */ import sun.awt.SunToolkit; import java.awt.BorderLayout; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import javax.swing.*; import javax.swing.text.AbstractDocument.AbstractElement; import javax.swing.text.AbstractDocument; import javax.swing.text.Document; import javax.swing.text.MutableAttributeSet; import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLDocument; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.parser.ParserDelegator; public class bug7165725 extends JFrame { private static class GoldenElement { private String goldenName; private List<GoldenElement> goldenChildren; GoldenElement(String goldenName, GoldenElement... goldenChildren){ this.goldenName = goldenName; if (goldenChildren != null) { this.goldenChildren = Arrays.asList(goldenChildren); } else { this.goldenChildren = new ArrayList<>(); } } // throws RuntimeException if not ok public void checkStructureEquivalence(AbstractDocument.AbstractElement elem) { String name = elem.getName(); if (!goldenName.equals(name)) { throw new RuntimeException("Bad structure: expected element name is '" + goldenName + "' but the actual name was '" + name + "'."); } int goldenChildCount = goldenChildren.size(); int childCount = elem.getChildCount(); if (childCount != goldenChildCount) { System.out.print("D: children: "); for (int i = 0; i < childCount; i++) { System.out.print(" " + elem.getElement(i).getName()); } System.out.println(""); System.out.print("D: goldenChildren: "); for (GoldenElement ge : goldenChildren) { System.out.print(" " + ge.goldenName); } System.out.println(""); throw new RuntimeException("Bad structure: expected child count of element '" + goldenName + "' is '" + goldenChildCount + "' but the actual count was '" + childCount + "'."); } for (int i = 0; i < childCount; i++) { AbstractDocument.AbstractElement nextElem = (AbstractDocument.AbstractElement) elem.getElement(i); GoldenElement goldenElement = goldenChildren.get(i); goldenElement.checkStructureEquivalence(nextElem); } } } private JEditorPane editorPane; public void execute(final String urlStr, final GoldenElement goldenElement) throws Exception { System.out.println(); System.out.println("***** TEST: " + urlStr + " *****"); System.out.println(); SwingUtilities.invokeAndWait(new Runnable() { public void run() { try { editorPane = new JEditorPane(); editorPane.setEditorKit(new HTMLEditorKit() { public Document createDefaultDocument() { AbstractDocument doc = (AbstractDocument) super.createDefaultDocument(); doc.setAsynchronousLoadPriority(-1); return doc; } }); editorPane.setPage(new URL(urlStr)); } catch (IOException ex) { throw new RuntimeException("Test failed", ex); } editorPane.setEditable(false); JScrollPane scroller = new JScrollPane(); JViewport vp = scroller.getViewport(); vp.add(editorPane); add(scroller, BorderLayout.CENTER); setDefaultCloseOperation(EXIT_ON_CLOSE); setSize(400, 400); setLocationRelativeTo(null); setVisible(true); } }); ((SunToolkit) SunToolkit.getDefaultToolkit()).realSync(); SwingUtilities.invokeAndWait(new Runnable() { public void run() { HTMLDocument doc = (HTMLDocument) editorPane.getDocument(); doc.dump(System.out); goldenElement.checkStructureEquivalence((AbstractElement) doc.getDefaultRootElement()); dispose(); } }); System.out.println(); System.out.println("*********************************"); System.out.println(); } public static void main(String[] args) throws Exception { String dirURL = getDirURL(); System.out.println("dirURL = " + dirURL); new bug7165725().execute(dirURL + "successive-script-tag.html", createSuccessiveScriptTags()); new bug7165725().execute(dirURL + "false-text-after-script.html", createFalseTextAfterScript()); checkByCallbackForSuccessiveScript(); checkByCallbackForFalseTextAfterScript(); System.out.println(); System.out.println(); System.out.println("Test passed."); } static String getDirURL() { return "file:///" + new File(System.getProperty("test.src", ".")).getAbsolutePath() + File.separator; } static String getParsedContentOneLine(String path) throws Exception { File f = new File(path); FileReader fr = new FileReader(f); ParserDelegator pd = new ParserDelegator(); SBParserCallback sbcallback = new SBParserCallback(); pd.parse(fr, sbcallback, true); fr.close(); return sbcallback.getStringOneLine(); } static String getParsedContentOneLine(URL url) throws Exception { return getParsedContentOneLine(url.getPath()); } static void checkByCallbackForSuccessiveScript() throws Exception { String content = getParsedContentOneLine(new URL(getDirURL() + "successive-script-tag.html")); if (!content.matches(".*<script .*/js/js1\\.js.*<script .*/js/js2\\.js.*<script .*/js/js3\\.js.*")) throw new RuntimeException("Failed to lookup script tags/attributes."); if (!content.matches(".*<style .*stylesheets/base\\.css.*<style .*stylesheets/adv\\.css.*")) throw new RuntimeException("Failed to lookup style tags."); } static void checkByCallbackForFalseTextAfterScript() throws Exception { String content = getParsedContentOneLine(new URL(getDirURL() + "false-text-after-script.html")); final int bodyIdx = content.indexOf("<body "); if (bodyIdx > 0) { String sbody = content.substring(bodyIdx); // There should be no Text(...) in this html if (sbody.indexOf("Text(") >= 0) throw new RuntimeException("Unexpected text found."); } else { throw new RuntimeException("Failed to find body tag."); } } private static GoldenElement createSuccessiveScriptTags() { return new GoldenElement("html", new GoldenElement("head", new GoldenElement("p-implied", new GoldenElement("title"), new GoldenElement("title"), new GoldenElement("script"), new GoldenElement("comment"), new GoldenElement("script"), new GoldenElement("script"), new GoldenElement("comment"), new GoldenElement("script"), new GoldenElement("script"), new GoldenElement("comment"), new GoldenElement("script"), new GoldenElement("content"))), new GoldenElement("body", new GoldenElement("p-implied", new GoldenElement("content")))); } private static GoldenElement createFalseTextAfterScript() { return new GoldenElement("html", new GoldenElement("head", new GoldenElement("p-implied", new GoldenElement("title"), new GoldenElement("title"), new GoldenElement("content"))), new GoldenElement("body", new GoldenElement("form", new GoldenElement("p-implied", new GoldenElement("input"), new GoldenElement("input"), new GoldenElement("content"))), new GoldenElement("p-implied", new GoldenElement("script"), new GoldenElement("comment"), new GoldenElement("script"), new GoldenElement("script"), new GoldenElement("comment"), new GoldenElement("script"), new GoldenElement("content")))); } static class SBParserCallback extends HTMLEditorKit.ParserCallback { private int indentSize = 0; private ArrayList<String> elist = new ArrayList<>(); public String getStringOneLine() { StringBuilder sb = new StringBuilder(); for (String s : elist) sb.append(s); return sb.toString(); } public String toString() { StringBuffer sb = new StringBuffer(); for (String s : elist) sb.append(s + "\n"); return sb.toString(); } protected void indent() { indentSize += 3; } protected void unIndent() { indentSize -= 3; if (indentSize < 0) indentSize = 0; } protected String pIndent() { StringBuilder sb = new StringBuilder(); for(int i = 0; i < indentSize; i++) sb.append(" "); return sb.toString(); } public void handleText(char[] data, int pos) { elist.add(pIndent() + "Text(" + data.length + " chars) \"" + new String(data) + "\""); } public void handleComment(char[] data, int pos) { elist.add(pIndent() + "Comment(" + data.length + " chars)"); } public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) { elist.add(pIndent() + "Tag start(<" + t.toString() + " " + a + ">, " + a.getAttributeCount() + " attrs)"); indent(); } public void handleEndTag(HTML.Tag t, int pos) { unIndent(); elist.add(pIndent() + "Tag end(</" + t.toString() + ">)"); } public void handleSimpleTag(HTML.Tag t, MutableAttributeSet a, int pos) { elist.add(pIndent() + "Tag(<" + t.toString() + ">, " + a.getAttributeCount() + " attrs)"); } public void handleError(String errorMsg, int pos){ } } }