Tuesday, June 13, 2006

What version of xerces have I got?

Keywords:
xerces version print classpath parser

Problem:
This is kind of related to the previous two posts. With XML parsing + classpath issues it's often useful to know not only what version of Xerces you're using but also where it's been loaded from.

Solution:
This is based on the equivalently useful site of Java Almanac - Determining from Where a Class Was Loaded. The point they make about the system classloader is crucial: "It is not possible to determine the location of classes loaded by the system class loader in the same way since the class' code source is null."

If your Xerces is the one loaded by the system, then this may explain some unusual behaviour if your web application expects to ship with it's own version.

  public static String getXercesDetails() {
       // no hard-writed references to the version class because it might be unavailable
       Class c;
       Method m;
       Object obj;

       try {
           c = Class.forName("org.apache.xerces.impl.Version");
           m = c.getDeclaredMethod("getVersion", new Class[] {});
           if (Modifier.isStatic(m.getModifiers())) {
               // Xerces 2.x
               obj = null;
           } else {
               // Xerces 2.1.x
               obj = c.newInstance();
           }
          
           ProtectionDomain pDomain = c.getProtectionDomain();
           CodeSource cSource = pDomain.getCodeSource();
           String loc = "?";
           if (cSource != null) {
               loc = cSource.getLocation().toString();
           } else {
               // CodeSource is null, Xerces loaded by system class loaded.
               loc = "(system classloader? sun.boot.class.path = " + System.getProperty("sun.boot.class.path") + ")";
           }
          
           return ((String) m.invoke(obj, new Object[] {})) + " from " + loc;
       } catch (Exception e) {
           return "unkown (" + e.getMessage() + ")";
       }
   }


Notes:
Xerces (and Xalan) in the endorsed directory can cause some nasty issues for applications that expect to use their own version. See the JBoss Issue: JBAS-2073

Saturday, June 10, 2006

How do you print the java classpath?

Keywords:
java servlet "print classpath"

Problem:
This requirement came in trying to diagnose the previous post. It'd be quite useful in a any enterprise/web application to be able to see the classpath in use (perhaps via an administration page).

Solution:
This is based on post on Java Tips (very useful site), but with the difference that your web application will have a different classloader to the system one. You'll need the classloader being used by a class within the web application (such as the one responsible for producing your admin-output).

 public String getClasspathString() {
     StringBuffer classpath = new StringBuffer();
     ClassLoader applicationClassLoader = this.getClass().getClassLoader();
     if (applicationClassLoader == null) {
         applicationClassLoader = ClassLoader.getSystemClassLoader();
     }
     URL[] urls = ((URLClassLoader)applicationClassLoader).getURLs();
      for(int i=0; i < urls.length; i++) {
          classpath.append(urls[i].getFile()).append("\r\n");
      }    
     
      return classpath.toString();
  }

Friday, June 09, 2006

An invalid XML character (Unicode: 0x0) was found in the comment

Keywords:
xerces "An invalid XML character (Unicode: 0x0) was found in the comment"

Problem:
This is a very specific problem I admit, but what are you meant to do? From the error message list for the Xerces parser, it's clear that this "0x0" character is a bad thing, but it's also clear that I haven't put this character in the document.

Something's wrong with the reading/processing of the byte stream containing the XML content.

Solution:
A very specific solution too. In this case it was that file was being stored using a Slide implementation that came with JBoss. I don't know anything about this implementation, but it doesn't seem to work when you're accessing it (via WebDAV) with jakarta-slide-client libraries. Switching the storage to using the latest version from Jakarta fixed this issue.