001 /* 002 @license.text@ 003 */ 004 package biz.hammurapi.util; 005 006 import java.util.ArrayList; 007 import java.util.Collections; 008 import java.util.HashMap; 009 import java.util.Iterator; 010 import java.util.List; 011 import java.util.Map; 012 013 import org.w3c.dom.Element; 014 import org.w3c.dom.Node; 015 import org.w3c.dom.NodeList; 016 017 import biz.hammurapi.config.ClassAcceptor; 018 import biz.hammurapi.config.Component; 019 import biz.hammurapi.config.ConfigurationException; 020 import biz.hammurapi.config.Context; 021 import biz.hammurapi.config.DomConfigFactory; 022 import biz.hammurapi.config.DomConfigurable; 023 import biz.hammurapi.config.PathNavigator; 024 import biz.hammurapi.xml.dom.DOMUtils; 025 026 027 /** 028 * Simple container 029 * @author Pavel Vlasov 030 * @revision $Revision$ 031 */ 032 public class CompositeWorkerContainer implements Component, DomConfigurable, Worker, Context { 033 private Map workerMap=new HashMap(); 034 private List workers=new ArrayList(); 035 private boolean started; 036 private Object parent; 037 038 private PathNavigator pathNavigator=new PathNavigator(this) { 039 040 protected Object getParent() { 041 return parent; 042 } 043 044 protected Object getChild(String name) { 045 return workerMap.get(name); 046 } 047 048 }; 049 050 051 public CompositeWorkerContainer() { 052 // Default constructor 053 } 054 055 /** 056 * Looks up component in component tree. 057 * @param name 058 * @return 059 */ 060 public Object get(String name) { 061 return pathNavigator.get(name); 062 } 063 064 /** 065 * Adds component and starts it. 066 * @param name 067 * @param worker 068 * @throws ConfigurationException 069 */ 070 private void addWorker(String name, Worker worker) throws ConfigurationException { 071 if (name!=null) { 072 // Remove previous worker 073 Object prevWorkerWithSameName=workerMap.remove(name); 074 if (prevWorkerWithSameName!=null) { 075 workers.remove(prevWorkerWithSameName); 076 if (prevWorkerWithSameName instanceof Component) { 077 if (started) { 078 ((Component) prevWorkerWithSameName).stop(); 079 } 080 ((Component) prevWorkerWithSameName).setOwner(null); 081 } 082 } 083 } 084 085 if (worker!=null) { 086 // Add new worker 087 if (worker instanceof Component) { 088 Component theComponent = (Component) worker; 089 theComponent.setOwner(this); 090 if (started) { 091 theComponent.start(); 092 } 093 } 094 095 if (name!=null) { 096 workerMap.put(name, worker); 097 } 098 099 workers.add(worker); 100 } 101 } 102 103 public void start() throws ConfigurationException { 104 Iterator it=workers.iterator(); 105 while (it.hasNext()) { 106 Object worker = it.next(); 107 if (worker instanceof Component) { 108 ((Component) worker).start(); 109 } 110 } 111 started=true; 112 } 113 114 public void stop() throws ConfigurationException { 115 started=false; 116 List reverseWorkerList=new ArrayList(workers); 117 Collections.reverse(reverseWorkerList); 118 Iterator it=reverseWorkerList.iterator(); 119 while (it.hasNext()) { 120 Object worker = it.next(); 121 if (worker instanceof Component) { 122 ((Component) worker).stop(); 123 } 124 } 125 } 126 127 public void setOwner(Object owner) { 128 parent=owner; 129 } 130 131 public void configure(Node configNode, Context context) throws ConfigurationException { 132 DomConfigFactory factory=new DomConfigFactory(context); 133 try { 134 NodeList nl = DOMUtils.selectNodeList(configNode, "worker|worker-ref"); 135 for (int i=0, l=nl.getLength(); i<l; ++i) { 136 Element we = (Element) nl.item(i); 137 if ("worker".equals(we.getNodeName())) { 138 addWorker( 139 we.hasAttribute("name") ? we.getAttribute("name") : null, 140 (Worker)factory.create( 141 we, 142 new ClassAcceptor() { 143 144 public void accept(Class clazz) throws ConfigurationException { 145 if (!(Worker.class.isAssignableFrom(clazz))) { 146 throw new ConfigurationException(clazz.getName()+" does not implement "+Worker.class+" interface."); 147 } 148 } 149 150 }, 151 null)); 152 } else { 153 String ref = DOMUtils.getElementText(we); 154 Object referencedWorker=get(ref); 155 if (referencedWorker==null) { 156 throw new ConfigurationException("Invalid worker reference: "+ref); 157 } 158 159 if (!(referencedWorker instanceof Worker)) { 160 throw new ConfigurationException(referencedWorker.getClass().getName()+" does not implement "+Worker.class+" interface."); 161 } 162 163 addWorker(we.hasAttribute("name") ? we.getAttribute("name") : null, (Worker) referencedWorker); 164 } 165 } 166 } catch (Exception e) { 167 throw new ConfigurationException(e); 168 } 169 } 170 171 /** 172 * Gives job to workers until one of them accepts it. 173 */ 174 public boolean post(Runnable job) { 175 Iterator it=workers.iterator(); 176 while (it.hasNext()) { 177 Worker worker=(Worker) it.next(); 178 if (worker.post(job)) { 179 return true; 180 } 181 } 182 return false; 183 } 184 }