1 19 20 package org.netbeans.modules.debugger.jpda.breakpoints; 21 22 import com.sun.jdi.AbsentInformationException; 23 import com.sun.jdi.InternalException; 24 import com.sun.jdi.Location; 25 import com.sun.jdi.ObjectCollectedException; 26 import com.sun.jdi.ReferenceType; 27 import com.sun.jdi.VMDisconnectedException; 28 import com.sun.jdi.ClassNotPreparedException; 29 import com.sun.jdi.event.BreakpointEvent; 30 import com.sun.jdi.event.LocatableEvent; 31 import com.sun.jdi.event.Event; 32 import com.sun.jdi.request.BreakpointRequest; 33 import java.util.ArrayList ; 34 import java.util.Collections ; 35 import java.util.Iterator ; 36 import java.util.List ; 37 import java.util.logging.Level ; 38 import java.util.logging.Logger ; 39 import java.util.regex.Matcher ; 40 import java.util.regex.Pattern ; 41 import org.netbeans.api.debugger.Breakpoint; 42 import org.netbeans.api.debugger.jpda.ClassLoadUnloadBreakpoint; 43 import org.netbeans.api.debugger.jpda.JPDABreakpoint; 44 import org.netbeans.api.debugger.jpda.LineBreakpoint; 45 import org.netbeans.api.debugger.Session; 46 import org.netbeans.modules.debugger.jpda.EditorContextBridge; 47 import org.netbeans.modules.debugger.jpda.SourcePath; 48 import org.netbeans.modules.debugger.jpda.JPDADebuggerImpl; 49 import org.openide.ErrorManager; 50 import org.openide.util.NbBundle; 51 52 53 54 59 public class LineBreakpointImpl extends ClassBasedBreakpoint { 60 61 private static Logger logger = Logger.getLogger("org.netbeans.modules.debugger.jpda.breakpoints"); 63 private int lineNumber; 64 private BreakpointsReader reader; 65 66 67 public LineBreakpointImpl ( 68 LineBreakpoint breakpoint, 69 BreakpointsReader reader, 70 JPDADebuggerImpl debugger, 71 Session session, 72 SourcePath sourcePath 73 ) { 74 super (breakpoint, reader, debugger, session); 75 this.reader = reader; 76 lineNumber = breakpoint.getLineNumber (); 77 setSourceRoot(sourcePath.getSourceRoot(breakpoint.getURL())); 78 set (); 79 } 80 81 protected LineBreakpoint getBreakpoint() { 82 return (LineBreakpoint) super.getBreakpoint(); 83 } 84 85 void fixed () { 86 logger.fine("LineBreakpoint fixed: "+this); 87 lineNumber = getBreakpoint().getLineNumber (); 88 super.fixed (); 89 } 90 91 protected void setRequests () { 92 LineBreakpoint breakpoint = getBreakpoint(); 93 lineNumber = breakpoint.getLineNumber (); 94 String className = breakpoint.getPreferredClassName(); 95 if (className == null) { 96 className = reader.findCachedClassName(breakpoint); 97 if (className == null) { 98 className = EditorContextBridge.getClassName ( 99 breakpoint.getURL (), 100 lineNumber 101 ); 102 if (className != null) { 103 reader.storeCachedClassName(breakpoint, className); 104 } 105 } 106 } 107 if (className == null) { 108 logger.warning("Class name not defined for breakpoint "+breakpoint); 109 return ; 110 } 111 logger.fine("LineBreakpoint "+breakpoint+" - setting request for "+className); 112 setClassRequests ( 113 new String [] { 114 className }, 116 new String [0], 117 ClassLoadUnloadBreakpoint.TYPE_CLASS_LOADED 118 ); 119 checkLoadedClasses (className); 120 } 121 122 protected void classLoaded (ReferenceType referenceType) { 123 LineBreakpoint breakpoint = getBreakpoint(); 124 logger.fine("Class "+referenceType+" loaded for breakpoint "+breakpoint); 125 126 String [] reason = new String [] { null }; 127 List locations = getLocations ( 128 referenceType, 129 breakpoint.getStratum (), 130 breakpoint.getSourceName (), 131 breakpoint.getSourcePath(), 132 lineNumber, 133 reason 134 ); 135 if (locations.isEmpty()) { 136 ErrorManager.getDefault().log(ErrorManager.WARNING, 137 "Unable to submit line breakpoint to "+referenceType.name()+ 138 " at line "+lineNumber+", reason: "+reason[0]); 139 setValidity(Breakpoint.VALIDITY.INVALID, reason[0]); 140 return; 141 } 142 for (Iterator it = locations.iterator(); it.hasNext();) { 143 Location location = (Location)it.next(); 144 try { 145 BreakpointRequest br = getEventRequestManager (). 146 createBreakpointRequest (location); 147 addEventRequest (br); 148 setValidity(Breakpoint.VALIDITY.VALID, null); 149 } catch (VMDisconnectedException e) { 151 } 152 } 153 } 154 155 public boolean exec (Event event) { 156 if (event instanceof BreakpointEvent) { 157 return perform ( 158 getBreakpoint().getCondition (), 159 ((BreakpointEvent) event).thread (), 160 ((LocatableEvent) event).location ().declaringType (), 161 null 162 ); 163 } 164 return super.exec (event); 165 } 166 167 private static List getLocations ( 168 ReferenceType referenceType, 169 String stratum, 170 String sourceName, 171 String bpSourcePath, 172 int lineNumber, 173 String [] reason 174 ) { 175 try { 176 reason[0] = null; 177 List locations = locationsOfLineInClass(referenceType, stratum, 178 sourceName, bpSourcePath, 179 lineNumber, reason); 180 195 if (locations.isEmpty() && reason[0] == null) { 196 reason[0] = NbBundle.getMessage(LineBreakpointImpl.class, "MSG_NoLocation", Integer.toString(lineNumber)); 197 } 198 return locations; 199 } catch (AbsentInformationException ex) { 200 reason[0] = NbBundle.getMessage(LineBreakpointImpl.class, "MSG_NoLineInfo"); 204 } catch (ObjectCollectedException ex) { 205 reason[0] = ex.getLocalizedMessage(); 209 } catch (ClassNotPreparedException ex) { 210 ErrorManager.getDefault().notify(ErrorManager.ERROR, ex); 213 } catch (InternalException iex) { 214 ErrorManager.getDefault().annotate(iex, 216 NbBundle.getMessage(LineBreakpointImpl.class, 217 "MSG_jdi_internal_error") ); 218 ErrorManager.getDefault().notify(iex); 219 reason[0] = iex.getLocalizedMessage(); 221 } 222 return Collections.EMPTY_LIST; 223 } 224 225 private static List <Location> locationsOfLineInClass( 226 ReferenceType referenceType, 227 String stratum, 228 String sourceName, 229 String bpSourcePath, 230 int lineNumber, 231 String [] reason) throws AbsentInformationException, ObjectCollectedException, 232 ClassNotPreparedException, InternalException { 233 List <Location> list = referenceType.locationsOfLine ( 234 stratum, 235 sourceName, 236 lineNumber 237 ); 238 239 if (logger.isLoggable(Level.FINER)) { 240 logger.finer("LineBreakpoint: locations for ReferenceType=" + 241 referenceType + ", stratum=" + stratum + 242 ", source name=" + sourceName + ", bpSourcePath=" + 243 bpSourcePath+", lineNumber=" + lineNumber + 244 " are: {" + list + "}"); 245 } 246 if (!list.isEmpty ()) { 247 if (bpSourcePath == null) 248 return list; 249 bpSourcePath = bpSourcePath.replace(java.io.File.separatorChar, '/'); 250 ArrayList <Location> locations = new ArrayList <Location>(list.size()); 251 for (Iterator <Location> it = list.iterator(); it.hasNext();) { 252 Location l = it.next(); 253 String lSourcePath = l.sourcePath().replace(java.io.File.separatorChar, '/'); 254 lSourcePath = normalize(lSourcePath); 255 if (lSourcePath.equals(bpSourcePath)) { 256 locations.add(l); 257 } else { 258 reason[0] = "Breakpoint source path '"+bpSourcePath+"' is different from the location source path '"+lSourcePath+"'."; 259 } 260 } 261 if (logger.isLoggable(Level.FINER)) { 262 logger.finer("LineBreakpoint: relevant location(s) for path '" + bpSourcePath + "': " + locations); 263 } 264 if (!locations.isEmpty()) 265 return locations; 266 } 267 return Collections.emptyList(); 268 } 269 270 279 private static String normalize(String path) { 280 Pattern thisDirectoryPattern = Pattern.compile("(/|\\A)\\./"); 281 Pattern parentDirectoryPattern = Pattern.compile("(/|\\A)([^/]+?)/\\.\\./"); 282 283 for (Matcher m = thisDirectoryPattern.matcher(path); m.find(); ) 284 { 285 path = m.replaceAll("$1"); 286 m = thisDirectoryPattern.matcher(path); 287 } 288 for (Matcher m = parentDirectoryPattern.matcher(path); m.find(); ) 289 { 290 if (!m.group(2).equals("..")) { 291 path = path.substring(0, m.start()) + m.group(1) + path.substring(m.end()); 292 m = parentDirectoryPattern.matcher(path); 293 } 294 } 295 return path; 296 } 297 } 298 299 | Popular Tags |