From d4bf11d8ba495ce308e7914fc1c2620937b68612 Mon Sep 17 00:00:00 2001 From: Gail Badner Date: Wed, 13 Oct 2010 13:16:25 -0700 Subject: [PATCH] HHH-5641 : Import JtaPlatform services --- .../internal/util/jta/JtaStatusHelper.java | 198 ++++++++++++++++++ .../internal/JBossAppServerPlatform.java | 94 +++++++++ .../internal/JtaPlatformInitiator.java | 74 +++++++ .../service/jta/platform/spi/JtaPlatform.java | 74 +++++++ 4 files changed, 440 insertions(+) create mode 100644 hibernate-core/src/main/java/org/hibernate/internal/util/jta/JtaStatusHelper.java create mode 100644 hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java create mode 100644 hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java create mode 100644 hibernate-core/src/main/java/org/hibernate/service/jta/platform/spi/JtaPlatform.java diff --git a/hibernate-core/src/main/java/org/hibernate/internal/util/jta/JtaStatusHelper.java b/hibernate-core/src/main/java/org/hibernate/internal/util/jta/JtaStatusHelper.java new file mode 100644 index 0000000000..d9c2c05e45 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/internal/util/jta/JtaStatusHelper.java @@ -0,0 +1,198 @@ +/* + * 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.internal.util.jta; + +import javax.transaction.Status; +import javax.transaction.SystemException; +import javax.transaction.TransactionManager; +import javax.transaction.UserTransaction; + +import org.hibernate.TransactionException; + +/** + * Utility for dealing with JTA statses. + * + * @author Steve Ebersole + */ +public class JtaStatusHelper { + /** + * Extract the status code from a {@link UserTransaction} + * + * @param userTransaction The {@link UserTransaction} from which to extract the status. + * + * @return The transaction status + * + * @throws TransactionException If the {@link UserTransaction} reports the status as unknown + */ + public static int getStatus(UserTransaction userTransaction) { + try { + final int status = userTransaction.getStatus(); + if ( status == Status.STATUS_UNKNOWN ) { + throw new TransactionException( "UserTransaction reported transaction status as unknwon" ); + } + return status; + } + catch ( SystemException se ) { + throw new TransactionException( "Could not determine transaction status", se ); + } + } + + /** + * Extract the status code from the current {@link javax.transaction.Transaction} associated with the + * given {@link TransactionManager} + * + * @param transactionManager The {@link TransactionManager} from which to extract the status. + * + * @return The transaction status + * + * @throws TransactionException If the {@link TransactionManager} reports the status as unknown + */ + public static int getStatus(TransactionManager transactionManager) { + try { + final int status = transactionManager.getStatus(); + if ( status == Status.STATUS_UNKNOWN ) { + throw new TransactionException( "TransactionManager reported transaction status as unknwon" ); + } + return status; + } + catch ( SystemException se ) { + throw new TransactionException( "Could not determine transaction status", se ); + } + } + + /** + * Does the given status code indicate an active transaction? + * + * @param status The transaction status code to check + * + * @return True if the code indicates active; false otherwise. + */ + public static boolean isActive(int status) { + return status == Status.STATUS_ACTIVE; + } + + /** + * Does the status code obtained from the given {@link UserTransaction} indicate an active transaction? + * + * @param userTransaction The {@link UserTransaction} whose status is to be checked + * + * @return True if the transactiion is active; false otherwise. + */ + public static boolean isActive(UserTransaction userTransaction) { + final int status = getStatus( userTransaction ); + return isActive( status ); + } + + /** + * Does the status code obtained from the given {@link TransactionManager} indicate an active transaction? + * + * @param transactionManager The {@link TransactionManager} whose status is to be checked + * + * @return True if the transactiion is active; false otherwise. + */ + public static boolean isActive(TransactionManager transactionManager) { + return isActive( getStatus( transactionManager ) ); + } + + /** + * Does the given status code indicate a rolled back transaction? + * + * @param status The transaction status code to check + * + * @return True if the code indicates a roll back; false otherwise. + */ + public static boolean isRollback(int status) { + return status == Status.STATUS_MARKED_ROLLBACK || + status == Status.STATUS_ROLLING_BACK || + status == Status.STATUS_ROLLEDBACK; + } + + /** + * Does the status code obtained from the given {@link UserTransaction} indicate a roll back? + * + * @param userTransaction The {@link UserTransaction} whose status is to be checked + * + * @return True if the transactiion indicates roll back; false otherwise. + */ + public static boolean isRollback(UserTransaction userTransaction) { + return isRollback( getStatus( userTransaction ) ); + } + + /** + * Does the status code obtained from the given {@link TransactionManager} indicate a roll back? + * + * @param transactionManager The {@link TransactionManager} whose status is to be checked + * + * @return True if the transactiion indicates roll back; false otherwise. + */ + public static boolean isRollback(TransactionManager transactionManager) { + return isRollback( getStatus( transactionManager ) ); + } + + /** + * Does the given status code indicate a committed transaction? + * + * @param status The transaction status code to check + * + * @return True if the code indicates a roll back; false otherwise. + */ + public static boolean isCommitted(int status) { + return status == Status.STATUS_MARKED_ROLLBACK || + status == Status.STATUS_ROLLING_BACK || + status == Status.STATUS_ROLLEDBACK; + } + + /** + * Does the status code obtained from the given {@link UserTransaction} indicate a commit? + * + * @param userTransaction The {@link UserTransaction} whose status is to be checked + * + * @return True if the transactiion indicates commit; false otherwise. + */ + public static boolean isCommitted(UserTransaction userTransaction) { + return isCommitted( getStatus( userTransaction ) ); + } + + /** + * Does the status code obtained from the given {@link TransactionManager} indicate a commit? + * + * @param transactionManager The {@link TransactionManager} whose status is to be checked + * + * @return True if the transactiion indicates commit; false otherwise. + */ + public static boolean isCommitted(TransactionManager transactionManager) { + return isCommitted( getStatus( transactionManager ) ); + } + + /** + * Does the given status code indicate the transaction has been marked for rollback? + * + * @param status The transaction status code to check + * + * @return True if the code indicates a roll back; false otherwise. + */ + public static boolean isMarkedForRollback(int status) { + return status == Status.STATUS_MARKED_ROLLBACK; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java new file mode 100644 index 0000000000..6250106a95 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JBossAppServerPlatform.java @@ -0,0 +1,94 @@ +/* + * 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.jta.platform.internal; + +import java.util.Map; +import javax.transaction.Synchronization; +import javax.transaction.TransactionManager; +import javax.transaction.TransactionSynchronizationRegistry; +import javax.transaction.UserTransaction; + +import org.hibernate.internal.util.jta.JtaStatusHelper; +import org.hibernate.service.jta.platform.spi.JtaPlatform; +import org.hibernate.service.spi.Configurable; +import org.hibernate.service.spi.InjectService; +import org.hibernate.internal.util.config.ConfigurationHelper; +import org.hibernate.service.jndi.spi.JndiService; + + +/** + * TODO : javadoc + * + * @author Steve Ebersole + */ +public class JBossAppServerPlatform implements JtaPlatform, Configurable { + public static final String TM_NAME = "java:/TransactionManager"; + public static final String UT_NAME = "UserTransaction"; + public static final String REG_NAME = "java:comp/TransactionSynchronizationRegistry"; + + private JndiService jndiService; + + @InjectService + public void setJndiService(JndiService jndiService) { + this.jndiService = jndiService; + } + + private boolean cacheTransactionManager; + + public void configure(Map configValues) { + cacheTransactionManager = ConfigurationHelper.getBoolean( CACHE_TM, configValues, true ); + } + + private TransactionManager transactionManager; + + public TransactionManager resolveTransactionManager() { + if ( cacheTransactionManager ) { + if ( transactionManager == null ) { + transactionManager = (TransactionManager) jndiService.locate( TM_NAME ); + } + return transactionManager; + } + else { + return (TransactionManager) jndiService.locate( TM_NAME ); + } + } + + public UserTransaction resolveUserTransaction() { + return (UserTransaction) jndiService.locate( UT_NAME ); + } + + public void registerSynchronization(Synchronization synchronization) { + getTransactionSynchronizationRegistry().registerInterposedSynchronization( synchronization ); + } + + private TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() { + return (TransactionSynchronizationRegistry) jndiService.locate( REG_NAME ); + } + + public boolean canRegisterSynchronization() { + TransactionSynchronizationRegistry registry = getTransactionSynchronizationRegistry(); + int status = registry.getTransactionStatus(); + return JtaStatusHelper.isActive( status ) && ! registry.getRollbackOnly(); + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java new file mode 100644 index 0000000000..a26c27fbea --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/internal/JtaPlatformInitiator.java @@ -0,0 +1,74 @@ +/* + * 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.jta.platform.internal; + +import java.util.Map; + +import org.hibernate.HibernateException; +import org.hibernate.service.classloading.spi.ClassLoaderService; +import org.hibernate.service.jta.platform.spi.JtaPlatform; +import org.hibernate.service.spi.ServicesRegistry; +import org.hibernate.service.spi.ServiceInitiator; + +/** + * Standard initiator for the standard {@link org.hibernate.service.jta.platform.spi.JtaPlatform} + * + * @author Steve Ebersole + */ +public class JtaPlatformInitiator implements ServiceInitiator { + public static final JtaPlatformInitiator INSTANCE = new JtaPlatformInitiator(); + + public static final String JTA_PLATFORM = "hibernate.jta.platform"; + + /** + * {@inheritDoc} + */ + public Class getServiceInitiated() { + return JtaPlatform.class; + } + + /** + * {@inheritDoc} + */ + public JtaPlatform initiateService(Map configVales, ServicesRegistry registry) { + final Object platform = configVales.get( JTA_PLATFORM ); + if ( JtaPlatform.class.isInstance( platform ) ) { + return (JtaPlatform) platform; + } + + if ( platform == null ) { + return null; + } + + final String platformImplName = platform.toString(); + + ClassLoaderService classLoaderService = registry.getService( ClassLoaderService.class ); + try { + return (JtaPlatform) classLoaderService.classForName( platformImplName ).newInstance(); + } + catch ( Exception e ) { + throw new HibernateException( "Unable to create specified JtaPlatform class [" + platformImplName + "]", e ); + } + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/service/jta/platform/spi/JtaPlatform.java b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/spi/JtaPlatform.java new file mode 100644 index 0000000000..a6e23eb5b0 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/service/jta/platform/spi/JtaPlatform.java @@ -0,0 +1,74 @@ +/* + * 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.jta.platform.spi; + +import javax.transaction.Synchronization; +import javax.transaction.TransactionManager; +import javax.transaction.UserTransaction; + +import org.hibernate.service.spi.Service; + +/** + * Defines how we interact with various JTA services on the given platform/environment. + * + * @author Steve Ebersole + */ +public interface JtaPlatform extends Service { + /** + * A configuration value key used to indicate that it is safe to cache + * {@link TransactionManager} references. + * + * @todo add to Environment. + * @todo same for UserTransaction too? On many platforms UserTransaction and TransactionManager are the same + */ + public static final String CACHE_TM = "hibernate.jta.cacheTransactionManager"; + + /** + * Locate the {@link TransactionManager} + * + * @return The {@link TransactionManager} + */ + public TransactionManager resolveTransactionManager(); + + /** + * Locate the {@link UserTransaction} + * + * @return The {@link UserTransaction} + */ + public UserTransaction resolveUserTransaction(); + + /** + * Register a JTA {@link Synchronization} in the means defined by the platform. + * + * @param synchronization The synchronization to register + */ + public void registerSynchronization(Synchronization synchronization); + + /** + * Can we currently regsiter a {@link Synchronization}? + * + * @return True if regsitering a {@link Synchronization} is currently allowed; false otherwise. + */ + public boolean canRegisterSynchronization(); +}