Initial Commit
[packages] / xemacs-packages / jde / java / src / jde / debugger / Etc.java
1 package jde.debugger;
2
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Iterator;
6 import java.util.List;
7 import java.util.StringTokenizer;
8
9 import com.sun.jdi.*;
10 import com.sun.jdi.request.*;
11 import jde.debugger.expr.*;
12
13
14 /**
15  * Etc.java
16  * <p>
17  * random useful utilities
18  * <p>
19  * Created: Thu Jul  8 13:01:24 1999
20  * 
21  * @author Amit Kumar
22  * @since 0.1
23  * @version $Revision: 1.3 $
24  */
25
26 public class Etc  {
27
28   /**
29    * dump a particular object, in whatever way seems appropriate
30    * @param obj The object to dump
31    */
32   public static void dump(Object obj) {
33     if (obj instanceof Collection) {
34       Iterator it = ((Collection)obj).iterator();
35       while (it.hasNext()) {
36         System.out.println(it.next());
37       }
38     } else if (obj instanceof Object[]) {
39       Object[] k = (Object[])obj;
40       for (int i=0; i<k.length; i++)
41         dump(k[i]);
42     } else {
43       System.out.println(obj);
44     }
45   }
46
47
48   /**
49    * Safely convert to a Long, raising an appropriate
50    * JDENumberFormatException if required
51    *
52    * @param obj The object to convert. The .toString() is used.
53    * @param type The type of long: used in the exception string if required
54    * @return the Long, or raises exception.
55    */
56   public static Long safeGetLong(Object obj, String type)
57     throws JDEException {
58     try {
59       return new Long(obj.toString());
60     } catch (NumberFormatException ex) {
61       throw new JDENumberFormatException(type);
62     }
63   }
64
65
66   /**
67    * Safely convert to an int, raising an appropriate
68    * JDENumberFormatException if required
69    *
70    * @param obj The object to convert. The .toString() is used.
71    * @param type The type of int: used in the exception string if required
72    * @return the Integer, or raises exception.
73    */
74   public static int safeGetint(Object obj, String type)
75     throws JDEException {
76     try {
77       return Integer.parseInt(obj.toString());
78     } catch (NumberFormatException ex) {
79       throw new JDENumberFormatException(type);
80     }
81   }
82
83
84   /**
85    * Evaluate an expression, given a context
86    * <p>
87    * @param expr The expression to evaluate
88    * @param frame The stackframe that defines the context
89    * @return a {@link Rep#getValueRep(Value) value}
90    */
91   public static Value evaluate(String expr, final StackFrame frame)
92     throws JDEException {
93     //  System.out.println(expr);
94     try {
95       ExpressionParser.GetFrame frameGetter = null;
96       frameGetter = new ExpressionParser.GetFrame() {
97           public StackFrame get()
98             throws IncompatibleThreadStateException {
99             return frame;
100           }
101         };
102       return ExpressionParser.evaluate(expr, frame.virtualMachine(),
103                                        frameGetter);
104     } catch (NativeMethodException ex) {
105       throw new JDEException("Can't access local variables in native methods");
106     } catch (ParseException ex) {
107       throw new JDEException(ex.toString());
108     } catch (InvocationException ex) {
109       throw new JDEException("Exception in expression: "+ex.exception().referenceType().name());
110     } catch (InvalidTypeException ite) {
111       throw new JDEException("Expression contains invalid type");
112     } catch (IncompatibleThreadStateException itse) {
113       throw new JDEException("This expression cannot be evaluated at an arbitrary location");
114     } catch (ClassNotLoadedException tnle) {
115       throw new JDEException("A required class for the evaluation hasn't been loaded");
116     }
117   }
118
119     
120   /**
121    * Parses the list of arguments for thread information.
122    * <pre>
123    * on_thread_id   threadID
124    * on_thread_name "threadName"
125    * </pre>
126    * Note that the exception is <b>not</b> raised if the tags are
127    * not present: only if what follows the tag is incorrect.
128    * <p>
129    * Commands having this argument will raise events only if the event
130    * thread matches the specification. More details in EventHandler.
131    * <p>
132    * Shortcuts: <u>-tid</u> and <u>-tname</u>
133    * <p>
134    * @return a Long corresponding to the threadID, or the string
135    * "threadName"
136    * @exception JDEException If the information cannot be resolved
137    */
138   public static Object getThreadFromArgs(List args)
139     throws JDEException {
140
141     String threadArg = null;
142     int threadIndex = -1;
143     for (int i = 0; i < args.size(); i++) {
144       String arg = args.get(i).toString().toLowerCase();
145       if (arg.equals("on_thread_id") || arg.equals("on_thread_name")
146           || arg.equals("-tid") || arg.equals("-tname")) {
147         threadIndex = i;
148         threadArg = args.remove(threadIndex).toString();
149         break;
150       }
151     }
152     // at this point, either threadArg = null, or on_thread_id/name. in
153     // that case, threadIndex should now have the index of the argument
154     if (threadArg == null) {
155       return null;
156     } else {
157       if (threadArg.equals("on_thread_id")
158           || threadArg.equals("-tid")) {
159         if (threadIndex == args.size()) {
160           // ie missing argument
161           throw new JDEException("Missing argument to 'on_thread_id'");
162         } else {
163           try {
164             return new Long(args.remove(threadIndex).toString());
165           } catch (NumberFormatException ex) {
166             throw new JDENumberFormatException("'on_thread_id' argument");
167           }
168         }
169       } else if (threadArg.equals("on_thread_name")
170                  || threadArg.equals("-tname")) {
171         if (threadIndex == args.size()) {
172           throw new JDEException("Missing argument to 'on_thread_name'");
173         } else {
174           return args.remove(threadIndex).toString();
175         }
176       } else {
177         throw new JDEException("Should not happen! Contact maintainer");
178       }
179     }
180   }
181
182     
183   /**
184    * Parses the list of arguments for expression information.
185    * <pre>
186    * if "expression"
187    * </pre>
188    * Note that the exception is <b>not</b> raised if the tag isn't
189    * present: only if what follows the tag is incorrect.
190    * <p>
191    * When used, the expression is evaluated at the time of the event,
192    * and the event passed to jde if the expression evaluates to "true".
193    * <p>
194    * Shortcut: <u>-e</u>
195    * <p>
196    * @return string corresponding to the expression
197    * @exception JDEException If the information cannot be resolved
198    */
199   public static String getExprFromArgs(List args)
200     throws JDEException {
201         
202     String exprArg = null;
203     int exprIndex = -1;
204     for (int i = 0; i < args.size(); i++) {
205       String arg = args.get(i).toString().toLowerCase();
206       if (arg.equals("if") || arg.equals("-e")) { 
207         exprIndex = i;
208         exprArg = args.remove(exprIndex).toString();
209         break;
210       }
211     }
212     // at this point, either exprArg = null, or "if". in
213     // that case, exprIndex should now have the index of the argument
214     if (exprArg == null) {
215       return null;
216     } else {
217       if (exprArg.equals("if") || exprArg.equals("-e")) {
218         if (exprIndex == args.size()) {
219           // ie missing argument
220           throw new JDEException("Missing argument to 'if'");
221         } else {
222           return args.remove(exprIndex).toString();
223         }
224       } else {
225         throw new JDEException("Should not happen! Contact maintainer");
226       }
227     }
228   }
229
230
231   /**
232    * Parses the list of arguments for class filter information.
233    * <pre>
234    * class_filters "classPatternList"
235    * </pre>
236    * Note that the exception is <b>not</b> raised if the tag isn't
237    * present: only if what follows the tag is incorrect.
238    * <p>
239    * the classPatternList should be a list of class patterns, using
240    * space or comma as delimiter.
241    * <p>
242    * Shortcut: <u>-cf</u>
243    * <p>
244    * This constraint is used to add class filters to events. To quote
245    * JDI documentation:
246    * <p>
247    * Restricts the events generated by this request to those whose
248    * location is in a class whose name matches a restricted regular
249    * expression. Regular expressions are limited to exact matches
250    * and patterns that begin with '*' or end with '*'; for example,
251    * "*.Foo" or "java.*".
252    * <p>
253    * @return a List of all the class filters. 
254    * @exception JDEException If the information cannot be resolved
255    */
256   public static List getClassFiltersFromArgs(List args)
257     throws JDEException {
258
259     String filterArg = null;
260     int filterIndex = -1;
261     for (int i = 0; i < args.size(); i++) {
262       String arg = args.get(i).toString().toLowerCase();
263       if (arg.equals("class_filters") || arg.equals("-cf")) { 
264         filterIndex = i;
265         filterArg = args.remove(filterIndex).toString();
266         break;
267       }
268     }
269     // at this point, either filterArg = null, or "if". in
270     // that case, filterIndex should now have the index of the argument
271     if (filterArg == null) {
272       return null;
273     } else {
274       if (filterArg.equals("class_filters")
275           || filterArg.equals("-cf")) {
276         if (filterIndex == args.size()) {
277           // ie missing argument
278           throw new JDEException("Missing argument to 'class_filters'");
279         } else {
280           List filters = new ArrayList();
281           StringTokenizer tokens = new StringTokenizer(args.remove(filterIndex).toString(), " \t\n\r\f,");
282           while (tokens.hasMoreTokens()) {
283             filters.add(tokens.nextToken());
284           }
285           return filters;
286         }
287       } else {
288         throw new JDEException("Should not happen! Contact maintainer");
289       }
290     }
291   }
292
293     
294   /**
295    * Parses the list of arguments for class exclusion filter information.
296    * <pre>
297    * class_exclusion_filters "classPatternList"
298    * </pre>
299    * Note that the exception is <b>not</b> raised if the tag isn't
300    * present: only if what follows the tag is incorrect.
301    * <p>
302    * the classPatternList should be a list of class patterns, using
303    * space or comma as delimiter.
304    * <p>
305    * Shortcut: <u>-cef</u>
306    * <p>
307    * This is used to add class exclusion filters to events. To quote
308    * JDI documentation:
309    * <p>
310    * Restricts the events generated by this request to those whose
311    * location is in a class whose name does <b>not</b> match this
312    * restricted
313    * regular expression. Regular expressions are limited to exact matches
314    * and patterns that begin with '*' or end with '*'; for example,
315    * "*.Foo" or "java.*".
316    * <p>
317    * @return a List of all the class exclusion filters. 
318    * @exception JDEException If the information cannot be resolved
319    */
320   public static List getClassExFiltersFromArgs(List args)
321     throws JDEException {
322         
323     String filterArg = null;
324     int filterIndex = -1;
325     for (int i = 0; i < args.size(); i++) {
326       String arg = args.get(i).toString().toLowerCase();
327       if (arg.equals("class_exclusion_filters")
328           || arg.equals("-cef")) { 
329         filterIndex = i;
330         filterArg = args.remove(filterIndex).toString();
331         break;
332       }
333     }
334     // at this point, either filterArg = null, or "if". in
335     // that case, filterIndex should now have the index of the argument
336     if (filterArg == null) {
337       return null;
338     } else {
339       if (filterArg.equals("class_exclusion_filters")
340           || filterArg.equals("-cef")) {
341         if (filterIndex == args.size()) {
342           // ie missing argument
343           throw new JDEException("Missing argument to 'class_exclusion_filters'");
344         } else {
345           List filters = new ArrayList();
346           StringTokenizer tokens = new StringTokenizer(args.remove(filterIndex).toString(), " \t\n\r\f,");
347           while (tokens.hasMoreTokens()) {
348             filters.add(tokens.nextToken());
349           }
350           return filters;
351         }
352       } else {
353         throw new JDEException("Should not happen! Contact maintainer");
354       }
355     }
356   }
357
358
359   /**
360    * Parses the list of arguments for suspend policy information.
361    * <pre>
362    * using_suspend_policy policy
363    * </pre>
364    * Note that the exception is <b>not</b> raised if the tags are
365    * not present: only if what follows the tag is incorrect.
366    * <p>
367    * <i>policy</i> is one of "all", "thread", or "none". "all" means the
368    * entire
369    * VM is suspended when the event occurs, "thread" indicates only the
370    * thread on which the event occurs is suspended (only for events
371    * associated with threads), while "none" means nothing is suspended
372    * when the event occurs.
373    * <p>
374    * Shortcut: <u>-sp</u>
375    * <p>
376    * @return a valid int indicating the suspend policy
377    * @exception JDEException If the information cannot be resolved
378    */
379   public static int getSuspendPolicyFromArgs(List args)
380     throws JDEException {
381         
382     String suspendPolicyArg = null;
383     int suspendPolicyIndex = -1;
384     for (int i = 0; i < args.size(); i++) {
385       String arg = args.get(i).toString().toLowerCase();
386       if (arg.equals("using_suspend_policy") || arg.equals("-sp")) { 
387         suspendPolicyIndex = i;
388         suspendPolicyArg =args.remove(suspendPolicyIndex).toString();
389         break;
390       }
391     }
392     // at this point, either suspendPolicyArg = null, or "if". in
393     // that case, suspendPolicyIndex should now have the index of the
394     // argument
395     if (suspendPolicyArg == null) {
396       return EventRequest.SUSPEND_ALL;
397     } else {
398       if (suspendPolicyArg.equals("using_suspend_policy")
399           || suspendPolicyArg.equals("-sp")) {
400         if (suspendPolicyIndex == args.size()) {
401           // ie missing argument
402           throw new JDEException("Missing argument to 'using_suspend_policy'");
403         } else {
404           String policy = args.remove(suspendPolicyIndex).toString().toLowerCase();
405           if (policy.equals("all")) {
406             return EventRequest.SUSPEND_ALL;
407           } else if (policy.equals("thread")) {
408             return EventRequest.SUSPEND_EVENT_THREAD;
409           } else if (policy.equals("none")) {
410             return EventRequest.SUSPEND_NONE;
411           } else {
412             throw new JDEException("Invalid suspend policy '"+policy+"'");
413           }
414                     
415         }
416       } else {
417         throw new JDEException("Should not happen! Contact maintainer");
418       }
419     }
420   }
421
422     
423   /**
424    * Parses the list of arguments for object ID information.
425    * <pre>
426    * if_object_id objectID
427    * </pre>
428    * Note that the exception is <b>not</b> raised if the tag isn't
429    * present: only if what follows the tag is incorrect.
430    * <p>
431    * Shortcut: <u>-oid</u>
432    * <p>
433    * @return a Long corresponding to the object ID.
434    * @exception JDEException If the information cannot be resolved
435    */
436   public static Long getObjectIDFromArgs(List args)
437     throws JDEException {
438         
439     String idArg = null;
440     int idIndex = -1;
441     for (int i = 0; i < args.size(); i++) {
442       String arg = args.get(i).toString().toLowerCase();
443       if (arg.equals("if_object_id") || arg.equals("-oid")) { 
444         idIndex = i;
445         idArg = args.remove(idIndex).toString();
446         break;
447       }
448     }
449     // at this point, either idArg = null, or "if". in
450     // that case, idIndex should now have the index of the argument
451     if (idArg == null) {
452       return null;
453     } else {
454       if (idArg.equals("if_object_id")
455           || idArg.equals("-oid")) {
456         if (idIndex == args.size()) {
457           // ie missing argument
458           throw new JDEException("Missing argument to 'if_object_id'");
459         } else {
460           try {
461             return new Long(args.remove(idIndex).toString());
462           } catch (NumberFormatException ex) {
463             throw new JDENumberFormatException("'if_object_id' argument");
464           }
465         }
466       } else {
467         throw new JDEException("Should not happen! Contact maintainer");
468       }
469     }
470   }
471
472 } // Etc
473
474 /*
475  * $Log: Etc.java,v $
476  * Revision 1.3  2003/01/08 06:53:38  paulk
477  * Integrate Petter Mahlen's updates.
478  *
479  */
480
481 // End of Etc.java