HHH-7993 Support jar scanning in OSGi

This commit is contained in:
Brett Meyer 2013-04-04 13:54:31 -04:00
parent d6fe409a48
commit d68dcd9ae6
7 changed files with 209 additions and 4 deletions

View File

@ -1619,4 +1619,8 @@ public interface CoreMessageLogger extends BasicLogger {
@LogMessage(level = INFO) @LogMessage(level = INFO)
@Message( value = "'javax.persistence.validation.mode' named multiple values : %s", id = 448 ) @Message( value = "'javax.persistence.validation.mode' named multiple values : %s", id = 448 )
void multipleValidationModes(String modes); void multipleValidationModes(String modes);
@LogMessage(level = WARN)
@Message(value = "Exception while loading a class or resource found during scanning", id = 449)
void unableToLoadScannedClassOrResource(@Cause Exception e);
} }

View File

@ -1,7 +1,7 @@
dependencies { dependencies {
compile( project( ':hibernate-core' ) ) compile( project( ':hibernate-core' ) )
compile( project( ':hibernate-entitymanager' ) ) compile( project( ':hibernate-entitymanager' ) )
compile( "org.osgi:org.osgi.core:4.2.0" ) compile( "org.osgi:org.osgi.core:4.3.0" )
} }
jar { jar {

View File

@ -23,7 +23,8 @@
*/ */
package org.hibernate.osgi; package org.hibernate.osgi;
import java.util.Properties; import java.util.Dictionary;
import java.util.Hashtable;
import javax.persistence.spi.PersistenceProvider; import javax.persistence.spi.PersistenceProvider;
@ -72,7 +73,7 @@ public class HibernateBundleActivator implements BundleActivator {
osgiJtaPlatform = new OsgiJtaPlatform( context ); osgiJtaPlatform = new OsgiJtaPlatform( context );
Properties properties = new Properties(); Dictionary properties = new Hashtable();
// In order to support existing persistence.xml files, register // In order to support existing persistence.xml files, register
// using the legacy provider name. // using the legacy provider name.
properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() ); properties.put( "javax.persistence.provider", HibernatePersistenceProvider.class.getName() );
@ -80,7 +81,7 @@ public class HibernateBundleActivator implements BundleActivator {
new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform ), properties ); new OsgiPersistenceProviderService( osgiClassLoader, osgiJtaPlatform ), properties );
context.registerService( SessionFactory.class.getName(), context.registerService( SessionFactory.class.getName(),
new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform ), new Properties()); new OsgiSessionFactoryService( osgiClassLoader, osgiJtaPlatform ), new Hashtable());
} }
@Override @Override

View File

@ -0,0 +1,106 @@
/*
* 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 java.io.InputStream;
import java.util.Collection;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.jpa.boot.archive.spi.ArchiveContext;
import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
import org.hibernate.jpa.boot.archive.spi.ArchiveEntry;
import org.hibernate.jpa.boot.spi.InputStreamAccess;
import org.hibernate.jpa.boot.spi.NamedInputStream;
import org.jboss.logging.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleWiring;
/**
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiArchiveDescriptor implements ArchiveDescriptor {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( CoreMessageLogger.class,
OsgiArchiveDescriptor.class.getName() );
private BundleWiring bundleWiring;
private Bundle persistenceBundle;
public OsgiArchiveDescriptor(Bundle persistenceBundle) {
this.persistenceBundle = persistenceBundle;
bundleWiring = (BundleWiring) persistenceBundle.adapt( BundleWiring.class );
}
@Override
public void visitArchive(ArchiveContext context) {
Collection<String> resources = bundleWiring.listResources( "/", "*", BundleWiring.LISTRESOURCES_RECURSE );
for ( final String resource : resources ) {
try {
final InputStream inputStream = persistenceBundle.getResource( resource ).openStream();
// TODO: Is using resource as the names correct?
final InputStreamAccess inputStreamAccess = new InputStreamAccess() {
@Override
public String getStreamName() {
return resource;
}
@Override
public InputStream accessInputStream() {
return inputStream;
}
@Override
public NamedInputStream asNamedInputStream() {
return new NamedInputStream( resource, inputStream );
}
};
final ArchiveEntry entry = new ArchiveEntry() {
@Override
public String getName() {
return resource;
}
@Override
public String getNameWithinArchive() {
return resource;
}
@Override
public InputStreamAccess getStreamAccess() {
return inputStreamAccess;
}
};
context.obtainArchiveEntryHandler( entry ).handleEntry( entry, context );
}
catch ( Exception e ) {
LOG.unableToLoadScannedClassOrResource( e );
}
}
}
}

View File

@ -0,0 +1,49 @@
/*
* 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 java.net.URL;
import org.hibernate.jpa.boot.archive.internal.StandardArchiveDescriptorFactory;
import org.hibernate.jpa.boot.archive.spi.ArchiveDescriptor;
import org.osgi.framework.Bundle;
/**
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiArchiveDescriptorFactory extends StandardArchiveDescriptorFactory {
private Bundle persistenceBundle;
public OsgiArchiveDescriptorFactory(Bundle persistenceBundle) {
this.persistenceBundle = persistenceBundle;
}
@Override
public ArchiveDescriptor buildArchiveDescriptor(URL url, String entry) {
final String protocol = url.getProtocol();
if ( "bundle".equals( protocol ) ) {
return new OsgiArchiveDescriptor( persistenceBundle );
}
return super.buildArchiveDescriptor( url, entry );
}
}

View File

@ -32,6 +32,7 @@ import javax.persistence.spi.PersistenceUnitInfo;
import org.hibernate.cfg.AvailableSettings; import org.hibernate.cfg.AvailableSettings;
import org.hibernate.jpa.HibernatePersistenceProvider; import org.hibernate.jpa.HibernatePersistenceProvider;
import org.osgi.framework.Bundle; import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
/** /**
* @author Brett Meyer * @author Brett Meyer
@ -62,6 +63,9 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
properties = new HashMap(); properties = new HashMap();
} }
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform ); properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
// TODO: This needs tested.
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
new OsgiScanner( requestingBundle ) );
osgiClassLoader.addBundle( requestingBundle ); osgiClassLoader.addBundle( requestingBundle );
@ -74,6 +78,9 @@ public class OsgiPersistenceProvider extends HibernatePersistenceProvider {
properties = new HashMap(); properties = new HashMap();
} }
properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform ); properties.put( AvailableSettings.JTA_PLATFORM, osgiJtaPlatform );
// OSGi ClassLoaders must implement BundleReference
properties.put( org.hibernate.ejb.AvailableSettings.SCANNER,
new OsgiScanner( ( (BundleReference) info.getClassLoader() ).getBundle() ) );
osgiClassLoader.addClassLoader( info.getClassLoader() ); osgiClassLoader.addClassLoader( info.getClassLoader() );

View File

@ -0,0 +1,38 @@
/*
* 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 org.hibernate.jpa.boot.scan.spi.AbstractScannerImpl;
import org.osgi.framework.Bundle;
/**
* OSGi-specific implementation of the Scanner contract. Scans the persistence
* unit Bundle for classes and resources.
*
* @author Brett Meyer
* @author Tim Ward
*/
public class OsgiScanner extends AbstractScannerImpl {
public OsgiScanner(Bundle persistenceBundle) {
super( new OsgiArchiveDescriptorFactory( persistenceBundle ) );
}
}