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

Thu, 31 Aug 2017 15:18:52 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:18:52 +0800
changeset 637
9c07ef4934dd
parent 515
6cd506508147
parent 0
373ffda63c9a
permissions
-rw-r--r--

merge

aoqi@0 1 /*
aoqi@0 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
aoqi@0 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
aoqi@0 4 *
aoqi@0 5 * This code is free software; you can redistribute it and/or modify it
aoqi@0 6 * under the terms of the GNU General Public License version 2 only, as
aoqi@0 7 * published by the Free Software Foundation. Oracle designates this
aoqi@0 8 * particular file as subject to the "Classpath" exception as provided
aoqi@0 9 * by Oracle in the LICENSE file that accompanied this code.
aoqi@0 10 *
aoqi@0 11 * This code is distributed in the hope that it will be useful, but WITHOUT
aoqi@0 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
aoqi@0 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
aoqi@0 14 * version 2 for more details (a copy is included in the LICENSE file that
aoqi@0 15 * accompanied this code).
aoqi@0 16 *
aoqi@0 17 * You should have received a copy of the GNU General Public License version
aoqi@0 18 * 2 along with this work; if not, write to the Free Software Foundation,
aoqi@0 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
aoqi@0 20 *
aoqi@0 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
aoqi@0 22 * or visit www.oracle.com if you need additional information or have any
aoqi@0 23 * questions.
aoqi@0 24 */
aoqi@0 25
aoqi@0 26 package com.sun.xml.internal.ws.api.streaming;
aoqi@0 27
aoqi@0 28 import com.sun.istack.internal.NotNull;
aoqi@0 29 import com.sun.istack.internal.Nullable;
aoqi@0 30 import com.sun.xml.internal.ws.streaming.XMLReaderException;
aoqi@0 31 import com.sun.xml.internal.ws.util.xml.XmlUtil;
aoqi@0 32 import org.xml.sax.InputSource;
aoqi@0 33
aoqi@0 34 import javax.xml.stream.XMLInputFactory;
aoqi@0 35 import javax.xml.stream.XMLStreamException;
aoqi@0 36 import javax.xml.stream.XMLStreamReader;
aoqi@0 37 import java.io.IOException;
aoqi@0 38 import java.io.InputStream;
aoqi@0 39 import java.io.InputStreamReader;
aoqi@0 40 import java.io.Reader;
aoqi@0 41 import java.io.StringReader;
aoqi@0 42 import java.io.UnsupportedEncodingException;
aoqi@0 43 import java.lang.reflect.InvocationTargetException;
aoqi@0 44 import java.lang.reflect.Method;
aoqi@0 45 import java.net.URL;
aoqi@0 46 import java.security.AccessController;
aoqi@0 47 import java.util.logging.Level;
aoqi@0 48 import java.util.logging.Logger;
aoqi@0 49
aoqi@0 50 import com.sun.xml.internal.ws.resources.StreamingMessages;
aoqi@0 51
aoqi@0 52 /**
aoqi@0 53 * Factory for {@link XMLStreamReader}.
aoqi@0 54 *
aoqi@0 55 * <p>
aoqi@0 56 * This wraps {@link XMLInputFactory} and allows us to reuse {@link XMLStreamReader} instances
aoqi@0 57 * when appropriate.
aoqi@0 58 *
aoqi@0 59 * @author Kohsuke Kawaguchi
aoqi@0 60 */
aoqi@0 61 @SuppressWarnings("StaticNonFinalUsedInInitialization")
aoqi@0 62 public abstract class XMLStreamReaderFactory {
aoqi@0 63
aoqi@0 64 private static final Logger LOGGER = Logger.getLogger(XMLStreamReaderFactory.class.getName());
aoqi@0 65
aoqi@0 66 private static final String CLASS_NAME_OF_WSTXINPUTFACTORY = "com.ctc.wstx.stax.WstxInputFactory";
aoqi@0 67
aoqi@0 68 /**
aoqi@0 69 * Singleton instance.
aoqi@0 70 */
aoqi@0 71 private static volatile ContextClassloaderLocal<XMLStreamReaderFactory> streamReader =
aoqi@0 72 new ContextClassloaderLocal<XMLStreamReaderFactory>() {
aoqi@0 73
aoqi@0 74 @Override
aoqi@0 75 protected XMLStreamReaderFactory initialValue() {
aoqi@0 76
aoqi@0 77 XMLInputFactory xif = getXMLInputFactory();
aoqi@0 78 XMLStreamReaderFactory f=null;
aoqi@0 79
aoqi@0 80 // this system property can be used to disable the pooling altogether,
aoqi@0 81 // in case someone hits an issue with pooling in the production system.
aoqi@0 82 if(!getProperty(XMLStreamReaderFactory.class.getName()+".noPool")) {
aoqi@0 83 f = Zephyr.newInstance(xif);
aoqi@0 84 }
aoqi@0 85
aoqi@0 86 if(f==null) {
aoqi@0 87 // is this Woodstox?
aoqi@0 88 if (xif.getClass().getName().equals(CLASS_NAME_OF_WSTXINPUTFACTORY)) {
aoqi@0 89 f = new Woodstox(xif);
aoqi@0 90 }
aoqi@0 91 }
aoqi@0 92
aoqi@0 93 if (f==null) {
aoqi@0 94 f = new Default();
aoqi@0 95 }
aoqi@0 96
aoqi@0 97 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 98 LOGGER.log(Level.FINE, "XMLStreamReaderFactory instance is = {0}", f);
aoqi@0 99 }
aoqi@0 100 return f;
aoqi@0 101 }
aoqi@0 102 };
aoqi@0 103
aoqi@0 104 private static XMLInputFactory getXMLInputFactory() {
aoqi@0 105 XMLInputFactory xif = null;
aoqi@0 106 if (getProperty(XMLStreamReaderFactory.class.getName()+".woodstox")) {
aoqi@0 107 try {
aoqi@0 108 xif = (XMLInputFactory)Class.forName("com.ctc.wstx.stax.WstxInputFactory").newInstance();
aoqi@0 109 } catch (Exception e) {
aoqi@0 110 if (LOGGER.isLoggable(Level.WARNING)) {
aoqi@0 111 LOGGER.log(Level.WARNING, StreamingMessages.WOODSTOX_CANT_LOAD(CLASS_NAME_OF_WSTXINPUTFACTORY), e);
aoqi@0 112 }
aoqi@0 113 }
aoqi@0 114 }
aoqi@0 115 if (xif == null) {
aoqi@0 116 xif = XmlUtil.newXMLInputFactory(true);
aoqi@0 117 }
aoqi@0 118 xif.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
aoqi@0 119 xif.setProperty(XMLInputFactory.SUPPORT_DTD, false);
aoqi@0 120 xif.setProperty(XMLInputFactory.IS_COALESCING, true);
aoqi@0 121
aoqi@0 122 return xif;
aoqi@0 123 }
aoqi@0 124
aoqi@0 125 /**
aoqi@0 126 * Overrides the singleton {@link XMLStreamReaderFactory} instance that
aoqi@0 127 * the JAX-WS RI uses.
aoqi@0 128 */
aoqi@0 129 public static void set(XMLStreamReaderFactory f) {
aoqi@0 130 if(f==null) {
aoqi@0 131 throw new IllegalArgumentException();
aoqi@0 132 }
aoqi@0 133 streamReader.set(f);
aoqi@0 134 }
aoqi@0 135
aoqi@0 136 public static XMLStreamReaderFactory get() {
aoqi@0 137 return streamReader.get();
aoqi@0 138 }
aoqi@0 139
aoqi@0 140 public static XMLStreamReader create(InputSource source, boolean rejectDTDs) {
aoqi@0 141 try {
aoqi@0 142 // Char stream available?
aoqi@0 143 if (source.getCharacterStream() != null) {
aoqi@0 144 return get().doCreate(source.getSystemId(), source.getCharacterStream(), rejectDTDs);
aoqi@0 145 }
aoqi@0 146
aoqi@0 147 // Byte stream available?
aoqi@0 148 if (source.getByteStream() != null) {
aoqi@0 149 return get().doCreate(source.getSystemId(), source.getByteStream(), rejectDTDs);
aoqi@0 150 }
aoqi@0 151
aoqi@0 152 // Otherwise, open URI
aoqi@0 153 return get().doCreate(source.getSystemId(), new URL(source.getSystemId()).openStream(),rejectDTDs);
aoqi@0 154 } catch (IOException e) {
aoqi@0 155 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 156 }
aoqi@0 157 }
aoqi@0 158
aoqi@0 159 public static XMLStreamReader create(@Nullable String systemId, InputStream in, boolean rejectDTDs) {
aoqi@0 160 return get().doCreate(systemId,in,rejectDTDs);
aoqi@0 161 }
aoqi@0 162
aoqi@0 163 public static XMLStreamReader create(@Nullable String systemId, InputStream in, @Nullable String encoding, boolean rejectDTDs) {
aoqi@0 164 return (encoding == null)
aoqi@0 165 ? create(systemId, in, rejectDTDs)
aoqi@0 166 : get().doCreate(systemId,in,encoding,rejectDTDs);
aoqi@0 167 }
aoqi@0 168
aoqi@0 169 public static XMLStreamReader create(@Nullable String systemId, Reader reader, boolean rejectDTDs) {
aoqi@0 170 return get().doCreate(systemId,reader,rejectDTDs);
aoqi@0 171 }
aoqi@0 172
aoqi@0 173 /**
aoqi@0 174 * Should be invoked when the code finished using an {@link XMLStreamReader}.
aoqi@0 175 *
aoqi@0 176 * <p>
aoqi@0 177 * If the recycled instance implements {@link RecycleAware},
aoqi@0 178 * {@link RecycleAware#onRecycled()} will be invoked to let the instance
aoqi@0 179 * know that it's being recycled.
aoqi@0 180 *
aoqi@0 181 * <p>
aoqi@0 182 * It is not a hard requirement to call this method on every {@link XMLStreamReader}
aoqi@0 183 * instance. Not doing so just reduces the performance by throwing away
aoqi@0 184 * possibly reusable instances. So the caller should always consider the effort
aoqi@0 185 * it takes to recycle vs the possible performance gain by doing so.
aoqi@0 186 *
aoqi@0 187 * <p>
aoqi@0 188 * This method may be invoked by multiple threads concurrently.
aoqi@0 189 *
aoqi@0 190 * @param r
aoqi@0 191 * The {@link XMLStreamReader} instance that the caller finished using.
aoqi@0 192 * This could be any {@link XMLStreamReader} implementation, not just
aoqi@0 193 * the ones that were created from this factory. So the implementation
aoqi@0 194 * of this class needs to be aware of that.
aoqi@0 195 */
aoqi@0 196 public static void recycle(XMLStreamReader r) {
aoqi@0 197 get().doRecycle(r);
aoqi@0 198 if (r instanceof RecycleAware) {
aoqi@0 199 ((RecycleAware)r).onRecycled();
aoqi@0 200 }
aoqi@0 201 }
aoqi@0 202
aoqi@0 203 // implementations
aoqi@0 204
aoqi@0 205 public abstract XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs);
aoqi@0 206
aoqi@0 207 private XMLStreamReader doCreate(String systemId, InputStream in, @NotNull String encoding, boolean rejectDTDs) {
aoqi@0 208 Reader reader;
aoqi@0 209 try {
aoqi@0 210 reader = new InputStreamReader(in, encoding);
aoqi@0 211 } catch(UnsupportedEncodingException ue) {
aoqi@0 212 throw new XMLReaderException("stax.cantCreate", ue);
aoqi@0 213 }
aoqi@0 214 return doCreate(systemId, reader, rejectDTDs);
aoqi@0 215 }
aoqi@0 216
aoqi@0 217 public abstract XMLStreamReader doCreate(String systemId, Reader reader, boolean rejectDTDs);
aoqi@0 218
aoqi@0 219 public abstract void doRecycle(XMLStreamReader r);
aoqi@0 220
aoqi@0 221 /**
aoqi@0 222 * Interface that can be implemented by {@link XMLStreamReader} to
aoqi@0 223 * be notified when it's recycled.
aoqi@0 224 *
aoqi@0 225 * <p>
aoqi@0 226 * This provides a filtering {@link XMLStreamReader} an opportunity to
aoqi@0 227 * recycle its inner {@link XMLStreamReader}.
aoqi@0 228 */
aoqi@0 229 public interface RecycleAware {
aoqi@0 230 void onRecycled();
aoqi@0 231 }
aoqi@0 232
aoqi@0 233 /**
aoqi@0 234 * {@link XMLStreamReaderFactory} implementation for SJSXP/JAXP RI.
aoqi@0 235 */
aoqi@0 236 private static final class Zephyr extends XMLStreamReaderFactory {
aoqi@0 237 private final XMLInputFactory xif;
aoqi@0 238
aoqi@0 239 private final ThreadLocal<XMLStreamReader> pool = new ThreadLocal<XMLStreamReader>();
aoqi@0 240
aoqi@0 241 /**
aoqi@0 242 * Sun StAX impl <code>XMLReaderImpl.setInputSource()</code> method via reflection.
aoqi@0 243 */
aoqi@0 244 private final Method setInputSourceMethod;
aoqi@0 245
aoqi@0 246 /**
aoqi@0 247 * Sun StAX impl <code>XMLReaderImpl.reset()</code> method via reflection.
aoqi@0 248 */
aoqi@0 249 private final Method resetMethod;
aoqi@0 250
aoqi@0 251 /**
aoqi@0 252 * The Sun StAX impl's {@link XMLStreamReader} implementation clas.
aoqi@0 253 */
aoqi@0 254 private final Class zephyrClass;
aoqi@0 255
aoqi@0 256 /**
aoqi@0 257 * Creates {@link Zephyr} instance if the given {@link XMLInputFactory} is the one
aoqi@0 258 * from Zephyr.
aoqi@0 259 */
aoqi@0 260 public static @Nullable
aoqi@0 261 XMLStreamReaderFactory newInstance(XMLInputFactory xif) {
aoqi@0 262 // check if this is from Zephyr
aoqi@0 263 try {
aoqi@0 264 Class<?> clazz = xif.createXMLStreamReader(new StringReader("<foo/>")).getClass();
aoqi@0 265 // JDK has different XMLStreamReader impl class. Even if we check for that,
aoqi@0 266 // it doesn't have setInputSource(InputSource). Let it use Default
aoqi@0 267 if(!(clazz.getName().startsWith("com.sun.xml.internal.stream.")) )
aoqi@0 268 return null; // nope
aoqi@0 269 return new Zephyr(xif,clazz);
aoqi@0 270 } catch (NoSuchMethodException e) {
aoqi@0 271 return null; // this factory is not for zephyr
aoqi@0 272 } catch (XMLStreamException e) {
aoqi@0 273 return null; // impossible to fail to parse <foo/>, but anyway
aoqi@0 274 }
aoqi@0 275 }
aoqi@0 276
aoqi@0 277 public Zephyr(XMLInputFactory xif, Class clazz) throws NoSuchMethodException {
aoqi@0 278 zephyrClass = clazz;
aoqi@0 279 setInputSourceMethod = clazz.getMethod("setInputSource", InputSource.class);
aoqi@0 280 resetMethod = clazz.getMethod("reset");
aoqi@0 281
aoqi@0 282 try {
aoqi@0 283 // Turn OFF internal factory caching in Zephyr.
aoqi@0 284 // Santiago told me that this makes it thread-safe.
aoqi@0 285 xif.setProperty("reuse-instance", false);
aoqi@0 286 } catch (IllegalArgumentException e) {
aoqi@0 287 // falls through
aoqi@0 288 }
aoqi@0 289 this.xif = xif;
aoqi@0 290 }
aoqi@0 291
aoqi@0 292 /**
aoqi@0 293 * Fetchs an instance from the pool if available, otherwise null.
aoqi@0 294 */
aoqi@0 295 private @Nullable XMLStreamReader fetch() {
aoqi@0 296 XMLStreamReader sr = pool.get();
aoqi@0 297 if(sr==null) return null;
aoqi@0 298 pool.set(null);
aoqi@0 299 return sr;
aoqi@0 300 }
aoqi@0 301
aoqi@0 302 @Override
aoqi@0 303 public void doRecycle(XMLStreamReader r) {
aoqi@0 304 if(zephyrClass.isInstance(r))
aoqi@0 305 pool.set(r);
aoqi@0 306 }
aoqi@0 307
aoqi@0 308 @Override
aoqi@0 309 public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
aoqi@0 310 try {
aoqi@0 311 XMLStreamReader xsr = fetch();
aoqi@0 312 if(xsr==null)
aoqi@0 313 return xif.createXMLStreamReader(systemId,in);
aoqi@0 314
aoqi@0 315 // try re-using this instance.
aoqi@0 316 InputSource is = new InputSource(systemId);
aoqi@0 317 is.setByteStream(in);
aoqi@0 318 reuse(xsr,is);
aoqi@0 319 return xsr;
aoqi@0 320 } catch (IllegalAccessException e) {
aoqi@0 321 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 322 } catch (InvocationTargetException e) {
aoqi@0 323 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 324 } catch (XMLStreamException e) {
aoqi@0 325 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 326 }
aoqi@0 327 }
aoqi@0 328
aoqi@0 329 @Override
aoqi@0 330 public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
aoqi@0 331 try {
aoqi@0 332 XMLStreamReader xsr = fetch();
aoqi@0 333 if(xsr==null)
aoqi@0 334 return xif.createXMLStreamReader(systemId,in);
aoqi@0 335
aoqi@0 336 // try re-using this instance.
aoqi@0 337 InputSource is = new InputSource(systemId);
aoqi@0 338 is.setCharacterStream(in);
aoqi@0 339 reuse(xsr,is);
aoqi@0 340 return xsr;
aoqi@0 341 } catch (IllegalAccessException e) {
aoqi@0 342 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 343 } catch (InvocationTargetException e) {
aoqi@0 344 Throwable cause = e.getCause();
aoqi@0 345 if (cause == null) {
aoqi@0 346 cause = e;
aoqi@0 347 }
aoqi@0 348 throw new XMLReaderException("stax.cantCreate", cause);
aoqi@0 349 } catch (XMLStreamException e) {
aoqi@0 350 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 351 }
aoqi@0 352 }
aoqi@0 353
aoqi@0 354 private void reuse(XMLStreamReader xsr, InputSource in) throws IllegalAccessException, InvocationTargetException {
aoqi@0 355 resetMethod.invoke(xsr);
aoqi@0 356 setInputSourceMethod.invoke(xsr,in);
aoqi@0 357 }
aoqi@0 358 }
aoqi@0 359
aoqi@0 360 /**
aoqi@0 361 * Default {@link XMLStreamReaderFactory} implementation
aoqi@0 362 * that can work with any {@link XMLInputFactory}.
aoqi@0 363 *
aoqi@0 364 * <p>
aoqi@0 365 * {@link XMLInputFactory} is not required to be thread-safe, but
aoqi@0 366 * if the create method on this implementation is synchronized,
aoqi@0 367 * it may run into (see <a href="https://jax-ws.dev.java.net/issues/show_bug.cgi?id=555">
aoqi@0 368 * race condition</a>). Hence, using a XMLInputFactory per thread.
aoqi@0 369 */
aoqi@0 370 public static final class Default extends XMLStreamReaderFactory {
aoqi@0 371
aoqi@0 372 private final ThreadLocal<XMLInputFactory> xif = new ThreadLocal<XMLInputFactory>() {
aoqi@0 373 @Override
aoqi@0 374 public XMLInputFactory initialValue() {
aoqi@0 375 return getXMLInputFactory();
aoqi@0 376 }
aoqi@0 377 };
aoqi@0 378
aoqi@0 379 @Override
aoqi@0 380 public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
aoqi@0 381 try {
aoqi@0 382 return xif.get().createXMLStreamReader(systemId,in);
aoqi@0 383 } catch (XMLStreamException e) {
aoqi@0 384 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 385 }
aoqi@0 386 }
aoqi@0 387
aoqi@0 388 @Override
aoqi@0 389 public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
aoqi@0 390 try {
aoqi@0 391 return xif.get().createXMLStreamReader(systemId,in);
aoqi@0 392 } catch (XMLStreamException e) {
aoqi@0 393 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 394 }
aoqi@0 395 }
aoqi@0 396
aoqi@0 397 @Override
aoqi@0 398 public void doRecycle(XMLStreamReader r) {
aoqi@0 399 // there's no way to recycle with the default StAX API.
aoqi@0 400 }
aoqi@0 401
aoqi@0 402 }
aoqi@0 403
aoqi@0 404 /**
aoqi@0 405 * Similar to {@link Default} but doesn't do any synchronization.
aoqi@0 406 *
aoqi@0 407 * <p>
aoqi@0 408 * This is useful when you know your {@link XMLInputFactory} is thread-safe by itself.
aoqi@0 409 */
aoqi@0 410 public static class NoLock extends XMLStreamReaderFactory {
aoqi@0 411 private final XMLInputFactory xif;
aoqi@0 412
aoqi@0 413 public NoLock(XMLInputFactory xif) {
aoqi@0 414 this.xif = xif;
aoqi@0 415 }
aoqi@0 416
aoqi@0 417 @Override
aoqi@0 418 public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
aoqi@0 419 try {
aoqi@0 420 return xif.createXMLStreamReader(systemId,in);
aoqi@0 421 } catch (XMLStreamException e) {
aoqi@0 422 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 423 }
aoqi@0 424 }
aoqi@0 425
aoqi@0 426 @Override
aoqi@0 427 public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
aoqi@0 428 try {
aoqi@0 429 return xif.createXMLStreamReader(systemId,in);
aoqi@0 430 } catch (XMLStreamException e) {
aoqi@0 431 throw new XMLReaderException("stax.cantCreate",e);
aoqi@0 432 }
aoqi@0 433 }
aoqi@0 434
aoqi@0 435 @Override
aoqi@0 436 public void doRecycle(XMLStreamReader r) {
aoqi@0 437 // there's no way to recycle with the default StAX API.
aoqi@0 438 }
aoqi@0 439 }
aoqi@0 440
aoqi@0 441 /**
aoqi@0 442 * Handles Woodstox's XIF, but sets properties to do the string interning, sets various limits, ...
aoqi@0 443 * Woodstox {@link XMLInputFactory} is thread safe.
aoqi@0 444 */
aoqi@0 445 public static final class Woodstox extends NoLock {
aoqi@0 446
aoqi@0 447 public final static String PROPERTY_MAX_ATTRIBUTES_PER_ELEMENT = "xml.ws.maximum.AttributesPerElement";
aoqi@0 448 public final static String PROPERTY_MAX_ATTRIBUTE_SIZE = "xml.ws.maximum.AttributeSize";
aoqi@0 449 public final static String PROPERTY_MAX_CHILDREN_PER_ELEMENT = "xml.ws.maximum.ChildrenPerElement";
aoqi@0 450 public final static String PROPERTY_MAX_ELEMENT_COUNT = "xml.ws.maximum.ElementCount";
aoqi@0 451 public final static String PROPERTY_MAX_ELEMENT_DEPTH = "xml.ws.maximum.ElementDepth";
aoqi@0 452 public final static String PROPERTY_MAX_CHARACTERS = "xml.ws.maximum.Characters";
aoqi@0 453
aoqi@0 454 private static final int DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT = 500;
aoqi@0 455 private static final int DEFAULT_MAX_ATTRIBUTE_SIZE = 65536 * 8;
aoqi@0 456 private static final int DEFAULT_MAX_CHILDREN_PER_ELEMENT = Integer.MAX_VALUE;
aoqi@0 457 private static final int DEFAULT_MAX_ELEMENT_DEPTH = 500;
aoqi@0 458 private static final long DEFAULT_MAX_ELEMENT_COUNT = Integer.MAX_VALUE;
aoqi@0 459 private static final long DEFAULT_MAX_CHARACTERS = Long.MAX_VALUE;
aoqi@0 460
aoqi@0 461 /* Woodstox default setting:
aoqi@0 462 int mMaxAttributesPerElement = 1000;
aoqi@0 463 int mMaxAttributeSize = 65536 * 8;
aoqi@0 464 int mMaxChildrenPerElement = Integer.MAX_VALUE;
aoqi@0 465 int mMaxElementDepth = 1000;
aoqi@0 466 long mMaxElementCount = Long.MAX_VALUE;
aoqi@0 467 long mMaxCharacters = Long.MAX_VALUE;
aoqi@0 468 */
aoqi@0 469
aoqi@0 470 private int maxAttributesPerElement = DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT;
aoqi@0 471 private int maxAttributeSize = DEFAULT_MAX_ATTRIBUTE_SIZE;
aoqi@0 472 private int maxChildrenPerElement = DEFAULT_MAX_CHILDREN_PER_ELEMENT;
aoqi@0 473 private int maxElementDepth = DEFAULT_MAX_ELEMENT_DEPTH;
aoqi@0 474 private long maxElementCount = DEFAULT_MAX_ELEMENT_COUNT;
aoqi@0 475 private long maxCharacters = DEFAULT_MAX_CHARACTERS;
aoqi@0 476
aoqi@0 477 // Note: this is a copy from com.ctc.wstx.api.WstxInputProperties, to be removed in the future
aoqi@0 478 private static final java.lang.String P_MAX_ATTRIBUTES_PER_ELEMENT = "com.ctc.wstx.maxAttributesPerElement";
aoqi@0 479 private static final java.lang.String P_MAX_ATTRIBUTE_SIZE = "com.ctc.wstx.maxAttributeSize";
aoqi@0 480 private static final java.lang.String P_MAX_CHILDREN_PER_ELEMENT = "com.ctc.wstx.maxChildrenPerElement";
aoqi@0 481 private static final java.lang.String P_MAX_ELEMENT_COUNT = "com.ctc.wstx.maxElementCount";
aoqi@0 482 private static final java.lang.String P_MAX_ELEMENT_DEPTH = "com.ctc.wstx.maxElementDepth";
aoqi@0 483 private static final java.lang.String P_MAX_CHARACTERS = "com.ctc.wstx.maxCharacters";
aoqi@0 484 private static final java.lang.String P_INTERN_NSURIS = "org.codehaus.stax2.internNsUris";
aoqi@0 485
aoqi@0 486 public Woodstox(XMLInputFactory xif) {
aoqi@0 487 super(xif);
aoqi@0 488
aoqi@0 489 if (xif.isPropertySupported(P_INTERN_NSURIS)) {
aoqi@0 490 xif.setProperty(P_INTERN_NSURIS, true);
aoqi@0 491 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 492 LOGGER.log(Level.FINE, P_INTERN_NSURIS + " is {0}", true);
aoqi@0 493 }
aoqi@0 494 }
aoqi@0 495
aoqi@0 496 if (xif.isPropertySupported(P_MAX_ATTRIBUTES_PER_ELEMENT)) {
aoqi@0 497 maxAttributesPerElement = Integer.valueOf(buildIntegerValue(
aoqi@0 498 PROPERTY_MAX_ATTRIBUTES_PER_ELEMENT, DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT)
aoqi@0 499 );
aoqi@0 500 xif.setProperty(P_MAX_ATTRIBUTES_PER_ELEMENT, maxAttributesPerElement);
aoqi@0 501 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 502 LOGGER.log(Level.FINE, P_MAX_ATTRIBUTES_PER_ELEMENT + " is {0}", maxAttributesPerElement);
aoqi@0 503 }
aoqi@0 504 }
aoqi@0 505
aoqi@0 506 if (xif.isPropertySupported(P_MAX_ATTRIBUTE_SIZE)) {
aoqi@0 507 maxAttributeSize = Integer.valueOf(buildIntegerValue(
aoqi@0 508 PROPERTY_MAX_ATTRIBUTE_SIZE, DEFAULT_MAX_ATTRIBUTE_SIZE)
aoqi@0 509 );
aoqi@0 510 xif.setProperty(P_MAX_ATTRIBUTE_SIZE, maxAttributeSize);
aoqi@0 511 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 512 LOGGER.log(Level.FINE, P_MAX_ATTRIBUTE_SIZE + " is {0}", maxAttributeSize);
aoqi@0 513 }
aoqi@0 514 }
aoqi@0 515
aoqi@0 516 if (xif.isPropertySupported(P_MAX_CHILDREN_PER_ELEMENT)) {
aoqi@0 517 maxChildrenPerElement = Integer.valueOf(buildIntegerValue(
aoqi@0 518 PROPERTY_MAX_CHILDREN_PER_ELEMENT, DEFAULT_MAX_CHILDREN_PER_ELEMENT)
aoqi@0 519 );
aoqi@0 520 xif.setProperty(P_MAX_CHILDREN_PER_ELEMENT, maxChildrenPerElement);
aoqi@0 521 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 522 LOGGER.log(Level.FINE, P_MAX_CHILDREN_PER_ELEMENT + " is {0}", maxChildrenPerElement);
aoqi@0 523 }
aoqi@0 524 }
aoqi@0 525
aoqi@0 526 if (xif.isPropertySupported(P_MAX_ELEMENT_DEPTH)) {
aoqi@0 527 maxElementDepth = Integer.valueOf(buildIntegerValue(
aoqi@0 528 PROPERTY_MAX_ELEMENT_DEPTH, DEFAULT_MAX_ELEMENT_DEPTH)
aoqi@0 529 );
aoqi@0 530 xif.setProperty(P_MAX_ELEMENT_DEPTH, maxElementDepth);
aoqi@0 531 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 532 LOGGER.log(Level.FINE, P_MAX_ELEMENT_DEPTH + " is {0}", maxElementDepth);
aoqi@0 533 }
aoqi@0 534 }
aoqi@0 535
aoqi@0 536 if (xif.isPropertySupported(P_MAX_ELEMENT_COUNT)) {
aoqi@0 537 maxElementCount = Long.valueOf(buildLongValue(
aoqi@0 538 PROPERTY_MAX_ELEMENT_COUNT, DEFAULT_MAX_ELEMENT_COUNT)
aoqi@0 539 );
aoqi@0 540 xif.setProperty(P_MAX_ELEMENT_COUNT, maxElementCount);
aoqi@0 541 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 542 LOGGER.log(Level.FINE, P_MAX_ELEMENT_COUNT + " is {0}", maxElementCount);
aoqi@0 543 }
aoqi@0 544 }
aoqi@0 545
aoqi@0 546 if (xif.isPropertySupported(P_MAX_CHARACTERS)) {
aoqi@0 547 maxCharacters = Long.valueOf(buildLongValue(
aoqi@0 548 PROPERTY_MAX_CHARACTERS, DEFAULT_MAX_CHARACTERS)
aoqi@0 549 );
aoqi@0 550 xif.setProperty(P_MAX_CHARACTERS, maxCharacters);
aoqi@0 551 if (LOGGER.isLoggable(Level.FINE)) {
aoqi@0 552 LOGGER.log(Level.FINE, P_MAX_CHARACTERS + " is {0}", maxCharacters);
aoqi@0 553 }
aoqi@0 554 }
aoqi@0 555 }
aoqi@0 556
aoqi@0 557 @Override
aoqi@0 558 public XMLStreamReader doCreate(String systemId, InputStream in, boolean rejectDTDs) {
aoqi@0 559 return super.doCreate(systemId, in, rejectDTDs);
aoqi@0 560 }
aoqi@0 561
aoqi@0 562 @Override
aoqi@0 563 public XMLStreamReader doCreate(String systemId, Reader in, boolean rejectDTDs) {
aoqi@0 564 return super.doCreate(systemId, in, rejectDTDs);
aoqi@0 565 }
aoqi@0 566 }
aoqi@0 567
aoqi@0 568 private static int buildIntegerValue(String propertyName, int defaultValue) {
aoqi@0 569 String propVal = System.getProperty(propertyName);
aoqi@0 570 if (propVal != null && propVal.length() > 0) {
aoqi@0 571 try {
aoqi@0 572 Integer value = Integer.parseInt(propVal);
aoqi@0 573 if (value > 0) {
aoqi@0 574 // return with the value in System property
aoqi@0 575 return value;
aoqi@0 576 }
aoqi@0 577 } catch (NumberFormatException nfe) {
aoqi@0 578 if (LOGGER.isLoggable(Level.WARNING)) {
aoqi@0 579 LOGGER.log(Level.WARNING, StreamingMessages.INVALID_PROPERTY_VALUE_INTEGER(propertyName, propVal, Integer.toString(defaultValue)), nfe);
aoqi@0 580 }
aoqi@0 581 }
aoqi@0 582 }
aoqi@0 583 // return with the default value
aoqi@0 584 return defaultValue;
aoqi@0 585 }
aoqi@0 586
aoqi@0 587 private static long buildLongValue(String propertyName, long defaultValue) {
aoqi@0 588 String propVal = System.getProperty(propertyName);
aoqi@0 589 if (propVal != null && propVal.length() > 0) {
aoqi@0 590 try {
aoqi@0 591 long value = Long.parseLong(propVal);
aoqi@0 592 if (value > 0L) {
aoqi@0 593 // return with the value in System property
aoqi@0 594 return value;
aoqi@0 595 }
aoqi@0 596 } catch (NumberFormatException nfe) {
aoqi@0 597 // defult will be returned
aoqi@0 598 if (LOGGER.isLoggable(Level.WARNING)) {
aoqi@0 599 LOGGER.log(Level.WARNING, StreamingMessages.INVALID_PROPERTY_VALUE_LONG(propertyName, propVal, Long.toString(defaultValue)), nfe);
aoqi@0 600 }
aoqi@0 601 }
aoqi@0 602 }
aoqi@0 603 // return with the default value
aoqi@0 604 return defaultValue;
aoqi@0 605 }
aoqi@0 606
aoqi@0 607 private static Boolean getProperty(final String prop) {
aoqi@0 608 return AccessController.doPrivileged(
aoqi@0 609 new java.security.PrivilegedAction<Boolean>() {
aoqi@0 610 @Override
aoqi@0 611 public Boolean run() {
aoqi@0 612 String value = System.getProperty(prop);
aoqi@0 613 return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
aoqi@0 614 }
aoqi@0 615 }
aoqi@0 616 );
aoqi@0 617 }
aoqi@0 618
aoqi@0 619 }

mercurial