org.jgroups.conf.XmlConfigurator Maven / Gradle / Ivy
Go to download
This artifact provides a single jar that contains all classes required to use remote Jakarta Enterprise Beans and Jakarta Messaging, including
all dependencies. It is intended for use by those not using maven, maven users should just import the Jakarta Enterprise Beans and
Jakarta Messaging BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up
with different versions on classes on the class path).
package org.jgroups.conf;
/**
* Uses XML to configure a protocol stack
* @author Vladimir Blagojevic
*/
import org.jgroups.Global;
import org.jgroups.logging.Log;
import org.jgroups.logging.LogFactory;
import org.w3c.dom.*;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.jgroups.stack.Configurator;
import org.jgroups.util.Util;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
public class XmlConfigurator implements ProtocolStackConfigurator {
private static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
private static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
private final List configuration=new ArrayList<>();
protected static final Log log=LogFactory.getLog(XmlConfigurator.class);
protected XmlConfigurator(List protocols) {
configuration.addAll(protocols);
}
public static XmlConfigurator getInstance(URL url) throws java.io.IOException {
return getInstance(url, null);
}
public static XmlConfigurator getInstance(InputStream stream) throws java.io.IOException {
return getInstance(stream, null);
}
public static XmlConfigurator getInstance(Element el) throws Exception {
return parse(el);
}
public static XmlConfigurator getInstance(URL url, Boolean validate) throws java.io.IOException {
InputStream is = url.openStream();
try {
return getInstance(is, validate);
} finally {
Util.close(is);
}
}
public static XmlConfigurator getInstance(InputStream stream, Boolean validate) throws java.io.IOException {
return parse(stream, validate);
}
/**
*
* @param convert If false: print old plain output, else print new XML format
* @return String with protocol stack in specified format
*/
public String getProtocolStackString(boolean convert) {
StringBuilder buf=new StringBuilder();
Iterator it=configuration.iterator();
if(convert)
buf.append("\n");
while(it.hasNext()) {
ProtocolConfiguration d=it.next();
if(convert)
buf.append(" <");
buf.append(d.getProtocolString(convert));
if(convert)
buf.append("/>");
if(it.hasNext()) {
if(convert)
buf.append('\n');
else
buf.append(':');
}
}
if(convert)
buf.append("\n ");
return buf.toString();
}
public String getProtocolStackString() {
return getProtocolStackString(false);
}
public List getProtocolStack() {
return configuration;
}
protected static XmlConfigurator parse(InputStream stream, Boolean validate) throws java.io.IOException {
/**
* CAUTION: crappy code ahead ! I (bela) am not an XML expert, so the code below is pretty
* amateurish... But it seems to work, and it is executed only on startup, so no perf loss
* on the critical path. If somebody wants to improve this, please be my guest.
*/
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
boolean validation = false;
String tmp = Util.getProperty(new String[] { Global.XML_VALIDATION }, null, null, null);
if (tmp != null) {
validation =Boolean.valueOf(tmp);
} else if (validate != null) {
validation =validate;
}
factory.setValidating(validation);
factory.setNamespaceAware(validation);
if (validation) {
factory.setAttribute(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
}
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setEntityResolver(new EntityResolver() {
public InputSource resolveEntity(String publicId, String systemId) throws IOException {
if (systemId != null && systemId.startsWith("http://www.jgroups.org/schema/JGroups-")) {
String schemaName = systemId.substring("http://www.jgroups.org/".length());
InputStream schemaIs = getAsInputStreamFromClassLoader(schemaName);
if (schemaIs == null) {
throw new IOException("Schema not found from classloader: " + schemaName);
}
InputSource source = new InputSource(schemaIs);
source.setPublicId(publicId);
source.setSystemId(systemId);
return source;
}
return null;
}
});
// Use AtomicReference to allow make variable final, not for atomicity
// We store only last exception
final AtomicReference exceptionRef = new AtomicReference<>();
builder.setErrorHandler(new ErrorHandler() {
public void warning(SAXParseException exception) throws SAXException {
log.warn(Util.getMessage("ParseFailure"), exception);
}
public void fatalError(SAXParseException exception) throws SAXException {
exceptionRef.set(exception);
}
public void error(SAXParseException exception) throws SAXException {
exceptionRef.set(exception);
}
});
Document document = builder.parse(stream);
if (exceptionRef.get() != null) {
throw exceptionRef.get();
}
// The root element of the document should be the "config" element,
// but the parser(Element) method checks this so a check is not
// needed here.
Element configElement = document.getDocumentElement();
return parse(configElement);
} catch (Exception x) {
throw new IOException(String.format(Util.getMessage("ParseError"), x.getLocalizedMessage()));
}
}
private static InputStream getAsInputStreamFromClassLoader(String filename) {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
InputStream is = cl == null ? null : cl.getResourceAsStream(filename);
if (is == null) {
// check system class loader
is = XmlConfigurator.class.getClassLoader().getResourceAsStream(filename);
}
return is;
}
protected static XmlConfigurator parse(Element root_element) throws Exception {
return new XmlConfigurator(parseProtocols(root_element));
}
public static List parseProtocols(Element root_element) throws Exception {
/**
* CAUTION: crappy code ahead ! I (bela) am not an XML expert, so the code below is pretty amateurish...
* But it seems to work, and it is executed only on startup, so no perf loss on the critical path. If
* somebody wants to improve this, please be my guest.
*/
String root_name=root_element.getNodeName().trim().toLowerCase();
if(!"config".equals(root_name))
throw new IOException("the configuration does not start with a element: " + root_name);
final List prot_data=new ArrayList<>();
NodeList prots=root_element.getChildNodes();
for(int i=0;i < prots.getLength();i++) {
Node node=prots.item(i);
if(node.getNodeType() != Node.ELEMENT_NODE)
continue;
Element tag=(Element)node;
String protocol=tag.getTagName();
Map params=new HashMap<>();
NamedNodeMap attrs=tag.getAttributes();
int attrLength=attrs.getLength();
for(int a=0;a < attrLength;a++) {
Attr attr=(Attr)attrs.item(a);
String name=attr.getName();
String value=attr.getValue();
params.put(name, value);
}
ProtocolConfiguration cfg=new ProtocolConfiguration(protocol, params);
prot_data.add(cfg);
// store protocol-specific configuration (if available); this will be passed to the protocol on
// creation to to parse
NodeList subnodes=node.getChildNodes();
for(int j=0; j < subnodes.getLength(); j++) {
Node subnode=subnodes.item(j);
if(subnode.getNodeType() != Node.ELEMENT_NODE)
continue;
cfg.addSubtree(subnode);
}
}
return prot_data;
}
public static void main(String[] args) throws Exception {
String input_file=null;
XmlConfigurator conf;
boolean old_format=false;
for(int i=0;i < args.length;i++) {
if(args[i].equals("-old")) {
old_format=true;
continue;
}
if(args[i].equals("-file")) {
input_file=args[++i];
continue;
}
help();
return;
}
if(input_file != null) {
InputStream input=null;
try {
input=new FileInputStream(new File(input_file));
}
catch(Throwable t) {
}
if(input == null) {
try {
input=new URL(input_file).openStream();
}
catch(Throwable t) {
}
}
if(input == null)
input=Thread.currentThread().getContextClassLoader().getResourceAsStream(input_file);
if(old_format) {
String cfg=inputAsString(input);
List tmp=Configurator.parseConfigurations(cfg);
System.out.println(dump(tmp));
}
else {
conf=XmlConfigurator.getInstance(input);
String tmp=conf.getProtocolStackString();
System.out.println("\n" + tmp);
}
}
else {
throw new Exception("no input file given");
}
}
private static String dump(Collection configs) {
StringBuilder sb=new StringBuilder();
String indent=" ";
sb.append("\n");
for(ProtocolConfiguration cfg: configs) {
sb.append(indent).append("<").append(cfg.getProtocolName());
Map props=cfg.getProperties();
if(props.isEmpty()) {
sb.append(" />\n");
}
else {
sb.append("\n").append(indent).append(indent);
for(Map.Entry entry: props.entrySet()) {
String key=entry.getKey();
String val=entry.getValue();
key=trim(key);
val=trim(val);
sb.append(key).append("=\"").append(val).append("\" ");
}
sb.append(" />\n");
}
}
sb.append(" \n");
return sb.toString();
}
private static String trim(String val) {
String retval="";
int index;
val=val.trim();
while(true) {
index=val.indexOf('\n');
if(index == -1) {
retval+=val;
break;
}
retval+=val.substring(0, index);
val=val.substring(index + 1);
}
return retval;
}
private static String inputAsString(InputStream input) throws IOException {
int len=input.available();
byte[] buf=new byte[len];
input.read(buf, 0, len);
return new String(buf);
}
public static String replace(String input, final String expr, String replacement) {
StringBuilder sb=new StringBuilder();
int new_index=0, index=0, len=expr.length(), input_len=input.length();
while(true) {
new_index=input.indexOf(expr, index);
if(new_index == -1) {
sb.append(input.substring(index, input_len));
break;
}
sb.append(input.substring(index, new_index));
sb.append(replacement);
index=new_index + len;
}
return sb.toString();
}
static void help() {
System.out.println("XmlConfigurator -file [-old]");
System.out.println("(-old: converts old (plain-text) input format into new XML format)");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy