Skip to content

Commit

Permalink
Better parsing of comments in XML documents (https://issues.redhat.co…
Browse files Browse the repository at this point in the history
  • Loading branch information
belaban committed Jun 2, 2023
1 parent fb79b2a commit 1695180
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 43 deletions.
40 changes: 40 additions & 0 deletions conf/comment-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

<!--
XML file to test comments (https://issues.redhat.com/browse/JGRP-2692)
author: Bela Ban
<!-- This is a nested comment -->
-->
<config xmlns="urn:org:jgroups"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:org:jgroups http://www.jgroups.org/schema/jgroups.xsd"
>
<SHARED_LOOPBACK
<!--mcast_port="${jgroups.udp.mcast_port:45588}"-->
<!--thread_pool.min_threads="0"
thread_pool.max_threads="200"--> <!-- weird XML shit but JGroups is happy to eat it:-) -->
thread_pool.keep_alive_time="30000"/>
<RED/>
<LOCAL_PING />
<MERGE3 max_interval="30000"
min_interval="10000"/>
<!--
<FD_SOCK2/>
<FD_ALL3/>
-->
<VERIFY_SUSPECT2 timeout="1500" />
<BARRIER />
<pbcast.NAKACK2 xmit_interval="500"/>
<UNICAST3 xmit_interval="500" />
<pbcast.STABLE desired_avg_gossip="50000"
max_bytes="4M"/>
<pbcast.GMS print_local_addr="true" join_timeout="5"/>

<UFC max_credits="10M"
<!-- comments inside of XML elements are accepted by the JGroups XML parser -->
min_threshold="0.4"/>
<MFC max_credits="10M"
min_threshold="0.4"/>
<FRAG2 frag_size="60K" />
<!--FRAG2 frag_size="60K" />
<pbcast.STATE_TRANSFER /-->
</config>
119 changes: 76 additions & 43 deletions src/org/jgroups/conf/XmlConfigurator.java
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,82 @@ public static XmlNode parseXmlDocument(InputStream in) throws IOException {


protected static String readNode(InputStream in) throws IOException {
String tmp=readTillMatchingCharacter(in, '<');
if(tmp == null)
return null;
StringBuilder sb=new StringBuilder("<");
tmp=readTillMatchingCharacter(in, '>');
if(tmp == null)
return null;
sb.append(tmp);
return sb.toString();
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 '<!--'");
if(comments == 0)
in_comment=false;
}
continue;
case '>':
if(!in_comment) {
sb.append((char)ch);
return sb.toString();
}
break;
}
if(!in_comment)
sb.append((char)ch);
}

String retval=sb.toString().trim();
return eof && retval.isEmpty()? null : retval;
}

/** Searches for a sequence of '!--' */
protected static boolean isCommentStart(InputStream in, StringBuilder sb, boolean drop) throws IOException {
return find('<', "!--", in, sb, drop);
}

/* Searches for an end comment, e.g. '-->' */
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 {
int index=0;
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 "/>" */
Expand Down Expand Up @@ -237,15 +304,6 @@ protected static ElementType getType(String s) {
return ElementType.UNDEFINED;
}

protected static boolean isClosed(String s) {
s=s.trim();
return s.startsWith("</") || s.endsWith("/>");
}

protected static boolean isComment(String s) {
return s.trim().startsWith("<!--");
}

public static void main(String[] args) throws Exception {
String input_file=null;
XmlConfigurator conf;
Expand Down Expand Up @@ -323,31 +381,6 @@ private static String trim(String val) {
return retval.toString();
}

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, index, input_len);
break;
}
sb.append(input, index, new_index);
sb.append(replacement);
index=new_index + len;
}

return sb.toString();
}

static void help() {
System.out.println("XmlConfigurator -file <input XML file>");
}
Expand Down
21 changes: 21 additions & 0 deletions tests/junit-functional/org/jgroups/tests/XmlParseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.jgroups.tests;

import org.jgroups.Global;
import org.jgroups.JChannel;
import org.testng.annotations.Test;

/**
* Tests XML file ./conf/comment-test.xml. This file contains invalid XML, but the JGroups parser is more lenient and
* accepts almost all XML, e.g. nested comments, comments within attributes etc.
* @author Bela Ban
* @since 5.2.15
*/
@Test(groups= Global.FUNCTIONAL)
public class XmlParseTest {
public void testXML() throws Exception {
try(JChannel ch=new JChannel("comment-test.xml").name("X")) {
ch.connect(getClass().getSimpleName());
assert ch.isConnected();
}
}
}

0 comments on commit 1695180

Please sign in to comment.