HHH-7995 Auto-discovery of Hibernate extension points in OSGi

This commit is contained in:
Brett Meyer 2013-04-22 14:00:54 -04:00
parent bbe408f994
commit a30347552c
8 changed files with 136 additions and 24 deletions

View File

@ -1618,4 +1618,8 @@ public interface CoreMessageLogger extends BasicLogger {
@LogMessage(level = WARN)
@Message(value = "Exception while loading a class or resource found during scanning", id = 449)
void unableToLoadScannedClassOrResource(@Cause Exception e);
@LogMessage(level = WARN)
@Message(value = "Exception while discovering OSGi service implementations : %s", id = 450)
void unableToDiscoverOsgiService(String service, @Cause Exception e);
}

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<blueprint default-activation="eager"
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<bean id="integrator" class="org.hibernate.envers.event.EnversIntegrator"/>
<service ref="integrator" interface="org.hibernate.integrator.spi.Integrator"/>
</blueprint>

View File

@ -1,7 +1,9 @@
dependencies {
compile( project( ':hibernate-core' ) )
compile( project( ':hibernate-entitymanager' ) )
compile( "org.osgi:org.osgi.core:4.3.0" )
// MUST use 4.3.1! 4.3.0 was compiled with "-target jsr14".
// http://blog.osgi.org/2012/10/43-companion-code-for-java-7.html
compile( "org.osgi:org.osgi.core:4.3.1" )
}
jar {

View File

@ -78,10 +78,10 @@ public class HibernateBundleActivator implements BundleActivator {
// using the legacy provider name.
properties.put( "javax.persistence.provider", HibernatePersistence.class.getName() );
context.registerService( PersistenceProvider.class.getName(),
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform ), properties );
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ), properties );
context.registerService( SessionFactory.class.getName(),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform ), new Hashtable());
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ), new Hashtable());
}
@Override

View File

@ -25,6 +25,7 @@ package org.hibernate.osgi;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
@ -33,8 +34,11 @@ import javax.persistence.spi.PersistenceUnitInfo;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.ejb.HibernatePersistence;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.osgi.util.OsgiServiceUtil;
import org.hibernate.service.BootstrapServiceRegistryBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleReference;
/**
@ -46,27 +50,32 @@ public class OsgiPersistenceProvider extends HibernatePersistence {
private OsgiClassLoader osgiClassLoader;
private OsgiJtaPlatform osgiJtaPlatform;
private Bundle requestingBundle;
public OsgiPersistenceProvider (OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform,
Bundle requestingBundle ) {
private BundleContext context;
public OsgiPersistenceProvider(OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform,
Bundle requestingBundle, BundleContext context) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.requestingBundle = requestingBundle;
this.context = context;
}
// TODO: Does "hibernate.classloaders" and osgiClassLoader need added to the
// EMFBuilder somehow?
@Override
public EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) {
if ( properties == null ) {
properties = new HashMap();
}
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
generateProperties( properties );
// TODO: This needs tested.
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
new OsgiScanner( requestingBundle ) );
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER, new OsgiScanner( requestingBundle ) );
// TODO: This is temporary -- for PersistenceXmlParser's use of
// ClassLoaderServiceImpl#fromConfigSettings
properties.put( AvailableSettings.ENVIRONMENT_CLASSLOADER, osgiClassLoader );
osgiClassLoader.addBundle( requestingBundle );
Ejb3Configuration cfg = new Ejb3Configuration();
@ -76,11 +85,9 @@ public class OsgiPersistenceProvider extends HibernatePersistence {
@Override
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
if ( properties == null ) {
properties = new HashMap();
}
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
// OSGi ClassLoaders must implement BundleReference
generateProperties( properties );
// OSGi ClassLoaders must implement BundleReference
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
new OsgiScanner( ( (BundleReference) info.getClassLoader() ).getBundle() ) );
@ -93,6 +100,7 @@ public class OsgiPersistenceProvider extends HibernatePersistence {
private BootstrapServiceRegistryBuilder getBuilder(Map properties) {
BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
final Collection<ClassLoader> classLoaders = (Collection<ClassLoader>) properties
.get( AvailableSettings.CLASSLOADERS );
if ( classLoaders != null ) {
@ -101,6 +109,22 @@ public class OsgiPersistenceProvider extends HibernatePersistence {
}
}
builder.with( osgiClassLoader );
final List<Integrator> integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
for ( Integrator integrator : integrators ) {
builder.with( integrator );
}
// TODO: other types of services?
return builder;
}
private void generateProperties(Map properties) {
if ( properties == null ) {
properties = new HashMap();
}
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
}
}

View File

@ -21,6 +21,7 @@
package org.hibernate.osgi;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
@ -37,14 +38,18 @@ public class OsgiPersistenceProviderService implements ServiceFactory {
private OsgiJtaPlatform osgiJtaPlatform;
public OsgiPersistenceProviderService( OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform ) {
private BundleContext context;
public OsgiPersistenceProviderService( OsgiClassLoader osgiClassLoader,
OsgiJtaPlatform osgiJtaPlatform, BundleContext context ) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.context = context;
}
@Override
public Object getService(Bundle requestingBundle, ServiceRegistration registration) {
return new OsgiPersistenceProvider(osgiClassLoader, osgiJtaPlatform, requestingBundle);
return new OsgiPersistenceProvider(osgiClassLoader, osgiJtaPlatform, requestingBundle, context);
}
@Override

View File

@ -20,13 +20,18 @@
*/
package org.hibernate.osgi;
import java.util.List;
import org.hibernate.SessionFactory;
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.BootstrapServiceRegistryBuilder;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
@ -54,9 +59,13 @@ public class OsgiSessionFactoryService implements ServiceFactory {
private OsgiJtaPlatform osgiJtaPlatform;
public OsgiSessionFactoryService( OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform ) {
private BundleContext context;
public OsgiSessionFactoryService( OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform,
BundleContext context ) {
this.osgiClassLoader = osgiClassLoader;
this.osgiJtaPlatform = osgiJtaPlatform;
this.context = context;
}
@Override
@ -70,8 +79,13 @@ public class OsgiSessionFactoryService implements ServiceFactory {
BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
builder.with( osgiClassLoader );
List<Integrator> integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
for (Integrator integrator : integrators) {
builder.with( integrator );
}
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder( builder.build() )
.applySettings(configuration.getProperties()).buildServiceRegistry();
.applySettings(configuration.getProperties()).buildServiceRegistry();
return configuration.buildSessionFactory(serviceRegistry);
}

View File

@ -0,0 +1,53 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* JBoss, Home of Professional Open Source
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
* as indicated by the @authors tag. All rights reserved.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* 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,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
package org.hibernate.osgi.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.hibernate.internal.CoreMessageLogger;
import org.jboss.logging.Logger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
* @author Brett Meyer
*/
public class OsgiServiceUtil {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
OsgiServiceUtil.class.getName() );
public static <T> List<T> getServiceImpls(Class<T> contract, BundleContext context) {
List<T> serviceImpls = new ArrayList<T>();
try {
Collection<ServiceReference<T>> serviceRefs = context.getServiceReferences( contract, null );
for ( ServiceReference<T> serviceRef : serviceRefs ) {
serviceImpls.add( context.getService( serviceRef ) );
}
}
catch ( Exception e ) {
LOG.unableToDiscoverOsgiService( contract.getName(), e );
}
return serviceImpls;
}
}