You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commons-dev@ws.apache.org by ve...@apache.org on 2009/08/02 10:00:47 UTC

svn commit: r800006 - in /webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect: BaseXLXPDialect.java CompliantXLXPDialect.java NonCompliantXLXPDialect.java StAXDialectDetector.java

Author: veithen
Date: Sun Aug  2 08:00:46 2009
New Revision: 800006

URL: http://svn.apache.org/viewvc?rev=800006&view=rev
Log:
Improved the StAX dialect detection algorithm and added support for XLXP.

Added:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/BaseXLXPDialect.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/CompliantXLXPDialect.java   (with props)
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NonCompliantXLXPDialect.java   (with props)
Modified:
    webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialectDetector.java

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/BaseXLXPDialect.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/BaseXLXPDialect.java?rev=800006&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/BaseXLXPDialect.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/BaseXLXPDialect.java Sun Aug  2 08:00:46 2009
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.util.stax.dialect;
+
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLOutputFactory;
+
+abstract class BaseXLXPDialect implements StAXDialect {
+    public void enableCDataReporting(XMLInputFactory factory) {
+        // TODO: check if that is enough
+        factory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE);
+    }
+
+    public XMLInputFactory makeThreadSafe(XMLInputFactory factory) {
+        // XLXP's factories are thread safe
+        return factory;
+    }
+
+    public XMLOutputFactory makeThreadSafe(XMLOutputFactory factory) {
+        // XLXP's factories are thread safe
+        return factory;
+    }
+
+    public XMLInputFactory normalize(XMLInputFactory factory) {
+        return factory;
+    }
+
+    public XMLOutputFactory normalize(XMLOutputFactory factory) {
+        return factory;
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/BaseXLXPDialect.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/CompliantXLXPDialect.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/CompliantXLXPDialect.java?rev=800006&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/CompliantXLXPDialect.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/CompliantXLXPDialect.java Sun Aug  2 08:00:46 2009
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.util.stax.dialect;
+
+class CompliantXLXPDialect extends BaseXLXPDialect {
+    public static final StAXDialect INSTANCE = new CompliantXLXPDialect();
+    
+    public String getName() {
+        return "XL XP-J (StAX compliant versions)";
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/CompliantXLXPDialect.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NonCompliantXLXPDialect.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NonCompliantXLXPDialect.java?rev=800006&view=auto
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NonCompliantXLXPDialect.java (added)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NonCompliantXLXPDialect.java Sun Aug  2 08:00:46 2009
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.axiom.util.stax.dialect;
+
+class NonCompliantXLXPDialect extends BaseXLXPDialect {
+    public static final StAXDialect INSTANCE = new NonCompliantXLXPDialect();
+    
+    public String getName() {
+        return "XL XP-J (StAX non-compliant versions)";
+    }
+}

Propchange: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/NonCompliantXLXPDialect.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialectDetector.java
URL: http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialectDetector.java?rev=800006&r1=800005&r2=800006&view=diff
==============================================================================
--- webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialectDetector.java (original)
+++ webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/util/stax/dialect/StAXDialectDetector.java Sun Aug  2 08:00:46 2009
@@ -57,9 +57,7 @@
      * Map that stores detected dialects by location. The location is the URL corresponding to the
      * root folder of the classpath entry from which the StAX implementation is loaded. Note that
      * in the case of a JAR file, this is not the URL pointing to the JAR, but a <tt>jar:</tt>
-     * URL that points to the root folder of the archive. The <code>null</code> location is used
-     * to represent StAX implementations that are loaded from the bootstrap class loader, i.e.
-     * which are part of the JRE.
+     * URL that points to the root folder of the archive.
      */
     private static final Map/*<URL,StAXDialect>*/ dialectByUrl =
             Collections.synchronizedMap(new HashMap());
@@ -75,6 +73,12 @@
      *         possible to determine the root URL
      */
     private static URL getRootUrlForResource(ClassLoader classLoader, String resource) {
+        if (classLoader == null) {
+            // A null class loader means the bootstrap class loader. In this case we use the
+            // system class loader. This is safe since we can assume that the system class
+            // loader uses parent first as delegation policy.
+            classLoader = ClassLoader.getSystemClassLoader();
+        }
         URL url = classLoader.getResource(resource);
         if (url == null) {
             return null;
@@ -92,6 +96,11 @@
         }
     }
     
+    private static URL getRootUrlForClass(Class cls) {
+        return getRootUrlForResource(cls.getClassLoader(),
+                cls.getName().replace('.', '/') + ".class");
+    }
+    
     /**
      * Detect the dialect of a given {@link XMLInputFactory} and normalize it.
      * 
@@ -127,85 +136,46 @@
      * @return the detected dialect
      */
     public static StAXDialect getDialect(Class implementationClass) {
-        URL rootUrl;
-        ClassLoader classLoader = implementationClass.getClassLoader();
-        if (classLoader == null) {
-            // null means bootstrap classloader; represent this location as null
-            rootUrl = null;
-        } else {
-            rootUrl = getRootUrlForResource(classLoader,
-                    implementationClass.getName().replace('.', '/') + ".class");
-            if (rootUrl == null) {
-                log.warn("Unable to determine location of StAX implementation containing class "
-                        + implementationClass.getName() + "; using default dialect");
-                return UnknownStAXDialect.INSTANCE;
-            }
+        URL rootUrl = getRootUrlForClass(implementationClass);
+        if (rootUrl == null) {
+            log.warn("Unable to determine location of StAX implementation containing class "
+                    + implementationClass.getName() + "; using default dialect");
+            return UnknownStAXDialect.INSTANCE;
         }
-        return getDialect(rootUrl);
+        return getDialect(implementationClass.getClassLoader(), rootUrl);
     }
 
-    private static StAXDialect getDialect(URL rootUrl) {
+    private static StAXDialect getDialect(ClassLoader classLoader, URL rootUrl) {
         StAXDialect dialect = (StAXDialect)dialectByUrl.get(rootUrl);
         if (dialect != null) {
             return dialect;
         } else {
-            dialect = detectDialect(rootUrl);
+            dialect = detectDialect(classLoader, rootUrl);
             dialectByUrl.put(rootUrl, dialect);
             return dialect;
         }
     }
     
-    private static StAXDialect detectDialect(URL rootUrl) {
-        StAXDialect dialect;
-        if (rootUrl == null) {
-            dialect = detectDialectFromJRE();
-        } else {
-            dialect = detectDialectFromJar(rootUrl);
-        }
-        if (log.isInfoEnabled()) {
-            log.info("Detected StAX dialect: " + dialect.getName());
+    private static StAXDialect detectDialect(ClassLoader classLoader, URL rootUrl) {
+        StAXDialect dialect = detectDialectFromJarManifest(rootUrl);
+        if (dialect == null) {
+            // Note: We look for well defined classes instead of just checking the package name
+            // of the class passed to getDialect(Class) because in some parsers, the implementations
+            // of the StAX interfaces (factories, readers and writers) are not in the same package.
+            dialect = detectDialectFromClasses(classLoader, rootUrl);
         }
-        return dialect;
-    }
-    
-    /**
-     * Check that a given class is part of the bootstrap classes. This method is used to detect
-     * different JRE flavors and to check which StAX implementation is part of the JRE.
-     * <p>
-     * Note: We look for a well defined class instead of just checking the package name of the class
-     * passed to {@link #getDialect(Class)} because on some JREs, the implementations of the StAX
-     * interfaces (factories, readers and writers) are not in the same package.
-     * 
-     * @param className
-     *            the class name
-     * @return <code>true</code> if the class can be loaded from the bootstrap class loader
-     */
-    private static boolean isBootstrapClass(String className) {
-        try {
-            Class cls = ClassLoader.getSystemClassLoader().loadClass(className);
-            return cls.getClassLoader() == null;
-        } catch (ClassNotFoundException ex) {
-            return false;
-        }
-    }
-    
-    private static StAXDialect detectDialectFromJRE() {
-        String vendor = System.getProperty("java.vendor");
-        String version = System.getProperty("java.version");
-        if (log.isDebugEnabled()) {
-            log.debug("StAX implementation is part of the JRE:\n" +
-                    "  Vendor:  " + vendor + "\n" +
-                    "  Version: " + version);
-        }
-        if (isBootstrapClass("com.sun.xml.internal.stream.XMLInputFactoryImpl")) {
-            return SJSXPDialect.INSTANCE;
-        } else {
-            log.warn("Unable to determine dialect of StAX implementation provided by the JRE");
+        if (dialect == null) {
+            log.warn("Unable to determine dialect of the StAX implementation at " + rootUrl);
             return UnknownStAXDialect.INSTANCE;
+        } else {
+            if (log.isInfoEnabled()) {
+                log.info("Detected StAX dialect: " + dialect.getName());
+            }
+            return dialect;
         }
     }
     
-    private static StAXDialect detectDialectFromJar(URL rootUrl) {
+    private static StAXDialect detectDialectFromJarManifest(URL rootUrl) {
         Manifest manifest;
         try {
             URL metaInfUrl = new URL(rootUrl, "META-INF/MANIFEST.MF");
@@ -236,9 +206,41 @@
         } else if (title != null && title.indexOf("SJSXP") != -1) {
             return SJSXPDialect.INSTANCE;
         } else {
-            log.warn("Unable to determine dialect of the StAX implementation at " + rootUrl
-                    + " (using JAR manifest)");
-            return UnknownStAXDialect.INSTANCE;
+            return null;
+        }
+    }
+
+    private static Class loadClass(ClassLoader classLoader, URL rootUrl, String name) {
+        try {
+            Class cls = classLoader.loadClass(name);
+            // Cross check if the class was loaded from the same location (JAR)
+            return rootUrl.equals(getRootUrlForClass(cls)) ? cls : null;
+        } catch (ClassNotFoundException ex) {
+            return null;
+        }
+    }
+    
+    private static StAXDialect detectDialectFromClasses(ClassLoader classLoader, URL rootUrl) {
+        // Try Sun's implementation found in JREs
+        if (loadClass(classLoader, rootUrl, "com.sun.xml.internal.stream.XMLInputFactoryImpl")
+                != null) {
+            return SJSXPDialect.INSTANCE;
+        }
+        
+        // Try IBM's XL XP-J
+        Class cls = loadClass(classLoader, rootUrl, "com.ibm.xml.xlxp.api.stax.StAXImplConstants");
+        if (cls != null) {
+            boolean isStAXCompliant;
+            try {
+                cls.getField("IS_SETPREFIX_BEFORE_STARTELEMENT");
+                isStAXCompliant = true;
+            } catch (NoSuchFieldException ex) {
+                isStAXCompliant = false;
+            }
+            return isStAXCompliant ? CompliantXLXPDialect.INSTANCE
+                    : NonCompliantXLXPDialect.INSTANCE;
         }
+        
+        return null;
     }
 }