xasessionimpl.java

来自「jsr170接口的java实现。是个apache的开源项目。」· Java 代码 · 共 424 行

JAVA
424
字号
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.jackrabbit.core;import org.apache.jackrabbit.core.config.WorkspaceConfig;import org.apache.jackrabbit.core.lock.LockManager;import org.apache.jackrabbit.core.lock.LockManagerImpl;import org.apache.jackrabbit.core.lock.XALockManager;import org.apache.jackrabbit.core.security.AuthContext;import org.apache.jackrabbit.core.state.SharedItemStateManager;import org.apache.jackrabbit.core.state.XAItemStateManager;import org.apache.jackrabbit.core.version.VersionManager;import org.apache.jackrabbit.core.version.VersionManagerImpl;import org.apache.jackrabbit.core.version.XAVersionManager;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.jcr.AccessDeniedException;import javax.jcr.RepositoryException;import javax.security.auth.Subject;import javax.transaction.xa.XAException;import javax.transaction.xa.XAResource;import javax.transaction.xa.Xid;import java.util.Collections;import java.util.HashMap;import java.util.Map;/** * Session extension that provides XA support. */public class XASessionImpl extends SessionImpl        implements XASession, XAResource {    /**     * Logger instance     */    private static final Logger log = LoggerFactory.getLogger(XASessionImpl.class);    /**     * Global transactions     */    private static final Map txGlobal = Collections.synchronizedMap(new HashMap());    /**     * Default transaction timeout, in seconds.     */    private static final int DEFAULT_TX_TIMEOUT = 5;    /**     * Currently associated transaction     */    private TransactionContext tx;    /**     * Transaction timeout, in seconds     */    private int txTimeout;    /**     * List of transactional resources.     */    private InternalXAResource[] txResources;    /**     * Session-local lock manager.     */    private LockManager lockMgr;    /**     * Create a new instance of this class.     *     * @param rep          repository     * @param loginContext login context containing authenticated subject     * @param wspConfig    workspace configuration     * @throws AccessDeniedException if the subject of the given login context     *                               is not granted access to the specified     *                               workspace     * @throws RepositoryException   if another error occurs     */    protected XASessionImpl(RepositoryImpl rep, AuthContext loginContext,                            WorkspaceConfig wspConfig)            throws AccessDeniedException, RepositoryException {        super(rep, loginContext, wspConfig);        init();    }    /**     * Create a new instance of this class.     *     * @param rep       repository     * @param subject   authenticated subject     * @param wspConfig workspace configuration     * @throws AccessDeniedException if the given subject is not granted access     *                               to the specified workspace     * @throws RepositoryException   if another error occurs     */    protected XASessionImpl(RepositoryImpl rep, Subject subject,                            WorkspaceConfig wspConfig)            throws AccessDeniedException, RepositoryException {        super(rep, subject, wspConfig);        init();    }    /**     * Initialize this object.     */    private void init() throws RepositoryException {        XAItemStateManager stateMgr = (XAItemStateManager) wsp.getItemStateManager();        XALockManager lockMgr = (XALockManager) getLockManager();        XAVersionManager versionMgr = (XAVersionManager) getVersionManager();        /**         * Create array that contains all resources that paricipate in this         * transactions. Some resources depend on each other, therefore you         * should only change the sequence if you know what you are doing!         *         * There are two artificial resources on the version manager (begin and         * end), which handle locking of the version manager. The begin resource         * acquires the write lock on the version manager in its prepare method,         * while the end resource releases the write lock in either commit or         * rollback. Please note that the write lock is only acquired if there         * is someting to commit by the version manager.         * For further information see JCR-335 and JCR-962.         */        txResources = new InternalXAResource[] {            versionMgr.getXAResourceBegin(),            stateMgr, lockMgr, versionMgr,            versionMgr.getXAResourceEnd()        };        stateMgr.setVirtualProvider(versionMgr);    }    /**     * {@inheritDoc}     */    protected WorkspaceImpl createWorkspaceInstance(WorkspaceConfig wspConfig,                                                    SharedItemStateManager stateMgr,                                                    RepositoryImpl rep,                                                    SessionImpl session) {        return new XAWorkspace(wspConfig, stateMgr, rep, session);    }    /**     * {@inheritDoc}     */    protected VersionManager createVersionManager(RepositoryImpl rep)            throws RepositoryException {        VersionManagerImpl vMgr = (VersionManagerImpl) rep.getVersionManager();        return new XAVersionManager(vMgr, rep.getNodeTypeRegistry(), this, rep.getItemStateCacheFactory());    }    /**     * {@inheritDoc}     */    public LockManager getLockManager() throws RepositoryException {        if (lockMgr == null) {            LockManagerImpl lockMgr = (LockManagerImpl) wsp.getLockManager();            this.lockMgr = new XALockManager(lockMgr);        }        return lockMgr;    }    //-------------------------------------------------------------< XASession >    /**     * {@inheritDoc}     */    public XAResource getXAResource() {        return this;    }    //------------------------------------------------------------< XAResource >    /**     * {@inheritDoc}     */    public int getTransactionTimeout() {        return txTimeout == 0 ? DEFAULT_TX_TIMEOUT : txTimeout;    }    /**     * {@inheritDoc}     */    public boolean setTransactionTimeout(int seconds) {        txTimeout = seconds;        return true;    }    /**     * {@inheritDoc}     * <p/>     * Two resources belong to the same resource manager if both connections     * (i.e. sessions) have the same credentials.     */    public boolean isSameRM(XAResource xares) throws XAException {        if (xares instanceof XASessionImpl) {            XASessionImpl xases = (XASessionImpl) xares;            return stringsEqual(userId, xases.userId);        }        return false;    }    /**     * {@inheritDoc}     * <p/>     * If <code>TMNOFLAGS</code> is specified, we create a new transaction     * context and associate it with this resource.     * If <code>TMJOIN</code> is specified, this resource should use the     * same transaction context as another, already known transaction.     * If <code>TMRESUME</code> is specified, we should resume work on     * a transaction context that was suspended earlier.     * All other flags generate an <code>XAException</code> of type     * <code>XAER_INVAL</code>     */    public void start(Xid xid, int flags) throws XAException {        if (isAssociated()) {            log.error("Resource already associated with a transaction.");            throw new XAException(XAException.XAER_PROTO);        }        TransactionContext tx = (TransactionContext) txGlobal.get(xid);        if (flags == TMNOFLAGS) {            if (tx != null) {                throw new XAException(XAException.XAER_DUPID);            }            tx = createTransaction(xid);        } else if (flags == TMJOIN) {            if (tx == null) {                throw new XAException(XAException.XAER_NOTA);            }        } else if (flags == TMRESUME) {            if (tx == null) {                throw new XAException(XAException.XAER_NOTA);            }            if (!tx.isSuspended()) {                log.error("Unable to resume: transaction not suspended.");                throw new XAException(XAException.XAER_PROTO);            }            tx.setSuspended(false);        } else {            throw new XAException(XAException.XAER_INVAL);        }        associate(tx);    }    /**     * Create a new transaction context.     * @param xid xid of global transaction.     * @return transaction context     */    private TransactionContext createTransaction(Xid xid) {        TransactionContext tx = new TransactionContext(txResources, getTransactionTimeout());        txGlobal.put(xid, tx);        return tx;    }    /**     * {@inheritDoc}     * <p/>     * If <code>TMSUCCESS</code> is specified, we disassociate this session     * from the transaction specified.     * If <code>TMFAIL</code> is specified, we disassociate this session from     * the transaction specified and mark the transaction rollback only.     * If <code>TMSUSPEND</code> is specified, we disassociate this session     * from the transaction specified.     * All other flags generate an <code>XAException</code> of type     * <code>XAER_INVAL</code>     * <p/>     * It is legal for a transaction association to be suspended and then     * ended (either with <code>TMSUCCESS</code> or <code>TMFAIL</code>)     * without having been resumed again.     */    public void end(Xid xid, int flags) throws XAException {        TransactionContext tx = (TransactionContext) txGlobal.get(xid);        if (tx == null) {            throw new XAException(XAException.XAER_NOTA);        }        if (flags == TMSUSPEND) {            if (!isAssociated()) {                log.error("Resource not associated with a transaction.");                throw new XAException(XAException.XAER_PROTO);            }            associate(null);            tx.setSuspended(true);        } else if (flags == TMFAIL || flags == TMSUCCESS) {            if (!tx.isSuspended()) {                if (!isAssociated()) {                    log.error("Resource not associated with a transaction.");                    throw new XAException(XAException.XAER_PROTO);                }                associate(null);            } else {                tx.setSuspended(false);            }        } else {            throw new XAException(XAException.XAER_INVAL);        }    }    /**     * {@inheritDoc}     */    public int prepare(Xid xid) throws XAException {        TransactionContext tx = (TransactionContext) txGlobal.get(xid);        if (tx == null) {            throw new XAException(XAException.XAER_NOTA);        }        tx.prepare();        return XA_OK;    }    /**     * {@inheritDoc}     */    public void commit(Xid xid, boolean onePhase) throws XAException {        TransactionContext tx = (TransactionContext) txGlobal.get(xid);        if (tx == null) {            throw new XAException(XAException.XAER_NOTA);        }        if (onePhase) {            tx.prepare();        }        tx.commit();        txGlobal.remove(xid);    }    /**     * {@inheritDoc}     */    public void rollback(Xid xid) throws XAException {        TransactionContext tx = (TransactionContext) txGlobal.get(xid);        if (tx == null) {            throw new XAException(XAException.XAER_NOTA);        }        tx.rollback();        txGlobal.remove(xid);    }    /**     * {@inheritDoc}     * <p/>     * No recovery support yet.     */    public Xid[] recover(int flags) throws XAException {        return new Xid[0];    }    /**     * {@inheritDoc}     * <p/>     * No recovery support yet.     */    public void forget(Xid xid) throws XAException {    }    /**     * Associate this session with a global transaction. Internally, set     * the transaction containing all transaction-local objects to be     * used when performing item retrieval and store.     */    public synchronized void associate(TransactionContext tx) {        this.tx = tx;        for (int i = 0; i < txResources.length; i++) {            InternalXAResource txResource = txResources[i];            txResource.associate(tx);        }    }    /**     * Return a flag indicating whether this resource is associated     * with a transaction.     *     * @return <code>true</code> if this resource is associated     *         with a transaction; otherwise <code>false</code>     */    private boolean isAssociated() {        return tx != null;    }    /**     * {@inheritDoc}     */    public synchronized void logout() {        super.logout();        // dispose the caches        try {            ((XAVersionManager)versionMgr).close();        } catch(Exception e) {            log.warn("error while closing XAVersionManager", e);        }    }    /**     * Compare two strings for equality. If both are <code>null</code>, this     * is also considered to be equal.     */    private static boolean stringsEqual(String s1, String s2) {        if (s1 == null) {            return s2 == null;        } else {            return s1.equals(s2);        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?