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.wrappers; 019 020 021 import java.util.Arrays; 022 import java.util.Date; 023 import org.aopalliance.intercept.ConstructorInvocation; 024 import org.aopalliance.intercept.MethodInvocation; 025 import org.objectweb.jac.aspects.gui.GuiAC; 026 import org.objectweb.jac.core.AspectComponent; 027 import org.objectweb.jac.core.Collaboration; 028 import org.objectweb.jac.core.Interaction; 029 import org.objectweb.jac.core.Jac; 030 import org.objectweb.jac.core.NameRepository; 031 import org.objectweb.jac.core.Wrapper; 032 import org.objectweb.jac.core.Wrapping; 033 import org.objectweb.jac.core.WrappingChain; 034 import org.objectweb.jac.core.rtti.MethodItem; 035 import org.objectweb.jac.util.Log; 036 037 /** 038 * This wrapper prints some informations about the wrapped method when 039 * it is called. */ 040 041 public class VerboseWrapper extends Wrapper { 042 043 public static final int TIMED = 0; 044 public static final int NAMED = 1; 045 public static final int STACK = 2; 046 public static final int WRAPPERS= 3; 047 048 protected int type = TIMED; 049 050 static final String DISABLE_TRACE = "DISABLE_TRACE"; 051 052 public VerboseWrapper(AspectComponent ac, int type) { 053 super(ac); 054 this.type = type; 055 } 056 057 /** 058 * A wrapping method that prints out the calling informations. 059 * 060 * @return the value of the called method */ 061 062 public Object printCallingInfos(Interaction interaction) { 063 064 /** Before code ... */ 065 Date d1 = new Date(); 066 String on = 067 interaction.method.isStatic() 068 ? "" 069 : (" on '" 070 + NameRepository.get().getName(interaction.wrappee) 071 + "'"); 072 073 System.out.println( 074 "<<< " 075 + (d1.getTime() - Jac.getStartTime().getTime()) 076 + " ms: calling '" + interaction.method + "'" 077 + on 078 + ", args = " 079 + Arrays.asList(interaction.args) 080 + " >>>"); 081 /** End before code */ 082 083 Object ret = interaction.proceed(); 084 085 /** After code ... */ 086 Date d2 = new Date(); 087 System.out.println( 088 "<<< " 089 + (d2.getTime() - Jac.getStartTime().getTime()) 090 + " ms: returning '" 091 + interaction.method 092 + "'" 093 + on 094 + ", value = " 095 + ret 096 + ", duration = " 097 + (d2.getTime() - d1.getTime()) 098 + " ms >>>"); 099 /** End after code */ 100 101 return ret; 102 } 103 104 public Object printNamedArgs(Interaction interaction) { 105 Collaboration collab = Collaboration.get(); 106 if (collab.getAttribute(DISABLE_TRACE)!=null) 107 return proceed(interaction); 108 // printing of parameters can call the wrapped method 109 collab.addAttribute(DISABLE_TRACE, Boolean.TRUE); 110 try { 111 String[] paramNames = GuiAC.getParameterNames(interaction.method); 112 String params = 113 interaction.method.isStatic() 114 ? "" 115 : "this=" + GuiAC.toString(interaction.wrappee); 116 Object[] args = interaction.args; 117 for (int i = 0; i < args.length; i++) { 118 if (paramNames != null) { 119 params += "," + paramNames[i] + "=" + GuiAC.toString(interaction.args[i]); 120 } else { 121 params += ",arg[" + i + "]=" + GuiAC.toString(interaction.args[i]); 122 } 123 } 124 System.out.println("Calling " + interaction.method + " with " + params); 125 } finally { 126 collab.removeAttribute(DISABLE_TRACE); 127 } 128 129 Object result = proceed(interaction); 130 131 collab.addAttribute(DISABLE_TRACE, Boolean.TRUE); 132 try { 133 if (interaction.method instanceof MethodItem) { 134 Class returnType = ((MethodItem) interaction.method).getType(); 135 if (returnType != void.class) { 136 if (returnType.isArray() 137 && Object.class.isAssignableFrom( 138 returnType.getComponentType())) 139 System.out.println( 140 "Called " 141 + interaction.method 142 + " -> " 143 + Arrays.asList((Object[]) result)); 144 else 145 System.out.println( 146 "Called " + interaction.method + " -> " + GuiAC.toString(result)); 147 } 148 } 149 } finally { 150 collab.removeAttribute(DISABLE_TRACE); 151 } 152 return result; 153 } 154 155 public Object printStackTrace(Interaction interaction) { 156 System.out.println( 157 "Calling '" 158 + interaction.method 159 + "' on '" 160 + NameRepository.get().getName(interaction.wrappee) 161 + "', args = " 162 + Arrays.asList(interaction.args)); 163 new Exception().printStackTrace(); 164 return proceed(interaction); 165 } 166 167 public Object printWrappersTrace(Interaction interaction) { 168 String on = 169 interaction.method.isStatic() 170 ? "" 171 : (" on '" 172 + NameRepository.get().getName(interaction.wrappee) 173 + "'"); 174 175 System.out.println( 176 "Calling '" 177 + interaction.method 178 + "'" 179 + on 180 + ", args = " 181 + Arrays.asList(interaction.args)); 182 WrappingChain chain = 183 Wrapping.getWrappingChain(interaction.wrappee, interaction.method); 184 System.out.println("WrappingChain = " + chain); 185 return proceed(interaction); 186 } 187 188 // TODO: support all the possible traces 189 190 public Object invoke(MethodInvocation invocation) throws Throwable { 191 switch (type) { 192 case TIMED: 193 return printCallingInfos((Interaction) invocation); 194 case NAMED: 195 return printNamedArgs((Interaction) invocation); 196 case STACK: 197 return printStackTrace((Interaction) invocation); 198 case WRAPPERS: 199 return printWrappersTrace((Interaction) invocation); 200 default: 201 Log.error("VerboseWrapper: unknown type "+type); 202 } 203 return invocation.proceed(); 204 } 205 206 public Object construct(ConstructorInvocation invocation) 207 throws Throwable { 208 return printCallingInfos((Interaction) invocation); 209 } 210 }