Skip to content

Commit a303475

Browse files
committed
HHH-7995 Auto-discovery of Hibernate extension points in OSGi
1 parent bbe408f commit a303475

File tree

8 files changed

+136
-24
lines changed

8 files changed

+136
-24
lines changed

hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1618,4 +1618,8 @@ void cannotResolveNonNullableTransientDependencies(String transientEntityString,
16181618
@LogMessage(level = WARN)
16191619
@Message(value = "Exception while loading a class or resource found during scanning", id = 449)
16201620
void unableToLoadScannedClassOrResource(@Cause Exception e);
1621+
1622+
@LogMessage(level = WARN)
1623+
@Message(value = "Exception while discovering OSGi service implementations : %s", id = 450)
1624+
void unableToDiscoverOsgiService(String service, @Cause Exception e);
16211625
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<blueprint default-activation="eager"
4+
xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
6+
7+
<bean id="integrator" class="org.hibernate.envers.event.EnversIntegrator"/>
8+
<service ref="integrator" interface="org.hibernate.integrator.spi.Integrator"/>
9+
10+
</blueprint>

hibernate-osgi/hibernate-osgi.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
dependencies {
22
compile( project( ':hibernate-core' ) )
33
compile( project( ':hibernate-entitymanager' ) )
4-
compile( "org.osgi:org.osgi.core:4.3.0" )
4+
// MUST use 4.3.1! 4.3.0 was compiled with "-target jsr14".
5+
// http://blog.osgi.org/2012/10/43-companion-code-for-java-7.html
6+
compile( "org.osgi:org.osgi.core:4.3.1" )
57
}
68

79
jar {

hibernate-osgi/src/main/java/org/hibernate/osgi/HibernateBundleActivator.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,10 @@ public void start(BundleContext context) throws Exception {
7878
// using the legacy provider name.
7979
properties.put( "javax.persistence.provider", HibernatePersistence.class.getName() );
8080
context.registerService( PersistenceProvider.class.getName(),
81-
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform ), properties );
81+
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform, context ), properties );
8282

8383
context.registerService( SessionFactory.class.getName(),
84-
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform ), new Hashtable());
84+
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform, context ), new Hashtable());
8585
}
8686

8787
@Override

hibernate-osgi/src/main/java/org/hibernate/osgi/OsgiPersistenceProvider.java

Lines changed: 41 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import java.util.Collection;
2727
import java.util.HashMap;
28+
import java.util.List;
2829
import java.util.Map;
2930

3031
import javax.persistence.EntityManagerFactory;
@@ -33,8 +34,11 @@
3334
import org.hibernate.cfg.AvailableSettings;
3435
import org.hibernate.ejb.Ejb3Configuration;
3536
import org.hibernate.ejb.HibernatePersistence;
37+
import org.hibernate.integrator.spi.Integrator;
38+
import org.hibernate.osgi.util.OsgiServiceUtil;
3639
import org.hibernate.service.BootstrapServiceRegistryBuilder;
3740
import org.osgi.framework.Bundle;
41+
import org.osgi.framework.BundleContext;
3842
import org.osgi.framework.BundleReference;
3943

4044
/**
@@ -46,27 +50,32 @@ public class OsgiPersistenceProvider extends HibernatePersistence {
4650
private OsgiClassLoader osgiClassLoader;
4751

4852
private OsgiJtaPlatform osgiJtaPlatform;
49-
53+
5054
private Bundle requestingBundle;
51-
52-
public OsgiPersistenceProvider (OsgiClassLoader osgiClassLoader,
53-
OsgiJtaPlatform osgiJtaPlatform,
54-
Bundle requestingBundle ) {
55+
56+
private BundleContext context;
57+
58+
public OsgiPersistenceProvider(OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform,
59+
Bundle requestingBundle, BundleContext context) {
5560
this.osgiClassLoader = osgiClassLoader;
5661
this.osgiJtaPlatform = osgiJtaPlatform;
5762
this.requestingBundle = requestingBundle;
63+
this.context = context;
5864
}
65+
66+
// TODO: Does "hibernate.classloaders" and osgiClassLoader need added to the
67+
// EMFBuilder somehow?
5968

6069
@Override
6170
public EntityManagerFactory createEntityManagerFactory(String persistenceUnitName, Map properties) {
62-
if ( properties == null ) {
63-
properties = new HashMap();
64-
}
65-
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
71+
generateProperties( properties );
72+
6673
// TODO: This needs tested.
67-
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
68-
new OsgiScanner( requestingBundle ) );
69-
74+
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER, new OsgiScanner( requestingBundle ) );
75+
// TODO: This is temporary -- for PersistenceXmlParser's use of
76+
// ClassLoaderServiceImpl#fromConfigSettings
77+
properties.put( AvailableSettings.ENVIRONMENT_CLASSLOADER, osgiClassLoader );
78+
7079
osgiClassLoader.addBundle( requestingBundle );
7180

7281
Ejb3Configuration cfg = new Ejb3Configuration();
@@ -76,11 +85,9 @@ public EntityManagerFactory createEntityManagerFactory(String persistenceUnitNam
7685

7786
@Override
7887
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map properties) {
79-
if ( properties == null ) {
80-
properties = new HashMap();
81-
}
82-
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
83-
// OSGi ClassLoaders must implement BundleReference
88+
generateProperties( properties );
89+
90+
// OSGi ClassLoaders must implement BundleReference
8491
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
8592
new OsgiScanner( ( (BundleReference) info.getClassLoader() ).getBundle() ) );
8693

@@ -93,6 +100,7 @@ public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitI
93100

94101
private BootstrapServiceRegistryBuilder getBuilder(Map properties) {
95102
BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
103+
96104
final Collection<ClassLoader> classLoaders = (Collection<ClassLoader>) properties
97105
.get( AvailableSettings.CLASSLOADERS );
98106
if ( classLoaders != null ) {
@@ -101,6 +109,22 @@ private BootstrapServiceRegistryBuilder getBuilder(Map properties) {
101109
}
102110
}
103111
builder.with( osgiClassLoader );
112+
113+
final List<Integrator> integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
114+
for ( Integrator integrator : integrators ) {
115+
builder.with( integrator );
116+
}
117+
118+
// TODO: other types of services?
119+
104120
return builder;
105121
}
122+
123+
private void generateProperties(Map properties) {
124+
if ( properties == null ) {
125+
properties = new HashMap();
126+
}
127+
128+
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
129+
}
106130
}

hibernate-osgi/src/main/java/org/hibernate/osgi/OsgiPersistenceProviderService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
package org.hibernate.osgi;
2222

2323
import org.osgi.framework.Bundle;
24+
import org.osgi.framework.BundleContext;
2425
import org.osgi.framework.ServiceFactory;
2526
import org.osgi.framework.ServiceRegistration;
2627

@@ -37,14 +38,18 @@ public class OsgiPersistenceProviderService implements ServiceFactory {
3738

3839
private OsgiJtaPlatform osgiJtaPlatform;
3940

40-
public OsgiPersistenceProviderService( OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform ) {
41+
private BundleContext context;
42+
43+
public OsgiPersistenceProviderService( OsgiClassLoader osgiClassLoader,
44+
OsgiJtaPlatform osgiJtaPlatform, BundleContext context ) {
4145
this.osgiClassLoader = osgiClassLoader;
4246
this.osgiJtaPlatform = osgiJtaPlatform;
47+
this.context = context;
4348
}
4449

4550
@Override
4651
public Object getService(Bundle requestingBundle, ServiceRegistration registration) {
47-
return new OsgiPersistenceProvider(osgiClassLoader, osgiJtaPlatform, requestingBundle);
52+
return new OsgiPersistenceProvider(osgiClassLoader, osgiJtaPlatform, requestingBundle, context);
4853
}
4954

5055
@Override

hibernate-osgi/src/main/java/org/hibernate/osgi/OsgiSessionFactoryService.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@
2020
*/
2121
package org.hibernate.osgi;
2222

23+
import java.util.List;
24+
2325
import org.hibernate.SessionFactory;
2426
import org.hibernate.cfg.AvailableSettings;
2527
import org.hibernate.cfg.Configuration;
28+
import org.hibernate.integrator.spi.Integrator;
29+
import org.hibernate.osgi.util.OsgiServiceUtil;
2630
import org.hibernate.service.BootstrapServiceRegistryBuilder;
2731
import org.hibernate.service.ServiceRegistry;
2832
import org.hibernate.service.ServiceRegistryBuilder;
2933
import org.osgi.framework.Bundle;
34+
import org.osgi.framework.BundleContext;
3035
import org.osgi.framework.ServiceFactory;
3136
import org.osgi.framework.ServiceRegistration;
3237

@@ -54,9 +59,13 @@ public class OsgiSessionFactoryService implements ServiceFactory {
5459

5560
private OsgiJtaPlatform osgiJtaPlatform;
5661

57-
public OsgiSessionFactoryService( OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform ) {
62+
private BundleContext context;
63+
64+
public OsgiSessionFactoryService( OsgiClassLoader osgiClassLoader, OsgiJtaPlatform osgiJtaPlatform,
65+
BundleContext context ) {
5866
this.osgiClassLoader = osgiClassLoader;
5967
this.osgiJtaPlatform = osgiJtaPlatform;
68+
this.context = context;
6069
}
6170

6271
@Override
@@ -70,8 +79,13 @@ public Object getService(Bundle requestingBundle, ServiceRegistration registrati
7079
BootstrapServiceRegistryBuilder builder = new BootstrapServiceRegistryBuilder();
7180
builder.with( osgiClassLoader );
7281

82+
List<Integrator> integrators = OsgiServiceUtil.getServiceImpls( Integrator.class, context );
83+
for (Integrator integrator : integrators) {
84+
builder.with( integrator );
85+
}
86+
7387
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder( builder.build() )
74-
.applySettings(configuration.getProperties()).buildServiceRegistry();
88+
.applySettings(configuration.getProperties()).buildServiceRegistry();
7589
return configuration.buildSessionFactory(serviceRegistry);
7690
}
7791

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* JBoss, Home of Professional Open Source
5+
* Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
6+
* as indicated by the @authors tag. All rights reserved.
7+
* See the copyright.txt in the distribution for a
8+
* full listing of individual contributors.
9+
*
10+
* This copyrighted material is made available to anyone wishing to use,
11+
* modify, copy, or redistribute it subject to the terms and conditions
12+
* of the GNU Lesser General Public License, v. 2.1.
13+
* This program is distributed in the hope that it will be useful, but WITHOUT A
14+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15+
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
16+
* You should have received a copy of the GNU Lesser General Public License,
17+
* v.2.1 along with this distribution; if not, write to the Free Software
18+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19+
* MA 02110-1301, USA.
20+
*/
21+
package org.hibernate.osgi.util;
22+
23+
import java.util.ArrayList;
24+
import java.util.Collection;
25+
import java.util.List;
26+
27+
import org.hibernate.internal.CoreMessageLogger;
28+
import org.jboss.logging.Logger;
29+
import org.osgi.framework.BundleContext;
30+
import org.osgi.framework.ServiceReference;
31+
32+
/**
33+
* @author Brett Meyer
34+
*/
35+
public class OsgiServiceUtil {
36+
37+
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
38+
OsgiServiceUtil.class.getName() );
39+
40+
public static <T> List<T> getServiceImpls(Class<T> contract, BundleContext context) {
41+
List<T> serviceImpls = new ArrayList<T>();
42+
try {
43+
Collection<ServiceReference<T>> serviceRefs = context.getServiceReferences( contract, null );
44+
for ( ServiceReference<T> serviceRef : serviceRefs ) {
45+
serviceImpls.add( context.getService( serviceRef ) );
46+
}
47+
}
48+
catch ( Exception e ) {
49+
LOG.unableToDiscoverOsgiService( contract.getName(), e );
50+
}
51+
return serviceImpls;
52+
}
53+
}

0 commit comments

Comments
 (0)