001    /*
002      Copyright (C) 2001 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 org.objectweb.jac.core.*;
021    import java.util.*;
022    import java.io.*;
023    
024    /**
025     * This class is a simple debugger that can by used by a program to
026     * step the called methods and print some informations.
027     *
028     * <p>It is used by the debugging wrapper.
029     *
030     * @see DebuggingWrapper
031     * @see DebuggingWrapper#step(Interaction) */
032    
033    public class Debugger {
034    
035       /** Constant for stepping. */
036       public static final int STEP = 0;
037       /** Constant for stepping into */
038       public static final int STEP_INTO = 1;
039    
040       /** Store the current debugging mode. */
041       public int mode = STEP;
042       /** Store if the debugger must step or not. */
043       public boolean stepping = true;
044       /** A stack that allows step into to stop. */
045       public transient Stack stepIntoStack;
046       
047       /** The debugger constructor. */
048       
049       public Debugger() {
050          stepIntoStack = new Stack();
051       }
052    
053       /**
054        * Set the debugging mode of the debugger. Can be "step",
055        * "step_into", or "run".
056        *
057        * @param mode the new mode
058        *
059        * @see #getDebuggingMode() */
060    
061       public void setDebuggingMode( int mode ) {
062          this.mode = mode;
063       }
064    
065       /**
066        * The getter for the debugging mode.
067        *
068        * @return the current debugging mode
069        *
070        * @see #setDebuggingMode(int)
071        */
072    
073       public int getDebuggingMode() {
074          return mode;
075       }
076    
077       /**
078        * Disable stepping.
079        * 
080        * <p>If this method is called, the debugger enters a run mode but
081        * is still active (a stepping mode can be recovered).
082        * 
083        * @see #isStepping()
084        * @see #enableStepping() */
085       
086       public void disableStepping() {
087          stepping = false;
088       }
089    
090       /**
091        * Enable stepping
092        * 
093        * <p>If this method is called and that the stepping was disabled,
094        * the debugger enters a stepping mode.
095        * 
096        * @see #isStepping()
097        * @see #disableStepping() */
098    
099       
100       public void enableStepping() {
101          stepping = true;
102       }   
103    
104       /**
105        * Tell if in stepping mode.
106        *
107        * @return true if stepping
108        *
109        * @see #enableStepping()
110        * @see #disableStepping() */
111       
112       public boolean isStepping() {
113          return stepping;
114       }
115    
116       /**
117        * Must be called when a new method is called.
118        *
119        * <p>If the debugger is in step mode, then, the program stops and
120        * the user is asked to press a key to continue.
121        *
122        * @param container the name of the container that runs the method
123        * @param objectName the name of the called object
124        * @param method the name of the called method
125        * @param args the arguments of the called method */
126    
127       public void startOfMethod( String container,
128                                  String objectName, 
129                                  String method, 
130                                  Object[] args ) {
131    
132          if( isStepping() && getDebuggingMode() == STEP_INTO ) {
133             if( stepIntoStack.isEmpty() ) {
134                setDebuggingMode( STEP );
135             } else {
136                stepIntoStack.push( "" );
137             }
138          }
139    
140          if( isStepping() && getDebuggingMode() == STEP && 
141              Collaboration.get().getAttribute( "step_into" ) == null ) {
142    
143             System.out.println( "Debugging is calling " + method + " (on container " + container + "):" );
144             System.out.println( "wrappee  = " + objectName );
145             System.out.println( "args     = " + Arrays.asList( args ) );
146    
147             BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
148             boolean ok = false;
149             String answer = "";
150             
151             while (!ok) {
152                
153                System.out.println(" - [s]tep");
154                System.out.println(" - step [i]nto");
155                System.out.println(" - [r]un");
156                System.out.println(" - [q]uit");
157                System.out.print("> ");
158                
159                try {
160                   answer = in.readLine();
161    
162                   if (answer.equals("q")) {
163                      System.out.println("Ciao!");
164                      System.exit(0);
165                   } else if (answer.equals("i")) {
166                      stepIntoStack.push( "" );
167                      setDebuggingMode( STEP_INTO );
168                      ok = true;
169                   } else if (answer.equals("s")) {
170                      setDebuggingMode( STEP );
171                      ok = true;
172                   } else if (answer.equals("r")) {
173                      disableStepping();
174                      ok = true;
175                   }
176                   
177                } catch (Exception e) {
178                   e.printStackTrace();
179                }
180                
181             }
182          }
183       }
184    
185       /**
186        * This must be called at the end of a stepped method to print the
187        * execution informations of the method.
188        *
189        * @param container the name of the container that runs the method
190        * @param objectName the name of the called object
191        * @param method the name of the called method
192        * @param args the arguments of the called method
193        * @param ret the value returned by the called method
194        * @param executionTime the method call duration */
195    
196       public void endOfMethod( String container,
197                                String objectName, 
198                                String method, 
199                                Object[] args,
200                                Object ret,
201                                long executionTime ) {
202    
203          if( isStepping() && getDebuggingMode() == STEP_INTO ) {
204             if( stepIntoStack.isEmpty() ) {
205                setDebuggingMode( STEP );
206             } else {
207                stepIntoStack.pop();
208             }
209          }
210    
211          if( isStepping() && getDebuggingMode() == STEP && 
212              Collaboration.get().getAttribute( "step_into" ) == null ) {
213    
214             System.out.println( "Debugging is returning from " + method + " (on container " + container + "):" );
215             System.out.println( "wrappee  = " + objectName );
216             System.out.println( "args     =" + Arrays.asList( args ) );
217             System.out.println( "return   =" + ret );
218             System.out.println( "duration = " + executionTime + " ms"
219             );
220          }
221       }
222    }
223    
224    
225       
226    
227    
228    
229    
230