001: package biz.hammurapi.rules.jsr94;
002:
003: import java.io.File;
004: import java.io.IOException;
005: import java.util.HashMap;
006: import java.util.Map;
007:
008: import javax.rules.ConfigurationException;
009: import javax.rules.RuleRuntime;
010: import javax.rules.RuleServiceProviderManager;
011: import javax.rules.admin.RuleAdministrator;
012: import javax.xml.parsers.FactoryConfigurationError;
013: import javax.xml.parsers.ParserConfigurationException;
014: import javax.xml.transform.TransformerException;
015:
016: import org.apache.xpath.XPathAPI;
017: import org.w3c.dom.Document;
018: import org.w3c.dom.Element;
019: import org.w3c.dom.Node;
020: import org.w3c.dom.traversal.NodeIterator;
021: import org.xml.sax.SAXException;
022:
023: import biz.hammurapi.config.DomConfigFactory;
024: import biz.hammurapi.rules.jsr94.admin.FileRuleAdministrator;
025: import biz.hammurapi.xml.dom.AbstractDomObject;
026: import biz.hammurapi.xml.dom.DOMUtils;
027: import biz.hammurapi.xml.dom.DomSerializable;
028:
029: /**
030: * This rule service provider reads configuration from XML files.
031: * XML definitions are read from rules home directory. By default it is <code>.hammurapi-rules</code> directory
032: * in user home directory. This can be changed by setting <code>biz.hammurapi.rules.jsr94.FileRuleServiceProvider:home</code>
033: * property to custom rules home directory name.
034: * @author Pavel Vlasov
035: * @version ${Revision}
036: */
037: public class FileRuleServiceProvider extends
038: javax.rules.RuleServiceProvider {
039: private static String home;
040:
041: static {
042: try {
043: RuleServiceProviderManager
044: .registerRuleServiceProvider(
045: "biz.hammurapi.rules.jsr94.FileRuleServiceProvider",
046: biz.hammurapi.rules.jsr94.FileRuleServiceProvider.class);
047: } catch (ConfigurationException e) {
048: System.err
049: .println("Could not register biz.hammurapi.rules.jsr94.FileRuleServiceProvider");
050: e.printStackTrace();
051: }
052:
053: home = System
054: .getProperty(biz.hammurapi.rules.jsr94.FileRuleServiceProvider.class
055: .getName()
056: + ":home");
057: }
058:
059: /**
060: * Registration entry
061: * @author Pavel Vlasov
062: * @version ${Revision}
063: */
064: public static class Registration implements DomSerializable {
065: private String uri;
066:
067: /**
068: * @return Returns the uri.
069: */
070: public String getUri() {
071: return uri;
072: }
073:
074: /**
075: * @param uri The uri to set.
076: */
077: public void setUri(String uri) {
078: this .uri = uri;
079: }
080:
081: private String ref;
082:
083: /**
084: * @return Returns the ref.
085: */
086: public String getRef() {
087: return ref;
088: }
089:
090: /**
091: * @param ref The ref to set.
092: */
093: public void setRef(String ref) {
094: this .ref = ref;
095: }
096:
097: private Node value;
098:
099: /**
100: * @return Returns the value.
101: */
102: public Node getValue() {
103: return value;
104: }
105:
106: /**
107: * @param value The value to set.
108: */
109: public void setValue(Node value) {
110: this .value = value;
111: }
112:
113: /* (non-Javadoc)
114: * @see biz.hammurapi.xml.dom.DomSerializable#toDom(org.w3c.dom.Element)
115: */
116: public void toDom(Element holder) {
117: holder.setAttribute("uri", uri);
118: if (ref != null) {
119: holder.setAttribute("ref", ref);
120: } else if (value != null) {
121: Element de = AbstractDomObject.addElement(holder,
122: "definition");
123: de.appendChild(holder.getOwnerDocument().importNode(
124: value, true));
125: }
126:
127: if (properties != null) {
128: DOMUtils.toDom(properties, "properties", holder);
129: }
130: }
131:
132: /* (non-Javadoc)
133: * @see biz.hammurapi.config.DomConfigurable#configure(org.w3c.dom.Node, biz.hammurapi.config.Context)
134: */
135: public Registration(Node configNode)
136: throws TransformerException,
137: biz.hammurapi.config.ConfigurationException {
138: Element configElement = (Element) configNode;
139: uri = configElement.getAttribute("uri");
140: if (configElement.hasAttribute("ref")) {
141: ref = configElement.getAttribute("ref");
142: } else {
143: value = XPathAPI.selectSingleNode(configNode,
144: "definition/*");
145: }
146:
147: Node propertiesNode = XPathAPI.selectSingleNode(configNode,
148: "properties");
149: if (propertiesNode != null) {
150: properties = (Map) new DomConfigFactory()
151: .create(propertiesNode);
152: }
153: }
154:
155: private Map properties;
156:
157: /**
158: * @return Returns the properties.
159: */
160: public Map getProperties() {
161: return properties;
162: }
163:
164: public Registration(String uri, String ref, Node value,
165: Map properties) {
166: super ();
167: // TODO Auto-generated constructor stub
168: this .uri = uri;
169: this .ref = ref;
170: this .value = value;
171:
172: if (properties != null) {
173: this .properties = new HashMap(properties);
174: }
175: }
176: }
177:
178: private Map registrations = new HashMap();
179: private RuleRuntime runtime;
180: private RuleAdministrator administrator;
181: private File regFile;
182:
183: /**
184: * Constructs rule service provider and reads
185: * rule definitions from XML file <code>registrations.xml</code> in
186: * rules home directory.
187: *
188: */
189: public FileRuleServiceProvider() {
190: File homeDir;
191:
192: if (home == null) {
193: homeDir = new File(
194: new File(System.getProperty("user.home")),
195: ".hammurapi-rules");
196: } else {
197: homeDir = new File(home);
198: }
199:
200: if (homeDir.exists()) {
201: if (!homeDir.isDirectory()) {
202: errorMessage = "Invalid home, not a directory - "
203: + homeDir.getAbsolutePath();
204: }
205: } else if (!homeDir.mkdirs()) {
206: errorMessage = "Cannot create home directory "
207: + homeDir.getAbsolutePath();
208: }
209:
210: regFile = new File(homeDir, "registrations.xml");
211: try {
212: load();
213: } catch (SAXException e) {
214: errorMessage = "Could not load registrations: " + e;
215: } catch (IOException e) {
216: errorMessage = "Could not load registrations: " + e;
217: } catch (ParserConfigurationException e) {
218: errorMessage = "Could not load registrations: " + e;
219: } catch (FactoryConfigurationError e) {
220: errorMessage = "Could not load registrations: " + e;
221: } catch (TransformerException e) {
222: errorMessage = "Could not load registrations: " + e;
223: } catch (biz.hammurapi.config.ConfigurationException e) {
224: errorMessage = "Could not load registrations: " + e;
225: }
226:
227: runtime = new FileRuleRuntime(registrations);
228: administrator = new FileRuleAdministrator(registrations,
229: regFile);
230: }
231:
232: /**
233: * Loads configuration from XML file
234: * @param regFile
235: * @throws SAXException
236: * @throws IOException
237: * @throws ParserConfigurationException
238: * @throws FactoryConfigurationError
239: * @throws TransformerException
240: * @throws biz.hammurapi.config.ConfigurationException
241: */
242: private void load() throws SAXException, IOException,
243: ParserConfigurationException, FactoryConfigurationError,
244: TransformerException,
245: biz.hammurapi.config.ConfigurationException {
246: if (regFile.exists()) {
247: synchronized (registrations) {
248: registrations.clear();
249: Document doc = DOMUtils.parse(regFile);
250: NodeIterator nit = XPathAPI.selectNodeIterator(doc
251: .getDocumentElement(),
252: "/registrations/registration");
253: Node n;
254: while ((n = nit.nextNode()) != null) {
255: Registration r = new Registration(n);
256: registrations.put(r.getUri(), r);
257: }
258: }
259: }
260: }
261:
262: private String errorMessage;
263:
264: public RuleRuntime getRuleRuntime() throws ConfigurationException {
265: if (errorMessage != null) {
266: throw new ConfigurationException(errorMessage);
267: }
268:
269: return runtime;
270: }
271:
272: public RuleAdministrator getRuleAdministrator()
273: throws ConfigurationException {
274: if (errorMessage != null) {
275: throw new ConfigurationException(errorMessage);
276: }
277:
278: return administrator;
279: }
280: }
|