/* * Copyright 2004-2015 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.extension.jta.xa; import javax.transaction.xa.XAException; import javax.transaction.xa.XAResource; import javax.transaction.xa.Xid; import org.seasar.framework.exception.SXAException; /** * {@link XAResource}の抽象クラスです。 * * @author higa * */ public abstract class AbstractXAResource implements XAResource, XAResourceStatus { private Xid currentXid; private int status = RS_NONE; private int timeout = 0; /** * {@link AbstractXAResource}を作成します。 */ public AbstractXAResource() { } public void start(Xid xid, int flags) throws XAException { switch (flags) { case TMNOFLAGS: begin(xid); break; case TMRESUME: resume(xid); break; default: throw new SXAException("ESSR0032", new Object[] { String .valueOf(flags) }); } } private void begin(Xid xid) throws XAException { assertCurrentXidNull(); doBegin(xid); currentXid = xid; status = RS_ACTIVE; } private void assertCurrentXidNull() throws XAException { if (currentXid != null) { throw new SXAException("ESSR0316", null); } } /** * トランザクションを開始します。 * * @param xid * トランザクション識別子 * @throws XAException * XA例外が発生した場合 */ protected abstract void doBegin(Xid xid) throws XAException; private void resume(Xid xid) throws XAException { assertCurrentXidSame(xid); assertStatusSuspended(); doResume(xid); status = RS_ACTIVE; } private void assertCurrentXidSame(final Xid xid) throws XAException { if (currentXid != xid) { throw new SXAException("ESSR0319", new Object[] { xid, currentXid }); } } private void assertStatusSuspended() throws XAException { if (status != RS_SUSPENDED) { throw new SXAException("ESSR0323", null); } } /** * レジュームします。 * * @param xid * トランザクション識別子 * @throws XAException * XA例外が発生した場合 */ protected abstract void doResume(Xid xid) throws XAException; public void end(Xid xid, int flags) throws XAException { assertCurrentXidSame(xid); assertStatusActive(); switch (flags) { case TMSUSPEND: suspend(xid); break; case TMFAIL: fail(xid); break; case TMSUCCESS: success(xid); break; default: throw new SXAException("ESSR0032", new Object[] { String .valueOf(flags) }); } } private void assertStatusActive() throws XAException { if (status != RS_ACTIVE) { throw new SXAException("ESSR0324", null); } } private void suspend(Xid xid) throws XAException { doSuspend(xid); status = RS_SUSPENDED; } /** * サスペンドします。 * * @param xid * トランザクション識別子 * @throws XAException * XA例外が発生した場合 */ protected abstract void doSuspend(Xid xid) throws XAException; private void fail(Xid xid) throws XAException { doFail(xid); status = RS_FAIL; } /** * 失敗させます。 * * @param xid * トランザクション識別子 * @throws XAException */ protected abstract void doFail(Xid xid) throws XAException; private void success(Xid xid) throws XAException { doSuccess(xid); status = RS_SUCCESS; } /** * 成功時の処理を行ないます。 * * @param xid * トランザクション識別子 * @throws XAException * XA例外が発生した場合 */ protected abstract void doSuccess(Xid xid) throws XAException; public int prepare(Xid xid) throws XAException { assertCurrentXidSame(xid); assertStatusSuccess(); int ret = doPrepare(xid); if (ret == XA_OK) { status = RS_PREPARED; } else { status = RS_NONE; } return ret; } private void assertStatusSuccess() throws XAException { if (status != RS_SUCCESS) { throw new SXAException("ESSR0320", null); } } /** * コミットする準備を行ないます。 * * @param xid * トランザクション識別子 * @return 投票の結果 * @throws XAException * XA例外が発生した場合 */ protected abstract int doPrepare(Xid xid) throws XAException; public void commit(Xid xid, boolean onePhase) throws XAException { assertCurrentXidSame(xid); if (onePhase) { assertStatusSuccess(); } else { assertStatusPrepared(); } doCommit(xid, onePhase); init(); } private void assertStatusPrepared() throws XAException { if (status != RS_PREPARED) { throw new SXAException("ESSR0321", null); } } /** * コミットします。 * * @param xid * トランザクション識別子 * @param onePhase * 1フェーズかどうか * @throws XAException * XA例外が発生した場合 */ protected abstract void doCommit(Xid xid, boolean onePhase) throws XAException; private void init() { currentXid = null; status = RS_NONE; } public void forget(Xid xid) throws XAException { assertCurrentXidSame(xid); doForget(xid); init(); } /** * トランザクションを忘れます。 * * @param xid * トランザクション識別子 * @throws XAException * XA例外が発生した場合 */ protected abstract void doForget(Xid xid) throws XAException; public Xid[] recover(final int flag) throws XAException { return null; } public void rollback(final Xid xid) throws XAException { assertCurrentXidSame(xid); assertStatusSuccessOrFailOrPrepared(); doRollback(xid); init(); } private void assertStatusSuccessOrFailOrPrepared() throws XAException { switch (status) { case RS_SUCCESS: case RS_FAIL: case RS_PREPARED: break; default: throw new SXAException("ESSR0322", null); } } /** * ロールバックします。 * * @param xid * トランザクション識別子 * @throws XAException * XA例外が発生した場合 */ protected abstract void doRollback(Xid xid) throws XAException; public boolean isSameRM(XAResource xar) throws XAException { return false; } public int getTransactionTimeout() throws XAException { return timeout; } public boolean setTransactionTimeout(int timeout) throws XAException { this.timeout = timeout; return true; } /** * 現在のトランザクション識別子を返します。 * * @return 現在のトランザクション識別子 */ public Xid getCurrentXid() { return currentXid; } /** * ステータスを返します。 * * @return ステータス */ public int getStatus() { return status; } }