src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java
Print this page
*** 32,49 ****
import org.xml.sax.InputSource;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
! import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessController;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Factory for {@link XMLStreamReader}.
*
* <p>
* This wraps {@link XMLInputFactory} and allows us to reuse {@link XMLStreamReader} instances
--- 32,56 ----
import org.xml.sax.InputSource;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
! import java.io.IOException;
! import java.io.InputStream;
! import java.io.InputStreamReader;
! import java.io.Reader;
! import java.io.StringReader;
! import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.security.AccessController;
import java.util.logging.Level;
import java.util.logging.Logger;
+ import com.sun.xml.internal.ws.resources.StreamingMessages;
+
/**
* Factory for {@link XMLStreamReader}.
*
* <p>
* This wraps {@link XMLInputFactory} and allows us to reuse {@link XMLStreamReader} instances
*** 59,68 ****
--- 66,77 ----
/**
* Singleton instance.
*/
private static volatile @NotNull XMLStreamReaderFactory theInstance;
+ private static final String CLASS_NAME_OF_WSTXINPUTFACTORY = "com.ctc.wstx.stax.WstxInputFactory";
+
static {
XMLInputFactory xif = getXMLInputFactory();
XMLStreamReaderFactory f=null;
// this system property can be used to disable the pooling altogether,
*** 71,112 ****
f = Zephyr.newInstance(xif);
}
if(f==null) {
// is this Woodstox?
! if (xif.getClass().getName().equals("com.ctc.wstx.stax.WstxInputFactory")) {
f = new Woodstox(xif);
}
}
if (f==null) {
f = new Default();
}
theInstance = f;
LOGGER.log(Level.FINE, "XMLStreamReaderFactory instance is = {0}", theInstance);
}
private static XMLInputFactory getXMLInputFactory() {
XMLInputFactory xif = null;
if (getProperty(XMLStreamReaderFactory.class.getName()+".woodstox")) {
try {
xif = (XMLInputFactory)Class.forName("com.ctc.wstx.stax.WstxInputFactory").newInstance();
} catch (Exception e) {
! // Ignore and fallback to default XMLInputFactory
}
}
if (xif == null) {
xif = XmlUtil.newXMLInputFactory(true);
}
xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
xif.setProperty(XMLInputFactory.IS_COALESCING, true);
return xif;
}
-
/**
* Overrides the singleton {@link XMLStreamReaderFactory} instance that
* the JAX-WS RI uses.
*/
public static void set(XMLStreamReaderFactory f) {
--- 80,125 ----
f = Zephyr.newInstance(xif);
}
if(f==null) {
// is this Woodstox?
! if (xif.getClass().getName().equals(CLASS_NAME_OF_WSTXINPUTFACTORY)) {
f = new Woodstox(xif);
}
}
if (f==null) {
f = new Default();
}
theInstance = f;
+ if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.log(Level.FINE, "XMLStreamReaderFactory instance is = {0}", theInstance);
}
+ }
private static XMLInputFactory getXMLInputFactory() {
XMLInputFactory xif = null;
if (getProperty(XMLStreamReaderFactory.class.getName()+".woodstox")) {
try {
xif = (XMLInputFactory)Class.forName("com.ctc.wstx.stax.WstxInputFactory").newInstance();
} catch (Exception e) {
! if (LOGGER.isLoggable(Level.WARNING)) {
! LOGGER.log(Level.WARNING, StreamingMessages.WOODSTOX_CANT_LOAD(CLASS_NAME_OF_WSTXINPUTFACTORY), e);
! }
}
}
if (xif == null) {
xif = XmlUtil.newXMLInputFactory(true);
}
xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
xif.setProperty(XMLInputFactory.IS_COALESCING, true);
+
return xif;
}
/**
* Overrides the singleton {@link XMLStreamReaderFactory} instance that
* the JAX-WS RI uses.
*/
public static void set(XMLStreamReaderFactory f) {
*** 166,176 ****
* instance. Not doing so just reduces the performance by throwing away
* possibly reusable instances. So the caller should always consider the effort
* it takes to recycle vs the possible performance gain by doing so.
*
* <p>
! * This method may be invked by multiple threads concurrently.
*
* @param r
* The {@link XMLStreamReader} instance that the caller finished using.
* This could be any {@link XMLStreamReader} implementation, not just
* the ones that were created from this factory. So the implementation
--- 179,189 ----
* instance. Not doing so just reduces the performance by throwing away
* possibly reusable instances. So the caller should always consider the effort
* it takes to recycle vs the possible performance gain by doing so.
*
* <p>
! * This method may be invoked by multiple threads concurrently.
*
* @param r
* The {@link XMLStreamReader} instance that the caller finished using.
* This could be any {@link XMLStreamReader} implementation, not just
* the ones that were created from this factory. So the implementation
*** 280,294 ****
--- 293,309 ----
if(sr==null) return null;
pool.set(null);
return sr;
}
+ @Override
public void doRecycle(XMLStreamReader r) {
if(zephyrClass.isInstance(r))
pool.set(r);
}
+ @Override
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
try {
XMLStreamReader xsr = fetch();
if(xsr==null)
return xif.createXMLStreamReader(systemId,in);
*** 305,314 ****
--- 320,330 ----
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
+ @Override
public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
try {
XMLStreamReader xsr = fetch();
if(xsr==null)
return xif.createXMLStreamReader(systemId,in);
*** 343,379 ****
*
* <p>
* {@link XMLInputFactory} is not required to be thread-safe, but
* if the create method on this implementation is synchronized,
* it may run into (see <a href="https://jax-ws.dev.java.net/issues/show_bug.cgi?id=555">
! * race condition</a>). Hence, using a XMLInputFactory per theread.
*/
public static final class Default extends XMLStreamReaderFactory {
private final ThreadLocal<XMLInputFactory> xif = new ThreadLocal<XMLInputFactory>() {
@Override
public XMLInputFactory initialValue() {
return getXMLInputFactory();
}
};
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
try {
return xif.get().createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
try {
return xif.get().createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
public void doRecycle(XMLStreamReader r) {
// there's no way to recycle with the default StAX API.
}
}
--- 359,398 ----
*
* <p>
* {@link XMLInputFactory} is not required to be thread-safe, but
* if the create method on this implementation is synchronized,
* it may run into (see <a href="https://jax-ws.dev.java.net/issues/show_bug.cgi?id=555">
! * race condition</a>). Hence, using a XMLInputFactory per thread.
*/
public static final class Default extends XMLStreamReaderFactory {
private final ThreadLocal<XMLInputFactory> xif = new ThreadLocal<XMLInputFactory>() {
@Override
public XMLInputFactory initialValue() {
return getXMLInputFactory();
}
};
+ @Override
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
try {
return xif.get().createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
+ @Override
public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
try {
return xif.get().createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
+ @Override
public void doRecycle(XMLStreamReader r) {
// there's no way to recycle with the default StAX API.
}
}
*** 389,444 ****
public NoLock(XMLInputFactory xif) {
this.xif = xif;
}
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
try {
return xif.createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
try {
return xif.createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
public void doRecycle(XMLStreamReader r) {
// there's no way to recycle with the default StAX API.
}
}
/**
! * Handles Woodstox's XIF but set properties to do the string interning.
* Woodstox {@link XMLInputFactory} is thread safe.
*/
public static final class Woodstox extends NoLock {
public Woodstox(XMLInputFactory xif) {
super(xif);
! xif.setProperty("org.codehaus.stax2.internNsUris",true);
}
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
return super.doCreate(systemId, in, rejectDTDs);
}
public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
return super.doCreate(systemId, in, rejectDTDs);
}
}
private static Boolean getProperty(final String prop) {
return AccessController.doPrivileged(
new java.security.PrivilegedAction<Boolean>() {
public Boolean run() {
String value = System.getProperty(prop);
return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
}
}
);
}
}
--- 408,615 ----
public NoLock(XMLInputFactory xif) {
this.xif = xif;
}
+ @Override
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
try {
return xif.createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
+ @Override
public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
try {
return xif.createXMLStreamReader(systemId,in);
} catch (XMLStreamException e) {
throw new XMLReaderException("stax.cantCreate",e);
}
}
+ @Override
public void doRecycle(XMLStreamReader r) {
// there's no way to recycle with the default StAX API.
}
}
/**
! * Handles Woodstox's XIF, but sets properties to do the string interning, sets various limits, ...
* Woodstox {@link XMLInputFactory} is thread safe.
*/
public static final class Woodstox extends NoLock {
+
+ public final static String PROPERTY_MAX_ATTRIBUTES_PER_ELEMENT = "xml.ws.maximum.AttributesPerElement";
+ public final static String PROPERTY_MAX_ATTRIBUTE_SIZE = "xml.ws.maximum.AttributeSize";
+ public final static String PROPERTY_MAX_CHILDREN_PER_ELEMENT = "xml.ws.maximum.ChildrenPerElement";
+ public final static String PROPERTY_MAX_ELEMENT_COUNT = "xml.ws.maximum.ElementCount";
+ public final static String PROPERTY_MAX_ELEMENT_DEPTH = "xml.ws.maximum.ElementDepth";
+ public final static String PROPERTY_MAX_CHARACTERS = "xml.ws.maximum.Characters";
+
+ private static final int DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT = 500;
+ private static final int DEFAULT_MAX_ATTRIBUTE_SIZE = 65536 * 8;
+ private static final int DEFAULT_MAX_CHILDREN_PER_ELEMENT = Integer.MAX_VALUE;
+ private static final int DEFAULT_MAX_ELEMENT_DEPTH = 500;
+ private static final long DEFAULT_MAX_ELEMENT_COUNT = Integer.MAX_VALUE;
+ private static final long DEFAULT_MAX_CHARACTERS = Long.MAX_VALUE;
+
+ /* Woodstox default setting:
+ int mMaxAttributesPerElement = 1000;
+ int mMaxAttributeSize = 65536 * 8;
+ int mMaxChildrenPerElement = Integer.MAX_VALUE;
+ int mMaxElementDepth = 1000;
+ long mMaxElementCount = Long.MAX_VALUE;
+ long mMaxCharacters = Long.MAX_VALUE;
+ */
+
+ private int maxAttributesPerElement = DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT;
+ private int maxAttributeSize = DEFAULT_MAX_ATTRIBUTE_SIZE;
+ private int maxChildrenPerElement = DEFAULT_MAX_CHILDREN_PER_ELEMENT;
+ private int maxElementDepth = DEFAULT_MAX_ELEMENT_DEPTH;
+ private long maxElementCount = DEFAULT_MAX_ELEMENT_COUNT;
+ private long maxCharacters = DEFAULT_MAX_CHARACTERS;
+
+ // Note: this is a copy from com.ctc.wstx.api.WstxInputProperties, to be removed in the future
+ private static final java.lang.String P_MAX_ATTRIBUTES_PER_ELEMENT = "com.ctc.wstx.maxAttributesPerElement";
+ private static final java.lang.String P_MAX_ATTRIBUTE_SIZE = "com.ctc.wstx.maxAttributeSize";
+ private static final java.lang.String P_MAX_CHILDREN_PER_ELEMENT = "com.ctc.wstx.maxChildrenPerElement";
+ private static final java.lang.String P_MAX_ELEMENT_COUNT = "com.ctc.wstx.maxElementCount";
+ private static final java.lang.String P_MAX_ELEMENT_DEPTH = "com.ctc.wstx.maxElementDepth";
+ private static final java.lang.String P_MAX_CHARACTERS = "com.ctc.wstx.maxCharacters";
+ private static final java.lang.String P_INTERN_NSURIS = "org.codehaus.stax2.internNsUris";
+
public Woodstox(XMLInputFactory xif) {
super(xif);
!
! if (xif.isPropertySupported(P_INTERN_NSURIS)) {
! xif.setProperty(P_INTERN_NSURIS, true);
! if (LOGGER.isLoggable(Level.FINE)) {
! LOGGER.log(Level.FINE, P_INTERN_NSURIS + " is {0}", true);
! }
! }
!
! if (xif.isPropertySupported(P_MAX_ATTRIBUTES_PER_ELEMENT)) {
! maxAttributesPerElement = Integer.valueOf(buildIntegerValue(
! PROPERTY_MAX_ATTRIBUTES_PER_ELEMENT, DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT)
! );
! xif.setProperty(P_MAX_ATTRIBUTES_PER_ELEMENT, maxAttributesPerElement);
! if (LOGGER.isLoggable(Level.FINE)) {
! LOGGER.log(Level.FINE, P_MAX_ATTRIBUTES_PER_ELEMENT + " is {0}", maxAttributesPerElement);
! }
! }
!
! if (xif.isPropertySupported(P_MAX_ATTRIBUTE_SIZE)) {
! maxAttributeSize = Integer.valueOf(buildIntegerValue(
! PROPERTY_MAX_ATTRIBUTE_SIZE, DEFAULT_MAX_ATTRIBUTE_SIZE)
! );
! xif.setProperty(P_MAX_ATTRIBUTE_SIZE, maxAttributeSize);
! if (LOGGER.isLoggable(Level.FINE)) {
! LOGGER.log(Level.FINE, P_MAX_ATTRIBUTE_SIZE + " is {0}", maxAttributeSize);
! }
! }
!
! if (xif.isPropertySupported(P_MAX_CHILDREN_PER_ELEMENT)) {
! maxChildrenPerElement = Integer.valueOf(buildIntegerValue(
! PROPERTY_MAX_CHILDREN_PER_ELEMENT, DEFAULT_MAX_CHILDREN_PER_ELEMENT)
! );
! xif.setProperty(P_MAX_CHILDREN_PER_ELEMENT, maxChildrenPerElement);
! if (LOGGER.isLoggable(Level.FINE)) {
! LOGGER.log(Level.FINE, P_MAX_CHILDREN_PER_ELEMENT + " is {0}", maxChildrenPerElement);
! }
}
+ if (xif.isPropertySupported(P_MAX_ELEMENT_DEPTH)) {
+ maxElementDepth = Integer.valueOf(buildIntegerValue(
+ PROPERTY_MAX_ELEMENT_DEPTH, DEFAULT_MAX_ELEMENT_DEPTH)
+ );
+ xif.setProperty(P_MAX_ELEMENT_DEPTH, maxElementDepth);
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.log(Level.FINE, P_MAX_ELEMENT_DEPTH + " is {0}", maxElementDepth);
+ }
+ }
+
+ if (xif.isPropertySupported(P_MAX_ELEMENT_COUNT)) {
+ maxElementCount = Long.valueOf(buildLongValue(
+ PROPERTY_MAX_ELEMENT_COUNT, DEFAULT_MAX_ELEMENT_COUNT)
+ );
+ xif.setProperty(P_MAX_ELEMENT_COUNT, maxElementCount);
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.log(Level.FINE, P_MAX_ELEMENT_COUNT + " is {0}", maxElementCount);
+ }
+ }
+
+ if (xif.isPropertySupported(P_MAX_CHARACTERS)) {
+ maxCharacters = Long.valueOf(buildLongValue(
+ PROPERTY_MAX_CHARACTERS, DEFAULT_MAX_CHARACTERS)
+ );
+ xif.setProperty(P_MAX_CHARACTERS, maxCharacters);
+ if (LOGGER.isLoggable(Level.FINE)) {
+ LOGGER.log(Level.FINE, P_MAX_CHARACTERS + " is {0}", maxCharacters);
+ }
+ }
+ }
+
+ @Override
public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
return super.doCreate(systemId, in, rejectDTDs);
}
+ @Override
public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
return super.doCreate(systemId, in, rejectDTDs);
}
}
+ private static int buildIntegerValue(String propertyName, int defaultValue) {
+ String propVal = System.getProperty(propertyName);
+ if (propVal != null && propVal.length() > 0) {
+ try {
+ Integer value = Integer.parseInt(propVal);
+ if (value > 0) {
+ // return with the value in System property
+ return value;
+ }
+ } catch (NumberFormatException nfe) {
+ if (LOGGER.isLoggable(Level.WARNING)) {
+ LOGGER.log(Level.WARNING, StreamingMessages.INVALID_PROPERTY_VALUE_INTEGER(propertyName, propVal, Integer.toString(defaultValue)), nfe);
+ }
+ }
+ }
+ // return with the default value
+ return defaultValue;
+ }
+
+ private static long buildLongValue(String propertyName, long defaultValue) {
+ String propVal = System.getProperty(propertyName);
+ if (propVal != null && propVal.length() > 0) {
+ try {
+ long value = Long.parseLong(propVal);
+ if (value > 0L) {
+ // return with the value in System property
+ return value;
+ }
+ } catch (NumberFormatException nfe) {
+ // defult will be returned
+ if (LOGGER.isLoggable(Level.WARNING)) {
+ LOGGER.log(Level.WARNING, StreamingMessages.INVALID_PROPERTY_VALUE_LONG(propertyName, propVal, Long.toString(defaultValue)), nfe);
+ }
+ }
+ }
+ // return with the default value
+ return defaultValue;
+ }
+
private static Boolean getProperty(final String prop) {
return AccessController.doPrivileged(
new java.security.PrivilegedAction<Boolean>() {
+ @Override
public Boolean run() {
String value = System.getProperty(prop);
return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
}
}
);
}
+
}