Author: veithen
Date: Sat Apr 18 11:28:34 2009
New Revision: 766302

URL: http://svn.apache.org/viewvc?rev=766302&view=rev
Log:
WSCOMMONS-461: Allow StAXUtils to apply properties to XMLInputFactory and 
XMLOutputFactory.

Modified:
    
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java

Modified: 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java
URL: 
http://svn.apache.org/viewvc/webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java?rev=766302&r1=766301&r2=766302&view=diff
==============================================================================
--- 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java
 (original)
+++ 
webservices/commons/trunk/modules/axiom/modules/axiom-api/src/main/java/org/apache/axiom/om/util/StAXUtils.java
 Sat Apr 18 11:28:34 2009
@@ -32,6 +32,7 @@
 import javax.xml.stream.XMLStreamWriter;
 
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.Reader;
@@ -41,10 +42,49 @@
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Properties;
 import java.util.WeakHashMap;
 
-
+/**
+ * Utility class containing StAX related methods.
+ * <p>This class defines a set of methods to get {...@link XMLStreamReader} 
and {...@link XMLStreamWriter}
+ * instances. This class caches the corresponding factories ({...@link 
XMLInputFactory}
+ * and {...@link XMLOutputFactory} objects) by classloader (default) or as 
singletons.
+ * The behavior can be changed using {...@link 
#setFactoryPerClassLoader(boolean)}.</p>
+ * <p>Default properties for these factories can be specified using
+ * <tt>XMLInputFactory.properties</tt> and 
<tt>XMLOutputFactory.properties</tt> files.
+ * When a new factory is instantiated, this class will attempt to load the 
corresponding file using
+ * the context classloader. This class supports properties with boolean, 
integer and string values.
+ * Both standard StAX properties and implementation specific properties can be 
specified. This
+ * feature should be used with care since changing some properties to non 
default values will break
+ * Axiom. Good candidates for <tt>XMLInputFactory.properties</tt> are:</p>
+ * <dl>
+ *   <dt><tt>javax.xml.stream.isCoalescing</tt></dt>
+ *   <dd>Requires the processor to coalesce adjacent character data (text 
nodes and CDATA
+ *       sections). This property also controls whether CDATA sections are 
reported or not.</dd>
+ *   <dt><tt>com.ctc.wstx.inputBufferLength</tt></dt>
+ *   <dd>Size of input buffer (in chars), to use for reading XML content from 
input stream/reader.
+ *       This property is Woodstox specific.</dd>
+ *   <dt><tt>com.ctc.wstx.minTextSegment</tt></dt>
+ *   <dd>Property to specify shortest non-complete text segment (part of CDATA 
section or text
+ *       content) that the parser is allowed to return, if not required to 
coalesce text.
+ *       This property is Woodstox specific.</dt>
+ * </dl>
+ * <p>Good candidates for <tt>XMLOutputFactory.properties</tt> are:</p>
+ * <dl>
+ *   <dt><tt>com.ctc.wstx.outputEscapeCr</tt></dt>
+ *   <dd>Property that determines whether Carriage Return (\r) characters are 
to be escaped when
+ *       output or not. If enabled, all instances of of character \r are 
escaped using a character
+ *       entity (where possible, that is, within CHARACTERS events, and 
attribute values).
+ *       Otherwise they are output as is. The main reason to enable this 
property is to ensure
+ *       that carriage returns are preserved as is through parsing, since 
otherwise they will be
+ *       converted to canonical XML linefeeds (\n), when occurring along or as 
part of \r\n pair.
+ *       This property is Woodstox specific.</dd>
+ * </dl>
+ */
 public class StAXUtils {
     private static Log log = LogFactory.getLog(StAXUtils.class);
     private static boolean isDebugEnabled = log.isDebugEnabled();
@@ -290,9 +330,68 @@
     public static void reset() {
     }
     
+    /**
+     * Load factory properties from a resource. The context class loader is 
used to locate
+     * the resource. The method converts boolean and integer values to the 
right Java types.
+     * All other values are returned as strings.
+     * 
+     * @param name
+     * @return
+     */
+    private static Map loadFactoryProperties(String name) {
+        ClassLoader cl = getContextClassLoader();
+        InputStream in = cl.getResourceAsStream(name);
+        if (in == null) {
+            return null;
+        } else {
+            try {
+                Properties rawProps = new Properties();
+                Map props = new HashMap();
+                rawProps.load(in);
+                for (Iterator it = rawProps.entrySet().iterator(); 
it.hasNext(); ) {
+                    Map.Entry entry = (Map.Entry)it.next();
+                    String strValue = (String)entry.getValue();
+                    Object value;
+                    if (strValue.equals("true")) {
+                        value = Boolean.TRUE;
+                    } else if (strValue.equals("false")) {
+                        value = Boolean.FALSE;
+                    } else {
+                        try {
+                            value = Integer.valueOf(strValue);
+                        } catch (NumberFormatException ex) {
+                            value = strValue;
+                        }
+                    }
+                    props.put(entry.getKey(), value);
+                }
+                if (log.isDebugEnabled()) {
+                    log.debug("Loaded factory properties from " + name + ": " 
+ props);
+                }
+                return props;
+            } catch (IOException ex) {
+                log.error("Failed to read " + name, ex);
+                return null;
+            } finally {
+                try {
+                    in.close();
+                } catch (IOException ex) {
+                    // Ignore
+                }
+            }
+        }
+    }
+    
     // This has package access since it is used from within anonymous inner 
classes
     static XMLInputFactory newXMLInputFactory(boolean isNetworkDetached) {
         XMLInputFactory factory = XMLInputFactory.newInstance();
+        Map props = loadFactoryProperties("XMLInputFactory.properties");
+        if (props != null) {
+            for (Iterator it = props.entrySet().iterator(); it.hasNext(); ) {
+                Map.Entry entry = (Map.Entry)it.next();
+                factory.setProperty((String)entry.getKey(), entry.getValue());
+            }
+        }
         if (isNetworkDetached) {
             
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, 
                       Boolean.FALSE);
@@ -438,6 +537,21 @@
         return f;
     }
     
+    // This has package access since it is used from within anonymous inner 
classes
+    static XMLOutputFactory newXMLOutputFactory() {
+        XMLOutputFactory factory = XMLOutputFactory.newInstance();
+        factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, 
+                            Boolean.FALSE);
+        Map props = loadFactoryProperties("XMLOutputFactory.properties");
+        if (props != null) {
+            for (Iterator it = props.entrySet().iterator(); it.hasNext(); ) {
+                Map.Entry entry = (Map.Entry)it.next();
+                factory.setProperty((String)entry.getKey(), entry.getValue());
+            }
+        }
+        return factory;
+    }
+    
     /**
      * @return XMLOutputFactory for the current classloader
      */
@@ -460,10 +574,7 @@
                     AccessController.doPrivileged(
                         new PrivilegedAction() {
                             public Object run() {
-                                XMLOutputFactory factory = 
XMLOutputFactory.newInstance();
-                                
factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, 
-                                                    Boolean.FALSE);
-                                return factory;
+                                return newXMLOutputFactory();
                             }
                         });
                 } catch (ClassCastException cce) {
@@ -478,20 +589,16 @@
                     AccessController.doPrivileged(
                         new PrivilegedAction() {
                             public Object run() {
-                                XMLOutputFactory f = null;
                                 ClassLoader saveCL = getContextClassLoader();
                                 try {                              
                                     Thread.currentThread().
                                         setContextClassLoader(
                                            
XMLOutputFactory.class.getClassLoader());
-                                    f =XMLOutputFactory.newInstance();
-                                    
f.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, 
-                                                        Boolean.FALSE);
+                                    return newXMLOutputFactory();
                                 } finally {
                                     Thread.currentThread().
                                         setContextClassLoader(saveCL);
                                 }
-                                return f;
                             }
                         });
                 }
@@ -522,17 +629,13 @@
 
                             Thread currentThread = Thread.currentThread();
                             ClassLoader savedClassLoader = 
currentThread.getContextClassLoader();
-                            XMLOutputFactory factory = null;
                             try {
                                 
currentThread.setContextClassLoader(StAXUtils.class.getClassLoader());
-                                factory = XMLOutputFactory.newInstance();
-                                
factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, 
-                                                    Boolean.FALSE);
+                                return newXMLOutputFactory();
                             }
                             finally {
                                 
currentThread.setContextClassLoader(savedClassLoader);
                             }
-                            return factory;
                         }
                     });
             if (log.isDebugEnabled()) {


Reply via email to