1/* 2 * Copyright (c) 1998, 2011, 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 35package com.sun.tools.example.debug.tty; 36 37import com.sun.jdi.*; 38import com.sun.jdi.request.EventRequest; 39import com.sun.jdi.request.ExceptionRequest; 40import com.sun.jdi.request.ClassPrepareRequest; 41import com.sun.jdi.event.ClassPrepareEvent; 42import java.util.ArrayList; 43 44abstract class EventRequestSpec { 45 46 final ReferenceTypeSpec refSpec; 47 48 int suspendPolicy = EventRequest.SUSPEND_ALL; 49 50 EventRequest resolved = null; 51 ClassPrepareRequest prepareRequest = null; 52 53 EventRequestSpec(ReferenceTypeSpec refSpec) { 54 this.refSpec = refSpec; 55 } 56 57 /** 58 * The 'refType' is known to match, return the EventRequest. 59 */ 60 abstract EventRequest resolveEventRequest(ReferenceType refType) 61 throws Exception; 62 63 /** 64 * @return If this EventRequestSpec matches the 'refType' 65 * return the cooresponding EventRequest. Otherwise 66 * return null. 67 */ 68 synchronized EventRequest resolve(ClassPrepareEvent event) throws Exception { 69 if ((resolved == null) && 70 (prepareRequest != null) && 71 prepareRequest.equals(event.request())) { 72 73 resolved = resolveEventRequest(event.referenceType()); 74 prepareRequest.disable(); 75 Env.vm().eventRequestManager().deleteEventRequest(prepareRequest); 76 prepareRequest = null; 77 78 if (refSpec instanceof PatternReferenceTypeSpec) { 79 PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec; 80 if (! prs.isUnique()){ 81 /* 82 * Class pattern event requests are never 83 * considered "resolved", since future class loads 84 * might also match. 85 * Create and enable a new ClassPrepareRequest to 86 * keep trying to resolve. 87 */ 88 resolved = null; 89 prepareRequest = refSpec.createPrepareRequest(); 90 prepareRequest.enable(); 91 } 92 } 93 } 94 return resolved; 95 } 96 97 synchronized void remove() { 98 if (isResolved()) { 99 Env.vm().eventRequestManager().deleteEventRequest(resolved()); 100 } 101 if (refSpec instanceof PatternReferenceTypeSpec) { 102 PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec; 103 if (! prs.isUnique()){ 104 /* 105 * This is a class pattern. Track down and delete 106 * all EventRequests matching this spec. 107 * Note: Class patterns apply only to ExceptionRequests, 108 * so that is all we need to examine. 109 */ 110 ArrayList<ExceptionRequest> deleteList = new ArrayList<ExceptionRequest>(); 111 for (ExceptionRequest er : 112 Env.vm().eventRequestManager().exceptionRequests()) { 113 if (prs.matches(er.exception())) { 114 deleteList.add (er); 115 } 116 } 117 Env.vm().eventRequestManager().deleteEventRequests(deleteList); 118 } 119 } 120 } 121 122 private EventRequest resolveAgainstPreparedClasses() throws Exception { 123 for (ReferenceType refType : Env.vm().allClasses()) { 124 if (refType.isPrepared() && refSpec.matches(refType)) { 125 resolved = resolveEventRequest(refType); 126 } 127 } 128 return resolved; 129 } 130 131 synchronized EventRequest resolveEagerly() throws Exception { 132 try { 133 if (resolved == null) { 134 /* 135 * Not resolved. Schedule a prepare request so we 136 * can resolve later. 137 */ 138 prepareRequest = refSpec.createPrepareRequest(); 139 prepareRequest.enable(); 140 141 // Try to resolve in case the class is already loaded. 142 resolveAgainstPreparedClasses(); 143 if (resolved != null) { 144 prepareRequest.disable(); 145 Env.vm().eventRequestManager().deleteEventRequest(prepareRequest); 146 prepareRequest = null; 147 } 148 } 149 if (refSpec instanceof PatternReferenceTypeSpec) { 150 PatternReferenceTypeSpec prs = (PatternReferenceTypeSpec)refSpec; 151 if (! prs.isUnique()){ 152 /* 153 * Class pattern event requests are never 154 * considered "resolved", since future class loads 155 * might also match. Create a new 156 * ClassPrepareRequest if necessary and keep 157 * trying to resolve. 158 */ 159 resolved = null; 160 if (prepareRequest == null) { 161 prepareRequest = refSpec.createPrepareRequest(); 162 prepareRequest.enable(); 163 } 164 } 165 } 166 } catch (VMNotConnectedException e) { 167 // Do nothing. Another resolve will be attempted when the 168 // VM is started. 169 } 170 return resolved; 171 } 172 173 /** 174 * @return the eventRequest this spec has been resolved to, 175 * null if so far unresolved. 176 */ 177 EventRequest resolved() { 178 return resolved; 179 } 180 181 /** 182 * @return true if this spec has been resolved. 183 */ 184 boolean isResolved() { 185 return resolved != null; 186 } 187 188 protected boolean isJavaIdentifier(String s) { 189 if (s.length() == 0) { 190 return false; 191 } 192 193 int cp = s.codePointAt(0); 194 if (! Character.isJavaIdentifierStart(cp)) { 195 return false; 196 } 197 198 for (int i = Character.charCount(cp); i < s.length(); i += Character.charCount(cp)) { 199 cp = s.codePointAt(i); 200 if (! Character.isJavaIdentifierPart(cp)) { 201 return false; 202 } 203 } 204 205 return true; 206 } 207 208 String errorMessageFor(Exception e) { 209 if (e instanceof IllegalArgumentException) { 210 return (MessageOutput.format("Invalid command syntax")); 211 } else if (e instanceof RuntimeException) { 212 // A runtime exception that we were not expecting 213 throw (RuntimeException)e; 214 } else { 215 return (MessageOutput.format("Internal error; unable to set", 216 this.refSpec.toString())); 217 } 218 } 219} 220