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; } } ); } + }