001 package biz.hammurapi.config; 002 003 import java.util.ArrayList; 004 import java.util.Collection; 005 import java.util.Collections; 006 import java.util.Iterator; 007 import java.util.LinkedHashMap; 008 import java.util.List; 009 import java.util.Map; 010 import java.util.Set; 011 012 import biz.hammurapi.metrics.MeasurementCollector; 013 import biz.hammurapi.metrics.MeasurementConsumer; 014 import biz.hammurapi.util.Attributable; 015 import biz.hammurapi.util.CollectionVisitable; 016 import biz.hammurapi.util.VisitableBase; 017 import biz.hammurapi.util.Visitor; 018 019 public class GenericContainer extends VisitableBase implements Component, Command, Attributable, Context, MeasurementCollector, MeasurementConsumer { 020 021 private Map componentMap = new LinkedHashMap(); 022 023 protected Map getComponentMap() { 024 return componentMap; 025 } 026 027 private boolean started; 028 private Object owner; 029 030 private PathNavigator pathNavigator = new PathNavigator(this) { 031 032 protected Object getParent() { 033 return owner; 034 } 035 036 protected Object getChild(String name) { 037 return componentMap.get(name); 038 } 039 040 }; 041 042 private LinkedHashMap attributes = new LinkedHashMap(); 043 private MeasurementConsumer measurementConsumer; 044 045 /** 046 * Looks up component in component tree. 047 * @param name 048 * @return 049 */ 050 public Object get(String name) { 051 return pathNavigator.get(name); 052 } 053 054 /** 055 * Adds component and starts it. 056 * @param name 057 * @param component 058 * @throws ConfigurationException 059 */ 060 public void addComponent(String name, Object component) throws ConfigurationException { 061 if (name==null) { 062 name = "Anonymous component "+componentMap.size(); 063 } 064 065 // Remove previous component 066 Object prevComponent=componentMap.remove(name); 067 if (prevComponent!=null) { 068 if (prevComponent instanceof Component) { 069 if (started) { 070 ((Component) prevComponent).stop(); 071 } 072 ((Component) prevComponent).setOwner(null); 073 } 074 075 if (prevComponent instanceof MeasurementCollector) { 076 ((MeasurementCollector) prevComponent).setMeasurementConsumer(null); 077 } 078 } 079 080 if (component!=null) { 081 if (component instanceof MeasurementCollector) { 082 final String componentName = name; 083 MeasurementConsumer cmc = new MeasurementConsumer() { 084 public void addMeasurement(String mName, double value, long time) { 085 if (measurementConsumer!=null) { 086 measurementConsumer.addMeasurement(componentName+"."+mName, value, time==0 ? System.currentTimeMillis() : time); 087 } 088 } 089 }; 090 ((MeasurementCollector) component).setMeasurementConsumer(cmc); 091 } 092 093 if (component instanceof NamedComponent) { 094 ((NamedComponent) component).setName(name); 095 } 096 097 // Add new component 098 if (component instanceof Component) { 099 Component theComponent = (Component) component; 100 theComponent.setOwner(this); 101 if (started) { 102 theComponent.start(); 103 } 104 } 105 106 if (name!=null) { 107 componentMap.put(name, component); 108 } 109 110 } 111 } 112 113 public void start() throws ConfigurationException { 114 if (getMeasurementConsumer() instanceof Component) { 115 ((Component) getMeasurementConsumer()).start(); 116 } 117 118 Iterator it=componentMap.values().iterator(); 119 while (it.hasNext()) { 120 Object component = it.next(); 121 if (component instanceof Component) { 122 ((Component) component).start(); 123 } 124 } 125 started=true; 126 } 127 128 public void stop() throws ConfigurationException { 129 started=false; 130 List reverseComponentList=new ArrayList(componentMap.values()); 131 Collections.reverse(reverseComponentList); 132 Iterator it=reverseComponentList.iterator(); 133 while (it.hasNext()) { 134 Object component = it.next(); 135 if (component instanceof Component) { 136 ((Component) component).stop(); 137 } 138 } 139 if (getMeasurementConsumer() instanceof Component) { 140 ((Component) getMeasurementConsumer()).stop(); 141 } 142 } 143 144 public void setOwner(Object owner) { 145 this.owner=owner; 146 } 147 148 /** 149 * Invokes execute() of executable components sequentially. 150 */ 151 public void execute(Object executionContext) { 152 Iterator it=componentMap.values().iterator(); 153 while (it.hasNext()) { 154 Object component = it.next(); 155 if (component instanceof Command) { 156 ((Command) component).execute(executionContext); 157 } 158 } 159 } 160 161 protected void acceptChildren(Visitor visitor) { 162 new CollectionVisitable(componentMap.values(), false).accept(visitor); 163 } 164 165 protected Collection getComponents() { 166 return componentMap.values(); 167 } 168 169 public Set getComponentNames() { 170 return Collections.unmodifiableSet(componentMap.keySet()); 171 } 172 173 public void setAttribute(Object key, Object value) { 174 attributes.put(key, value); 175 } 176 177 public Object getAttribute(Object key) { 178 return attributes.get(key); 179 } 180 181 public Object removeAttribute(Object key) { 182 return attributes.remove(key); 183 } 184 185 public void setMeasurementConsumer(MeasurementConsumer measurementConsumer) { 186 this.measurementConsumer = measurementConsumer; 187 if (measurementConsumer instanceof Component) { 188 ((Component) measurementConsumer).setOwner(this); 189 } 190 } 191 192 public MeasurementConsumer getMeasurementConsumer() { 193 return measurementConsumer; 194 } 195 196 public void addMeasurement(String name, double value, long time) { 197 if (measurementConsumer!=null) { 198 measurementConsumer.addMeasurement(name, value, time); 199 } 200 } 201 202 /** 203 * Finds component owner of particular type. 204 * @param ownerType 205 * @return Owner which is an instance of specified type or null if no such owner is found. 206 */ 207 public Object getOwner(Class ownerType) { 208 if (owner==null || ownerType.isInstance(owner)) { 209 return owner; 210 } 211 212 if (owner instanceof ComponentBase) { 213 return ((ComponentBase) owner).getOwner(ownerType); 214 } 215 216 if (owner instanceof GenericContainer) { 217 return ((GenericContainer) owner).getOwner(ownerType); 218 } 219 220 return null; 221 } 222 }