001 /* 002 Copyright (C) 2001-2002 Renaud Pawlak <renaud@aopsys.com> 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.tracing; 019 020 import java.util.*; 021 import org.aopalliance.intercept.ConstructorInvocation; 022 import org.aopalliance.intercept.MethodInvocation; 023 import org.objectweb.jac.core.*; 024 import org.objectweb.jac.core.rtti.ClassItem; 025 import org.objectweb.jac.core.rtti.ClassRepository; 026 027 /** 028 * This counter must wrap the methods of which calls have to be 029 * counted. It extends the simple counting wrapper to provide 2 030 * optimization methods when client methods call several times the 031 * method wrapped by <code>incr</code>. In these cases, the counter is 032 * direcly incremented by the number of times the <code>incr</code> 033 * method has to be called. 034 * 035 * <p>In order to avoid redundancy, <code>incr</code> must not be 036 * called if <code>incrWithArg</code> or <code>incrWithField</code> 037 * have already been called. To perform this contextual test, use the 038 * before and after running wrapper methods of the aspect 039 * component. */ 040 041 public class OptimizedCountingWrapper extends SimpleCountingWrapper { 042 043 /** The field on which the optimization can be done. */ 044 String field = null; 045 046 /** The argument on which the optimization can be done. */ 047 int arg = 0; 048 049 /** 050 * Create the counter and parametrize it regarding the base program 051 * shape. 052 * 053 * @param c the used counter 054 * @param field the field that is used to optimize the counting */ 055 056 public OptimizedCountingWrapper(AspectComponent ac, Counter c, String field) { 057 super(ac,c); 058 this.field = field; 059 } 060 061 /** 062 * Create the counter and parametrize it regarding the base program 063 * shape. 064 * 065 * @param c the used counter 066 * @param arg the argument number that used to optimize the 067 * counting */ 068 069 public OptimizedCountingWrapper(AspectComponent ac, Counter c, int arg) { 070 super(ac,c); 071 this.arg = arg; 072 } 073 074 /** 075 * This wrapping method increments the counter with the field when 076 * the wrapped method is called. It is an optimization for the incr 077 * method. 078 * 079 * @return the return value of the wrapped method 080 * @see SimpleCountingWrapper#incr(Interaction) */ 081 082 public Object incrWithField(Interaction interaction) { 083 attrdef( "tracing.globalIncr", "" ); 084 Object ret = proceed(interaction); 085 ClassItem cl=ClassRepository.get().getClass(interaction.wrappee); 086 Object fval = cl.getField(field).get(interaction.wrappee); 087 if (fval == null) { 088 System.out.println( "<<< Counting aspect says: the field to count (" + 089 field + ") is null or does not exist... >>>" ); 090 return ret; 091 } 092 if (fval.getClass().isArray()) { 093 counter.incr(((Object[])fval).length); 094 } else if ( fval instanceof Collection ) { 095 counter.incr(((Collection)fval).size()); 096 } else { 097 /** this type is not supported... */ 098 System.out.println( "<<< Counting aspect says: the field to count (" + 099 field + ") is not of a supported type... >>>" ); 100 return ret; 101 } 102 printCounter(); 103 return ret; 104 } 105 106 /** 107 * This wrapping method increments the counter with the argument 108 * value when the wrapped method is called. It is an optimization 109 * for the <code>incr</code> method. 110 * 111 * @return the return value of the wrapped method 112 * @see SimpleCountingWrapper#incr(Interaction) */ 113 114 public Object incrWithArg(Interaction interaction) { 115 attrdef( "tracing.globalIncr", "" ); 116 Object ret = proceed(interaction); 117 counter.incr( ((Integer)interaction.args[arg]).intValue() ); 118 printCounter(); 119 return ret; 120 } 121 122 public Object invoke(MethodInvocation invocation) throws Throwable { 123 if (field==null) 124 return incrWithArg((Interaction)invocation); 125 else 126 return incrWithField((Interaction)invocation); 127 } 128 129 public Object construct(ConstructorInvocation invocation) throws Throwable { 130 if (field==null) 131 return incrWithArg((Interaction)invocation); 132 else 133 return incrWithField((Interaction)invocation); 134 } 135 136 }