From 882866173171204465345184a3de1f9fb790c41a Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Thu, 7 Oct 2010 13:39:28 -0500 Subject: [PATCH] HHH-5632 - Import initial services work --- .../internal/ClassLoaderServiceImpl.java | 201 ++++++++++++++++ .../internal/ClassLoaderServiceInitiator.java | 54 +++++ .../classloading/spi/ClassLoaderService.java | 75 ++++++ .../spi/ClassLoadingException.java | 41 ++++ .../internal/ServiceDependencyException.java | 41 ++++ .../service/internal/ServicesInitializer.java | 192 +++++++++++++++ .../internal/ServicesRegistryImpl.java | 112 +++++++++ .../jmx/internal/DisabledJmxServiceImpl.java | 46 ++++ .../service/jmx/internal/JmxServiceImpl.java | 220 ++++++++++++++++++ .../jmx/internal/JmxServiceInitiator.java | 57 +++++ .../hibernate/service/jmx/spi/JmxService.java | 52 +++++ .../jndi/internal/JndiServiceImpl.java | 91 ++++++++ .../jndi/internal/JndiServiceInitiator.java | 53 +++++ .../service/jndi/spi/JndiService.java | 50 ++++ .../hibernate/service/spi/Configurable.java | 40 ++++ .../hibernate/service/spi/InjectService.java | 54 +++++ .../org/hibernate/service/spi/Manageable.java | 54 +++++ .../org/hibernate/service/spi/Service.java | 32 +++ .../service/spi/ServiceException.java | 41 ++++ .../service/spi/ServiceInitiator.java | 50 ++++ .../service/spi/ServicesRegistry.java | 43 ++++ .../spi/ServicesRegistryAwareService.java | 38 +++ .../org/hibernate/service/spi/Startable.java | 36 +++ .../org/hibernate/service/spi/Stoppable.java | 36 +++ .../service/spi/UnknownServiceException.java | 44 ++++ 25 files changed, 1753 insertions(+) create mode 100644 core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceImpl.java create mode 100644 core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceInitiator.java create mode 100644 core/src/main/java/org/hibernate/service/classloading/spi/ClassLoaderService.java create mode 100644 core/src/main/java/org/hibernate/service/classloading/spi/ClassLoadingException.java create mode 100644 core/src/main/java/org/hibernate/service/internal/ServiceDependencyException.java create mode 100644 core/src/main/java/org/hibernate/service/internal/ServicesInitializer.java create mode 100644 core/src/main/java/org/hibernate/service/internal/ServicesRegistryImpl.java create mode 100644 core/src/main/java/org/hibernate/service/jmx/internal/DisabledJmxServiceImpl.java create mode 100644 core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceImpl.java create mode 100644 core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceInitiator.java create mode 100644 core/src/main/java/org/hibernate/service/jmx/spi/JmxService.java create mode 100644 core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceImpl.java create mode 100644 core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceInitiator.java create mode 100644 core/src/main/java/org/hibernate/service/jndi/spi/JndiService.java create mode 100644 core/src/main/java/org/hibernate/service/spi/Configurable.java create mode 100644 core/src/main/java/org/hibernate/service/spi/InjectService.java create mode 100644 core/src/main/java/org/hibernate/service/spi/Manageable.java create mode 100644 core/src/main/java/org/hibernate/service/spi/Service.java create mode 100644 core/src/main/java/org/hibernate/service/spi/ServiceException.java create mode 100644 core/src/main/java/org/hibernate/service/spi/ServiceInitiator.java create mode 100644 core/src/main/java/org/hibernate/service/spi/ServicesRegistry.java create mode 100644 core/src/main/java/org/hibernate/service/spi/ServicesRegistryAwareService.java create mode 100644 core/src/main/java/org/hibernate/service/spi/Startable.java create mode 100644 core/src/main/java/org/hibernate/service/spi/Stoppable.java create mode 100644 core/src/main/java/org/hibernate/service/spi/UnknownServiceException.java diff --git a/core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceImpl.java b/core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceImpl.java new file mode 100644 index 0000000000..aa96d57150 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceImpl.java @@ -0,0 +1,201 @@ +/* + * 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.service.classloading.internal; + +import java.io.InputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; + +import org.hibernate.service.classloading.spi.ClassLoaderService; +import org.hibernate.service.classloading.spi.ClassLoadingException; + +/** + * Standard implementation of the service for interacting with class loaders + * + * @author Steve Ebersole + */ +public class ClassLoaderServiceImpl implements ClassLoaderService { + public static final String APP_CL = "hibernate.classLoader.application"; + public static final String RESOURCES_CL = "hibernate.classLoader.resources"; + public static final String HIB_CL = "hibernate.classLoader.hibernate"; + public static final String ENV_CL = "hibernate.classLoader.environment"; + + private final LinkedHashSet classLoadingClassLoaders; + private final ClassLoader resourcesClassLoader; + + public ClassLoaderServiceImpl(Map configVales) { + this( determineClassLoaders( configVales ) ); + } + + private ClassLoaderServiceImpl(ClassLoader[] classLoaders) { + this( classLoaders[0], classLoaders[1], classLoaders[2], classLoaders[3] ); + } + + private static ClassLoader[] determineClassLoaders(Map configVales) { + ClassLoader applicationClassLoader = (ClassLoader) configVales.get( APP_CL ); + ClassLoader resourcesClassLoader = (ClassLoader) configVales.get( RESOURCES_CL ); + ClassLoader hibernateClassLoader = (ClassLoader) configVales.get( HIB_CL ); + ClassLoader environmentClassLoader = (ClassLoader) configVales.get( ENV_CL ); + + if ( hibernateClassLoader == null ) { + hibernateClassLoader = ClassLoaderServiceImpl.class.getClassLoader(); + } + + if ( environmentClassLoader == null || applicationClassLoader == null ) { + ClassLoader sysClassLoader = locateSystemClassLoader(); + ClassLoader tccl = locateTCCL(); + if ( environmentClassLoader == null ) { + environmentClassLoader = sysClassLoader != null ? sysClassLoader : hibernateClassLoader; + } + if ( applicationClassLoader == null ) { + applicationClassLoader = tccl != null ? tccl : hibernateClassLoader; + } + } + + if ( resourcesClassLoader == null ) { + resourcesClassLoader = applicationClassLoader; + } + + return new ClassLoader[] { + applicationClassLoader, + resourcesClassLoader, + hibernateClassLoader, + environmentClassLoader + }; + } + + private static ClassLoader locateSystemClassLoader() { + try { + return ClassLoader.getSystemClassLoader(); + } + catch ( Exception e ) { + return null; + } + } + + private static ClassLoader locateTCCL() { + try { + return Thread.currentThread().getContextClassLoader(); + } + catch ( Exception e ) { + return null; + } + } + + public ClassLoaderServiceImpl(ClassLoader classLoader) { + this( classLoader, classLoader, classLoader, classLoader ); + } + + public ClassLoaderServiceImpl( + ClassLoader applicationClassLoader, + ClassLoader resourcesClassLoader, + ClassLoader hibernateClassLoader, + ClassLoader environmentClassLoader) { + this.classLoadingClassLoaders = new LinkedHashSet(); + classLoadingClassLoaders.add( applicationClassLoader ); + classLoadingClassLoaders.add( hibernateClassLoader ); + classLoadingClassLoaders.add( environmentClassLoader ); + + this.resourcesClassLoader = resourcesClassLoader; + } + + /** + * {@inheritDoc} + */ + public Class classForName(String className) { + for ( ClassLoader classLoader : classLoadingClassLoaders ) { + try { + return classLoader.loadClass( className ); + } + catch ( Exception e ) { + } + } + throw new ClassLoadingException( "Unable to load class [" + className + "]" ); + } + + /** + * {@inheritDoc} + */ + public URL locateResource(String name) { + // first we try name as a URL + try { + return new URL( name ); + } + catch ( Exception e ) { + } + + try { + return resourcesClassLoader.getResource( name ); + } + catch ( Exception e ) { + } + + return null; + } + + /** + * {@inheritDoc} + */ + public InputStream locateResourceStream(String name) { + // first we try name as a URL + try { + return new URL( name ).openStream(); + } + catch ( Exception e ) { + } + + try { + return resourcesClassLoader.getResourceAsStream( name ); + } + catch ( Exception e ) { + } + + return null; + } + + /** + * {@inheritDoc} + */ + public List locateResources(String name) { + try { + Enumeration urlEnumeration = resourcesClassLoader.getResources( name ); + if ( urlEnumeration != null && urlEnumeration.hasMoreElements() ) { + ArrayList urls = new ArrayList(); + while ( urlEnumeration.hasMoreElements() ) { + urls.add( urlEnumeration.nextElement() ); + } + return urls; + } + } + catch ( Exception e ) { + } + + return null; + } + +} diff --git a/core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceInitiator.java b/core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceInitiator.java new file mode 100644 index 0000000000..6ce8f84006 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/classloading/internal/ClassLoaderServiceInitiator.java @@ -0,0 +1,54 @@ +/* + * 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.service.classloading.internal; + +import java.util.Map; + +import org.hibernate.service.classloading.spi.ClassLoaderService; +import org.hibernate.service.spi.ServiceInitiator; +import org.hibernate.service.spi.ServicesRegistry; + + +/** + * Standard initiator for the stanndard {@link ClassLoaderService} service. + * + * @author Steve Ebersole + */ +public class ClassLoaderServiceInitiator implements ServiceInitiator { + public static final ClassLoaderServiceInitiator INSTANCE = new ClassLoaderServiceInitiator(); + + /** + * {@inheritDoc} + */ + public Class getServiceInitiated() { + return ClassLoaderService.class; + } + + /** + * {@inheritDoc} + */ + public ClassLoaderService initiateService(Map configurationValues, ServicesRegistry registry) { + return new ClassLoaderServiceImpl( configurationValues ); + } +} diff --git a/core/src/main/java/org/hibernate/service/classloading/spi/ClassLoaderService.java b/core/src/main/java/org/hibernate/service/classloading/spi/ClassLoaderService.java new file mode 100644 index 0000000000..b10175e9a0 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/classloading/spi/ClassLoaderService.java @@ -0,0 +1,75 @@ +/* + * 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.service.classloading.spi; + +import java.io.InputStream; +import java.net.URL; +import java.util.List; + +import org.hibernate.service.spi.Service; + +/** + * A service for interacting with class loaders + * + * @author Steve Ebersole + */ +public interface ClassLoaderService extends Service { + /** + * Locate a class by name + * + * @param className The name of the class to locate + * + * @return The class reference + * + * @throws ClassLoadingException Indicates the class could not be found + */ + public Class classForName(String className); + + /** + * Locate a resource by name (classpath lookup) + * + * @param name The resource name. + * + * @return The located URL; may return {@code null} to indicate the resource was not found + */ + public URL locateResource(String name); + + /** + * Locate a resource by name (classpath lookup) and gets its stream + * + * @param name The resource name. + * + * @return The stream of the located resource; may return {@code null} to indicate the resource was not found + */ + public InputStream locateResourceStream(String name); + + /** + * Locate a series of resource by name (classpath lookup) + * + * @param name The resource name. + * + * @return The list of URL matching; may return {@code null} to indicate the resource was not found + */ + public List locateResources(String name); +} diff --git a/core/src/main/java/org/hibernate/service/classloading/spi/ClassLoadingException.java b/core/src/main/java/org/hibernate/service/classloading/spi/ClassLoadingException.java new file mode 100644 index 0000000000..e254c832f5 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/classloading/spi/ClassLoadingException.java @@ -0,0 +1,41 @@ +/* + * 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.service.classloading.spi; + +import org.hibernate.HibernateException; + +/** + * Indicates a problem performing class loading + * + * @author Steve Ebersole + */ +public class ClassLoadingException extends HibernateException { + public ClassLoadingException(String string, Throwable root) { + super( string, root ); + } + + public ClassLoadingException(String s) { + super( s ); + } +} diff --git a/core/src/main/java/org/hibernate/service/internal/ServiceDependencyException.java b/core/src/main/java/org/hibernate/service/internal/ServiceDependencyException.java new file mode 100644 index 0000000000..246a8bb2c4 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/internal/ServiceDependencyException.java @@ -0,0 +1,41 @@ +/* + * 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.service.internal; + +import org.hibernate.HibernateException; + +/** + * Indictes a problem processing service dependencies. + * + * @author Steve Ebersole + */ +public class ServiceDependencyException extends HibernateException { + public ServiceDependencyException(String string, Throwable root) { + super( string, root ); + } + + public ServiceDependencyException(String s) { + super( s ); + } +} \ No newline at end of file diff --git a/core/src/main/java/org/hibernate/service/internal/ServicesInitializer.java b/core/src/main/java/org/hibernate/service/internal/ServicesInitializer.java new file mode 100644 index 0000000000..e41a8c3a7e --- /dev/null +++ b/core/src/main/java/org/hibernate/service/internal/ServicesInitializer.java @@ -0,0 +1,192 @@ +/* + * 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.service.internal; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.hibernate.engine.basic.spi.JmxService; +import org.hibernate.service.spi.Configurable; +import org.hibernate.service.spi.InjectService; +import org.hibernate.service.spi.Manageable; +import org.hibernate.service.spi.Service; +import org.hibernate.service.spi.ServiceException; +import org.hibernate.service.spi.ServiceInitiator; +import org.hibernate.service.spi.ServicesRegistryAwareService; +import org.hibernate.service.spi.Startable; +import org.hibernate.service.spi.UnknownServiceException; + +/** + * Delegate responsible for initializing services + * + * @author Steve Ebersole + */ +public class ServicesInitializer { + private static final Logger log = LoggerFactory.getLogger( ServicesInitializer.class ); + + private final ServicesRegistryImpl servicesRegistry; + private final Map serviceInitiatorMap; + private final Map configurationValues; + + public ServicesInitializer( + ServicesRegistryImpl servicesRegistry, + List serviceInitiators, + Map configurationValues) { + this.servicesRegistry = servicesRegistry; + this.serviceInitiatorMap = toMap( serviceInitiators ); + this.configurationValues = configurationValues; + } + + /** + * We convert the incoming list of initiators to a map for 2 reasons:
    + *
  • to make it easier to look up the initiator we need for a given service role
  • + *
  • to make sure there is only one initator for a given service role (last wins)
  • + *
+ * + * @param serviceInitiators + * @return + */ + private static Map toMap(List serviceInitiators) { + final Map result = new HashMap(); + for ( ServiceInitiator initiator : serviceInitiators ) { + result.put( initiator.getServiceInitiated(), initiator ); + } + return result; + } + + /** + * The main function of this delegate. Used to initialize the service of a given role. + * + * @param serviceRole The service role + * @param The type of service role + * + * @return The intiialized instance of the service + */ + public T initializeService(Class serviceRole) { + log.trace( "Initializing service [role=" + serviceRole.getName() + "]" ); + + // PHASE 1 : create service + T service = createService( serviceRole ); + + // PHASE 2 : configure service (***potentially recursive***) + configureService( service ); + + // PHASE 3 : Start service + startService( service, serviceRole ); + + return service; + } + + @SuppressWarnings({ "unchecked" }) + private T createService(Class serviceRole) { + ServiceInitiator initiator = (ServiceInitiator) serviceInitiatorMap.get( serviceRole ); + if ( initiator == null ) { + throw new UnknownServiceException( serviceRole ); + } + try { + T service = initiator.initiateService( configurationValues, servicesRegistry ); + // IMPL NOTE : the register call here is important to avoid potential stack overflow issues + // from recursive calls through #configureService + servicesRegistry.registerService( serviceRole, service ); + return service; + } + catch ( ServiceException e ) { + throw e; + } + catch ( Exception e ) { + throw new ServiceException( "Unable to create requested service [" + serviceRole.getName() + "]", e ); + } + } + + private void configureService(T service) { + applyInjections( service ); + + if ( Configurable.class.isInstance( service ) ) { + ( (Configurable) service ).configure( configurationValues ); + } + + if ( ServicesRegistryAwareService.class.isInstance( service ) ) { + ( (ServicesRegistryAwareService) service ).injectServices( servicesRegistry ); + } + } + + private void applyInjections(T service) { + for ( Method method : service.getClass().getMethods() ) { + InjectService injectService = method.getAnnotation( InjectService.class ); + if ( injectService == null ) { + continue; + } + + applyInjection( service, method, injectService ); + } + } + + @SuppressWarnings({ "unchecked" }) + private void applyInjection(T service, Method injectionMethod, InjectService injectService) { + if ( injectionMethod.getParameterTypes() == null || injectionMethod.getParameterTypes().length != 1 ) { + throw new ServiceDependencyException( + "Encountered @InjectService on method with unexpected number of parameters" + ); + } + + Class dependentServiceRole = injectService.serviceRole(); + if ( dependentServiceRole == null || dependentServiceRole.equals( Void.class ) ) { + dependentServiceRole = injectionMethod.getParameterTypes()[0]; + } + + final Service dependantService = servicesRegistry.internalGetService( dependentServiceRole ); + if ( dependantService == null ) { + if ( injectService.required() ) { + throw new ServiceDependencyException( + "Dependency [" + dependentServiceRole + "] declared by service [" + service + "] not found" + ); + } + } + else { + try { + injectionMethod.invoke( service, dependantService ); + } + catch ( Exception e ) { + throw new ServiceDependencyException( "Cannot inject dependency service", e ); + } + } + } + + @SuppressWarnings({ "unchecked" }) + private void startService(T service, Class serviceRole) { + if ( Startable.class.isInstance( service ) ) { + ( (Startable) service ).start(); + } + + if ( Manageable.class.isInstance( service ) ) { + servicesRegistry.getService( JmxService.class ).registerService( (Manageable) service, serviceRole ); + } + } + +} diff --git a/core/src/main/java/org/hibernate/service/internal/ServicesRegistryImpl.java b/core/src/main/java/org/hibernate/service/internal/ServicesRegistryImpl.java new file mode 100644 index 0000000000..5af363c9e5 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/internal/ServicesRegistryImpl.java @@ -0,0 +1,112 @@ +/* + * 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.service.internal; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.service.spi.Service; +import org.hibernate.service.spi.ServiceInitiator; +import org.hibernate.service.spi.ServicesRegistry; +import org.hibernate.service.spi.Stoppable; +import org.hibernate.service.spi.UnknownServiceException; + +/** + * Basic Hibernate implementation of the service registry. + * + * @author Steve Ebersole + */ +public class ServicesRegistryImpl implements ServicesRegistry { + private static final Logger log = LoggerFactory.getLogger( ServicesRegistryImpl.class ); + + private final List serviceInitiators; + private ServicesInitializer initializer; + + private HashMap serviceMap = new HashMap(); + // IMPL NOTE : the list used for ordered destruction. Cannot used ordered map above because we need to + // iterate it in reverse order which is only available through ListIterator + private List serviceList = new ArrayList(); + + public ServicesRegistryImpl(List serviceInitiators) { + this.serviceInitiators = Collections.unmodifiableList( serviceInitiators ); + } + + public void initialize(Map configurationValues) { + this.initializer = new ServicesInitializer( this, serviceInitiators, ConfigurationHelper.clone( configurationValues ) ); + } + + public void destroy() { + ListIterator serviceIterator = serviceList.listIterator(); + while ( serviceIterator.hasPrevious() ) { + final Service service = serviceIterator.previous(); + if ( Stoppable.class.isInstance( service ) ) { + try { + ( (Stoppable) service ).stop(); + } + catch ( Exception e ) { + log.info( "Error stopping service [" + service.getClass() + "] : " + e.toString() ); + } + } + } + serviceList.clear(); + serviceList = null; + serviceMap.clear(); + serviceMap = null; + } + + @SuppressWarnings({ "unchecked" }) + public T getService(Class serviceRole) { + T service = internalGetService( serviceRole ); + if ( service == null ) { + throw new UnknownServiceException( serviceRole ); + } + return service; + } + + @SuppressWarnings({ "unchecked" }) + private T locateService(Class serviceRole) { + return (T) serviceMap.get( serviceRole ); + } + + T internalGetService(Class serviceRole) { + T service = locateService( serviceRole ); + if ( service == null ) { + service = initializer.initializeService( serviceRole ); + } + return service; + } + + void registerService(Class serviceRole, T service) { + serviceList.add( service ); + serviceMap.put( serviceRole, service ); + } +} diff --git a/core/src/main/java/org/hibernate/service/jmx/internal/DisabledJmxServiceImpl.java b/core/src/main/java/org/hibernate/service/jmx/internal/DisabledJmxServiceImpl.java new file mode 100644 index 0000000000..1492208620 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/jmx/internal/DisabledJmxServiceImpl.java @@ -0,0 +1,46 @@ +/* + * 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.service.jmx.internal; + +import javax.management.ObjectName; + +import org.hibernate.service.jmx.spi.JmxService; +import org.hibernate.service.spi.Manageable; + +/** + * A no-op version of the {@link JmxService} + * + * @author Steve Ebersole + */ +public class DisabledJmxServiceImpl implements JmxService { + public static final DisabledJmxServiceImpl INSTANCE = new DisabledJmxServiceImpl(); + + @Override + public void registerService(Manageable service, Class serviceRole) { + } + + @Override + public void registerMBean(ObjectName objectName, Object mBean) { + } +} diff --git a/core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceImpl.java b/core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceImpl.java new file mode 100644 index 0000000000..cb08e3d935 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceImpl.java @@ -0,0 +1,220 @@ +/* + * 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.service.jmx.internal; + +import java.lang.management.ManagementFactory; +import java.util.ArrayList; +import java.util.Map; +import javax.management.MBeanServer; +import javax.management.MBeanServerFactory; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.hibernate.HibernateException; +import org.hibernate.cfg.Environment; +import org.hibernate.service.jmx.spi.JmxService; +import org.hibernate.service.spi.Manageable; +import org.hibernate.service.spi.Service; +import org.hibernate.service.spi.Stoppable; +import org.hibernate.internal.util.config.ConfigurationHelper; + +/** + * Standard implementation of JMX services + * + * @author Steve Ebersole + */ +public class JmxServiceImpl implements JmxService, Stoppable { + private static final Logger log = LoggerFactory.getLogger( JmxServiceImpl.class ); + + public static final String JMX_PLATFORM_SERVER = "hibernate.jmx.usePlatformServer"; + public static final String JMX_AGENT_ID = "hibernate.jmx.agentId"; + public static final String JMX_DOMAIN_NAME = "hibernate.jmx.defaultDomain"; + public static final String JMX_SF_NAME = "hibernate.jmx.sessionFactoryName"; + + private final boolean usePlatformServer; + private final String agentId; + private final String defaultDomain; + private final String sessionFactoryName; + + public JmxServiceImpl(Map configValues) { + usePlatformServer = ConfigurationHelper.getBoolean( JMX_PLATFORM_SERVER, configValues ); + agentId = (String) configValues.get( JMX_AGENT_ID ); + defaultDomain = (String) configValues.get( JMX_DOMAIN_NAME ); + sessionFactoryName = ConfigurationHelper.getString( + JMX_SF_NAME, + configValues, + ConfigurationHelper.getString( Environment.SESSION_FACTORY_NAME, configValues ) + ); + } + + private boolean startedServer; + private ArrayList registeredMBeans; + + @Override + public void stop() { + try { + // if we either started the JMX server or we registered some MBeans we at least need to look up + // MBean server and do *some* work on shutdwon. + if ( startedServer || registeredMBeans != null ) { + MBeanServer mBeanServer = findServer(); + if ( mBeanServer == null ) { + log.warn( "Unable to locate MBeanServer on JMX service shutdown" ); + return; + } + + // release any MBeans we registered + if ( registeredMBeans != null ) { + for ( ObjectName objectName : registeredMBeans ) { + try { + log.trace( "Unregistering registered MBean [ON=" + objectName + "]" ); + mBeanServer.unregisterMBean( objectName ); + } + catch ( Exception e ) { + log.debug( "Unable to unregsiter registered MBean [ON=" + objectName + "] : " + e.toString() ); + } + } + } + + // stop the MBean server if we started it + if ( startedServer ) { + log.trace( "Attempting to release created MBeanServer" ); + try { + MBeanServerFactory.releaseMBeanServer( mBeanServer ); + } + catch ( Exception e ) { + log.warn( "Unable to release created MBeanServer : " + e.toString() ); + } + } + } + } + finally { + startedServer = false; + if ( registeredMBeans != null ) { + registeredMBeans.clear(); + registeredMBeans = null; + } + } + } + + public static final String DEFAULT_OBJ_NAME_DOMAIN = "org.hibernate.core"; + public static final String OBJ_NAME_TEMPLATE = "%s:sessionFactory=%s,serviceRole=%s,serviceType=%s"; + + // todo : should serviceRole come first in ObjectName template? depends on the groupings we want in the UI. + // as-is mbeans from each sessionFactory are grouped primarily. + + @Override + public void registerService(Manageable service, Class serviceRole) { + final String domain = service.getManagementDomain() == null + ? DEFAULT_OBJ_NAME_DOMAIN + : service.getManagementDomain(); + final String serviceType = service.getManagementServiceType() == null + ? service.getClass().getName() + : service.getManagementServiceType(); + try { + final ObjectName objectName = new ObjectName( + String.format( + OBJ_NAME_TEMPLATE, + domain, + sessionFactoryName, + serviceRole.getName(), + serviceType + ) + ); + registerMBean( objectName, service.getManagementBean() ); + } + catch ( HibernateException e ) { + throw e; + } + catch ( MalformedObjectNameException e ) { + throw new HibernateException( "Unable to generate service IbjectName", e ); + } + } + + @Override + public void registerMBean(ObjectName objectName, Object mBean) { + MBeanServer mBeanServer = findServer(); + if ( mBeanServer == null ) { + if ( startedServer ) { + throw new HibernateException( "Could not locate previously started MBeanServer" ); + } + mBeanServer = startMBeanServer(); + startedServer = true; + } + + try { + mBeanServer.registerMBean( mBean, objectName ); + if ( registeredMBeans == null ) { + registeredMBeans = new ArrayList(); + } + registeredMBeans.add( objectName ); + } + catch ( Exception e ) { + throw new HibernateException( "Unable to register MBean [ON=" + objectName + "]", e ); + } + } + + /** + * Locate the MBean server to use based on user input from startup. + * + * @return The MBean server to use. + */ + private MBeanServer findServer() { + if ( usePlatformServer ) { + // they specified to use the platform (vm) server + return ManagementFactory.getPlatformMBeanServer(); + } + + // otherwise lookup all servers by (optional) agentId. + // IMPL NOTE : the findMBeanServer call treats a null agentId to mean match all... + ArrayList mbeanServers = MBeanServerFactory.findMBeanServer( agentId ); + + if ( defaultDomain == null ) { + // they did not specify a domain by which to locate a particular MBeanServer to use, so chose the first + return mbeanServers.get( 0 ); + } + + for ( MBeanServer mbeanServer : mbeanServers ) { + // they did specify a domain, so attempt to locate an MBEanServer with a matching default domain, returning it + // if we find it. + if ( defaultDomain.equals( mbeanServer.getDefaultDomain() ) ) { + return mbeanServer; + } + } + + return null; + } + + private MBeanServer startMBeanServer() { + try { + MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer( defaultDomain ); + return mbeanServer; + } + catch ( Exception e ) { + throw new HibernateException( "Unable to start MBeanServer", e ); + } + } +} diff --git a/core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceInitiator.java b/core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceInitiator.java new file mode 100644 index 0000000000..e971a8caf4 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/jmx/internal/JmxServiceInitiator.java @@ -0,0 +1,57 @@ +/* + * 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.service.jmx.internal; + +import java.util.Map; + +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.service.jmx.spi.JmxService; +import org.hibernate.service.spi.ServicesRegistry; +import org.hibernate.service.spi.ServiceInitiator; + +/** + * Standard initiator for the standard {@link JmxService} service + * + * @author Steve Ebersole + */ +public class JmxServiceInitiator implements ServiceInitiator { + public static final String JMX_ENABLED = "hibernate.jmx.enabled"; + public static final JmxServiceInitiator INSTANCE = new JmxServiceInitiator(); + + /** + * {@inheritDoc} + */ + public Class getServiceInitiated() { + return JmxService.class; + } + + /** + * {@inheritDoc} + */ + public JmxService initiateService(Map configValues, ServicesRegistry registry) { + return ConfigurationHelper.getBoolean( JMX_ENABLED, configValues, false ) + ? new JmxServiceImpl( configValues ) + : DisabledJmxServiceImpl.INSTANCE; + } +} diff --git a/core/src/main/java/org/hibernate/service/jmx/spi/JmxService.java b/core/src/main/java/org/hibernate/service/jmx/spi/JmxService.java new file mode 100644 index 0000000000..1b588d9ee3 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/jmx/spi/JmxService.java @@ -0,0 +1,52 @@ +/* + * 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.service.jmx.spi; + +import javax.management.ObjectName; + +import org.hibernate.service.spi.Manageable; +import org.hibernate.service.spi.Service; + +/** + * Service providing simplified access to JMX related features needed by Hibernate. + * + * @author Steve Ebersole + */ +public interface JmxService extends Service { + /** + * Handles regsitration of a manageable service. + * + * @param service The manageable service + * @param serviceRole The service's role. + */ + public void registerService(Manageable service, Class serviceRole); + + /** + * Registers the given {@code mBean} under the given {@code objectName} + * + * @param objectName The name under which to register the MBean + * @param mBean The MBean to register + */ + public void registerMBean(ObjectName objectName, Object mBean); +} diff --git a/core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceImpl.java b/core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceImpl.java new file mode 100644 index 0000000000..46d7491012 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceImpl.java @@ -0,0 +1,91 @@ +/* + * 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.service.jndi.internal; + +import java.util.Hashtable; +import java.util.Map; +import javax.naming.InitialContext; +import javax.naming.NamingException; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +import org.hibernate.internal.util.jndi.JndiException; +import org.hibernate.internal.util.jndi.JndiHelper; +import org.hibernate.service.jndi.spi.JndiService; + +/** + * Standard implementation of JNDI services. + * + * @author Steve Ebersole + */ +public class JndiServiceImpl implements JndiService { + private static final Logger log = LoggerFactory.getLogger( JndiServiceImpl.class ); + + private final Hashtable initialContextSettings; + + public JndiServiceImpl(Map configurationValues) { + this.initialContextSettings = JndiHelper.extractJndiProperties( configurationValues ); + } + + public Object locate(String jndiName) { + InitialContext initialContext = buildInitialContext(); + try { + return JndiHelper.locate( jndiName, initialContext ); + } + finally { + try { + initialContext.close(); + } + catch ( NamingException e ) { + log.info( "error closing InitialContext [" + e.toString() + "]" ); + } + } + } + + private InitialContext buildInitialContext() { + try { + return initialContextSettings.size() == 0 ? new InitialContext() : new InitialContext( initialContextSettings ); + } + catch ( NamingException e ) { + throw new JndiException( "Unable to open InitialContext", e ); + } + } + + public void bind(String jndiName, Object value) { + InitialContext initialContext = buildInitialContext(); + try { + JndiHelper.bind( jndiName, value, initialContext ); + } + finally { + try { + initialContext.close(); + } + catch ( NamingException e ) { + log.info( "error closing InitialContet [" + e.toString() + "]" ); + } + } + } +} diff --git a/core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceInitiator.java b/core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceInitiator.java new file mode 100644 index 0000000000..5160b76d5a --- /dev/null +++ b/core/src/main/java/org/hibernate/service/jndi/internal/JndiServiceInitiator.java @@ -0,0 +1,53 @@ +/* + * 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.service.jndi.internal; + +import java.util.Map; + +import org.hibernate.service.jndi.spi.JndiService; +import org.hibernate.service.spi.ServiceInitiator; +import org.hibernate.service.spi.ServicesRegistry; + +/** + * Standard initiator for the standard {@link JndiService} service + * + * @author Steve Ebersole + */ +public class JndiServiceInitiator implements ServiceInitiator { + public static final JndiServiceInitiator INSTANCE = new JndiServiceInitiator(); + + /** + * {@inheritDoc} + */ + public Class getServiceInitiated() { + return JndiService.class; + } + + /** + * {@inheritDoc} + */ + public JndiService initiateService(Map configurationValues, ServicesRegistry registry) { + return new JndiServiceImpl( configurationValues ); + } +} diff --git a/core/src/main/java/org/hibernate/service/jndi/spi/JndiService.java b/core/src/main/java/org/hibernate/service/jndi/spi/JndiService.java new file mode 100644 index 0000000000..7d16f1d4ff --- /dev/null +++ b/core/src/main/java/org/hibernate/service/jndi/spi/JndiService.java @@ -0,0 +1,50 @@ +/* + * 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.service.jndi.spi; + +import org.hibernate.service.spi.Service; + +/** + * Service providing simplified access to JNDI related features needed by Hibernate. + * + * @author Steve Ebersole + */ +public interface JndiService extends Service { + /** + * Locate an object in JNDI by name + * + * @param jndiName The JNDI name of the object to locate + * + * @return The object found (may be null). + */ + public Object locate(String jndiName); + + /** + * Binds a value into JNDI by name. + * + * @param jndiName The name under whcih to bind the object + * @param value The value to bind + */ + public void bind(String jndiName, Object value); +} diff --git a/core/src/main/java/org/hibernate/service/spi/Configurable.java b/core/src/main/java/org/hibernate/service/spi/Configurable.java new file mode 100644 index 0000000000..4e1a69dbf5 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/Configurable.java @@ -0,0 +1,40 @@ +/* + * 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.service.spi; + +import java.util.Map; + +/** + * Allows the service to request access to the configuration properties for configuring itself. + * + * @author Steve Ebersole + */ +public interface Configurable { + /** + * Configure the service. + * + * @param configurationValues The configuration properties. + */ + public void configure(Map configurationValues); +} diff --git a/core/src/main/java/org/hibernate/service/spi/InjectService.java b/core/src/main/java/org/hibernate/service/spi/InjectService.java new file mode 100644 index 0000000000..e146c180ec --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/InjectService.java @@ -0,0 +1,54 @@ +/* + * 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.service.spi; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +/** + * Annotation to allow services to request injection of other services + * + * @author Steve Ebersole + */ +@Target(METHOD) +@Retention(RUNTIME) +public @interface InjectService { + /** + * The service role to inject, the default is to use the type of the parameter to which this method is + * attached. + * + * @return The service role. + */ + public Class serviceRole() default Void.class; + + /** + * Is the service to be injected required (not optional)? + * + * @return True if the service is required. + */ + public boolean required() default true; +} diff --git a/core/src/main/java/org/hibernate/service/spi/Manageable.java b/core/src/main/java/org/hibernate/service/spi/Manageable.java new file mode 100644 index 0000000000..150447fb16 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/Manageable.java @@ -0,0 +1,54 @@ +/* + * 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.service.spi; + +/** + * Optional {@link Service} contract for services which can be managed in JMX + * + * @author Steve Ebersole + */ +public interface Manageable { + /** + * Get the domain name to be used in registering the management bean. May be {@code null} to indicate Hibernate's + * default domain ({@code org.hibernate.core}) should be used. + * + * @return The management domain. + */ + public String getManagementDomain(); + + /** + * Allows the service to specify a special 'serviceType' portion of the object name. {@code null} indicates + * we should use the default scheme, which is to use the name of the service impl class for this purpose. + * + * @return The custom 'serviceType' name. + */ + public String getManagementServiceType(); + + /** + * The the management bean (MBean) for this service. + * + * @return The management bean. + */ + public Object getManagementBean(); +} diff --git a/core/src/main/java/org/hibernate/service/spi/Service.java b/core/src/main/java/org/hibernate/service/spi/Service.java new file mode 100644 index 0000000000..134f3e5836 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/Service.java @@ -0,0 +1,32 @@ +/* + * 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.service.spi; + +/** + * Marker interface for services. + * + * @author Steve Ebersole + */ +public interface Service { +} diff --git a/core/src/main/java/org/hibernate/service/spi/ServiceException.java b/core/src/main/java/org/hibernate/service/spi/ServiceException.java new file mode 100644 index 0000000000..59ea3f1385 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/ServiceException.java @@ -0,0 +1,41 @@ +/* + * 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.service.spi; + +import org.hibernate.HibernateException; + +/** + * Indicates a problem with a service. + * + * @author Steve Ebersole + */ +public class ServiceException extends HibernateException { + public ServiceException(String message, Throwable root) { + super( message, root ); + } + + public ServiceException(String message) { + super( message ); + } +} diff --git a/core/src/main/java/org/hibernate/service/spi/ServiceInitiator.java b/core/src/main/java/org/hibernate/service/spi/ServiceInitiator.java new file mode 100644 index 0000000000..52e768f98b --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/ServiceInitiator.java @@ -0,0 +1,50 @@ +/* + * 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.service.spi; + +import java.util.Map; + +/** + * Responsible for initiating services. + * + * @author Steve Ebersole + */ +public interface ServiceInitiator { + /** + * Obtains the service role initiated by this initiator. Should be uniqie withion a registry + * + * @return The service role. + */ + public Class getServiceInitiated(); + + /** + * Initiates the managed service. + * + * @param configurationValues The configuration values in effect + * @param registry The service registry. Can be used to locate services needed to fulfill initiation. + * + * @return The initiated service. + */ + public T initiateService(Map configurationValues, ServicesRegistry registry); +} diff --git a/core/src/main/java/org/hibernate/service/spi/ServicesRegistry.java b/core/src/main/java/org/hibernate/service/spi/ServicesRegistry.java new file mode 100644 index 0000000000..f46017634b --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/ServicesRegistry.java @@ -0,0 +1,43 @@ +/* + * 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.service.spi; + +/** + * The registry of services used by Hibernate + * + * @author Steve Ebersole + */ +public interface ServicesRegistry { + /** + * Retrieve a service by role. + * + * @param type The service role + * @param The type of the service + * + * @return The requested service. + * + * @throws UnknownServiceException Indicates the service was not known. + */ + public T getService(Class type); +} diff --git a/core/src/main/java/org/hibernate/service/spi/ServicesRegistryAwareService.java b/core/src/main/java/org/hibernate/service/spi/ServicesRegistryAwareService.java new file mode 100644 index 0000000000..50ea752cc9 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/ServicesRegistryAwareService.java @@ -0,0 +1,38 @@ +/* + * 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.service.spi; + +/** + * Allows services to be injected with the {@link ServicesRegistry} during configuration phase. + * + * @author Steve Ebersole + */ +public interface ServicesRegistryAwareService { + /** + * Callback to inject the regsitry. + * + * @param servicesRegistry The registry + */ + public void injectServices(ServicesRegistry servicesRegistry); +} diff --git a/core/src/main/java/org/hibernate/service/spi/Startable.java b/core/src/main/java/org/hibernate/service/spi/Startable.java new file mode 100644 index 0000000000..53b79d098b --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/Startable.java @@ -0,0 +1,36 @@ +/* + * 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.service.spi; + +/** + * Lifecyle contract for services which wish to be notified when it is time to start. + * + * @author Steve Ebersole + */ +public interface Startable { + /** + * Start phase notification + */ + public void start(); +} diff --git a/core/src/main/java/org/hibernate/service/spi/Stoppable.java b/core/src/main/java/org/hibernate/service/spi/Stoppable.java new file mode 100644 index 0000000000..65cdceea7f --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/Stoppable.java @@ -0,0 +1,36 @@ +/* + * 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.service.spi; + +/** + * Lifecyle contract for services which wish to be notified when it is time to stop. + * + * @author Steve Ebersole + */ +public interface Stoppable { + /** + * Stop phase notification + */ + public void stop(); +} diff --git a/core/src/main/java/org/hibernate/service/spi/UnknownServiceException.java b/core/src/main/java/org/hibernate/service/spi/UnknownServiceException.java new file mode 100644 index 0000000000..2d2c249c45 --- /dev/null +++ b/core/src/main/java/org/hibernate/service/spi/UnknownServiceException.java @@ -0,0 +1,44 @@ +/* + * 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.service.spi; + +import org.hibernate.HibernateException; + +/** + * Indicates that an unkown service was requested from the registry. + * + * @author Steve Ebersole + */ +public class UnknownServiceException extends HibernateException { + public final Class serviceRole; + + public UnknownServiceException(Class serviceRole) { + super( "Unknown service requested [" + serviceRole.getName() + "]" ); + this.serviceRole = serviceRole; + } + + public Class getServiceRole() { + return serviceRole; + } +}