HHH-6117 - Figure out best way to handle SessionFactoryObjectFactory dealing with JNDI
This commit is contained in:
parent
ff74ceaaa4
commit
1a40b0232f
|
@ -54,6 +54,8 @@ import org.hibernate.engine.loading.CollectionLoadContext;
|
||||||
import org.hibernate.engine.loading.EntityLoadContext;
|
import org.hibernate.engine.loading.EntityLoadContext;
|
||||||
import org.hibernate.id.IntegralDataTypeHolder;
|
import org.hibernate.id.IntegralDataTypeHolder;
|
||||||
import org.hibernate.service.jdbc.dialect.internal.AbstractDialectResolver;
|
import org.hibernate.service.jdbc.dialect.internal.AbstractDialectResolver;
|
||||||
|
import org.hibernate.service.jndi.JndiException;
|
||||||
|
import org.hibernate.service.jndi.JndiNameException;
|
||||||
import org.hibernate.type.BasicType;
|
import org.hibernate.type.BasicType;
|
||||||
import org.hibernate.type.SerializationException;
|
import org.hibernate.type.SerializationException;
|
||||||
import org.hibernate.type.Type;
|
import org.hibernate.type.Type;
|
||||||
|
@ -310,12 +312,8 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
void factoryBoundToJndiName( String name );
|
void factoryBoundToJndiName( String name );
|
||||||
|
|
||||||
@LogMessage( level = INFO )
|
@LogMessage( level = INFO )
|
||||||
@Message( value = "Factory name: %s", id = 95 )
|
@Message( value = "A factory was renamed from [%s] to [%s] in JNDI", id = 96 )
|
||||||
void factoryName( String name );
|
void factoryJndiRename(String oldName, String newName);
|
||||||
|
|
||||||
@LogMessage( level = INFO )
|
|
||||||
@Message( value = "A factory was renamed from name: %s", id = 96 )
|
|
||||||
void factoryRenamedFromName( String name );
|
|
||||||
|
|
||||||
@LogMessage( level = INFO )
|
@LogMessage( level = INFO )
|
||||||
@Message( value = "Unbound factory from JNDI name: %s", id = 97 )
|
@Message( value = "Unbound factory from JNDI name: %s", id = 97 )
|
||||||
|
@ -438,8 +436,8 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
void indexes( Set keySet );
|
void indexes( Set keySet );
|
||||||
|
|
||||||
@LogMessage( level = WARN )
|
@LogMessage( level = WARN )
|
||||||
@Message( value = "InitialContext did not implement EventContext", id = 127 )
|
@Message( value = "Could not bind JNDI listener", id = 127 )
|
||||||
void initialContextDidNotImplementEventContext();
|
void couldNotBindJndiListener();
|
||||||
|
|
||||||
@LogMessage( level = WARN )
|
@LogMessage( level = WARN )
|
||||||
@Message( value = "InitialContext did not implement EventContext", id = 128 )
|
@Message( value = "InitialContext did not implement EventContext", id = 128 )
|
||||||
|
@ -464,7 +462,7 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
@LogMessage( level = ERROR )
|
@LogMessage( level = ERROR )
|
||||||
@Message( value = "Invalid JNDI name: %s", id = 135 )
|
@Message( value = "Invalid JNDI name: %s", id = 135 )
|
||||||
void invalidJndiName( String name,
|
void invalidJndiName( String name,
|
||||||
@Cause InvalidNameException e );
|
@Cause JndiNameException e );
|
||||||
|
|
||||||
@LogMessage( level = WARN )
|
@LogMessage( level = WARN )
|
||||||
@Message( value = "Inapropriate use of @OnDelete on entity, annotation ignored: %s", id = 136 )
|
@Message( value = "Inapropriate use of @OnDelete on entity, annotation ignored: %s", id = 136 )
|
||||||
|
@ -594,10 +592,6 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
void noSessionFactoryWithJndiName( String sfJNDIName,
|
void noSessionFactoryWithJndiName( String sfJNDIName,
|
||||||
@Cause NameNotFoundException e );
|
@Cause NameNotFoundException e );
|
||||||
|
|
||||||
@LogMessage( level = INFO )
|
|
||||||
@Message( value = "Not binding factory to JNDI, no JNDI name configured", id = 185 )
|
|
||||||
void notBindingFactoryToJndi();
|
|
||||||
|
|
||||||
@LogMessage( level = INFO )
|
@LogMessage( level = INFO )
|
||||||
@Message( value = "Optimistic lock failures: %s", id = 187 )
|
@Message( value = "Optimistic lock failures: %s", id = 187 )
|
||||||
void optimisticLockFailures( long optimisticFailureCount );
|
void optimisticLockFailures( long optimisticFailureCount );
|
||||||
|
@ -910,7 +904,7 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
|
|
||||||
@LogMessage( level = WARN )
|
@LogMessage( level = WARN )
|
||||||
@Message( value = "Could not bind factory to JNDI", id = 277 )
|
@Message( value = "Could not bind factory to JNDI", id = 277 )
|
||||||
void unableToBindFactoryToJndi( @Cause NamingException e );
|
void unableToBindFactoryToJndi( @Cause JndiException e );
|
||||||
|
|
||||||
@LogMessage( level = INFO )
|
@LogMessage( level = INFO )
|
||||||
@Message( value = "Could not bind value '%s' to parameter: %s; %s", id = 278 )
|
@Message( value = "Could not bind value '%s' to parameter: %s; %s", id = 278 )
|
||||||
|
@ -1292,7 +1286,7 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
|
|
||||||
@LogMessage( level = WARN )
|
@LogMessage( level = WARN )
|
||||||
@Message( value = "Could not unbind factory from JNDI", id = 374 )
|
@Message( value = "Could not unbind factory from JNDI", id = 374 )
|
||||||
void unableToUnbindFactoryFromJndi( @Cause NamingException e );
|
void unableToUnbindFactoryFromJndi( @Cause JndiException e );
|
||||||
|
|
||||||
@Message( value = "Could not update hi value in: %s", id = 375 )
|
@Message( value = "Could not update hi value in: %s", id = 375 )
|
||||||
Object unableToUpdateHiValue( String tableName );
|
Object unableToUpdateHiValue( String tableName );
|
||||||
|
@ -1311,10 +1305,6 @@ public interface CoreMessageLogger extends BasicLogger {
|
||||||
void unableToWriteCachedFile( String path,
|
void unableToWriteCachedFile( String path,
|
||||||
String message );
|
String message );
|
||||||
|
|
||||||
@LogMessage( level = INFO )
|
|
||||||
@Message( value = "Unbinding factory from JNDI name: %s", id = 379 )
|
|
||||||
void unbindingFactoryFromJndiName( String name );
|
|
||||||
|
|
||||||
@LogMessage( level = WARN )
|
@LogMessage( level = WARN )
|
||||||
@Message( value = "Unexpected literal token type [%s] passed for numeric processing", id = 380 )
|
@Message( value = "Unexpected literal token type [%s] passed for numeric processing", id = 380 )
|
||||||
void unexpectedLiteralTokenType( int type );
|
void unexpectedLiteralTokenType( int type );
|
||||||
|
|
|
@ -121,6 +121,7 @@ import org.hibernate.proxy.EntityNotFoundDelegate;
|
||||||
import org.hibernate.service.ServiceRegistry;
|
import org.hibernate.service.ServiceRegistry;
|
||||||
import org.hibernate.integrator.spi.IntegratorService;
|
import org.hibernate.integrator.spi.IntegratorService;
|
||||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||||
|
import org.hibernate.service.jndi.spi.JndiService;
|
||||||
import org.hibernate.service.jta.platform.spi.JtaPlatform;
|
import org.hibernate.service.jta.platform.spi.JtaPlatform;
|
||||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||||
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
import org.hibernate.service.spi.SessionFactoryServiceRegistry;
|
||||||
|
@ -397,7 +398,7 @@ public final class SessionFactoryImpl
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
throw new AssertionFailure("Could not generate UUID");
|
throw new AssertionFailure("Could not generate UUID");
|
||||||
}
|
}
|
||||||
SessionFactoryObjectFactory.addInstance(uuid, name, this, properties);
|
SessionFactoryRegistry.INSTANCE.addSessionFactory( uuid, name, this, serviceRegistry.getService( JndiService.class ) );
|
||||||
|
|
||||||
LOG.debugf("Instantiated session factory");
|
LOG.debugf("Instantiated session factory");
|
||||||
|
|
||||||
|
@ -709,13 +710,14 @@ public final class SessionFactoryImpl
|
||||||
return collectionRolesByEntityParticipant.get( entityName );
|
return collectionRolesByEntityParticipant.get( entityName );
|
||||||
}
|
}
|
||||||
|
|
||||||
// from javax.naming.Referenceable
|
@Override
|
||||||
public Reference getReference() throws NamingException {
|
public Reference getReference() throws NamingException {
|
||||||
LOG.debugf( "Returning a Reference to the SessionFactory" );
|
// from javax.naming.Referenceable
|
||||||
|
LOG.debug( "Returning a Reference to the SessionFactory" );
|
||||||
return new Reference(
|
return new Reference(
|
||||||
SessionFactoryImpl.class.getName(),
|
SessionFactoryImpl.class.getName(),
|
||||||
new StringRefAddr("uuid", uuid),
|
new StringRefAddr("uuid", uuid),
|
||||||
SessionFactoryObjectFactory.class.getName(),
|
SessionFactoryRegistry.ObjectFactoryImpl.class.getName(),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -723,14 +725,19 @@ public final class SessionFactoryImpl
|
||||||
private Object readResolve() throws ObjectStreamException {
|
private Object readResolve() throws ObjectStreamException {
|
||||||
LOG.trace("Resolving serialized SessionFactory");
|
LOG.trace("Resolving serialized SessionFactory");
|
||||||
// look for the instance by uuid
|
// look for the instance by uuid
|
||||||
Object result = SessionFactoryObjectFactory.getInstance(uuid);
|
Object result = SessionFactoryRegistry.INSTANCE.getSessionFactory( uuid );
|
||||||
if (result==null) {
|
if ( result == null ) {
|
||||||
// in case we were deserialized in a different JVM, look for an instance with the same name
|
// in case we were deserialized in a different JVM, look for an instance with the same name
|
||||||
// (alternatively we could do an actual JNDI lookup here....)
|
// (alternatively we could do an actual JNDI lookup here....)
|
||||||
result = SessionFactoryObjectFactory.getNamedInstance(name);
|
result = SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( name );
|
||||||
if (result == null) throw new InvalidObjectException("Could not find a SessionFactory named: " + name);
|
if ( result == null ) {
|
||||||
|
throw new InvalidObjectException( "Could not find a SessionFactory [uuid=" + uuid + ",name=" + name + "]" );
|
||||||
|
}
|
||||||
LOG.debugf("Resolved SessionFactory by name");
|
LOG.debugf("Resolved SessionFactory by name");
|
||||||
} else LOG.debugf("Resolved SessionFactory by UID");
|
}
|
||||||
|
else {
|
||||||
|
LOG.debugf("Resolved SessionFactory by UUID");
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,7 +938,9 @@ public final class SessionFactoryImpl
|
||||||
schemaExport.drop( false, true );
|
schemaExport.drop( false, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionFactoryObjectFactory.removeInstance(uuid, name, properties);
|
SessionFactoryRegistry.INSTANCE.removeSessionFactory(
|
||||||
|
uuid, name, serviceRegistry.getService( JndiService.class )
|
||||||
|
);
|
||||||
|
|
||||||
observer.sessionFactoryClosed( this );
|
observer.sessionFactoryClosed( this );
|
||||||
serviceRegistry.destroy();
|
serviceRegistry.destroy();
|
||||||
|
@ -1264,17 +1273,14 @@ public final class SessionFactoryImpl
|
||||||
* @throws ClassNotFoundException indicates problems reading back serial data stream
|
* @throws ClassNotFoundException indicates problems reading back serial data stream
|
||||||
*/
|
*/
|
||||||
static SessionFactoryImpl deserialize(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
static SessionFactoryImpl deserialize(ObjectInputStream ois) throws IOException, ClassNotFoundException {
|
||||||
String uuid = ois.readUTF();
|
final String uuid = ois.readUTF();
|
||||||
boolean isNamed = ois.readBoolean();
|
boolean isNamed = ois.readBoolean();
|
||||||
String name = null;
|
final String name = isNamed ? ois.readUTF() : null;
|
||||||
if ( isNamed ) {
|
Object result = SessionFactoryRegistry.INSTANCE.getSessionFactory( uuid );
|
||||||
name = ois.readUTF();
|
|
||||||
}
|
|
||||||
Object result = SessionFactoryObjectFactory.getInstance( uuid );
|
|
||||||
if ( result == null ) {
|
if ( result == null ) {
|
||||||
LOG.trace("Could not locate session factory by uuid [" + uuid + "] during session deserialization; trying name");
|
LOG.trace("Could not locate session factory by uuid [" + uuid + "] during session deserialization; trying name");
|
||||||
if ( isNamed ) {
|
if ( isNamed ) {
|
||||||
result = SessionFactoryObjectFactory.getNamedInstance( name );
|
result = SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( name );
|
||||||
}
|
}
|
||||||
if ( result == null ) {
|
if ( result == null ) {
|
||||||
throw new InvalidObjectException( "could not resolve session factory during session deserialization [uuid=" + uuid + ", name=" + name + "]" );
|
throw new InvalidObjectException( "could not resolve session factory during session deserialization [uuid=" + uuid + ", name=" + name + "]" );
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* Copyright (c) 2010, Red Hat Inc. or third-party contributors as
|
|
||||||
* indicated by the @author tags or express copyright attribution
|
|
||||||
* statements applied by the authors. All third-party contributions are
|
|
||||||
* distributed under license by Red Hat Inc.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
|
||||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
|
||||||
* Lesser General Public License, as published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this distribution; if not, write to:
|
|
||||||
* Free Software Foundation, Inc.
|
|
||||||
* 51 Franklin Street, Fifth Floor
|
|
||||||
* Boston, MA 02110-1301 USA
|
|
||||||
*/
|
|
||||||
package org.hibernate.internal;
|
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import javax.naming.Context;
|
|
||||||
import javax.naming.InvalidNameException;
|
|
||||||
import javax.naming.Name;
|
|
||||||
import javax.naming.NamingException;
|
|
||||||
import javax.naming.Reference;
|
|
||||||
import javax.naming.event.EventContext;
|
|
||||||
import javax.naming.event.NamespaceChangeListener;
|
|
||||||
import javax.naming.event.NamingEvent;
|
|
||||||
import javax.naming.event.NamingExceptionEvent;
|
|
||||||
import javax.naming.event.NamingListener;
|
|
||||||
import javax.naming.spi.ObjectFactory;
|
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
|
||||||
import org.hibernate.internal.util.jndi.JndiHelper;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolves {@link SessionFactory} instances during <tt>JNDI<tt> look-ups as well as during deserialization
|
|
||||||
*/
|
|
||||||
public class SessionFactoryObjectFactory implements ObjectFactory {
|
|
||||||
|
|
||||||
@SuppressWarnings({ "UnusedDeclaration" })
|
|
||||||
private static final SessionFactoryObjectFactory INSTANCE; //to stop the class from being unloaded
|
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class,
|
|
||||||
SessionFactoryObjectFactory.class.getName());
|
|
||||||
|
|
||||||
static {
|
|
||||||
INSTANCE = new SessionFactoryObjectFactory();
|
|
||||||
LOG.debugf("Initializing class SessionFactoryObjectFactory");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final ConcurrentHashMap<String, SessionFactory> INSTANCES = new ConcurrentHashMap<String, SessionFactory>();
|
|
||||||
private static final ConcurrentHashMap<String, SessionFactory> NAMED_INSTANCES = new ConcurrentHashMap<String, SessionFactory>();
|
|
||||||
|
|
||||||
private static final NamingListener LISTENER = new NamespaceChangeListener() {
|
|
||||||
public void objectAdded(NamingEvent evt) {
|
|
||||||
LOG.debugf("A factory was successfully bound to name: %s", evt.getNewBinding().getName());
|
|
||||||
}
|
|
||||||
public void objectRemoved(NamingEvent evt) {
|
|
||||||
String name = evt.getOldBinding().getName();
|
|
||||||
LOG.factoryUnboundFromName(name);
|
|
||||||
Object instance = NAMED_INSTANCES.remove(name);
|
|
||||||
Iterator iter = INSTANCES.values().iterator();
|
|
||||||
while ( iter.hasNext() ) {
|
|
||||||
if ( iter.next()==instance ) iter.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public void objectRenamed(NamingEvent evt) {
|
|
||||||
String name = evt.getOldBinding().getName();
|
|
||||||
LOG.factoryRenamedFromName(name);
|
|
||||||
NAMED_INSTANCES.put( evt.getNewBinding().getName(), NAMED_INSTANCES.remove(name) );
|
|
||||||
}
|
|
||||||
public void namingExceptionThrown(NamingExceptionEvent evt) {
|
|
||||||
//noinspection ThrowableResultOfMethodCallIgnored
|
|
||||||
LOG.namingExceptionAccessingFactory(evt.getException());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public Object getObjectInstance(Object reference, Name name, Context ctx, Hashtable env) throws Exception {
|
|
||||||
LOG.debugf("JNDI lookup: %s", name);
|
|
||||||
String uid = (String) ( (Reference) reference ).get(0).getContent();
|
|
||||||
return getInstance(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addInstance(String uid, String name, SessionFactory instance, Properties properties) {
|
|
||||||
LOG.debugf("Registered: %s (%s)", uid, name == null ? "<unnamed>" : name);
|
|
||||||
INSTANCES.put(uid, instance);
|
|
||||||
if (name!=null) NAMED_INSTANCES.put(name, instance);
|
|
||||||
|
|
||||||
//must add to JNDI _after_ adding to HashMaps, because some JNDI servers use serialization
|
|
||||||
if (name == null) LOG.notBindingFactoryToJndi();
|
|
||||||
else {
|
|
||||||
LOG.factoryName(name);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Context ctx = JndiHelper.getInitialContext(properties);
|
|
||||||
JndiHelper.bind(ctx, name, instance);
|
|
||||||
LOG.factoryBoundToJndiName(name);
|
|
||||||
( (EventContext) ctx ).addNamingListener(name, EventContext.OBJECT_SCOPE, LISTENER);
|
|
||||||
}
|
|
||||||
catch (InvalidNameException ine) {
|
|
||||||
LOG.invalidJndiName(name, ine);
|
|
||||||
}
|
|
||||||
catch (NamingException ne) {
|
|
||||||
LOG.unableToBindFactoryToJndi(ne);
|
|
||||||
}
|
|
||||||
catch(ClassCastException cce) {
|
|
||||||
LOG.initialContextDidNotImplementEventContext();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void removeInstance(String uid, String name, Properties properties) {
|
|
||||||
//TODO: theoretically non-threadsafe...
|
|
||||||
|
|
||||||
if (name!=null) {
|
|
||||||
LOG.unbindingFactoryFromJndiName(name);
|
|
||||||
|
|
||||||
try {
|
|
||||||
Context ctx = JndiHelper.getInitialContext(properties);
|
|
||||||
ctx.unbind(name);
|
|
||||||
LOG.factoryUnboundFromJndiName(name);
|
|
||||||
}
|
|
||||||
catch (InvalidNameException ine) {
|
|
||||||
LOG.invalidJndiName(name, ine);
|
|
||||||
}
|
|
||||||
catch (NamingException ne) {
|
|
||||||
LOG.unableToUnbindFactoryFromJndi(ne);
|
|
||||||
}
|
|
||||||
|
|
||||||
NAMED_INSTANCES.remove(name);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
INSTANCES.remove(uid);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object getNamedInstance(String name) {
|
|
||||||
LOG.debugf("Lookup: name=%s", name);
|
|
||||||
Object result = NAMED_INSTANCES.get(name);
|
|
||||||
if (result==null) {
|
|
||||||
LOG.debugf("Not found: %s", name);
|
|
||||||
LOG.debugf(NAMED_INSTANCES.toString());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Object getInstance(String uid) {
|
|
||||||
LOG.debugf("Lookup: uid=%s", uid);
|
|
||||||
Object result = INSTANCES.get(uid);
|
|
||||||
if (result==null) {
|
|
||||||
LOG.debugf("Not found: %s", uid);
|
|
||||||
LOG.debugf(INSTANCES.toString());
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,182 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.internal;
|
||||||
|
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.Name;
|
||||||
|
import javax.naming.Reference;
|
||||||
|
import javax.naming.event.NamespaceChangeListener;
|
||||||
|
import javax.naming.event.NamingEvent;
|
||||||
|
import javax.naming.event.NamingExceptionEvent;
|
||||||
|
import javax.naming.spi.ObjectFactory;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.SessionFactory;
|
||||||
|
import org.hibernate.service.jndi.JndiException;
|
||||||
|
import org.hibernate.service.jndi.JndiNameException;
|
||||||
|
import org.hibernate.service.jndi.spi.JndiService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A registry of all {@link SessionFactory} instances for the same classloader as this class.
|
||||||
|
*
|
||||||
|
* This registry is used for serialization/deserialization as well as JNDI binding.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class SessionFactoryRegistry {
|
||||||
|
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
|
||||||
|
CoreMessageLogger.class,
|
||||||
|
SessionFactoryRegistry.class.getName()
|
||||||
|
);
|
||||||
|
|
||||||
|
public static final SessionFactoryRegistry INSTANCE = new SessionFactoryRegistry();
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<String, SessionFactory> sessionFactoryMap = new ConcurrentHashMap<String, SessionFactory>();
|
||||||
|
private final ConcurrentHashMap<String,String> nameUuidXref = new ConcurrentHashMap<String, String>();
|
||||||
|
|
||||||
|
public SessionFactoryRegistry() {
|
||||||
|
LOG.debugf( "Initializing SessionFactoryRegistry : %s", this );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addSessionFactory(String uuid, String name, SessionFactory instance, JndiService jndiService) {
|
||||||
|
LOG.debugf( "Registering SessionFactory: %s (%s)", uuid, name == null ? "<unnamed>" : name );
|
||||||
|
sessionFactoryMap.put( uuid, instance );
|
||||||
|
|
||||||
|
if ( name == null ) {
|
||||||
|
LOG.debug( "Not binding factory to JNDI, no JNDI name configured" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nameUuidXref.put( name, uuid );
|
||||||
|
|
||||||
|
LOG.debugf( "SessionFactory name : %s, attempting to bind to JNDI", name );
|
||||||
|
|
||||||
|
try {
|
||||||
|
jndiService.bind( name, instance );
|
||||||
|
LOG.factoryBoundToJndiName( name );
|
||||||
|
try {
|
||||||
|
jndiService.addListener( name, LISTENER );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOG.couldNotBindJndiListener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (JndiNameException e) {
|
||||||
|
LOG.invalidJndiName( name, e );
|
||||||
|
}
|
||||||
|
catch (JndiException e) {
|
||||||
|
LOG.unableToBindFactoryToJndi( e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeSessionFactory(String uuid, String name, JndiService jndiService) {
|
||||||
|
if ( name != null ) {
|
||||||
|
try {
|
||||||
|
LOG.tracef( "Unbinding SessionFactory from JNDI : %s", name );
|
||||||
|
jndiService.unbind( name );
|
||||||
|
LOG.factoryUnboundFromJndiName( name );
|
||||||
|
}
|
||||||
|
catch ( JndiNameException e ) {
|
||||||
|
LOG.invalidJndiName( name, e );
|
||||||
|
}
|
||||||
|
catch ( JndiException e ) {
|
||||||
|
LOG.unableToUnbindFactoryFromJndi( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
nameUuidXref.remove( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionFactoryMap.remove( uuid );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionFactory getNamedSessionFactory(String name) {
|
||||||
|
LOG.debugf( "Lookup: name=%s", name );
|
||||||
|
final String uuid = nameUuidXref.get( name );
|
||||||
|
return getSessionFactory( uuid );
|
||||||
|
}
|
||||||
|
|
||||||
|
public SessionFactory getSessionFactory(String uuid) {
|
||||||
|
LOG.debugf( "Lookup: uid=%s", uuid );
|
||||||
|
final SessionFactory sessionFactory = sessionFactoryMap.get( uuid );
|
||||||
|
if ( sessionFactory == null ) {
|
||||||
|
LOG.debugf( "Not found: %s", uuid );
|
||||||
|
LOG.debugf( sessionFactoryMap.toString() );
|
||||||
|
}
|
||||||
|
return sessionFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of {@literal JNDI} {@link javax.naming.event.NamespaceChangeListener} contract to listener for context events
|
||||||
|
* and react accordingly if necessary
|
||||||
|
*/
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void objectRemoved(NamingEvent evt) {
|
||||||
|
final String jndiName = evt.getOldBinding().getName();
|
||||||
|
LOG.factoryUnboundFromName( jndiName );
|
||||||
|
|
||||||
|
final String uuid = nameUuidXref.remove( jndiName );
|
||||||
|
if ( uuid == null ) {
|
||||||
|
// serious problem... but not sure what to do yet
|
||||||
|
}
|
||||||
|
sessionFactoryMap.remove( uuid );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void objectRenamed(NamingEvent evt) {
|
||||||
|
final String oldJndiName = evt.getOldBinding().getName();
|
||||||
|
final String newJndiName = evt.getNewBinding().getName();
|
||||||
|
|
||||||
|
LOG.factoryJndiRename( oldJndiName, newJndiName );
|
||||||
|
|
||||||
|
final String uuid = nameUuidXref.remove( oldJndiName );
|
||||||
|
nameUuidXref.put( newJndiName, uuid );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void namingExceptionThrown(NamingExceptionEvent evt) {
|
||||||
|
//noinspection ThrowableResultOfMethodCallIgnored
|
||||||
|
LOG.namingExceptionAccessingFactory(evt.getException());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static class ObjectFactoryImpl implements ObjectFactory {
|
||||||
|
@Override
|
||||||
|
public Object getObjectInstance(Object reference, Name name, Context nameCtx, Hashtable<?, ?> environment)
|
||||||
|
throws Exception {
|
||||||
|
LOG.debugf( "JNDI lookup: %s", name );
|
||||||
|
final String uuid = (String) ( (Reference) reference ).get( 0 ).getContent();
|
||||||
|
LOG.tracef( "Resolved to UUID = %s", uuid );
|
||||||
|
return INSTANCE.getSessionFactory( uuid );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,5 +28,6 @@
|
||||||
<p>
|
<p>
|
||||||
An internal package containing mostly implementations of central Hibernate APIs of the
|
An internal package containing mostly implementations of central Hibernate APIs of the
|
||||||
{@link org.hibernate} package.
|
{@link org.hibernate} package.
|
||||||
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -22,33 +22,35 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.internal.util.jndi;
|
package org.hibernate.internal.util.jndi;
|
||||||
import java.util.Hashtable;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.Set;
|
|
||||||
import javax.naming.Context;
|
import javax.naming.Context;
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.Name;
|
import javax.naming.Name;
|
||||||
import javax.naming.NameNotFoundException;
|
import javax.naming.NameNotFoundException;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
/**
|
||||||
|
* Helper for dealing with JNDI.
|
||||||
|
*
|
||||||
|
* @deprecated As JNDI access should get routed through {@link org.hibernate.service.jndi.spi.JndiService}
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
public final class JndiHelper {
|
public final class JndiHelper {
|
||||||
|
|
||||||
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, JndiHelper.class.getName());
|
|
||||||
|
|
||||||
private JndiHelper() {
|
private JndiHelper() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a hodge-podge of properties, extract out the ones relevant for JNDI interaction.
|
* Given a hodgepodge of properties, extract out the ones relevant for JNDI interaction.
|
||||||
*
|
*
|
||||||
* @param properties
|
* @param configurationValues The map of config values
|
||||||
* @return
|
*
|
||||||
|
* @return The extracted JNDI specific properties.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings({ "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
public static Properties extractJndiProperties(Map configurationValues) {
|
public static Properties extractJndiProperties(Map configurationValues) {
|
||||||
|
@ -83,117 +85,12 @@ public final class JndiHelper {
|
||||||
return jndiProperties;
|
return jndiProperties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Do a JNDI lookup. Mainly we are handling {@link NamingException}
|
|
||||||
*
|
|
||||||
* @param jndiName The namespace of the object to locate
|
|
||||||
* @param context The context in which to resolve the namespace.
|
|
||||||
*
|
|
||||||
* @return The located object; may be null.
|
|
||||||
*
|
|
||||||
* @throws JndiException if a {@link NamingException} occurs
|
|
||||||
*/
|
|
||||||
public static Object locate(String jndiName, Context context) {
|
|
||||||
try {
|
|
||||||
return context.lookup( jndiName );
|
|
||||||
}
|
|
||||||
catch ( NamingException e ) {
|
|
||||||
throw new JndiException( "Unable to lookup JNDI name [" + jndiName + "]", e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Bind val to name in ctx, and make sure that all intermediate contexts exist.
|
|
||||||
*
|
|
||||||
* @param ctx the root context
|
|
||||||
* @param name the name as a string
|
|
||||||
* @param val the object to be bound
|
|
||||||
*
|
|
||||||
* @throws JndiException if a {@link NamingException} occurs
|
|
||||||
*/
|
|
||||||
public static void bind(String jndiName, Object value, Context context) {
|
|
||||||
try {
|
|
||||||
LOG.trace("Binding : " + jndiName);
|
|
||||||
context.rebind( jndiName, value );
|
|
||||||
}
|
|
||||||
catch ( Exception initialException ) {
|
|
||||||
// We had problems doing a simple bind operation. This could very well be caused by missing intermediate
|
|
||||||
// contexts, so we attempt to create those intermmediate contexts and bind again
|
|
||||||
Name n = tokenizeName( jndiName, context );
|
|
||||||
Context intermediateContextBase = context;
|
|
||||||
while ( n.size() > 1 ) {
|
|
||||||
final String intermediateContextName = n.get( 0 );
|
|
||||||
|
|
||||||
Context intermediateContext = null;
|
|
||||||
try {
|
|
||||||
LOG.trace("Intermediate lookup: " + intermediateContextName);
|
|
||||||
intermediateContext = (Context) intermediateContextBase.lookup( intermediateContextName );
|
|
||||||
}
|
|
||||||
catch ( NameNotFoundException handledBelow ) {
|
|
||||||
// ok as we will create it below if not found
|
|
||||||
}
|
|
||||||
catch ( NamingException e ) {
|
|
||||||
throw new JndiException( "Unaniticipated error doing intermediate lookup", e );
|
|
||||||
}
|
|
||||||
|
|
||||||
if (intermediateContext != null) LOG.trace("Found intermediate context: " + intermediateContextName);
|
|
||||||
else {
|
|
||||||
LOG.trace("Creating subcontext: " + intermediateContextName);
|
|
||||||
try {
|
|
||||||
intermediateContext = intermediateContextBase.createSubcontext( intermediateContextName );
|
|
||||||
}
|
|
||||||
catch ( NamingException e ) {
|
|
||||||
throw new JndiException( "Error creating intermediate context [" + intermediateContextName + "]", e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intermediateContextBase = intermediateContext;
|
|
||||||
n = n.getSuffix( 1 );
|
|
||||||
}
|
|
||||||
LOG.trace("Binding : " + n);
|
|
||||||
try {
|
|
||||||
intermediateContextBase.rebind( n, value );
|
|
||||||
}
|
|
||||||
catch ( NamingException e ) {
|
|
||||||
throw new JndiException( "Error performing intermediate bind [" + n + "]", e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG.debugf("Bound name: %s", jndiName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Name tokenizeName(String jndiName, Context context) {
|
|
||||||
try {
|
|
||||||
return context.getNameParser( "" ).parse( jndiName );
|
|
||||||
}
|
|
||||||
catch ( NamingException e ) {
|
|
||||||
throw new JndiException( "Unable to tokenize JNDI name [" + jndiName + "]", e );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// todo : remove these once we get the services in place and integrated into the SessionFactory
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static InitialContext getInitialContext(Properties props) throws NamingException {
|
public static InitialContext getInitialContext(Properties props) throws NamingException {
|
||||||
|
|
||||||
Hashtable hash = extractJndiProperties(props);
|
Hashtable hash = extractJndiProperties(props);
|
||||||
LOG.jndiInitialContextProperties(hash);
|
|
||||||
try {
|
|
||||||
return hash.size()==0 ?
|
return hash.size()==0 ?
|
||||||
new InitialContext() :
|
new InitialContext() :
|
||||||
new InitialContext(hash);
|
new InitialContext(hash);
|
||||||
}
|
}
|
||||||
catch (NamingException e) {
|
|
||||||
LOG.unableToObtainInitialContext(e);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bind val to name in ctx, and make sure that all intermediate contexts exist.
|
* Bind val to name in ctx, and make sure that all intermediate contexts exist.
|
||||||
|
@ -201,11 +98,11 @@ public final class JndiHelper {
|
||||||
* @param ctx the root context
|
* @param ctx the root context
|
||||||
* @param name the name as a string
|
* @param name the name as a string
|
||||||
* @param val the object to be bound
|
* @param val the object to be bound
|
||||||
* @throws NamingException
|
*
|
||||||
|
* @throws NamingException Indicates a problem performing the bind.
|
||||||
*/
|
*/
|
||||||
public static void bind(Context ctx, String name, Object val) throws NamingException {
|
public static void bind(Context ctx, String name, Object val) throws NamingException {
|
||||||
try {
|
try {
|
||||||
LOG.trace("Binding : " + name);
|
|
||||||
ctx.rebind(name, val);
|
ctx.rebind(name, val);
|
||||||
}
|
}
|
||||||
catch (Exception e) {
|
catch (Exception e) {
|
||||||
|
@ -215,25 +112,21 @@ public final class JndiHelper {
|
||||||
|
|
||||||
Context subctx=null;
|
Context subctx=null;
|
||||||
try {
|
try {
|
||||||
LOG.trace("Lookup: " + ctxName);
|
|
||||||
subctx = (Context) ctx.lookup(ctxName);
|
subctx = (Context) ctx.lookup(ctxName);
|
||||||
}
|
}
|
||||||
catch (NameNotFoundException nfe) {}
|
catch (NameNotFoundException ignore) {
|
||||||
|
}
|
||||||
|
|
||||||
if (subctx!=null) {
|
if (subctx!=null) {
|
||||||
LOG.debugf("Found subcontext: %s", ctxName);
|
|
||||||
ctx = subctx;
|
ctx = subctx;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LOG.creatingSubcontextInfo(ctxName);
|
|
||||||
ctx = ctx.createSubcontext(ctxName);
|
ctx = ctx.createSubcontext(ctxName);
|
||||||
}
|
}
|
||||||
n = n.getSuffix(1);
|
n = n.getSuffix(1);
|
||||||
}
|
}
|
||||||
LOG.trace("Binding : " + n);
|
|
||||||
ctx.rebind(n, val);
|
ctx.rebind(n, val);
|
||||||
}
|
}
|
||||||
LOG.debugf("Bound name: %s", name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,9 +47,10 @@ import org.hibernate.TypeHelper;
|
||||||
import org.hibernate.engine.FilterDefinition;
|
import org.hibernate.engine.FilterDefinition;
|
||||||
import org.hibernate.id.IdentifierGenerator;
|
import org.hibernate.id.IdentifierGenerator;
|
||||||
import org.hibernate.id.UUIDGenerator;
|
import org.hibernate.id.UUIDGenerator;
|
||||||
import org.hibernate.internal.SessionFactoryObjectFactory;
|
import org.hibernate.internal.SessionFactoryRegistry;
|
||||||
import org.hibernate.metadata.ClassMetadata;
|
import org.hibernate.metadata.ClassMetadata;
|
||||||
import org.hibernate.metadata.CollectionMetadata;
|
import org.hibernate.metadata.CollectionMetadata;
|
||||||
|
import org.hibernate.service.jndi.internal.JndiServiceImpl;
|
||||||
import org.hibernate.stat.Statistics;
|
import org.hibernate.stat.Statistics;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -79,7 +80,7 @@ public class SessionFactoryStub implements SessionFactory {
|
||||||
throw new AssertionFailure("Could not generate UUID");
|
throw new AssertionFailure("Could not generate UUID");
|
||||||
}
|
}
|
||||||
|
|
||||||
SessionFactoryObjectFactory.addInstance( uuid, name, this, service.getProperties() );
|
SessionFactoryRegistry.INSTANCE.addSessionFactory( uuid, name, this, new JndiServiceImpl( service.getProperties() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -103,25 +104,31 @@ public class SessionFactoryStub implements SessionFactory {
|
||||||
//readResolveObject
|
//readResolveObject
|
||||||
private Object readResolve() throws ObjectStreamException {
|
private Object readResolve() throws ObjectStreamException {
|
||||||
// look for the instance by uuid
|
// look for the instance by uuid
|
||||||
Object result = SessionFactoryObjectFactory.getInstance(uuid);
|
Object result = SessionFactoryRegistry.INSTANCE.getSessionFactory( uuid ) ;
|
||||||
if (result==null) {
|
if ( result == null ) {
|
||||||
// in case we were deserialized in a different JVM, look for an instance with the same name
|
// in case we were deserialized in a different JVM, look for an instance with the same name
|
||||||
// (alternatively we could do an actual JNDI lookup here....)
|
// (alternatively we could do an actual JNDI lookup here....)
|
||||||
result = SessionFactoryObjectFactory.getNamedInstance(name);
|
result = SessionFactoryRegistry.INSTANCE.getNamedSessionFactory( name );
|
||||||
if (result == null) throw new InvalidObjectException("Could not find a stub SessionFactory named: " + name);
|
if ( result == null ) {
|
||||||
|
throw new InvalidObjectException( "Could not find a SessionFactory [uuid=" + uuid + ",name=" + name + "]" );
|
||||||
|
}
|
||||||
LOG.debugf("Resolved stub SessionFactory by name");
|
LOG.debugf("Resolved stub SessionFactory by name");
|
||||||
} else LOG.debugf("Resolved stub SessionFactory by uid");
|
}
|
||||||
|
else {
|
||||||
|
LOG.debugf("Resolved stub SessionFactory by UUID");
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see javax.naming.Referenceable#getReference()
|
* @see javax.naming.Referenceable#getReference()
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public Reference getReference() throws NamingException {
|
public Reference getReference() throws NamingException {
|
||||||
return new Reference(
|
return new Reference(
|
||||||
SessionFactoryStub.class.getName(),
|
SessionFactoryStub.class.getName(),
|
||||||
new StringRefAddr("uuid", uuid),
|
new StringRefAddr("uuid", uuid),
|
||||||
SessionFactoryObjectFactory.class.getName(),
|
SessionFactoryRegistry.ObjectFactoryImpl.class.getName(),
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
//$Id: StatisticsService.java 8262 2005-09-30 07:48:53Z oneovthafew $
|
|
||||||
package org.hibernate.jmx;
|
package org.hibernate.jmx;
|
||||||
|
|
||||||
import javax.naming.InitialContext;
|
import javax.naming.InitialContext;
|
||||||
import javax.naming.NameNotFoundException;
|
import javax.naming.NameNotFoundException;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.naming.Reference;
|
import javax.naming.Reference;
|
||||||
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
import org.hibernate.SessionFactory;
|
import org.hibernate.SessionFactory;
|
||||||
import org.hibernate.internal.SessionFactoryObjectFactory;
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.SessionFactoryRegistry;
|
||||||
import org.hibernate.stat.CollectionStatistics;
|
import org.hibernate.stat.CollectionStatistics;
|
||||||
import org.hibernate.stat.EntityStatistics;
|
import org.hibernate.stat.EntityStatistics;
|
||||||
import org.hibernate.stat.QueryStatistics;
|
import org.hibernate.stat.QueryStatistics;
|
||||||
|
@ -15,8 +17,6 @@ import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||||
import org.hibernate.stat.Statistics;
|
import org.hibernate.stat.Statistics;
|
||||||
import org.hibernate.stat.internal.ConcurrentStatisticsImpl;
|
import org.hibernate.stat.internal.ConcurrentStatisticsImpl;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JMX service for Hibernate statistics<br>
|
* JMX service for Hibernate statistics<br>
|
||||||
* <br>
|
* <br>
|
||||||
|
@ -64,14 +64,16 @@ public class StatisticsService implements StatisticsServiceMBean {
|
||||||
public void setSessionFactoryJNDIName(String sfJNDIName) {
|
public void setSessionFactoryJNDIName(String sfJNDIName) {
|
||||||
this.sfJNDIName = sfJNDIName;
|
this.sfJNDIName = sfJNDIName;
|
||||||
try {
|
try {
|
||||||
Object obj = new InitialContext().lookup(sfJNDIName);
|
final SessionFactory sessionFactory;
|
||||||
if (obj instanceof Reference) {
|
final Object jndiValue = new InitialContext().lookup( sfJNDIName );
|
||||||
Reference ref = (Reference) obj;
|
if ( jndiValue instanceof Reference ) {
|
||||||
setSessionFactory( (SessionFactory) SessionFactoryObjectFactory.getInstance( (String) ref.get(0).getContent() ) );
|
final String uuid = (String) ( (Reference) jndiValue ).get( 0 ).getContent();
|
||||||
|
sessionFactory = SessionFactoryRegistry.INSTANCE.getSessionFactory( uuid );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setSessionFactory( (SessionFactory) obj );
|
sessionFactory = (SessionFactory) jndiValue;
|
||||||
}
|
}
|
||||||
|
setSessionFactory( sessionFactory );
|
||||||
}
|
}
|
||||||
catch (NameNotFoundException e) {
|
catch (NameNotFoundException e) {
|
||||||
LOG.noSessionFactoryWithJndiName(sfJNDIName, e);
|
LOG.noSessionFactoryWithJndiName(sfJNDIName, e);
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
* 51 Franklin Street, Fifth Floor
|
* 51 Franklin Street, Fifth Floor
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.internal.util.jndi;
|
package org.hibernate.service.jndi;
|
||||||
import org.hibernate.HibernateException;
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* Copyright (c) 2011, Red Hat Inc. or third-party contributors as
|
||||||
|
* indicated by the @author tags or express copyright attribution
|
||||||
|
* statements applied by the authors. All third-party contributions are
|
||||||
|
* distributed under license by Red Hat Inc.
|
||||||
|
*
|
||||||
|
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||||
|
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||||
|
* Lesser General Public License, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
|
* for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this distribution; if not, write to:
|
||||||
|
* Free Software Foundation, Inc.
|
||||||
|
* 51 Franklin Street, Fifth Floor
|
||||||
|
* Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
package org.hibernate.service.jndi;
|
||||||
|
|
||||||
|
import org.hibernate.HibernateException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates a problem with a given JNDI name being deemed as not valid.
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class JndiNameException extends HibernateException {
|
||||||
|
public JndiNameException(String string, Throwable root) {
|
||||||
|
super( string, root );
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,18 +22,26 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.service.jndi.internal;
|
package org.hibernate.service.jndi.internal;
|
||||||
|
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
import javax.naming.InvalidNameException;
|
||||||
|
import javax.naming.Name;
|
||||||
|
import javax.naming.NameNotFoundException;
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.naming.event.EventContext;
|
||||||
|
import javax.naming.event.NamespaceChangeListener;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import javax.naming.InitialContext;
|
|
||||||
import javax.naming.NamingException;
|
|
||||||
|
|
||||||
import org.hibernate.internal.CoreMessageLogger;
|
|
||||||
import org.hibernate.internal.util.jndi.JndiException;
|
|
||||||
import org.hibernate.internal.util.jndi.JndiHelper;
|
|
||||||
import org.hibernate.service.jndi.spi.JndiService;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import org.hibernate.internal.CoreMessageLogger;
|
||||||
|
import org.hibernate.internal.util.jndi.JndiHelper;
|
||||||
|
import org.hibernate.service.jndi.JndiException;
|
||||||
|
import org.hibernate.service.jndi.JndiNameException;
|
||||||
|
import org.hibernate.service.jndi.spi.JndiService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard implementation of JNDI services.
|
* Standard implementation of JNDI services.
|
||||||
*
|
*
|
||||||
|
@ -52,16 +60,15 @@ public class JndiServiceImpl implements JndiService {
|
||||||
@Override
|
@Override
|
||||||
public Object locate(String jndiName) {
|
public Object locate(String jndiName) {
|
||||||
InitialContext initialContext = buildInitialContext();
|
InitialContext initialContext = buildInitialContext();
|
||||||
|
Name name = parseName( jndiName, initialContext );
|
||||||
try {
|
try {
|
||||||
return JndiHelper.locate( jndiName, initialContext );
|
return initialContext.lookup( name );
|
||||||
}
|
|
||||||
finally {
|
|
||||||
try {
|
|
||||||
initialContext.close();
|
|
||||||
}
|
}
|
||||||
catch ( NamingException e ) {
|
catch ( NamingException e ) {
|
||||||
LOG.unableToCloseInitialContext(e.toString());
|
throw new JndiException( "Unable to lookup JNDI name [" + jndiName + "]", e );
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
cleanUp( initialContext );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,13 +81,19 @@ public class JndiServiceImpl implements JndiService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private Name parseName(String jndiName, Context context) {
|
||||||
public void bind(String jndiName, Object value) {
|
|
||||||
InitialContext initialContext = buildInitialContext();
|
|
||||||
try {
|
try {
|
||||||
JndiHelper.bind( jndiName, value, initialContext );
|
return context.getNameParser( "" ).parse( jndiName );
|
||||||
}
|
}
|
||||||
finally {
|
catch ( InvalidNameException e ) {
|
||||||
|
throw new JndiNameException( "JNDI name [" + jndiName + "] was not valid", e );
|
||||||
|
}
|
||||||
|
catch ( NamingException e ) {
|
||||||
|
throw new JndiException( "Error parsing JNDI name [" + jndiName + "]", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cleanUp(InitialContext initialContext) {
|
||||||
try {
|
try {
|
||||||
initialContext.close();
|
initialContext.close();
|
||||||
}
|
}
|
||||||
|
@ -88,5 +101,101 @@ public class JndiServiceImpl implements JndiService {
|
||||||
LOG.unableToCloseInitialContext(e.toString());
|
LOG.unableToCloseInitialContext(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bind(String jndiName, Object value) {
|
||||||
|
InitialContext initialContext = buildInitialContext();
|
||||||
|
Name name = parseName( jndiName, initialContext );
|
||||||
|
try {
|
||||||
|
bind( name, value, initialContext );
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
cleanUp( initialContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bind(Name name, Object value, Context context) {
|
||||||
|
try {
|
||||||
|
LOG.tracef( "Binding : %s", name );
|
||||||
|
context.rebind( name, value );
|
||||||
|
}
|
||||||
|
catch ( Exception initialException ) {
|
||||||
|
// We had problems doing a simple bind operation.
|
||||||
|
if ( name.size() == 1 ) {
|
||||||
|
// if the jndi name had only 1 component there is nothing more we can do...
|
||||||
|
throw new JndiException( "Error performing bind [" + name + "]", initialException );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, there is a good chance this may have been caused by missing intermediate contexts. So we
|
||||||
|
// attempt to create those missing intermediate contexts and bind again
|
||||||
|
Context intermediateContextBase = context;
|
||||||
|
while ( name.size() > 1 ) {
|
||||||
|
final String intermediateContextName = name.get( 0 );
|
||||||
|
|
||||||
|
Context intermediateContext = null;
|
||||||
|
try {
|
||||||
|
LOG.trace("Intermediate lookup: " + intermediateContextName);
|
||||||
|
intermediateContext = (Context) intermediateContextBase.lookup( intermediateContextName );
|
||||||
|
}
|
||||||
|
catch ( NameNotFoundException handledBelow ) {
|
||||||
|
// ok as we will create it below if not found
|
||||||
|
}
|
||||||
|
catch ( NamingException e ) {
|
||||||
|
throw new JndiException( "Unanticipated error doing intermediate lookup", e );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (intermediateContext != null) LOG.trace("Found intermediate context: " + intermediateContextName);
|
||||||
|
else {
|
||||||
|
LOG.trace("Creating sub-context: " + intermediateContextName);
|
||||||
|
try {
|
||||||
|
intermediateContext = intermediateContextBase.createSubcontext( intermediateContextName );
|
||||||
|
}
|
||||||
|
catch ( NamingException e ) {
|
||||||
|
throw new JndiException( "Error creating intermediate context [" + intermediateContextName + "]", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
intermediateContextBase = intermediateContext;
|
||||||
|
name = name.getSuffix( 1 );
|
||||||
|
}
|
||||||
|
LOG.trace("Binding : " + name);
|
||||||
|
try {
|
||||||
|
intermediateContextBase.rebind( name, value );
|
||||||
|
}
|
||||||
|
catch ( NamingException e ) {
|
||||||
|
throw new JndiException( "Error performing intermediate bind [" + name + "]", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG.debugf( "Bound name: %s", name );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unbind(String jndiName) {
|
||||||
|
InitialContext initialContext = buildInitialContext();
|
||||||
|
Name name = parseName( jndiName, initialContext );
|
||||||
|
try {
|
||||||
|
initialContext.unbind( name );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new JndiException( "Error performing unbind [" + name + "]", e );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
cleanUp( initialContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(String jndiName, NamespaceChangeListener listener) {
|
||||||
|
InitialContext initialContext = buildInitialContext();
|
||||||
|
Name name = parseName( jndiName, initialContext );
|
||||||
|
try {
|
||||||
|
( (EventContext) initialContext ).addNamingListener( name, EventContext.OBJECT_SCOPE, listener );
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new JndiException( "Unable to bind listener to namespace [" + name + "]", e );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
cleanUp( initialContext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,28 +23,45 @@
|
||||||
*/
|
*/
|
||||||
package org.hibernate.service.jndi.spi;
|
package org.hibernate.service.jndi.spi;
|
||||||
|
|
||||||
|
import javax.naming.event.NamespaceChangeListener;
|
||||||
|
|
||||||
import org.hibernate.service.Service;
|
import org.hibernate.service.Service;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service providing simplified access to JNDI related features needed by Hibernate.
|
* Service providing simplified access to {@literal JNDI} related features needed by Hibernate.
|
||||||
*
|
*
|
||||||
* @author Steve Ebersole
|
* @author Steve Ebersole
|
||||||
*/
|
*/
|
||||||
public interface JndiService extends Service {
|
public interface JndiService extends Service {
|
||||||
/**
|
/**
|
||||||
* Locate an object in JNDI by name
|
* Locate an object in {@literal JNDI} by name
|
||||||
*
|
*
|
||||||
* @param jndiName The JNDI name of the object to locate
|
* @param jndiName The {@literal JNDI} name of the object to locate
|
||||||
*
|
*
|
||||||
* @return The object found (may be null).
|
* @return The object found (may be null).
|
||||||
*/
|
*/
|
||||||
public Object locate(String jndiName);
|
public Object locate(String jndiName);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Binds a value into JNDI by name.
|
* Binds a value into {@literal JNDI} by name.
|
||||||
*
|
*
|
||||||
* @param jndiName The name under whcih to bind the object
|
* @param jndiName The name under which to bind the object
|
||||||
* @param value The value to bind
|
* @param value The value to bind
|
||||||
*/
|
*/
|
||||||
public void bind(String jndiName, Object value);
|
public void bind(String jndiName, Object value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unbind a value from {@literal JNDI} by name.
|
||||||
|
*
|
||||||
|
* @param jndiName The name under which the object is bound
|
||||||
|
*/
|
||||||
|
public void unbind(String jndiName);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the specified listener to the given {@literal JNDI} namespace.
|
||||||
|
*
|
||||||
|
* @param jndiName The {@literal JNDI} namespace
|
||||||
|
* @param listener The listener
|
||||||
|
*/
|
||||||
|
public void addListener(String jndiName, NamespaceChangeListener listener);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue