001 /***************************************************************************** 002 * Copyright (C) PicoContainer Organization. All rights reserved. * 003 * ------------------------------------------------------------------------- * 004 * The software in this package is published under the terms of the BSD * 005 * style license a copy of which has been included with this distribution in * 006 * the LICENSE.txt file. * 007 *****************************************************************************/ 008 package org.picocontainer.visitors; 009 010 import java.util.ArrayList; 011 import java.util.HashSet; 012 import java.util.List; 013 import java.util.Set; 014 015 import org.picocontainer.ComponentAdapter; 016 import org.picocontainer.ComponentFactory; 017 import org.picocontainer.Parameter; 018 import org.picocontainer.PicoContainer; 019 import org.picocontainer.PicoVerificationException; 020 import org.picocontainer.PicoVisitor; 021 022 023 /** 024 * Visitor to verify {@link PicoContainer} instances. The visitor walks down the logical container hierarchy. 025 * 026 * @author Jörg Schaible 027 */ 028 public class VerifyingVisitor extends TraversalCheckingVisitor { 029 030 private final List<RuntimeException> nestedVerificationExceptions; 031 private final Set<ComponentAdapter> verifiedComponentAdapters; 032 private final Set<ComponentFactory> verifiedComponentFactories; 033 private final PicoVisitor componentAdapterCollector; 034 private PicoContainer currentPico; 035 036 /** 037 * Construct a VerifyingVisitor. 038 */ 039 public VerifyingVisitor() { 040 nestedVerificationExceptions = new ArrayList<RuntimeException>(); 041 verifiedComponentAdapters = new HashSet<ComponentAdapter>(); 042 verifiedComponentFactories = new HashSet<ComponentFactory>(); 043 componentAdapterCollector = new ComponentAdapterCollector(); 044 } 045 046 /** 047 * Traverse through all components of the {@link PicoContainer} hierarchy and verify the components. 048 * 049 * @throws PicoVerificationException if some components could not be verified. 050 * @see org.picocontainer.PicoVisitor#traverse(java.lang.Object) 051 */ 052 public Object traverse(Object node) throws PicoVerificationException { 053 nestedVerificationExceptions.clear(); 054 verifiedComponentAdapters.clear(); 055 try { 056 super.traverse(node); 057 if (!nestedVerificationExceptions.isEmpty()) { 058 throw new PicoVerificationException(new ArrayList<RuntimeException>(nestedVerificationExceptions)); 059 } 060 } finally { 061 nestedVerificationExceptions.clear(); 062 verifiedComponentAdapters.clear(); 063 } 064 return Void.TYPE; 065 } 066 067 public boolean visitContainer(PicoContainer pico) { 068 super.visitContainer(pico); 069 currentPico = pico; 070 return CONTINUE_TRAVERSAL; 071 } 072 073 public void visitComponentAdapter(ComponentAdapter<?> componentAdapter) { 074 super.visitComponentAdapter(componentAdapter); 075 if (!verifiedComponentAdapters.contains(componentAdapter)) { 076 try { 077 componentAdapter.verify(currentPico); 078 } catch (RuntimeException e) { 079 nestedVerificationExceptions.add(e); 080 } 081 componentAdapter.accept(componentAdapterCollector); 082 } 083 084 } 085 086 public void visitComponentFactory(ComponentFactory componentFactory) { 087 super.visitComponentFactory(componentFactory); 088 089 if (!verifiedComponentFactories.contains(componentFactory)) { 090 try { 091 componentFactory.verify(currentPico); 092 } catch (RuntimeException e) { 093 nestedVerificationExceptions.add(e); 094 } 095 componentFactory.accept(componentAdapterCollector); 096 } 097 098 } 099 100 101 102 private class ComponentAdapterCollector implements PicoVisitor { 103 // /CLOVER:OFF 104 public Object traverse(Object node) { 105 return null; 106 } 107 108 public boolean visitContainer(PicoContainer pico) { 109 return CONTINUE_TRAVERSAL; 110 } 111 112 // /CLOVER:ON 113 114 public void visitComponentAdapter(ComponentAdapter componentAdapter) { 115 verifiedComponentAdapters.add(componentAdapter); 116 } 117 118 public void visitComponentFactory(ComponentFactory componentFactory) { 119 verifiedComponentFactories.add(componentFactory); 120 } 121 122 public void visitParameter(Parameter parameter) { 123 124 } 125 } 126 }