|
1 | 1 | /* |
2 | | - * Copyright 2002-2012 the original author or authors. |
| 2 | + * Copyright 2002-2013 the original author or authors. |
3 | 3 | * |
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | 5 | * you may not use this file except in compliance with the License. |
|
16 | 16 |
|
17 | 17 | package org.springframework.orm.hibernate4; |
18 | 18 |
|
| 19 | +import java.lang.reflect.InvocationHandler; |
| 20 | +import java.lang.reflect.Method; |
| 21 | +import java.lang.reflect.Proxy; |
| 22 | +import javax.transaction.Status; |
| 23 | +import javax.transaction.Synchronization; |
| 24 | +import javax.transaction.SystemException; |
| 25 | +import javax.transaction.Transaction; |
19 | 26 | import javax.transaction.TransactionManager; |
| 27 | +import javax.transaction.TransactionSynchronizationRegistry; |
20 | 28 | import javax.transaction.UserTransaction; |
21 | 29 |
|
22 | | -import org.hibernate.service.jta.platform.internal.AbstractJtaPlatform; |
| 30 | +import org.hibernate.TransactionException; |
| 31 | +import org.hibernate.service.Service; |
23 | 32 |
|
24 | 33 | import org.springframework.transaction.jta.UserTransactionAdapter; |
25 | 34 | import org.springframework.util.Assert; |
26 | 35 |
|
27 | 36 | /** |
28 | | - * Implementation of Hibernate 4's {@link org.hibernate.service.jta.platform.spi.JtaPlatform} |
29 | | - * SPI, exposing passed-in {@link TransactionManager} and {@link UserTransaction} references. |
| 37 | + * Implementation of Hibernate 4's JtaPlatform SPI (which has a different package |
| 38 | + * location in Hibernate 4.0-4.2 vs 4.3), exposing passed-in {@link TransactionManager}, |
| 39 | + * {@link UserTransaction} and {@link TransactionSynchronizationRegistry} references. |
30 | 40 | * |
31 | 41 | * @author Juergen Hoeller |
32 | 42 | * @since 3.1.2 |
33 | 43 | */ |
34 | | -@SuppressWarnings("serial") |
35 | | -class ConfigurableJtaPlatform extends AbstractJtaPlatform { |
| 44 | +@SuppressWarnings({"serial", "unchecked"}) |
| 45 | +class ConfigurableJtaPlatform implements InvocationHandler { |
| 46 | + |
| 47 | + static final Class<? extends Service> jtaPlatformClass; |
| 48 | + |
| 49 | + static { |
| 50 | + Class<?> jpClass; |
| 51 | + try { |
| 52 | + // Try Hibernate 4.0-4.2 JtaPlatform variant |
| 53 | + jpClass = SpringSessionContext.class.getClassLoader().loadClass( |
| 54 | + "org.hibernate.service.jta.platform.spi.JtaPlatform"); |
| 55 | + } |
| 56 | + catch (ClassNotFoundException ex) { |
| 57 | + try { |
| 58 | + // Try Hibernate 4.3 JtaPlatform variant |
| 59 | + jpClass = SpringSessionContext.class.getClassLoader().loadClass( |
| 60 | + "org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform"); |
| 61 | + } |
| 62 | + catch (ClassNotFoundException ex2) { |
| 63 | + throw new IllegalStateException("Neither Hibernate 4.0-4.2 nor 4.3 variant of JtaPlatform found"); |
| 64 | + } |
| 65 | + } |
| 66 | + jtaPlatformClass = (Class<? extends Service>) jpClass; |
| 67 | + } |
| 68 | + |
| 69 | + static String getJtaPlatformBasePackage() { |
| 70 | + String className = jtaPlatformClass.getName(); |
| 71 | + return className.substring(0, className.length() - "spi.JtaPlatform".length()); |
| 72 | + } |
| 73 | + |
36 | 74 |
|
37 | 75 | private final TransactionManager transactionManager; |
38 | 76 |
|
39 | 77 | private final UserTransaction userTransaction; |
40 | 78 |
|
| 79 | + private final TransactionSynchronizationRegistry transactionSynchronizationRegistry; |
| 80 | + |
41 | 81 |
|
42 | 82 | /** |
43 | 83 | * Create a new ConfigurableJtaPlatform instance with the given |
44 | 84 | * JTA TransactionManager and optionally a given UserTransaction. |
45 | 85 | * @param tm the JTA TransactionManager reference (required) |
46 | 86 | * @param ut the JTA UserTransaction reference (optional) |
| 87 | + * @param tsr the JTA 1.1 TransactionSynchronizationRegistry (optional) |
47 | 88 | */ |
48 | | - public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut) { |
| 89 | + public ConfigurableJtaPlatform(TransactionManager tm, UserTransaction ut, TransactionSynchronizationRegistry tsr) { |
49 | 90 | Assert.notNull(tm, "TransactionManager reference must not be null"); |
50 | 91 | this.transactionManager = tm; |
51 | 92 | this.userTransaction = (ut != null ? ut : new UserTransactionAdapter(tm)); |
| 93 | + this.transactionSynchronizationRegistry = tsr; |
52 | 94 | } |
53 | 95 |
|
54 | 96 |
|
55 | | - @Override |
56 | | - protected TransactionManager locateTransactionManager() { |
| 97 | + public TransactionManager retrieveTransactionManager() { |
57 | 98 | return this.transactionManager; |
58 | 99 | } |
59 | 100 |
|
60 | | - @Override |
61 | | - protected UserTransaction locateUserTransaction() { |
| 101 | + public UserTransaction retrieveUserTransaction() { |
62 | 102 | return this.userTransaction; |
63 | 103 | } |
64 | 104 |
|
65 | | - @Override |
66 | | - protected boolean canCacheTransactionManager() { |
67 | | - return true; |
| 105 | + public Object getTransactionIdentifier(Transaction transaction) { |
| 106 | + return transaction; |
68 | 107 | } |
69 | 108 |
|
| 109 | + public boolean canRegisterSynchronization() { |
| 110 | + try { |
| 111 | + return (this.transactionManager.getStatus() == Status.STATUS_ACTIVE); |
| 112 | + } |
| 113 | + catch (SystemException ex) { |
| 114 | + throw new TransactionException("Could not determine JTA transaction status", ex); |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + public void registerSynchronization(Synchronization synchronization) { |
| 119 | + if (this.transactionSynchronizationRegistry != null) { |
| 120 | + this.transactionSynchronizationRegistry.registerInterposedSynchronization(synchronization); |
| 121 | + } |
| 122 | + else { |
| 123 | + try { |
| 124 | + this.transactionManager.getTransaction().registerSynchronization(synchronization); |
| 125 | + } |
| 126 | + catch (Exception ex) { |
| 127 | + throw new TransactionException("Could not access JTA Transaction to register synchronization", ex); |
| 128 | + } |
| 129 | + } |
| 130 | + } |
| 131 | + |
| 132 | + public int getCurrentStatus() throws SystemException { |
| 133 | + return this.transactionManager.getStatus(); |
| 134 | + } |
| 135 | + |
| 136 | + |
70 | 137 | @Override |
71 | | - protected boolean canCacheUserTransaction() { |
72 | | - return true; |
| 138 | + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { |
| 139 | + Method targetMethod = getClass().getMethod(method.getName(), method.getParameterTypes()); |
| 140 | + return targetMethod.invoke(this, args); |
| 141 | + } |
| 142 | + |
| 143 | + /** |
| 144 | + * Obtain a proxy that implements the current Hibernate version's JtaPlatform interface |
| 145 | + * in the right package location, delegating all invocations to the same-named methods |
| 146 | + * on this ConfigurableJtaPlatform class itself. |
| 147 | + */ |
| 148 | + public Object getJtaPlatformProxy() { |
| 149 | + return Proxy.newProxyInstance(getClass().getClassLoader(), new Class<?>[] {jtaPlatformClass}, this); |
73 | 150 | } |
74 | 151 |
|
75 | 152 | } |
0 commit comments