All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgroups.conf.XmlConfigurator Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS 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).

The newest version!

package org.jgroups.conf;


import org.jgroups.logging.Log;
import org.jgroups.logging.LogFactory;
import org.jgroups.util.Tuple;
import org.jgroups.util.Util;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

import static org.jgroups.util.Util.readTillMatchingCharacter;

/**
 * Uses XML to configure a protocol stack
 * @author Vladimir Blagojevic
 * @author Bela Ban
 */
public class XmlConfigurator implements ProtocolStackConfigurator {
    private final List configuration=new ArrayList<>();
    protected static final Log                log=LogFactory.getLog(XmlConfigurator.class);

    protected enum ElementType {
        START, COMPLETE, END, COMMENT, UNDEFINED
    }
    
    protected XmlConfigurator(List protocols) {
        configuration.addAll(protocols);
    }

    public static XmlConfigurator getInstance(InputStream stream) throws java.io.IOException {
        return parse(stream);
    }

    /**
     * 
     * @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) throws java.io.IOException {
        try {
            XmlNode root=parseXmlDocument(stream);
            return parse(root);
        }
        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(XmlNode root) throws Exception {
        return new XmlConfigurator(parseProtocols(root));
    }


    public static List parseProtocols(XmlNode root) throws Exception {
        String root_name=root.getName().trim().toLowerCase();
        if(!"config".equals(root_name))
            throw new IOException("the configuration does not start with a  element: " + root_name);

        List prot_data=new ArrayList<>();
        for(XmlNode node: root.getChildren()) {
            String  protocol=node.getName();
            Map attrs=node.getAttributes();
            ProtocolConfiguration cfg=new ProtocolConfiguration(protocol, attrs);
            prot_data.add(cfg);

            // store protocol-specific configuration (if available); this will be passed to the protocol on
            // creation to to parse
            List subnodes=node.getChildren();
            if(subnodes == null)
                continue;
            for(XmlNode subnode: subnodes) {
                cfg.addSubtree(subnode);
            }
        }
        return prot_data;
    }


    /** Reads XML and returns a simple tree of XmlNodes */
    public static XmlNode parseXmlDocument(InputStream in) throws IOException {
        Deque stack=new ArrayDeque<>();
        XmlNode        current=null;
        while(true) {
            String s=readNode(in);
            if(s == null)
                break;

            s=sanitize(s);
            ElementType type=getType(s);
            if(type == ElementType.COMMENT)
                continue;

            // remove "<", "/> and ">"
            s=s.replace("<", "").replace( "/>", "").replace(">", "")
              .trim();

            InputStream input=new ByteArrayInputStream(s.getBytes());
            String name=Util.readToken(input);
            XmlNode n=new XmlNode(name);
            for(;;) {
                Tuple tuple=readAttribute(input);
                if(tuple == null)
                    break;
                n.addAttribute(tuple.getVal1(), tuple.getVal2());
            }

            current=stack.peekFirst();
            switch(type) {
                case COMPLETE:
                    current.addChild(n);
                    break;
                case START:
                    if(current != null)
                        current.addChild(n);
                    stack.push(n);
                    break;
                case END:
                    stack.pop();
            }
        }
        return current;
    }


    protected static String readNode(InputStream in) throws IOException {
        StringBuilder sb=new StringBuilder();
        boolean       eof=false, in_comment=false;
        int           comments=0;

        for(;;) {
            int ch=in.read();
            if(ch == -1) {
                eof=true;
                break;
            }
            switch(ch) {
                case '<':
                    if(isCommentStart(in, sb, in_comment)) {
                        comments++;
                        in_comment=true;
                    }
                    continue;
                case '-':
                    if(isCommentEnd(in, sb, in_comment)) {
                        comments--;
                        if(comments < 0)
                            throw new IllegalStateException("found '-->' without corresponding '' */
    protected static boolean isCommentEnd(InputStream in, StringBuilder sb, boolean drop) throws IOException {
        return find('-', "->", in, sb, drop);
    }

    protected static boolean find(char starting_ch, String s, InputStream in, StringBuilder sb, boolean drop)
      throws IOException {
        StringBuilder tmp=new StringBuilder().append(starting_ch);
        for(int i=0; i < s.length(); i++) {
            int c=s.codePointAt(i);
            for(;;) {
                int ch=in.read();
                if(ch == -1) {
                    sb.append(tmp);
                    return false;
                }
                tmp.append((char)ch);
                if(Character.isWhitespace(ch))
                    continue;
                if(ch != c) {
                    if(!drop)
                        sb.append(tmp);
                    return false;
                }
                else
                    break;
            }
        }
        return true;
    }

    /** Fixes errors like "/  >" with "/>" */
    protected static String sanitize(String s) {
        return s.replaceAll("/\\s*>", "/>");
    }

    protected static Tuple readAttribute(InputStream in) throws IOException {
        String attr_name=readTillMatchingCharacter(in, '=');
        if(attr_name == null)
            return null;
        attr_name=attr_name.replace("=", "").trim();
        String val=readQuotedString(in);
        if(val == null)
            return null;
        return new Tuple<>(attr_name, val);
    }

    /** Reads the characters between a start and end quote ("). Skips chars escaped with '\' */
    protected static String readQuotedString(InputStream in) throws IOException {
        String s=readTillMatchingCharacter(in, '"');
        if(s == null)
            return null;
        StringBuilder sb=new StringBuilder();
        boolean escaped=false;
        for(;;) {
            int ch=in.read();
            if(ch == -1)
                break;
            if(ch == '\\') {
                escaped=true;
                continue;
            }

            if(escaped)
                escaped=false;
            else if(ch == '"')
                break;
            sb.append((char)ch);
        }
        return sb.toString();
    }

    protected static ElementType getType(String s) {
        s=s.trim();
        if(s.startsWith("