diff --git a/hibernate-core/src/main/java/org/hibernate/QueryException.java b/hibernate-core/src/main/java/org/hibernate/QueryException.java index 475852cc21..eca6070aa4 100644 --- a/hibernate-core/src/main/java/org/hibernate/QueryException.java +++ b/hibernate-core/src/main/java/org/hibernate/QueryException.java @@ -90,11 +90,31 @@ public class QueryException extends HibernateException { @Override public String getMessage() { - String msg = super.getMessage(); + String msg = getOriginalMessage(); if ( queryString != null ) { msg += " [" + queryString + ']'; } return msg; } + protected final String getOriginalMessage() { + return super.getMessage(); + } + + /** + * + * @param queryString + * @return + */ + public final QueryException wrapWithQueryString(String queryString) { + if ( this.getQueryString() != null ) { + return this; + } + + return doWrapWithQueryString( queryString ); + } + + protected QueryException doWrapWithQueryString(String queryString) { + return new QueryException( getOriginalMessage(), queryString, this ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/QueryParameterException.java b/hibernate-core/src/main/java/org/hibernate/QueryParameterException.java index 92998c0029..b86ea91c5b 100644 --- a/hibernate-core/src/main/java/org/hibernate/QueryParameterException.java +++ b/hibernate-core/src/main/java/org/hibernate/QueryParameterException.java @@ -37,4 +37,20 @@ public class QueryParameterException extends QueryException { public QueryParameterException(String message) { super( message ); } + + /** + * Constructs a QueryParameterException + * + * @param message The message explaining the exception condition + * @param queryString The query that led to the exception + * @param cause The underlying cause + */ + public QueryParameterException(String message, String queryString, Exception cause) { + super( message, queryString, cause ); + } + + @Override + protected QueryException doWrapWithQueryString(String queryString) { + return new QueryParameterException( super.getOriginalMessage(), queryString, this ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/QueryExecutionRequestException.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/QueryExecutionRequestException.java index c20f56e9fc..f55bdaf782 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/QueryExecutionRequestException.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/QueryExecutionRequestException.java @@ -33,5 +33,8 @@ import org.hibernate.QueryException; public class QueryExecutionRequestException extends QueryException { public QueryExecutionRequestException(String message, String queryString) { super( message, queryString ); + if ( queryString == null ) { + throw new IllegalArgumentException( "Illegal to pass null as queryString argument" ); + } } } 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 1e3f6341b4..95cba36400 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 @@ -410,7 +410,7 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par AST hqlSqlWithNode = returnAST; if (LOG.isDebugEnabled()) LOG.debugf("handleWithFragment() : %s", getASTPrinter().showAsString(hqlSqlWithNode, "-- with clause --")); - WithClauseVisitor visitor = new WithClauseVisitor( fromElement ); + WithClauseVisitor visitor = new WithClauseVisitor( fromElement, queryTranslatorImpl ); NodeTraverser traverser = new NodeTraverser( visitor ); traverser.traverseDepthFirst( hqlSqlWithNode ); @@ -421,7 +421,10 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par else { FromElement referencedFromElement = visitor.getReferencedFromElement(); if ( referencedFromElement != fromElement ) { - throw new InvalidWithClauseException( "with-clause expressions did not reference from-clause element to which the with-clause was associated" ); + throw new InvalidWithClauseException( + "with-clause expressions did not reference from-clause element to which the with-clause was associated", + queryTranslatorImpl.getQueryString() + ); } } @@ -443,11 +446,14 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par private static class WithClauseVisitor implements NodeTraverser.VisitationStrategy { private final FromElement joinFragment; + private final QueryTranslatorImpl queryTranslatorImpl; + private FromElement referencedFromElement; private String joinAlias; - public WithClauseVisitor(FromElement fromElement) { + public WithClauseVisitor(FromElement fromElement, QueryTranslatorImpl queryTranslatorImpl) { this.joinFragment = fromElement; + this.queryTranslatorImpl = queryTranslatorImpl; } public void visit(AST node) { @@ -477,7 +483,10 @@ public class HqlSqlWalker extends HqlSqlBaseWalker implements ErrorReporter, Par // creates and renders the join fragments for inheritance // hierarchies... if ( !joinAlias.equals( referencedFromElement.getTableAlias() ) ) { - throw new InvalidWithClauseException( "with clause can only reference columns in the driving table" ); + throw new InvalidWithClauseException( + "with clause can only reference columns in the driving table", + queryTranslatorImpl.getQueryString() + ); } } } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/InvalidWithClauseException.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/InvalidWithClauseException.java index aa7f97e336..1630801054 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/InvalidWithClauseException.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/InvalidWithClauseException.java @@ -30,11 +30,10 @@ package org.hibernate.hql.internal.ast; * @author Steve Ebersole */ public class InvalidWithClauseException extends QuerySyntaxException { - public InvalidWithClauseException(String message) { - super( message ); - } - public InvalidWithClauseException(String message, String queryString) { super( message, queryString ); + if ( queryString == null ) { + throw new IllegalArgumentException( "Illegal to pass null as queryString argument" ); + } } } diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QuerySyntaxException.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QuerySyntaxException.java index f2f952f33a..ea97a8ce49 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QuerySyntaxException.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/ast/QuerySyntaxException.java @@ -42,6 +42,10 @@ public class QuerySyntaxException extends QueryException { super( message, hql ); } + protected QuerySyntaxException(String message, String queryString, Exception cause) { + super( message, queryString, cause ); + } + public static QuerySyntaxException convert(RecognitionException e) { return convert( e, null ); } @@ -53,4 +57,8 @@ public class QuerySyntaxException extends QueryException { return new QuerySyntaxException( e.getMessage() + positionInfo, hql ); } + @Override + protected QueryException doWrapWithQueryString(String queryString) { + return new QuerySyntaxException( getOriginalMessage(), queryString, this ); + } } 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 3f0fc884b0..0e1f176767 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 @@ -211,7 +211,7 @@ public class QueryTranslatorImpl implements FilterTranslator { } catch ( QueryException qe ) { if ( qe.getQueryString() == null ) { - throw new QueryException( qe.getMessage(), hql, qe ); + throw qe.wrapWithQueryString( hql ); } else { throw qe; diff --git a/hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java b/hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java index e33092bf97..79c248c62b 100644 --- a/hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/hql/internal/classic/QueryTranslatorImpl.java @@ -245,7 +245,7 @@ public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator } catch ( QueryException qe ) { if ( qe.getQueryString() == null ) { - throw generateQueryException( qe.getMessage(), qe ); + throw qe.wrapWithQueryString( queryString ); } else { throw qe; @@ -257,7 +257,7 @@ public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator catch ( Exception e ) { LOG.debug( "Unexpected query compilation problem", e ); e.printStackTrace(); - throw generateQueryException( "Incorrect query syntax", e ); + throw new QueryException( "Incorrect query syntax", queryString, e ); } postInstantiate(); @@ -266,14 +266,6 @@ public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator } - public QueryException generateQueryException(String message) { - return new QueryException( message, queryString ); - } - - public QueryException generateQueryException(String message, Exception cause) { - return new QueryException( message, queryString, cause ); - } - @Override public String getSQLString() { return sqlString; @@ -557,7 +549,7 @@ public class QueryTranslatorImpl extends BasicLoader implements FilterTranslator public int[] getNamedParameterLocs(String name) throws QueryException { Object o = namedParameters.get( name ); if ( o == null ) { - throw generateQueryException( ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name ); + throw new QueryException( ERROR_NAMED_PARAMETER_DOES_NOT_APPEAR + name, queryString ); } if ( o instanceof Integer ) return new int[] { (Integer) o }; else { diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryRegistry.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryRegistry.java index 9cdfd99886..d40db42ce0 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryRegistry.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionFactoryRegistry.java @@ -24,6 +24,7 @@ package org.hibernate.internal; import java.util.Hashtable; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.naming.Context; import javax.naming.Name; @@ -53,15 +54,34 @@ public class SessionFactoryRegistry { SessionFactoryRegistry.class.getName() ); + /** + * Singleton access + */ public static final SessionFactoryRegistry INSTANCE = new SessionFactoryRegistry(); + /** + * A map for mapping the UUID of a SessionFactory to the corresponding SessionFactory instance + */ private final ConcurrentHashMap sessionFactoryMap = new ConcurrentHashMap(); + + /** + * A cross-reference for mapping a SessionFactory name to its UUID. Not all SessionFactories get named, + */ private final ConcurrentHashMap nameUuidXref = new ConcurrentHashMap(); - public SessionFactoryRegistry() { + private SessionFactoryRegistry() { LOG.debugf( "Initializing SessionFactoryRegistry : %s", this ); } + /** + * Adds a SessionFactory to the registry + * + * @param uuid The uuid under which to register the SessionFactory + * @param name The optional name under which to register the SessionFactory + * @param isNameAlsoJndiName Is name, if provided, also a JNDI name? + * @param instance The SessionFactory instance + * @param jndiService The JNDI service, so we can register a listener if name is a JNDI name + */ public void addSessionFactory( String uuid, String name, @@ -72,7 +92,7 @@ public class SessionFactoryRegistry { throw new IllegalArgumentException( "SessionFactory UUID cannot be null" ); } - LOG.debugf( "Registering SessionFactory: %s (%s)", uuid, name == null ? "" : name ); + LOG.debugf( "Registering SessionFactory: %s (%s)", uuid, name == null ? "" : name ); sessionFactoryMap.put( uuid, instance ); if ( name != null ) { nameUuidXref.put( name, uuid ); @@ -103,6 +123,14 @@ public class SessionFactoryRegistry { } } + /** + * Remove a previously added SessionFactory + * + * @param uuid The uuid + * @param name The optional name + * @param isNameAlsoJndiName Is name, if provided, also a JNDI name? + * @param jndiService The JNDI service + */ public void removeSessionFactory( String uuid, String name, @@ -129,8 +157,15 @@ public class SessionFactoryRegistry { sessionFactoryMap.remove( uuid ); } + /** + * Get a registered SessionFactory by name + * + * @param name The name + * + * @return The SessionFactory + */ public SessionFactory getNamedSessionFactory(String name) { - LOG.debugf( "Lookup: name=%s", name ); + LOG.debugf( "Lookup: name=%s", name ); final String uuid = nameUuidXref.get( name ); return getSessionFactory( uuid ); } @@ -145,6 +180,27 @@ public class SessionFactoryRegistry { return sessionFactory; } + /** + * Does this registry currently contain registrations? + * + * @return true/false + */ + public boolean hasRegistrations() { + return ! sessionFactoryMap.isEmpty(); + } + + public void clearRegistrations() { + nameUuidXref.clear(); + for ( SessionFactory factory : sessionFactoryMap.values() ) { + try { + factory.close(); + } + catch (Exception ignore) { + } + } + sessionFactoryMap.clear(); + } + /** * Implementation of {@literal JNDI} {@link javax.naming.event.NamespaceChangeListener} contract to listener for context events * and react accordingly if necessary @@ -152,7 +208,7 @@ public class SessionFactoryRegistry { private final NamespaceChangeListener LISTENER = new NamespaceChangeListener() { @Override public void objectAdded(NamingEvent evt) { - LOG.debugf("A factory was successfully bound to name: %s", evt.getNewBinding().getName()); + LOG.debugf("A factory was successfully bound to name: %s", evt.getNewBinding().getName()); } @Override @@ -172,7 +228,7 @@ public class SessionFactoryRegistry { final String oldJndiName = evt.getOldBinding().getName(); final String newJndiName = evt.getNewBinding().getName(); - LOG.factoryJndiRename( oldJndiName, newJndiName ); + LOG.factoryJndiRename( oldJndiName, newJndiName ); final String uuid = nameUuidXref.remove( oldJndiName ); nameUuidXref.put( newJndiName, uuid );