HHH-8159 - Apply fixups indicated by analysis tools

This commit is contained in:
Steve Ebersole 2013-04-30 14:40:44 -05:00
parent 97e28200f0
commit 20866585f3
11 changed files with 195 additions and 118 deletions

View File

@ -51,37 +51,40 @@ import org.osgi.framework.FrameworkUtil;
* SessionFactory is registered as an OSGi ServiceFactory -- each requesting
* bundle gets its own instance of a SessionFactory. The use of services,
* rather than direct use of Configuration, is necessary to shield users
* from ClassLoader issues. See {@link #OsgiSessionFactoryService} for more
* from ClassLoader issues. See {@link OsgiSessionFactoryService} for more
* information.
*
* @author Brett Meyer
* @author Tim Ward
*/
@SuppressWarnings("UnusedDeclaration")
public class HibernateBundleActivator implements BundleActivator {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
@Override
@SuppressWarnings("unchecked")
public void start(BundleContext context) throws Exception {
osgiClassLoader = new OsgiClassLoader();
// build a ClassLoader that uses all the necessary OSGi bundles, and place it into
// a well-known location so internals can access it
final OsgiClassLoader osgiClassLoader = new OsgiClassLoader();
osgiClassLoader.addBundle( FrameworkUtil.getBundle( Session.class ) );
osgiClassLoader.addBundle( FrameworkUtil.getBundle( HibernatePersistenceProvider.class ) );
ClassLoaderHelper.overridenClassLoader = osgiClassLoader;
osgiJtaPlatform = new OsgiJtaPlatform( context );
// Build a JtaPlatform specific for this OSGi context
final OsgiJtaPlatform osgiJtaPlatform = new OsgiJtaPlatform( context );
Dictionary properties = new Hashtable();
// In order to support existing persistence.xml files, register
// using the legacy provider name.
final Dictionary properties = new Hashtable();
// In order to support existing persistence.xml files, register using the legacy provider name.
properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() );
context.registerService( PersistenceProvider.class.getName(),
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ), properties );
context.registerService( SessionFactory.class.getName(),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ), new Hashtable());
context.registerService(
PersistenceProvider.class.getName(),
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ),
properties
);
context.registerService(
SessionFactory.class.getName(),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ),
new Hashtable()
);
}
@Override

View File

@ -37,18 +37,26 @@ import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleWiring;
/**
* ArchiveDescriptor implementation for describing archives in the OSGi sense
*
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiArchiveDescriptor implements ArchiveDescriptor {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
OsgiArchiveDescriptor.class.getName()
);
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
OsgiArchiveDescriptor.class.getName() );
private BundleWiring bundleWiring;
private Bundle persistenceBundle;
private final Bundle persistenceBundle;
private final BundleWiring bundleWiring;
/**
* Creates a OsgiArchiveDescriptor
*
* @param persistenceBundle The bundle being described as an archive
*/
@SuppressWarnings("RedundantCast")
public OsgiArchiveDescriptor(Bundle persistenceBundle) {
this.persistenceBundle = persistenceBundle;
bundleWiring = (BundleWiring) persistenceBundle.adapt( BundleWiring.class );
@ -56,14 +64,12 @@ public class OsgiArchiveDescriptor implements ArchiveDescriptor {
@Override
public void visitArchive(ArchiveContext context) {
Collection<String> resources = bundleWiring.listResources( "/", "*", BundleWiring.LISTRESOURCES_RECURSE );
final Collection<String> resources = bundleWiring.listResources( "/", "*", BundleWiring.LISTRESOURCES_RECURSE );
for ( final String resource : resources ) {
// TODO: Is there a better way to check this? Karaf is including
// directories.
// TODO: Is there a better way to check this? Karaf is including directories.
if ( !resource.endsWith( "/" ) ) {
try {
// TODO: Is using resource as the names correct?
final InputStreamAccess inputStreamAccess = new InputStreamAccess() {
@Override
public String getStreamName() {

View File

@ -27,13 +27,19 @@ import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptorFactory;
import org.osgi.framework.Bundle;
/**
* ArchiveDescriptorFactory implementation for OSGi environments
*
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiArchiveDescriptorFactory implements ArchiveDescriptorFactory {
private Bundle persistenceBundle;
/**
* Creates a OsgiArchiveDescriptorFactory
*
* @param persistenceBundle The OSGi bundle being scanned
*/
public OsgiArchiveDescriptorFactory(Bundle persistenceBundle) {
this.persistenceBundle = persistenceBundle;
}

View File

@ -41,15 +41,11 @@ import org.osgi.framework.Bundle;
* @author Tim Ward
*/
public class OsgiClassLoader extends ClassLoader {
private List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
private List<Bundle> bundles = new ArrayList<Bundle>();
private Map<String, Class<?>> classCache = new HashMap<String, Class<?>>();
private Map<String, URL> resourceCache = new HashMap<String, URL>();
private Map<String, Enumeration<URL>> resourceListCache = new HashMap<String, Enumeration<URL>>();
/**
@ -57,8 +53,8 @@ public class OsgiClassLoader extends ClassLoader {
* TODO: Should this throw a different exception or warn if multiple
* classes were found? Naming collisions can and do happen in OSGi...
*/
@SuppressWarnings("rawtypes")
@Override
@SuppressWarnings("rawtypes")
protected Class<?> findClass(String name) throws ClassNotFoundException {
if ( classCache.containsKey( name ) ) {
return classCache.get( name );
@ -66,7 +62,7 @@ public class OsgiClassLoader extends ClassLoader {
for ( Bundle bundle : bundles ) {
try {
Class clazz = bundle.loadClass( name );
final Class clazz = bundle.loadClass( name );
if ( clazz != null ) {
classCache.put( name, clazz );
return clazz;
@ -78,7 +74,7 @@ public class OsgiClassLoader extends ClassLoader {
for ( ClassLoader classLoader : classLoaders ) {
try {
Class clazz = classLoader.loadClass( name );
final Class clazz = classLoader.loadClass( name );
if ( clazz != null ) {
classCache.put( name, clazz );
return clazz;
@ -104,7 +100,7 @@ public class OsgiClassLoader extends ClassLoader {
for ( Bundle bundle : bundles ) {
try {
URL resource = bundle.getResource( name );
final URL resource = bundle.getResource( name );
if ( resource != null ) {
resourceCache.put( name, resource );
return resource;
@ -116,7 +112,7 @@ public class OsgiClassLoader extends ClassLoader {
for ( ClassLoader classLoader : classLoaders ) {
try {
URL resource = classLoader.getResource( name );
final URL resource = classLoader.getResource( name );
if ( resource != null ) {
resourceCache.put( name, resource );
return resource;
@ -135,8 +131,8 @@ public class OsgiClassLoader extends ClassLoader {
* TODO: Should this throw a different exception or warn if multiple
* classes were found? Naming collisions can and do happen in OSGi...
*/
@SuppressWarnings("unchecked")
@Override
@SuppressWarnings("unchecked")
protected Enumeration<URL> findResources(String name) {
if ( resourceListCache.containsKey( name ) ) {
return resourceListCache.get( name );
@ -146,7 +142,7 @@ public class OsgiClassLoader extends ClassLoader {
for ( Bundle bundle : bundles ) {
try {
Enumeration<URL> resources = bundle.getResources( name );
final Enumeration<URL> resources = bundle.getResources( name );
if ( resources != null ) {
enumerations.add( resources );
}
@ -157,7 +153,7 @@ public class OsgiClassLoader extends ClassLoader {
for ( ClassLoader classLoader : classLoaders ) {
try {
Enumeration<URL> resources = classLoader.getResources( name );
final Enumeration<URL> resources = classLoader.getResources( name );
if ( resources != null ) {
enumerations.add( resources );
}
@ -166,7 +162,7 @@ public class OsgiClassLoader extends ClassLoader {
}
}
Enumeration<URL> aggEnumeration = new Enumeration<URL>() {
final Enumeration<URL> aggEnumeration = new Enumeration<URL>() {
@Override
public boolean hasMoreElements() {
for ( Enumeration<URL> enumeration : enumerations ) {
@ -193,14 +189,27 @@ public class OsgiClassLoader extends ClassLoader {
return aggEnumeration;
}
/**
* Adds a ClassLoader to the wrapped set of ClassLoaders
*
* @param classLoader The ClassLoader to add
*/
public void addClassLoader( ClassLoader classLoader ) {
classLoaders.add( classLoader );
}
/**
* Adds a Bundle to the wrapped set of Bundles
*
* @param bundle The Bundle to add
*/
public void addBundle( Bundle bundle ) {
bundles.add( bundle );
}
/**
* Clear all resources.
*/
public void clear() {
classCache.clear();
resourceCache.clear();

View File

@ -38,24 +38,28 @@ import org.osgi.framework.ServiceReference;
* @author Brett Meyer
*/
public class OsgiJtaPlatform implements JtaPlatform {
private static final long serialVersionUID = 1L;
private BundleContext bundleContext;
/**
* Constructs a OsgiJtaPlatform
*
* @param bundleContext The OSGi bundle context
*/
public OsgiJtaPlatform(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
public TransactionManager retrieveTransactionManager() {
ServiceReference sr = bundleContext.getServiceReference( TransactionManager.class.getName() );
final ServiceReference sr = bundleContext.getServiceReference( TransactionManager.class.getName() );
return (TransactionManager) bundleContext.getService( sr );
}
@Override
public UserTransaction retrieveUserTransaction() {
ServiceReference sr = bundleContext.getServiceReference( UserTransaction.class.getName() );
final ServiceReference sr = bundleContext.getServiceReference( UserTransaction.class.getName() );
return (UserTransaction) bundleContext.getService( sr );
}

View File

@ -37,27 +37,36 @@ import org.hibernate.jpa.HibernatePersistenceProvider;
import org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl;
import org.hibernate.jpa.boot.spi.IntegratorProvider;
import org.hibernate.jpa.boot.spi.StrategyRegistrationProviderList;
import org.hibernate.osgi.util.OsgiServiceUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleReference;
/**
* Acts as the PersistenceProvider service in OSGi environments
*
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
private Bundle requestingBundle;
private BundleContext context;
public OsgiPersistenceProvider(OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform,
Bundle requestingBundle, BundleContext context) {
/**
* Constructs a OsgiPersistenceProvider
*
* @param osgiClassLoader The ClassLoader we built from OSGi Bundles
* @param osgiJtaPlatform The OSGi-specific JtaPlatform impl we built
* @param requestingBundle The OSGi Bundle requesting the PersistenceProvider
* @param context The OSGi context
*/
public OsgiPersistenceProvider(
OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform,
Bundle requestingBundle,
BundleContext context) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.requestingBundle = requestingBundle;
@ -68,14 +77,15 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
// EMFBuilder somehow?
@Override
@SuppressWarnings("unchecked")
public EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) {
properties = generateProperties( properties );
final Map settings = generateSettings( properties );
// TODO: This needs tested.
properties.put( org.hibernate.jpa.AvailableSettings.SCANNER, new OsgiScanner( requestingBundle ) );
settings.put( org.hibernate.jpa.AvailableSettings.SCANNER, new OsgiScanner( requestingBundle ) );
// TODO: This is temporary -- for PersistenceXmlParser's use of
// ClassLoaderServiceImpl#fromConfigSettings
properties.put( AvailableSettings.ENVIRONMENT_CLASSLOADER, osgiClassLoader );
settings.put( AvailableSettings.ENVIRONMENT_CLASSLOADER, osgiClassLoader );
osgiClassLoader.addBundle( requestingBundle );
@ -83,45 +93,49 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
}
@Override
@SuppressWarnings("unchecked")
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
properties = generateProperties( properties );
final Map settings = generateSettings( properties );
// OSGi ClassLoaders must implement BundleReference
properties.put( org.hibernate.jpa.AvailableSettings.SCANNER,
new OsgiScanner( ( (BundleReference) info.getClassLoader() ).getBundle() ) );
settings.put(
org.hibernate.jpa.AvailableSettings.SCANNER,
new OsgiScanner( ( (BundleReference) info.getClassLoader() ).getBundle() )
);
osgiClassLoader.addClassLoader( info.getClassLoader() );
return super.createContainerEntityManagerFactory( info, properties );
}
private Map generateProperties(Map properties) {
if ( properties == null ) {
properties = new HashMap();
@SuppressWarnings("unchecked")
private Map generateSettings(Map properties) {
final Map settings = new HashMap();
if ( properties != null ) {
settings.putAll( properties );
}
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
settings.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
final List<Integrator> integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
IntegratorProvider integratorProvider = new IntegratorProvider() {
final IntegratorProvider integratorProvider = new IntegratorProvider() {
@Override
public List<Integrator> getIntegrators() {
return integrators;
}
};
properties.put( EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER, integratorProvider );
settings.put( EntityManagerFactoryBuilderImpl.INTEGRATOR_PROVIDER, integratorProvider );
final List<StrategyRegistrationProvider> strategyRegistrationProviders = OsgiServiceUtil.getServiceImpls(
StrategyRegistrationProvider.class, context );
StrategyRegistrationProviderList strategyRegistrationProviderList = new StrategyRegistrationProviderList() {
final StrategyRegistrationProviderList strategyRegistrationProviderList = new StrategyRegistrationProviderList() {
@Override
public List<StrategyRegistrationProvider> getStrategyRegistrationProviders() {
return strategyRegistrationProviders;
}
};
properties.put( EntityManagerFactoryBuilderImpl.STRATEGY_REGISTRATION_PROVIDERS,
strategyRegistrationProviderList );
settings.put( EntityManagerFactoryBuilderImpl.STRATEGY_REGISTRATION_PROVIDERS, strategyRegistrationProviderList );
return properties;
return settings;
}
}

View File

@ -26,22 +26,28 @@ import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
/**
* See the description on {@link #OsgiSessionFactoryService}. This class
* is similar, providing an PersistenceProvider as an OSGi Service.
* See the description on {@link OsgiSessionFactoryService}. This class is similar, providing an
* PersistenceProvider as an OSGi Service.
*
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiPersistenceProviderService implements ServiceFactory {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
private BundleContext context;
public OsgiPersistenceProviderService( OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform, BundleContext context ) {
/**
* Constructs a OsgiPersistenceProviderService
*
* @param osgiClassLoader The OSGi-specific ClassLoader created in HibernateBundleActivator
* @param osgiJtaPlatform The OSGi-specific JtaPlatform created in HibernateBundleActivator
* @param context The OSGi context
*/
public OsgiPersistenceProviderService(
OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform,
BundleContext context) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.context = context;

View File

@ -31,7 +31,11 @@ import org.osgi.framework.Bundle;
* @author Tim Ward
*/
public class OsgiScanner extends AbstractScannerImpl {
/**
* Constructs the scanner for finding things in a OSGi bundle
*
* @param persistenceBundle The OSGi Bundle to scan
*/
public OsgiScanner(Bundle persistenceBundle) {
super( new OsgiArchiveDescriptorFactory( persistenceBundle ) );
}

View File

@ -18,7 +18,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgi.util;
package org.hibernate.osgi;
import java.util.ArrayList;
import java.util.Collection;
@ -30,17 +30,29 @@ import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
* Utilities for dealing with OSGi environments
*
* @author Brett Meyer
*/
public class OsgiServiceUtil {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
OsgiServiceUtil.class.getName()
);
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
OsgiServiceUtil.class.getName() );
/**
* Locate all implementors of the given service contract in the given OSGi buindle context
*
* @param contract The service contract for which to locate implementors
* @param context The OSGi bundle context
* @param <T> The Java type of the service to locate
*
* @return All know implementors
*/
public static <T> List<T> getServiceImpls(Class<T> contract, BundleContext context) {
List<T> serviceImpls = new ArrayList<T>();
final List<T> serviceImpls = new ArrayList<T>();
try {
Collection<ServiceReference<T>> serviceRefs = context.getServiceReferences( contract, null );
final Collection<ServiceReference<T>> serviceRefs = context.getServiceReferences( contract, null );
for ( ServiceReference<T> serviceRef : serviceRefs ) {
serviceImpls.add( context.getService( serviceRef ) );
}
@ -50,4 +62,7 @@ public class OsgiServiceUtil {
}
return serviceImpls;
}
private OsgiServiceUtil() {
}
}

View File

@ -22,6 +22,11 @@ package org.hibernate.osgi;
import java.util.List;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.BootstrapServiceRegistryBuilder;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
@ -29,12 +34,7 @@ import org.hibernate.boot.registry.selector.StrategyRegistrationProvider;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.osgi.util.OsgiServiceUtil;
import org.hibernate.service.ServiceRegistry;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
/**
* Hibernate 4.2 and 4.3 still heavily rely on TCCL for ClassLoading. Although
@ -42,11 +42,11 @@ import org.osgi.framework.ServiceRegistration;
* unfortunately not available during Configuration. An OSGi
* bundle manually creating a SessionFactory would require numerous ClassLoader
* tricks (or may be impossible altogether).
*
* <p/>
* In order to fully control the TCCL issues and shield users from the
* knowledge, we're requiring that bundles use this OSGi ServiceFactory. It
* configures and provides a SessionFactory as an OSGi service.
*
* <p/>
* Note that an OSGi ServiceFactory differs from a Service. The ServiceFactory
* allows individual instances of Services to be created and provided to
* multiple client Bundles.
@ -55,14 +55,20 @@ import org.osgi.framework.ServiceRegistration;
* @author Tim Ward
*/
public class OsgiSessionFactoryService implements ServiceFactory {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
private BundleContext context;
public OsgiSessionFactoryService( OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform,
/**
* Constructs a OsgiSessionFactoryService
*
* @param osgiClassLoader The OSGi-specific ClassLoader created in HibernateBundleActivator
* @param osgiJtaPlatform The OSGi-specific JtaPlatform created in HibernateBundleActivator
* @param context The OSGi context
*/
public OsgiSessionFactoryService(
OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform,
BundleContext context) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
@ -73,25 +79,25 @@ public class OsgiSessionFactoryService implements ServiceFactory {
public Object getService(Bundle requestingBundle, ServiceRegistration registration) {
osgiClassLoader.addBundle( requestingBundle );
Configuration configuration = new Configuration();
final Configuration configuration = new Configuration();
configuration.getProperties().put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
configuration.configure();
BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
final BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
builder.with( osgiClassLoader );
List<Integrator> integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
final List<Integrator> integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
for ( Integrator integrator : integrators ) {
builder.with( integrator );
}
List<StrategyRegistrationProvider> strategyRegistrationProviders
final List<StrategyRegistrationProvider> strategyRegistrationProviders
= OsgiServiceUtil.getServiceImpls( StrategyRegistrationProvider.class, context );
for ( StrategyRegistrationProvider strategyRegistrationProvider : strategyRegistrationProviders ) {
builder.withStrategySelectors( strategyRegistrationProvider );
}
ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder( builder.build() )
final ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder( builder.build() )
.applySettings( configuration.getProperties() ).build();
return configuration.buildSessionFactory( serviceRegistry );
}

View File

@ -0,0 +1,4 @@
/**
* Main OSGi support classes
*/
package org.hibernate.osgi;