HHH-7527 Enterprise OSGi JPA support

This commit is contained in:
Brett Meyer 2013-02-08 19:02:11 -05:00
parent 7fe238ac70
commit 94cbc61f04
28 changed files with 650 additions and 68 deletions

View File

@ -59,6 +59,8 @@ subprojects { subProject ->
apply plugin: 'java'
apply plugin: 'maven' // for install task as well as deploy dependencies
apply plugin: 'uploadAuth'
apply plugin: 'osgi'
apply from: "../utilities.gradle"
configurations {
provided {
@ -155,13 +157,51 @@ subprojects { subProject ->
compileJava.options.define(compilerArgs: ["-proc:none", "-encoding", "UTF-8"])
compileTestJava.options.define(compilerArgs: ["-proc:none", "-encoding", "UTF-8"])
manifest.mainAttributes(
provider: 'gradle',
'Implementation-Url': 'http://hibernate.org',
'Implementation-Version': version,
'Implementation-Vendor': 'Hibernate.org',
'Implementation-Vendor-Id': 'org.hibernate'
)
jar {
Set<String> exportPackages = new HashSet<String>()
Set<String> privatePackages = new HashSet<String>()
// TODO: Could more of this be pulled into utilities.gradle?
sourceSets.each { SourceSet sourceSet ->
// skip certain source sets
if ( ! ['test','matrix'].contains( sourceSet.name ) ) {
sourceSet.java.each { javaFile ->
// - .util for external module use (especially envers)
final String[] temporaryExports = [
'org.hibernate.internal.util' ]
final String packageName = determinePackageName( sourceSet.java, javaFile );
if ( ! temporaryExports.contains( packageName )
&& ( packageName.endsWith( ".internal" )
|| packageName.contains( ".internal." )
|| packageName.endsWith( ".test" )
|| packageName.contains( ".test." ) ) ) {
privatePackages.add( packageName );
}
else {
exportPackages.add( packageName );
}
}
}
}
manifest = osgiManifest {
// GRADLE-1411: Even if we override Imports and Exports
// auto-generation with instructions, classesDir and classpath
// need to be here (temporarily).
classesDir = sourceSets.main.output.classesDir
classpath = configurations.runtime
instruction 'Export-Package', exportPackages.toArray(new String[0])
instruction 'Private-Package', privatePackages.toArray(new String[0])
instruction 'Bundle-Vendor', 'Hibernate.org'
instruction 'Implementation-Url', 'http://hibernate.org'
instruction 'Implementation-Version', version
instruction 'Implementation-Vendor', 'Hibernate.org'
instruction 'Implementation-Vendor-Id', 'org.hibernate'
}
}
test {
// pass along command line defined system props (-D) to the test

View File

@ -9,3 +9,10 @@ dependencies {
}
testCompile project( ':hibernate-testing' )
}
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM C3P0'
instruction 'Bundle-SymbolicName', 'org.hibernate.c3p0'
}
}

View File

@ -37,6 +37,19 @@ manifest.mainAttributes(
'Main-Class': 'org.hibernate.Version'
)
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM Core'
instruction 'Bundle-SymbolicName', 'org.hibernate.core'
// TODO: Uncomment once EntityManagerFactoryBuilderImpl no longer
// uses ClassLoaderServiceImpl.
instruction 'Export-Package',
'org.hibernate.boot.registry.classloading.internal',
'*'
}
}
sourceSets.main {
ext.jaxbTargetDir = file( "${buildDir}/generated-src/jaxb/main" )
java.srcDir jaxbTargetDir

View File

@ -285,7 +285,7 @@ public abstract class CascadeStyle implements Serializable {
public CascadeStyle() {
}
static final Map<String, CascadeStyle> STYLES = new HashMap<String, CascadeStyle>();
public static final Map<String, CascadeStyle> STYLES = new HashMap<String, CascadeStyle>();
static {
STYLES.put( "all", ALL );

View File

@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
@ -170,11 +171,11 @@ public interface SessionImplementor extends Serializable, LobCreationContext {
/**
* Execute a criteria query
*/
public ScrollableResults scroll(CriteriaImpl criteria, ScrollMode scrollMode);
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode);
/**
* Execute a criteria query
*/
public List list(CriteriaImpl criteria);
public List list(Criteria criteria);
/**
* Execute a filter

View File

@ -1561,14 +1561,17 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
return new CriteriaImpl(entityName, this);
}
public ScrollableResults scroll(CriteriaImpl criteria, ScrollMode scrollMode) {
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode) {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
errorIfClosed();
checkTransactionSynchStatus();
String entityName = criteria.getEntityOrClassName();
String entityName = criteriaImpl.getEntityOrClassName();
CriteriaLoader loader = new CriteriaLoader(
getOuterJoinLoadable(entityName),
factory,
criteria,
criteriaImpl,
entityName,
getLoadQueryInfluencers()
);
@ -1582,8 +1585,11 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
}
}
public List list(CriteriaImpl criteria) throws HibernateException {
final NaturalIdLoadAccess naturalIdLoadAccess = this.tryNaturalIdLoadAccess( criteria );
public List list(Criteria criteria) throws HibernateException {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
final NaturalIdLoadAccess naturalIdLoadAccess = this.tryNaturalIdLoadAccess( criteriaImpl );
if ( naturalIdLoadAccess != null ) {
// EARLY EXIT!
return Arrays.asList( naturalIdLoadAccess.load() );
@ -1591,7 +1597,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
errorIfClosed();
checkTransactionSynchStatus();
String[] implementors = factory.getImplementors( criteria.getEntityOrClassName() );
String[] implementors = factory.getImplementors( criteriaImpl.getEntityOrClassName() );
int size = implementors.length;
CriteriaLoader[] loaders = new CriteriaLoader[size];
@ -1601,7 +1607,7 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc
loaders[i] = new CriteriaLoader(
getOuterJoinLoadable( implementors[i] ),
factory,
criteria,
criteriaImpl,
implementors[i],
getLoadQueryInfluencers()
);

View File

@ -30,8 +30,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.jboss.logging.Logger;
import org.hibernate.CacheMode;
import org.hibernate.ConnectionReleaseMode;
import org.hibernate.Criteria;
@ -73,6 +71,7 @@ import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.pretty.MessageHelper;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.type.Type;
import org.jboss.logging.Logger;
/**
* @author Gavin King
@ -618,13 +617,16 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
}
@Override
public ScrollableResults scroll(CriteriaImpl criteria, ScrollMode scrollMode) {
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode) {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
errorIfClosed();
String entityName = criteria.getEntityOrClassName();
String entityName = criteriaImpl.getEntityOrClassName();
CriteriaLoader loader = new CriteriaLoader(
getOuterJoinLoadable( entityName ),
factory,
criteria,
criteriaImpl,
entityName,
getLoadQueryInfluencers()
);
@ -633,9 +635,12 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
@Override
@SuppressWarnings( {"unchecked"})
public List list(CriteriaImpl criteria) throws HibernateException {
public List list(Criteria criteria) throws HibernateException {
// TODO: Is this guaranteed to always be CriteriaImpl?
CriteriaImpl criteriaImpl = (CriteriaImpl) criteria;
errorIfClosed();
String[] implementors = factory.getImplementors( criteria.getEntityOrClassName() );
String[] implementors = factory.getImplementors( criteriaImpl.getEntityOrClassName() );
int size = implementors.length;
CriteriaLoader[] loaders = new CriteriaLoader[size];
@ -643,7 +648,7 @@ public class StatelessSessionImpl extends AbstractSessionImpl implements Statele
loaders[i] = new CriteriaLoader(
getOuterJoinLoadable( implementors[i] ),
factory,
criteria,
criteriaImpl,
implementors[i],
getLoadQueryInfluencers()
);

View File

@ -73,6 +73,9 @@ public final class ReflectHelper {
OBJECT_HASHCODE = hash;
}
// TODO: Better way to do this?
public static ClassLoader overridenClassLoader = null;
/**
* Disallow instantiation of ReflectHelper.
*/
@ -160,11 +163,16 @@ public final class ReflectHelper {
*/
public static Class classForName(String name, Class caller) throws ClassNotFoundException {
try {
if (overridenClassLoader != null) {
return overridenClassLoader.loadClass( name );
}
else {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if ( contextClassLoader != null ) {
return contextClassLoader.loadClass( name );
}
}
}
catch ( Throwable ignore ) {
}
return Class.forName( name, true, caller.getClassLoader() );
@ -182,11 +190,16 @@ public final class ReflectHelper {
*/
public static Class classForName(String name) throws ClassNotFoundException {
try {
if (overridenClassLoader != null) {
return overridenClassLoader.loadClass( name );
}
else {
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
if ( contextClassLoader != null ) {
return contextClassLoader.loadClass(name);
}
}
}
catch ( Throwable ignore ) {
}
return Class.forName( name );

View File

@ -4,3 +4,10 @@ dependencies {
testCompile project( ':hibernate-testing' )
}
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM EHCache'
instruction 'Bundle-SymbolicName', 'org.hibernate.ehcache'
}
}

View File

@ -16,6 +16,25 @@ dependencies {
testRuntime( libraries.validator )
}
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM JPA Entity Manager'
instruction 'Bundle-SymbolicName', 'org.hibernate.entitymanager'
// A cdi-api OSGi bundle does not currently exist. For now, explicitly
// ignore its packages. This will only cause issues if an app tries
// to use the BeanManagerListenerFactory functionality.
// NOTE: The "!" negates the package, keeping it out of Import-Package
// and including it in Ignore-Package. Also note that '*' does not mean
// <Import-Package>*</ImportPackage> will occur. This is simply a
// BND instruction -- the auto-discovery of imported packages still
// occurs.
instruction 'Import-Package',
'!javax.enterprise*',
'*'
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
// JPA model-gen set up
////////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -169,6 +169,12 @@ public class Ejb3Configuration implements Serializable, Referenceable {
public Ejb3Configuration() {
this(null);
}
public Ejb3Configuration(ClassLoader overridenClassLoader) {
this.overridenClassLoader = overridenClassLoader;
cfg = new Configuration();
cfg.setEntityNotFoundDelegate( ejb3EntityNotFoundDelegate );
}
@ -541,14 +547,20 @@ public class Ejb3Configuration implements Serializable, Referenceable {
// set the classloader, passed in by the container in info, to set as the TCCL so that
// Hibernate uses it to properly resolve class references.
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
boolean sameClassLoader = true;
if (overridenClassLoader != null) {
thread.setContextClassLoader( overridenClassLoader );
sameClassLoader = false;
}
else {
if ( info.getClassLoader() == null ) {
throw new IllegalStateException(
"[PersistenceUnit: " + info.getPersistenceUnitName() == null ? "" : info.getPersistenceUnitName()
+ "] " + "PersistenceUnitInfo.getClassLoader() id null" );
}
Thread thread = Thread.currentThread();
ClassLoader contextClassLoader = thread.getContextClassLoader();
boolean sameClassLoader = info.getClassLoader().equals( contextClassLoader );
sameClassLoader = info.getClassLoader().equals( contextClassLoader );
if ( ! sameClassLoader ) {
overridenClassLoader = info.getClassLoader();
thread.setContextClassLoader( overridenClassLoader );
@ -556,6 +568,7 @@ public class Ejb3Configuration implements Serializable, Referenceable {
else {
overridenClassLoader = null;
}
}
// Best I can tell, 'workingVars' is some form of additional configuration contract.
// But it does not correlate 1-1 to EMF/SF settings. It really is like a set of de-typed
@ -848,6 +861,12 @@ public class Ejb3Configuration implements Serializable, Referenceable {
LOG.containerProvidingNullPersistenceUnitRootUrl();
return;
}
if ( scanningContext.url.getProtocol().equalsIgnoreCase( "bundle" ) ) {
// TODO: Is there a way to scan the root bundle URL in OSGi containers?
// Although the URL provides a stream handler that works for finding
// resources in a specific Bundle, the root one does not work.
return;
}
try {
addScannedEntries( scanningContext, entities, packages, hbmFiles, null );
}
@ -898,6 +917,10 @@ public class Ejb3Configuration implements Serializable, Referenceable {
thread = Thread.currentThread();
contextClassLoader = thread.getContextClassLoader();
thread.setContextClassLoader( overridenClassLoader );
builder.withApplicationClassLoader( overridenClassLoader );
builder.withEnvironmentClassLoader( overridenClassLoader );
builder.withHibernateClassLoader( overridenClassLoader );
builder.withResourceClassLoader( overridenClassLoader );
}
try {

View File

@ -24,6 +24,7 @@
package org.hibernate.ejb;
import java.util.Map;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.LoadState;
import javax.persistence.spi.PersistenceProvider;
@ -38,6 +39,7 @@ import org.hibernate.ejb.util.PersistenceUtilHelper;
* @author Gavin King
*/
public class HibernatePersistence extends AvailableSettings implements PersistenceProvider {
private final PersistenceUtilHelper.MetadataCache cache = new PersistenceUtilHelper.MetadataCache();
/**

View File

@ -19,7 +19,12 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.spi;
package org.hibernate.ejb.engine.spi;
import static org.hibernate.engine.spi.CascadeStyle.STYLES;
import org.hibernate.engine.spi.CascadeStyle;
import org.hibernate.engine.spi.CascadingAction;
/**
* Becasue CascadeStyle is not opened and package protected,

View File

@ -19,7 +19,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.engine.spi;
package org.hibernate.ejb.engine.spi;
import java.util.Iterator;
import java.util.Map;
@ -28,6 +28,7 @@ import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.ejb.internal.EntityManagerMessageLogger;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.event.spi.EventSource;
import org.hibernate.type.CollectionType;

View File

@ -25,9 +25,9 @@ package org.hibernate.ejb.event;
import java.io.Serializable;
import org.hibernate.ejb.engine.spi.EJB3CascadeStyle;
import org.hibernate.ejb.engine.spi.EJB3CascadingAction;
import org.hibernate.engine.spi.CascadingAction;
import org.hibernate.engine.spi.EJB3CascadeStyle;
import org.hibernate.engine.spi.EJB3CascadingAction;
import org.hibernate.event.internal.DefaultPersistEventListener;
import org.hibernate.event.spi.EventSource;

View File

@ -37,3 +37,9 @@ task generateJpaMetamodelClasses(type: Compile) {
}
compileJava.dependsOn generateJpaMetamodelClasses
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM Envers'
instruction 'Bundle-SymbolicName', 'org.hibernate.envers'
}
}

View File

@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map;
import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
@ -48,7 +49,6 @@ import org.hibernate.engine.spi.QueryParameters;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.transaction.spi.TransactionCoordinator;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.loader.custom.CustomQuery;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.Type;
@ -160,12 +160,12 @@ public abstract class AbstractDelegateSessionImplementor implements SessionImple
}
@Override
public ScrollableResults scroll(CriteriaImpl criteria, ScrollMode scrollMode) {
public ScrollableResults scroll(Criteria criteria, ScrollMode scrollMode) {
return delegate.scroll(criteria, scrollMode);
}
@Override
public List list(CriteriaImpl criteria) {
public List list(Criteria criteria) {
return delegate.list(criteria);
}

View File

@ -41,3 +41,10 @@ task sourcesTestJar(type: Jar, dependsOn:classes) {
artifacts.archives packageTests
artifacts.archives sourcesTestJar
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM Infinispan'
instruction 'Bundle-SymbolicName', 'org.hibernate.infinispan'
}
}

View File

@ -0,0 +1,13 @@
dependencies {
compile( project( ':hibernate-core' ) )
compile( project( ':hibernate-entitymanager' ) )
compile( "org.osgi:org.osgi.core:4.2.0" )
}
jar {
manifest {
instruction 'Bundle-Activator', 'org.hibernate.osgi.HibernateBundleActivator'
instruction 'Bundle-Description', 'Hibernate ORM OSGi'
instruction 'Bundle-SymbolicName', 'org.hibernate.osgi'
}
}

View File

@ -0,0 +1,113 @@
/*
* 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.osgi;
import java.util.Map;
import java.util.Properties;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import javax.persistence.spi.PersistenceUnitTransactionType;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.ejb.Ejb3Configuration;
import org.hibernate.ejb.HibernatePersistence;
import org.hibernate.internal.util.ReflectHelper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
/**
* @author Brett Meyer
* @author Martin Neimeier
*/
public class HibernateBundleActivator
extends HibernatePersistence
implements BundleActivator, /*ServiceListener,*/ BundleListener {
private BundleContext context;
private OsgiClassLoader osgiClassLoader;
@Override
public void start(BundleContext context) throws Exception {
this.context = context;
// register this instance as a bundle listener to get informed about all
// bundle live cycle events
context.addBundleListener(this);
osgiClassLoader = new OsgiClassLoader();
ReflectHelper.overridenClassLoader = osgiClassLoader;
for ( Bundle bundle : context.getBundles() ) {
handleBundleChange( bundle );
}
Properties properties = new Properties();
properties.put( "javax.persistence.provider", HibernateBundleActivator.class.getName() );
context.registerService(
PersistenceProvider.class.getName(),
this,
properties
);
}
@Override
public void stop(BundleContext context) throws Exception {
context.removeBundleListener(this);
// Nothing else to do. When re-activated, this Activator will be
// re-started and the EMF re-created.
}
@Override
public void bundleChanged(BundleEvent event) {
handleBundleChange( event.getBundle() );
}
private void handleBundleChange( Bundle bundle ) {
if ( bundle.getState() == Bundle.ACTIVE ) {
osgiClassLoader.registerBundle(bundle);
} else {
osgiClassLoader.unregisterBundle(bundle);
}
}
@Override
public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) {
Ejb3Configuration cfg = new Ejb3Configuration(osgiClassLoader);
if ( info.getTransactionType().equals( PersistenceUnitTransactionType.JTA ) ) {
map.put( AvailableSettings.JTA_PLATFORM, new OsgiJtaPlatform( context ) );
}
Ejb3Configuration configured = cfg.configure( info, map );
return configured != null ? configured.buildEntityManagerFactory() : null;
}
}

View File

@ -0,0 +1,168 @@
/*
* 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.osgi;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import org.osgi.framework.Bundle;
/**
* Custom OSGI ClassLoader helper which knows all the "interesting" bundles and
* encapsulates the OSGi related capabilities.
*
* @author Brett Meyer
*/
public class OsgiClassLoader extends ClassLoader {
private HashMap<String, Bundle> bundles;
public OsgiClassLoader() {
bundles = new HashMap<String, Bundle>();
}
/**
* Load the class and break on first found match.
* 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
protected Class<?> findClass(String name) throws ClassNotFoundException {
// TODO: This is horrible -- we shouldn't iterate over all the
// classloaders every time we need to construct an entity, etc. Instead,
// keep references to all classes/resources found in active bundles
// in memory? Find a way to identify what we "care about" and keep
// only those? Discover them the first time and then cache the
// reference?
for ( Bundle bundle : bundles.values() ) {
try {
Class clazz = bundle.loadClass( name );
if ( clazz != null ) {
return clazz;
}
}
catch ( Exception ignore ) {
}
}
throw new ClassNotFoundException( "Could not load requested class : " + name );
}
/**
* Load the class and break on first found match.
* TODO: Should this throw a different exception or warn if multiple
* classes were found? Naming collisions can and do happen in OSGi...
*/
@Override
protected URL findResource(String name) {
// TODO: This is horrible -- we shouldn't iterate over all the
// classloaders every time we need to construct an entity, etc. Instead,
// keep references to all classes/resources found in active bundles
// in memory? Find a way to identify what we "care about" and keep
// only those? Discover them the first time and then cache the
// reference?
for ( Bundle bundle : bundles.values() ) {
try {
URL resource = bundle.getResource( name );
if ( resource != null ) {
return resource;
}
}
catch ( Exception ignore ) {
}
}
// TODO: Error?
return null;
}
/**
* Load the class and break on first found match.
* 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
protected Enumeration<URL> findResources(String name) {
// TODO: This is horrible -- we shouldn't iterate over all the
// classloaders every time we need to construct an entity, etc. Instead,
// keep references to all classes/resources found in active bundles
// in memory? Find a way to identify what we "care about" and keep
// only those? Discover them the first time and then cache the
// reference?
for ( Bundle bundle : bundles.values() ) {
try {
Enumeration<URL> resources = bundle.getResources( name );
if ( resources != null ) {
return resources;
}
}
catch ( Exception ignore ) {
}
}
// TODO: Error?
return null;
}
/**
* Register the bundle with this class loader
*/
public void registerBundle(Bundle bundle) {
if ( bundle != null ) {
synchronized ( bundles ) {
// create a bundle classloader and add it to the list of
// classloaders
String key = getBundleKey( bundle );
if ( !bundles.containsKey( key ) ) {
bundles.put( key, bundle );
}
}
}
}
/**
* Unregister the bundle from this class loader
*/
public void unregisterBundle(Bundle bundle) {
if ( bundle != null ) {
synchronized ( bundles ) {
// remove a bundle classloader for a given bundle
String key = getBundleKey( bundle );
if ( bundles.containsKey( key ) ) {
bundles.remove( key );
}
}
}
}
public void clear() {
bundles.clear();
}
protected static String getBundleKey(Bundle bundle) {
return bundle.getSymbolicName() + " " + bundle.getVersion().toString();
}
}

View File

@ -0,0 +1,84 @@
/*
* 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;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;
import org.hibernate.service.jta.platform.spi.JtaPlatform;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
/**
* Offers the JTA Platform provided by the OSGi container. The Enterprise
* OSGi spec requires all containers to register UserTransaction
* and TransactionManager OSGi services.
*
* @author Brett Meyer
*/
public class OsgiJtaPlatform implements JtaPlatform {
private static final long serialVersionUID = 1L;
private BundleContext bundleContext;
public OsgiJtaPlatform(BundleContext bundleContext) {
this.bundleContext = bundleContext;
}
@Override
public TransactionManager retrieveTransactionManager() {
ServiceReference sr = bundleContext.getServiceReference( TransactionManager.class.getName() );
return (TransactionManager) bundleContext.getService( sr );
}
@Override
public UserTransaction retrieveUserTransaction() {
ServiceReference sr = bundleContext.getServiceReference( UserTransaction.class.getName() );
return (UserTransaction) bundleContext.getService( sr );
}
@Override
public Object getTransactionIdentifier(Transaction transaction) {
// AbstractJtaPlatform just uses the transaction itself.
return transaction;
}
@Override
public boolean canRegisterSynchronization() {
// TODO
return false;
}
@Override
public void registerSynchronization(Synchronization synchronization) {
// TODO
}
@Override
public int getCurrentStatus() throws SystemException {
return retrieveTransactionManager().getStatus();
}
}

View File

@ -1,6 +1,12 @@
dependencies {
compile project( ':hibernate-core' )
compile( libraries.proxool )
testCompile project( ':hibernate-testing' )
}
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM Proxool'
instruction 'Bundle-SymbolicName', 'org.hibernate.proxool'
}
}

View File

@ -9,3 +9,10 @@ dependencies {
transitive=false;
}
}
jar {
manifest {
instruction 'Bundle-Description', 'Hibernate ORM Testing'
instruction 'Bundle-SymbolicName', 'org.hibernate.testing'
}
}

View File

@ -32,7 +32,7 @@ libraries = [
jpa: 'org.hibernate.javax.persistence:hibernate-jpa-2.0-api:1.0.1.Final',
jta: 'org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:1.0.0.Final',
validation: 'javax.validation:validation-api:1.0.0.GA',
jacc: 'org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec:1.0.0.Final',
jacc: 'org.jboss.spec.javax.security.jacc:jboss-jacc-api_1.4_spec:1.0.2.Final',
// logging
logging: 'org.jboss.logging:jboss-logging:3.1.0.GA',
@ -77,8 +77,7 @@ libraries = [
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~ c3p0
c3p0: "c3p0:c3p0:0.9.1",
ehcache: "net.sf.ehcache:ehcache-core:2.4.3",
proxool: "proxool:proxool:0.8.3",
proxool: "proxool:proxool:0.8.3"
]
}

View File

@ -1,5 +1,6 @@
apply plugin: 'base'
apply plugin: 'idea'
apply from: "../utilities.gradle"
buildDir = "target"
@ -83,21 +84,6 @@ task aggregateJavadocs(type: Javadoc) {
}
}
String determinePackageName(SourceDirectorySet sourceDirectorySet, File javaFile) {
final javaFileAbsolutePath = javaFile.absolutePath;
for ( File sourceDirectory : sourceDirectorySet.srcDirs ) {
final String sourceDirectoryAbsolutePath = sourceDirectory.absolutePath;
if ( javaFileAbsolutePath.startsWith( sourceDirectoryAbsolutePath ) ) {
final String javaFileRelativePath = javaFileAbsolutePath.substring(
sourceDirectoryAbsolutePath.length() + 1,
javaFileAbsolutePath.lastIndexOf( File.separator )
);
return javaFileRelativePath.replace( File.separator, "." );
}
}
throw new RuntimeException( "ugh" );
}
aggregateJavadocs.doLast {
copy {
from new File( projectDir, 'src/javadoc/images' )

View File

@ -3,6 +3,8 @@ include 'hibernate-testing'
include 'hibernate-entitymanager'
include 'hibernate-envers'
include 'hibernate-osgi'
include 'hibernate-c3p0'
include 'hibernate-proxool'

49
utilities.gradle Normal file
View File

@ -0,0 +1,49 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, 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
*/
apply plugin: UtilitiesPlugin
class UtilitiesPlugin implements Plugin {
def void apply(Object project) {
project.convention.plugins.utilities = new UtilitiesPluginDef()
}
}
class UtilitiesPluginDef {
public String determinePackageName(SourceDirectorySet sourceDirectorySet, File javaFile) {
final javaFileAbsolutePath = javaFile.absolutePath;
for ( File sourceDirectory : sourceDirectorySet.srcDirs ) {
final String sourceDirectoryAbsolutePath = sourceDirectory.absolutePath;
if ( javaFileAbsolutePath.startsWith( sourceDirectoryAbsolutePath ) ) {
final String javaFileRelativePath = javaFileAbsolutePath.substring(
sourceDirectoryAbsolutePath.length() + 1,
javaFileAbsolutePath.lastIndexOf( File.separator )
);
return javaFileRelativePath.replace( File.separator, "." );
}
}
throw new RuntimeException( "ugh" );
}
}