diff --git a/settings/sql_developer/trivadis_custom_format.arbori b/settings/sql_developer/trivadis_custom_format.arbori index dea7a9d9..268fb60c 100644 --- a/settings/sql_developer/trivadis_custom_format.arbori +++ b/settings/sql_developer/trivadis_custom_format.arbori @@ -187,19 +187,30 @@ identifiers: i5_define_global_variables: runOnce -> { - // Java classes + // java.lang classes + var Integer = Java.type('java.lang.Integer'); + var System = Java.type('java.lang.System'); + + // java.util classes var ArrayList = Java.type('java.util.ArrayList'); - var Format = Java.type('oracle.dbtools.app.Format'); var HashMap = Java.type('java.util.HashMap'); var HashSet = Java.type('java.util.HashSet'); - var Integer = Java.type('java.lang.Integer'); - var LexerToken = Java.type('oracle.dbtools.parser.LexerToken'); - var logger = Java.type('oracle.dbtools.util.Logger'); var Pattern = Java.type("java.util.regex.Pattern"); + var Collectors = Java.type('java.util.stream.Collectors'); + + // oracle.dbtools.app classes + var Format = Java.type('oracle.dbtools.app.Format'); + var Format$Breaks = Java.type("oracle.dbtools.app.Format$Breaks"); + var Format$Space = Java.type("oracle.dbtools.app.Format$Space"); + + // oracle.dbtools.parser classes + var LexerToken = Java.type('oracle.dbtools.parser.LexerToken'); var Substitutions = Java.type('oracle.dbtools.parser.Substitutions'); - var System = Java.type('java.lang.System'); var Token = Java.type('oracle.dbtools.parser.Token'); + // oracle.dbtools.util classes + var logger = Java.type('oracle.dbtools.util.Logger'); + // use reflection to access hidden field newlinePositions var newlinePositionsField = Format.class.getDeclaredField("newlinePositions"); newlinePositionsField.setAccessible(true); @@ -289,9 +300,9 @@ i5_define_global_functions: // Returns the indentation without leading new lines from a string. var getNumCharsAfterNewLine = function(indent) { if (indent.indexOf("\n") != -1) { - return indent.length() - indent.lastIndexOf("\n") - 1; + return indent.length - indent.lastIndexOf("\n") - 1; } - return indent.length(); + return indent.length; } // Returns the leading new lines from a node position (without trailing spaces). @@ -310,7 +321,7 @@ i5_define_global_functions: var col=getNumCharsAfterNewLine(getIndent(startPos)); var indent = getIndent(startPos); for (var i=startPos-1; i>=0 && indent.indexOf("\n") == -1; i=i-1) { - col += target.src.get(i).content.length(); + col += target.src.get(i).content.length; var indent = getIndent(i); col += getNumCharsAfterNewLine(indent); } @@ -323,7 +334,7 @@ i5_define_global_functions: var col=getNumCharsAfterNewLine(getIndent(startPos)); var indent = getIndent(startPos); for (var i=startPos-1; i>=0 && indent.indexOf("\n") == -1; i=i-1) { - col += target.src.get(i).content.length(); + col += target.src.get(i).content.length; var indent = getIndent(i); if (indent.indexOf("\n") == -1) { col += getNumCharsAfterNewLine(indent); @@ -418,9 +429,9 @@ i5_define_global_functions: // Aligns all nodes per scope. var align = function(map, alignNodeName, indentNodeName, logText) { - var it = map.keySet().iterator(); - while (it.hasNext()) { - var scope = it.next(); + var keys = map.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var scope = keys[i]; var list = map.get(scope); var maxCol = getMaxColumn(list, alignNodeName); alignAtPos(maxCol, list, alignNodeName, indentNodeName, logText); @@ -506,9 +517,9 @@ i5_define_global_functions: if (spaceAfterCommas) { comma += 1; } - var it = map.keySet().iterator(); - while (it.hasNext()) { - var scope = it.next(); + var keys = map.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var scope = keys[i]; var list = map.get(scope); for (var i=0; i { - var it = newlinePositions.keySet().iterator(); - while (it.hasNext()) { - var pos = it.next(); + var keys = newlinePositions.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var pos = keys[i]; if (overrideIndents(pos)) { var indent = getIndent(pos); var nlpos = indent.lastIndexOf("\n"); @@ -899,12 +910,12 @@ a1_replace_tabs_with_spaces: runOnce -> { var indent = getSpaces(indentSpaces); - var it = newlinePositions.keySet().iterator(); - while (it.hasNext()) { - var key = it.next(); + var keys = newlinePositions.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var key = keys[i]; var value = newlinePositions.get(key); if (value.indexOf("\t") != -1) { - struct.putNewline(key, value.replaceAll("\t", indent)); + struct.putNewline(key, replaceAll(value, "\t", indent)); logger.fine(struct.getClass(), "a1_replace_tabs_with_spaces: at " + key + "."); } } @@ -918,13 +929,13 @@ a2_remove_trailing_spaces: runOnce -> { var indent = getSpaces(indentSpaces); - var it = newlinePositions.keySet().iterator(); - while (it.hasNext()) { - var key = it.next(); + var keys = newlinePositions.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var key = keys[i]; var value = newlinePositions.get(key); // handle Linux and Windows line separators regardless of the OS var newValue = replaceAll(replaceAll(value, "[ ]+\\n", "\n"), "[ ]+\\r\\n", "\r\n"); - if (!value.equals(newValue)) { + if (value !== newValue) { struct.putNewline(key, newValue); logger.fine(struct.getClass(), "a2_remove_trailing_spaces: at " + key + "."); } @@ -1099,7 +1110,7 @@ a13_short_nodes: var maxLen = maxCharLineSize / 2; var node = tuple.get("node"); if (getNodeLength(node) <= maxLen) { - if (breaksConcat == Format.Breaks.None || !containsConcat(node)) { + if (breaksConcat == Format$Breaks.None || !containsConcat(node)) { reduceNodeIndents(node); } } @@ -1774,10 +1785,10 @@ o3_whitespace_around_open_paren: [node) '(' -> { var node = tuple.get("node"); - if (spaceAroundBrackets != Format.Space.Default) { + if (spaceAroundBrackets != Format$Space.Default) { if (getIndent(node.from).indexOf("\n") == -1) { var spaceBefore; - if (spaceAroundBrackets == Format.Space.Inside || spaceAroundBrackets == Format.Space.NoSpace) { + if (spaceAroundBrackets == Format$Space.Inside || spaceAroundBrackets == Format$Space.NoSpace) { spaceBefore = ""; } else { spaceBefore = " "; @@ -1788,7 +1799,7 @@ o3_whitespace_around_open_paren: } if (getIndent(node.to).indexOf("\n") == -1) { var spaceAfter; - if (spaceAroundBrackets == Format.Space.Outside || spaceAroundBrackets == Format.Space.NoSpace || spaceAroundBrackets == Format.Space.Default) { + if (spaceAroundBrackets == Format$Space.Outside || spaceAroundBrackets == Format$Space.NoSpace || spaceAroundBrackets == Format$Space.Default) { spaceAfter = ""; } else { spaceAfter = " "; @@ -1804,7 +1815,7 @@ o3_whitespace_around_close_paren: var node = tuple.get("node"); if (getIndent(node.from).indexOf("\n") == -1) { var spaceBefore; - if (spaceAroundBrackets == Format.Space.Outside || spaceAroundBrackets == Format.Space.NoSpace || spaceAroundBrackets == Format.Space.Default) { + if (spaceAroundBrackets == Format$Space.Outside || spaceAroundBrackets == Format$Space.NoSpace || spaceAroundBrackets == Format$Space.Default) { spaceBefore = ""; } else { spaceBefore = " "; @@ -1812,10 +1823,10 @@ o3_whitespace_around_close_paren: struct.putNewline(node.from, spaceBefore); logger.fine(struct.getClass(), "o3_whitespace_around_close_paren: <" + spaceBefore + "> before at " + node.from + "."); } - if (spaceAroundBrackets != Format.Space.Default) { + if (spaceAroundBrackets != Format$Space.Default) { if (getIndent(node.to).indexOf("\n") == -1) { var spaceAfter; - if (spaceAroundBrackets == Format.Space.Inside || spaceAroundBrackets == Format.Space.NoSpace) { + if (spaceAroundBrackets == Format$Space.Inside || spaceAroundBrackets == Format$Space.NoSpace) { spaceAfter = ""; } else { spaceAfter = " "; @@ -1826,7 +1837,7 @@ o3_whitespace_around_close_paren: } } --- based on issue #99, applied only with Format.Space.Default +-- based on issue #99, applied only with Format$Space.Default o3_no_space_before_open_paren: [node) '(' & ( @@ -1835,7 +1846,7 @@ o3_no_space_before_open_paren: | [node^) paren_expr_list & [node^^) function_call ) -> { - if (spaceAroundBrackets == Format.Space.Default) { + if (spaceAroundBrackets == Format$Space.Default) { var node = tuple.get("node"); struct.putNewline(node.from, ""); logger.fine(struct.getClass(), "o3_no_space_before_open_paren: at " + node.from + "."); @@ -2053,7 +2064,7 @@ o9_boolean_option: var node = tuple.get("node") if (struct.breaksBeforeLogicalConjunction()) { if (getIndent(node.from).indexOf("\n") == -1) { - if (breaksAroundLogicalConjunctions != Format.Breaks.BeforeAndAfter) { + if (breaksAroundLogicalConjunctions != Format$Breaks.BeforeAndAfter) { struct.putNewline(node.to, " "); } struct.putNewline(node.from, theLineSeparator); @@ -2062,7 +2073,7 @@ o9_boolean_option: } if (struct.breaksAfterLogicalConjunction()) { if (getIndent(node.to).indexOf("\n") == -1) { - if (breaksAroundLogicalConjunctions != Format.Breaks.BeforeAndAfter) { + if (breaksAroundLogicalConjunctions != Format$Breaks.BeforeAndAfter) { struct.putNewline(node.from, " "); } struct.putNewline(node.to, theLineSeparator); @@ -2483,7 +2494,7 @@ r5_commas: } var getIndentForComma = function(indent) { - var len = indent.length() - 1; + var len = indent.length - 1; if (spaceAfterCommas) { len = len - 1; } @@ -2498,7 +2509,7 @@ r5_commas: var indent = getIndent(nodeFrom); if (indent.indexOf("\n") != -1) { var pos = 0; - for (var i=0; i { // Left margin is expressed in number of spaces. var leftMargin = new HashMap(); - var it = newlinePositions.keySet().iterator(); - while (it.hasNext()) { - var key = it.next(); + var keys = newlinePositions.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var key = keys[i]; var value = newlinePositions.get(key); if (value.indexOf("\n") != -1) { // enforce uniform datatype in map; therefore convert values to Integer @@ -3050,12 +3061,12 @@ r2_increment_left_margin_for_assignment: r2_indent_nodes: runOnce -> { - var it = leftMargin.keySet().iterator(); - while (it.hasNext()) { - var key = it.next(); + var keys = leftMargin.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var key = keys[i]; var margin = leftMargin.get(key); var value = newlinePositions.get(key); - var spaces = value.length()-value.lastIndexOf("\n")-1; // 0 = first column + var spaces = value.length-value.lastIndexOf("\n")-1; // 0 = first column var comma = 0; if (key < target.src.size()) { if (target.src.get(key).content == ",") { @@ -3121,14 +3132,14 @@ r7_declaration: if (!breaksAfterSelect) { var keyword = tuple.get("keyword"); var parent = tuple.get("parent"); - var parentLength = target.src.get(parent.from).content.length(); + var parentLength = target.src.get(parent.from).content.length; if (target.src.get(parent.from).content.toLowerCase() == "with") { parentLength = 6; } if (getIndent(keyword.from).indexOf("\n") != -1) { if (alignRight) { var content = target.src.get(keyword.from).content; - var missingSpaces = parentLength - target.src.get(keyword.from).content.length(); + var missingSpaces = parentLength - target.src.get(keyword.from).content.length; var keywordIndent = theLineSeparator + getSpaces(getColumn(parent.from) + missingSpaces) struct.putNewline(keyword.from, keywordIndent); @@ -3690,9 +3701,9 @@ r6_ensure_all_assoc_args_are_on_same_line: runOnce -> { var toRemove = new ArrayList(); - var it = assocValues.keySet().iterator(); - while (it.hasNext()) { - var scope = it.next(); + var keys = assocValues.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var scope = keys[i]; var list = assocValues.get(scope); if (list.size() > 0) { // we start with the second AssocArg @@ -3754,9 +3765,9 @@ a9_find_columns: a9_align_xmltable_columns: runOnce -> { - var it = xmlTableColumns.keySet().iterator(); - while (it.hasNext()) { - var scope = it.next(); + var keys = xmlTableColumns.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var scope = keys[i]; var pos = getColumn(scope.from+1); var list = xmlTableColumns.get(scope); alignAtPos(pos, list, "aligner", null, "a9_align_xmltable_columns"); @@ -3817,9 +3828,9 @@ a20_find_columns: a20_align_json_table_columns: runOnce -> { - var it = jsonTableColumns.keySet().iterator(); - while (it.hasNext()) { - var scope = it.next(); + var keys = jsonTableColumns.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var scope = keys[i]; var pos = getColumn(scope.from+2); // first column var list = jsonTableColumns.get(scope); alignAtPos(pos, list, "aligner", null, "a20_align_json_table_columns"); @@ -3934,9 +3945,9 @@ a4_add_line_breaks_with_indent: var pos = 0; var indent = theLineSeparator; // handle first line for (var key=0; key maxCharLineSize && target.src.get(key).content.length() > 1 && getIndent(key).indexOf("\n") == -1) { + if (pos > maxCharLineSize && target.src.get(key).content.length > 1 && getIndent(key).indexOf("\n") == -1) { struct.putNewline(key, indent); - pos = indent.length() + target.src.get(key).content.length(); + pos = indent.length + target.src.get(key).content.length; logger.fine(struct.getClass(), "a4_add_line_breaks_with_indent: at " + key + "."); } else { var value = getIndent(key); @@ -4015,7 +4026,7 @@ a18_indent_comment: var getIndentBefore = function(pos) { var indent = getIndent(pos); var content = target.src.get(pos).content.toLowerCase(); - if (content.startsWith("end")) { + if (content.indexOf("end") == 0) { indent += getSpaces(indentSpaces); if (target.src.get(pos+1).content.toLowerCase() == "case") { indent += getSpaces(indentSpaces); @@ -4045,7 +4056,7 @@ a18_indent_comment: substitutions.put(tokens[firstWS].begin, tokens[pos].begin, content); logger.fine(struct.getClass(), "a18_indent_comment: at " + parserPos + "."); if (tokens[pos].type == Token.COMMENT) { - var newComment = tokens[pos].content.replaceAll( + var newComment = replaceAll(tokens[pos].content, oldIndent.substring(oldIndent.lastIndexOf("\n")), newIndent.substring(newIndent.lastIndexOf("\n"))); substitutions.put(tokens[pos].begin, tokens[pos].end, newComment); @@ -4143,9 +4154,9 @@ a19_restore_indent_in_conditional_branch: runOnce -> { var indent = getSpaces(indentSpaces); - var it = indentInConditionalBranch.keySet().iterator(); - while (it.hasNext()) { - var key = it.next(); + var keys = indentInConditionalBranch.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var key = keys[i]; var originalIndent = indentInConditionalBranch.get(key); var indent = getIndent(key); if (indent != originalIndent) { @@ -4166,9 +4177,9 @@ a19_restore_indent_in_conditional_branch: a21_remove_non_ws_indent: runOnce -> { - var it = newlinePositions.keySet().iterator(); - while (it.hasNext()) { - var pos = it.next(); + var keys = newlinePositions.keySet().stream().collect(Collectors.toList()).toArray(); + for (var i in keys) { + var pos = keys[i]; var indent = getIndent(pos); var newIndent = replaceAll(indent, "[^\\s]+", ""); if (indent != newIndent) { @@ -4186,7 +4197,7 @@ d2_log_time: runOnce -> { var endTime = (new Date()).getTime(); - logger.info(struct.getClass(), "d2_log_time: formatted " + target.input.length() + " chars and " + logger.info(struct.getClass(), "d2_log_time: formatted " + target.input.length + " chars and " + target.root.to + " nodes in " + ((endTime - startTime) / 1000) + " seconds."); } diff --git a/sqlcl/format.js b/sqlcl/format.js index 89baff3e..c2bd5966 100644 --- a/sqlcl/format.js +++ b/sqlcl/format.js @@ -16,20 +16,35 @@ "use strict"; +// SQLcl uses the Nashorn JS engine of the JDK 8/11 by default. +// As a result, this JS file must comply with ECMAScript 5.1. + +// java.lang var javaString = Java.type("java.lang.String"); -var javaArrays = Java.type("java.util.Arrays"); -var javaPaths = Java.type("java.nio.file.Paths"); -var javaFile = Java.type("java.io.File"); +var javaSystem = Java.type("java.lang.System"); +// java.nio var javaFiles = Java.type("java.nio.file.Files"); var javaFileSystems = Java.type("java.nio.file.FileSystems"); -var javaCollectors = Java.type("java.util.stream.Collectors"); -var javaPersist2XML = Java.type("oracle.dbtools.app.Persist2XML"); +var javaPaths = Java.type("java.nio.file.Paths"); +// java.io +var javaFile = Java.type("java.io.File"); +// java.util +var javaArrays = Java.type("java.util.Arrays"); var javaPattern = Java.type("java.util.regex.Pattern"); +var javaCollectors = Java.type("java.util.stream.Collectors"); +// oracle.dbtools.app var javaFormat = Java.type("oracle.dbtools.app.Format"); +var javaFormat$Breaks = Java.type("oracle.dbtools.app.Format$Breaks"); +var javaFormat$BreaksX2 = Java.type("oracle.dbtools.app.Format$BreaksX2"); +var javaFormat$Case = Java.type("oracle.dbtools.app.Format$Case"); +var javaFormat$FlowControl = Java.type("oracle.dbtools.app.Format$FlowControl"); +var javaFormat$InlineComments = Java.type("oracle.dbtools.app.Format$InlineComments"); +var javaFormat$Space = Java.type("oracle.dbtools.app.Format$Space"); +var javaPersist2XML = Java.type("oracle.dbtools.app.Persist2XML"); +// oracle.dbtools.parser var javaLexer = Java.type("oracle.dbtools.parser.Lexer"); var javaParsed = Java.type("oracle.dbtools.parser.Parsed"); var javaSqlEarley = Java.type("oracle.dbtools.parser.plsql.SqlEarley"); -var javaSystem = Java.type("java.lang.System"); var getFiles = function (rootPath, extensions, ignoreMatcher) { var files; @@ -41,7 +56,7 @@ var getFiles = function (rootPath, extensions, ignoreMatcher) { } } else { files = javaFiles.walk(javaPaths.get(rootPath.toString())) - .filter(function (f) javaFiles.isRegularFile(f) && isRelevantFile(f, extensions, ignoreMatcher)) + .filter(function (f) {return javaFiles.isRegularFile(f) && isRelevantFile(f, extensions, ignoreMatcher)}) .sorted() .collect(javaCollectors.toList()); } @@ -55,7 +70,8 @@ var isRelevantFile = function (file, extensions, ignoreMatcher) { } } for (var i in extensions) { - if (file.toString().toLowerCase().endsWith(extensions[i])) { + var fileName = file.toString().toLowerCase(); + if (fileName.lastIndexOf(extensions[i]) + extensions[i].length === fileName.length) { return true; } } @@ -75,20 +91,20 @@ var getRelevantFiles = function (files, extensions, ignoreMatcher) { } var configure = function (formatter, xmlPath, arboriPath) { - if (!"default".equals(xmlPath) && !"embedded".equals(xmlPath) && xmlPath != null) { + if ("default" !== xmlPath && "embedded" !== xmlPath && xmlPath != null) { var url = new javaFile(xmlPath).toURI().toURL(); var options = javaPersist2XML.read(url); var keySet = options.keySet().stream().collect(javaCollectors.toList()); for (var j in keySet) { formatter.options.put(keySet[j], options.get(keySet[j])); } - } else if ("embedded".equals(xmlPath)) { + } else if ("embedded" === xmlPath) { // Code Editor: Format formatter.options.put(formatter.adjustCaseOnly, false); // default: false (set true to skip formatting) // Advanced Format: General - formatter.options.put(formatter.kwCase, javaFormat.Case.lower); // default: javaFormat.Case.UPPER - formatter.options.put(formatter.idCase, javaFormat.Case.NoCaseChange); // default: javaFormat.Case.lower - formatter.options.put(formatter.singleLineComments, javaFormat.InlineComments.CommentsUnchanged); // default: javaFormat.InlineComments.CommentsUnchanged + formatter.options.put(formatter.kwCase, javaFormat$Case.lower); // default: javaFormat.Case.UPPER + formatter.options.put(formatter.idCase, javaFormat$Case.NoCaseChange); // default: javaFormat.Case.lower + formatter.options.put(formatter.singleLineComments, javaFormat$InlineComments.CommentsUnchanged); // default: javaFormat.InlineComments.CommentsUnchanged // Advanced Format: Alignment formatter.options.put(formatter.alignTabColAliases, false); // default: true formatter.options.put(formatter.alignTypeDecl, true); // default: true @@ -100,28 +116,28 @@ var configure = function (formatter, xmlPath, arboriPath) { formatter.options.put(formatter.identSpaces, 3); // default: 3 formatter.options.put(formatter.useTab, false); // default: false // Advanced Format: Line Breaks - formatter.options.put(formatter.breaksComma, javaFormat.Breaks.After); // default: javaFormat.Breaks.After + formatter.options.put(formatter.breaksComma, javaFormat$Breaks.After); // default: javaFormat.Breaks.After formatter.options.put("commasPerLine", 1); // default: 5 - formatter.options.put(formatter.breaksConcat, javaFormat.Breaks.Before); // default: javaFormat.Breaks.Before - formatter.options.put(formatter.breaksAroundLogicalConjunctions, javaFormat.Breaks.Before); // default: javaFormat.Breaks.Before + formatter.options.put(formatter.breaksConcat, javaFormat$Breaks.Before); // default: javaFormat.Breaks.Before + formatter.options.put(formatter.breaksAroundLogicalConjunctions, javaFormat$Breaks.Before); // default: javaFormat.Breaks.Before formatter.options.put(formatter.breakAnsiiJoin, true); // default: false formatter.options.put(formatter.breakParenCondition, true); // default: false formatter.options.put(formatter.breakOnSubqueries, true); // default: true formatter.options.put(formatter.maxCharLineSize, 120); // default: 128 formatter.options.put(formatter.forceLinebreaksBeforeComment, false); // default: false - formatter.options.put(formatter.extraLinesAfterSignificantStatements, javaFormat.BreaksX2.Keep); // default: javaFormat.BreaksX2.X2 + formatter.options.put(formatter.extraLinesAfterSignificantStatements, javaFormat$BreaksX2.Keep); // default: javaFormat.BreaksX2.X2 formatter.options.put(formatter.breaksAfterSelect, false); // default: true - formatter.options.put(formatter.flowControl, javaFormat.FlowControl.IndentedActions); // default: javaFormat.FlowControl.IndentedActions + formatter.options.put(formatter.flowControl, javaFormat$FlowControl.IndentedActions); // default: javaFormat.FlowControl.IndentedActions // Advanced Format: White Space formatter.options.put(formatter.spaceAroundOperators, true); // default: true formatter.options.put(formatter.spaceAfterCommas, true); // default: true - formatter.options.put(formatter.spaceAroundBrackets, javaFormat.Space.Default); // default: javaFormat.Space.Default + formatter.options.put(formatter.spaceAroundBrackets, javaFormat$Space.Default); // default: javaFormat.Space.Default // Advanced Format: Hidden, not configurable in the GUI preferences dialog of SQLDev 20.4.1 formatter.options.put(formatter.breaksProcArgs, false); // default: false (overridden in Arbori program based on other settings) formatter.options.put(formatter.formatThreshold, 1); // default: 1 (disables deprecated post-processing logic) } var arboriFileName = arboriPath; - if (!"default".equals(arboriPath)) { + if ("default" !== arboriPath) { arboriFileName = new javaFile(arboriPath).getAbsolutePath(); } formatter.options.put(formatter.formatProgramURL, arboriFileName); // default: "default" (= provided by SQLDev / SQLcl) @@ -129,7 +145,7 @@ var configure = function (formatter, xmlPath, arboriPath) { var getConfiguredFormatter = function (xmlPath, arboriPath) { // set relative path for include directive in Arbori program to the directory of the main Arbori program - if (arboriPath != "default") { + if (arboriPath !== "default") { javaSystem.setProperty("dbtools.arbori.home", new javaFile(arboriPath).getParentFile().getAbsolutePath()); } // now instantiate and configure the formatter @@ -158,14 +174,14 @@ var readFile = function (file) { } var writeFile = function (file, content) { - var contentString = new javaString(content); - javaFiles.write(file, contentString.getBytes()); + var writer = javaFiles.newBufferedWriter(file); + writer.write(content); + writer.close(); } var existsDirectory = function (dir) { var f = new javaFile(dir.toString()); return f.isDirectory(); - return true; } var existsFile = function (file) { @@ -207,17 +223,17 @@ var getJsPath = function () { } var getCdPath = function (path) { - if (path.startsWith("/")) { + if (path.indexOf("/") === 0) { return path; // Unix, fully qualified - } else if (path.length > 1 && path.substring(1, 2) == ":") { + } else if (path.length > 1 && path.substring(1, 2) === ":") { return path; // Windows, fully qualified, e.g. C:\mydir } var currentDir = ctx.getProperty("script.runner.cd_command"); if (currentDir == null) { return path; } else { - if (path.endsWith(javaFile.separator)) { - return currentdir + path; + if (path.lastIndexOf(javaFile.separator) + javaFile.separator.length === path.length) { + return currentDir + path; } else { return currentDir + javaFile.separator + path; } @@ -229,7 +245,7 @@ var createIgnoreMatcher = function (ignorePath) { var lines = javaFiles.readAllLines(javaPaths.get(ignorePath)); for (var i=0; i < lines.size(); i++) { var line = lines[i].trim(); - if (line.length > 0 && !line.startsWith('#')) { + if (line.length > 0 && line.indexOf('#') === -1) { if (globPattern.length > 6) { globPattern += ","; } @@ -269,14 +285,14 @@ var processAndValidateArgs = function (args) { return result(false); } rootPath = getCdPath(args[1]); - if (rootPath != "*" && !existsFile(rootPath) && !existsDirectory(rootPath)) { + if (rootPath !== "*" && !existsFile(rootPath) && !existsDirectory(rootPath)) { ctx.write("file or directory " + rootPath + " does not exist.\n\n"); return result(false); } // If the rootPath ends with '.json', then the file is assumed to be a - // instead. - if (rootPath.endsWith('.json')) { + // instead. + if ((rootPath.lastIndexOf('.json') + 5) === rootPath.length) { var configJson = readFile(javaPaths.get(rootPath)); try { configJson = JSON.parse(configJson); @@ -347,7 +363,7 @@ var processAndValidateArgs = function (args) { } for (var i = 2; i < args.length; i++) { - if (args[i].toLowerCase().startsWith("ext=")) { + if (args[i].toLowerCase().indexOf("ext=") === 0) { extArgFound = true; if (args[i].length > 4) { var values = args[i].substring(4).split(","); @@ -357,7 +373,7 @@ var processAndValidateArgs = function (args) { } continue; } - if (args[i].toLowerCase().startsWith("mext=")) { + if (args[i].toLowerCase().indexOf("mext=") === 0) { mextArgFound = true; if (args[i].length > 5) { var values = args[i].substring(5).split(","); @@ -367,15 +383,15 @@ var processAndValidateArgs = function (args) { } continue; } - if (args[i].toLowerCase().startsWith("xml=")) { + if (args[i].toLowerCase().indexOf("xml=") === 0) { xmlPath = args[i].substring(4); continue; } - if (args[i].toLowerCase().startsWith("arbori=")) { + if (args[i].toLowerCase().indexOf("arbori=") === 0) { arboriPath = args[i].substring(7); continue; } - if (args[i].toLowerCase().startsWith("ignore=")) { + if (args[i].toLowerCase().indexOf("ignore=") === 0) { ignorePath = args[i].substring(7); continue; } @@ -399,7 +415,7 @@ var processAndValidateArgs = function (args) { xmlPath = "embedded"; } } else { - if (!"default".equals(xmlPath) && !"embedded".equals(xmlPath)) { + if ("default" !== xmlPath && "embedded" !== xmlPath) { xmlPath = getCdPath(xmlPath); if (!existsFile(xmlPath)) { ctx.write("XML file " + xmlPath + " does not exist.\n\n"); @@ -414,7 +430,7 @@ var processAndValidateArgs = function (args) { arboriPath = "default"; } } else { - if (!"default".equals(arboriPath)) { + if ("default" !== arboriPath) { arboriPath = getCdPath(arboriPath); if (!existsFile(arboriPath)) { ctx.write("Arbori file " + arboriPath + " does not exist.\n\n"); @@ -451,7 +467,8 @@ var formatBuffer = function (formatter) { var isMarkdownFile = function (file, markdownExtensions) { for (var j in markdownExtensions) { - if (file.toString().toLowerCase().endsWith(markdownExtensions[j])) { + var fileName = file.toString().toLowerCase(); + if (fileName.lastIndexOf(markdownExtensions[j]) + markdownExtensions[j].length === fileName.length) { return true; } } @@ -483,9 +500,9 @@ var formatMarkdownFile = function (file, formatter) { var getLineSeparator = function (input) { var lineSep; - if (input.indexOf("\r\n") != -1) { + if (input.indexOf("\r\n") !== -1) { lineSep = "\r\n"; - } else if (input.indexOf("\n") != -1) { + } else if (input.indexOf("\n") !== -1) { lineSep = "\n"; } else { lineSep = javaSystem.lineSeparator(); @@ -520,10 +537,10 @@ var run = function (args) { ctx.write("\n"); var options = processAndValidateArgs(args); if (!options.valid) { - printUsage(args[0].equalsIgnoreCase("tvdformat"), javaSystem.getProperty('tvdformat.standalone') != null); + printUsage(args[0].toLowerCase() === "tvdformat", javaSystem.getProperty('tvdformat.standalone') != null); } else { var formatter = getConfiguredFormatter(options.xmlPath, options.arboriPath); - if (options.rootPath == "*") { + if (options.rootPath === "*") { formatBuffer(formatter); } else { var files; @@ -553,10 +570,10 @@ var unregisterTvdFormat = function () { javaCommandRegistry.removeListener(javaSQLCommand.StmtSubType.G_S_FORALLSTMTS_STMTSUBTYPE); javaCommandRegistry.clearCaches(ctx.getBaseConnection(), ctx); var remainingListeners = javaCommandRegistry.getListeners(ctx.getBaseConnection(), ctx).get(javaSQLCommand.StmtSubType.G_S_FORALLSTMTS_STMTSUBTYPE) - .stream().map(function(l) l.getClass()).collect(javaCollectors.toSet()); + .stream().map(function(l) {return l.getClass()}).collect(javaCollectors.toSet()); // re-register all commands except for class TvdFormat and remaining (not removed) listener classes for (var i in listeners) { - if (!listeners.get(i).toString().equals("TvdFormat") && !remainingListeners.contains(listeners.get(i).getClass())) { + if (listeners.get(i).toString() !== "TvdFormat" && !remainingListeners.contains(listeners.get(i).getClass())) { javaCommandRegistry.addForAllStmtsListener(listeners.get(i).getClass()); } } @@ -565,7 +582,7 @@ var unregisterTvdFormat = function () { var registerTvdFormat = function () { var handleEvent = function (conn, ctx, cmd) { var args = getArgs(cmd.getSql()); - if (args != null && typeof args[0] != "undefined" && args[0].equalsIgnoreCase("tvdformat")) { + if (args != null && typeof args[0] != "undefined" && args[0].toLowerCase() === "tvdformat") { run(args); return true; } @@ -591,7 +608,7 @@ var registerTvdFormat = function () { } // main -if (args.length >= 2 && (args[1].equalsIgnoreCase("-r") || args[1].equalsIgnoreCase("--register"))) { +if (args.length >= 2 && (args[1].toLowerCase() === "-r" || args[1].toLowerCase() === "--register")) { var javaSQLCommand = Java.type("oracle.dbtools.raptor.newscriptrunner.SQLCommand"); var javaCommandRegistry = Java.type("oracle.dbtools.raptor.newscriptrunner.CommandRegistry"); var javaCommandListener = Java.type("oracle.dbtools.raptor.newscriptrunner.CommandListener"); diff --git a/standalone/.gitignore b/standalone/.gitignore index ba2ce844..2bcf61e3 100644 --- a/standalone/.gitignore +++ b/standalone/.gitignore @@ -31,6 +31,7 @@ hs_err_pid* .project .classpath **/.settings +.vscode # IntelliJ **/.idea diff --git a/standalone/README.md b/standalone/README.md index 0d8a2524..2c08a101 100644 --- a/standalone/README.md +++ b/standalone/README.md @@ -2,18 +2,66 @@ ## Introduction -This Maven project produces a standalone command line executable `tvdformat.jar` for the SQLcl script [`format.js`](../sqlcl/format.js). Optionally it produces also a GraalVM native image `tvdformat`. +This Maven project produces a standalone command line executable `tvdformat.jar` for the SQLcl script [`format.js`](../sqlcl/format.js). Optionally it produces also a GraalVM [native image](https://www.graalvm.org/reference-manual/native-image/) `tvdformat`. -The startup time of standalone JAR file and the native image are identical since the image still requires a JDK to execute. However, it is faster than running `format.js` from SQLcl. +The startup time of standalone JAR file and the native image are similar since the image still requires a JDK to execute. However, it is faster than running `format.js` from SQLcl. This project contains JUnit tests for - the SQLDev/SQLcl formatter settings `trivadis_advanced_format.xml` and `trivadis_custom_format.arbori` - the SQLcl script `format.js` - the SQLcl command `tvdformat` -- the standalone executable `tvdformat` +- the standalone exectable `tvdformat` -The project requires a JDK 17, but it produces a Java 8 JAR file. A GraalVM JDK is required only if you want to produce a native image. +The project requires a JDK 17, but it produces a Java 8 executable JAR file. A GraalVM JDK is required only if you want to build a [native image](https://www.graalvm.org/reference-manual/native-image/). + +## Running the Standalone Formatter + +### Configure Logging + +Optionally, you can define the following environment variables: + +Variable | Description +-------- | ----------- +`TVDFORMAT_LOGGING_CONF_FILE` | Path to a [java.util.logging](https://docs.oracle.com/en/java/javase/17/core/java-logging-overview.html#GUID-B83B652C-17EA-48D9-93D2-563AE1FF8EDA) configuration file. Fully qualified or relative paths are supported. [This file](src/test/resources/logging.conf) is used for tests. +`TVDFORMAT_DEBUG` | `true` enables Arbori debug messages. +`TVDFORMAT_TIMING` |`true` enables Arbori query/callback timing messages. + +### Executable JAR + +The `tvdformat.jar` is a shaded, executable JAR. This means it contains all dependend Java classes. However, it still needs a JDK 8 or higher. + +To run it, open a terminal window and type + +``` +java -jar tvdformat.jar +``` + +The parameters are the same as for the [SQLcl command `tvdformat`](../sqlcl/README.md#register-script-formatjs-as-sqlcl-command-tvdformat). Except for formatting the SQLcl buffer, of course. + +### Native Image + +A native image is a platform specific executable. The following images can be produced with a GraalVM JDK 17: + +OS | amd64)? | aarch64? | Requires JDK 8+? | No JDK required? +------- | ------- | -------- | ---------------- | ---------------- +macOS | yes | no | yes | yes +Linux | yes | yes | yes | yes +Windows | yes | no | yes | yes + +Currently there is no way to produce an ARM based (aarch64) native image for macOS and Windows. This reduces the possible combinations from 12 to 8 native images. Native images are not part of a release. You have to build them yourself as described [below](#how-to-build). + +Native images produced with the `--force-fallback` option have a size of around 14 MB. They require a JDK 8+ at runtime and are considered stable. + +Native images produced with the `--no-fallback` option have a size of around 500 MB. They do not require a JDK at runtime. Due to the absence of automatic tests, these images are considered experimental. + +To run a native image open a terminal window and type + +``` +./tvdformat +``` + +The parameters are the same as for the [executable JAR](#executable-jar). ## How to Build @@ -25,12 +73,33 @@ The project requires a JDK 17, but it produces a Java 8 JAR file. A GraalVM JDK 6. Clone the plsql-formatter-settings repository 7. Open a terminal window in the plsql-formatter-settings root folder and type - cd standalone + ``` + cd standalone + ``` + +8. Run Maven build by the following command + + ``` + mvn -Dsqlcl.libdir=/usr/local/bin/sqlcl/lib clean package + ``` + + Amend the parameter `sqlcl.libdir` to match the path of the lib directory of your SQLcl installation. This folder is used to reference libraries such as `dbtools-common.jar` which contains the formatter and its dependencies. These libraries are not available in public Maven repositories. + + You can define the following optional parameters: -6. Run maven build by the following command + | Parameter | Value | Meaning | + | -------------------------- | ------- | ------- | + | `skip.native` | `true` | Do not produce a native image (default) | + | | `false` | Produce a native image | + | `native.image.fallback` | `no` | Produce a native image of about 14 MB which requires a JDK at runtime (default) | + | | `force` | Produce a native image of about 500 MB that runs without JDK | + | `skipTests` | `true` | Run tests (default) | + | | `false` | Do not run tests | + | `disable.logging` | `true` | Disable logging message during test run (default) | + | | `false` | Enable logging message during test run | - mvn -Dsqlcl.libdir=/usr/local/bin/sqlcl/lib -Dskip.native=false clean package + Here's a fully qualified example to produce a native image: - Amend the parameter `sqlcl.libdir` to match the path of the lib directory of you SQLcl installation. This folder is used to reference the `dbtools-common.jar` library (containing the formatter and its dependencies) which is not available in public Maven repositories. - - When you specifiy the parameter `-Dskip.native=false` a native image for your platform is created. When you pass the value `true` (default) then no native image is produced. + ``` + mvn -Dsqlcl.libdir=/usr/local/bin/sqlcl/lib -Dskip.native=false -Dnative.image.fallback=no -DskipTests=true -Ddisable.logging=true clean package + ``` diff --git a/standalone/pom.xml b/standalone/pom.xml index adab7a59..ab9345f1 100644 --- a/standalone/pom.xml +++ b/standalone/pom.xml @@ -17,6 +17,9 @@ 21.3.0 21.2.0 true + + force + true @@ -90,6 +93,17 @@ 5.8.2 test + + + org.reflections + reflections + 0.10.2 + + + org.slf4j + slf4j-jdk14 + 1.7.32 + @@ -179,6 +193,7 @@ META-INF/MANIFEST.MF module-info.class META-INF/versions/** + META-INF/native-image/org.graalvm.*/** @@ -220,17 +235,27 @@ ${skip.native} ${project.artifactId} com.trivadis.plsql.formatter.TvdFormat - - -H:IncludeResources=.* --force-fallback + -H:IncludeResources=.* + -H:DynamicProxyConfigurationFiles=${project.basedir}/src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/proxy-config.json + -H:ReflectionConfigurationFiles=${project.basedir}/src/main/resources/META-INF/native-image/${project.groupId}/${project.artifactId}/reflect-config.json + -H:+ReportExceptionStackTraces + --language:js + --features=com.trivadis.plsql.formatter.RuntimeReflectionRegistrationFeature + --${native.image.fallback}-fallback @@ -243,6 +268,9 @@ **/*.java + + ${disable.logging} + diff --git a/standalone/src/main/java/com/trivadis/plsql/formatter/RuntimeReflectionRegistrationFeature.java b/standalone/src/main/java/com/trivadis/plsql/formatter/RuntimeReflectionRegistrationFeature.java new file mode 100644 index 00000000..85a8c409 --- /dev/null +++ b/standalone/src/main/java/com/trivadis/plsql/formatter/RuntimeReflectionRegistrationFeature.java @@ -0,0 +1,71 @@ +package com.trivadis.plsql.formatter; + +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.nativeimage.hosted.RuntimeReflection; +import org.reflections.Reflections; +import org.reflections.scanners.Scanners; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Set; + +@SuppressWarnings("unused") +public class RuntimeReflectionRegistrationFeature implements Feature { + private static final String[] SKIP_CLASS_NAMES = { + "oracle.dbtools.util.Closeables", + }; + + private static void register(String packageName, boolean includeSubPackages, ClassLoader classLoader) { + Reflections reflections = new Reflections(packageName); + Set allClassNames = reflections.getAll(Scanners.SubTypes); + // allClassNames contains also inner classes + for (String className : allClassNames) { + if (className.startsWith((packageName))) { + if (includeSubPackages || (!className.substring(packageName.length() + 1).contains("."))) { + if (validClass(className)) { + registerClass(className, classLoader); + } + } + } + } + } + + private static boolean validClass(String className) { + for (String skipClassName : SKIP_CLASS_NAMES) { + if (className.startsWith(skipClassName)) { + return false; + } + } + return true; + } + + private static void registerClass(String className, ClassLoader classLoader) { + try { + Class clazz = Class.forName(className, false, classLoader); + // calling getClass() on a clazz throws an Exception when not found on the classpath + RuntimeReflection.register(clazz.getClass()); + for (Constructor constructor : clazz.getDeclaredConstructors()) { + RuntimeReflection.register(constructor); + } + for (Method method : clazz.getDeclaredMethods()) { + RuntimeReflection.register((method)); + } + for (Field field : clazz.getDeclaredFields()) { + RuntimeReflection.register(field); + } + } catch (Throwable t) { + // ignore + } + } + + public void beforeAnalysis(BeforeAnalysisAccess access) { + ClassLoader classLoader = access.getApplicationClassLoader(); + // register all classes in a package + register("oracle.dbtools.app", true, classLoader); + register("oracle.dbtools.arbori", true, classLoader); + register("oracle.dbtools.parser", true, classLoader); + register("oracle.dbtools.raptor", false, classLoader); + register("oracle.dbtools.util", true, classLoader); + } +} diff --git a/standalone/src/main/java/com/trivadis/plsql/formatter/TvdFormat.java b/standalone/src/main/java/com/trivadis/plsql/formatter/TvdFormat.java index ebbe497e..c68e93d8 100644 --- a/standalone/src/main/java/com/trivadis/plsql/formatter/TvdFormat.java +++ b/standalone/src/main/java/com/trivadis/plsql/formatter/TvdFormat.java @@ -1,12 +1,13 @@ package com.trivadis.plsql.formatter; import com.oracle.truffle.js.scriptengine.GraalJSScriptEngine; +import oracle.dbtools.arbori.Program; import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.HostAccess; import javax.script.*; import java.io.*; import java.net.URL; -import java.util.function.Predicate; import java.util.logging.LogManager; public class TvdFormat { @@ -16,8 +17,8 @@ public class TvdFormat { TvdFormat() { scriptEngine = GraalJSScriptEngine.create(null, Context.newBuilder("js") - .option("js.nashorn-compat", "true") - .allowAllAccess(true)); + .allowHostAccess(HostAccess.ALL) + .allowHostClassLookup(s -> true)); ctx = new ScriptRunnerContext(); ctx.setOutputStream(System.out); scriptEngine.getContext().setAttribute("ctx", ctx, ScriptContext.ENGINE_SCOPE); @@ -35,9 +36,33 @@ public void run(String[] arguments) throws IOException, ScriptException { } public static void main(String[] args) throws IOException, ScriptException { + // configure logging LogManager.getLogManager().reset(); + String loggingConfFile = System.getenv("TVDFORMAT_LOGGING_CONF_FILE"); + if (loggingConfFile != null) { + // enable logging according java.util.logging configuration file + try { + LogManager.getLogManager().readConfiguration(new FileInputStream(loggingConfFile)); + } catch (FileNotFoundException e) { + System.out.println("\nWarning: The file '" + loggingConfFile + + "' does not exist. Please update the environment variable TVDFORMAT_LOGGING_CONF_FILE.\n"); + } + } + // enable Arbori program debug + String debug = System.getenv("TVDFORMAT_DEBUG"); + if (debug != null && debug.trim().equalsIgnoreCase("true")) { + Program.debug = true; + } + // enable Arbori program timing + String timing = System.getenv("TVDFORMAT_TIMING"); + if (timing != null && timing.trim().equalsIgnoreCase("true")) { + Program.timing = true; + } + // amend usage help in format.js for standalone tvdformat System.setProperty("tvdformat.standalone", "true"); + // format.js is compiled at runtime with a GraalVM JDK but interpreted with other JDKs System.setProperty("polyglot.engine.WarnInterpreterOnly", "false"); + // run formatter with command line parameters TvdFormat formatter = new TvdFormat(); formatter.run(args); } diff --git a/standalone/src/main/resources/META-INF/native-image/com.trivadis.plsql.formatter/tvdformat/proxy-config.json b/standalone/src/main/resources/META-INF/native-image/com.trivadis.plsql.formatter/tvdformat/proxy-config.json new file mode 100644 index 00000000..08575859 --- /dev/null +++ b/standalone/src/main/resources/META-INF/native-image/com.trivadis.plsql.formatter/tvdformat/proxy-config.json @@ -0,0 +1,4 @@ +[ + [], + ["java.util.function.Predicate"] +] \ No newline at end of file diff --git a/standalone/src/main/resources/META-INF/native-image/com.trivadis.plsql.formatter/tvdformat/reflect-config.json b/standalone/src/main/resources/META-INF/native-image/com.trivadis.plsql.formatter/tvdformat/reflect-config.json new file mode 100644 index 00000000..6c472544 --- /dev/null +++ b/standalone/src/main/resources/META-INF/native-image/com.trivadis.plsql.formatter/tvdformat/reflect-config.json @@ -0,0 +1,517 @@ +[ + { + "name" : "com.trivadis.plsql.formatter.ScriptRunnerContext", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.net.URI", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.Collection", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.HashMap", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.HashMap$KeySet", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.TreeSet", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.lang.Class", + "methods" : [ + {"name" : "getDeclaredField"} + ] + }, + { + "name" : "java.lang.String", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.lang.StringBuilder", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.lang.reflect.Field", + "methods" : [ + { "name" : "setAccessible"}, + { "name" : "get"} + ] + }, + { + "name" : "java.util.Arrays", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.nio.file.Paths", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.io.BufferedWriter", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.io.File", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.nio.file.Files", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.nio.file.FileSystems", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.ArrayList", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.HashMap", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.HashSet", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.Iterator", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.regex.Matcher", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.stream.Collectors", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.stream.ReferencePipeline$Head", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.stream.Stream", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.lang.Integer", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.lang.System", + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.io.PrintStream", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "java.util.regex.Pattern", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Format", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Format$Breaks", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Format$BreaksX2", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Format$Case", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Format$FlowControl", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Format$InlineComments", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Format$Space", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.app.Persist2XML", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.arbori.Program", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.arbori.SqlProgram", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.Lexer", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.LexerToken", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.Parsed", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.ParseNode", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.Substitutions", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.Token", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.plsql.SqlEarley", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.parser.plsql.SyntaxError", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.util.Logger", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + }, + { + "name" : "oracle.dbtools.util.Service", + "allDeclaredConstructors": true, + "allDeclaredMethods": true, + "allDeclaredFields": true, + "allDeclaredClasses": true, + "allPublicConstructors": true, + "allPublicMethods": true, + "allPublicFields": true, + "allPublicClasses": true + } +] \ No newline at end of file diff --git a/standalone/src/test/java/com/trivadis/plsql/formatter/settings/ConfiguredTestFormatter.java b/standalone/src/test/java/com/trivadis/plsql/formatter/settings/ConfiguredTestFormatter.java index 5da57497..aa0bc75f 100644 --- a/standalone/src/test/java/com/trivadis/plsql/formatter/settings/ConfiguredTestFormatter.java +++ b/standalone/src/test/java/com/trivadis/plsql/formatter/settings/ConfiguredTestFormatter.java @@ -28,11 +28,15 @@ private void setArboriHome() { } private void loadLoggingConf() { + var disableLogging = System.getProperty("disable.logging"); var manager = LogManager.getLogManager(); - try { - manager.readConfiguration(Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.conf")); - } catch (SecurityException | IOException e) { - e.printStackTrace(); + manager.reset(); + if (disableLogging != null && !disableLogging.trim().equalsIgnoreCase("true")) { + try { + manager.readConfiguration(Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.conf")); + } catch (SecurityException | IOException e) { + e.printStackTrace(); + } } } diff --git a/standalone/src/test/java/com/trivadis/plsql/formatter/sqlcl/tests/AbstractSqlclTest.java b/standalone/src/test/java/com/trivadis/plsql/formatter/sqlcl/tests/AbstractSqlclTest.java index 74be99e3..678327c6 100644 --- a/standalone/src/test/java/com/trivadis/plsql/formatter/sqlcl/tests/AbstractSqlclTest.java +++ b/standalone/src/test/java/com/trivadis/plsql/formatter/sqlcl/tests/AbstractSqlclTest.java @@ -31,11 +31,15 @@ public abstract class AbstractSqlclTest { } private void loadLoggingConf() { + var disableLogging = System.getProperty("disable.logging"); var manager = LogManager.getLogManager(); - try { - manager.readConfiguration(Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.conf")); - } catch (SecurityException | IOException e) { - e.printStackTrace(); + manager.reset(); + if (disableLogging != null && !disableLogging.trim().equalsIgnoreCase("true")) { + try { + manager.readConfiguration(Thread.currentThread().getContextClassLoader().getResourceAsStream("logging.conf")); + } catch (SecurityException | IOException e) { + e.printStackTrace(); + } } } @@ -51,14 +55,8 @@ public void setup() { var bufferedOutputStream = new BufferedOutputStream(byteArrayOutputStream); var wrapListenBufferOutputStream = new WrapListenBufferOutputStream(bufferedOutputStream); var bindings = new SimpleBindings(); - bindings.put("polyglot.js.nashorn-compat", true); - bindings.put("polyglot.js.allowHostAccess", Boolean.TRUE); - bindings.put("polyglot.js.allowNativeAccess", Boolean.TRUE); - bindings.put("polyglot.js.allowCreateThread", Boolean.TRUE); - bindings.put("polyglot.js.allowIO", Boolean.TRUE); - bindings.put("polyglot.js.allowHostClassLoading", Boolean.TRUE); + bindings.put("polyglot.js.allowHostAccess", true); bindings.put("polyglot.js.allowHostClassLookup", (Predicate) s -> true); - bindings.put("polyglot.js.allowAllAccess", Boolean.TRUE); scriptContext.setBindings(bindings, ScriptContext.ENGINE_SCOPE); sqlcl.setOut(bufferedOutputStream); ctx.setOutputStreamWrapper(wrapListenBufferOutputStream);