User: rinkrank
Date: 02/02/24 14:11:51
Modified: src/xjavadoc XJavaDocTest.java XJavaDoc.java
SourceClass.java AbstractClass.java
Log:
-Added inner class test
-Fixed classcast bug in AbstractClass.innerClasses()
-Experimented with unicode in benchmark grammars
-Restructured build.xml so all benchmarks can be run separately
Revision Changes Path
1.14 +15 -2 xjavadoc/src/xjavadoc/XJavaDocTest.java
Index: XJavaDocTest.java
===================================================================
RCS file: /cvsroot/xdoclet/xjavadoc/src/xjavadoc/XJavaDocTest.java,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -w -r1.13 -r1.14
--- XJavaDocTest.java 24 Feb 2002 04:38:56 -0000 1.13
+++ XJavaDocTest.java 24 Feb 2002 22:11:51 -0000 1.14
@@ -192,10 +192,23 @@
* @todo-javadoc Write javadocs for exception
*/
public void testAddCommentToCommentedClass() throws Exception {
- XClass clazz;
- clazz = XJavaDoc.getInstance().updateClassTag("Hello", "here", "is",
"a tag for ya", 0);
+ XClass clazz = XJavaDoc.getInstance().updateClassTag("Hello", "here",
"is", "a tag for ya", 0);
File testDir = new File("build/junit/testAddCommentToCommentedClass");
String fileName = clazz.save(testDir);
+ }
+
+
+ /**
+ * A unit test for JUnit
+ *
+ * @exception Exception Describe the exception @todo-javadoc Write javadocs for
+ * exception
+ */
+ public void testInnerlass() throws Exception {
+ XClass clazz = XJavaDoc.getInstance().getXClass("Hello", true);
+ XClass[] innerClasses = clazz.innerClasses();
+ assertEquals(1, innerClasses.length);
+ assertEquals("Hello.InnerClass", innerClasses[0].qualifiedName());
}
1.17 +891 -655 xjavadoc/src/xjavadoc/XJavaDoc.java
Index: XJavaDoc.java
===================================================================
RCS file: /cvsroot/xdoclet/xjavadoc/src/xjavadoc/XJavaDoc.java,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -w -r1.16 -r1.17
--- XJavaDoc.java 24 Feb 2002 18:19:30 -0000 1.16
+++ XJavaDoc.java 24 Feb 2002 22:11:51 -0000 1.17
@@ -36,60 +36,88 @@
package xjavadoc;
import java.io.File;
+
import java.io.FileNotFoundException;
+
import java.io.FileReader;
+
import java.io.Reader;
+
import java.io.Serializable;
+
import java.util.Arrays;
+
import java.util.Collection;
+
import java.util.Collections;
+
import java.util.HashMap;
+
import java.util.HashSet;
+
import java.util.Iterator;
+
import java.util.List;
/**
* @author <a href="mailto:[EMAIL PROTECTED]">Aslak Helles�y</a>
* @created 3. januar 2002
*/
+
public class XJavaDoc implements XJavaDocRoot, Serializable {
/**
* @todo-javadoc Describe the field
*/
+
private final HashMap _sourceClasses = new HashMap();
+
/**
* @todo-javadoc Describe the field
*/
+
private final HashMap _binaryClasses = new HashMap();
+
/**
* @todo-javadoc Describe the field
*/
+
private final HashMap _unknownClasses = new HashMap();
+
/**
* @todo-javadoc Describe the field
*/
+
private final HashMap _proxyClasses = new HashMap();
+
/**
* @todo-javadoc Describe the field
*/
+
private final HashMap _packages = new HashMap();
+
/**
* @todo-javadoc Describe the field
*/
+
private File _dir;
+
/**
* @todo-javadoc Describe the field
*/
+
private String[] _files;
+
/**
* @todo-javadoc Describe the field
*/
+
private String _docletClass;
/**
* @todo-javadoc Describe the field
*/
+
public final static List PRIMITIVES =
Collections.unmodifiableList(Arrays.asList(new String[]
{"void", "byte", "short", "int", "long", "char", "float",
"double", "boolean"}
));
@@ -97,92 +125,122 @@
/**
* @todo-javadoc Describe the field
*/
+
private final static XJavaDoc instance = new XJavaDoc();
+
/**
* Get static reference to Log4J Logger
*/
+
private static org.apache.log4j.Category _log =
org.apache.log4j.Category.getInstance(XJavaDoc.class.getName());
/**
* @todo-javadoc Describe the field
*/
+
private static JavaParser _javaParser;
/**
* @todo-javadoc Describe the field
*/
+
private final static HashMap _primitiveClasses = new HashMap();
+
/**
* Describe what the XJavaDoc constructor does
*
* @todo-javadoc Write javadocs for constructor
*/
+
private XJavaDoc() {
+
}
+
/**
* Sets the Dir attribute of the XJavaDoc object
*
* @param dir The new Dir value
*/
+
public void setDir(File dir) {
+
this._dir = dir;
+
}
+
/**
* Sets the DocletClass attribute of the XJavaDoc object
*
* @param docletClass The new DocletClass value
*/
+
public void setDocletClass(String docletClass) {
+
this._docletClass = docletClass;
+
}
+
/**
* Sets the Files attribute of the XJavaDoc object
*
* @param files The new Files value
*/
+
public void setFiles(String[] files) {
+
this._files = files;
+
}
+
/**
* Gets the Dir attribute of the XJavaDoc object
*
* @return The Dir value
*/
+
public File getDir() {
+
return _dir;
}
+
/**
* Gets the DocletClass attribute of the XJavaDoc object
*
* @return The DocletClass value
*/
+
public String getDocletClass() {
+
return _docletClass;
}
+
/**
* Gets the Files attribute of the XJavaDoc object
*
* @return The Files value
*/
+
public String[] getFiles() {
+
return _files;
}
+
/**
* Describe what the method does
*
@@ -207,6 +265,7 @@
* @todo-javadoc Write javadocs for return value
* @todo-javadoc Write javadocs for exception
*/
+
public XClass updateMethodTag(
String className,
String methodNameWithSignature,
@@ -215,14 +274,20 @@
String parameterValue,
int tagIndex
) throws XJavaDocException {
+
XClass clazz = getXClass(className, false);
+
XMethod method = clazz.getMethod(methodNameWithSignature);
+
XDoc doc = method.doc();
+
doc.updateTagValue(tagName, parameterName, parameterValue, tagIndex);
+
return clazz;
}
+
/**
* Describe what the method does
*
@@ -242,6 +307,7 @@
* @todo-javadoc Write javadocs for return value
* @todo-javadoc Write javadocs for exception
*/
+
public XClass updateClassTag(
String className,
String tagName,
@@ -249,14 +315,20 @@
String parameterValue,
int tagIndex
) throws XJavaDocException {
+
// Don't get proxy. It's only overhead
+
XClass clazz = getXClass(className, false);
+
XDoc doc = clazz.doc();
+
doc.updateTagValue(tagName, parameterName, parameterValue, tagIndex);
+
return clazz;
}
+
/**
* Describe what the method does
*
@@ -268,50 +340,49 @@
* @todo-javadoc Write javadocs for return value
* @todo-javadoc Write javadocs for exception
*/
+
public XClass scan(String qualifiedName) throws XJavaDocException {
+
File f = null;
-// try {
+
f = new File(_dir, qualifiedName.replace('.', '/') + ".java");
+
if (!f.exists()) {
+
throw new XJavaDocException("No source found for " +
qualifiedName + " at " + f.getAbsolutePath());
}
_log.debug("Scanning class: " + qualifiedName);
- //Token.lastParsedToken = null;
- /*
- * if (_javaParser == null) {
- * _javaParser = new JavaParser(in);
- * }
- * else {
- * _javaParser.ReInit(in);
- * }
- * _javaParser.CompilationUnit(sourceClass);
- */
SourceClass sourceClass = new SourceClass(null, qualifiedName, f);
ParseThread parseThread = new ParseThread(sourceClass);
+
// We must wait here until the first part of the parsing is done.
+
// we'll be notified by the parser when it's done
+
synchronized (sourceClass.getParseLock()) {
+
parseThread.start();
try {
+
sourceClass.getParseLock().wait();
+
} catch (InterruptedException e) {
+
e.printStackTrace();
+
}
+
}
return sourceClass;
-// } catch (FileNotFoundException e) {
-// throw new XJavaDocException(e.getMessage());
-// } catch (ParseException e) {
-// throw new XJavaDocException("Error parsing " +
f.getAbsolutePath() + ":" + e.getMessage());
-// }
}
+
/**
* Describe what the method does
*
@@ -319,26 +390,45 @@
* @todo-javadoc Write javadocs for method
* @todo-javadoc Write javadocs for exception
*/
+
public void scan() throws XJavaDocException {
+
long start = System.currentTimeMillis();
+
System.out.println("Scanning " + _files.length + " classes...");
+
for (int i = 0; i < _files.length; i++) {
+
String qualifiedName = _files[i].replace('/', '.');
+
qualifiedName = qualifiedName.replace('\\', '.');
+
qualifiedName = qualifiedName.substring(0,
qualifiedName.length() - 5);
+
XClass clazz = scan(qualifiedName);
+
_sourceClasses.put(qualifiedName, clazz);
+
}
+
long end = System.currentTimeMillis();
+
System.out.println("Scanned " + _sourceClasses.size() + " classes in "
+ (end - start) + " milliseconds.");
+
printMemoryStatus();
+
if (_docletClass != null) {
+
_log.debug("Running doclet " + _docletClass);
+
invokeDoclet();
+
}
+
}
+
/**
* Describe what the method does
*
@@ -346,28 +436,42 @@
* @todo-javadoc Write javadocs for method
* @todo-javadoc Write javadocs for return value
*/
+
public XClass[] classes() {
+
XClass[] result = new XClass[_sourceClasses.size()];
+
return (XClass[])_sourceClasses.values().toArray(result);
}
+
/**
* Returns the packages of the specified classes during parsing.
*
* @return Describe the return value
* @todo-javadoc Write javadocs for return value
*/
+
public XPackage[] specifiedPackages() {
+
HashSet packages = new HashSet();
+
XClass[] classes = classes();
+
for (int i = 0; i < classes.length; i++) {
+
packages.add(classes[i].containingPackage());
+
}
+
XPackage[] result = new XPackage[packages.size()];
+
result = (XPackage[])packages.toArray(result);
+
return result;
// We don't want to return all packages
+
/*
* XPackage[] result = new XPackage[ _packages.size() ];
* return (XPackage[]) _packages.values().toArray( result );
@@ -375,6 +479,7 @@
}
+
/**
* Describe what the method does
*
@@ -384,11 +489,14 @@
* @todo-javadoc Write javadocs for method parameter
* @todo-javadoc Write javadocs for return value
*/
+
public XPackage packageNamed(String s) {
+
return (XPackage)_packages.get(s);
}
+
/**
* Get the XClass corresponding to the qualifiedName. This can be a class from
* source, a precompiled class or a primitive. UnknownClass is never returned
@@ -402,72 +510,119 @@
* @pre qualifiedName != null
* @post return != null
*/
+
XClass getXClass(String qualifiedName, boolean proxy) {
+
if (qualifiedName.equals("")) {
+
throw new IllegalStateException("Classname can't be empty
String");
}
+
// first, see if we have the class among the sources
+
XClass result = (XClass)_sourceClasses.get(qualifiedName);
+
if (result == null) {
+
// Couldn't find the class among the sources. Try a Primitive
class.
+
result = getPrimitive(qualifiedName);
+
if (result == null) {
+
// Couldn't find the class among the sources and
wasn't primitive.
// Try a BinaryClass first
+
Class clazz = getClass(qualifiedName);
+
if (clazz != null) {
+
// there is a known binary class
+
if (proxy) {
+
// Just return a proxy. The proxy
+
// will ask for a non-proxy later
+
return getProxyClass(qualifiedName);
}
+
else {
+
return getBinaryClass(clazz);
}
+
}
+
else {
+
// No known binary either. Last resort is
+
// a source class
+
File f = new File(_dir,
qualifiedName.replace('.', '/') + ".java");
+
if (f.exists()) {
+
// The source exists. Let's parse it.
+
if (proxy) {
+
return
getProxyClass(qualifiedName);
}
+
else {
+
try {
+
return
scan(qualifiedName);
} catch (XJavaDocException e1)
{
+
throw new
IllegalStateException("Error during parse:" + e1.getMessage());
}
+
}
+
}
+
}
+
}
+
}
+
return result;
}
+
/**
* @param qualifiedName Describe what the parameter does
* @return The UnknownClass value
* @todo-javadoc Write javadocs for method parameter
*/
+
UnknownClass getUnknownClass(String qualifiedName) {
UnknownClass result = (UnknownClass)_unknownClasses.get(qualifiedName);
+
if (result == null) {
+
// Couldn't find the UnknownClass class in the cache.
Instantiate it.
+
result = new UnknownClass(qualifiedName);
+
_unknownClasses.put(qualifiedName, result);
+
}
+
return result;
}
+
/**
* Describe the method
*
@@ -477,17 +632,26 @@
* @todo-javadoc Describe the method parameter
* @todo-javadoc Write javadocs for return value
*/
+
XPackage addPackageMaybe(String packageName) {
+
XPackage result = (XPackage)_packages.get(packageName);
+
if (result == null) {
+
// The package doesn't exist yet. Add it then
+
result = new XPackage(packageName);
+
_packages.put(packageName, result);
+
}
+
return result;
}
+
/**
* Gets the ProxyClass attribute of the XJavaDoc object
*
@@ -495,19 +659,29 @@
* @return The ProxyClass value
* @todo-javadoc Write javadocs for method parameter
*/
+
private ProxyClass getProxyClass(String qualifiedName) {
+
if (qualifiedName.equals("")) {
+
throw new IllegalStateException("Classname can't be empty
String");
}
+
ProxyClass result = (ProxyClass)_proxyClasses.get(qualifiedName);
+
if (result == null) {
+
result = new ProxyClass(qualifiedName);
+
_proxyClasses.put(qualifiedName, result);
+
}
+
return result;
}
+
/**
* Returns the Class with the given name, or null if unknown.
*
@@ -516,15 +690,21 @@
* @todo-javadoc Write javadocs for method parameter
* @todo-javadoc Write javadocs for method parameter
*/
+
private Class getClass(String qualifiedName) {
+
try {
+
return Class.forName(qualifiedName);
} catch (ClassNotFoundException e) {
+
return null;
}
+
}
+
/**
* Gets the BinaryClass attribute of the XJavaDoc object
*
@@ -534,30 +714,46 @@
* @todo-javadoc Write javadocs for method parameter
* @todo-javadoc Write javadocs for exception
*/
+
private BinaryClass getBinaryClass(Class clazz) {
+
BinaryClass result = (BinaryClass)_binaryClasses.get(clazz);
+
if (result == null) {
+
// Couldn't find the binary class in the cache. Try to
instantiate it.
+
result = new BinaryClass(clazz);
+
_binaryClasses.put(clazz, result);
+
}
+
return result;
}
+
/**
* Describe what the method does
*
* @todo-javadoc Write javadocs for method
*/
+
private void printMemoryStatus() {
+
System.out.println("ParameterImpl instances: " +
ParameterImpl.instanceCount);
+
System.out.println("MethodImpl instances: " +
MethodImpl.instanceCount);
+
System.out.println("ConstructorImpl instances: " +
ConstructorImpl.instanceCount);
+
System.out.println("SimpleNode instances: " +
SimpleNode.instanceCount);
+
}
+
/**
* Describe what the method does
*
@@ -565,28 +761,41 @@
* @todo-javadoc Write javadocs for method
* @todo-javadoc Write javadocs for exception
*/
+
private void invokeDoclet() throws XJavaDocException {
+
try {
+
Object o = Class.forName(_docletClass).newInstance();
+
XJavaDoclet doclet = (XJavaDoclet)o;
+
doclet.start(this);
+
} catch (Exception e) {
+
e.printStackTrace();
+
throw new XJavaDocException(e);
}
+
}
+
/**
* Gets the Instance attribute of the XJavaDoc class
*
* @return The Instance value
*/
+
public static XJavaDoc getInstance() {
+
return instance;
}
+
/**
* Gets the Primitive attribute of the XJavaDoc class
*
@@ -594,11 +803,14 @@
* @return The Primitive value
* @todo-javadoc Write javadocs for method parameter
*/
+
private static Primitive getPrimitive(String name) {
+
return (Primitive)_primitiveClasses.get(name);
}
+
/**
* Describe the method
*
@@ -606,11 +818,15 @@
* @todo-javadoc Describe the method
* @todo-javadoc Describe the method parameter
*/
+
private final static void addPrimitive(String name) {
+
_primitiveClasses.put(name, new Primitive(name));
+
}
+
/**
* Describe what this class does
*
@@ -618,13 +834,17 @@
* @created 23. februar 2002
* @todo-javadoc Write javadocs
*/
+
private class ParseThread extends Thread {
+
/**
* @todo-javadoc Describe the field
*/
+
private final SourceClass _sourceClass;
+
/**
* Describe what the ParseThread constructor does
*
@@ -632,24 +852,40 @@
* @todo-javadoc Write javadocs for constructor
* @todo-javadoc Write javadocs for method parameter
*/
+
public ParseThread(SourceClass sourceClass) {
+
super(sourceClass.qualifiedName());
+
setDaemon(true);
+
_sourceClass = sourceClass;
+
}
+
/**
* Main processing method for the ParseThread object
*/
+
public void run() {
+
_sourceClass.parse();
+
}
+
}
static {
+
for (int i = 0; i < PRIMITIVES.size(); i++) {
+
addPrimitive((String)PRIMITIVES.get(i));
+
}
+
}
+
}
+
1.9 +18 -8 xjavadoc/src/xjavadoc/SourceClass.java
Index: SourceClass.java
===================================================================
RCS file: /cvsroot/xdoclet/xjavadoc/src/xjavadoc/SourceClass.java,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -w -r1.8 -r1.9
--- SourceClass.java 24 Feb 2002 20:44:49 -0000 1.8
+++ SourceClass.java 24 Feb 2002 22:11:51 -0000 1.9
@@ -92,6 +92,7 @@
super(containingClass, qualifiedName);
// We need to check if sourceFile is null. All inner classes will have
it set to null
if (sourceFile != null) {
+ addImportedPackage("java.lang");
try {
Reader in = new FileReader(sourceFile);
_javaParser = new JavaParser(in);
@@ -149,7 +150,9 @@
_javaParser.CompilationUnit(this);
} catch (ParseException e) {
// Source code is bad. Not according to grammar. User's fault.
- System.err.println("Error parsing " + qualifiedName() + ":" +
e.getMessage());
+ System.out.println("Error parsing " + qualifiedName() + ":" +
e.getMessage());
+ } catch (TokenMgrError e) {
+ System.out.println("Error parsing " + qualifiedName() + ":" +
e.getMessage());
}
}
@@ -210,6 +213,7 @@
if (dot_index != -1) {
// It's already qualified
qualifiedClassName = unqualifiedClassName;
+ // Get a proxy for the class
result = XJavaDoc.getInstance().getXClass(qualifiedClassName,
true);
}
else {
@@ -219,10 +223,16 @@
if (result != null) {
return result;
}
+ result =
isUnqualifiedNameInTheSamePackage(unqualifiedClassName, result);
result =
isUnqualifiedNameInImportedClasses(unqualifiedClassName, result);
+ if (result != null) {
+ return result;
+ }
result =
isUnqualifiedNameInImportedPackages(unqualifiedClassName, result);
- result =
isUnqualifiedNameInTheSamePackage(unqualifiedClassName, result);
- result =
isUnqualifiedNameInJavaLangPackage(unqualifiedClassName, result);
+ /*
+ * Results in ambiguous class if java.lang is explcitly
imported
+ * result =
isUnqualifiedNameInJavaLangPackage(unqualifiedClassName, result);
+ */
}
if (result == null) {
// We'll get here when we use inner classes and nonexisting
classes
@@ -304,10 +314,10 @@
String importedClassName = getImportedClassName(i);
if (importedClassName.endsWith(suffix)) {
- // We've found a candidate
+ // We've found a candidate. Get a proxy for it.
XClass clazz =
XJavaDoc.getInstance().getXClass(importedClassName, true);
if (clazz != null && result != null) {
- throw new IllegalStateException("Ambiguous
class:" + unqualifiedClassName);
+ throw new IllegalStateException("In class " +
qualifiedName() + ": Ambiguous class:" + unqualifiedClassName);
}
if (clazz != null) {
result = clazz;
@@ -348,7 +358,7 @@
XClass clazz =
XJavaDoc.getInstance().getXClass(qualifiedClassName, true);
if (result != null && clazz != null) {
- throw new IllegalStateException("Ambiguous class:" +
unqualifiedClassName);
+ throw new IllegalStateException("In class " +
qualifiedName() + ": Ambiguous class:" + unqualifiedClassName);
}
if (clazz != null) {
@@ -373,7 +383,7 @@
String qualifiedClassName = containingPackage().name() + "." +
unqualifiedClassName;
XClass clazz = XJavaDoc.getInstance().getXClass(qualifiedClassName,
true);
if (result != null && clazz != null) {
- throw new IllegalStateException("Ambiguous class:" +
unqualifiedClassName);
+ throw new IllegalStateException("In class " + qualifiedName()
+ ": Ambiguous class:" + unqualifiedClassName + " " + result.qualifiedName() + " or "
+ clazz.qualifiedName() + " ?");
}
if (clazz != null) {
result = clazz;
@@ -396,7 +406,7 @@
String qualifiedClassName = "java.lang." + unqualifiedClassName;
XClass clazz = XJavaDoc.getInstance().getXClass(qualifiedClassName,
true);
if (result != null && clazz != null) {
- throw new IllegalStateException("Ambiguous class:" +
unqualifiedClassName);
+ throw new IllegalStateException("In class " + qualifiedName()
+ ": Ambiguous class:" + unqualifiedClassName);
}
if (clazz != null) {
result = clazz;
1.8 +5 -19 xjavadoc/src/xjavadoc/AbstractClass.java
Index: AbstractClass.java
===================================================================
RCS file: /cvsroot/xdoclet/xjavadoc/src/xjavadoc/AbstractClass.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -w -r1.7 -r1.8
--- AbstractClass.java 24 Feb 2002 20:33:49 -0000 1.7
+++ AbstractClass.java 24 Feb 2002 22:11:51 -0000 1.8
@@ -56,7 +56,10 @@
* @todo-javadoc Describe the field
*/
protected XClass[] _xinterfaces;
-
+ /**
+ * @todo-javadoc Describe the field
+ */
+ private ArrayList _interfaces;
/**
* @todo-javadoc Describe the field
*/
@@ -73,22 +76,14 @@
* @todo-javadoc Describe the field
*/
private ArrayList _importedPackages;
-
/**
* @todo-javadoc Describe the field
*/
private XConstructor[] _xconstructors;
-
/**
* @todo-javadoc Describe the field
*/
private ArrayList _constructors;
-
- /**
- * @todo-javadoc Describe the field
- */
- private ArrayList _interfaces;
-
/**
* @todo-javadoc Describe the field
*/
@@ -101,7 +96,6 @@
* @todo-javadoc Describe the field
*/
private HashMap _namedMethods;
-
/**
* @todo-javadoc Describe the field
*/
@@ -110,7 +104,6 @@
* @todo-javadoc Describe the field
*/
private ArrayList _fields;
-
/**
* @todo-javadoc Describe the field
*/
@@ -119,22 +112,18 @@
* @todo-javadoc Describe the field
*/
private ArrayList _innerClasses;
-
/**
* @todo-javadoc Describe the field
*/
private boolean _isInterface;
-
/**
* @todo-javadoc Describe the field
*/
private String _superclass;
-
/**
* @todo-javadoc Describe the field
*/
private String _containingPackage = "";
-
/**
* @todo-javadoc Describe the field
*/
@@ -152,12 +141,10 @@
* @todo-javadoc Describe the field
*/
final static XPackage[] ZERO_PACKAGES = new XPackage[0];
-
/**
* @todo-javadoc Describe the field
*/
final static XMethod[] ZERO_METHODS = new XMethod[0];
-
/**
* Get static reference to Log4J Logger
*/
@@ -428,8 +415,7 @@
_xinnerClasses = new XClass[_innerClasses.size()];
for (int i = 0; i < _innerClasses.size(); i++) {
- String inner_class = (String)_innerClasses.get(i);
- _xinnerClasses[i] = qualify(inner_class);
+ _xinnerClasses[i] = (XClass)_innerClasses.get(i);
}
}
_______________________________________________
Xdoclet-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/xdoclet-devel