1/*
2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25package sun.jvm.hotspot.tools.soql;
26
27import java.io.*;
28import java.util.*;
29import sun.jvm.hotspot.debugger.*;
30import sun.jvm.hotspot.oops.*;
31import sun.jvm.hotspot.runtime.*;
32import sun.jvm.hotspot.tools.*;
33import sun.jvm.hotspot.utilities.*;
34import sun.jvm.hotspot.utilities.soql.*;
35
36/**
37  This is command line SOQL (Simple Object Query Language) interpreter.
38*/
39
40public class SOQL extends Tool {
41   public static void main(String[] args) {
42      SOQL soql = new SOQL();
43      soql.execute(args);
44   }
45
46   public SOQL() {
47      super();
48   }
49
50   public SOQL(JVMDebugger d) {
51      super(d);
52   }
53
54   protected SOQLEngine soqlEngine;
55   protected BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
56   protected PrintStream out       = System.out;
57   static protected String prompt       = "soql> ";
58   static protected String secondPrompt = "> ";
59
60   public void run() {
61      soqlEngine = SOQLEngine.getEngine();
62      while (true) {
63         try {
64            out.print(prompt);
65            String line = in.readLine();
66            if (line == null) {
67               return;
68            }
69            StringTokenizer st = new StringTokenizer(line);
70            if (st.hasMoreTokens()) {
71               String cmd = st.nextToken();
72               if (cmd.equals("select")) {
73                  handleSelect(line);
74               } else if (cmd.equals("classes")) {
75                  handleClasses(line);
76               } else if (cmd.equals("class")) {
77                  handleClass(line);
78               } else if (cmd.equals("object")) {
79                  handleObject(line);
80               } else if (cmd.equals("quit")) {
81                  out.println("Bye!");
82                  return;
83               } else if (cmd.equals("")) {
84                  // do nothing ...
85               } else {
86                  handleUnknown(line);
87               }
88            }
89         } catch (IOException e) {
90            e.printStackTrace();
91            return;
92         }
93      }
94   }
95
96   protected void handleSelect(String query) {
97      StringBuffer buf = new StringBuffer(query);
98      String tmp = null;
99      while (true) {
100         out.print(secondPrompt);
101         try {
102            tmp = in.readLine();
103         } catch (IOException ioe) {
104            break;
105         }
106         if (tmp.equals("") || tmp.equals("go"))
107            break;
108         buf.append('\n');
109         buf.append(tmp);
110      }
111      query = buf.toString();
112
113      try {
114         soqlEngine.executeQuery(query,
115                           new ObjectVisitor() {
116                              public void visit(Object o) {
117                                 if (o != null && o instanceof JSJavaObject) {
118                                     String oopAddr = ((JSJavaObject)o).getOop().getHandle().toString();
119                                     out.println(oopAddr);
120                                 } else {
121                                     out.println((o == null)? "null" : o.toString());
122                                 }
123                              }
124                           });
125      } catch (SOQLException se) {
126         se.printStackTrace();
127      }
128   }
129
130   protected void handleClasses(String line) {
131      // just list all InstanceKlasses
132      InstanceKlass[] klasses = SystemDictionaryHelper.getAllInstanceKlasses();
133      for (int i = 0; i < klasses.length; i++) {
134         out.print(klasses[i].getName().asString().replace('/', '.'));
135         out.print(" @");
136         out.println(klasses[i].getAddress());
137      }
138   }
139
140   protected void handleClass(String line) {
141      StringTokenizer st = new StringTokenizer(line);
142      st.nextToken(); // ignore "class"
143      if (st.hasMoreTokens()) {
144         String className = st.nextToken();
145         InstanceKlass klass = SystemDictionaryHelper.findInstanceKlass(className);
146         if (klass == null) {
147            out.println("class " + className + " not found");
148         } else {
149            // klass.iterate(new OopPrinter(out), true);
150
151            // base class
152            InstanceKlass base = (InstanceKlass) klass.getSuper();
153            if (base != null) {
154               out.println("super");
155               out.print("\t");
156               out.println(base.getName().asString().replace('/', '.'));
157            }
158
159            // list immediate fields only
160            U2Array fields = klass.getFields();
161            int numFields = (int) fields.length();
162            ConstantPool cp = klass.getConstants();
163            out.println("fields");
164            if (numFields != 0) {
165              for (int f = 0; f < numFields; f++){
166                 Symbol f_name = klass.getFieldName(f);
167                 Symbol f_sig  = klass.getFieldSignature(f);
168                 StringBuffer sigBuf = new StringBuffer();
169                 new SignatureConverter(f_sig, sigBuf).dispatchField();
170                 out.print('\t');
171                 out.print(sigBuf.toString().replace('/', '.'));
172                 out.print(' ');
173                 out.println(f_name.asString());
174               }
175            } else {
176               out.println("\tno fields in this class");
177            }
178         }
179      } else {
180         out.println("usage: class <name of the class>");
181      }
182   }
183
184   protected Oop getOopAtAddress(Address addr) {
185      OopHandle oopHandle = addr.addOffsetToAsOopHandle(0);
186      return VM.getVM().getObjectHeap().newOop(oopHandle);
187   }
188
189   protected void handleObject(String line) {
190      StringTokenizer st = new StringTokenizer(line);
191      st.nextToken(); // ignore "object"
192      if (st.hasMoreTokens()) {
193         String addrStr = st.nextToken();
194         Address addr = null;
195         Debugger dbg = VM.getVM().getDebugger();
196         try {
197            addr = dbg.parseAddress(addrStr);
198         } catch (Exception e) {
199            out.println("invalid address : " + e.getMessage());
200            return;
201         }
202
203         Oop oop = null;
204         try {
205            oop = getOopAtAddress(addr);
206         } catch (Exception e) {
207            out.println("invalid object : " + e.getMessage());
208         }
209
210         if (oop != null) {
211            oop.iterate(new OopPrinter(out), true);
212         } else {
213            out.println("null object!");
214         }
215      } else {
216         out.println("usage: object <address>");
217      }
218   }
219
220   protected void handleUnknown(String line) {
221      out.println("Unknown command!");
222   }
223}
224