1 /* 2 * Copyright (c) 1998, 2019, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * This source code is provided to illustrate the usage of a given feature 28 * or technique and has been deliberately simplified. Additional steps 29 * required for a production-quality application, such as security checks, 30 * input validation and proper error handling, might not be present in 31 * this sample code. 32 */ 33 34 35 package com.sun.tools.example.debug.tty; 36 37 import com.sun.jdi.*; 38 import com.sun.jdi.request.StepRequest; 39 import com.sun.jdi.request.MethodEntryRequest; 40 import com.sun.jdi.request.MethodExitRequest; 41 import java.util.*; 42 import java.io.*; 43 44 45 class Env { 46 47 static EventRequestSpecList specList = new EventRequestSpecList(); 48 49 private static VMConnection connection; 50 51 private static SourceMapper sourceMapper = new SourceMapper(""); 52 private static List<String> excludes; 53 54 private static final int SOURCE_CACHE_SIZE = 5; 55 private static List<SourceCode> sourceCache = new LinkedList<SourceCode>(); 56 57 private static HashMap<String, Value> savedValues = new HashMap<String, Value>(); 58 private static Method atExitMethod; 59 init(String connectSpec, boolean openNow, int flags)60 static void init(String connectSpec, boolean openNow, int flags) { 61 connection = new VMConnection(connectSpec, flags); 62 if (!connection.isLaunch() || openNow) { 63 connection.open(); 64 } 65 } 66 setTraceFlags(int flags)67 static void setTraceFlags(int flags) { 68 connection.setTraceFlags(flags); 69 } 70 connection()71 static VMConnection connection() { 72 return connection; 73 } 74 vm()75 static VirtualMachine vm() { 76 return connection.vm(); 77 } 78 shutdown()79 static void shutdown() { 80 shutdown(null); 81 } 82 shutdown(String message)83 static void shutdown(String message) { 84 if (connection != null) { 85 try { 86 connection.disposeVM(); 87 } catch (VMDisconnectedException e) { 88 // Shutting down after the VM has gone away. This is 89 // not an error, and we just ignore it. 90 } 91 } 92 if (message != null) { 93 MessageOutput.lnprint(message); 94 MessageOutput.println(); 95 } 96 System.exit(0); 97 } 98 setSourcePath(String srcPath)99 static void setSourcePath(String srcPath) { 100 sourceMapper = new SourceMapper(srcPath); 101 sourceCache.clear(); 102 } 103 setSourcePath(List<String> srcList)104 static void setSourcePath(List<String> srcList) { 105 sourceMapper = new SourceMapper(srcList); 106 sourceCache.clear(); 107 } 108 getSourcePath()109 static String getSourcePath() { 110 return sourceMapper.getSourcePath(); 111 } 112 excludes()113 static private List<String> excludes() { 114 if (excludes == null) { 115 setExcludes("java.*, javax.*, sun.*, com.sun.*, jdk.*"); 116 } 117 return excludes; 118 } 119 excludesString()120 static String excludesString() { 121 StringBuilder sb = new StringBuilder(); 122 for (String pattern : excludes()) { 123 sb.append(pattern); 124 sb.append(","); 125 } 126 return sb.toString(); 127 } 128 addExcludes(StepRequest request)129 static void addExcludes(StepRequest request) { 130 for (String pattern : excludes()) { 131 request.addClassExclusionFilter(pattern); 132 } 133 } 134 addExcludes(MethodEntryRequest request)135 static void addExcludes(MethodEntryRequest request) { 136 for (String pattern : excludes()) { 137 request.addClassExclusionFilter(pattern); 138 } 139 } 140 addExcludes(MethodExitRequest request)141 static void addExcludes(MethodExitRequest request) { 142 for (String pattern : excludes()) { 143 request.addClassExclusionFilter(pattern); 144 } 145 } 146 setExcludes(String excludeString)147 static void setExcludes(String excludeString) { 148 StringTokenizer t = new StringTokenizer(excludeString, " ,;"); 149 List<String> list = new ArrayList<String>(); 150 while (t.hasMoreTokens()) { 151 list.add(t.nextToken()); 152 } 153 excludes = list; 154 } 155 atExitMethod()156 static Method atExitMethod() { 157 return atExitMethod; 158 } 159 setAtExitMethod(Method mmm)160 static void setAtExitMethod(Method mmm) { 161 atExitMethod = mmm; 162 } 163 164 /** 165 * Return a Reader cooresponding to the source of this location. 166 * Return null if not available. 167 * Note: returned reader must be closed. 168 */ sourceReader(Location location)169 static BufferedReader sourceReader(Location location) { 170 return sourceMapper.sourceReader(location); 171 } 172 sourceLine(Location location, int lineNumber)173 static synchronized String sourceLine(Location location, int lineNumber) 174 throws IOException { 175 if (lineNumber == -1) { 176 throw new IllegalArgumentException(); 177 } 178 179 try { 180 String fileName = location.sourceName(); 181 182 Iterator<SourceCode> iter = sourceCache.iterator(); 183 SourceCode code = null; 184 while (iter.hasNext()) { 185 SourceCode candidate = iter.next(); 186 if (candidate.fileName().equals(fileName)) { 187 code = candidate; 188 iter.remove(); 189 break; 190 } 191 } 192 if (code == null) { 193 BufferedReader reader = sourceReader(location); 194 if (reader == null) { 195 throw new FileNotFoundException(fileName); 196 } 197 code = new SourceCode(fileName, reader); 198 if (sourceCache.size() == SOURCE_CACHE_SIZE) { 199 sourceCache.remove(sourceCache.size() - 1); 200 } 201 } 202 sourceCache.add(0, code); 203 return code.sourceLine(lineNumber); 204 } catch (AbsentInformationException e) { 205 throw new IllegalArgumentException(); 206 } 207 } 208 209 /** Return a description of an object. */ description(ObjectReference ref)210 static String description(ObjectReference ref) { 211 ReferenceType clazz = ref.referenceType(); 212 long id = ref.uniqueID(); 213 if (clazz == null) { 214 return Long.toString(id); 215 } else { 216 return MessageOutput.format("object description and id", 217 new Object [] {clazz.name(), 218 Long.toString(id)}); 219 } 220 } 221 getReferenceTypeFromToken(String idToken)222 static ReferenceType getReferenceTypeFromToken(String idToken) { 223 ReferenceType cls = null; 224 if (Character.isDigit(idToken.charAt(0))) { 225 cls = null; 226 } else if (idToken.startsWith("*.")) { 227 // This notation saves typing by letting the user omit leading 228 // package names. The first 229 // loaded class whose name matches this limited regular 230 // expression is selected. 231 idToken = idToken.substring(1); 232 for (ReferenceType type : Env.vm().allClasses()) { 233 if (type.name().endsWith(idToken)) { 234 cls = type; 235 break; 236 } 237 } 238 } else { 239 // It's a class name 240 List<ReferenceType> classes = Env.vm().classesByName(idToken); 241 if (classes.size() > 0) { 242 // TO DO: handle multiples 243 cls = classes.get(0); 244 } 245 } 246 return cls; 247 } 248 getSaveKeys()249 static Set<String> getSaveKeys() { 250 return savedValues.keySet(); 251 } 252 getSavedValue(String key)253 static Value getSavedValue(String key) { 254 return savedValues.get(key); 255 } 256 setSavedValue(String key, Value value)257 static void setSavedValue(String key, Value value) { 258 savedValues.put(key, value); 259 } 260 261 static class SourceCode { 262 private String fileName; 263 private List<String> sourceLines = new ArrayList<String>(); 264 SourceCode(String fileName, BufferedReader reader)265 SourceCode(String fileName, BufferedReader reader) throws IOException { 266 this.fileName = fileName; 267 try { 268 String line = reader.readLine(); 269 while (line != null) { 270 sourceLines.add(line); 271 line = reader.readLine(); 272 } 273 } finally { 274 reader.close(); 275 } 276 } 277 fileName()278 String fileName() { 279 return fileName; 280 } 281 sourceLine(int number)282 String sourceLine(int number) { 283 int index = number - 1; // list is 0-indexed 284 if (index >= sourceLines.size()) { 285 return null; 286 } else { 287 return sourceLines.get(index); 288 } 289 } 290 } 291 } 292