HHH-7552 - New StrategySelectorService : initial auto-detection

This commit is contained in:
Steve Ebersole 2012-08-31 16:20:05 -05:00
parent 98ad44e75d
commit ab64f5c3be
11 changed files with 358 additions and 54 deletions

View File

@ -26,6 +26,8 @@ package org.hibernate.boot.registry;
import java.util.LinkedHashSet;
import org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl;
import org.hibernate.boot.registry.selector.Availability;
import org.hibernate.boot.registry.selector.AvailabilityAnnouncer;
import org.hibernate.integrator.internal.IntegratorServiceImpl;
import org.hibernate.integrator.spi.Integrator;
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
@ -120,7 +122,24 @@ public class BootstrapServiceRegistryBuilder {
*/
@SuppressWarnings( {"UnusedDeclaration"})
public <T> BootstrapServiceRegistryBuilder withStrategySelector(Class<T> strategy, String name, Class<? extends T> implementation) {
this.strategySelectorBuilder.addCustomRegistration( strategy, name, implementation );
this.strategySelectorBuilder.addExplicitAvailability( strategy, implementation, name );
return this;
}
/**
* Applies one or more strategy selectors announced as available by the passed announcer.
*
* @param availabilityAnnouncer An announcer for one or more available selectors
*
* @return {@code this}, for method chaining
*
* @see org.hibernate.boot.registry.selector.spi.StrategySelector#registerStrategyImplementor(Class, String, Class)
*/
@SuppressWarnings( {"UnusedDeclaration"})
public <T> BootstrapServiceRegistryBuilder withStrategySelectors(AvailabilityAnnouncer availabilityAnnouncer) {
for ( Availability availability : availabilityAnnouncer.getAvailabilities() ) {
this.strategySelectorBuilder.addExplicitAvailability( availability );
}
return this;
}

View File

@ -0,0 +1,33 @@
/*
* 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
*/
package org.hibernate.boot.registry.selector;
/**
* @author Steve Ebersole
*/
public interface Availability {
public Class getStrategyRole();
public Iterable<String> getSelectorNames();
public Class getStrategyImplementation();
}

View File

@ -0,0 +1,36 @@
/*
* 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
*/
package org.hibernate.boot.registry.selector;
/**
* Responsible for announcing the availability of strategy selector(s). Can be registered directly with the
* {@link org.hibernate.boot.registry.BootstrapServiceRegistry} or located via discovery
*
* todo : better name?
*
* @author Steve Ebersole
*/
public interface AvailabilityAnnouncer {
public Iterable<Availability> getAvailabilities();
}

View File

@ -0,0 +1,66 @@
/*
* 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
*/
package org.hibernate.boot.registry.selector;
import java.util.Arrays;
/**
* @author Steve Ebersole
*/
public class SimpleAvailabilityImpl implements Availability {
private final Class strategyRole;
private final Class strategyImplementation;
private final Iterable<String> selectorNames;
public SimpleAvailabilityImpl(
Class strategyRole,
Class strategyImplementation,
Iterable<String> selectorNames) {
this.strategyRole = strategyRole;
this.strategyImplementation = strategyImplementation;
this.selectorNames = selectorNames;
}
public SimpleAvailabilityImpl(
Class strategyRole,
Class strategyImplementation,
String... selectorNames) {
this( strategyRole, strategyImplementation, Arrays.asList( selectorNames ) );
}
@Override
public Class getStrategyRole() {
return strategyRole;
}
@Override
public Iterable<String> getSelectorNames() {
return selectorNames;
}
@Override
public Class getStrategyImplementation() {
return strategyImplementation;
}
}

View File

@ -29,6 +29,9 @@ import java.util.List;
import org.jboss.logging.Logger;
import org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl;
import org.hibernate.boot.registry.selector.Availability;
import org.hibernate.boot.registry.selector.AvailabilityAnnouncer;
import org.hibernate.boot.registry.selector.SimpleAvailabilityImpl;
import org.hibernate.boot.registry.selector.spi.StrategySelectionException;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.dialect.CUBRIDDialect;
@ -98,38 +101,27 @@ import org.hibernate.engine.transaction.spi.TransactionFactory;
public class StrategySelectorBuilder {
private static final Logger log = Logger.getLogger( StrategySelectorBuilder.class );
private static class CustomRegistration<T> {
private final Class<T> strategy;
private final String name;
private final Class<? extends T> implementation;
private CustomRegistration(Class<T> strategy, String name, Class<? extends T> implementation) {
this.strategy = strategy;
this.name = name;
this.implementation = implementation;
}
public void registerWith(StrategySelectorImpl strategySelector) {
strategySelector.registerStrategyImplementor( strategy, name, implementation );
}
}
private final List<CustomRegistration> customRegistrations = new ArrayList<CustomRegistration>();
private final List<Availability> explicitAvailabilities = new ArrayList<Availability>();
@SuppressWarnings("unchecked")
public <T> void addCustomRegistration(Class<T> strategy, String name, Class<? extends T> implementation) {
if ( !strategy.isInterface() ) {
// not good form...
log.debug( "Registering non-interface strategy implementation : " + strategy.getName() );
public <T> void addExplicitAvailability(Class<T> strategy, Class<? extends T> implementation, String name) {
addExplicitAvailability( new SimpleAvailabilityImpl( strategy, implementation, name ) );
}
if ( ! strategy.isAssignableFrom( implementation ) ) {
public void addExplicitAvailability(Availability availability) {
if ( !availability.getStrategyRole().isInterface() ) {
// not good form...
log.debug( "Registering non-interface strategy implementation : " + availability.getStrategyRole().getName() );
}
if ( ! availability.getStrategyRole().isAssignableFrom( availability.getStrategyImplementation() ) ) {
throw new StrategySelectionException(
"Implementation class [" + implementation.getName() + "] does not implement strategy interface ["
+ strategy.getName() + "]"
"Implementation class [" + availability.getStrategyImplementation().getName()
+ "] does not implement strategy interface ["
+ availability.getStrategyRole().getName() + "]"
);
}
customRegistrations.add( new CustomRegistration( strategy, name, implementation ) );
explicitAvailabilities.add( availability );
}
public StrategySelector buildSelector(ClassLoaderServiceImpl classLoaderService) {
@ -140,16 +132,32 @@ public class StrategySelectorBuilder {
addJtaPlatforms( strategySelector );
addTransactionFactories( strategySelector );
// todo : apply auto-discovered registrations
// apply auto-discovered registrations
for ( AvailabilityAnnouncer announcer : classLoaderService.loadJavaServices( AvailabilityAnnouncer.class ) ) {
for ( Availability discoveredAvailability : announcer.getAvailabilities() ) {
applyFromAvailability( strategySelector, discoveredAvailability );
}
}
// apply customizations
for ( CustomRegistration customRegistration : customRegistrations ) {
customRegistration.registerWith( strategySelector );
for ( Availability explicitAvailability : explicitAvailabilities ) {
applyFromAvailability( strategySelector, explicitAvailability );
}
return strategySelector;
}
@SuppressWarnings("unchecked")
private void applyFromAvailability(StrategySelectorImpl strategySelector, Availability availability) {
for ( String name : availability.getSelectorNames() ) {
strategySelector.registerStrategyImplementor(
availability.getStrategyRole(),
name,
availability.getStrategyImplementation()
);
}
}
private void addDialects(StrategySelectorImpl strategySelector) {
addDialect( strategySelector, Cache71Dialect.class );
addDialect( strategySelector, CUBRIDDialect.class );

View File

@ -43,6 +43,8 @@ import org.hibernate.cfg.Settings;
* @author Steve Ebersole
*/
public class NoCachingRegionFactory implements RegionFactory {
public static final NoCachingRegionFactory INSTANCE = new NoCachingRegionFactory();
public NoCachingRegionFactory() {
}

View File

@ -26,6 +26,7 @@ package org.hibernate.cache.internal;
import java.util.Map;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.service.spi.ServiceException;
@ -52,32 +53,37 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
@Override
@SuppressWarnings( { "unchecked" })
public RegionFactory initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
final Object impl = configurationValues.get( IMPL_NAME );
if ( impl == null ) {
return new NoCachingRegionFactory();
}
if ( getServiceInitiated().isInstance( impl ) ) {
return (RegionFactory) impl;
}
Class<? extends RegionFactory> customImplClass = null;
if ( Class.class.isInstance( impl ) ) {
customImplClass = (Class<? extends RegionFactory>) impl;
}
else {
customImplClass = registry.getService( ClassLoaderService.class )
.classForName( mapLegacyNames( impl.toString() ) );
}
try {
return customImplClass.newInstance();
}
catch ( Exception e ) {
throw new ServiceException(
"Could not initialize custom RegionFactory impl [" + customImplClass.getName() + "]", e
final Object setting = configurationValues.get( IMPL_NAME );
return registry.getService( StrategySelector.class ).resolveDefaultableStrategy(
RegionFactory.class,
setting,
NoCachingRegionFactory.INSTANCE
);
}
// if ( setting == null ) {
// return new NoCachingRegionFactory();
// }
//
// if ( getServiceInitiated().isInstance( setting ) ) {
// return (RegionFactory) setting;
// }
//
// Class<? extends RegionFactory> customImplClass = null;
// if ( Class.class.isInstance( setting ) ) {
// customImplClass = (Class<? extends RegionFactory>) setting;
// }
// else {
// customImplClass = registry.getService( ClassLoaderService.class )
// .classForName( mapLegacyNames( setting.toString() ) );
// }
//
// try {
// return customImplClass.newInstance();
// }
// catch ( Exception e ) {
// throw new ServiceException(
// "Could not initialize custom RegionFactory impl [" + customImplClass.getName() + "]", e
// );
// }
}
// todo this shouldn't be public (nor really static):

View File

@ -0,0 +1,68 @@
/*
* 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
*/
package org.hibernate.cache.ehcache;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.boot.registry.selector.Availability;
import org.hibernate.boot.registry.selector.AvailabilityAnnouncer;
import org.hibernate.boot.registry.selector.SimpleAvailabilityImpl;
import org.hibernate.cache.spi.RegionFactory;
/**
* Makes the 2 contained region factory implementations available to the Hibernate
* {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service.
*
* @author Steve Ebersole
*/
public class AvailabilityAnnouncerImpl implements AvailabilityAnnouncer {
@Override
@SuppressWarnings("unchecked")
public Iterable<Availability> getAvailabilities() {
final List<Availability> availabilities = new ArrayList<Availability>();
availabilities.add(
new SimpleAvailabilityImpl(
RegionFactory.class,
EhCacheRegionFactory.class,
"ehcache",
EhCacheRegionFactory.class.getSimpleName(),
"org.hibernate.cache.EhCacheRegionFactory" // legacy impl class name
)
);
availabilities.add(
new SimpleAvailabilityImpl(
RegionFactory.class,
SingletonEhCacheRegionFactory.class,
"ehcache-singleton",
SingletonEhCacheRegionFactory.class.getSimpleName(),
"org.hibernate.cache.SingletonEhCacheRegionFactory" // legacy impl class name
)
);
return availabilities;
}
}

View File

@ -0,0 +1 @@
org.hibernate.cache.ehcache.AvailabilityAnnouncerImpl

View File

@ -0,0 +1,65 @@
/*
* 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
*/
package org.hibernate.cache.infinispan;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.boot.registry.selector.Availability;
import org.hibernate.boot.registry.selector.AvailabilityAnnouncer;
import org.hibernate.boot.registry.selector.SimpleAvailabilityImpl;
import org.hibernate.cache.spi.RegionFactory;
/**
* Makes the 2 contained region factory implementations available to the Hibernate
* {@link org.hibernate.boot.registry.selector.spi.StrategySelector} service.
*
* @author Steve Ebersole
*/
public class AvailabilityAnnouncerImpl implements AvailabilityAnnouncer {
@Override
public Iterable<Availability> getAvailabilities() {
final List<Availability> availabilities = new ArrayList<Availability>();
availabilities.add(
new SimpleAvailabilityImpl(
RegionFactory.class,
InfinispanRegionFactory.class,
"infinispan",
InfinispanRegionFactory.class.getSimpleName()
)
);
availabilities.add(
new SimpleAvailabilityImpl(
RegionFactory.class,
JndiInfinispanRegionFactory.class,
"infinispan-jndi",
JndiInfinispanRegionFactory.class.getSimpleName()
)
);
return availabilities;
}
}