Mon, 09 Nov 2015 13:45:10 -0800
Merge
1 #// Usage: jjs -scripting jsadapter_dom.js
3 /*
4 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 *
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * - Neither the name of Oracle nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
34 // Simple example that demonstrates reading XML Rss feed
35 // to generate a HTML file from script and show it by browser
36 // Uses XML DOM parser and DOM element wrapped by script
37 // "proxy" (JSAdapter constructor)
39 // Java classes used
40 var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory");
41 var Node = Java.type("org.w3c.dom.Node");
42 var File = Java.type("java.io.File");
43 var FileWriter = Java.type("java.io.FileWriter");
44 var PrintWriter = Java.type("java.io.PrintWriter");
46 // constants from Node class
47 var ELEMENT_NODE = Node.ELEMENT_NODE;
48 var TEXT_NODE = Node.TEXT_NODE;
50 // parse XML from uri and return Document
51 function parseXML(uri) {
52 var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder();
53 return docBuilder["parse(java.lang.String)"](uri);
54 }
56 // get child Elements of given name of the parent element given
57 function getChildElements(elem, name) {
58 var nodeList = elem.childNodes;
59 var childElems = [];
60 var len = nodeList.length;
61 for (var i = 0; i < len; i++) {
62 var node = nodeList.item(i);
63 if (node.nodeType == ELEMENT_NODE &&
64 node.tagName == name) {
65 childElems.push(wrapElement(node));
66 }
67 }
69 return childElems;
70 }
72 // get concatenated child text content of an Element
73 function getElemText(elem) {
74 var nodeList = elem.childNodes;
75 var len = nodeList.length;
76 var text = '';
77 for (var i = 0; i < len; i++) {
78 var node = nodeList.item(i);
79 if (node.nodeType == TEXT_NODE) {
80 text += node.nodeValue;
81 }
82 }
84 return text;
85 }
87 // Wrap DOM Element object as a convenient script object
88 // using JSAdapter. JSAdapter is like java.lang.reflect.Proxy
89 // in that it allows property access, method calls be trapped
90 // by 'magic' methods like __get__, __call__.
91 function wrapElement(elem) {
92 if (! elem) {
93 return elem;
94 }
95 return new JSAdapter() {
96 // getter to expose child elements and attributes by name
97 __get__: function(name) {
98 if (typeof name == 'string') {
99 if (name.startsWith('@')) {
100 var attr = elem.getAttributeNode(name.substring(1));
101 return !attr? undefined : attr.value;
102 }
104 var arr = getChildElements(elem, name);
105 if (arr.length == 1) {
106 // single child element, expose as single element
107 return arr[0];
108 } else {
109 // multiple children of given name, expose as array
110 return arr;
111 }
112 }
113 return undefined;
114 },
116 __call__: function(name) {
117 // toString override to get text content of this Element
118 if (name == 'toString' || name == 'valueOf') {
119 return getElemText(elem);
120 }
121 return undefined;
122 }
123 }
124 }
126 // generate HTML using here-doc and string interpolation
127 function getBooksHtml() {
128 var doc = parseXML("http://www.gutenberg.org/cache/epub/feeds/today.rss");
129 // wrap document root Element as script convenient object
130 var rss = wrapElement(doc.documentElement);
131 print("rss file version " + rss['@version']);
133 var str = <<HEAD
135 <html>
136 <title>${rss.channel.title}</title>
137 <body>
138 <h1>${rss.channel.description}</h1>
139 <p>
140 Published on ${rss.channel.pubDate}
141 </p>
143 HEAD
145 var items = rss.channel.item;
146 for each (var i in items) {
147 str += <<LIST
149 <dl>
150 <dt><a href="${i.link}">${i.title}</a></dt>
151 <dd>${i.description}</dd>
152 </dl>
154 LIST
155 }
156 str += <<END
158 </body>
159 </html>
161 END
162 return str;
163 }
165 // write the string to the given file
166 function writeTo(file, str) {
167 var w = new PrintWriter(new FileWriter(file));
168 try {
169 w.print(str);
170 } finally {
171 w.close();
172 }
173 }
175 // generate books HTML
176 var str = getBooksHtml();
178 // write to file. __DIR__ is directory where
179 // this script is stored.
180 var file = new File(__DIR__ + "books.html");
181 writeTo(file, str);
183 // show it by desktop browser
184 try {
185 var Desktop = Java.type("java.awt.Desktop");
186 Desktop.desktop.browse(file.toURI());
187 } catch (e) {
188 print(e);
189 }