blob: be3fb306a578a36a6bc29a4ac9f1631f2a99778f [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2004 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package com.sun.tools.example.debug.tty;
27
28import com.sun.jdi.*;
29import com.sun.jdi.request.StepRequest;
30import com.sun.jdi.request.MethodEntryRequest;
31import com.sun.jdi.request.MethodExitRequest;
32import com.sun.tools.jdi.*;
33import java.util.*;
34import java.io.*;
35
36
37class Env {
38
39 static EventRequestSpecList specList = new EventRequestSpecList();
40
41 private static VMConnection connection;
42
43 private static SourceMapper sourceMapper = new SourceMapper("");
44 private static List<String> excludes;
45
46 private static final int SOURCE_CACHE_SIZE = 5;
47 private static List<SourceCode> sourceCache = new LinkedList<SourceCode>();
48
49 private static HashMap<String, Value> savedValues = new HashMap<String, Value>();
50 private static Method atExitMethod;
51
52 static void init(String connectSpec, boolean openNow, int flags) {
53 connection = new VMConnection(connectSpec, flags);
54 if (!connection.isLaunch() || openNow) {
55 connection.open();
56 }
57 }
58
59 static VMConnection connection() {
60 return connection;
61 }
62
63 static VirtualMachine vm() {
64 return connection.vm();
65 }
66
67 static void shutdown() {
68 shutdown(null);
69 }
70
71 static void shutdown(String message) {
72 if (connection != null) {
73 try {
74 connection.disposeVM();
75 } catch (VMDisconnectedException e) {
76 // Shutting down after the VM has gone away. This is
77 // not an error, and we just ignore it.
78 }
79 }
80 if (message != null) {
81 MessageOutput.lnprint(message);
82 MessageOutput.println();
83 }
84 System.exit(0);
85 }
86
87 static void setSourcePath(String srcPath) {
88 sourceMapper = new SourceMapper(srcPath);
89 sourceCache.clear();
90 }
91
92 static void setSourcePath(List srcList) {
93 sourceMapper = new SourceMapper(srcList);
94 sourceCache.clear();
95 }
96
97 static String getSourcePath() {
98 return sourceMapper.getSourcePath();
99 }
100
101 static private List<String> excludes() {
102 if (excludes == null) {
103 setExcludes("java.*, javax.*, sun.*, com.sun.*");
104 }
105 return excludes;
106 }
107
108 static String excludesString() {
109 Iterator iter = excludes().iterator();
110 StringBuffer buffer = new StringBuffer();
111 while (iter.hasNext()) {
112 String pattern = (String)iter.next();
113 buffer.append(pattern);
114 buffer.append(",");
115 }
116 return buffer.toString();
117 }
118
119 static void addExcludes(StepRequest request) {
120 Iterator iter = excludes().iterator();
121 while (iter.hasNext()) {
122 String pattern = (String)iter.next();
123 request.addClassExclusionFilter(pattern);
124 }
125 }
126
127 static void addExcludes(MethodEntryRequest request) {
128 Iterator iter = excludes().iterator();
129 while (iter.hasNext()) {
130 String pattern = (String)iter.next();
131 request.addClassExclusionFilter(pattern);
132 }
133 }
134
135 static void addExcludes(MethodExitRequest request) {
136 Iterator iter = excludes().iterator();
137 while (iter.hasNext()) {
138 String pattern = (String)iter.next();
139 request.addClassExclusionFilter(pattern);
140 }
141 }
142
143 static void setExcludes(String excludeString) {
144 StringTokenizer t = new StringTokenizer(excludeString, " ,;");
145 List<String> list = new ArrayList<String>();
146 while (t.hasMoreTokens()) {
147 list.add(t.nextToken());
148 }
149 excludes = list;
150 }
151
152 static Method atExitMethod() {
153 return atExitMethod;
154 }
155
156 static void setAtExitMethod(Method mmm) {
157 atExitMethod = mmm;
158 }
159
160 /**
161 * Return a Reader cooresponding to the source of this location.
162 * Return null if not available.
163 * Note: returned reader must be closed.
164 */
165 static BufferedReader sourceReader(Location location) {
166 return sourceMapper.sourceReader(location);
167 }
168
169 static synchronized String sourceLine(Location location, int lineNumber)
170 throws IOException {
171 if (lineNumber == -1) {
172 throw new IllegalArgumentException();
173 }
174
175 try {
176 String fileName = location.sourceName();
177
178 Iterator iter = sourceCache.iterator();
179 SourceCode code = null;
180 while (iter.hasNext()) {
181 SourceCode candidate = (SourceCode)iter.next();
182 if (candidate.fileName().equals(fileName)) {
183 code = candidate;
184 iter.remove();
185 break;
186 }
187 }
188 if (code == null) {
189 BufferedReader reader = sourceReader(location);
190 if (reader == null) {
191 throw new FileNotFoundException(fileName);
192 }
193 code = new SourceCode(fileName, reader);
194 if (sourceCache.size() == SOURCE_CACHE_SIZE) {
195 sourceCache.remove(sourceCache.size() - 1);
196 }
197 }
198 sourceCache.add(0, code);
199 return code.sourceLine(lineNumber);
200 } catch (AbsentInformationException e) {
201 throw new IllegalArgumentException();
202 }
203 }
204
205 /** Return a description of an object. */
206 static String description(ObjectReference ref) {
207 ReferenceType clazz = ref.referenceType();
208 long id = ref.uniqueID();
209 if (clazz == null) {
210 return toHex(id);
211 } else {
212 return MessageOutput.format("object description and hex id",
213 new Object [] {clazz.name(),
214 toHex(id)});
215 }
216 }
217
218 /** Convert a long to a hexadecimal string. */
219 static String toHex(long n) {
220 char s1[] = new char[16];
221 char s2[] = new char[18];
222
223 /* Store digits in reverse order. */
224 int i = 0;
225 do {
226 long d = n & 0xf;
227 s1[i++] = (char)((d < 10) ? ('0' + d) : ('a' + d - 10));
228 } while ((n >>>= 4) > 0);
229
230 /* Now reverse the array. */
231 s2[0] = '0';
232 s2[1] = 'x';
233 int j = 2;
234 while (--i >= 0) {
235 s2[j++] = s1[i];
236 }
237 return new String(s2, 0, j);
238 }
239
240 /** Convert hexadecimal strings to longs. */
241 static long fromHex(String hexStr) {
242 String str = hexStr.startsWith("0x") ?
243 hexStr.substring(2).toLowerCase() : hexStr.toLowerCase();
244 if (hexStr.length() == 0) {
245 throw new NumberFormatException();
246 }
247
248 long ret = 0;
249 for (int i = 0; i < str.length(); i++) {
250 int c = str.charAt(i);
251 if (c >= '0' && c <= '9') {
252 ret = (ret * 16) + (c - '0');
253 } else if (c >= 'a' && c <= 'f') {
254 ret = (ret * 16) + (c - 'a' + 10);
255 } else {
256 throw new NumberFormatException();
257 }
258 }
259 return ret;
260 }
261
262 static ReferenceType getReferenceTypeFromToken(String idToken) {
263 ReferenceType cls = null;
264 if (Character.isDigit(idToken.charAt(0))) {
265 cls = null;
266 } else if (idToken.startsWith("*.")) {
267 // This notation saves typing by letting the user omit leading
268 // package names. The first
269 // loaded class whose name matches this limited regular
270 // expression is selected.
271 idToken = idToken.substring(1);
272 List classes = Env.vm().allClasses();
273 Iterator iter = classes.iterator();
274 while (iter.hasNext()) {
275 ReferenceType type = ((ReferenceType)iter.next());
276 if (type.name().endsWith(idToken)) {
277 cls = type;
278 break;
279 }
280 }
281 } else {
282 // It's a class name
283 List classes = Env.vm().classesByName(idToken);
284 if (classes.size() > 0) {
285 // TO DO: handle multiples
286 cls = (ReferenceType)classes.get(0);
287 }
288 }
289 return cls;
290 }
291
292 static Set getSaveKeys() {
293 return savedValues.keySet();
294 }
295
296 static Value getSavedValue(String key) {
297 return (Value)savedValues.get(key);
298 }
299
300 static void setSavedValue(String key, Value value) {
301 savedValues.put(key, value);
302 }
303
304 static class SourceCode {
305 private String fileName;
306 private List<String> sourceLines = new ArrayList<String>();
307
308 SourceCode(String fileName, BufferedReader reader) throws IOException {
309 this.fileName = fileName;
310 try {
311 String line = reader.readLine();
312 while (line != null) {
313 sourceLines.add(line);
314 line = reader.readLine();
315 }
316 } finally {
317 reader.close();
318 }
319 }
320
321 String fileName() {
322 return fileName;
323 }
324
325 String sourceLine(int number) {
326 int index = number - 1; // list is 0-indexed
327 if (index >= sourceLines.size()) {
328 return null;
329 } else {
330 return (String)sourceLines.get(index);
331 }
332 }
333 }
334}