1 52 53 package freemarker.debug.impl; 54 55 import java.io.Serializable ; 56 import java.lang.ref.ReferenceQueue ; 57 import java.lang.ref.WeakReference ; 58 import java.rmi.RemoteException ; 59 import java.rmi.server.RemoteObject ; 60 import java.util.ArrayList ; 61 import java.util.Collection ; 62 import java.util.Collections ; 63 import java.util.Enumeration ; 64 import java.util.HashMap ; 65 import java.util.HashSet ; 66 import java.util.Iterator ; 67 import java.util.List ; 68 import java.util.Map ; 69 70 import freemarker.core.DebugBreak; 71 import freemarker.core.Environment; 72 import freemarker.core.TemplateElement; 73 import freemarker.debug.Breakpoint; 74 import freemarker.debug.DebuggerListener; 75 import freemarker.debug.EnvironmentSuspendedEvent; 76 import freemarker.template.Template; 77 import freemarker.template.utility.UndeclaredThrowableException; 78 79 83 class RmiDebuggerService 84 extends 85 DebuggerService 86 { 87 private final Map templateDebugInfos = new HashMap (); 88 private final HashSet suspendedEnvironments = new HashSet (); 89 private final Map listeners = new HashMap (); 90 private final ReferenceQueue refQueue = new ReferenceQueue (); 91 92 RmiDebuggerService() 93 { 94 try 95 { 96 new DebuggerServer((Serializable )RemoteObject.toStub(new RmiDebuggerImpl(this))).start(); 97 } 98 catch(RemoteException e) 99 { 100 throw new UndeclaredThrowableException(e); 101 } 102 } 103 104 List getBreakpointsSpi(String templateName) 105 { 106 synchronized(templateDebugInfos) 107 { 108 TemplateDebugInfo tdi = findTemplateDebugInfo(templateName); 109 return tdi == null ? Collections.EMPTY_LIST : tdi.breakpoints; 110 } 111 } 112 113 List getBreakpointsSpi() 114 { 115 List sumlist = new ArrayList (); 116 synchronized(templateDebugInfos) 117 { 118 for (Iterator iter = templateDebugInfos.values().iterator(); iter.hasNext();) 119 { 120 sumlist.addAll(((TemplateDebugInfo) iter.next()).breakpoints); 121 } 122 } 123 Collections.sort(sumlist); 124 return sumlist; 125 } 126 127 boolean suspendEnvironmentSpi(Environment env, int line) 128 throws 129 RemoteException 130 { 131 RmiDebuggedEnvironmentImpl denv = 132 (RmiDebuggedEnvironmentImpl) 133 RmiDebuggedEnvironmentImpl.getCachedWrapperFor(env); 134 135 synchronized(suspendedEnvironments) 136 { 137 suspendedEnvironments.add(denv); 138 } 139 try 140 { 141 EnvironmentSuspendedEvent breakpointEvent = 142 new EnvironmentSuspendedEvent(this, line, denv); 143 144 synchronized(listeners) 145 { 146 for (Iterator iter = listeners.values().iterator(); iter.hasNext();) 147 { 148 DebuggerListener listener = (DebuggerListener) iter.next(); 149 listener.environmentSuspended(breakpointEvent); 150 } 151 } 152 synchronized(denv) 153 { 154 try 155 { 156 denv.wait(); 157 } 158 catch(InterruptedException e) 159 { 160 ; } 162 } 163 return denv.isStopped(); 164 } 165 finally 166 { 167 synchronized(suspendedEnvironments) 168 { 169 suspendedEnvironments.remove(denv); 170 } 171 } 172 } 173 174 void registerTemplateSpi(Template template) 175 { 176 String templateName = template.getName(); 177 synchronized(templateDebugInfos) 178 { 179 TemplateDebugInfo tdi = createTemplateDebugInfo(templateName); 180 tdi.templates.add(new TemplateReference(templateName, template, refQueue)); 181 for (Iterator iter = tdi.breakpoints.iterator(); iter.hasNext();) 183 { 184 Breakpoint breakpoint = (Breakpoint) iter.next(); 185 insertDebugBreak(template, breakpoint); 186 } 187 } 188 } 189 190 Collection getSuspendedEnvironments() 191 { 192 return (Collection )suspendedEnvironments.clone(); 193 } 194 195 Object addDebuggerListener(DebuggerListener listener) 196 { 197 Object id; 198 synchronized(listeners) 199 { 200 id = new Long (System.currentTimeMillis()); 201 listeners.put(id, listener); 202 } 203 return id; 204 } 205 206 void removeDebuggerListener(Object id) 207 { 208 synchronized(listeners) 209 { 210 listeners.remove(id); 211 } 212 } 213 214 void addBreakpoint(Breakpoint breakpoint) 215 { 216 String templateName = breakpoint.getTemplateName(); 217 synchronized(templateDebugInfos) 218 { 219 TemplateDebugInfo tdi = createTemplateDebugInfo(templateName); 220 List breakpoints = tdi.breakpoints; 221 int pos = Collections.binarySearch(breakpoints, breakpoint); 222 if(pos < 0) 223 { 224 breakpoints.add(-pos - 1, breakpoint); 226 for (Iterator iter = tdi.templates.iterator(); iter.hasNext();) 228 { 229 TemplateReference ref = (TemplateReference) iter.next(); 230 Template t = ref.getTemplate(); 231 if(t == null) 232 { 233 iter.remove(); 234 } 235 else 236 { 237 insertDebugBreak(t, breakpoint); 238 } 239 } 240 } 241 } 242 } 243 244 private static void insertDebugBreak(Template t, Breakpoint breakpoint) 245 { 246 TemplateElement te = findTemplateElement(t.getRootTreeNode(), breakpoint.getLine()); 247 if(te == null) 248 { 249 return; 250 } 251 TemplateElement parent = (TemplateElement)te.getParent(); 252 DebugBreak db = new DebugBreak(te); 253 parent.setChildAt(parent.getIndex(te), db); 257 } 258 259 private static TemplateElement findTemplateElement(TemplateElement te, int line) 260 { 261 if(te.getBeginLine() > line || te.getEndLine() < line) 262 { 263 return null; 264 } 265 for(Enumeration children = te.children(); children.hasMoreElements();) 267 { 268 TemplateElement child = (TemplateElement)children.nextElement(); 269 TemplateElement childmatch = findTemplateElement(child, line); 270 if(childmatch != null) 271 { 272 return childmatch; 273 } 274 } 275 return te; 277 } 278 279 private TemplateDebugInfo findTemplateDebugInfo(String templateName) 280 { 281 processRefQueue(); 282 return (TemplateDebugInfo)templateDebugInfos.get(templateName); 283 } 284 285 private TemplateDebugInfo createTemplateDebugInfo(String templateName) 286 { 287 TemplateDebugInfo tdi = findTemplateDebugInfo(templateName); 288 if(tdi == null) 289 { 290 tdi = new TemplateDebugInfo(); 291 templateDebugInfos.put(templateName, tdi); 292 } 293 return tdi; 294 } 295 296 void removeBreakpoint(Breakpoint breakpoint) 297 { 298 String templateName = breakpoint.getTemplateName(); 299 synchronized(templateDebugInfos) 300 { 301 TemplateDebugInfo tdi = findTemplateDebugInfo(templateName); 302 if(tdi != null) 303 { 304 List breakpoints = tdi.breakpoints; 305 int pos = Collections.binarySearch(breakpoints, breakpoint); 306 if(pos >= 0) 307 { 308 breakpoints.remove(pos); 309 for (Iterator iter = tdi.templates.iterator(); iter.hasNext();) 310 { 311 TemplateReference ref = (TemplateReference) iter.next(); 312 Template t = ref.getTemplate(); 313 if(t == null) 314 { 315 iter.remove(); 316 } 317 else 318 { 319 removeDebugBreak(t, breakpoint); 320 } 321 } 322 } 323 if(tdi.isEmpty()) 324 { 325 templateDebugInfos.remove(templateName); 326 } 327 } 328 } 329 } 330 331 private void removeDebugBreak(Template t, Breakpoint breakpoint) 332 { 333 TemplateElement te = findTemplateElement(t.getRootTreeNode(), breakpoint.getLine()); 334 if(te == null) 335 { 336 return; 337 } 338 DebugBreak db = null; 339 while(te != null) 340 { 341 if(te instanceof DebugBreak) 342 { 343 db = (DebugBreak)te; 344 break; 345 } 346 te = (TemplateElement)te.getParent(); 347 } 348 if(db == null) 349 { 350 return; 351 } 352 TemplateElement parent = (TemplateElement)db.getParent(); 353 parent.setChildAt(parent.getIndex(db), (TemplateElement)db.getChildAt(0)); 354 } 355 356 void removeBreakpoints(String templateName) 357 { 358 synchronized(templateDebugInfos) 359 { 360 TemplateDebugInfo tdi = findTemplateDebugInfo(templateName); 361 if(tdi != null) 362 { 363 removeBreakpoints(tdi); 364 if(tdi.isEmpty()) 365 { 366 templateDebugInfos.remove(templateName); 367 } 368 } 369 } 370 } 371 372 void removeBreakpoints() 373 { 374 synchronized(templateDebugInfos) 375 { 376 for (Iterator iter = templateDebugInfos.values().iterator(); iter.hasNext();) 377 { 378 TemplateDebugInfo tdi = (TemplateDebugInfo) iter.next(); 379 removeBreakpoints(tdi); 380 if(tdi.isEmpty()) 381 { 382 iter.remove(); 383 } 384 } 385 } 386 } 387 388 private void removeBreakpoints(TemplateDebugInfo tdi) 389 { 390 tdi.breakpoints.clear(); 391 for (Iterator iter = tdi.templates.iterator(); iter.hasNext();) 392 { 393 TemplateReference ref = (TemplateReference) iter.next(); 394 Template t = ref.getTemplate(); 395 if(t == null) 396 { 397 iter.remove(); 398 } 399 else 400 { 401 removeDebugBreaks(t.getRootTreeNode()); 402 } 403 } 404 } 405 406 private void removeDebugBreaks(TemplateElement te) 407 { 408 int count = te.getChildCount(); 409 for(int i = 0; i < count; ++i) 410 { 411 TemplateElement child = (TemplateElement)te.getChildAt(i); 412 while(child instanceof DebugBreak) 413 { 414 TemplateElement dbchild = (TemplateElement)child.getChildAt(0); 415 te.setChildAt(i, dbchild); 416 child = dbchild; 417 } 418 removeDebugBreaks(child); 419 } 420 } 421 422 private static final class TemplateDebugInfo 423 { 424 final List templates = new ArrayList (); 425 final List breakpoints = new ArrayList (); 426 427 boolean isEmpty() 428 { 429 return templates.isEmpty() && breakpoints.isEmpty(); 430 } 431 } 432 433 private static final class TemplateReference extends WeakReference 434 { 435 final String templateName; 436 437 TemplateReference(String templateName, Template template, ReferenceQueue queue) 438 { 439 super(template, queue); 440 this.templateName = templateName; 441 } 442 443 Template getTemplate() 444 { 445 return (Template)get(); 446 } 447 } 448 449 private void processRefQueue() 450 { 451 for(;;) 452 { 453 TemplateReference ref = (TemplateReference)refQueue.poll(); 454 if(ref == null) 455 { 456 break; 457 } 458 TemplateDebugInfo tdi = findTemplateDebugInfo(ref.templateName); 459 if(tdi != null) 460 { 461 tdi.templates.remove(ref); 462 if(tdi.isEmpty()) 463 { 464 templateDebugInfos.remove(ref.templateName); 465 } 466 } 467 } 468 } 469 } 470 | Popular Tags |