1 package com.ctc.wstx.api;
2
3 import java.lang.ref.SoftReference;
4 import java.net.URL;
5 import java.util.*;
6
7 import javax.xml.XMLConstants;
8 import javax.xml.stream.*;
9
10 import org.codehaus.stax2.XMLInputFactory2; // for property consts
11 import org.codehaus.stax2.XMLStreamProperties; // for property consts
12 import org.codehaus.stax2.validation.DTDValidationSchema;
13
14 import com.ctc.wstx.cfg.InputConfigFlags;
15 import com.ctc.wstx.dtd.DTDEventListener;
16 import com.ctc.wstx.ent.IntEntity;
17 import com.ctc.wstx.ent.EntityDecl;
18 import com.ctc.wstx.io.BufferRecycler;
19 import com.ctc.wstx.util.ArgUtil;
20 import com.ctc.wstx.util.DataUtil;
21 import com.ctc.wstx.util.SymbolTable;
22
23 /**
24  * Simple configuration container class; passed by reader factory to reader
25  * instance created.
26  *<p>
27  * In addition to its main task as a configuration container, this class
28  * also acts as a wrapper around simple buffer recycling functionality.
29  * The reason is that while conceptually this is a separate concern,
30  * there are enough commonalities with the life-cycle of this object to
31  * make this a very convenience place to add that functionality...
32  * (that is: conceptually this is not right, but from pragmatic viewpoint
33  * it just makes sense)
34  */

35 public final class ReaderConfig
36     extends CommonConfig
37     implements InputConfigFlags
38 {
39     // Default limit values
40     
41     public final static int DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT = 1000;
42     public final static int DEFAULT_MAX_ATTRIBUTE_LENGTH = 65536 * 8;
43
44     public final static int DEFAULT_MAX_ELEMENT_DEPTH = 1000;
45
46     public final static int DEFAULT_MAX_ENTITY_DEPTH = 500;
47     public final static int DEFAULT_MAX_ENTITY_COUNT = 100 * 1000;
48
49     /*
50     ///////////////////////////////////////////////////////////////////////
51     // Constants for reader properties:
52     ///////////////////////////////////////////////////////////////////////
53     */

54
55     // // First, standard StAX properties:
56
57     // Simple flags:
58     final static int PROP_COALESCE_TEXT = 1;
59     final static int PROP_NAMESPACE_AWARE = 2;
60     final static int PROP_REPLACE_ENTITY_REFS = 3;
61     final static int PROP_SUPPORT_EXTERNAL_ENTITIES = 4;
62     final static int PROP_VALIDATE_AGAINST_DTD = 5;
63     final static int PROP_SUPPORT_DTD = 6;
64
65     // Object type properties
66     public final static int PROP_EVENT_ALLOCATOR = 7;
67     final static int PROP_WARNING_REPORTER = 8;
68     final static int PROP_XML_RESOLVER = 9;
69
70     // // Then StAX2 standard properties:
71
72     // Simple flags:
73     final static int PROP_INTERN_NS_URIS = 20;
74     final static int PROP_INTERN_NAMES = 21;
75     final static int PROP_REPORT_CDATA = 22;
76     final static int PROP_REPORT_PROLOG_WS = 23;
77     final static int PROP_PRESERVE_LOCATION = 24;
78     final static int PROP_AUTO_CLOSE_INPUT = 25;
79
80     // Enum / Object type properties:
81     final static int PROP_SUPPORT_XMLID = 26; // shared with WriterConfig
82     final static int PROP_DTD_OVERRIDE = 27;
83
84     // And then JAXB feature(s) (since 5.3)
85     final static int PROP_JAXP_SECURE_PROCESSING = 30;
86
87     // // // Constants for additional Wstx properties:
88
89     // Simple flags:
90
91     /**
92      * Note: this entry was deprecated for 4.0 versions up until
93      * and including 4.0.7; was brought back for 4.0.8 (and will
94      * be retained for 4.1)
95      */

96     final static int PROP_NORMALIZE_LFS = 40;
97
98     /* This entry was deprecated for 3.2 and removed in 4.0
99      * version. There are no plans to bring it back.
100      */

101     //final static int PROP_NORMALIZE_ATTR_VALUES = 41;
102
103     final static int PROP_CACHE_DTDS = 42;
104     final static int PROP_CACHE_DTDS_BY_PUBLIC_ID = 43;
105     final static int PROP_LAZY_PARSING = 44;
106     final static int PROP_SUPPORT_DTDPP = 45;
107     final static int PROP_TREAT_CHAR_REFS_AS_ENTS = 46;
108     
109     /**
110      * @since 5.2
111      */

112     final static int PROP_ALLOW_XML11_ESCAPED_CHARS_IN_XML10 = 47;
113
114     // Object type properties:
115
116     final static int PROP_INPUT_BUFFER_LENGTH = 50;
117     //final static int PROP_TEXT_BUFFER_LENGTH = 51;
118     final static int PROP_MIN_TEXT_SEGMENT = 52;
119     final static int PROP_CUSTOM_INTERNAL_ENTITIES = 53;
120     final static int PROP_DTD_RESOLVER = 54;
121     final static int PROP_ENTITY_RESOLVER = 55;
122     final static int PROP_UNDECLARED_ENTITY_RESOLVER = 56;
123     final static int PROP_BASE_URL = 57;
124     final static int PROP_INPUT_PARSING_MODE = 58;
125
126     // Size limitation to prevent various DOS attacks
127     final static int PROP_MAX_ATTRIBUTES_PER_ELEMENT = 60;
128     final static int PROP_MAX_CHILDREN_PER_ELEMENT = 61;
129     final static int PROP_MAX_ELEMENT_COUNT = 62;
130     final static int PROP_MAX_ELEMENT_DEPTH = 63;
131     final static int PROP_MAX_CHARACTERS = 64;
132     final static int PROP_MAX_ATTRIBUTE_SIZE = 65;
133     final static int PROP_MAX_TEXT_LENGTH = 66;
134     final static int PROP_MAX_ENTITY_COUNT = 67;
135     final static int PROP_MAX_ENTITY_DEPTH = 68;
136     
137     /*
138     ////////////////////////////////////////////////
139     // Limits for numeric properties
140     ////////////////////////////////////////////////
141     */

142
143     /**
144      * Need to set a minimum size, since there are some limitations to
145      * smallest consequtive block that can be used.
146      */

147     final static int MIN_INPUT_BUFFER_LENGTH = 8; // 16 bytes
148
149     /**
150      * Let's allow caching of just a dozen DTDs... shouldn't really
151      * matter, how many DTDs does one really use?
152      */

153     final static int DTD_CACHE_SIZE_J2SE = 12;
154
155     final static int DTD_CACHE_SIZE_J2ME = 5;
156
157     /*
158     ///////////////////////////////////////////////////////////////////////
159     // Default values for custom properties:
160     ///////////////////////////////////////////////////////////////////////
161     */

162
163     /**
164      * By default, let's require minimum of 64 chars to be delivered
165      * as shortest partial (piece of) text (CDATA, text) segment;
166      * same for both J2ME subset and full readers. Prevents tiniest
167      * runts from getting passed
168      */

169     final static int DEFAULT_SHORTEST_TEXT_SEGMENT = 64;
170
171     /**
172      * Default config flags are converted from individual settings,
173      * to conform to StAX 1.0 specifications.
174      */

175     final static int DEFAULT_FLAGS_FULL =
176         0
177         // First, default settings StAX specs dictate:
178
179         | CFG_NAMESPACE_AWARE
180         // Coalescing to be disabled
181         //| CFG_COALESCE_TEXT
182         | CFG_REPLACE_ENTITY_REFS
183         | CFG_SUPPORT_EXTERNAL_ENTITIES
184         | CFG_SUPPORT_DTD
185
186         // and then custom setting defaults:
187
188         // and namespace URI interning
189         | CFG_INTERN_NAMES
190         | CFG_INTERN_NS_URIS
191
192         // we will also accurately report CDATA, by default
193         | CFG_REPORT_CDATA
194
195         /* 20-Jan-2006, TSa: As per discussions on stax-builders list
196          *   (and input from xml experts), 4.0 will revert to "do not
197          *   report SPACE events outside root element by default"
198          *   settings. Conceptually this is what xml specification
199          *   implies should be done: there is no content outside of
200          *   the element tree, including any ignorable content, just
201          *   processing instructions and comments.
202          */

203         //| CFG_REPORT_PROLOG_WS
204
205         /* but enable DTD caching (if they are handled):
206          * (... maybe J2ME subset shouldn't do it?)
207          */

208         | CFG_CACHE_DTDS
209         /* 29-Mar-2006, TSa: But note, no caching by public-id, due
210          *   to problems with cases where public-id/system-id were
211          *   inconsistently used, leading to problems.
212          */

213
214         /* by default, let's also allow lazy parsing, since it tends
215          * to improve performance
216          */

217         | CFG_LAZY_PARSING
218
219         /* and also make Event objects preserve location info...
220          * can be turned off for maximum performance
221          */

222         | CFG_PRESERVE_LOCATION
223
224         // As per Stax 1.0 specs, we can not enable this by default:
225         //| CFG_AUTO_CLOSE_INPUT);
226
227         /* Also, let's enable dtd++ support (shouldn't hurt with non-dtd++
228          * dtds)
229          */

230
231         | CFG_SUPPORT_DTDPP
232         
233         /*
234          * Set this as a default, as this is required in xml;
235          */

236         | CFG_NORMALIZE_LFS
237
238         /* Regarding Xml:id, let's enabled typing by default, but not
239          * uniqueness validity checks: latter will be taken care of
240          * by DTD validation if enabled, otherwise needs to be explicitly
241          * enabled
242          */

243         | CFG_XMLID_TYPING
244         // | CFG_XMLID_UNIQ_CHECKS
245         ;
246
247     /**
248      * For now defaults for J2ME flags can be identical to 'full' set;
249      * differences are in buffer sizes.
250      */

251     final static int DEFAULT_FLAGS_J2ME = DEFAULT_FLAGS_FULL;
252
253     // // //
254
255     /**
256      * Map to use for converting from String property ids to ints
257      * described above; useful to allow use of switch later on.
258      */

259     final static HashMap<String,Integer> sProperties = new HashMap<String,Integer>(64); // we have about 40 entries
260     static {
261         // Standard ones; support for features
262         sProperties.put(XMLInputFactory.IS_COALESCING, PROP_COALESCE_TEXT);
263         sProperties.put(XMLInputFactory.IS_NAMESPACE_AWARE,
264                         PROP_NAMESPACE_AWARE);
265         sProperties.put(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES,
266                     PROP_REPLACE_ENTITY_REFS);
267         sProperties.put(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES,
268                     PROP_SUPPORT_EXTERNAL_ENTITIES);
269         sProperties.put(XMLInputFactory.IS_VALIDATING,
270                         PROP_VALIDATE_AGAINST_DTD);
271         sProperties.put(XMLInputFactory.SUPPORT_DTD,
272                         PROP_SUPPORT_DTD);
273
274         // Standard ones; pluggable components
275         sProperties.put(XMLInputFactory.ALLOCATOR,
276                         PROP_EVENT_ALLOCATOR);
277         sProperties.put(XMLInputFactory.REPORTER,
278                         PROP_WARNING_REPORTER);
279         sProperties.put(XMLInputFactory.RESOLVER,
280                         PROP_XML_RESOLVER);
281
282         // StAX2-introduced flags:
283         sProperties.put(XMLInputFactory2.P_INTERN_NAMES,
284                         PROP_INTERN_NAMES);
285         sProperties.put(XMLInputFactory2.P_INTERN_NS_URIS,
286                         PROP_INTERN_NS_URIS);
287         sProperties.put(XMLInputFactory2.P_REPORT_CDATA,
288                         PROP_REPORT_CDATA);
289         sProperties.put(XMLInputFactory2.P_REPORT_PROLOG_WHITESPACE,
290                         PROP_REPORT_PROLOG_WS);
291         sProperties.put(XMLInputFactory2.P_PRESERVE_LOCATION,
292                         PROP_PRESERVE_LOCATION);
293         sProperties.put(XMLInputFactory2.P_AUTO_CLOSE_INPUT,
294                         PROP_AUTO_CLOSE_INPUT);
295         sProperties.put(XMLInputFactory2.XSP_SUPPORT_XMLID,
296                         PROP_SUPPORT_XMLID);
297         sProperties.put(XMLInputFactory2.P_DTD_OVERRIDE,
298                         PROP_DTD_OVERRIDE);
299
300         // JAXP-features/properties:
301
302         
303         sProperties.put(XMLConstants.FEATURE_SECURE_PROCESSING,
304                 PROP_JAXP_SECURE_PROCESSING);
305
306         // Non-standard ones, flags:
307
308         sProperties.put(WstxInputProperties.P_CACHE_DTDS, PROP_CACHE_DTDS);
309         sProperties.put(WstxInputProperties.P_CACHE_DTDS_BY_PUBLIC_ID,
310                         PROP_CACHE_DTDS_BY_PUBLIC_ID);
311         sProperties.put(XMLInputFactory2.P_LAZY_PARSING, PROP_LAZY_PARSING);
312         /*
313         sProperties.put(WstxInputProperties.P_SUPPORT_DTDPP,
314                         PROP_SUPPORT_DTDPP));
315                         */

316         sProperties.put(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS,
317                 PROP_TREAT_CHAR_REFS_AS_ENTS);
318         sProperties.put(WstxInputProperties.P_ALLOW_XML11_ESCAPED_CHARS_IN_XML10,
319                 PROP_ALLOW_XML11_ESCAPED_CHARS_IN_XML10);
320         sProperties.put(WstxInputProperties.P_NORMALIZE_LFS, PROP_NORMALIZE_LFS);
321
322         // Non-standard ones, non-flags:
323
324         sProperties.put(WstxInputProperties.P_INPUT_BUFFER_LENGTH,
325                         PROP_INPUT_BUFFER_LENGTH);
326         sProperties.put(WstxInputProperties.P_MIN_TEXT_SEGMENT,
327                         PROP_MIN_TEXT_SEGMENT);
328         sProperties.put(WstxInputProperties.P_MAX_ATTRIBUTES_PER_ELEMENT,
329                         PROP_MAX_ATTRIBUTES_PER_ELEMENT);
330         sProperties.put(WstxInputProperties.P_MAX_ATTRIBUTE_SIZE,
331                         PROP_MAX_ATTRIBUTE_SIZE);
332         sProperties.put(WstxInputProperties.P_MAX_CHILDREN_PER_ELEMENT,
333                         PROP_MAX_CHILDREN_PER_ELEMENT);
334         sProperties.put(WstxInputProperties.P_MAX_TEXT_LENGTH,
335                         PROP_MAX_TEXT_LENGTH);
336         sProperties.put(WstxInputProperties.P_MAX_ELEMENT_COUNT,
337                         PROP_MAX_ELEMENT_COUNT);
338         sProperties.put(WstxInputProperties.P_MAX_ELEMENT_DEPTH,
339                         PROP_MAX_ELEMENT_DEPTH);
340         sProperties.put(WstxInputProperties.P_MAX_ENTITY_DEPTH,
341                  PROP_MAX_ENTITY_DEPTH);
342         sProperties.put(WstxInputProperties.P_MAX_ENTITY_COUNT,
343                  PROP_MAX_ENTITY_COUNT);
344         sProperties.put(WstxInputProperties.P_MAX_CHARACTERS, PROP_MAX_CHARACTERS);
345         sProperties.put(WstxInputProperties.P_CUSTOM_INTERNAL_ENTITIES,
346                 Integer.valueOf(PROP_CUSTOM_INTERNAL_ENTITIES));
347         sProperties.put(WstxInputProperties.P_DTD_RESOLVER,
348                         PROP_DTD_RESOLVER);
349         sProperties.put(WstxInputProperties.P_ENTITY_RESOLVER,
350                         PROP_ENTITY_RESOLVER);
351         sProperties.put(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER,
352                         PROP_UNDECLARED_ENTITY_RESOLVER);
353         sProperties.put(WstxInputProperties.P_BASE_URL,
354                         PROP_BASE_URL);
355         sProperties.put(WstxInputProperties.P_INPUT_PARSING_MODE,
356                         PROP_INPUT_PARSING_MODE);
357     }
358
359     /*
360     ///////////////////////////////////////////////////////////////////////
361     // Current config state:
362     ///////////////////////////////////////////////////////////////////////
363      */

364
365     final protected boolean mIsJ2MESubset;
366
367     final protected SymbolTable mSymbols;
368
369     /**
370      * Bitset that contains state of on/off properties; initialized
371      * to defaults, but can be set/cleared.
372      */

373     protected int mConfigFlags;
374
375     /**
376      * Bitset that indicates explicit changes to {@link #mConfigFlags}
377      * through calls; empty bit means that the corresponding property
378      * has its default value, set bit that an explicit call has been
379      * made.
380      */

381     protected int mConfigFlagMods;
382
383     /**
384      * 13-Nov-2008, tatus: Need to be able to keep track of whether
385      *    name-interning has been explicitly enabled/disable or not
386      *    (not if it's whatever defaults we have)
387      */

388     final static int PROP_INTERN_NAMES_EXPLICIT = 26;
389     final static int PROP_INTERN_NS_URIS_EXPLICIT = 27;
390
391     protected int mInputBufferLen;
392     protected int mMinTextSegmentLen;
393     protected int mMaxAttributesPerElement = DEFAULT_MAX_ATTRIBUTES_PER_ELEMENT;
394     protected int mMaxAttributeSize = DEFAULT_MAX_ATTRIBUTE_LENGTH;
395     protected int mMaxChildrenPerElement = Integer.MAX_VALUE;
396     protected int mMaxElementDepth = DEFAULT_MAX_ELEMENT_DEPTH;
397     protected long mMaxElementCount = Long.MAX_VALUE; // unlimited
398     protected long mMaxCharacters = Long.MAX_VALUE; // unlimited
399     protected int mMaxTextLength = Integer.MAX_VALUE; // unlimited
400
401     protected int mMaxEntityDepth = DEFAULT_MAX_ENTITY_DEPTH;
402     protected long mMaxEntityCount = DEFAULT_MAX_ENTITY_COUNT;
403     
404     /**
405      * Base URL to use as the resolution context for relative entity
406      * references
407      */

408     protected URL mBaseURL;
409
410     /**
411      * Parsing mode can be changed from the default xml compliant
412      * behavior to one of alternate modes (fragment processing,
413      * multiple document processing).
414      */

415     protected WstxInputProperties.ParsingMode mParsingMode =
416         WstxInputProperties.PARSING_MODE_DOCUMENT;
417
418     /**
419      * This boolean flag is set if the input document requires
420      * xml 1.1 (or above) compliant processing: default is xml 1.0
421      * compliant. Note that unlike most other properties, this
422      * does not come from configuration settings, but from processed
423      * document itself.
424      */

425     protected boolean mXml11 = false;
426
427     /*
428     ///////////////////////////////////////////////////////////////////////
429     // Common configuration objects
430     ///////////////////////////////////////////////////////////////////////
431      */

432
433     XMLReporter mReporter;
434
435     XMLResolver mDtdResolver = null;
436     XMLResolver mEntityResolver = null;
437
438     /*
439     ///////////////////////////////////////////////////////////////////////
440     // More special(ized) configuration objects
441     ///////////////////////////////////////////////////////////////////////
442      */

443
444     //Map mCustomEntities;
445     //XMLResolver mUndeclaredEntityResolver;
446     //DTDEventListener mDTDEventListener;
447
448     Object[] mSpecialProperties = null;
449
450     private final static int SPEC_PROC_COUNT = 4;
451
452     private final static int SP_IX_CUSTOM_ENTITIES = 0;
453     private final static int SP_IX_UNDECL_ENT_RESOLVER = 1;
454     private final static int SP_IX_DTD_EVENT_LISTENER = 2;
455     private final static int SP_IX_DTD_OVERRIDE = 3;
456
457     /*
458     ///////////////////////////////////////////////////////////////////////
459     // Buffer recycling:
460     ///////////////////////////////////////////////////////////////////////
461      */

462
463     /**
464      * This <code>ThreadLocal</code> contains a {@link SoftRerefence}
465      * to a {@link BufferRecycler} used to provide a low-cost
466      * buffer recycling between Reader instances.
467      */

468     final static ThreadLocal<SoftReference<BufferRecycler>> mRecyclerRef = new ThreadLocal<SoftReference<BufferRecycler>>();
469
470     /**
471      * This is the actually container of the recyclable buffers. It
472      * is obtained via ThreadLocal/SoftReference combination, if one
473      * exists, when Config instance is created. If one does not
474      * exist, it will created first time a buffer is returned.
475      */

476     BufferRecycler mCurrRecycler = null;
477
478     /*
479     ///////////////////////////////////////////////////////////////////////
480     // Life-cycle
481     ///////////////////////////////////////////////////////////////////////
482      */

483
484     private ReaderConfig(ReaderConfig base,
485             boolean j2meSubset, SymbolTable symbols,
486             int configFlags, int configFlagMods,
487             int inputBufLen,
488             int minTextSegmentLen)
489     {
490         super(base);
491         mIsJ2MESubset = j2meSubset;
492         mSymbols = symbols;
493
494         mConfigFlags = configFlags;
495         mConfigFlagMods = configFlagMods;
496
497         mInputBufferLen = inputBufLen;
498         mMinTextSegmentLen = minTextSegmentLen;
499         if (base != null) {
500             mMaxAttributesPerElement = base.mMaxAttributesPerElement;
501             mMaxAttributeSize = base.mMaxAttributeSize;
502             mMaxChildrenPerElement = base.mMaxChildrenPerElement;
503             mMaxElementCount = base.mMaxElementCount;
504             mMaxElementDepth = base.mMaxElementDepth;
505             mMaxCharacters = base.mMaxCharacters;
506             mMaxTextLength = base.mMaxTextLength;
507             mMaxEntityDepth = base.mMaxEntityDepth;
508             mMaxEntityCount = base.mMaxEntityCount;
509         }
510
511         /* Ok, let's then see if we can find a buffer recycler. Since they
512          * are lazily constructed, and since GC may just flush them out
513          * on its whims, it's possible we might not find one. That's ok;
514          * we can reconstruct one if and when we are to return one or more
515          * buffers.
516          */

517         SoftReference<BufferRecycler> ref = mRecyclerRef.get();
518         if (ref != null) {
519             mCurrRecycler = ref.get();
520         }
521     }
522
523     public static ReaderConfig createJ2MEDefaults()
524     {
525         /* For J2ME we'll use slightly smaller buffer sizes by
526          * default, on assumption lower memory usage is desireable:
527          */

528         ReaderConfig rc = new ReaderConfig(null,
529                 truenull, DEFAULT_FLAGS_J2ME, 0,
530                 // 4k input buffer (2000 chars):
531                 2000,
532                 DEFAULT_SHORTEST_TEXT_SEGMENT);
533         return rc;
534     }
535
536     public static ReaderConfig createFullDefaults()
537     {
538         /* For full version, can use bit larger buffers to achieve better
539          * overall performance.
540          */

541         ReaderConfig rc = new ReaderConfig(null,
542                 falsenull, DEFAULT_FLAGS_FULL, 0,
543                 // 8k input buffer (4000 chars):
544                 4000,
545                 DEFAULT_SHORTEST_TEXT_SEGMENT);
546         return rc;
547     }
548
549     public ReaderConfig createNonShared(SymbolTable sym)
550     {
551         // should we throw an exception?
552         //if (sym == null) { }
553         ReaderConfig rc = new ReaderConfig(this,
554                 mIsJ2MESubset, sym,
555                 mConfigFlags, mConfigFlagMods,
556                 mInputBufferLen,
557                 mMinTextSegmentLen);
558         rc.mReporter = mReporter;
559         rc.mDtdResolver = mDtdResolver;
560         rc.mEntityResolver = mEntityResolver;
561         rc.mBaseURL = mBaseURL;
562         rc.mParsingMode = mParsingMode;
563         rc.mMaxAttributesPerElement = mMaxAttributesPerElement;
564         rc.mMaxAttributeSize = mMaxAttributeSize;
565         rc.mMaxChildrenPerElement = mMaxChildrenPerElement;
566         rc.mMaxElementCount = mMaxElementCount;
567         rc.mMaxCharacters = mMaxCharacters;
568         rc.mMaxTextLength = mMaxTextLength;
569         rc.mMaxElementDepth = mMaxElementDepth;
570         rc.mMaxEntityDepth = mMaxEntityDepth;
571         rc.mMaxEntityCount = mMaxEntityCount;
572         if (mSpecialProperties != null) {
573             int len = mSpecialProperties.length;
574             Object[] specProps = new Object[len];
575             System.arraycopy(mSpecialProperties, 0, specProps, 0, len);
576             rc.mSpecialProperties = specProps;
577         }
578         return rc;
579     }
580
581     /**
582      * Unlike name suggests there is also some limited state information
583      * associated with the config object. If these objects are reused,
584      * that state needs to be reset between reuses, to avoid carrying
585      * over incorrect state.
586      */

587     public void resetState()
588     {
589         // Current, only xml 1.0 vs 1.1 state is stored here:
590         mXml11 = false;
591     }
592
593     /*
594     ///////////////////////////////////////////////////////////////////////
595     // Implementation of abstract methods
596     ///////////////////////////////////////////////////////////////////////
597      */

598
599     @Override
600     protected int findPropertyId(String propName)
601     {
602         Integer I = sProperties.get(propName);
603         return (I == null) ? -1 : I.intValue();
604     }
605  
606     /*
607     ///////////////////////////////////////////////////////////////////////
608     // Public API, accessors
609     ///////////////////////////////////////////////////////////////////////
610      */

611
612     // // // Accessors for immutable configuration:
613
614     public SymbolTable getSymbols() { return mSymbols; }
615
616     /**
617      * In future this property could/should be made configurable?
618      */

619
620     public int getDtdCacheSize() {
621         return mIsJ2MESubset ? DTD_CACHE_SIZE_J2ME : DTD_CACHE_SIZE_J2SE;
622     }
623
624     // // // "Raw" accessors for on/off properties:
625
626     public int getConfigFlags() { return mConfigFlags; }
627
628     // // // Standard StAX on/off property accessors
629
630     public boolean willCoalesceText() {
631         return _hasConfigFlag(CFG_COALESCE_TEXT);
632     }
633
634     public boolean willSupportNamespaces() {
635         return _hasConfigFlag(CFG_NAMESPACE_AWARE);
636     }
637
638     public boolean willReplaceEntityRefs() {
639         return _hasConfigFlag(CFG_REPLACE_ENTITY_REFS);
640     }
641
642     public boolean willSupportExternalEntities() {
643         return _hasConfigFlag(CFG_SUPPORT_EXTERNAL_ENTITIES);
644     }
645
646     public boolean willSupportDTDs() {
647         return _hasConfigFlag(CFG_SUPPORT_DTD);
648     }
649
650     public boolean willValidateWithDTD() {
651         return _hasConfigFlag(CFG_VALIDATE_AGAINST_DTD);
652     }
653
654     // // // Stax2 on/off property accessors
655
656     public boolean willReportCData() {
657         return _hasConfigFlag(CFG_REPORT_CDATA);
658     }
659
660     public boolean willParseLazily() {
661         return _hasConfigFlag(CFG_LAZY_PARSING);
662     }
663
664     public boolean willInternNames() {
665         return _hasConfigFlag(CFG_INTERN_NAMES);
666     }
667
668     public boolean willInternNsURIs() {
669         return _hasConfigFlag(CFG_INTERN_NS_URIS);
670     }
671
672     public boolean willPreserveLocation() {
673         return _hasConfigFlag(CFG_PRESERVE_LOCATION);
674     }
675
676     public boolean willAutoCloseInput() {
677         return _hasConfigFlag(CFG_AUTO_CLOSE_INPUT);
678     }
679
680     // // // JAXP on/off
681
682     public boolean willProcessSecurely() {
683         return _hasConfigFlag(CFG_JAXP_FEATURE_SECURE_PROCESSING);
684     }
685     
686     // // // Woodstox on/off property accessors
687
688     public boolean willReportPrologWhitespace() {
689         return _hasConfigFlag(CFG_REPORT_PROLOG_WS);
690     }
691
692     public boolean willCacheDTDs() {
693         return _hasConfigFlag(CFG_CACHE_DTDS);
694     }
695
696     public boolean willCacheDTDsByPublicId() {
697         return _hasConfigFlag(CFG_CACHE_DTDS_BY_PUBLIC_ID);
698     }
699
700     public boolean willDoXmlIdTyping() {
701         return _hasConfigFlag(CFG_XMLID_TYPING);
702     }
703
704     public boolean willDoXmlIdUniqChecks() {
705         return _hasConfigFlag(CFG_XMLID_UNIQ_CHECKS);
706     }
707
708     public boolean willSupportDTDPP() {
709         return _hasConfigFlag(CFG_SUPPORT_DTDPP);
710     }
711     
712     public boolean willNormalizeLFs() {
713         return _hasConfigFlag(CFG_NORMALIZE_LFS);
714     }
715     
716     public boolean willTreatCharRefsAsEnts() {
717         return _hasConfigFlag(CFG_TREAT_CHAR_REFS_AS_ENTS);
718     }
719
720     public boolean willAllowXml11EscapedCharsInXml10() {
721         return _hasConfigFlag(CFG_ALLOW_XML11_ESCAPED_CHARS_IN_XML10);
722     }
723
724     public int getInputBufferLength() { return mInputBufferLen; }
725
726     public int getShortestReportedTextSegment() { return mMinTextSegmentLen; }
727     
728     public int getMaxAttributesPerElement() { return mMaxAttributesPerElement; }
729     public int getMaxAttributeSize() { return mMaxAttributeSize; }
730     public int getMaxChildrenPerElement() { return mMaxChildrenPerElement; }
731
732     public int getMaxElementDepth() { return mMaxElementDepth; }
733     public long getMaxElementCount() { return mMaxElementCount; }
734
735     public int getMaxEntityDepth() { return mMaxEntityDepth; }
736     public long getMaxEntityCount() { return mMaxEntityCount; }
737
738     public long getMaxCharacters() { return mMaxCharacters; }
739     public long getMaxTextLength() { return mMaxTextLength; }
740
741     public Map<String,EntityDecl> getCustomInternalEntities()
742     {
743         @SuppressWarnings("unchecked")
744         Map<String,EntityDecl> custEnt = (Map<String,EntityDecl>) _getSpecialProperty(SP_IX_CUSTOM_ENTITIES);
745         if (custEnt == null) {
746             return Collections.emptyMap();
747         }
748         // Better be defensive and just return a copy...
749         int len = custEnt.size();
750         HashMap<String,EntityDecl> m = new HashMap<String,EntityDecl>(len + (len >> 2), 0.81f);
751         for (Map.Entry<String,EntityDecl> me : custEnt.entrySet()) {
752             m.put(me.getKey(), me.getValue());
753         }
754         return m;
755     }
756
757     public EntityDecl findCustomInternalEntity(String id)
758     {
759         @SuppressWarnings("unchecked")
760         Map<String,EntityDecl> custEnt = (Map<String,EntityDecl>) _getSpecialProperty(SP_IX_CUSTOM_ENTITIES);
761         if (custEnt == null) {
762             return null;
763         }
764         return custEnt.get(id);
765     }
766
767     public XMLReporter getXMLReporter() { return mReporter; }
768
769     public XMLResolver getXMLResolver() { return mEntityResolver; }
770
771     public XMLResolver getDtdResolver() { return mDtdResolver; }
772     public XMLResolver getEntityResolver() { return mEntityResolver; }
773     public XMLResolver getUndeclaredEntityResolver() {
774         return (XMLResolver) _getSpecialProperty(SP_IX_UNDECL_ENT_RESOLVER);
775     }
776
777     public URL getBaseURL() { return mBaseURL; }
778
779     public WstxInputProperties.ParsingMode getInputParsingMode() {
780         return mParsingMode;
781     }
782
783     public boolean inputParsingModeDocuments() {
784         return mParsingMode == WstxInputProperties.PARSING_MODE_DOCUMENTS;
785     }
786
787     public boolean inputParsingModeFragment() {
788         return mParsingMode == WstxInputProperties.PARSING_MODE_FRAGMENT;
789     }
790
791     /**
792      * @return True if the input well-formedness and validation checks
793      *    should be done according to xml 1.1 specification; false if
794      *    xml 1.0 specification.
795      */

796     public boolean isXml11() {
797         return mXml11;
798     }
799
800     public DTDEventListener getDTDEventListener() {
801         return (DTDEventListener) _getSpecialProperty(SP_IX_DTD_EVENT_LISTENER);
802     }
803
804     public DTDValidationSchema getDTDOverride() {
805         return (DTDValidationSchema) _getSpecialProperty(SP_IX_DTD_OVERRIDE);
806     }
807
808     /**
809      * Special accessor to use to verify whether name interning has
810      * explicitly been enabled; true if call was been made to set
811      * it to truefalse otherwise (default, or set to false)
812      */

813     public boolean hasInternNamesBeenEnabled() {
814         return _hasExplicitConfigFlag(CFG_INTERN_NAMES);
815     }
816
817     public boolean hasInternNsURIsBeenEnabled() {
818         return _hasExplicitConfigFlag(CFG_INTERN_NS_URIS);
819     }
820
821     /*
822     ///////////////////////////////////////////////////////////////////////
823     // Simple mutators
824     ///////////////////////////////////////////////////////////////////////
825      */

826
827     public void setConfigFlag(int flag) {
828         mConfigFlags |= flag;
829         mConfigFlagMods |= flag;
830     }
831
832     public void clearConfigFlag(int flag) {
833         mConfigFlags &= ~flag;
834         mConfigFlagMods |= flag;
835     }
836
837     // // // Mutators for standard StAX properties
838
839     public void doCoalesceText(boolean state) {
840         setConfigFlag(CFG_COALESCE_TEXT, state);
841     }
842
843     public void doSupportNamespaces(boolean state) {
844         setConfigFlag(CFG_NAMESPACE_AWARE, state);
845     }
846
847     public void doReplaceEntityRefs(boolean state) {
848         setConfigFlag(CFG_REPLACE_ENTITY_REFS, state);
849     }
850
851     public void doSupportExternalEntities(boolean state) {
852         setConfigFlag(CFG_SUPPORT_EXTERNAL_ENTITIES, state);
853     }
854
855     public void doSupportDTDs(boolean state) {
856         setConfigFlag(CFG_SUPPORT_DTD, state);
857     }
858
859     public void doValidateWithDTD(boolean state) {
860         setConfigFlag(CFG_VALIDATE_AGAINST_DTD, state);
861     }
862
863     // // // Mutators for JAXB features/properties
864
865     /**
866      * Method called when {code XMLConstants.FEATURE_SECURE_PROCESSING} is being
867      * enabled or disabled.
868      *<p>
869      * Note that disabling (passing {code false} as argument) does not actually
870      * change any settings.
871      *<p>
872      * Calls made when {@code true} is passed (that is, secure processing enabled):
873      *<ul>
874      * <li>{@code doSupportExternalEntities(false)}
875      *  </li>
876      *</ul>
877      *
878      * @since 5.3
879      */

880     public void doProcessSecurely(boolean value) {
881         // if disabling, nothing special to do; only matters if it's being enabled
882         setConfigFlag(CFG_JAXP_FEATURE_SECURE_PROCESSING, value);
883         if (value) {
884             doSupportExternalEntities(false);
885         }
886     }
887     
888     // // // Mutators for Woodstox-specific properties
889
890     public void doInternNames(boolean state) {
891         setConfigFlag(CFG_INTERN_NAMES, state);
892     }
893
894     public void doInternNsURIs(boolean state) {
895         setConfigFlag(CFG_INTERN_NS_URIS, state);
896     }
897
898     public void doReportPrologWhitespace(boolean state) {
899         setConfigFlag(CFG_REPORT_PROLOG_WS, state);
900     }
901
902     public void doReportCData(boolean state) {
903         setConfigFlag(CFG_REPORT_CDATA, state);
904     }
905
906     public void doCacheDTDs(boolean state) {
907         setConfigFlag(CFG_CACHE_DTDS, state);
908     }
909
910     public void doCacheDTDsByPublicId(boolean state) {
911         setConfigFlag(CFG_CACHE_DTDS_BY_PUBLIC_ID, state);
912     }
913
914     public void doParseLazily(boolean state) {
915         setConfigFlag(CFG_LAZY_PARSING, state);
916     }
917
918     public void doXmlIdTyping(boolean state) {
919         setConfigFlag(CFG_XMLID_TYPING, state);
920     }
921
922     public void doXmlIdUniqChecks(boolean state) {
923         setConfigFlag(CFG_XMLID_UNIQ_CHECKS, state);
924     }
925
926     public void doPreserveLocation(boolean state) {
927         setConfigFlag(CFG_PRESERVE_LOCATION, state);
928     }
929
930     public void doAutoCloseInput(boolean state) {
931         setConfigFlag(CFG_AUTO_CLOSE_INPUT, state);
932     }
933
934     public void doSupportDTDPP(boolean state) {
935         setConfigFlag(CFG_SUPPORT_DTDPP, state);
936     }
937     
938     public void doTreatCharRefsAsEnts(final boolean state) {
939         setConfigFlag(CFG_TREAT_CHAR_REFS_AS_ENTS, state);
940     }
941
942     public void doAllowXml11EscapedCharsInXml10(final boolean state) {
943         setConfigFlag(CFG_ALLOW_XML11_ESCAPED_CHARS_IN_XML10, state);
944     }
945
946     public void doNormalizeLFs(final boolean state) {
947         setConfigFlag(CFG_NORMALIZE_LFS, state);
948     }
949
950     public void setInputBufferLength(int value)
951     {
952         /* Let's enforce minimum here; necessary to allow longest
953          * consequtive text span to be available (xml decl, etc)
954          */

955         if (value < MIN_INPUT_BUFFER_LENGTH) {
956             value = MIN_INPUT_BUFFER_LENGTH;
957         }
958         mInputBufferLen = value;
959     }
960
961     public void setShortestReportedTextSegment(int value) {
962         mMinTextSegmentLen = value;
963     }
964     public void setMaxAttributesPerElement(int value) {
965         mMaxAttributesPerElement = value;
966     }
967     public void setMaxAttributeSize(int value) {
968         mMaxAttributeSize = value;
969     }
970     public void setMaxChildrenPerElement(int value) {
971         mMaxChildrenPerElement = value;
972     }
973     public void setMaxElementDepth(int value) {
974         mMaxElementDepth = value;
975     }
976     public void setMaxElementCount(long value) {
977         mMaxElementCount = value;
978     }
979     public void setMaxCharacters(long value) {
980         mMaxCharacters = value;
981     }
982     public void setMaxTextLength(int value) {
983         mMaxTextLength = value;
984     }
985     public void setMaxEntityDepth(int value) {
986         mMaxEntityDepth = value;
987     }
988     public void setMaxEntityCount(long value) {
989         mMaxEntityCount = value;
990     }
991
992     public void setCustomInternalEntities(Map<String,?> m)
993     {
994         Map<String,EntityDecl> entMap;
995         if (m == null || m.size() < 1) {
996             entMap = Collections.emptyMap();
997         } else {
998             int len = m.size();
999             entMap = new HashMap<String,EntityDecl>(len + (len >> 1), 0.75f);
1000             for (Map.Entry<String,?> me : m.entrySet()) {
1001                 Object val = me.getValue();
1002                 char[] ch;
1003                 if (val == null) {
1004                     ch = DataUtil.getEmptyCharArray();
1005                 } else if (val instanceof char[]) {
1006                     ch = (char[]) val;
1007                 } else {
1008                     // Probably String, but let's just ensure that
1009                     String str = val.toString();
1010                     ch = str.toCharArray();
1011                 }
1012                 String name = me.getKey();
1013                 entMap.put(name, IntEntity.create(name, ch));
1014             }
1015         }
1016         _setSpecialProperty(SP_IX_CUSTOM_ENTITIES, entMap);
1017     }
1018
1019     public void setXMLReporter(XMLReporter r) {
1020         mReporter = r;
1021     }
1022
1023     /**
1024      * Note: for better granularity, you should call {@link #setEntityResolver}
1025      * and {@link #setDtdResolver} instead.
1026      */

1027     public void setXMLResolver(XMLResolver r) {
1028         mEntityResolver = r;
1029         mDtdResolver = r;
1030     }
1031
1032     public void setDtdResolver(XMLResolver r) {
1033         mDtdResolver = r;
1034     }
1035
1036     public void setEntityResolver(XMLResolver r) {
1037         mEntityResolver = r;
1038     }
1039
1040     public void setUndeclaredEntityResolver(XMLResolver r) {
1041         _setSpecialProperty(SP_IX_UNDECL_ENT_RESOLVER, r);
1042     }
1043
1044     public void setBaseURL(URL baseURL) { mBaseURL = baseURL; }
1045
1046     public void setInputParsingMode(WstxInputProperties.ParsingMode mode) {
1047         mParsingMode = mode;
1048     }
1049
1050     /**
1051      * Method called to enable or disable 1.1 compliant processing; if
1052      * disabled, defaults to xml 1.0 compliant processing.
1053      */

1054     public void enableXml11(boolean state) {
1055         mXml11 = state;
1056     }
1057
1058     public void setDTDEventListener(DTDEventListener l) {
1059         _setSpecialProperty(SP_IX_DTD_EVENT_LISTENER, l);
1060     }
1061
1062     public void setDTDOverride(DTDValidationSchema schema) {
1063         _setSpecialProperty(SP_IX_DTD_OVERRIDE, schema);
1064     }
1065
1066     /*
1067     ///////////////////////////////////////////////////////////////////////
1068     // Profile mutators:
1069     ///////////////////////////////////////////////////////////////////////
1070      */

1071
1072     /**
1073      * Method to call to make Reader created conform as closely to XML
1074      * standard as possible, doing all checks and transformations mandated
1075      * (linefeed conversions, attr value normalizations).
1076      * See {@link XMLInputFactory2#configureForXmlConformance} for
1077      * required settings for standard StAX/StAX properties.
1078      *<p>
1079      * In addition to the standard settings, following Woodstox-specific
1080      * settings are also done:
1081      *<ul>
1082      * <li><b>None</b></li>
1083      *</ul>
1084      *<p>
1085      * Notes: Does NOT change 'performance' settings (buffer sizes,
1086      * DTD caching, coalescing, interning, accurate location info).
1087      */

1088     public void configureForXmlConformance()
1089     {
1090         // // StAX 1.0 settings
1091         doSupportNamespaces(true);
1092         doSupportDTDs(true);
1093         doSupportExternalEntities(true);
1094         doReplaceEntityRefs(true);
1095
1096         // // Stax2 additional settings
1097
1098         // Better enable full xml:id checks:
1099         doXmlIdTyping(true);
1100         doXmlIdUniqChecks(true);
1101
1102         // Woodstox-specific ones:
1103     }
1104
1105     /**
1106      * Method to call to make Reader created be as "convenient" to use
1107      * as possible; ie try to avoid having to deal with some of things
1108      * like segmented text chunks. This may incur some slight performance
1109      * penalties, but should not affect XML conformance.
1110      * See {@link XMLInputFactory2#configureForConvenience} for
1111      * required settings for standard StAX/StAX properties.
1112      *<p>
1113      * In addition to the standard settings, following Woodstox-specific
1114      * settings are also done:
1115      *<ul>
1116      *  <li>Disable <code>XMLStreamFactory2.P_LAZY_PARSING</code> (to allow for synchronous
1117      *    error notification by forcing full XML events to be completely
1118      *    parsed when reader's {@code next()} is called)
1119      * </li>
1120      *</ul>
1121      */

1122     public void configureForConvenience()
1123     {
1124         // StAX (1.0) settings:
1125         doCoalesceText(true);
1126         doReplaceEntityRefs(true);
1127
1128         // StAX2: 
1129         doReportCData(false);
1130         doReportPrologWhitespace(false);
1131         /* Also, knowing exact locations is nice esp. for error
1132          * reporting purposes
1133          */

1134         doPreserveLocation(true);
1135
1136         // Woodstox-specific:
1137
1138         /* Also, we can force errors to be reported in timely manner:
1139          * (once again, at potential expense of performance)
1140          */

1141         doParseLazily(false);
1142     }
1143
1144     /**
1145      * Method to call to make the Reader created be as fast as possible reading
1146      * documents, especially for long-running processes where caching is
1147      * likely to help.
1148      *
1149      * See {@link XMLInputFactory2#configureForSpeed} for
1150      * required settings for standard StAX/StAX properties.
1151      *<p>
1152      * In addition to the standard settings, following Woodstox-specific
1153      * settings are also done:
1154      *<ul>
1155      * <li>Enable <code>P_CACHE_DTDS</code>.
1156      *  </li>
1157      * <li>Enable <code>XMLStremaFactory2.P_LAZY_PARSING</code> (can improve performance
1158      *   especially when skipping text segments)
1159      *  </li>
1160      * <li>Disable Xml:id uniqueness checks (and leave typing as is)
1161      *  </li>
1162      * <li>Set lowish value for <code>P_MIN_TEXT_SEGMENT</code>, to allow
1163      *   reader to optimize segment length it uses (and possibly avoids
1164      *   one copy operation in the process)
1165      *  </li>
1166      * <li>Increase <code>P_INPUT_BUFFER_LENGTH</code> a bit from default,
1167      *   to allow for longer consequtive read operations; also reduces cases
1168      *   where partial text segments are on input buffer boundaries.
1169      *  </li>
1170      *</ul>
1171      */

1172     public void configureForSpeed()
1173     {
1174         // StAX (1.0):
1175         doCoalesceText(false);
1176
1177         // StAX2:
1178         doPreserveLocation(false);
1179         doReportPrologWhitespace(false);
1180         //doInternNames(true); // this is a NOP
1181         doInternNsURIs(true);
1182         doXmlIdUniqChecks(false);
1183
1184         // Woodstox-specific:
1185         doCacheDTDs(true);
1186         doParseLazily(true);
1187
1188         /* If we let Reader decide sizes of text segments, it should be
1189          * able to optimize it better, thus low min value. This value
1190          * is only used in cases where text is at buffer boundary, or
1191          * where entity prevents using consequtive chars from input buffer:
1192          */

1193         setShortestReportedTextSegment(16);
1194         setInputBufferLength(8000); // 16k input buffer
1195     }
1196
1197     /**
1198      * Method to call to minimize the memory usage of the stream/event reader;
1199      * both regarding Objects created, and the temporary memory usage during
1200      * parsing.
1201      * This generally incurs some performance penalties, due to using
1202      * smaller input buffers.
1203      *<p>
1204      * See {@link XMLInputFactory2#configureForLowMemUsage} for
1205      * required settings for standard StAX/StAX properties.
1206      *<p>
1207      * In addition to the standard settings, following Woodstox-specific
1208      * settings are also done:
1209      *<ul>
1210      * <li>Disable <code>P_CACHE_DTDS</code>
1211      *  </li>
1212      * <li>Enable <code>P_PARSE_LAZILY</code>
1213      *  </li>
1214      * <li>Resets <code>P_MIN_TEXT_SEGMENT</code> to the (somewhat low)
1215      *   default value.
1216      *  <li>
1217      * <li>Reduces <code>P_INPUT_BUFFER_LENGTH</code> a bit from the default
1218      *  <li>
1219      *</ul>
1220      */

1221     public void configureForLowMemUsage()
1222     {
1223         // StAX (1.0)
1224         doCoalesceText(false);
1225
1226         // StAX2:
1227
1228         doPreserveLocation(false); // can reduce temporary mem usage
1229
1230         // Woodstox-specific:
1231         doCacheDTDs(false);
1232         doParseLazily(true); // can reduce temporary mem usage
1233         doXmlIdUniqChecks(false); // enabling would increase mem usage
1234         setShortestReportedTextSegment(ReaderConfig.DEFAULT_SHORTEST_TEXT_SEGMENT);
1235         setInputBufferLength(512); // 1k input buffer
1236         // Text buffer need not be huge, as we do not coalesce
1237     }
1238     
1239     /**
1240      * Method to call to make Reader try to preserve as much of input
1241      * formatting as possible, so that round-tripping would be as lossless
1242      * as possible.
1243      *<p>
1244      * See {@link XMLInputFactory2#configureForLowMemUsage} for
1245      * required settings for standard StAX/StAX properties.
1246      *<p>
1247      * In addition to the standard settings, following Woodstox-specific
1248      * settings are also done:
1249      *<ul>
1250      * <li>Increases <code>P_MIN_TEXT_SEGMENT</code> to the maximum value so
1251      *    that all original text segment chunks are reported without
1252      *    segmentation (but without coalescing with adjacent CDATA segments)
1253      *  <li>
1254      *  <li>Sets <code>P_TREAT_CHAR_REFS_AS_ENTS</code> to true, so the all the 
1255      *   original character references are reported with their position, 
1256      *   original text, and the replacement text.
1257      *   </li>
1258      *</ul>
1259      */

1260     public void configureForRoundTripping()
1261     {
1262         // StAX (1.0)
1263         doCoalesceText(false);
1264         doReplaceEntityRefs(false);
1265         
1266         // StAX2:
1267         doReportCData(true);
1268         doReportPrologWhitespace(true);
1269         
1270         // Woodstox specific settings
1271         doTreatCharRefsAsEnts(true);
1272         doNormalizeLFs(false);
1273
1274         // effectively prevents from reporting partial segments:
1275         setShortestReportedTextSegment(Integer.MAX_VALUE);
1276     }
1277
1278     /*
1279     ///////////////////////////////////////////////////////////////////////
1280     // Buffer recycling:
1281     ///////////////////////////////////////////////////////////////////////
1282      */

1283
1284     public char[] allocSmallCBuffer(int minSize)
1285     {
1286         if (mCurrRecycler != null) {
1287             char[] result = mCurrRecycler.getSmallCBuffer(minSize);
1288             if (result != null) {
1289                 return result;
1290             }
1291         }
1292         // Nope; no recycler, or it has no suitable buffers, let's create:
1293         return new char[minSize];
1294     }
1295
1296     public void freeSmallCBuffer(char[] buffer)
1297     {
1298         // Need to create (and assign) the buffer?
1299         if (mCurrRecycler == null) {
1300             mCurrRecycler = createRecycler();
1301         }
1302         mCurrRecycler.returnSmallCBuffer(buffer);
1303     }
1304
1305     public char[] allocMediumCBuffer(int minSize)
1306     {
1307         if (mCurrRecycler != null) {
1308             char[] result = mCurrRecycler.getMediumCBuffer(minSize);
1309             if (result != null) {
1310                 return result;
1311             }
1312         }
1313         return new char[minSize];
1314     }
1315
1316     public void freeMediumCBuffer(char[] buffer)
1317     {
1318         if (mCurrRecycler == null) {
1319             mCurrRecycler = createRecycler();
1320         }
1321         mCurrRecycler.returnMediumCBuffer(buffer);
1322     }
1323
1324     public char[] allocFullCBuffer(int minSize)
1325     {
1326         if (mCurrRecycler != null) {
1327             char[] result = mCurrRecycler.getFullCBuffer(minSize);
1328             if (result != null) {
1329                 return result;
1330             }
1331         }
1332         return new char[minSize];
1333     }
1334
1335     public void freeFullCBuffer(char[] buffer)
1336     {
1337         // Need to create (and assign) the buffer?
1338         if (mCurrRecycler == null) {
1339             mCurrRecycler = createRecycler();
1340         }
1341         mCurrRecycler.returnFullCBuffer(buffer);
1342     }
1343
1344     public byte[] allocFullBBuffer(int minSize)
1345     {
1346         if (mCurrRecycler != null) {
1347             byte[] result = mCurrRecycler.getFullBBuffer(minSize);
1348             if (result != null) {
1349                 return result;
1350             }
1351         }
1352         return new byte[minSize];
1353     }
1354
1355     public void freeFullBBuffer(byte[] buffer)
1356     {
1357         // Need to create (and assign) the buffer?
1358         if (mCurrRecycler == null) {
1359             mCurrRecycler = createRecycler();
1360         }
1361         mCurrRecycler.returnFullBBuffer(buffer);
1362     }
1363
1364     private BufferRecycler createRecycler()
1365     {
1366         BufferRecycler recycler = new BufferRecycler();
1367         // No way to reuse/reset SoftReference, have to create new always:
1368         mRecyclerRef.set(new SoftReference<BufferRecycler>(recycler));
1369         return recycler;
1370     }
1371
1372     /*
1373     ///////////////////////////////////////////////////////////////////////
1374     // Internal methods:
1375     ///////////////////////////////////////////////////////////////////////
1376      */

1377
1378     private void setConfigFlag(int flag, boolean state)
1379     {
1380         if (state) {
1381             mConfigFlags |= flag;
1382         } else {
1383             mConfigFlags &= ~flag;
1384         }
1385         mConfigFlagMods |= flag;
1386     }
1387
1388     @Override
1389     public Object getProperty(int id)
1390     {
1391         switch (id) {
1392             // First, standard Stax 1.0 properties:
1393
1394         case PROP_COALESCE_TEXT:
1395             return willCoalesceText() ? Boolean.TRUE : Boolean.FALSE;
1396         case PROP_NAMESPACE_AWARE:
1397             return willSupportNamespaces() ? Boolean.TRUE : Boolean.FALSE;
1398         case PROP_REPLACE_ENTITY_REFS:
1399             return willReplaceEntityRefs() ? Boolean.TRUE : Boolean.FALSE;
1400         case PROP_SUPPORT_EXTERNAL_ENTITIES:
1401             return willSupportExternalEntities() ? Boolean.TRUE : Boolean.FALSE;
1402
1403         case PROP_VALIDATE_AGAINST_DTD:
1404             return willValidateWithDTD() ? Boolean.TRUE : Boolean.FALSE;
1405         case PROP_SUPPORT_DTD:
1406             return willSupportDTDs() ? Boolean.TRUE : Boolean.FALSE;
1407         case PROP_WARNING_REPORTER:
1408             return getXMLReporter();
1409         case PROP_XML_RESOLVER:
1410             return getXMLResolver();
1411         case PROP_EVENT_ALLOCATOR:
1412             /* 25-Mar-2006, TSa: Not really supported here, so let's
1413              *   return null
1414              */

1415             return null;
1416
1417         // Then Stax2 properties:
1418
1419         case PROP_REPORT_PROLOG_WS:
1420             return willReportPrologWhitespace() ? Boolean.TRUE : Boolean.FALSE;
1421         case PROP_REPORT_CDATA:
1422             return willReportCData() ? Boolean.TRUE : Boolean.FALSE;
1423
1424         case PROP_INTERN_NAMES:
1425             return willInternNames() ? Boolean.TRUE : Boolean.FALSE;
1426         case PROP_INTERN_NS_URIS:
1427             return willInternNsURIs() ? Boolean.TRUE : Boolean.FALSE;
1428
1429         case PROP_PRESERVE_LOCATION:
1430             return willPreserveLocation() ? Boolean.TRUE : Boolean.FALSE;
1431         case PROP_AUTO_CLOSE_INPUT:
1432             return willAutoCloseInput() ? Boolean.TRUE : Boolean.FALSE;
1433
1434         case PROP_DTD_OVERRIDE:
1435             return getDTDOverride();            
1436
1437         // // // JAXP
1438
1439         case PROP_JAXP_SECURE_PROCESSING:
1440             return _hasConfigFlag(CFG_JAXP_FEATURE_SECURE_PROCESSING);
1441
1442         // // // Then Woodstox custom properties:
1443
1444         // first, flags:
1445         case PROP_CACHE_DTDS:
1446             return willCacheDTDs() ? Boolean.TRUE : Boolean.FALSE;
1447         case PROP_CACHE_DTDS_BY_PUBLIC_ID:
1448             return willCacheDTDsByPublicId() ? Boolean.TRUE : Boolean.FALSE;
1449         case PROP_LAZY_PARSING:
1450             return willParseLazily() ? Boolean.TRUE : Boolean.FALSE;
1451         case PROP_SUPPORT_XMLID:
1452             {
1453                 if (!_hasConfigFlag(CFG_XMLID_TYPING)) {
1454                     return XMLStreamProperties.XSP_V_XMLID_NONE;
1455                 }
1456                 return _hasConfigFlag(CFG_XMLID_UNIQ_CHECKS) ?
1457                     XMLStreamProperties.XSP_V_XMLID_FULL :
1458                     XMLStreamProperties.XSP_V_XMLID_TYPING;
1459             }
1460             
1461         case PROP_TREAT_CHAR_REFS_AS_ENTS:
1462             return willTreatCharRefsAsEnts() ? Boolean.TRUE : Boolean.FALSE;
1463         case PROP_ALLOW_XML11_ESCAPED_CHARS_IN_XML10:
1464             return willAllowXml11EscapedCharsInXml10() ? Boolean.TRUE : Boolean.FALSE;
1465         case PROP_NORMALIZE_LFS:
1466             return willNormalizeLFs() ? Boolean.TRUE : Boolean.FALSE;
1467
1468             // then object values:
1469         case PROP_INPUT_BUFFER_LENGTH:
1470             return getInputBufferLength();
1471         case PROP_MAX_ATTRIBUTES_PER_ELEMENT:
1472             return getMaxAttributesPerElement();
1473         case PROP_MAX_ATTRIBUTE_SIZE:
1474             return getMaxAttributeSize();
1475         case PROP_MAX_CHILDREN_PER_ELEMENT:
1476             return getMaxChildrenPerElement();
1477         case PROP_MAX_ELEMENT_DEPTH:
1478             return getMaxElementDepth();
1479         case PROP_MAX_ELEMENT_COUNT:
1480             return getMaxElementCount();
1481         case PROP_MAX_CHARACTERS:
1482             return getMaxCharacters();
1483         case PROP_MAX_TEXT_LENGTH:
1484             return getMaxTextLength();
1485         case PROP_MAX_ENTITY_DEPTH:
1486             return getMaxEntityDepth();
1487         case PROP_MAX_ENTITY_COUNT:
1488             return getMaxEntityCount();
1489
1490         case PROP_MIN_TEXT_SEGMENT:
1491             return getShortestReportedTextSegment();
1492         case PROP_CUSTOM_INTERNAL_ENTITIES:
1493             return getCustomInternalEntities();
1494         case PROP_DTD_RESOLVER:
1495             return getDtdResolver();
1496         case PROP_ENTITY_RESOLVER:
1497             return getEntityResolver();
1498         case PROP_UNDECLARED_ENTITY_RESOLVER:
1499             return getUndeclaredEntityResolver();
1500         case PROP_BASE_URL:
1501             return getBaseURL();
1502         case PROP_INPUT_PARSING_MODE:
1503             return getInputParsingMode();
1504
1505         default// sanity check, should never happen
1506             throw new IllegalStateException("Internal error: no handler for property with internal id "+id+".");
1507         }
1508     }
1509
1510     @Override
1511     public boolean setProperty(String propName, int id, Object value)
1512     {
1513         switch (id) {
1514             // First, standard (Stax 1.0) properties:
1515
1516         case PROP_COALESCE_TEXT:
1517             doCoalesceText(ArgUtil.convertToBoolean(propName, value));
1518             break;
1519
1520         case PROP_NAMESPACE_AWARE:
1521             doSupportNamespaces(ArgUtil.convertToBoolean(propName, value));
1522             break;
1523
1524         case PROP_REPLACE_ENTITY_REFS:
1525             doReplaceEntityRefs(ArgUtil.convertToBoolean(propName, value));
1526             break;
1527
1528         case PROP_SUPPORT_EXTERNAL_ENTITIES:
1529             doSupportExternalEntities(ArgUtil.convertToBoolean(propName, value));
1530             break;
1531
1532         case PROP_SUPPORT_DTD:
1533             doSupportDTDs(ArgUtil.convertToBoolean(propName, value));
1534             break;
1535             
1536         // // // Then ones that can be dispatched:
1537
1538         case PROP_VALIDATE_AGAINST_DTD:
1539             doValidateWithDTD(ArgUtil.convertToBoolean(propName, value));
1540             break;
1541
1542         case PROP_WARNING_REPORTER:
1543             setXMLReporter((XMLReporter) value);
1544             break;
1545
1546         case PROP_XML_RESOLVER:
1547             setXMLResolver((XMLResolver) value);
1548             break;
1549
1550         case PROP_EVENT_ALLOCATOR:
1551             /* 25-Mar-2006, TSa: Not really supported here, so let's
1552              *   return false to let caller deal with it
1553              */

1554             return false;
1555
1556         // // // Then Stax2 properties, flags:
1557
1558         case PROP_INTERN_NS_URIS:
1559             doInternNsURIs(ArgUtil.convertToBoolean(propName, value));
1560             break;
1561
1562         case PROP_INTERN_NAMES:
1563             doInternNames(ArgUtil.convertToBoolean(propName, value));
1564             break;
1565
1566         case PROP_REPORT_CDATA:
1567             doReportCData(ArgUtil.convertToBoolean(propName, value));
1568             break;
1569
1570         case PROP_REPORT_PROLOG_WS:
1571             doReportPrologWhitespace(ArgUtil.convertToBoolean(propName, value));
1572             break;
1573
1574         case PROP_PRESERVE_LOCATION:
1575             doPreserveLocation(ArgUtil.convertToBoolean(propName, value));
1576             break;
1577
1578         case PROP_AUTO_CLOSE_INPUT:
1579             doAutoCloseInput(ArgUtil.convertToBoolean(propName, value));
1580             break;
1581
1582         // // // Then Stax2 properties, enum/object types:
1583
1584         case PROP_SUPPORT_XMLID:
1585             {
1586                 boolean typing, uniq;
1587
1588                 if (XMLStreamProperties.XSP_V_XMLID_NONE.equals(value)) {
1589                     typing = uniq = false;
1590                 } else if (XMLStreamProperties.XSP_V_XMLID_TYPING.equals(value)) {
1591                     typing = true;
1592                     uniq = false;
1593                 } else if (XMLStreamProperties.XSP_V_XMLID_FULL.equals(value)) {
1594                     typing = uniq = true;
1595                 } else {
1596                     throw new IllegalArgumentException
1597                         ("Illegal argument ('"+value+"') to set property "
1598 +XMLStreamProperties.XSP_SUPPORT_XMLID+" to: has to be one of '"
1599 +XMLStreamProperties.XSP_V_XMLID_NONE+"', '"+XMLStreamProperties.XSP_V_XMLID_TYPING+"' or '"+XMLStreamProperties.XSP_V_XMLID_FULL+"'"
1600                          );
1601                 }
1602                 setConfigFlag(CFG_XMLID_TYPING, typing);
1603                 setConfigFlag(CFG_XMLID_UNIQ_CHECKS, uniq);
1604             }
1605             break;
1606
1607         case PROP_DTD_OVERRIDE:
1608             setDTDOverride((DTDValidationSchema) value);
1609             break;
1610
1611         // // // JAXB properties
1612
1613         case PROP_JAXP_SECURE_PROCESSING:
1614             // 13-Jul-2019, tatu: This is an alias... 
1615             doProcessSecurely(ArgUtil.convertToBoolean(propName, value));
1616             break;
1617
1618             // // // And then Woodstox specific, flags
1619
1620         case PROP_CACHE_DTDS:
1621             doCacheDTDs(ArgUtil.convertToBoolean(propName, value));
1622             break;
1623
1624         case PROP_CACHE_DTDS_BY_PUBLIC_ID:
1625             doCacheDTDsByPublicId(ArgUtil.convertToBoolean(propName, value));
1626             break;
1627
1628         case PROP_LAZY_PARSING:
1629             doParseLazily(ArgUtil.convertToBoolean(propName, value));
1630             break;
1631             
1632         case PROP_TREAT_CHAR_REFS_AS_ENTS:
1633             doTreatCharRefsAsEnts(ArgUtil.convertToBoolean(propName, value));
1634             break;
1635
1636         case PROP_ALLOW_XML11_ESCAPED_CHARS_IN_XML10:
1637             doAllowXml11EscapedCharsInXml10(ArgUtil.convertToBoolean(propName, value));
1638             break;
1639
1640         case PROP_NORMALIZE_LFS:
1641             doNormalizeLFs(ArgUtil.convertToBoolean(propName, value));
1642             break;
1643             
1644         // // // And then Woodstox specific, enum/object:
1645
1646         case PROP_INPUT_BUFFER_LENGTH:
1647             setInputBufferLength(ArgUtil.convertToInt(propName, value, 1));
1648             break;
1649             
1650         case PROP_MAX_ATTRIBUTES_PER_ELEMENT:
1651             setMaxAttributesPerElement(ArgUtil.convertToInt(propName, value, 1));
1652             break;
1653         case PROP_MAX_ATTRIBUTE_SIZE:
1654             setMaxAttributeSize(ArgUtil.convertToInt(propName, value, 1));
1655             break;
1656         case PROP_MAX_CHILDREN_PER_ELEMENT:
1657             setMaxChildrenPerElement(ArgUtil.convertToInt(propName, value, 1));
1658             break;
1659         case PROP_MAX_ELEMENT_DEPTH:
1660             setMaxElementDepth(ArgUtil.convertToInt(propName, value, 1));
1661             break;
1662         case PROP_MAX_ELEMENT_COUNT:
1663             setMaxElementCount(ArgUtil.convertToLong(propName, value, 1));
1664             break;
1665         case PROP_MAX_CHARACTERS:
1666             setMaxCharacters(ArgUtil.convertToLong(propName, value, 1));
1667             break;
1668         case PROP_MAX_TEXT_LENGTH:
1669             setMaxTextLength(ArgUtil.convertToInt(propName, value, 1));
1670             break;
1671         case PROP_MAX_ENTITY_DEPTH:
1672             setMaxEntityDepth(ArgUtil.convertToInt(propName, value, 1));
1673             break;
1674         case PROP_MAX_ENTITY_COUNT:
1675             setMaxEntityCount(ArgUtil.convertToLong(propName, value, 1));
1676             break;
1677             
1678         case PROP_MIN_TEXT_SEGMENT:
1679             setShortestReportedTextSegment(ArgUtil.convertToInt(propName, value, 1));
1680             break;
1681
1682         case PROP_CUSTOM_INTERNAL_ENTITIES:
1683             {
1684                 @SuppressWarnings("unchecked")
1685                 Map<String,?> arg = (Map<String,?>) value;
1686                 setCustomInternalEntities(arg);
1687             }
1688             break;
1689
1690         case PROP_DTD_RESOLVER:
1691             setDtdResolver((XMLResolver) value);
1692             break;
1693
1694         case PROP_ENTITY_RESOLVER:
1695             setEntityResolver((XMLResolver) value);
1696             break;
1697
1698         case PROP_UNDECLARED_ENTITY_RESOLVER:
1699             setUndeclaredEntityResolver((XMLResolver) value);
1700             break;
1701
1702         case PROP_BASE_URL:
1703             /* 17-Nov-2008, TSa: Let's make it bit more versatile; if it's not
1704              *   a URL per se, let's assume it is something that we can convert
1705              *   to URL
1706              */

1707             {
1708                 URL u;
1709                 if (value == null) {
1710                     u = null;
1711                 } else if (value instanceof URL) {
1712                     u = (URL) value;
1713                 } else {
1714                     try {
1715                         u = new URL(value.toString());
1716                     } catch (Exception ioe) { // MalformedURLException actually...
1717                         throw new IllegalArgumentException(ioe.getMessage(), ioe);
1718                     }
1719                 }
1720                 setBaseURL(u);
1721             }
1722             break;
1723
1724         case PROP_INPUT_PARSING_MODE:
1725             setInputParsingMode((WstxInputProperties.ParsingMode) value);
1726             break;
1727
1728         default// sanity check, should never happen
1729             throw new IllegalStateException("Internal error: no handler for property with internal id "+id+".");
1730         }
1731
1732         return true;
1733     }
1734
1735     protected boolean _hasConfigFlag(int flag) {
1736         return (mConfigFlags & flag) != 0;
1737     }
1738
1739     /**
1740      * Method similar to {@link #_hasConfigFlag}, but that will only
1741      * return true if in addition to being set, flag has been explicitly
1742      * modified (i.e. setProperty has been called to modify it)
1743      */

1744     protected boolean _hasExplicitConfigFlag(int flag) {
1745         return _hasConfigFlag(flag) && (mConfigFlagMods & flag) != 0;
1746     }
1747
1748     private final Object _getSpecialProperty(int ix)
1749     {
1750         if (mSpecialProperties == null) {
1751             return null;
1752         }
1753         return mSpecialProperties[ix];
1754     }
1755
1756     private final void _setSpecialProperty(int ix, Object value)
1757     {
1758         if (mSpecialProperties == null) {
1759             mSpecialProperties = new Object[SPEC_PROC_COUNT];
1760         }
1761         mSpecialProperties[ix] = value;
1762     }
1763 }
1764