001 /* 002 Copyright (C) 2001 Renaud Pawlak 003 004 This program is free software; you can redistribute it and/or modify 005 it under the terms of the GNU Lesser General Public License as 006 published by the Free Software Foundation; either version 2 of the 007 License, or (at your option) any later version. 008 009 This program is distributed in the hope that it will be useful, 010 but WITHOUT ANY WARRANTY; without even the implied warranty of 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 012 GNU Lesser General Public License for more details. 013 014 You should have received a copy of the GNU Lesser General Public License 015 along with this program; if not, write to the Free Software 016 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ 017 018 package org.objectweb.jac.aspects.transaction; 019 020 021 import java.util.Iterator; 022 import java.util.Vector; 023 import org.aopalliance.intercept.ConstructorInvocation; 024 import org.aopalliance.intercept.MethodInvocation; 025 import org.apache.log4j.Logger; 026 import org.objectweb.jac.core.AspectComponent; 027 import org.objectweb.jac.core.Interaction; 028 import org.objectweb.jac.core.Wrappee; 029 import org.objectweb.jac.core.Wrapper; 030 import org.objectweb.jac.core.Wrapping; 031 import org.objectweb.jac.util.Log; 032 033 /** 034 * This aspect component handle the transaction aspect within JAC 035 * applications. 036 * 037 * @author Renaud Pawlak */ 038 039 public class TransactionAC extends AspectComponent implements TransactionConf { 040 static Logger logger = Logger.getLogger("transaction"); 041 042 /** 043 * The default constructor. Wraps every application objects with a 044 * <code>DispatchTransactionWrapper</code> instance. 045 * 046 * @see DispatchTransactionWrapper 047 * @see DispatchTransactionWrapper#dispatch 048 */ 049 050 public TransactionAC() { 051 pointcut("ALL", "ALL", "ALL", 052 DispatchTransactionWrapper.class.getName(), 053 null, true); 054 } 055 056 public void defineTransactionalMethods(String classExpr, 057 String methodExpr, 058 String objectExpr) { 059 pointcut(objectExpr, classExpr, methodExpr, 060 new TransactionWrapper(this), "handleTransaction", null); 061 } 062 063 /** 064 * This wrapper defines the transaction wrapper. 065 * 066 * <p>It defines a wrapping method that starts a transaction when a 067 * method is called and that commits it when the method returns 068 * normally. 069 * 070 * <code>Within the transaction, the cloning and the dispatching is 071 * ensured by an external 072 * <code>DispatchTransactionWrapper</code>. 073 * 074 * @see DispatchTransactionWrapper */ 075 076 public class TransactionWrapper extends Wrapper { 077 /** The current transaction count (increments on each 078 transaction). */ 079 int transactionCount=0; 080 081 public TransactionWrapper(AspectComponent ac) { 082 super(ac); 083 } 084 085 /** 086 * This wrapping method wraps a transactional method. 087 */ 088 public Object handleTransaction(Interaction interaction) { 089 beginOfTransaction(interaction); 090 Object ret = proceed(interaction); 091 endOfTransaction(interaction); 092 return ret; 093 } 094 /** 095 * Initializes the transaction. */ 096 public void beginOfTransaction(Interaction interaction) { 097 logger.debug("begin of transactional method: "+interaction.method); 098 Integer id = new Integer(++transactionCount); 099 this.attrdef("Transaction.id",id); 100 this.attrdef("Transaction"+id+".affectedObjects",new Vector()); 101 } 102 /** 103 * Ends the transaction (when success). */ 104 public void endOfTransaction(Interaction interaction) { 105 logger.debug("end of transactional method: "+interaction.method); 106 Integer id = (Integer)this.attr("Transaction.id"); 107 Vector v = (Vector)this.attr("Transaction"+id+".affectedObjects"); 108 this.attrdef("Transaction.commit",id); 109 Iterator it = v.iterator(); 110 while( it.hasNext() ) { 111 Wrappee w = (Wrappee)it.next(); 112 Wrapping.invokeRoleMethod(w,"commit",new Object[] {this.attr("Transaction.id")}); 113 } 114 this.attrdef("Transaction"+id+".affectedObjects",null); 115 } 116 /** 117 * Handles an exception within a transaction (rollback). 118 */ 119 public void catchException(Interaction interaction, Exception e) throws Exception { 120 logger.debug("exception in transactionnal method: "+interaction.method); 121 Integer id = (Integer)this.attr("Transaction.id"); 122 Vector v = (Vector)this.attr("Transaction"+id+".affectedObjects"); 123 this.attrdef("Transaction.rollback",id); 124 if( id != null && v != null ) { 125 Iterator it = v.iterator(); 126 while( it.hasNext() ) { 127 Wrappee w = (Wrappee)it.next(); 128 Wrapping.invokeRoleMethod(w,"rollback",new Object[] {this.attr("Transaction.id")}); 129 } 130 this.attrdef("Transaction"+id+".affectedObjects",null); 131 } 132 throw e; 133 } 134 135 /* (non-Javadoc) 136 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation) 137 */ 138 public Object invoke(MethodInvocation invocation) throws Throwable { 139 // TODO Auto-generated method stub 140 return null; 141 } 142 143 /* (non-Javadoc) 144 * @see org.aopalliance.intercept.ConstructorInterceptor#construct(org.aopalliance.intercept.ConstructorInvocation) 145 */ 146 public Object construct(ConstructorInvocation invocation) throws Throwable { 147 // TODO Auto-generated method stub 148 return null; 149 } 150 } 151 } 152 153