001: /*
002: * hgcommons 7
003: * Hammurapi Group Common Library
004: * Copyright (C) 2003 Hammurapi Group
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2 of the License, or (at your option) any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: *
020: * URL: http://www.hammurapi.biz/hammurapi-biz/ef/xmenu/hammurapi-group/products/products/hgcommons/index.html
021: * e-Mail: support@hammurapi.biz
022: */
023: package biz.hammurapi.util;
024:
025: import java.util.ArrayList;
026: import java.util.Collections;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.List;
030: import java.util.Map;
031:
032: import javax.xml.transform.TransformerException;
033:
034: import org.apache.xpath.XPathAPI;
035: import org.w3c.dom.Element;
036: import org.w3c.dom.Node;
037: import org.w3c.dom.traversal.NodeIterator;
038:
039: import biz.hammurapi.config.ClassAcceptor;
040: import biz.hammurapi.config.Component;
041: import biz.hammurapi.config.ConfigurationException;
042: import biz.hammurapi.config.Context;
043: import biz.hammurapi.config.DomConfigFactory;
044: import biz.hammurapi.config.DomConfigurable;
045: import biz.hammurapi.config.PathNavigator;
046: import biz.hammurapi.xml.dom.DOMUtils;
047:
048: /**
049: * Simple container
050: * @author Pavel Vlasov
051: * @revision $Revision$
052: */
053: public class CompositeWorkerContainer implements Component,
054: DomConfigurable, Worker, Context {
055: private Map workerMap = new HashMap();
056: private List workers = new ArrayList();
057: private boolean started;
058: private Object parent;
059:
060: private PathNavigator pathNavigator = new PathNavigator(this ) {
061:
062: protected Object getParent() {
063: return parent;
064: }
065:
066: protected Object getChild(String name) {
067: return workerMap.get(name);
068: }
069:
070: };
071:
072: public CompositeWorkerContainer() {
073: // Default constructor
074: }
075:
076: /**
077: * Looks up component in component tree.
078: * @param name
079: * @return
080: */
081: public Object get(String name) {
082: return pathNavigator.get(name);
083: }
084:
085: /**
086: * Adds component and starts it.
087: * @param name
088: * @param worker
089: * @throws ConfigurationException
090: */
091: private void addWorker(String name, Worker worker)
092: throws ConfigurationException {
093: if (name != null) {
094: // Remove previous worker
095: Object prevWorkerWithSameName = workerMap.remove(name);
096: if (prevWorkerWithSameName != null) {
097: workers.remove(prevWorkerWithSameName);
098: if (prevWorkerWithSameName instanceof Component) {
099: if (started) {
100: ((Component) prevWorkerWithSameName).stop();
101: }
102: ((Component) prevWorkerWithSameName).setOwner(null);
103: }
104: }
105: }
106:
107: if (worker != null) {
108: // Add new worker
109: if (worker instanceof Component) {
110: Component theComponent = (Component) worker;
111: theComponent.setOwner(this );
112: if (started) {
113: theComponent.start();
114: }
115: }
116:
117: if (name != null) {
118: workerMap.put(name, worker);
119: }
120:
121: workers.add(worker);
122: }
123: }
124:
125: public void start() throws ConfigurationException {
126: Iterator it = workers.iterator();
127: while (it.hasNext()) {
128: Object worker = it.next();
129: if (worker instanceof Component) {
130: ((Component) worker).start();
131: }
132: }
133: started = true;
134: }
135:
136: public void stop() throws ConfigurationException {
137: started = false;
138: List reverseWorkerList = new ArrayList(workers);
139: Collections.reverse(reverseWorkerList);
140: Iterator it = reverseWorkerList.iterator();
141: while (it.hasNext()) {
142: Object worker = it.next();
143: if (worker instanceof Component) {
144: ((Component) worker).stop();
145: }
146: }
147: }
148:
149: public void setOwner(Object owner) {
150: parent = owner;
151: }
152:
153: public void configure(Node configNode, Context context)
154: throws ConfigurationException {
155: DomConfigFactory factory = new DomConfigFactory(context);
156: try {
157: NodeIterator nit = XPathAPI.selectNodeIterator(configNode,
158: "worker|worker-ref");
159: Element we;
160: while ((we = (Element) nit.nextNode()) != null) {
161: if ("worker".equals(we.getNodeName())) {
162: addWorker(we.hasAttribute("name") ? we
163: .getAttribute("name") : null,
164: (Worker) factory.create(we,
165: new ClassAcceptor() {
166:
167: public void accept(Class clazz)
168: throws ConfigurationException {
169: if (!(Worker.class
170: .isAssignableFrom(clazz))) {
171: throw new ConfigurationException(
172: clazz.getName()
173: + " does not implement "
174: + Worker.class
175: + " interface.");
176: }
177: }
178:
179: }, null));
180: } else {
181: String ref = DOMUtils.getElementText(we);
182: Object referencedWorker = get(ref);
183: if (referencedWorker == null) {
184: throw new ConfigurationException(
185: "Invalid worker reference: " + ref);
186: }
187:
188: if (!(referencedWorker instanceof Worker)) {
189: throw new ConfigurationException(
190: referencedWorker.getClass().getName()
191: + " does not implement "
192: + Worker.class + " interface.");
193: }
194:
195: addWorker(we.hasAttribute("name") ? we
196: .getAttribute("name") : null,
197: (Worker) referencedWorker);
198: }
199: }
200: } catch (TransformerException e) {
201: throw new ConfigurationException(e);
202: }
203: }
204:
205: /**
206: * Gives job to workers until one of them accepts it.
207: */
208: public boolean post(Runnable job) {
209: Iterator it = workers.iterator();
210: while (it.hasNext()) {
211: Worker worker = (Worker) it.next();
212: if (worker.post(job)) {
213: return true;
214: }
215: }
216: return false;
217: }
218: }
|