8074939: Add few sample scripts to demo nashorn parser API

Reviewed-by: attila, hannesw
This commit is contained in:
Athijegannathan Sundararajan 2015-03-11 14:30:40 +05:30
parent 86fefb1f46
commit e383c777af
7 changed files with 793 additions and 0 deletions

View File

@ -0,0 +1,129 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Find break or continue inside try..finally in all scripts
// in a given directory (recursively). If no directory is specified
// the current working directory is scanned for scripts.
if (arguments.length == 0) {
arguments[0] = ".";
}
var File = Java.type("java.io.File");
var file = new File(arguments[0]);
if (!file.exists()) {
print(arguments[0] + " is neither a directory nor a file");
exit(1);
}
var Files = Java.type("java.nio.file.Files");
var Parser = Java.type("jdk.nashorn.api.tree.Parser");
var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1");
var parser = Parser.create("-scripting", "--const-as-var");
function checkFile(file) {
// print("checking " + file);
var ast = parser.parse(file, print);
if (!ast) {
return;
}
// locate 'break/continue' inside try..finally
ast.accept(visitor = new (Java.extend(SimpleTreeVisitor)) {
lineMap: null,
inTryFinally: false,
printWarning: function(node, msg) {
var pos = node.startPosition;
var line = this.lineMap.getLineNumber(pos);
var column = this.lineMap.getColumnNumber(pos);
print(msg + " found in " + file + " @ " + line + ":" + column);
},
visitBreak: function(node, extra) {
if (this.inTryFinally) {
this.printWarning(node, "break");
}
},
visitContinue: function(node, extra) {
if (this.inTryFinally) {
this.printWarning(node, "continue");
}
},
visitCompilationUnit: function(node, extra) {
this.lineMap = node.lineMap;
Java.super(visitor).visitCompilationUnit(node, extra);
},
visitFunctionDeclaration: function(node, extra) {
var oldInTryFinally = this.inTryFinally;
this.inTryFinally = false;
try {
Java.super(visitor).visitFunctionDeclaration(node, extra);
} finally {
this.inTryFinally = oldInTryFinally;
}
},
visitFunctionExpression: function(node, extra) {
var oldInTryFinally = this.inTryFinally;
this.inTryFinally = false;
try {
Java.super(visitor).visitFunctionExpression(node, extra);
} finally {
this.inTryFinally = oldInTryFinally;
}
},
visitTry: function(node, extra) {
var oldInTryFinally = this.inTryFinally;
this.inTryFinally = (node.finallyBlock != null);
try {
Java.super(visitor).visitTry(node, extra);
} finally {
this.inTryFinally = oldInTryFinally;
}
}
}, null);
}
if (file.isDirectory()) {
Files.walk(file.toPath())
.filter(function(p) Files.isRegularFile(p))
.filter(function(p) p.toFile().name.endsWith('.js'))
.forEach(checkFile);
} else {
checkFile(file);
}

140
nashorn/samples/cricket.js Normal file
View File

@ -0,0 +1,140 @@
#// Usage: jjs -scripting cricket.js
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// Example that demonstrates reading XML Rss feed.
// XML DOM Document element is wrapped by script
// "proxy" (JSAdapter constructor)
// Java classes used
var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory");
var Node = Java.type("org.w3c.dom.Node");
// constants from Node class
var ELEMENT_NODE = Node.ELEMENT_NODE;
var TEXT_NODE = Node.TEXT_NODE;
// parse XML from uri and return Document
function parseXML(uri) {
var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder();
return docBuilder["parse(java.lang.String)"](uri);
}
// get child Elements of given name of the parent element given
function getChildElements(elem, name) {
var nodeList = elem.childNodes;
var childElems = [];
var len = nodeList.length;
for (var i = 0; i < len; i++) {
var node = nodeList.item(i);
if (node.nodeType == ELEMENT_NODE &&
node.tagName == name) {
childElems.push(wrapElement(node));
}
}
return childElems;
}
// get concatenated child text content of an Element
function getElemText(elem) {
var nodeList = elem.childNodes;
var len = nodeList.length;
var text = '';
for (var i = 0; i < len; i++) {
var node = nodeList.item(i);
if (node.nodeType == TEXT_NODE) {
text += node.nodeValue;
}
}
return text;
}
// Wrap DOM Element object as a convenient script object
// using JSAdapter. JSAdapter is like java.lang.reflect.Proxy
// in that it allows property access, method calls be trapped
// by 'magic' methods like __get__, __call__.
function wrapElement(elem) {
if (! elem) {
return elem;
}
return new JSAdapter() {
// getter to expose child elements and attributes by name
__get__: function(name) {
if (typeof name == 'string') {
if (name.startsWith('@')) {
var attr = elem.getAttributeNode(name.substring(1));
return !attr? undefined : attr.value;
}
var arr = getChildElements(elem, name);
if (arr.length == 1) {
// single child element, expose as single element
return arr[0];
} else {
// multiple children of given name, expose as array
return arr;
}
}
return undefined;
},
__call__: function(name) {
// toString override to get text content of this Element
if (name == 'toString' || name == 'valueOf') {
return getElemText(elem);
}
return undefined;
}
}
}
function printCricketScore() {
var doc = parseXML("http://static.cricinfo.com/rss/livescores.xml");
// wrap document root Element as script convenient object
var rss = wrapElement(doc.documentElement);
print("rss file version " + rss['@version']);
print(rss.channel.title);
print(rss.channel.description);
print(rss.channel.pubDate);
print("=====================");
var items = rss.channel.item;
for each (var i in items) {
print(i.description);
}
}
printCricketScore();

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// __proto__ magic property is non-standard. Use Object.getPrototypeOf
// and Object.setPrototypeOf instead. This script finds __proto__
// usage in scripts a given directory (recursively). If no directory
// is specified the current working directory is scanned for scripts.
if (arguments.length == 0) {
arguments[0] = ".";
}
var File = Java.type("java.io.File");
var file = new File(arguments[0]);
if (!file.exists()) {
print(arguments[0] + " is neither a file nor a directory");
exit(1);
}
var Files = Java.type("java.nio.file.Files");
var Parser = Java.type("jdk.nashorn.api.tree.Parser");
var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1");
var parser = Parser.create("-scripting", "--const-as-var");
var protoFound = false;
function checkFile(file) {
// print("checking " + file);
var ast = parser.parse(file, print);
if (!ast) {
return;
}
// locate __proto__ usage and warn
ast.accept(visitor = new (Java.extend(SimpleTreeVisitor)) {
lineMap: null,
printWarning: function(node) {
var pos = node.startPosition;
var line = this.lineMap.getLineNumber(pos);
var column = this.lineMap.getColumnNumber(pos);
print("WARNING: __proto__ usage in " + file + " @ " + line + ":" + column);
},
checkProto: function(node, name) {
if (name == "__proto__") {
protoFound = true;
this.printWarning(node);
}
},
visitCompilationUnit: function(node, extra) {
this.lineMap = node.lineMap;
Java.super(visitor).visitCompilationUnit(node, extra);
},
visitIdentifier: function(node, extra) {
this.checkProto(node, node.name);
Java.super(visitor).visitIdentifier(node, extra);
},
visitMemberSelect: function(node, extra) {
this.checkProto(node, node.identifier);
Java.super(visitor).visitMemberSelect(node, extra);
},
visitProperty: function(node, extra) {
this.checkProto(node, node.key);
Java.super(visitor).visitProperty(node, extra);
}
}, null);
}
if (file.isDirectory()) {
Files.walk(file.toPath())
.filter(function(p) Files.isRegularFile(p))
.filter(function(p) p.toFile().name.endsWith('.js'))
.forEach(checkFile);
} else {
checkFile(file);
}
if (protoFound) {
print("__proto__ is non-standard. Use Object.get/setPrototypeOf instead");
}

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// delete of scope vars is reported as error in strict mode.
// This script finds scripts that such deletes. Scripts in
// the specified directory are scanned. If no directory is
// specified, the current directory is scanned.
if (arguments.length == 0) {
arguments[0] = ".";
}
var File = Java.type("java.io.File");
var file = new File(arguments[0]);
if (!file.exists()) {
print(arguments[0] + " is neither a directory nor a file");
exit(1);
}
var Files = Java.type("java.nio.file.Files");
var IdentifierTree = Java.type("jdk.nashorn.api.tree.IdentifierTree");
var Parser = Java.type("jdk.nashorn.api.tree.Parser");
var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1");
var Tree = Java.type("jdk.nashorn.api.tree.Tree");
var parser = Parser.create("-scripting", "--const-as-var");
function checkFile(file) {
// print("checking " + file);
var ast = parser.parse(file, print);
if (!ast) {
return;
}
// locate __proto__ usage and warn
ast.accept(visitor = new (Java.extend(SimpleTreeVisitor)) {
lineMap: null,
printWarning: function(node, varName) {
var pos = node.startPosition;
var line = this.lineMap.getLineNumber(pos);
var column = this.lineMap.getColumnNumber(pos);
print("WARNING: delete " + varName + " in " + file + " @ " + line + ":" + column);
},
visitCompilationUnit: function(node, extra) {
this.lineMap = node.lineMap;
Java.super(visitor).visitCompilationUnit(node, extra);
},
visitUnary: function(node, extra) {
if (node.kind == Tree.Kind.DELETE &&
node.expression instanceof IdentifierTree) {
this.printWarning(node, node.expression.name);
}
Java.super(visitor).visitUnary(node, extra);
},
}, null);
}
if (file.isDirectory()) {
Files.walk(file.toPath())
.filter(function(p) Files.isRegularFile(p))
.filter(function(p) p.toFile().name.endsWith('.js'))
.forEach(checkFile);
} else {
checkFile(file);
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
// 'with' statement is not considered a good practive. In strict mode,
// with statements result in early error being thrown.
// This script finds 'with' usage in scripts a given directory (recursively).
// If no directory is specified the current working directory is scanned
// for scripts.
if (arguments.length == 0) {
arguments[0] = ".";
}
var File = Java.type("java.io.File");
var file = new File(arguments[0]);
if (!file.exists()) {
print(arguments[0] + " is neither a directory nor a file");
exit(1);
}
var Files = Java.type("java.nio.file.Files");
var Parser = Java.type("jdk.nashorn.api.tree.Parser");
var SimpleTreeVisitor = Java.type("jdk.nashorn.api.tree.SimpleTreeVisitorES5_1");
var parser = Parser.create("-scripting", "--const-as-var");
var protoFound = false;
function checkFile(file) {
// print("checking " + file);
var ast = parser.parse(file, print);
if (!ast) {
return;
}
// locate __proto__ usage and warn
ast.accept(visitor = new (Java.extend(SimpleTreeVisitor)) {
lineMap: null,
printWarning: function(node) {
var pos = node.startPosition;
var line = this.lineMap.getLineNumber(pos);
var column = this.lineMap.getColumnNumber(pos);
print("WARNING: 'with' usage in " + file + " @ " + line + ":" + column);
},
visitCompilationUnit: function(node, extra) {
this.lineMap = node.lineMap;
Java.super(visitor).visitCompilationUnit(node, extra);
},
visitWith: function(node, extra) {
this.printWarning(node);
Java.super(visitor).visitWith(node, extra);
}
}, null);
}
if (file.isDirectory()) {
Files.walk(file.toPath())
.filter(function(p) Files.isRegularFile(p))
.filter(function(p) p.toFile().name.endsWith('.js'))
.forEach(checkFile);
} else {
checkFile(file);
}
if (protoFound) {
print("__proto__ is non-standard. Use Object.get/setPrototypeOf instead");
}

View File

@ -0,0 +1,113 @@
#// Usage: jjs -scripting -fx nashornastviewer.js -- <scriptfile>
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
# NOTE: This script requires JDK 9 build to run
if (!$OPTIONS._fx) {
print("Usage: jjs -scripting -fx nashornastviewer.js -- <.js file>");
exit(1);
}
// Using JavaFX from Nashorn. See also:
// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html
// This example shows AST of a script file as a JavaFX
// tree view in a window. If no file is specified, AST of
// this script file is shown. This script demonstrates
// Nashorn Parser API too - http://openjdk.java.net/jeps/236
// JavaFX classes used
var StackPane = Java.type("javafx.scene.layout.StackPane");
var Scene = Java.type("javafx.scene.Scene");
var TreeItem = Java.type("javafx.scene.control.TreeItem");
var TreeView = Java.type("javafx.scene.control.TreeView");
// Java classes used
var Enum = Java.type("java.lang.Enum");
var File = Java.type("java.io.File");
var List = Java.type("java.util.List");
var Parser = Java.type("jdk.nashorn.api.tree.Parser");
var Tree = Java.type("jdk.nashorn.api.tree.Tree");
// Create a javafx TreeItem to view a AST node
function treeItemForASTNode(ast, name) {
var item = new TreeItem(name);
// make an iteratable script object from a Tree
ast = Object.bindProperties({}, ast);
for (var prop in ast) {
var node = ast[prop];
var type = typeof node;
if (node == null || type == "function") {
// skip nulls and Java methods
continue;
}
var subitem = null;
if (node instanceof Tree) {
subitem = treeItemForASTNode(node, prop);
} else if (node instanceof List) {
var len = node.size();
subitem = new TreeItem(prop);
for (var i = 0; i < len; i++) {
var li = treeItemForASTNode(node.get(i), String(i));
subitem.children.add(li);
}
} else if (node instanceof Enum || type != 'object') {
subitem = new TreeItem(prop + ": " + node);
}
if (subitem) {
item.children.add(subitem);
}
}
return item;
}
// do we have a script file passed? if not, use current script
var sourceName = arguments.length == 0? __FILE__ : arguments[0];
var parser = Parser.create("-scripting");
// parse script to get CompilationUnitTree of it
var ast = parser.parse(new File(sourceName), null);
// JavaFX start method
function start(stage) {
stage.title = "AST Viewer";
var rootItem = treeItemForASTNode(ast, sourceName);
var tree = new TreeView(rootItem);
var root = new StackPane();
root.children.add(tree);
stage.scene = new Scene(root, 300, 450);
stage.show();
}

View File

@ -0,0 +1,103 @@
#jjs -fx xmlviewer.js [-- <url-of-xml-doc>]
/*
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
if (! $OPTIONS._fx) {
print("Usage: jjs -fx xmlviewer.js [-- <url-of-xml-doc>]");
exit(1);
}
// Using JavaFX from Nashorn. See also:
// http://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/javafx.html
// Simple sample to view a XML document as a JavaFX tree.
// JavaFX classes used
var StackPane = Java.type("javafx.scene.layout.StackPane");
var Scene = Java.type("javafx.scene.Scene");
var TreeItem = Java.type("javafx.scene.control.TreeItem");
var TreeView = Java.type("javafx.scene.control.TreeView");
// XML DocumentBuilderFactory
var DocBuilderFac = Java.type("javax.xml.parsers.DocumentBuilderFactory");
var Attr = Java.type("org.w3c.dom.Attr");
var Element = Java.type("org.w3c.dom.Element");
var Text = Java.type("org.w3c.dom.Text");
// parse XML from uri and return Document
function parseXML(uri) {
var docBuilder = DocBuilderFac.newInstance().newDocumentBuilder();
docBuilder.validating = false;
return docBuilder["parse(java.lang.String)"](uri);
}
// Create a javafx TreeItem to view a XML element
function treeItemForObject(element, name) {
var item = new TreeItem(name);
item.expanded = true;
var attrs = element.attributes;
var numAttrs = attrs.length;
for (var a = 0; a < numAttrs; a++) {
var attr = attrs.item(a);
var subitem = new TreeItem(attr.name + " = " + attr.value);
item.children.add(subitem);
}
var childNodes = element.childNodes;
var numNodes = childNodes.length;
for (var n = 0; n < numNodes; n++) {
var node = childNodes.item(n);
if (node instanceof Element) {
var subitem = treeItemForObject(node, node.tagName);
item.children.add(subitem);
}
}
return item;
}
// Ofcourse, the best default URL is cricket score :)
var DEFAULT_URL = "http://synd.cricbuzz.com/j2me/1.0/livematches.xml";
var url = arguments.length == 0? DEFAULT_URL : arguments[0];
var element = parseXML(url).getDocumentElement();
// JavaFX start method
function start(stage) {
stage.title = "XML Viewer: " + url;
var rootItem = treeItemForObject(element, element.tagName);
var tree = new TreeView(rootItem);
var root = new StackPane();
root.children.add(tree);
stage.scene = new Scene(root, 300, 450);
stage.show();
}