001/* 002 * (C) Copyright 2012 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 * 016 * Contributors: 017 * Florent Guillaume 018 */ 019package org.nuxeo.ecm.core.storage.sql.jdbc; 020 021import static javax.transaction.xa.XAException.XAER_INVAL; 022import static javax.transaction.xa.XAException.XAER_PROTO; 023import static javax.transaction.xa.XAException.XAER_RMERR; 024 025import java.sql.SQLException; 026 027import javax.transaction.xa.XAException; 028import javax.transaction.xa.XAResource; 029import javax.transaction.xa.Xid; 030 031import org.apache.commons.logging.Log; 032import org.apache.commons.logging.LogFactory; 033 034/** 035 * Adapter for a simple JDBC Connection that gives it the XAResource interface, without actually implementing XA 036 * (prepare does nothing). 037 * 038 * @since 5.7 039 */ 040public class XAResourceConnectionAdapter implements XAResource { 041 042 private static final Log log = LogFactory.getLog(XAResourceConnectionAdapter.class); 043 044 protected JDBCConnection owner; 045 046 protected Xid xid; 047 048 public XAResourceConnectionAdapter(JDBCConnection connection) { 049 owner = connection; 050 } 051 052 @Override 053 public void start(Xid xid, int flag) throws XAException { 054 if (flag == TMNOFLAGS) { 055 if (this.xid != null) { 056 throw newXAException(XAER_PROTO, "Already started"); 057 } 058 this.xid = xid; 059 try { 060 owner.connection.setAutoCommit(false); 061 } catch (SQLException e) { 062 throw newXAException(XAER_RMERR, "Cannot set autoCommit=false"); 063 } 064 } else { 065 // cannot support resume 066 throw newXAException(XAER_INVAL, "Invalid flag: " + flag); 067 } 068 } 069 070 @Override 071 public void end(Xid xid, int flag) throws XAException { 072 if (xid != this.xid) { 073 throw newXAException(XAER_INVAL, "Invalid Xid"); 074 } 075 if (flag != TMSUCCESS && flag != TMFAIL) { 076 throw newXAException(XAER_INVAL, "Invalid flag: " + flag); 077 } 078 } 079 080 @Override 081 public int prepare(Xid xid) throws XAException { 082 return XA_OK; 083 } 084 085 @Override 086 public void commit(Xid xid, boolean flag) throws XAException { 087 if (this.xid == null || !this.xid.equals(xid)) { 088 throw newXAException(XAER_INVAL, "Invalid Xid"); 089 } 090 this.xid = null; 091 try { 092 owner.connection.commit(); 093 } catch (SQLException e) { 094 throw newXAException(XAER_RMERR, "Cannot commit", e); 095 } finally { 096 try { 097 owner.connection.setAutoCommit(true); 098 } catch (SQLException e) { 099 log.error("Cannot set autoCommit=true", e); 100 } 101 } 102 } 103 104 @Override 105 public void rollback(Xid xid) throws XAException { 106 if (this.xid == null || !this.xid.equals(xid)) { 107 throw newXAException(XAER_INVAL, "Invalid Xid"); 108 } 109 this.xid = null; 110 try { 111 owner.connection.rollback(); 112 } catch (SQLException e) { 113 throw newXAException(XAER_RMERR, "Cannot rollback", e); 114 } finally { 115 try { 116 owner.connection.setAutoCommit(true); 117 } catch (SQLException e) { 118 log.error("Cannot set autoCommit=true", e); 119 } 120 } 121 } 122 123 @Override 124 public void forget(Xid xid) throws XAException { 125 throw newXAException(XAER_PROTO, "Unsupported method"); 126 } 127 128 @Override 129 public Xid[] recover(int n) throws XAException { 130 return new Xid[0]; 131 } 132 133 @Override 134 public int getTransactionTimeout() throws XAException { 135 return 0; 136 } 137 138 @Override 139 public boolean setTransactionTimeout(int txTimeout) throws XAException { 140 return false; 141 } 142 143 @Override 144 public boolean isSameRM(XAResource xares) throws XAException { 145 return this == xares; 146 } 147 148 protected static XAException newXAException(int errorCode, String message, Exception cause) { 149 return (XAException) newXAException(errorCode, message).initCause(cause); 150 } 151 152 protected static XAException newXAException(int errorCode, String message) { 153 XAException e = new XAException(message); 154 e.errorCode = errorCode; 155 return e; 156 } 157 158}