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    }