Home » openejb-3.1.2-src » org.apache.openejb.ri » sp » [javadoc | source]

    1   /**
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.openejb.ri.sp;
   18   
   19   import java.util.ArrayList;
   20   import java.util.Collections;
   21   import java.util.HashMap;
   22   import java.util.List;
   23   import java.util.Map;
   24   import java.util.Properties;
   25   import javax.transaction.InvalidTransactionException;
   26   import javax.transaction.NotSupportedException;
   27   import javax.transaction.RollbackException;
   28   import javax.transaction.Status;
   29   import javax.transaction.Synchronization;
   30   import javax.transaction.Transaction;
   31   import javax.transaction.TransactionManager;
   32   import javax.transaction.TransactionSynchronizationRegistry;
   33   import javax.transaction.xa.XAException;
   34   import javax.transaction.xa.XAResource;
   35   
   36   import org.apache.openejb.spi.TransactionService;
   37   import org.apache.openejb.util.LogCategory;
   38   import org.apache.openejb.util.Logger;
   39   
   40   /**
   41    * @org.apache.xbean.XBean element="pseudoTransactionService"
   42    */
   43   public class PseudoTransactionService implements TransactionService, TransactionManager, TransactionSynchronizationRegistry {
   44       private static final Logger logger = Logger.getInstance(LogCategory.OPENEJB, "org.apache.openejb.core.cmp");
   45       private final ThreadLocal<MyTransaction> threadTransaction = new ThreadLocal<MyTransaction>();
   46   
   47       public void init(Properties props) {
   48       }
   49   
   50       public TransactionManager getTransactionManager() {
   51           return this;
   52       }
   53   
   54       public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
   55           return this;
   56       }
   57   
   58       public int getStatus() {
   59           MyTransaction tx = threadTransaction.get();
   60           if (tx == null) {
   61               return Status.STATUS_NO_TRANSACTION;
   62           }
   63           return tx.getStatus();
   64       }
   65   
   66       public Transaction getTransaction() {
   67           return threadTransaction.get();
   68       }
   69   
   70       public boolean getRollbackOnly() {
   71           MyTransaction tx = threadTransaction.get();
   72           if (tx == null) {
   73               throw new IllegalStateException("No transaction active");
   74           }
   75           return tx.getRollbackOnly();
   76       }
   77   
   78       public void setRollbackOnly() {
   79           MyTransaction tx = threadTransaction.get();
   80           if (tx == null) {
   81               throw new IllegalStateException("No transaction active");
   82           }
   83           tx.setRollbackOnly();
   84       }
   85   
   86       public void begin() throws NotSupportedException {
   87           if (threadTransaction.get() != null) {
   88               throw new NotSupportedException("A transaction is already active");
   89           }
   90   
   91           MyTransaction tx = new MyTransaction();
   92           threadTransaction.set(tx);
   93       }
   94   
   95       public void commit() throws RollbackException {
   96           MyTransaction tx = threadTransaction.get();
   97           if (tx == null) {
   98               throw new IllegalStateException("No transaction active");
   99           }
  100   
  101           try {
  102               tx.commit();
  103           } finally {
  104               threadTransaction.set(null);
  105           }
  106       }
  107   
  108   
  109       public void rollback() {
  110           MyTransaction tx = threadTransaction.get();
  111           if (tx == null) {
  112               throw new IllegalStateException("No transaction active");
  113           }
  114   
  115           try {
  116               tx.rollback();
  117           } finally {
  118               threadTransaction.set(null);
  119           }
  120       }
  121   
  122       public Transaction suspend() {
  123           return threadTransaction.get();
  124       }
  125   
  126       public void resume(Transaction tx) throws InvalidTransactionException {
  127           if (tx == null) {
  128               throw new InvalidTransactionException("Transaction is null");
  129           }
  130           if (!(tx instanceof MyTransaction)) {
  131               throw new InvalidTransactionException("Unknown transaction type " + tx.getClass().getName());
  132           }
  133           MyTransaction myTransaction = (MyTransaction) tx;
  134   
  135           if (threadTransaction.get() != null) {
  136               throw new IllegalStateException("A transaction is already active");
  137           }
  138   
  139           int status = myTransaction.getStatus();
  140           if (status != Status.STATUS_ACTIVE && status != Status.STATUS_MARKED_ROLLBACK) {
  141               throw new InvalidTransactionException("Expected transaction to be STATUS_ACTIVE or STATUS_MARKED_ROLLBACK, but was " + status);
  142           }
  143   
  144           threadTransaction.set(myTransaction);
  145       }
  146   
  147       public Object getTransactionKey() {
  148           return getTransaction();
  149       }
  150   
  151       public int getTransactionStatus() {
  152           return getStatus();
  153       }
  154   
  155       public Object getResource(Object key) {
  156           MyTransaction tx = threadTransaction.get();
  157           if (tx == null) {
  158               throw new IllegalStateException("No transaction active");
  159           }
  160   
  161           Object value = tx.getResource(key);
  162           return value;
  163       }
  164   
  165       public void putResource(Object key, Object value) {
  166           MyTransaction tx = threadTransaction.get();
  167           if (tx == null) {
  168               throw new IllegalStateException("No transaction active");
  169           }
  170   
  171           tx.putResource(key, value);
  172       }
  173   
  174       public void registerInterposedSynchronization(Synchronization synchronization) {
  175           MyTransaction tx = threadTransaction.get();
  176           if (tx == null) {
  177               throw new IllegalStateException("No transaction active");
  178           }
  179   
  180           tx.registerInterposedSynchronization(synchronization);
  181       }
  182   
  183       public void setTransactionTimeout(int seconds) {
  184       }
  185   
  186       public class MyTransaction implements Transaction {
  187           private final List<Synchronization> registeredSynchronizations = Collections.synchronizedList(new ArrayList<Synchronization>());
  188           private final List<XAResource> xaResources =  Collections.synchronizedList(new ArrayList<XAResource>());
  189           private final Map<Object, Object> resources = new HashMap<Object,Object>();
  190           private int status = Status.STATUS_ACTIVE;
  191   
  192           public boolean delistResource(XAResource xaRes, int flag) {
  193               xaResources.remove(xaRes);
  194               return true;
  195           }
  196   
  197           public boolean enlistResource(XAResource xaRes) {
  198               xaResources.add(xaRes);
  199               return true;
  200           }
  201   
  202           public int getStatus() {
  203               return status;
  204           }
  205   
  206           public void registerSynchronization(Synchronization synchronization) {
  207               registeredSynchronizations.add(synchronization);
  208           }
  209   
  210           public void registerInterposedSynchronization(Synchronization synchronization) {
  211               registeredSynchronizations.add(synchronization);
  212           }
  213   
  214           public boolean getRollbackOnly() {
  215               return status == Status.STATUS_MARKED_ROLLBACK;
  216           }
  217   
  218           public void setRollbackOnly() {
  219               status = Status.STATUS_MARKED_ROLLBACK;
  220           }
  221   
  222           public Object getResource(Object key) {
  223               if (key == null) throw new NullPointerException("key is null");
  224               return resources.get(key);
  225           }
  226   
  227           public void putResource(Object key, Object value) {
  228               if (key == null) throw new NullPointerException("key is null");
  229               if (value != null) {
  230                   resources.put(key, value);
  231               } else {
  232                   resources.remove(key);
  233               }
  234           }
  235   
  236           public void commit() throws RollbackException {
  237               try {
  238                   if (status == Status.STATUS_MARKED_ROLLBACK) {
  239                       rollback();
  240                       throw new RollbackException();
  241                   }
  242                   try {
  243                       doBeforeCompletion();
  244                   } catch (Exception e) {
  245                       rollback();
  246                       throw (RollbackException) new RollbackException().initCause(e);
  247                   }
  248                   doXAResources(Status.STATUS_COMMITTED);
  249                   status = Status.STATUS_COMMITTED;
  250                   doAfterCompletion(Status.STATUS_COMMITTED);
  251               } finally {
  252                   threadTransaction.set(null);
  253               }
  254           }
  255   
  256           public void rollback() {
  257               try {
  258                   doXAResources(Status.STATUS_ROLLEDBACK);
  259                   doAfterCompletion(Status.STATUS_ROLLEDBACK);
  260                   status = Status.STATUS_ROLLEDBACK;
  261                   registeredSynchronizations.clear();
  262               } finally {
  263                   threadTransaction.set(null);
  264               }
  265           }
  266   
  267           private void doBeforeCompletion() {
  268               for (Synchronization sync : new ArrayList<Synchronization>(registeredSynchronizations)) {
  269                   sync.beforeCompletion();
  270               }
  271           }
  272   
  273           private void doAfterCompletion(int status) {
  274               for (Synchronization sync : new ArrayList<Synchronization>(registeredSynchronizations)) {
  275                   try {
  276                       sync.afterCompletion(status);
  277                   } catch (RuntimeException e) {
  278                       logger.warning("Synchronization afterCompletion threw a RuntimeException", e);
  279                   }
  280               }
  281           }
  282   
  283           private void doXAResources(int status) {
  284               for (XAResource xaRes : new ArrayList<XAResource>(xaResources)) {
  285                   if (status == Status.STATUS_COMMITTED) {
  286                       try {
  287                           xaRes.commit(null, true);
  288                       } catch (XAException e) {
  289   
  290                       }
  291                       try {
  292                           xaRes.end(null, XAResource.TMSUCCESS);
  293                       } catch (XAException e) {
  294   
  295                       }
  296                   } else {
  297                       try {
  298                           xaRes.rollback(null);
  299                       } catch (XAException e) {
  300   
  301                       }
  302                       try {
  303                           xaRes.end(null, XAResource.TMFAIL);
  304                       } catch (XAException e) {
  305                       }
  306                   }
  307               }
  308               xaResources.clear();
  309           }
  310       }
  311   }
  312   

Home » openejb-3.1.2-src » org.apache.openejb.ri » sp » [javadoc | source]