DispatchingVisitor.java

biz/hammurapi/util/DispatchingVisitor.java

Violations

Inspector Message Severity Location
Java Inspector 048 Copyrights information should be present in each file. 1
Java Inspector 086 Use equals() instead of == or != to compare objects. 1 657:37
Java Inspector 086 Use equals() instead of == or != to compare objects. 1 665:37
Java Inspector 086 Use equals() instead of == or != to compare objects. 1 673:37
Java Inspector 049 Use a Collection instead of arrays Object[] 2 245:41
Java Inspector 049 Use a Collection instead of arrays Object[] 2 540:31
Java Inspector 068 Do not use System.out and System.err to output logging messages. Use loggers instead. 2 307:67
Java Inspector 070-A Cyclomatic complexity is too high: 16, maximum allowed is 12 2 288:17
Java Inspector 070-A Cyclomatic complexity is too high: 17, maximum allowed is 12 2 521:9
Java Inspector 083 Do not use printStackTrace() for exception logging. 2 313:66
Java Inspector 083 Do not use printStackTrace() for exception logging. 2 319:66
Java Inspector 089 Non-private, non-local types shall be documented 2 170:9
Java Inspector 089 Non-private, non-local types shall be documented 2 193:9
Java Inspector 089 Undocumented method 2 203:17
Java Inspector 089 Undocumented method 2 207:17
Java Inspector 089 Undocumented method 2 211:17
Java Inspector 089 Undocumented method 2 216:17
Java Inspector 089 Undocumented method 2 233:17
Java Inspector 089 Undocumented method 2 248:17
Java Inspector 089 Undocumented method 2 337:17
Java Inspector 089 Undocumented method 2 410:17
Java Inspector 089 Undocumented method 2 417:9
Java Inspector 089 Undocumented method 2 421:9
Java Inspector 089 Undocumented method 2 462:9
Java Inspector 089 Method is not properly documented 2 494:9
Java Inspector 089 Undocumented method 2 498:9
Java Inspector 089 Constructor is not properly documented 2 521:9
Java Inspector 089 Parameter targets is not documented 2 521:9
Java Inspector 089 Parameter exceptionSink is not documented 2 521:9
Java Inspector 089 Undocumented parameter listener 2 521:9
Java Inspector 089 Undocumented constructor 2 596:9
Java Inspector 089 Constructor is not properly documented 2 604:9
Java Inspector 089 Parameter target is not documented 2 604:9
Java Inspector 089 Parameter exceptionSink is not documented 2 604:9
Java Inspector 089 Undocumented constructor 2 608:9
Java Inspector 089 Method is not properly documented 2 615:9
Java Inspector 089 Undocumented method 2 619:9
Java Inspector 089 Undocumented method 2 624:9
Java Inspector 089 Parameter target is not documented 2 653:9
Java Inspector 089 Undocumented parameter executionContext 2 685:9
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 217:32
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 217:59
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 217:71
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 217:95
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 249:53
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 249:63
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 249:74
Java Inspector 026 Avoid hardwired string literals. Allowed literals: [] 3 307:75
Java Inspector 040 Parameter name handlers clashes with field name in DispatchingVisitor 3 581:36
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 267:17
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 521:9
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 596:9
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 604:9
Java Inspector 051 It is good practice to call in any case super() in a constructor. 3 608:9
Java Inspector 090 Unnecessary else part in if. The main part terminates control flow (return, break, throw, or continue). 3 325:41
Java Inspector 090 Unnecessary else part in if. The main part terminates control flow (return, break, throw, or continue). 3 349:41
Java Inspector 090 Unnecessary else part in if. The main part terminates control flow (return, break, throw, or continue). 3 351:48

Source code

1/*
2 * hgcommons 9
3 * Hammurapi Group Common Library
4 * Copyright (C) 2003 Hammurapi Group
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
21 * e-Mail: support@hammurapi.biz
22 */
23package biz.hammurapi.util;
24
25import java.lang.reflect.Array;
26import java.lang.reflect.InvocationTargetException;
27import java.lang.reflect.Method;
28import java.util.ArrayList;
29import java.util.Arrays;
30import java.util.Collection;
31import java.util.Collections;
32import java.util.HashMap;
33import java.util.IdentityHashMap;
34import java.util.Iterator;
35import java.util.LinkedList;
36import java.util.List;
37import java.util.Map;
38
39import biz.hammurapi.config.Command;
40
41/**
42 * Dispatching visitor navigates through Visitables hierarchy and
43 * invokes visit(<I>Type</I>) method of targets with compatible <I>Type</I>.
44 * @author Pavel Vlasov
45 * @version $Revision: 1.9 $
46 */
47public class DispatchingVisitor implements PoliteVisitor, VisitorStackSource, Command {
48 private static final String APPROVE = "approve";
49 private static final String VERIFY = "verify";
50 private static final String LEAVE = "leave";
51 private static final String VISIT = "visit";
52 private Collection targets;
53 private VisitorExceptionSink exceptionSink;
54 private Map handlers=new HashMap();
55 private Map leaveHandlers=new HashMap();
56 private Map verifyHandlers=new HashMap();
57 private Map filterHandlers=new HashMap();
58 private Collection listeners=new ArrayList();
59 private Collection classesOfInterest=new ArrayList();
60 private Collection unmodifiableClassesOfInterest=Collections.unmodifiableCollection(classesOfInterest);
61
62 private Collection handlerList=new ArrayList();
63 private Collection leaveHandlerList=new ArrayList();
64 private Collection verifyHandlerList=new ArrayList();
65 private Collection filterHandlerList=new ArrayList();
66
67 /**
68 * @param clazz
69 * @return handlers for class.
70 */
71 private Collection getHandlers(Class clazz) {
72 synchronized (handlers) {
73 List ret=(List) handlers.get(clazz);
74 if (ret==null) {
75 ret=new ArrayList();
76 handlers.put(clazz, ret);
77 Iterator it=handlerList.iterator();
78 while (it.hasNext()) {
79 InvocationHandler handler=(InvocationHandler) it.next();
80 if (handler.method.getParameterTypes()[0].isAssignableFrom(clazz)) {
81 ret.add(handler);
82 }
83 }
84 Collections.sort(ret);
85 }
86 return ret;
87 }
88 }
89
90 /**
91 * @param clazz
92 * @return leave handlers for class
93 */
94 private Collection getLeaveHandlers(Class clazz) {
95 synchronized (leaveHandlers) {
96 List ret=(List) leaveHandlers.get(clazz);
97 if (ret==null) {
98 ret=new ArrayList();
99 leaveHandlers.put(clazz, ret);
100 Iterator it=leaveHandlerList.iterator();
101 while (it.hasNext()) {
102 InvocationHandler handler=(InvocationHandler) it.next();
103 if (handler.method.getParameterTypes()[0].isAssignableFrom(clazz)) {
104 ret.add(handler);
105 }
106 }
107 Collections.sort(ret);
108 Collections.reverse(ret);
109 }
110 return ret;
111 }
112 }
113
114 /**
115 * @param clazz
116 * @return leave handlers for class
117 */
118 private Collection getVerifyHandlers(Class clazz) {
119 synchronized (verifyHandlers) {
120 List ret=(List) verifyHandlers.get(clazz);
121 if (ret==null) {
122 ret=new ArrayList();
123 verifyHandlers.put(clazz, ret);
124 Iterator it=verifyHandlerList.iterator();
125 while (it.hasNext()) {
126 InvocationHandler handler=(InvocationHandler) it.next();
127 if (handler.method.getParameterTypes()[0].isAssignableFrom(clazz)) {
128 ret.add(handler);
129 }
130 }
131 Collections.sort(ret);
132 Collections.reverse(ret);
133 }
134 return ret;
135 }
136 }
137
138 /**
139 * @param clazz
140 * @return filter handlers for class.
141 */
142 private Collection getFilterHandlers(Class clazz) {
143 synchronized (filterHandlers) {
144 List ret=(List) filterHandlers.get(clazz);
145 if (ret==null) {
146 ret=new ArrayList();
147 filterHandlers.put(clazz, ret);
148 Iterator it=filterHandlerList.iterator();
149 while (it.hasNext()) {
150 InvocationHandler handler=(InvocationHandler) it.next();
151 if (handler.method.getParameterTypes()[0].isAssignableFrom(clazz)) {
152 ret.add(handler);
153 }
154 }
155 }
156 return ret;
157 }
158 }
159
160 /**
161 * Targets which want to listen to invocations of self should implement
162 * this interface.
163 * @author Pavel Vlasov
164 * @revision $Revision: 1.9 $
165 */
166 public interface SelfListener {
167 void onInvocation(Method method, Object visitable);
168 }
169
170 public interface Listener {
171 void onInvocationRegistration(Object target, Method method);
172 void onTargetRegistration(Object target);
173 void onFilterRegistration(Method filter, Method target);
174 void noInvocationsWarning(Object target);
175 void onInvocation(Object target, Method method, Object visitable);
176 void onVisit(Object target);
177 void onLeave(Object target);
178 }
179
180 /**
181 * If target implements this insterface then it is used to
182 * filter invocations to other targets. approve() method(s) of
183 * this target, if any, will be invoked before invocation of
184 * visit()/leave() methods of filtered target.
185 *
186 * @author Pavel Vlasov
187 * @version $Revision: 1.9 $
188 */
189 public interface Filter {
190 Collection getTargets();
191 }
192
193 public interface Stats {
194 long getVisits();
195 long getInvocations();
196 void reset();
197 }
198
199 private static class StatsImpl implements Stats {
200 private long visits;
201 private long invocations;
202
203 public long getVisits() {
204 return visits;
205 }
206
207 public long getInvocations() {
208 return invocations;
209 }
210
211 public void reset() {
212 visits=0;
213 invocations=0;
214 }
215
216 public String toString() {
217 return "["+Thread.currentThread()+"] "+visits+" visits, "+invocations+" invocations";
218 }
219
220 synchronized void addVisit() {
221 visits++;
222 }
223
224 synchronized void addInvocation() {
225 invocations++;
226 }
227
228 }
229
230 private int handlerCounter;
231 private StatsImpl stats=new StatsImpl();
232 private ThreadLocal threadStats=new ThreadLocal() {
233 protected Object initialValue() {
234 return new StatsImpl();
235 }
236 };
237
238 private class InvocationHandler implements Comparable {
239 boolean active=true;
240 Method method;
241 Object object;
242 int position=handlerCounter++;
243 int order;
244 List filtersList=new LinkedList();
245 ApproveInvocationHandler[] filters;
246 boolean returnsValue;
247
248 public String toString() {
249 return getClass().getName()+"["+order+" "+method+"]";
250 }
251
252 void addFilter(ApproveInvocationHandler filter) {
253 filtersList.add(filter);
254 Iterator it=listeners.iterator();
255 while (it.hasNext()) {
256 ((Listener) it.next()).onFilterRegistration(filter.method, method);
257 }
258 }
259
260 void commitFilters() {
261 filters=null;
262 if (!filtersList.isEmpty()) {
263 filters=(ApproveInvocationHandler[]) filtersList.toArray(new ApproveInvocationHandler[filtersList.size()]);
264 }
265 }
266
267 InvocationHandler(Method method, Object object) {
268 Iterator it=listeners.iterator();
269 while (it.hasNext()) {
270 ((Listener) it.next()).onInvocationRegistration(object, method);
271 }
272
273 this.method=method;
274 this.object=object;
275 this.returnsValue=!(void.class.equals(method.getReturnType()) || boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType()));
276
277 addClassOfInterest(method.getParameterTypes()[0]);
278
279 if (object instanceof OrderedTarget) {
280 Integer ret=((OrderedTarget) object).getOrder();
281 if (ret!=null) {
282 order=ret.intValue();
283 }
284 }
285
286 }
287
288 Object invoke(Object arg) {
289 if (active) {
290 for (int i=0; filters!=null && i<filters.length; i++) {
291 if (Boolean.FALSE.equals(filters[i].invoke(arg))) {
292 return null;
293 }
294 }
295 try {
296 Iterator it=listeners.iterator();
297 while (it.hasNext()) {
298 ((Listener) it.next()).onInvocation(object, method, arg);
299 }
300 stats.addInvocation();
301 ((StatsImpl) threadStats.get()).addInvocation();
302 if (object instanceof SelfListener) {
303 ((SelfListener) object).onInvocation(method, arg);
304 }
305
306 if (!method.getParameterTypes()[0].isInstance(arg)) {
307 System.err.println(method+", "+arg.getClass());
308 }
309
310 return method.invoke(object, new Object[] {arg});
311 } catch (IllegalArgumentException e) {
312 if (exceptionSink==null) {
313 e.printStackTrace();
314 } else {
315 exceptionSink.consume(DispatchingVisitor.this, object, method, arg, e);
316 }
317 } catch (IllegalAccessException e) {
318 if (exceptionSink==null) {
319 e.printStackTrace();
320 } else {
321 exceptionSink.consume(DispatchingVisitor.this, object, method, arg, e);
322 }
323 } catch (InvocationTargetException e) {
324 Throwable targetException = e.getTargetException();
325 if (targetException instanceof Error) {
326 throw (Error) targetException;
327 } else if (exceptionSink==null) {
328 targetException.printStackTrace();
329 } else {
330 exceptionSink.consume(DispatchingVisitor.this, object, method, arg, targetException instanceof Exception ? (Exception) targetException : e);
331 }
332 }
333 }
334 return null;
335 }
336
337 public int compareTo(Object o) {
338 if (this==o) {
339 return 0;
340 }
341 InvocationHandler ih=(InvocationHandler) o;
342 if (order==ih.order) {
343 if (position==ih.position) {
344 Class c=method.getParameterTypes()[0];
345 Class ihc=ih.method.getParameterTypes()[0];
346 if (c.equals(ihc)) {
347 return method.getDeclaringClass().getName().compareTo(ih.method.getDeclaringClass().getName());
348 }
349 if (c.isAssignableFrom(ihc)) {
350 return -1;
351 } else if (ihc.isAssignableFrom(c)) {
352 return 1;
353 } else {
354 int idc=inheritanceDepth(c);
355 int ihidc=inheritanceDepth(ihc);
356 if (idc==ihidc) {
357 return method.getDeclaringClass().getName().compareTo(ih.method.getDeclaringClass().getName());
358 }
359 return idc-ihidc;
360 }
361 }
362 return position-ih.position;
363 }
364 return order==ih.order ? 0 : order>ih.order ? 1 : -1;
365 }
366 }
367
368 private int inheritanceDepth(Class clazz) {
369 if (clazz==null || Object.class.equals(clazz)) {
370 return 0;
371 }
372 int ret=0;
373 ret=Math.max(ret, inheritanceDepth(clazz.getSuperclass()));
374 for (int i=0, j=clazz.getInterfaces().length; i<j; i++) {
375 ret=Math.max(ret, inheritanceDepth(clazz.getInterfaces()[i]));
376 }
377 return ret+1;
378 }
379
380 private class ApproveInvocationHandler extends InvocationHandler {
381 private Class parameterType;
382
383 ApproveInvocationHandler(Method method, Object object) {
384 super(method, object);
385 parameterType=method.getParameterTypes()[0];
386 }
387
388 Map results=new IdentityHashMap();
389
390 Object invoke(Object arg) {
391 if (!parameterType.isInstance(arg)) {
392 return null; // Incompatible parameter.
393 }
394
395 if (results.containsKey(arg)) {
396 return results.get(arg);
397 }
398 Object ret=super.invoke(arg);
399 results.put(arg, ret);
400 return ret;
401 }
402
403 void remove(Object key) {
404 results.remove(key);
405 }
406 }
407
408 private ThreadLocal visitorStackTL=new ThreadLocal() {
409
410 protected Object initialValue() {
411 return new VisitorStack();
412 }
413 };
414
415 private int size;
416
417 public VisitorStack getVisitorStack() {
418 return (VisitorStack) visitorStackTL.get();
419 }
420
421 public boolean visit(Object target) {
422 getVisitorStack().push(target);
423 Iterator lit=listeners.iterator();
424 while (lit.hasNext()) {
425 ((Listener) lit.next()).onVisit(target);
426 }
427
428 if (handlerList.isEmpty()) {
429 return false;
430 }
431
432 stats.addVisit();
433 ((StatsImpl) threadStats.get()).addVisit();
434
435 if (target!=null) {
436 // Verify target first.
437 Iterator it=getVerifyHandlers(target.getClass()).iterator();
438 while (it.hasNext()) {
439 if (Boolean.FALSE.equals(((InvocationHandler) it.next()).invoke(target))) {
440 return false;
441 }
442 }
443
444 // Invoke visit methods.
445 it=getHandlers(target.getClass()).iterator();
446 while (it.hasNext()) {
447 InvocationHandler ih=(InvocationHandler) it.next();
448 Object ret=ih.invoke(target);
449 if (Boolean.FALSE.equals(ret)) {
450 return false;
451 }
452
453 if (ret!=null && ih.returnsValue) {
454 processReturnValue(ih.object, ih.method, target, ret);
455 }
456 }
457 }
458
459 return true;
460 }
461
462 public Collection getTargets() {
463 return targets;
464 }
465
466 /**
467 * Passes return values back to visitor.
468 * Arrays and collections are iterated and individual elements are passed to the visitor.
469 * Override this method to process return values in a different way.
470 * @param target - Object which method was invoked
471 * @param method - Method which was invoked
472 * @param argument - Method argument
473 * @param returnValue - Return value
474 */
475 protected void processReturnValue(Object target, Method method, Object argument, Object returnValue) {
476 if (returnValue instanceof Collection) {
477 Iterator it=((Collection) returnValue).iterator();
478 while (it.hasNext()) {
479 VisitableBase.object2visitor(it.next(), this);
480 }
481 } else if (returnValue.getClass().isArray()) {
482 for (int i=0,l=Array.getLength(returnValue);i<l;i++) {
483 VisitableBase.object2visitor(Array.get(returnValue, i), this);
484 }
485 } else {
486 VisitableBase.object2visitor(returnValue, this);
487 }
488 }
489
490 /**
491 *
492 * @return total number of handlers
493 */
494 public int size() {
495 return size;
496 }
497
498 public Collection getClassesOfInterest() {
499 return unmodifiableClassesOfInterest;
500 }
501
502 private void addClassOfInterest(Class clazz) {
503 Iterator it=classesOfInterest.iterator();
504 while (it.hasNext()) {
505 Class cls=(Class) it.next();
506 if (cls.isAssignableFrom(clazz)) {
507 return;
508 }
509
510 if (clazz.isAssignableFrom(cls)) {
511 it.remove();
512 }
513 }
514 classesOfInterest.add(clazz);
515 }
516
517 /**
518 * @param targets
519 * @param exceptionSink
520 */
521 public DispatchingVisitor(Collection targets, VisitorExceptionSink exceptionSink, Listener listener) {
522 if (listener!=null) {
523 listeners.add(listener);
524 }
525 this.targets = Collections.unmodifiableList(new LinkedList(targets));
526 this.exceptionSink = exceptionSink;
527 Iterator it=targets.iterator();
528 while (it.hasNext()) {
529 Object target=it.next();
530 if (target instanceof DispatcherAware) {
531 ((DispatcherAware) target).setDispatcher(this);
532 }
533
534 Iterator lit=listeners.iterator();
535 while (lit.hasNext()) {
536 ((Listener) lit.next()).onTargetRegistration(target);
537 }
538
539 boolean hasInvocations=false;
540 Method[] methods=target.getClass().getMethods();
541 for (int i=0; i<methods.length; i++) {
542 if (methods[i].getParameterTypes().length == 1) {
543 Class returnType = methods[i].getReturnType();
544 if (VISIT.equals(methods[i].getName()) && (void.class.equals(returnType) || boolean.class.equals(returnType))) {
545 handlerList.add(new InvocationHandler(methods[i], target));
546 hasInvocations=true;
547 } else if (LEAVE.equals(methods[i].getName()) && void.class.equals(returnType)) {
548 leaveHandlerList.add(new InvocationHandler(methods[i], target));
549 hasInvocations=true;
550 } else if (boolean.class.equals(returnType) && VERIFY.equals(methods[i].getName())) {
551 verifyHandlerList.add(new InvocationHandler(methods[i], target));
552 hasInvocations=true;
553 } else if (target instanceof Filter && !((Filter) target).getTargets().isEmpty() && APPROVE.equals(methods[i].getName()) && boolean.class.equals(returnType)) {
554 filterHandlerList.add(new ApproveInvocationHandler(methods[i], target));
555 hasInvocations=true;
556 }
557 }
558 }
559
560 if (!hasInvocations) {
561 lit=listeners.iterator();
562 while (lit.hasNext()) {
563 ((Listener) lit.next()).noInvocationsWarning(target);
564 }
565 }
566
567 if (target instanceof Listener) {
568 listeners.add(target);
569 }
570 }
571
572 assignFilters(handlerList);
573 assignFilters(leaveHandlerList);
574
575 size = handlerList.size()+leaveHandlerList.size();
576 }
577
578 /**
579 *
580 */
581 private void assignFilters(Collection handlers) {
582 Iterator it=handlers.iterator();
583 while (it.hasNext()) {
584 InvocationHandler handler=(InvocationHandler) it.next();
585 Iterator fit=filterHandlerList.iterator();
586 while (fit.hasNext()) {
587 ApproveInvocationHandler approveHandler=(ApproveInvocationHandler) fit.next();
588 if (((Filter) approveHandler.object).getTargets().contains(handler.object)) {
589 handler.addFilter(approveHandler);
590 }
591 }
592 handler.commitFilters();
593 }
594 }
595
596 public DispatchingVisitor(Collection targets, VisitorExceptionSink exceptionSink) {
597 this(targets, exceptionSink, null);
598 }
599
600 /**
601 * @param target
602 * @param exceptionSink
603 */
604 public DispatchingVisitor(Object target, VisitorExceptionSink exceptionSink) {
605 this(Arrays.asList(new Object[] {target}), exceptionSink);
606 }
607
608 public DispatchingVisitor(Object target, VisitorExceptionSink exceptionSink, Listener listener) {
609 this(Arrays.asList(new Object[] {target}), exceptionSink, listener);
610 }
611
612 /**
613 * @return Returns visitor statistics.
614 */
615 public Stats getStats() {
616 return stats;
617 }
618
619 public Stats getThreadStats() {
620 Stats ret = (Stats) threadStats.get();
621 return ret;
622 }
623
624 public void leave(Object target) {
625 Iterator lit=listeners.iterator();
626 while (lit.hasNext()) {
627 ((Listener) lit.next()).onLeave(target);
628 }
629
630 if (target!=null) {
631 Iterator it=getLeaveHandlers(target.getClass()).iterator();
632 while (it.hasNext()) {
633 InvocationHandler ih=(InvocationHandler) it.next();
634 Object ret=ih.invoke(target);
635
636 if (ret!=null && ih.returnsValue) {
637 processReturnValue(ih.object, ih.method, target, ret);
638 }
639 }
640
641 it=getFilterHandlers(target.getClass()).iterator();
642 while (it.hasNext()) {
643 ((ApproveInvocationHandler) it.next()).remove(target);
644 }
645 }
646 getVisitorStack().pop(target);
647 }
648
649 /**
650 * Removes object from targets collection.
651 * @param target
652 */
653 public void remove(Object target) {
654 Iterator it=handlerList.iterator();
655 while (it.hasNext()) {
656 InvocationHandler h=(InvocationHandler) it.next();
657 if (h.object==target) {
658 h.active=false;
659 }
660 }
661
662 it=leaveHandlerList.iterator();
663 while (it.hasNext()) {
664 InvocationHandler h=(InvocationHandler) it.next();
665 if (h.object==target) {
666 h.active=false;
667 }
668 }
669
670 it=verifyHandlerList.iterator();
671 while (it.hasNext()) {
672 InvocationHandler h=(InvocationHandler) it.next();
673 if (h.object==target) {
674 h.active=false;
675 }
676 }
677 }
678
679 /**
680 * Passes executionContext for visiting.
681 * Subclasses can override this method and
682 * queue object for execution and invoke
683 * accept/visit in a different thread.
684 */
685 public void execute(Object executionContext) {
686 if (executionContext instanceof Visitable) {
687 ((Visitable) executionContext).accept(this);
688 } else {
689 visit(executionContext);
690 }
691 }
692}
693