1 19 package org.netbeans.modules.debugger.jpda.ui; 20 21 import com.sun.jdi.AbsentInformationException; 22 import java.beans.PropertyChangeEvent ; 23 import java.beans.PropertyChangeListener ; 24 import java.util.HashMap ; 25 import java.util.Iterator ; 26 import javax.swing.SwingUtilities ; 27 28 import org.netbeans.api.debugger.*; 29 import org.netbeans.api.debugger.jpda.CallStackFrame; 30 import org.netbeans.api.debugger.jpda.JPDADebugger; 31 import org.netbeans.api.debugger.jpda.JPDAThread; 32 import org.netbeans.api.debugger.jpda.LineBreakpoint; 33 import org.openide.ErrorManager; 34 35 import org.openide.util.RequestProcessor; 36 37 38 46 public class CurrentThreadAnnotationListener extends DebuggerManagerAdapter { 47 48 private transient Object currentPC; 50 private transient Object currentPCLock = new Object (); 51 private transient boolean currentPCSet = false; 52 private JPDAThread currentThread; 53 private JPDADebugger currentDebugger; 54 55 56 57 public String [] getProperties () { 58 return new String [] {DebuggerManager.PROP_CURRENT_ENGINE}; 59 } 60 61 64 public void propertyChange (PropertyChangeEvent e) { 65 if (e.getPropertyName () == DebuggerManager.PROP_CURRENT_ENGINE) { 66 updateCurrentDebugger (); 67 updateCurrentThread (); 68 annotate (); 69 } else 70 if (e.getPropertyName () == JPDADebugger.PROP_CURRENT_THREAD) { 71 updateCurrentThread (); 72 annotate (); 73 } else 74 if (e.getPropertyName () == JPDADebugger.PROP_CURRENT_CALL_STACK_FRAME) { 75 updateCurrentThread (); 76 annotate (); 77 } else 78 if (e.getPropertyName () == JPDADebugger.PROP_STATE) { 79 annotate (); 80 } 81 } 82 83 84 86 private void updateCurrentDebugger () { 87 JPDADebugger newDebugger = getCurrentDebugger (); 88 if (currentDebugger == newDebugger) return; 89 if (currentDebugger != null) 90 currentDebugger.removePropertyChangeListener (this); 91 if (newDebugger != null) 92 newDebugger.addPropertyChangeListener (this); 93 currentDebugger = newDebugger; 94 } 95 96 private static JPDADebugger getCurrentDebugger () { 97 DebuggerEngine currentEngine = DebuggerManager. 98 getDebuggerManager ().getCurrentEngine (); 99 if (currentEngine == null) return null; 100 return (JPDADebugger) currentEngine.lookupFirst 101 (null, JPDADebugger.class); 102 } 103 104 private void updateCurrentThread () { 105 if (currentDebugger != null) 107 currentThread = currentDebugger.getCurrentThread (); 108 else 109 currentThread = null; 110 } 111 112 115 private void annotate () { 116 if ( (currentThread == null) || 118 (currentDebugger.getState () != JPDADebugger.STATE_STOPPED) ) { 119 synchronized (currentPCLock) { 120 currentPCSet = false; } 122 removeAnnotations (); 123 return; 124 } 125 126 CallStackFrame[] stack; 128 try { 129 stack = currentThread.getCallStack (); 130 } catch (AbsentInformationException ex) { 131 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, ex); 132 synchronized (currentPCLock) { 133 currentPCSet = false; } 135 removeAnnotations (); 136 return; 137 } 138 final CallStackFrame csf = currentDebugger.getCurrentCallStackFrame (); 139 Session currentSession = null; 140 Session[] sessions = DebuggerManager.getDebuggerManager().getSessions(); 141 for (int i = 0; i < sessions.length; i++) { 142 if (sessions[i].lookupFirst(null, JPDADebugger.class) == currentDebugger) { 143 currentSession = sessions[i]; 144 break; 145 } 146 } 147 final String language = currentSession == null ? 148 null : currentSession.getCurrentLanguage (); 149 DebuggerEngine currentEngine = (currentSession == null) ? 150 null : currentSession.getCurrentEngine(); 151 final SourcePath sourcePath = (currentEngine == null) ? 152 null : (SourcePath) currentEngine.lookupFirst(null, SourcePath.class); 153 154 synchronized (currentPCLock) { 156 currentPCSet = true; } 158 SwingUtilities.invokeLater (new Runnable () { 159 public void run () { 160 synchronized (currentPCLock) { 162 if (currentPC != null) 163 EditorContextBridge.removeAnnotation (currentPC); 164 if (csf != null && sourcePath != null && currentThread != null) { 165 166 sourcePath.showSource (csf, language); 167 currentPC = sourcePath.annotate (currentThread, language); 169 } 170 } 171 } 172 }); 173 annotateCallStack (stack, sourcePath); 174 } 175 176 177 private HashMap stackAnnotations = new HashMap (); 179 180 private RequestProcessor rp = new RequestProcessor("Debugger Thread Annotation Refresher"); 181 182 private RequestProcessor.Task taskRemove; 185 private RequestProcessor.Task taskAnnotate; 186 private CallStackFrame[] stackToAnnotate; 187 private SourcePath sourcePathToAnnotate; 188 189 private void removeAnnotations () { 190 synchronized (rp) { 191 if (taskRemove == null) { 192 taskRemove = rp.create (new Runnable () { 193 public void run () { 194 synchronized (currentPCLock) { 195 if (currentPCSet) { 196 return ; 198 } 199 if (currentPC != null) 200 EditorContextBridge.removeAnnotation (currentPC); 201 currentPC = null; 202 } 203 Iterator i = stackAnnotations.values ().iterator (); 204 while (i.hasNext ()) 205 EditorContextBridge.removeAnnotation (i.next ()); 206 stackAnnotations.clear (); 207 } 208 }); 209 } 210 } 211 taskRemove.schedule(500); 212 } 213 214 private void annotateCallStack ( 215 CallStackFrame[] stack, 216 SourcePath sourcePath 217 ) { 218 synchronized (rp) { 219 if (taskRemove != null) { 220 taskRemove.cancel(); 221 } 222 this.stackToAnnotate = stack; 223 this.sourcePathToAnnotate = sourcePath; 224 if (taskAnnotate == null) { 225 taskAnnotate = rp.post (new Runnable () { 226 public void run () { 227 CallStackFrame[] stack; 228 SourcePath sourcePath; 229 synchronized (rp) { 230 if (stackToAnnotate == null) { 231 return ; } 233 stack = stackToAnnotate; 234 sourcePath = sourcePathToAnnotate; 235 stackToAnnotate = null; 236 sourcePathToAnnotate = null; 237 } 238 HashMap newAnnotations = new HashMap (); 239 int i, k = stack.length; 240 for (i = 1; i < k; i++) { 241 242 String language = stack[i].getDefaultStratum(); 244 String resourceName = EditorContextBridge.getRelativePath 245 (stack[i], language); 246 int lineNumber = stack[i].getLineNumber (language); 247 String line = resourceName + lineNumber; 248 249 if (newAnnotations.containsKey (line)) 251 continue; 252 253 Object da = stackAnnotations.remove (line); 255 if (da == null) { 256 da = sourcePath.annotate (stack[i], language); 258 } 259 260 if (da != null) 262 newAnnotations.put (line, da); 263 } 265 Iterator iter = stackAnnotations.values ().iterator (); 267 while (iter.hasNext ()) 268 EditorContextBridge.removeAnnotation ( 269 iter.next () 270 ); 271 stackAnnotations = newAnnotations; 272 } 273 }); 274 } 275 } 276 taskAnnotate.schedule(500); 277 } 278 } 279 | Popular Tags |