001    package org.apache.ojb.odmg;
002    
003    /* Copyright 2002-2005 The Apache Software Foundation
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    
018    import org.apache.ojb.broker.OJBRuntimeException;
019    import org.apache.ojb.broker.PBFactoryException;
020    import org.apache.ojb.broker.PBKey;
021    import org.apache.ojb.broker.PersistenceBroker;
022    import org.apache.ojb.broker.PersistenceBrokerFactory;
023    import org.apache.ojb.broker.util.logging.Logger;
024    import org.apache.ojb.broker.util.logging.LoggerFactory;
025    import org.odmg.Transaction;
026    
027    public final class PBCapsule
028    {
029        private static Logger log = LoggerFactory.getLogger(PBCapsule.class);
030    
031        PersistenceBroker broker;
032        PBKey pbKey;
033        Transaction tx;
034        boolean needsTxCommit = false;
035        boolean needsPBCommit = false;
036        boolean isIlleagal = false;
037    
038        public PBCapsule(final PBKey pbKey, final Transaction tx)
039        {
040            this.tx = tx;
041            this.pbKey = pbKey;
042            prepare();
043        }
044    
045        public PersistenceBroker getBroker()
046        {
047            if(isIlleagal) throw new OJBRuntimeException("You could not reuse PBCapsule after destroy");
048            return broker;
049        }
050    
051        private void prepare()
052        {
053            if(isIlleagal) throw new OJBRuntimeException("You could not reuse PBCapsule after destroy");
054            // we allow queries even if no ODMG transaction is running.
055            // thus we use direct access to PBF via the given PBKey to
056            // get a PB instance
057            if (tx == null)
058            {
059                if (log.isDebugEnabled())
060                    log.debug("No running transaction found, try to get " +
061                            "PersistenceBroker instance via PBKey " + pbKey);
062                broker = obtainBroker();
063                // begin tx on the PB instance
064                if (!broker.isInTransaction())
065                {
066                    broker.beginTransaction();
067                    needsPBCommit = true;
068                }
069            }
070            else
071            {
072                // we allow to work with unopened transactions.
073                // we assume that such a tx is to be closed after performing the query
074                if (!tx.isOpen())
075                {
076                    tx.begin();
077                    needsTxCommit = true;
078                }
079                // obtain a broker instance from the current transaction
080                broker = ((HasBroker) tx).getBroker();
081            }
082        }
083    
084        public void destroy()
085        {
086            if (needsTxCommit)
087            {
088                if (log.isDebugEnabled()) log.debug("Indicated to commit tx");
089                tx.commit();
090            }
091            else if (needsPBCommit)
092            {
093                if (log.isDebugEnabled()) log.debug("Indicated to commit PersistenceBroker");
094                try
095                {
096                    broker.commitTransaction();
097                }
098                finally
099                {
100                    if (broker != null) broker.close();
101                }
102            }
103            isIlleagal = true;
104            needsTxCommit = false;
105            needsPBCommit = false;
106        }
107    
108        /**
109         * Used to get PB, when no tx is running.
110         */
111        private PersistenceBroker obtainBroker()
112        {
113            PersistenceBroker _broker;
114            try
115            {
116                if (pbKey == null)
117                {
118                    //throw new OJBRuntimeException("Not possible to do action, cause no tx runnning and no PBKey is set");
119                    log.warn("No tx runnning and PBKey is null, try to use the default PB");
120                    _broker = PersistenceBrokerFactory.defaultPersistenceBroker();
121                }
122                else
123                {
124                    _broker = PersistenceBrokerFactory.createPersistenceBroker(pbKey);
125                }
126            }
127            catch (PBFactoryException e)
128            {
129                log.error("Could not obtain PB for PBKey " + pbKey, e);
130                throw new OJBRuntimeException("Unexpected micro-kernel exception", e);
131            }
132            return _broker;
133        }
134    }