[Git][java-team/noggit][upstream] New upstream version 0.8
Sudip Mukherjee
gitlab at salsa.debian.org
Fri May 15 23:04:13 BST 2020
Sudip Mukherjee pushed to branch upstream at Debian Java Maintainers / noggit
Commits:
edbaa039 by Sudip Mukherjee at 2020-05-15T18:30:53+01:00
New upstream version 0.8
- - - - -
12 changed files:
- README.txt → README.md
- pom.xml
- src/main/java/org/noggit/CharArr.java
- src/main/java/org/noggit/JSONParser.java
- src/main/java/org/noggit/JSONUtil.java
- src/main/java/org/noggit/JSONWriter.java
- src/main/java/org/noggit/ObjectBuilder.java
- + src/test/java/org/noggit/CharArrTest.java
- src/test/java/org/noggit/TestJSONParser.java
- src/test/java/org/noggit/TestJSONWriter.java
- src/test/java/org/noggit/TestObjectBuilder.java
- src/test/java/org/noggit/TestPerf.java
Changes:
=====================================
README.txt → README.md
=====================================
@@ -1,9 +1,10 @@
N o g g i t
------------
+===========
Noggit is the world's fastest streaming JSON parser for Java.
Features:
+---------
- Fast! Measured as the fastest JSON parser on char[], String input.
- Streaming API (StAX/pull-parser like) for both easy and efficient parsing.
- Conforms to JSON standard: http://www.ietf.org/rfc/rfc4627.txt
@@ -19,6 +20,7 @@ Features:
- Optional creation of objects (List, Map, etc) when parsing.
Syntax Features (Optional):
+---------------------------
- Single-line comments using either # or //
- Multi-line comments using C style /* comments in here */
- Single quoted strings.
@@ -27,4 +29,3 @@ Syntax Features (Optional):
- Allow backslash escaping of any character.
- Allow trailing commas and extra commas. Example: [9,4,3,]
- Handle nbsp (non-break space, \u00a0) as whitespace.
-
=====================================
pom.xml
=====================================
@@ -3,7 +3,7 @@
<groupId>org.noggit</groupId>
<artifactId>noggit</artifactId>
<packaging>jar</packaging>
- <version>0.7</version>
+ <version>0.8</version>
<name>Noggit</name>
<url>http://github.com/yonik/noggit</url>
<description>Noggit is the world's fastest streaming JSON parser for Java.</description>
=====================================
src/main/java/org/noggit/CharArr.java
=====================================
@@ -70,6 +70,8 @@ public class CharArr implements CharSequence, Appendable {
public int size() { return end-start; }
@Override
public int length() { return size(); }
+
+ /** The capacity of the buffer when empty (getArray().size()) */
public int capacity() { return buf.length; }
@@ -133,7 +135,7 @@ public class CharArr implements CharSequence, Appendable {
}
public final void write(CharArr arr) {
- write(arr.buf, start, end-start);
+ write(arr.buf, arr.start, arr.end-arr.start);
}
public final void write(String s) {
=====================================
src/main/java/org/noggit/JSONParser.java
=====================================
@@ -63,13 +63,15 @@ public class JSONParser {
public static final int ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER = 1 << 2;
public static final int ALLOW_UNQUOTED_KEYS = 1 << 3;
public static final int ALLOW_UNQUOTED_STRING_VALUES = 1 << 4;
- /** ALLOW_EXTRA_COMMAS causes any nunber of extra commas in arrays and objects to be ignored
+ /** ALLOW_EXTRA_COMMAS causes any number of extra commas in arrays and objects to be ignored
* Note that a trailing comma in [] would be [,] (hence calling the feature "trailing" commas
- * isn't really correct. Since trailing commas is fundamentally incompatible with any future
+ * is either limiting or misleading. Since trailing commas is fundamentally incompatible with any future
* "fill-in-missing-values-with-null", it was decided to extend this feature to handle any
* number of extra commas.
*/
public static final int ALLOW_EXTRA_COMMAS = 1 << 5;
+ public static final int ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT = 1 << 6;
+ public static final int OPTIONAL_OUTER_BRACES = 1 << 7;
public static final int FLAGS_STRICT = 0;
public static final int FLAGS_DEFAULT = ALLOW_COMMENTS | ALLOW_SINGLE_QUOTES | ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER | ALLOW_UNQUOTED_KEYS | ALLOW_UNQUOTED_STRING_VALUES | ALLOW_EXTRA_COMMAS;
@@ -101,18 +103,20 @@ public class JSONParser {
private static final CharArr devNull = new NullCharArr();
- int flags = FLAGS_DEFAULT;
+ protected int flags = FLAGS_DEFAULT;
- final char[] buf; // input buffer with JSON text in it
- int start; // current position in the buffer
- int end; // end position in the buffer (one past last valid index)
- final Reader in; // optional reader to obtain data from
- boolean eof=false; // true if the end of the stream was reached.
- long gpos; // global position = gpos + start
+ protected final char[] buf; // input buffer with JSON text in it
+ protected int start; // current position in the buffer
+ protected int end; // end position in the buffer (one past last valid index)
+ protected final Reader in; // optional reader to obtain data from
+ protected boolean eof=false; // true if the end of the stream was reached.
+ protected long gpos; // global position = gpos + start
- int event; // last event read
+ protected int event; // last event read
- int stringTerm; // The terminator for the last string we read: single quote, double quote, or 0 for unterminated.
+ protected int stringTerm; // The terminator for the last string we read: single quote, double quote, or 0 for unterminated.
+
+ protected boolean missingOpeningBrace = false;
public JSONParser(Reader in) {
this(in, new char[8192]);
@@ -308,7 +312,7 @@ public class JSONParser {
}
}
- private int getCharExpected(int expected) throws IOException {
+ protected int getCharExpected(int expected) throws IOException {
for(;;) {
int ch = getChar();
if (ch==expected) return expected;
@@ -359,7 +363,7 @@ public class JSONParser {
}
- private boolean matchBareWord(char[] arr) throws IOException {
+ protected boolean matchBareWord(char[] arr) throws IOException {
for (int i=1; i<arr.length; i++) {
int ch = getChar();
if (ch != arr[i]) {
@@ -418,10 +422,10 @@ public class JSONParser {
private String getContext() {
String context = "";
if (start>=0) {
- context += " BEFORE='" + errEscape(Math.max(start-60,0), start+1) + "'";
+ context += " AFTER='" + errEscape(Math.max(start - 60, 0), start + 1) + "'";
}
if (start<end) {
- context += " AFTER='" + errEscape(start+1, start+40) + "'";
+ context += " BEFORE='" + errEscape(start + 1, start + 40) + "'";
}
return context;
}
@@ -749,7 +753,7 @@ public class JSONParser {
// isName==true if this is a field name (as opposed to a value)
- private void handleNonDoubleQuoteString(int ch, boolean isName) throws IOException {
+ protected void handleNonDoubleQuoteString(int ch, boolean isName) throws IOException {
if (ch == '\'') {
stringTerm = ch;
if ((flags & ALLOW_SINGLE_QUOTES) == 0) {
@@ -1019,7 +1023,15 @@ public class JSONParser {
outer: for(;;) {
switch (state) {
case 0:
- return event = next(getChar());
+ event = next(getChar());
+ if (event == STRING && (flags & OPTIONAL_OUTER_BRACES) != 0) {
+ if (start > 0) start--;
+ missingOpeningBrace = true;
+ stringTerm = 0;
+ valstate = 0;
+ event = next('{');
+ }
+ return event;
case DID_OBJSTART:
ch = getCharExpected('"');
if (ch == '}') {
@@ -1039,7 +1051,11 @@ public class JSONParser {
case DID_MEMNAME:
ch = getCharExpected(':');
if (ch != ':') {
- throw err("Expected key,value separator ':'");
+ if ((ch == '{' || ch == '[') && (flags & ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT) != 0) {
+ start--;
+ } else {
+ throw err("Expected key,value separator ':'");
+ }
}
state = DID_MEMVAL; // set state first because it might be pushed...
return event = next(getChar());
@@ -1049,7 +1065,13 @@ public class JSONParser {
pop();
return event = OBJECT_END;
} else if (ch != ',') {
- throw err("Expected ',' or '}'");
+ if ((flags & ALLOW_EXTRA_COMMAS) != 0 && (ch == '\'' || ch == '"' || Character.isLetter(ch))) {
+ start--;
+ } else if (missingOpeningBrace && ch == -1 && (flags & OPTIONAL_OUTER_BRACES) != 0) {
+ missingOpeningBrace = false;
+ pop();
+ return event = OBJECT_END;
+ } else throw err("Expected ',' or '}'");
}
ch = getCharExpected('"');
if (ch == '"') {
@@ -1081,7 +1103,11 @@ public class JSONParser {
pop();
return event = ARRAY_END;
} else {
- throw err("Expected ',' or ']'");
+ if ((ch == '{' || ch == '[') && (flags & ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT) != 0) {
+ return event = next(ch);
+ } else {
+ throw err("Expected ',' or ']'");
+ }
}
}
} // end for(;;)
=====================================
src/main/java/org/noggit/JSONUtil.java
=====================================
@@ -16,6 +16,8 @@
package org.noggit;
+import java.util.Arrays;
+
/**
* @author yonik
* @version $Id: JSONUtil.java 1209632 2011-12-02 18:48:42Z yonik $
@@ -76,6 +78,12 @@ public class JSONUtil {
out.write('"');
}
+ public static void writeString(String val, int start, int end, CharArr out) {
+ out.write('"');
+ writeStringPart(val,start,end,out);
+ out.write('"');
+ }
+
public static void writeString(CharSequence val, int start, int end, CharArr out) {
out.write('"');
writeStringPart(val,start,end,out);
@@ -85,29 +93,70 @@ public class JSONUtil {
public static void writeStringPart(char[] val, int start, int end, CharArr out) {
for (int i=start; i<end; i++) {
char ch = val[i];
- switch(ch) {
- case '"':
- case '\\':
- out.write('\\');
+ // When ch>=1f, (ch*146087937)&0xd6a01f80) is 0 only for characters that need escaping: " \\ u2028 u2029
+ // and has 7 false positives: 204a 4051 802f c022 c044 e04a e04b
+ if (ch > 0x1f && ((ch * 146087937) & 0xd6a01f80) != 0) {
+ out.write(ch);
+ } else {
+ writeChar(ch, out);
+ }
+ }
+ }
+
+ public static void writeChar(char ch, CharArr out) {
+ switch(ch) {
+ case '"':
+ case '\\':
+ out.write('\\');
+ out.write(ch);
+ break;
+ case '\r': out.write('\\'); out.write('r'); break;
+ case '\n': out.write('\\'); out.write('n'); break;
+ case '\t': out.write('\\'); out.write('t'); break;
+ case '\b': out.write('\\'); out.write('b'); break;
+ case '\f': out.write('\\'); out.write('f'); break;
+ // case '/':
+ case '\u2028': // valid JSON, but not valid json script
+ case '\u2029':
+ unicodeEscape(ch,out);
+ break;
+ default:
+ if (ch <= 0x1F) {
+ unicodeEscape(ch,out);
+ } else {
out.write(ch);
- break;
- case '\r': out.write('\\'); out.write('r'); break;
- case '\n': out.write('\\'); out.write('n'); break;
- case '\t': out.write('\\'); out.write('t'); break;
- case '\b': out.write('\\'); out.write('b'); break;
- case '\f': out.write('\\'); out.write('f'); break;
- // case '/':
- default:
- if (ch <= 0x1F) {
- unicodeEscape(ch,out);
- } else {
- // These characters are valid JSON, but not valid JavaScript
- if (ch=='\u2028' || ch=='\u2029') {
- unicodeEscape(ch,out);
- } else {
- out.write(ch);
- }
- }
+ }
+ }
+ }
+
+
+ public static void writeStringPart(String chars, int start, int end, CharArr out) {
+ // TODO: write in chunks?
+
+ int toWrite = end - start;
+ char[] arr = out.getArray();
+ int pos = out.getEnd();
+ int space = arr.length - pos;
+ if (space < toWrite) {
+ writeStringPart((CharSequence)chars, start, end, out);
+ return;
+ }
+
+ // get chars directly from String into output array
+ chars.getChars(start, end, arr, pos);
+
+ int endInOut = pos + toWrite;
+ out.setEnd(endInOut);
+ for (int i=pos; i<endInOut ;i++) {
+ char ch = arr[i];
+
+ // When ch>=1f, (ch*146087937)&0xd6a01f80) is 0 only for characters that need escaping: " \\ u2028 u2029
+ // and has 7 false positives: 204a 4051 802f c022 c044 e04a e04b
+ if (ch<=0x1f || ((ch*146087937)&0xd6a01f80)==0 ) {
+ // We hit a char that needs escaping. do the rest char by char.
+ out.setEnd(i);
+ writeStringPart((CharSequence)chars, start+(i-pos), end, out);
+ return;
}
}
}
@@ -115,29 +164,12 @@ public class JSONUtil {
public static void writeStringPart(CharSequence chars, int start, int end, CharArr out) {
for (int i=start; i<end; i++) {
char ch = chars.charAt(i);
- switch(ch) {
- case '"':
- case '\\':
- out.write('\\');
- out.write(ch);
- break;
- case '\r': out.write('\\'); out.write('r'); break;
- case '\n': out.write('\\'); out.write('n'); break;
- case '\t': out.write('\\'); out.write('t'); break;
- case '\b': out.write('\\'); out.write('b'); break;
- case '\f': out.write('\\'); out.write('f'); break;
- // case '/':
- default:
- if (ch <= 0x1F) {
- unicodeEscape(ch,out);
- } else {
- // These characters are valid JSON, but not valid JavaScript
- if (ch=='\u2028' || ch=='\u2029') {
- unicodeEscape(ch,out);
- } else {
- out.write(ch);
- }
- }
+ // When ch>=1f, (ch*146087937)&0xd6a01f80) is 0 only for characters that need escaping: " \\ u2028 u2029
+ // and has 7 false positives: 204a 4051 802f c022 c044 e04a e04b
+ if ( ch>0x1f && ((ch*146087937)&0xd6a01f80)!=0 ) {
+ out.write(ch);
+ } else {
+ writeChar(ch, out);
}
}
}
=====================================
src/main/java/org/noggit/JSONWriter.java
=====================================
@@ -64,10 +64,11 @@ public class JSONWriter {
}
public void write(Object o) {
+ // NOTE: an instance-of chain was about 50% faster than hashing on the classes, even with perfect hashing.
if (o == null) {
writeNull();
- } else if (o instanceof CharSequence) {
- writeString((CharSequence)o);
+ } else if (o instanceof String) {
+ writeString((String)o);
} else if (o instanceof Number) {
if (o instanceof Integer || o instanceof Long) {
write(((Number)o).longValue());
@@ -82,14 +83,15 @@ public class JSONWriter {
write((Map<?,?>)o);
} else if (o instanceof Collection) {
write((Collection<?>)o);
- } else if (o instanceof Object[]) {
- write(Arrays.asList((Object[])o));
} else if (o instanceof Boolean) {
write(((Boolean)o).booleanValue());
+ } else if (o instanceof CharSequence) {
+ writeString((CharSequence)o);
} else if (o instanceof Writable) {
((Writable) o).write(this);
- }
- else if (o instanceof int[]) {
+ } else if (o instanceof Object[]) {
+ write(Arrays.asList((Object[])o));
+ } else if (o instanceof int[]) {
write((int[])o);
} else if (o instanceof float[]) {
write((float[])o);
@@ -112,7 +114,7 @@ public class JSONWriter {
/** Override this method for custom handling of unknown classes. Also see the Writable interface. */
public void handleUnknownClass(Object o) {
- writeString(out.toString());
+ writeString(o.toString());
}
public void write(Map<?,?> val) {
@@ -259,6 +261,10 @@ public class JSONWriter {
JSONUtil.writeNull(out);
}
+ public void writeString(String str) {
+ JSONUtil.writeString(str,0,str.length(),out);
+ }
+
public void writeString(CharSequence str) {
JSONUtil.writeString(str,0,str.length(),out);
}
=====================================
src/main/java/org/noggit/ObjectBuilder.java
=====================================
@@ -77,7 +77,7 @@ public class ObjectBuilder {
double d = Double.parseDouble(numstr);
if (!Double.isInfinite(d)) return Double.valueOf(d);
// TODO: use more efficient constructor in Java5
- return new BigDecimal(numstr);
+ return new BigDecimal(num.buf, num.start, num.size());
}
public Object getBigNumber() throws IOException {
=====================================
src/test/java/org/noggit/CharArrTest.java
=====================================
@@ -0,0 +1,20 @@
+package org.noggit;
+
+import junit.framework.TestCase;
+
+/**
+ * Created by eudoden on 07/01/2016.
+ */
+public class CharArrTest extends TestCase {
+
+ public void testFixWriteCharArrToCharArr() throws Exception {
+ CharArr target = new CharArr(10);
+ target.append("1");
+ assertEquals(1,target.size());
+ CharArr source = new CharArr(10);
+ source.append("23");
+ assertEquals(2, source.size());
+ target.write(source);
+ assertEquals(3, target.size());
+ }
+}
\ No newline at end of file
=====================================
src/test/java/org/noggit/TestJSONParser.java
=====================================
@@ -18,6 +18,7 @@ package org.noggit;
import java.io.IOException;
import java.io.StringReader;
+import java.util.Map;
import java.util.Random;
import junit.framework.TestCase;
@@ -41,7 +42,7 @@ public class TestJSONParser extends TestCase {
public static String lastParser() {
return "parserType=" + parserType
+ (parserType==1 ? " bufferSize=" + bufferSize : "")
- + " parserInput='" + parserInput + "'";
+ + " parserInput='" + parserInput + "'" + "flags : " + lastParser.flags;
}
public static JSONParser getParser(String s) {
@@ -314,7 +315,6 @@ public class TestJSONParser extends TestCase {
}
-
public static void err(String input) throws IOException {
try {
JSONParser p = getParser(input);
@@ -617,7 +617,22 @@ public class TestJSONParser extends TestCase {
parse("{true: 'b'}", new Object[]{m,"true","b",M,e});
parse("{ false :'b'}", new Object[]{m,"false","b",M,e});
parse("{null:null, true : true , false : false , x:'y',a:'b'}", new Object[]{m,"null",N,"true",t,"false",f,"x","y","a","b",M,e});
- flags=JSONParser.FLAGS_DEFAULT;
+ flags = JSONParser.FLAGS_DEFAULT | JSONParser.ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT;
+ parse("{'a'{'b':'c'}}", new Object[]{m, "a", m, "b", "c", M, M, e});
+ parse("{'a': [{'b':'c'} {'b':'c'}]}", new Object[]{m, "a",a, m, "b", "c", M, m, "b", "c", M,A, M, e});
+ parse("{'a' [{'b':'c'} {'b':'c'}]}", new Object[]{m, "a", a, m, "b", "c", M, m, "b", "c", M, A, M, e});
+ parse("{'a':[['b']['c']]}", new Object[]{m, "a", a, a, "b", A, a, "c", A, A, M, e});
+ parse("{'a': {'b':'c'} 'd': {'e':'f'}}", new Object[]{m, "a", m, "b", "c",M, "d", m,"e","f", M, M, e});
+ parse("{'a': {'b':'c'} d: {'e':'f'}}", new Object[]{m, "a", m, "b", "c",M, "d", m,"e","f", M, M, e});
+
+ flags = JSONParser.FLAGS_DEFAULT | JSONParser.ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT | JSONParser.OPTIONAL_OUTER_BRACES;
+ parse("'a':{'b':'c'}", new Object[]{m, "a", m, "b", "c", M, M, e});
+ parse("'a':{'b':'c'}", true, new Object[]{m, "a", m, "b", "c", M, M, e});
+ parse("a:'b'", new Object[]{m, "a", "b", M, e});
+
+
+ flags = JSONParser.FLAGS_DEFAULT;
+
}
public void testBareString() throws Exception {
=====================================
src/test/java/org/noggit/TestJSONWriter.java
=====================================
@@ -60,6 +60,14 @@ public class TestJSONWriter extends TestCase {
}
+
+ public static class Unknown {
+ @Override
+ public String toString() {
+ return "a,\"b\",c";
+ }
+ }
+
public static class Custom implements JSONWriter.Writable {
@Override
public void write(JSONWriter writer) {
@@ -74,4 +82,9 @@ public class TestJSONWriter extends TestCase {
test("[{'a':1,'b':2}]", L(new Custom()), -1);
test("[10,{'a':1,'b':2},20]", L(10, new Custom(), 20), -1);
}
+
+ public void testUnknown() throws Exception {
+ test("['a,\\\"b\\\",c']", L(new Unknown()), -1);
+ }
+
}
=====================================
src/test/java/org/noggit/TestObjectBuilder.java
=====================================
@@ -55,6 +55,14 @@ public class TestObjectBuilder extends TestCase {
}
return map;
}
+ public void testWithoutStartingBraces() throws IOException {
+ JSONParser parser = new JSONParser("a: {key:val1}b:{key:val2}");
+ parser.setFlags(JSONParser.FLAGS_DEFAULT | JSONParser.OPTIONAL_OUTER_BRACES| JSONParser.ALLOW_MISSING_COLON_COMMA_BEFORE_OBJECT);
+ ObjectBuilder objectBuilder = new ObjectBuilder(parser);
+ String s1 = JSONUtil.toJSON(objectBuilder.getObject(),-1);
+ String expected = JSONUtil.toJSON(O("a", O("key", "val1"), "b", O("key", "val2")),-1);
+ assertEquals(s1, expected);
+ }
public void testVariations(String str, Object expected) throws IOException {
test("["+str+"]", L(expected));
=====================================
src/test/java/org/noggit/TestPerf.java
=====================================
@@ -25,13 +25,14 @@ import java.util.List;
*/
public class TestPerf {
static int flags = JSONParser.FLAGS_DEFAULT;
+ static int iter = 1;
+ static List<String> vals = new ArrayList<String>();
+ static List<Object> objs = new ArrayList<Object>();
+ static boolean ws = false;
+ static boolean nows = false;
+ static boolean writer = false;
public static void main(String[] args) throws Exception {
- int iter=1;
- List<String> vals = new ArrayList<String>();
- boolean ws = false;
- boolean nows = false;
-
int i=0;
while (i<args.length) {
String k=args[i++];
@@ -47,6 +48,8 @@ public class TestPerf {
nows = true;
} else if ("-flags".equals(k)) {
Integer.parseInt(k);
+ } else if ("-writer".equals(k)) {
+ writer = true;
}
}
@@ -81,21 +84,25 @@ public class TestPerf {
vals.add(sb.toString());
}
+
+
// handle adding or removing whitespace
- if (ws || nows) {
+ if (ws || nows || writer) {
List<String> out = new ArrayList<String>();
for (String val : vals) {
Object o = ObjectBuilder.fromJSON(val);
- if (ws) {
+ if (writer) {
+ objs.add(o);
+ } else if (ws) {
String s = JSONUtil.toJSON(o, 2);
out.add(s);
- }
- if (nows) {
+ } else if (nows) {
String s = JSONUtil.toJSON(o, -1);
out.add(s);
}
}
- vals = out;
+ if (!writer)
+ vals = out;
}
// calculate total size per iteration
@@ -108,8 +115,15 @@ public class TestPerf {
int ret=0;
for (int j=0; j<iter; j++) {
- for (String json : vals)
- ret += parse(json);
+ if (writer) {
+ for (Object o : objs) {
+ ret += write(o);
+ }
+ } else {
+ for (String json : vals) {
+ ret += parse(json);
+ }
+ }
}
long end = System.currentTimeMillis();
@@ -143,4 +157,11 @@ public class TestPerf {
return ret;
}
+ static CharArr out = new CharArr();
+ public static int write(Object o) {
+ out.reset();
+ JSONWriter writer = new JSONWriter(out,-1);
+ writer.write(o);
+ return out.size();
+ }
}
View it on GitLab: https://salsa.debian.org/java-team/noggit/-/commit/edbaa039edfcfa1db2b52c9c0604129ae01b513f
--
View it on GitLab: https://salsa.debian.org/java-team/noggit/-/commit/edbaa039edfcfa1db2b52c9c0604129ae01b513f
You're receiving this email because of your account on salsa.debian.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-java-commits/attachments/20200515/87b0f046/attachment.html>
More information about the pkg-java-commits
mailing list