From 0546eaac3b6a71eb834f80b75d83b6bf19d58a4e Mon Sep 17 00:00:00 2001 From: Sanne Grinovero Date: Thu, 12 Apr 2018 18:40:31 +0100 Subject: [PATCH] HHH-12511 Make ASTPrinter threadsafe and have code reuse their instances --- .../hibernate/hql/internal/ast/HqlParser.java | 8 +-- .../hql/internal/ast/HqlSqlWalker.java | 7 +-- .../hql/internal/ast/QueryTranslatorImpl.java | 9 +-- .../hql/internal/ast/SqlGenerator.java | 4 +- .../hql/internal/ast/tree/SelectClause.java | 3 +- .../ast/tree/SelectExpressionList.java | 3 +- .../hql/internal/ast/util/ASTPrinter.java | 55 ++++--------------- .../hql/internal/ast/util/TokenPrinters.java | 24 ++++++++ .../antlr/OrderByFragmentRenderer.java | 4 +- .../antlr/OrderByFragmentTranslator.java | 4 +- .../hibernate/test/ast/ASTIteratorTest.java | 4 +- 11 files changed, 56 insertions(+), 69 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/TokenPrinters.java diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlParser.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlParser.java index 9e6e490875..12dc091503 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlParser.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlParser.java @@ -20,6 +20,7 @@ import org.hibernate.hql.internal.antlr.HqlBaseParser; import org.hibernate.hql.internal.antlr.HqlTokenTypes; import org.hibernate.hql.internal.ast.util.ASTPrinter; import org.hibernate.hql.internal.ast.util.ASTUtil; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; @@ -41,11 +42,6 @@ public final class HqlParser extends HqlBaseParser { private static final CoreMessageLogger LOG = CoreLogging.messageLogger( HqlParser.class ); private final ParseErrorHandler parseErrorHandler; - private final ASTPrinter printer = getASTPrinter(); - - private static ASTPrinter getASTPrinter() { - return new ASTPrinter( org.hibernate.hql.internal.antlr.HqlTokenTypes.class ); - } /** * Get a HqlParser instance for the given HQL string. @@ -362,7 +358,7 @@ public final class HqlParser extends HqlBaseParser { } private void showAst(AST ast, PrintWriter pw) { - printer.showAst( ast, pw ); + TokenPrinters.HQL_TOKEN_PRINTER.showAst( ast, pw ); } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java index c361a60e27..f493f9c974 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/HqlSqlWalker.java @@ -65,6 +65,7 @@ import org.hibernate.hql.internal.ast.util.LiteralProcessor; import org.hibernate.hql.internal.ast.util.NodeTraverser; import org.hibernate.hql.internal.ast.util.SessionFactoryHelper; import org.hibernate.hql.internal.ast.util.SyntheticAndFactory; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import org.hibernate.hql.spi.QueryTranslator; import org.hibernate.id.BulkInsertionCapableIdentifierGenerator; import org.hibernate.id.IdentifierGenerator; @@ -118,7 +119,6 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par private final AliasGenerator aliasGenerator = new AliasGenerator(); private final LiteralProcessor literalProcessor; private final ParseErrorHandler parseErrorHandler; - private final ASTPrinter printer; private final String collectionFilterRole; private FromClause currentFromClause; @@ -171,7 +171,6 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par this.tokenReplacements = tokenReplacements; this.collectionFilterRole = collectionRole; this.hqlParser = parser; - this.printer = new ASTPrinter( SqlTokenTypes.class ); } // handle trace logging ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -194,7 +193,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par private String buildTraceNodeName(AST tree) { return tree == null ? "???" - : tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]"; + : tree.getText() + " [" + TokenPrinters.SQL_TOKEN_PRINTER.getTokenTypeName( tree.getType() ) + "]"; } @Override @@ -1337,7 +1336,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par } public ASTPrinter getASTPrinter() { - return printer; + return TokenPrinters.SQL_TOKEN_PRINTER; } public ArrayList getParameterSpecs() { diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java index 5935db05bc..2d4a135c13 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QueryTranslatorImpl.java @@ -42,6 +42,7 @@ import org.hibernate.hql.internal.ast.tree.UpdateStatement; import org.hibernate.hql.internal.ast.util.ASTPrinter; import org.hibernate.hql.internal.ast.util.ASTUtil; import org.hibernate.hql.internal.ast.util.NodeTraverser; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import org.hibernate.hql.spi.FilterTranslator; import org.hibernate.hql.spi.ParameterTranslations; import org.hibernate.internal.CoreMessageLogger; @@ -262,8 +263,6 @@ public class QueryTranslatorImpl implements FilterTranslator { } } - private static final ASTPrinter SQL_TOKEN_PRINTER = new ASTPrinter( SqlTokenTypes.class ); - private HqlSqlWalker analyze(HqlParser parser, String collectionRole) throws QueryException, RecognitionException { final HqlSqlWalker w = new HqlSqlWalker( this, factory, parser, tokenReplacements, collectionRole ); final AST hqlAst = parser.getAST(); @@ -272,7 +271,7 @@ public class QueryTranslatorImpl implements FilterTranslator { w.statement( hqlAst ); if ( LOG.isDebugEnabled() ) { - LOG.debug( SQL_TOKEN_PRINTER.showAsString( w.getAST(), "--- SQL AST ---" ) ); + LOG.debug( TokenPrinters.SQL_TOKEN_PRINTER.showAsString( w.getAST(), "--- SQL AST ---" ) ); } w.getParseErrorHandler().throwQueryException(); @@ -304,11 +303,9 @@ public class QueryTranslatorImpl implements FilterTranslator { return parser; } - private static final ASTPrinter HQL_TOKEN_PRINTER = new ASTPrinter( HqlTokenTypes.class ); - void showHqlAst(AST hqlAst) { if ( LOG.isDebugEnabled() ) { - LOG.debug( HQL_TOKEN_PRINTER.showAsString( hqlAst, "--- HQL AST ---" ) ); + LOG.debug( TokenPrinters.HQL_TOKEN_PRINTER.showAsString( hqlAst, "--- HQL AST ---" ) ); } } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java index ed85c71658..4db85674f0 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/SqlGenerator.java @@ -23,6 +23,7 @@ import org.hibernate.hql.internal.ast.tree.Node; import org.hibernate.hql.internal.ast.tree.ParameterContainer; import org.hibernate.hql.internal.ast.tree.ParameterNode; import org.hibernate.hql.internal.ast.util.ASTPrinter; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import org.hibernate.internal.CoreLogging; import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.util.StringHelper; @@ -57,7 +58,6 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { private ParseErrorHandler parseErrorHandler; private SessionFactoryImplementor sessionFactory; private LinkedList outputStack = new LinkedList(); - private final ASTPrinter printer = new ASTPrinter( SqlTokenTypes.class ); private List collectedParameters = new ArrayList(); @@ -81,7 +81,7 @@ public class SqlGenerator extends SqlGeneratorBase implements ErrorReporter { private String buildTraceNodeName(AST tree) { return tree == null ? "???" - : tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]"; + : tree.getText() + " [" + TokenPrinters.SQL_TOKEN_PRINTER.getTokenTypeName( tree.getType() ) + "]"; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java index c41c910ad8..734d553e71 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectClause.java @@ -16,6 +16,7 @@ import org.hibernate.hql.internal.antlr.SqlTokenTypes; import org.hibernate.hql.internal.ast.util.ASTAppender; import org.hibernate.hql.internal.ast.util.ASTIterator; import org.hibernate.hql.internal.ast.util.ASTPrinter; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import org.hibernate.type.Type; import antlr.SemanticException; @@ -157,7 +158,7 @@ public class SelectClause extends SelectExpressionList { if ( type == null ) { throw new QueryException( "No data type for node: " + selectExpression.getClass().getName() + " " - + new ASTPrinter( SqlTokenTypes.class ).showAsString( (AST) selectExpression, "" ) + + TokenPrinters.SQL_TOKEN_PRINTER.showAsString( (AST) selectExpression, "" ) ); } //sqlResultTypeList.add( type ); diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectExpressionList.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectExpressionList.java index d38d4023ee..46dec1198a 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectExpressionList.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/tree/SelectExpressionList.java @@ -11,6 +11,7 @@ import java.util.List; import org.hibernate.hql.internal.antlr.SqlTokenTypes; import org.hibernate.hql.internal.ast.util.ASTPrinter; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import antlr.collections.AST; @@ -44,7 +45,7 @@ public abstract class SelectExpressionList extends HqlSqlWalkerNode { else { throw new IllegalStateException( "Unexpected AST: " + n.getClass().getName() + " " - + new ASTPrinter( SqlTokenTypes.class ).showAsString( n, "" ) + + TokenPrinters.SQL_TOKEN_PRINTER.showAsString( n, "" ) ); } p++; diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTPrinter.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTPrinter.java index 0d1e10d4d3..fb32e58f4a 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTPrinter.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/ASTPrinter.java @@ -20,52 +20,24 @@ import antlr.collections.AST; /** * Utility for generating pretty "ASCII art" representations of syntax trees. * + * This class is threadsafe: reuse instances as needed. + * * @author Joshua Davis * @author Steve Ebersole */ public class ASTPrinter { + private final Map tokenTypeNameCache; - private final boolean showClassNames; /** - * Constructs a printer. - *

- * Delegates to {@link #ASTPrinter(Class, boolean)} with {@link #isShowClassNames showClassNames} as true + * Constructs a printer. Package protected: use the constants from {TokenPrinters} + * @see TokenPrinters * * @param tokenTypeConstants The token types to use during printing; typically the {vocabulary}TokenTypes.java * interface generated by ANTLR. */ - public ASTPrinter(Class tokenTypeConstants) { - this( ASTUtil.generateTokenNameCache( tokenTypeConstants ), true ); - } - - public ASTPrinter(boolean showClassNames) { - this( (Map) null, showClassNames ); - } - - /** - * Constructs a printer. - * - * @param tokenTypeConstants The token types to use during printing; typically the {vocabulary}TokenTypes.java - * interface generated by ANTLR. - * @param showClassNames Should the AST class names be shown. - */ - public ASTPrinter(Class tokenTypeConstants, boolean showClassNames) { - this( ASTUtil.generateTokenNameCache( tokenTypeConstants ), showClassNames ); - } - - private ASTPrinter(Map tokenTypeNameCache, boolean showClassNames) { - this.tokenTypeNameCache = tokenTypeNameCache; - this.showClassNames = showClassNames; - } - - /** - * Getter for property 'showClassNames'. - * - * @return Value for property 'showClassNames'. - */ - public boolean isShowClassNames() { - return showClassNames; + ASTPrinter(Class tokenTypeConstants) { + this.tokenTypeNameCache = ASTUtil.generateTokenNameCache( tokenTypeConstants ); } /** @@ -117,10 +89,7 @@ public class ASTPrinter { */ public String getTokenTypeName(int type) { final Integer typeInteger = type; - String value = null; - if ( tokenTypeNameCache != null ) { - value = tokenTypeNameCache.get( typeInteger ); - } + String value = tokenTypeNameCache.get( typeInteger ); if ( value == null ) { value = typeInteger.toString(); } @@ -161,19 +130,17 @@ public class ASTPrinter { } private void showNode(PrintWriter pw, AST ast) { - String s = nodeToString( ast, isShowClassNames() ); + String s = nodeToString( ast ); pw.println( s ); } - public String nodeToString(AST ast, boolean showClassName) { + public String nodeToString(AST ast) { if ( ast == null ) { return "{node:null}"; } StringBuilder buf = new StringBuilder(); buf.append( "[" ).append( getTokenTypeName( ast.getType() ) ).append( "] " ); - if ( showClassName ) { - buf.append( StringHelper.unqualify( ast.getClass().getName() ) ).append( ": " ); - } + buf.append( StringHelper.unqualify( ast.getClass().getName() ) ).append( ": " ); buf.append( "'" ); String text = ast.getText(); diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/TokenPrinters.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/TokenPrinters.java new file mode 100644 index 0000000000..66a03adb3b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/util/TokenPrinters.java @@ -0,0 +1,24 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * License: GNU Lesser General Public License (LGPL), version 2.1 or later. + * See the lgpl.txt file in the root directory or . + */ +package org.hibernate.hql.internal.ast.util; + +import org.hibernate.hql.internal.antlr.HqlTokenTypes; +import org.hibernate.hql.internal.antlr.SqlTokenTypes; +import org.hibernate.sql.ordering.antlr.GeneratedOrderByFragmentRendererTokenTypes; + +/** + * Commonly used token printers expressed as constants. + */ +public interface TokenPrinters { + + ASTPrinter HQL_TOKEN_PRINTER = new ASTPrinter( HqlTokenTypes.class ); + + ASTPrinter SQL_TOKEN_PRINTER = new ASTPrinter( SqlTokenTypes.class ); + + ASTPrinter ORDERBY_FRAGMENT_PRINTER = new ASTPrinter( GeneratedOrderByFragmentRendererTokenTypes.class ); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java b/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java index 8b888d8b82..ea0eb25d45 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentRenderer.java @@ -9,6 +9,7 @@ package org.hibernate.sql.ordering.antlr; import org.hibernate.NullPrecedence; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.hql.internal.ast.util.ASTPrinter; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import org.hibernate.internal.util.StringHelper; import org.jboss.logging.Logger; @@ -25,7 +26,6 @@ import antlr.collections.AST; public class OrderByFragmentRenderer extends GeneratedOrderByFragmentRenderer { private static final Logger LOG = Logger.getLogger( OrderByFragmentRenderer.class.getName() ); - private static final ASTPrinter printer = new ASTPrinter( GeneratedOrderByFragmentRendererTokenTypes.class ); private final SessionFactoryImplementor sessionFactory; @@ -56,7 +56,7 @@ public class OrderByFragmentRenderer extends GeneratedOrderByFragmentRenderer { private String buildTraceNodeName(AST tree) { return tree == null ? "???" - : tree.getText() + " [" + printer.getTokenTypeName( tree.getType() ) + "]"; + : tree.getText() + " [" + TokenPrinters.ORDERBY_FRAGMENT_PRINTER.getTokenTypeName( tree.getType() ) + "]"; } @Override diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java b/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java index cb6c7c54ca..69ae897682 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ordering/antlr/OrderByFragmentTranslator.java @@ -11,6 +11,7 @@ import java.util.Set; import org.hibernate.HibernateException; import org.hibernate.hql.internal.ast.util.ASTPrinter; +import org.hibernate.hql.internal.ast.util.TokenPrinters; import org.jboss.logging.Logger; @@ -55,8 +56,7 @@ public class OrderByFragmentTranslator { } if ( LOG.isTraceEnabled() ) { - ASTPrinter printer = new ASTPrinter( OrderByTemplateTokenTypes.class ); - LOG.trace( printer.showAsString( parser.getAST(), "--- {order-by fragment} ---" ) ); + LOG.trace( TokenPrinters.ORDERBY_FRAGMENT_PRINTER.showAsString( parser.getAST(), "--- {order-by fragment} ---" ) ); } // Render the parsed tree to text. diff --git a/hibernate-core/src/test/java/org/hibernate/test/ast/ASTIteratorTest.java b/hibernate-core/src/test/java/org/hibernate/test/ast/ASTIteratorTest.java index ccd015b403..1c278d718c 100644 --- a/hibernate-core/src/test/java/org/hibernate/test/ast/ASTIteratorTest.java +++ b/hibernate-core/src/test/java/org/hibernate/test/ast/ASTIteratorTest.java @@ -18,6 +18,8 @@ import org.hibernate.hql.internal.ast.util.ASTIterator; import org.hibernate.hql.internal.ast.util.ASTParentsFirstIterator; import org.hibernate.hql.internal.ast.util.ASTPrinter; import org.hibernate.hql.internal.ast.util.ASTUtil; +import org.hibernate.hql.internal.ast.util.TokenPrinters; + import org.hibernate.testing.junit4.BaseUnitTestCase; import static org.junit.Assert.assertEquals; @@ -36,7 +38,7 @@ public class ASTIteratorTest extends BaseUnitTestCase { HqlParser parser = HqlParser.getInstance( input ); parser.statement(); AST ast = parser.getAST(); - ASTPrinter printer = new ASTPrinter( HqlTokenTypes.class ); + ASTPrinter printer = TokenPrinters.HQL_TOKEN_PRINTER; printer.showAst( ast, new PrintWriter( System.out ) ); ASTIterator iterator = new ASTIterator( ast ); int count = 0;