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