package biz.hammurapi.rules.jsr94;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.rules.RuleExecutionSetNotFoundException;
import javax.rules.RuleSession;
import javax.rules.RuleSessionCreateException;
import javax.rules.RuleSessionTypeUnsupportedException;
import biz.hammurapi.config.ConfigurationException;
import biz.hammurapi.config.Context;
import biz.hammurapi.config.DomConfigFactory;
import biz.hammurapi.rules.jsr94.FileRuleServiceProvider.Registration;
import biz.hammurapi.util.Attributable;
/**
* Loads rules from configuration file.
* @author Pavel Vlasov
* @revision $Revision$
*/
class FileRuleRuntime implements javax.rules.RuleRuntime {
/**
*
*/
private static final long serialVersionUID = 7086685393129078091L;
private Map registrations;
/**
* Constructs rule runtime from registrations.
*/
FileRuleRuntime(Map registrations) {
this.registrations=registrations;
}
/**
* Creates rule session.
* @param uri Registration name for rule set. If uri starts with <code>direct:</code> then the rest is treated as direct URI of rule set definition.
* If URI tail starts with <code>resource:</code> then rule set definition is loaded from classloader resource, otherwise it is loaded from URL.
* If URI tails starts with <code>property:</code> then rule set is read from a property. Property value can be of type InputStream, Reader, org.w3c.Element, String, File or URL.
* @param properties Vendor-specific properties.
* @param type Session type.
*/
public RuleSession createRuleSession(String uri, Map properties, int type)
throws RuleSessionTypeUnsupportedException,
RuleSessionCreateException, RuleExecutionSetNotFoundException {
DomConfigFactory factory=new DomConfigFactory();
Object container;
try {
if (uri==null) {
throw new NullPointerException("URI is null");
} else if (uri.startsWith("direct:")) {
String ss=uri.substring("direct:".length());
if (ss.startsWith("resource:")) {
container=factory.create(getClass().getClassLoader().getResourceAsStream(ss.substring("resource:".length())), null);
} else {
container=factory.create(new URL(ss), null);
}
} else synchronized (registrations) {
FileRuleServiceProvider.Registration registration=(Registration) registrations.get(uri);
if (registration==null) {
throw new RuleExecutionSetNotFoundException("Rule execution set is not found for URI: "+uri);
}
if (registration.getRef()!=null) {
if (registration.getRef().startsWith("resource:")) {
container=factory.create(getClass().getClassLoader().getResourceAsStream(registration.getRef().substring("resource:".length())), null);
} else {
container=factory.create(new URL(registration.getRef()), null);
}
} else if (registration.getValue()!=null) {
try {
container=factory.create(registration.getValue());
} catch (ConfigurationException e) {
throw new RuleSessionCreateException("Could instantiate rule set: "+e, e);
}
} else {
throw new RuleSessionCreateException("Could instantiate rule set because neither reference nor definition is specified for URI: "+uri);
}
if (registration.getProperties()!=null) {
setAttributes(registration.getProperties(), container);
}
}
} catch (ConfigurationException e) {
throw new RuleSessionCreateException("Could instantiate rule set: "+e, e);
} catch (MalformedURLException e) {
throw new RuleSessionCreateException("Malformed rule set URL: "+e, e);
} catch (IOException e) {
throw new RuleSessionCreateException("Could load rule set: "+e, e);
}
setAttributes(properties, container);
biz.hammurapi.rules.jsr94.RuleSession ret = new biz.hammurapi.rules.jsr94.RuleSession((Context) container, type, uri);
// Injecting rule session into container as "*" attribute, which will be addressable as "/@*"
if (container instanceof Attributable) {
((Attributable) container).setAttribute("*", ret);
}
return ret;
}
private void setAttributes(Map properties, Object container) throws RuleSessionCreateException {
if (properties!=null && !properties.isEmpty()) {
if (container instanceof Attributable) {
Iterator it=properties.entrySet().iterator();
while (it.hasNext()) {
Map.Entry entry=(Entry) it.next();
((Attributable) container).setAttribute(entry.getKey(), entry.getValue());
}
} else {
throw new RuleSessionCreateException(container.getClass().getName()+" must implement "+Attributable.class);
}
}
}
/**
* Returns list of registrations.
*/
public List getRegistrations() {
return new ArrayList(registrations.keySet());
}
}
|