HtmlSection.java revision 2326:49aa366f9afc
1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24package jdk.test.failurehandler;
25
26import java.io.FilterWriter;
27import java.io.IOException;
28import java.io.PrintWriter;
29
30public class HtmlSection {
31    protected final HtmlSection rootSection;
32    protected final String id;
33    protected final String name;
34
35    public PrintWriter getWriter() {
36        return textWriter;
37    }
38
39    protected final PrintWriter pw;
40    protected final PrintWriter textWriter;
41    protected boolean closed;
42
43    private HtmlSection child;
44
45
46    public HtmlSection(PrintWriter pw) {
47        this(pw, "", null, null);
48    }
49
50    private HtmlSection(PrintWriter pw, String id, String name, HtmlSection rootSection) {
51        this.pw = pw;
52        textWriter = new PrintWriter(new HtmlFilterWriter(pw), true);
53        this.id = id;
54        this.name = name;
55        child = null;
56        // main
57        if (rootSection == null) {
58            this.rootSection = this;
59            this.pw.println("<html>");
60            this.pw.println("<style>\n"
61                    + "div { display:none;}\n"
62                    + "</style>\n"
63                    + "\n"
64                    + "<script>\n"
65                    + "function show(e) {\n"
66                    + "  while (e != null) {\n"
67                    + "    if (e.tagName == 'DIV') {\n"
68                    + "      e.style.display = 'block';\n"
69                    + "    }\n"
70                    + "    e = e.parentNode;\n"
71                    + "  }\n"
72                    + "}\n"
73                    + "\n"
74                    + "function toggle(id) {\n"
75                    + "  e = document.getElementById(id);\n"
76                    + "  d = e.style.display;\n"
77                    + "  if (d == 'block') {\n"
78                    + "    e.style.display = 'none';\n"
79                    + "  } else {\n"
80                    + "    show(e);\n"
81                    + "  }\n"
82                    + "}\n"
83                    + "\n"
84                    + "function main() {\n"
85                    + "  index = location.href.indexOf(\"#\");"
86                    + "  if (index != -1) {\n"
87                    + "    show(document.getElementById(location.href.substring(index + 1)));\n"
88                    + "  }\n"
89                    + "}\n"
90                    + "\n"
91                    + "</script>\n"
92                    + "</head>");
93
94            this.pw.println("<body onload='main()'>");
95        } else {
96            this.rootSection = rootSection;
97            this.pw.print("<ul>");
98        }
99    }
100
101    public HtmlSection createChildren(String section) {
102        if (child != null) {
103            if (child.name.equals(section)) {
104                return child;
105            }
106            child.close();
107        }
108        child = new SubSection(this, section, rootSection);
109        return child;
110    }
111
112    protected final void removeChild(HtmlSection child) {
113        if (this.child == child) {
114            this.child = null;
115        }
116    }
117
118    public void close() {
119        closeChild();
120        if (closed) {
121            return;
122        }
123        closed = true;
124
125        if (rootSection == this) {
126            pw.println("</body>");
127            pw.println("</html>");
128            pw.close();
129        } else {
130            pw.println("</ul>");
131        }
132
133    }
134
135    protected final void closeChild() {
136        if (child != null) {
137            child.close();
138            child = null;
139        }
140    }
141
142    public void link(HtmlSection section, String child, String name) {
143        String path = section.id;
144        if (path.isEmpty()) {
145            path = child;
146        } else if (child != null) {
147            path = String.format("%s.%s", path, child);
148        }
149        pw.printf("<a href=\"#%1$s\" onclick=\"show(document.getElementById('%1$s')); return true;\">%2$s</a>%n",
150                path, name);
151    }
152
153    public HtmlSection createChildren(String[] sections) {
154        int i = 0;
155        int n = sections.length;
156        HtmlSection current = rootSection;
157        if (current != null) {
158            for (; i < n && current.child != null;
159                    ++i, current = current.child) {
160                if (!sections[i].equals(current.child.name)) {
161                    break;
162                }
163            }
164        }
165        for (; i < n; ++i) {
166            current = current.createChildren(sections[i]);
167        }
168        return current;
169    }
170
171    private static class SubSection extends HtmlSection {
172        private final HtmlSection parent;
173
174        public SubSection(HtmlSection parent, String name,
175                          HtmlSection rootSection) {
176            super(parent.pw,
177                    parent.id.isEmpty()
178                            ? name
179                            : String.format("%s.%s", parent.id, name),
180                    name, rootSection);
181            this.parent = parent;
182            pw.printf("<li><a name='%1$s'/><a href='#%1$s' onclick=\"toggle('%1$s'); return false;\">%2$s</a><div id='%1$s'><code><pre>",
183                    id, name);
184        }
185
186        @Override
187        public void close() {
188            closeChild();
189            if (closed) {
190                return;
191            }
192            pw.print("</pre></code></div></li><!-- " + id + "-->");
193            parent.removeChild(this);
194            super.close();
195        }
196    }
197
198    private static class HtmlFilterWriter extends FilterWriter {
199        public HtmlFilterWriter(PrintWriter pw) {
200            super(pw);
201        }
202
203        @Override
204        public void write(int c) throws IOException {
205            switch (c) {
206                case '<':
207                    super.write("&lt;", 0, 4);
208                    break;
209                case '>':
210                    super.write("&gt;", 0, 4);
211                    break;
212                case '"':
213                    super.write("&quot;", 0, 5);
214                    break;
215                case '&':
216                    super.write("&amp;", 0, 4);
217                    break;
218                default:
219                    super.write(c);
220            }
221        }
222
223        @Override
224        public void write(char[] cbuf, int off, int len) throws IOException {
225            for (int i = off; i < len; ++i){
226                write(cbuf[i]);
227            }
228        }
229
230        @Override
231        public void write(String str, int off, int len) throws IOException {
232            for (int i = off; i < len; ++i){
233                write(str.charAt(i));
234            }
235        }
236    }
237}
238