src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java

changeset 0
373ffda63c9a
child 637
9c07ef4934dd
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/src/share/jaxws_classes/com/sun/xml/internal/ws/api/streaming/XMLStreamReaderFactory.java	Wed Apr 27 01:27:09 2016 +0800
     1.3 @@ -0,0 +1,619 @@
     1.4 +/*
     1.5 + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
     1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     1.7 + *
     1.8 + * This code is free software; you can redistribute it and/or modify it
     1.9 + * under the terms of the GNU General Public License version 2 only, as
    1.10 + * published by the Free Software Foundation.  Oracle designates this
    1.11 + * particular file as subject to the "Classpath" exception as provided
    1.12 + * by Oracle in the LICENSE file that accompanied this code.
    1.13 + *
    1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
    1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    1.17 + * version 2 for more details (a copy is included in the LICENSE file that
    1.18 + * accompanied this code).
    1.19 + *
    1.20 + * You should have received a copy of the GNU General Public License version
    1.21 + * 2 along with this work; if not, write to the Free Software Foundation,
    1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    1.23 + *
    1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    1.25 + * or visit www.oracle.com if you need additional information or have any
    1.26 + * questions.
    1.27 + */
    1.28 +
    1.29 +package com.sun.xml.internal.ws.api.streaming;
    1.30 +
    1.31 +import com.sun.istack.internal.NotNull;
    1.32 +import com.sun.istack.internal.Nullable;
    1.33 +import com.sun.xml.internal.ws.streaming.XMLReaderException;
    1.34 +import com.sun.xml.internal.ws.util.xml.XmlUtil;
    1.35 +import org.xml.sax.InputSource;
    1.36 +
    1.37 +import javax.xml.stream.XMLInputFactory;
    1.38 +import javax.xml.stream.XMLStreamException;
    1.39 +import javax.xml.stream.XMLStreamReader;
    1.40 +import java.io.IOException;
    1.41 +import java.io.InputStream;
    1.42 +import java.io.InputStreamReader;
    1.43 +import java.io.Reader;
    1.44 +import java.io.StringReader;
    1.45 +import java.io.UnsupportedEncodingException;
    1.46 +import java.lang.reflect.InvocationTargetException;
    1.47 +import java.lang.reflect.Method;
    1.48 +import java.net.URL;
    1.49 +import java.security.AccessController;
    1.50 +import java.util.logging.Level;
    1.51 +import java.util.logging.Logger;
    1.52 +
    1.53 +import com.sun.xml.internal.ws.resources.StreamingMessages;
    1.54 +
    1.55 +/**
    1.56 + * Factory for {@link XMLStreamReader}.
    1.57 + *
    1.58 + * <p>
    1.59 + * This wraps {@link XMLInputFactory} and allows us to reuse {@link XMLStreamReader} instances
    1.60 + * when appropriate.
    1.61 + *
    1.62 + * @author Kohsuke Kawaguchi
    1.63 + */
    1.64 +@SuppressWarnings("StaticNonFinalUsedInInitialization")
    1.65 +public abstract class XMLStreamReaderFactory {
    1.66 +
    1.67 +    private static final Logger LOGGER = Logger.getLogger(XMLStreamReaderFactory.class.getName());
    1.68 +
    1.69 +    private static final String CLASS_NAME_OF_WSTXINPUTFACTORY = "com.ctc.wstx.stax.WstxInputFactory";
    1.70 +
    1.71 +    /**
    1.72 +     * Singleton instance.
    1.73 +     */
    1.74 +    private static volatile ContextClassloaderLocal<XMLStreamReaderFactory> streamReader =
    1.75 +            new ContextClassloaderLocal<XMLStreamReaderFactory>() {
    1.76 +
    1.77 +                @Override
    1.78 +                protected XMLStreamReaderFactory initialValue() {
    1.79 +
    1.80 +                    XMLInputFactory xif = getXMLInputFactory();
    1.81 +                    XMLStreamReaderFactory f=null;
    1.82 +
    1.83 +                    // this system property can be used to disable the pooling altogether,
    1.84 +                    // in case someone hits an issue with pooling in the production system.
    1.85 +                    if(!getProperty(XMLStreamReaderFactory.class.getName()+".noPool")) {
    1.86 +                        f = Zephyr.newInstance(xif);
    1.87 +                    }
    1.88 +
    1.89 +                    if(f==null) {
    1.90 +                        // is this Woodstox?
    1.91 +                        if (xif.getClass().getName().equals(CLASS_NAME_OF_WSTXINPUTFACTORY)) {
    1.92 +                            f = new Woodstox(xif);
    1.93 +                        }
    1.94 +                    }
    1.95 +
    1.96 +                    if (f==null) {
    1.97 +                        f = new Default();
    1.98 +                    }
    1.99 +
   1.100 +                    if (LOGGER.isLoggable(Level.FINE)) {
   1.101 +                        LOGGER.log(Level.FINE, "XMLStreamReaderFactory instance is = {0}", f);
   1.102 +                    }
   1.103 +                    return f;
   1.104 +                }
   1.105 +            };
   1.106 +
   1.107 +    private static XMLInputFactory getXMLInputFactory() {
   1.108 +        XMLInputFactory xif = null;
   1.109 +        if (getProperty(XMLStreamReaderFactory.class.getName()+".woodstox")) {
   1.110 +            try {
   1.111 +                xif = (XMLInputFactory)Class.forName("com.ctc.wstx.stax.WstxInputFactory").newInstance();
   1.112 +            } catch (Exception e) {
   1.113 +                if (LOGGER.isLoggable(Level.WARNING)) {
   1.114 +                    LOGGER.log(Level.WARNING, StreamingMessages.WOODSTOX_CANT_LOAD(CLASS_NAME_OF_WSTXINPUTFACTORY), e);
   1.115 +                }
   1.116 +            }
   1.117 +        }
   1.118 +        if (xif == null) {
   1.119 +             xif = XmlUtil.newXMLInputFactory(true);
   1.120 +        }
   1.121 +        xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
   1.122 +        xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
   1.123 +        xif.setProperty(XMLInputFactory.IS_COALESCING, true);
   1.124 +
   1.125 +        return xif;
   1.126 +    }
   1.127 +
   1.128 +    /**
   1.129 +     * Overrides the singleton {@link XMLStreamReaderFactory} instance that
   1.130 +     * the JAX-WS RI uses.
   1.131 +     */
   1.132 +    public static void set(XMLStreamReaderFactory f) {
   1.133 +        if(f==null) {
   1.134 +            throw new IllegalArgumentException();
   1.135 +        }
   1.136 +        streamReader.set(f);
   1.137 +    }
   1.138 +
   1.139 +    public static XMLStreamReaderFactory get() {
   1.140 +        return streamReader.get();
   1.141 +    }
   1.142 +
   1.143 +    public static XMLStreamReader create(InputSource source, boolean rejectDTDs) {
   1.144 +        try {
   1.145 +            // Char stream available?
   1.146 +            if (source.getCharacterStream() != null) {
   1.147 +                return get().doCreate(source.getSystemId(), source.getCharacterStream(), rejectDTDs);
   1.148 +            }
   1.149 +
   1.150 +            // Byte stream available?
   1.151 +            if (source.getByteStream() != null) {
   1.152 +                return get().doCreate(source.getSystemId(), source.getByteStream(), rejectDTDs);
   1.153 +            }
   1.154 +
   1.155 +            // Otherwise, open URI
   1.156 +            return get().doCreate(source.getSystemId(), new URL(source.getSystemId()).openStream(),rejectDTDs);
   1.157 +        } catch (IOException e) {
   1.158 +            throw new XMLReaderException("stax.cantCreate",e);
   1.159 +        }
   1.160 +    }
   1.161 +
   1.162 +    public static XMLStreamReader create(@Nullable String systemId, InputStream in, boolean rejectDTDs) {
   1.163 +        return get().doCreate(systemId,in,rejectDTDs);
   1.164 +    }
   1.165 +
   1.166 +    public static XMLStreamReader create(@Nullable String systemId, InputStream in, @Nullable String encoding, boolean rejectDTDs) {
   1.167 +        return (encoding == null)
   1.168 +                ? create(systemId, in, rejectDTDs)
   1.169 +                : get().doCreate(systemId,in,encoding,rejectDTDs);
   1.170 +    }
   1.171 +
   1.172 +    public static XMLStreamReader create(@Nullable String systemId, Reader reader, boolean rejectDTDs) {
   1.173 +        return get().doCreate(systemId,reader,rejectDTDs);
   1.174 +    }
   1.175 +
   1.176 +    /**
   1.177 +     * Should be invoked when the code finished using an {@link XMLStreamReader}.
   1.178 +     *
   1.179 +     * <p>
   1.180 +     * If the recycled instance implements {@link RecycleAware},
   1.181 +     * {@link RecycleAware#onRecycled()} will be invoked to let the instance
   1.182 +     * know that it's being recycled.
   1.183 +     *
   1.184 +     * <p>
   1.185 +     * It is not a hard requirement to call this method on every {@link XMLStreamReader}
   1.186 +     * instance. Not doing so just reduces the performance by throwing away
   1.187 +     * possibly reusable instances. So the caller should always consider the effort
   1.188 +     * it takes to recycle vs the possible performance gain by doing so.
   1.189 +     *
   1.190 +     * <p>
   1.191 +     * This method may be invoked by multiple threads concurrently.
   1.192 +     *
   1.193 +     * @param r
   1.194 +     *      The {@link XMLStreamReader} instance that the caller finished using.
   1.195 +     *      This could be any {@link XMLStreamReader} implementation, not just
   1.196 +     *      the ones that were created from this factory. So the implementation
   1.197 +     *      of this class needs to be aware of that.
   1.198 +     */
   1.199 +    public static void recycle(XMLStreamReader r) {
   1.200 +        get().doRecycle(r);
   1.201 +        if (r instanceof RecycleAware) {
   1.202 +            ((RecycleAware)r).onRecycled();
   1.203 +        }
   1.204 +    }
   1.205 +
   1.206 +    // implementations
   1.207 +
   1.208 +    public abstract XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs);
   1.209 +
   1.210 +    private XMLStreamReader doCreate(String systemId, InputStream in, @NotNull String encoding, boolean rejectDTDs) {
   1.211 +        Reader reader;
   1.212 +        try {
   1.213 +            reader = new InputStreamReader(in, encoding);
   1.214 +        } catch(UnsupportedEncodingException ue) {
   1.215 +            throw new XMLReaderException("stax.cantCreate", ue);
   1.216 +        }
   1.217 +        return doCreate(systemId, reader, rejectDTDs);
   1.218 +    }
   1.219 +
   1.220 +    public abstract XMLStreamReader doCreate(String systemId, Reader reader, boolean rejectDTDs);
   1.221 +
   1.222 +    public abstract void doRecycle(XMLStreamReader r);
   1.223 +
   1.224 +    /**
   1.225 +     * Interface that can be implemented by {@link XMLStreamReader} to
   1.226 +     * be notified when it's recycled.
   1.227 +     *
   1.228 +     * <p>
   1.229 +     * This provides a filtering {@link XMLStreamReader} an opportunity to
   1.230 +     * recycle its inner {@link XMLStreamReader}.
   1.231 +     */
   1.232 +    public interface RecycleAware {
   1.233 +        void onRecycled();
   1.234 +    }
   1.235 +
   1.236 +    /**
   1.237 +     * {@link XMLStreamReaderFactory} implementation for SJSXP/JAXP RI.
   1.238 +     */
   1.239 +    private static final class Zephyr extends XMLStreamReaderFactory {
   1.240 +        private final XMLInputFactory xif;
   1.241 +
   1.242 +        private final ThreadLocal<XMLStreamReader> pool = new ThreadLocal<XMLStreamReader>();
   1.243 +
   1.244 +        /**
   1.245 +         * Sun StAX impl <code>XMLReaderImpl.setInputSource()</code> method via reflection.
   1.246 +         */
   1.247 +        private final Method setInputSourceMethod;
   1.248 +
   1.249 +        /**
   1.250 +         * Sun StAX impl <code>XMLReaderImpl.reset()</code> method via reflection.
   1.251 +         */
   1.252 +        private final Method resetMethod;
   1.253 +
   1.254 +        /**
   1.255 +         * The Sun StAX impl's {@link XMLStreamReader} implementation clas.
   1.256 +         */
   1.257 +        private final Class zephyrClass;
   1.258 +
   1.259 +        /**
   1.260 +         * Creates {@link Zephyr} instance if the given {@link XMLInputFactory} is the one
   1.261 +         * from Zephyr.
   1.262 +         */
   1.263 +        public static @Nullable
   1.264 +        XMLStreamReaderFactory newInstance(XMLInputFactory xif) {
   1.265 +            // check if this is from Zephyr
   1.266 +            try {
   1.267 +                Class<?> clazz = xif.createXMLStreamReader(new StringReader("<foo/>")).getClass();
   1.268 +                // JDK has different XMLStreamReader impl class. Even if we check for that,
   1.269 +                // it doesn't have setInputSource(InputSource). Let it use Default
   1.270 +                if(!(clazz.getName().startsWith("com.sun.xml.internal.stream.")) )
   1.271 +                    return null;    // nope
   1.272 +                return new Zephyr(xif,clazz);
   1.273 +            } catch (NoSuchMethodException e) {
   1.274 +                return null;    // this factory is not for zephyr
   1.275 +            } catch (XMLStreamException e) {
   1.276 +                return null;    // impossible to fail to parse <foo/>, but anyway
   1.277 +            }
   1.278 +        }
   1.279 +
   1.280 +        public Zephyr(XMLInputFactory xif, Class clazz) throws NoSuchMethodException {
   1.281 +            zephyrClass = clazz;
   1.282 +            setInputSourceMethod = clazz.getMethod("setInputSource", InputSource.class);
   1.283 +            resetMethod = clazz.getMethod("reset");
   1.284 +
   1.285 +            try {
   1.286 +                // Turn OFF internal factory caching in Zephyr.
   1.287 +                // Santiago told me that this makes it thread-safe.
   1.288 +                xif.setProperty("reuse-instance", false);
   1.289 +            } catch (IllegalArgumentException e) {
   1.290 +                // falls through
   1.291 +            }
   1.292 +            this.xif = xif;
   1.293 +        }
   1.294 +
   1.295 +        /**
   1.296 +         * Fetchs an instance from the pool if available, otherwise null.
   1.297 +         */
   1.298 +        private @Nullable XMLStreamReader fetch() {
   1.299 +            XMLStreamReader sr = pool.get();
   1.300 +            if(sr==null)    return null;
   1.301 +            pool.set(null);
   1.302 +            return sr;
   1.303 +        }
   1.304 +
   1.305 +        @Override
   1.306 +        public void doRecycle(XMLStreamReader r) {
   1.307 +            if(zephyrClass.isInstance(r))
   1.308 +                pool.set(r);
   1.309 +        }
   1.310 +
   1.311 +        @Override
   1.312 +        public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
   1.313 +            try {
   1.314 +                XMLStreamReader xsr = fetch();
   1.315 +                if(xsr==null)
   1.316 +                    return xif.createXMLStreamReader(systemId,in);
   1.317 +
   1.318 +                // try re-using this instance.
   1.319 +                InputSource is = new InputSource(systemId);
   1.320 +                is.setByteStream(in);
   1.321 +                reuse(xsr,is);
   1.322 +                return xsr;
   1.323 +            } catch (IllegalAccessException e) {
   1.324 +                throw new XMLReaderException("stax.cantCreate",e);
   1.325 +            } catch (InvocationTargetException e) {
   1.326 +                throw new XMLReaderException("stax.cantCreate",e);
   1.327 +            } catch (XMLStreamException e) {
   1.328 +                throw new XMLReaderException("stax.cantCreate",e);
   1.329 +            }
   1.330 +        }
   1.331 +
   1.332 +        @Override
   1.333 +        public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
   1.334 +            try {
   1.335 +                XMLStreamReader xsr = fetch();
   1.336 +                if(xsr==null)
   1.337 +                    return xif.createXMLStreamReader(systemId,in);
   1.338 +
   1.339 +                // try re-using this instance.
   1.340 +                InputSource is = new InputSource(systemId);
   1.341 +                is.setCharacterStream(in);
   1.342 +                reuse(xsr,is);
   1.343 +                return xsr;
   1.344 +            } catch (IllegalAccessException e) {
   1.345 +                throw new XMLReaderException("stax.cantCreate",e);
   1.346 +            } catch (InvocationTargetException e) {
   1.347 +                Throwable cause = e.getCause();
   1.348 +                if (cause == null) {
   1.349 +                    cause = e;
   1.350 +                }
   1.351 +                throw new XMLReaderException("stax.cantCreate", cause);
   1.352 +            } catch (XMLStreamException e) {
   1.353 +                throw new XMLReaderException("stax.cantCreate",e);
   1.354 +            }
   1.355 +        }
   1.356 +
   1.357 +        private void reuse(XMLStreamReader xsr, InputSource in) throws IllegalAccessException, InvocationTargetException {
   1.358 +            resetMethod.invoke(xsr);
   1.359 +            setInputSourceMethod.invoke(xsr,in);
   1.360 +        }
   1.361 +    }
   1.362 +
   1.363 +    /**
   1.364 +     * Default {@link XMLStreamReaderFactory} implementation
   1.365 +     * that can work with any {@link XMLInputFactory}.
   1.366 +     *
   1.367 +     * <p>
   1.368 +     * {@link XMLInputFactory} is not required to be thread-safe, but
   1.369 +     * if the create method on this implementation is synchronized,
   1.370 +     * it may run into (see <a href="https://jax-ws.dev.java.net/issues/show_bug.cgi?id=555">
   1.371 +     * race condition</a>). Hence, using a XMLInputFactory per thread.
   1.372 +     */
   1.373 +    public static final class Default extends XMLStreamReaderFactory {
   1.374 +
   1.375 +        private final ThreadLocal<XMLInputFactory> xif = new ThreadLocal<XMLInputFactory>() {
   1.376 +            @Override
   1.377 +            public XMLInputFactory initialValue() {
   1.378 +                return getXMLInputFactory();
   1.379 +            }
   1.380 +        };
   1.381 +
   1.382 +        @Override
   1.383 +        public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
   1.384 +            try {
   1.385 +                return xif.get().createXMLStreamReader(systemId,in);
   1.386 +            } catch (XMLStreamException e) {
   1.387 +                throw new XMLReaderException("stax.cantCreate",e);
   1.388 +            }
   1.389 +        }
   1.390 +
   1.391 +        @Override
   1.392 +        public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
   1.393 +            try {
   1.394 +                return xif.get().createXMLStreamReader(systemId,in);
   1.395 +            } catch (XMLStreamException e) {
   1.396 +                throw new XMLReaderException("stax.cantCreate",e);
   1.397 +            }
   1.398 +        }
   1.399 +
   1.400 +        @Override
   1.401 +        public void doRecycle(XMLStreamReader r) {
   1.402 +            // there's no way to recycle with the default StAX API.
   1.403 +        }
   1.404 +
   1.405 +    }
   1.406 +
   1.407 +    /**
   1.408 +     * Similar to {@link Default} but doesn't do any synchronization.
   1.409 +     *
   1.410 +     * <p>
   1.411 +     * This is useful when you know your {@link XMLInputFactory} is thread-safe by itself.
   1.412 +     */
   1.413 +    public static class NoLock extends XMLStreamReaderFactory {
   1.414 +        private final XMLInputFactory xif;
   1.415 +
   1.416 +        public NoLock(XMLInputFactory xif) {
   1.417 +            this.xif = xif;
   1.418 +        }
   1.419 +
   1.420 +        @Override
   1.421 +        public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
   1.422 +            try {
   1.423 +                return xif.createXMLStreamReader(systemId,in);
   1.424 +            } catch (XMLStreamException e) {
   1.425 +                throw new XMLReaderException("stax.cantCreate",e);
   1.426 +            }
   1.427 +        }
   1.428 +
   1.429 +        @Override
   1.430 +        public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
   1.431 +            try {
   1.432 +                return xif.createXMLStreamReader(systemId,in);
   1.433 +            } catch (XMLStreamException e) {
   1.434 +                throw new XMLReaderException("stax.cantCreate",e);
   1.435 +            }
   1.436 +        }
   1.437 +
   1.438 +        @Override
   1.439 +        public void doRecycle(XMLStreamReader r) {
   1.440 +            // there's no way to recycle with the default StAX API.
   1.441 +        }
   1.442 +    }
   1.443 +
   1.444 +    /**
   1.445 +     * Handles Woodstox's XIF, but sets properties to do the string interning, sets various limits, ...
   1.446 +     * Woodstox {@link XMLInputFactory} is thread safe.
   1.447 +     */
   1.448 +    public static final class Woodstox extends NoLock {
   1.449 +
   1.450 +        public final static String PROPERTY_MAX_ATTRIBUTES_PER_ELEMENT = "xml.ws.maximum.AttributesPerElement";
   1.451 +        public final static String PROPERTY_MAX_ATTRIBUTE_SIZE = "xml.ws.maximum.AttributeSize";
   1.452 +        public final static String PROPERTY_MAX_CHILDREN_PER_ELEMENT = "xml.ws.maximum.ChildrenPerElement";
   1.453 +        public final static String PROPERTY_MAX_ELEMENT_COUNT = "xml.ws.maximum.ElementCount";
   1.454 +        public final static String PROPERTY_MAX_ELEMENT_DEPTH = "xml.ws.maximum.ElementDepth";
   1.455 +        public final static String PROPERTY_MAX_CHARACTERS = "xml.ws.maximum.Characters";
   1.456 +
   1.457 +        private static final int DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT = 500;
   1.458 +        private static final int DEFAULT_MAX_ATTRIBUTE_SIZE = 65536 * 8;
   1.459 +        private static final int DEFAULT_MAX_CHILDREN_PER_ELEMENT = Integer.MAX_VALUE;
   1.460 +        private static final int DEFAULT_MAX_ELEMENT_DEPTH = 500;
   1.461 +        private static final long DEFAULT_MAX_ELEMENT_COUNT = Integer.MAX_VALUE;
   1.462 +        private static final long DEFAULT_MAX_CHARACTERS = Long.MAX_VALUE;
   1.463 +
   1.464 +        /* Woodstox default setting:
   1.465 +         int mMaxAttributesPerElement = 1000;
   1.466 +         int mMaxAttributeSize = 65536 * 8;
   1.467 +         int mMaxChildrenPerElement = Integer.MAX_VALUE;
   1.468 +         int mMaxElementDepth = 1000;
   1.469 +         long mMaxElementCount = Long.MAX_VALUE;
   1.470 +         long mMaxCharacters = Long.MAX_VALUE;
   1.471 +         */
   1.472 +
   1.473 +        private int maxAttributesPerElement = DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT;
   1.474 +        private int maxAttributeSize = DEFAULT_MAX_ATTRIBUTE_SIZE;
   1.475 +        private int maxChildrenPerElement = DEFAULT_MAX_CHILDREN_PER_ELEMENT;
   1.476 +        private int maxElementDepth = DEFAULT_MAX_ELEMENT_DEPTH;
   1.477 +        private long maxElementCount = DEFAULT_MAX_ELEMENT_COUNT;
   1.478 +        private long maxCharacters = DEFAULT_MAX_CHARACTERS;
   1.479 +
   1.480 +        // Note: this is a copy from com.ctc.wstx.api.WstxInputProperties, to be removed in the future
   1.481 +        private static final java.lang.String P_MAX_ATTRIBUTES_PER_ELEMENT = "com.ctc.wstx.maxAttributesPerElement";
   1.482 +        private static final java.lang.String P_MAX_ATTRIBUTE_SIZE = "com.ctc.wstx.maxAttributeSize";
   1.483 +        private static final java.lang.String P_MAX_CHILDREN_PER_ELEMENT = "com.ctc.wstx.maxChildrenPerElement";
   1.484 +        private static final java.lang.String P_MAX_ELEMENT_COUNT = "com.ctc.wstx.maxElementCount";
   1.485 +        private static final java.lang.String P_MAX_ELEMENT_DEPTH = "com.ctc.wstx.maxElementDepth";
   1.486 +        private static final java.lang.String P_MAX_CHARACTERS = "com.ctc.wstx.maxCharacters";
   1.487 +        private static final java.lang.String P_INTERN_NSURIS = "org.codehaus.stax2.internNsUris";
   1.488 +
   1.489 +        public Woodstox(XMLInputFactory xif) {
   1.490 +            super(xif);
   1.491 +
   1.492 +            if (xif.isPropertySupported(P_INTERN_NSURIS)) {
   1.493 +                xif.setProperty(P_INTERN_NSURIS, true);
   1.494 +                if (LOGGER.isLoggable(Level.FINE)) {
   1.495 +                    LOGGER.log(Level.FINE, P_INTERN_NSURIS + " is {0}", true);
   1.496 +                }
   1.497 +            }
   1.498 +
   1.499 +            if (xif.isPropertySupported(P_MAX_ATTRIBUTES_PER_ELEMENT)) {
   1.500 +                maxAttributesPerElement = Integer.valueOf(buildIntegerValue(
   1.501 +                    PROPERTY_MAX_ATTRIBUTES_PER_ELEMENT, DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT)
   1.502 +                );
   1.503 +                xif.setProperty(P_MAX_ATTRIBUTES_PER_ELEMENT, maxAttributesPerElement);
   1.504 +                if (LOGGER.isLoggable(Level.FINE)) {
   1.505 +                    LOGGER.log(Level.FINE, P_MAX_ATTRIBUTES_PER_ELEMENT + " is {0}", maxAttributesPerElement);
   1.506 +                }
   1.507 +            }
   1.508 +
   1.509 +            if (xif.isPropertySupported(P_MAX_ATTRIBUTE_SIZE)) {
   1.510 +                maxAttributeSize = Integer.valueOf(buildIntegerValue(
   1.511 +                    PROPERTY_MAX_ATTRIBUTE_SIZE, DEFAULT_MAX_ATTRIBUTE_SIZE)
   1.512 +                );
   1.513 +                xif.setProperty(P_MAX_ATTRIBUTE_SIZE, maxAttributeSize);
   1.514 +                if (LOGGER.isLoggable(Level.FINE)) {
   1.515 +                    LOGGER.log(Level.FINE, P_MAX_ATTRIBUTE_SIZE + " is {0}", maxAttributeSize);
   1.516 +                }
   1.517 +            }
   1.518 +
   1.519 +            if (xif.isPropertySupported(P_MAX_CHILDREN_PER_ELEMENT)) {
   1.520 +                maxChildrenPerElement = Integer.valueOf(buildIntegerValue(
   1.521 +                    PROPERTY_MAX_CHILDREN_PER_ELEMENT, DEFAULT_MAX_CHILDREN_PER_ELEMENT)
   1.522 +                );
   1.523 +                xif.setProperty(P_MAX_CHILDREN_PER_ELEMENT, maxChildrenPerElement);
   1.524 +                if (LOGGER.isLoggable(Level.FINE)) {
   1.525 +                    LOGGER.log(Level.FINE, P_MAX_CHILDREN_PER_ELEMENT + " is {0}", maxChildrenPerElement);
   1.526 +                }
   1.527 +            }
   1.528 +
   1.529 +            if (xif.isPropertySupported(P_MAX_ELEMENT_DEPTH)) {
   1.530 +                maxElementDepth = Integer.valueOf(buildIntegerValue(
   1.531 +                    PROPERTY_MAX_ELEMENT_DEPTH, DEFAULT_MAX_ELEMENT_DEPTH)
   1.532 +                );
   1.533 +                xif.setProperty(P_MAX_ELEMENT_DEPTH, maxElementDepth);
   1.534 +                if (LOGGER.isLoggable(Level.FINE)) {
   1.535 +                    LOGGER.log(Level.FINE, P_MAX_ELEMENT_DEPTH + " is {0}", maxElementDepth);
   1.536 +                }
   1.537 +            }
   1.538 +
   1.539 +            if (xif.isPropertySupported(P_MAX_ELEMENT_COUNT)) {
   1.540 +                maxElementCount = Long.valueOf(buildLongValue(
   1.541 +                    PROPERTY_MAX_ELEMENT_COUNT, DEFAULT_MAX_ELEMENT_COUNT)
   1.542 +                );
   1.543 +                xif.setProperty(P_MAX_ELEMENT_COUNT, maxElementCount);
   1.544 +                if (LOGGER.isLoggable(Level.FINE)) {
   1.545 +                    LOGGER.log(Level.FINE, P_MAX_ELEMENT_COUNT + " is {0}", maxElementCount);
   1.546 +                }
   1.547 +            }
   1.548 +
   1.549 +            if (xif.isPropertySupported(P_MAX_CHARACTERS)) {
   1.550 +                maxCharacters = Long.valueOf(buildLongValue(
   1.551 +                    PROPERTY_MAX_CHARACTERS, DEFAULT_MAX_CHARACTERS)
   1.552 +                );
   1.553 +                xif.setProperty(P_MAX_CHARACTERS, maxCharacters);
   1.554 +                if (LOGGER.isLoggable(Level.FINE)) {
   1.555 +                    LOGGER.log(Level.FINE, P_MAX_CHARACTERS + " is {0}", maxCharacters);
   1.556 +                }
   1.557 +            }
   1.558 +        }
   1.559 +
   1.560 +        @Override
   1.561 +        public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
   1.562 +            return super.doCreate(systemId, in, rejectDTDs);
   1.563 +        }
   1.564 +
   1.565 +        @Override
   1.566 +        public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
   1.567 +            return super.doCreate(systemId, in, rejectDTDs);
   1.568 +        }
   1.569 +    }
   1.570 +
   1.571 +    private static int buildIntegerValue(String propertyName, int defaultValue) {
   1.572 +        String propVal = System.getProperty(propertyName);
   1.573 +        if (propVal != null && propVal.length() > 0) {
   1.574 +            try {
   1.575 +                Integer value = Integer.parseInt(propVal);
   1.576 +                if (value > 0) {
   1.577 +                    // return with the value in System property
   1.578 +                    return value;
   1.579 +                }
   1.580 +            } catch (NumberFormatException nfe) {
   1.581 +                if (LOGGER.isLoggable(Level.WARNING)) {
   1.582 +                    LOGGER.log(Level.WARNING, StreamingMessages.INVALID_PROPERTY_VALUE_INTEGER(propertyName, propVal, Integer.toString(defaultValue)), nfe);
   1.583 +                }
   1.584 +            }
   1.585 +        }
   1.586 +        // return with the default value
   1.587 +        return defaultValue;
   1.588 +    }
   1.589 +
   1.590 +    private static long buildLongValue(String propertyName, long defaultValue) {
   1.591 +        String propVal = System.getProperty(propertyName);
   1.592 +        if (propVal != null && propVal.length() > 0) {
   1.593 +            try {
   1.594 +                long value = Long.parseLong(propVal);
   1.595 +                if (value > 0L) {
   1.596 +                    // return with the value in System property
   1.597 +                    return value;
   1.598 +                }
   1.599 +            } catch (NumberFormatException nfe) {
   1.600 +                // defult will be returned
   1.601 +                if (LOGGER.isLoggable(Level.WARNING)) {
   1.602 +                    LOGGER.log(Level.WARNING, StreamingMessages.INVALID_PROPERTY_VALUE_LONG(propertyName, propVal, Long.toString(defaultValue)), nfe);
   1.603 +                }
   1.604 +            }
   1.605 +        }
   1.606 +        // return with the default value
   1.607 +        return defaultValue;
   1.608 +    }
   1.609 +
   1.610 +    private static Boolean getProperty(final String prop) {
   1.611 +        return AccessController.doPrivileged(
   1.612 +            new java.security.PrivilegedAction<Boolean>() {
   1.613 +                @Override
   1.614 +                public Boolean run() {
   1.615 +                    String value = System.getProperty(prop);
   1.616 +                    return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
   1.617 +                }
   1.618 +            }
   1.619 +        );
   1.620 +    }
   1.621 +
   1.622 +}

mercurial