blob: 2e33185aa0b7ba36f97758970b829ae6ea926693 [file] [log] [blame]
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001/* Jackson JSON-processor.
2 *
3 * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi
Tatu Salorantaf15531c2011-12-22 23:00:40 -08004 */
5package com.fasterxml.jackson.core;
6
7import java.io.*;
8import java.lang.ref.SoftReference;
9import java.net.URL;
10
11import com.fasterxml.jackson.core.format.InputAccessor;
12import com.fasterxml.jackson.core.format.MatchStrength;
13import com.fasterxml.jackson.core.io.*;
Tatu07351902012-01-19 13:12:13 -080014import com.fasterxml.jackson.core.json.*;
Cowtowncoder3a00c862015-02-04 22:30:30 -080015import com.fasterxml.jackson.core.sym.ByteQuadsCanonicalizer;
Tatu Salorantaf15531c2011-12-22 23:00:40 -080016import com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer;
17import com.fasterxml.jackson.core.util.BufferRecycler;
Tatu Salorantae6dfc692012-09-28 15:34:05 -070018import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
Tatu Salorantaf15531c2011-12-22 23:00:40 -080019
20/**
21 * The main factory class of Jackson package, used to configure and
22 * construct reader (aka parser, {@link JsonParser})
23 * and writer (aka generator, {@link JsonGenerator})
24 * instances.
25 *<p>
26 * Factory instances are thread-safe and reusable after configuration
27 * (if any). Typically applications and services use only a single
28 * globally shared factory instance, unless they need differently
29 * configured factories. Factory reuse is important if efficiency matters;
30 * most recycling of expensive construct is done on per-factory basis.
31 *<p>
32 * Creation of a factory instance is a light-weight operation,
33 * and since there is no need for pluggable alternative implementations
34 * (as there is no "standard" JSON processor API to implement),
35 * the default constructor is used for constructing factory
36 * instances.
37 *
38 * @author Tatu Saloranta
39 */
Tatu Salorantae92d04f2013-07-24 22:58:08 -070040@SuppressWarnings("resource")
Tatu Saloranta95f76a42012-10-05 13:04:23 -070041public class JsonFactory
42 implements Versioned,
43 java.io.Serializable // since 2.1 (for Android, mostly)
Tatu Salorantaf15531c2011-12-22 23:00:40 -080044{
Tatu Salorantadccffbe2015-02-05 21:17:57 -080045 private static final long serialVersionUID = 1; // since 2.6.0
Tatu Saloranta95f76a42012-10-05 13:04:23 -070046
Tatu Saloranta7b796a82013-04-27 10:18:30 -070047 /*
48 /**********************************************************
49 /* Helper types
50 /**********************************************************
Tatu Salorantaf15531c2011-12-22 23:00:40 -080051 */
Tatu Salorantae92d04f2013-07-24 22:58:08 -070052
Tatu07351902012-01-19 13:12:13 -080053 /**
54 * Enumeration that defines all on/off features that can only be
55 * changed for {@link JsonFactory}.
56 */
57 public enum Feature {
58
59 // // // Symbol handling (interning etc)
60
61 /**
62 * Feature that determines whether JSON object field names are
63 * to be canonicalized using {@link String#intern} or not:
64 * if enabled, all field names will be intern()ed (and caller
65 * can count on this being true for all such names); if disabled,
66 * no intern()ing is done. There may still be basic
67 * canonicalization (that is, same String will be used to represent
68 * all identical object property names for a single document).
69 *<p>
70 * Note: this setting only has effect if
71 * {@link #CANONICALIZE_FIELD_NAMES} is true -- otherwise no
72 * canonicalization of any sort is done.
73 *<p>
74 * This setting is enabled by default.
75 */
76 INTERN_FIELD_NAMES(true),
77
78 /**
79 * Feature that determines whether JSON object field names are
80 * to be canonicalized (details of how canonicalization is done
81 * then further specified by
82 * {@link #INTERN_FIELD_NAMES}).
83 *<p>
84 * This setting is enabled by default.
85 */
Tatu Saloranta383bc8f2014-05-24 00:47:07 -070086 CANONICALIZE_FIELD_NAMES(true),
87
88 /**
89 * Feature that determines what happens if we encounter a case in symbol
90 * handling where number of hash collisions exceeds a safety threshold
91 * -- which almost certainly means a denial-of-service attack via generated
92 * duplicate hash codes.
93 * If feature is enabled, an {@link IllegalStateException} is
94 * thrown to indicate the suspected denial-of-service attack; if disabled, processing continues but
95 * canonicalization (and thereby <code>intern()</code>ing) is disabled) as protective
96 * measure.
97 *<p>
98 * This setting is enabled by default.
99 *
100 * @since 2.4
101 */
102 FAIL_ON_SYMBOL_HASH_OVERFLOW(true),
Tatu07351902012-01-19 13:12:13 -0800103
Tatu Saloranta8891c0c2015-04-23 22:47:05 -0700104 /**
105 * Feature that determines whether we will use {@link BufferRecycler} with
106 * {@link ThreadLocal} and {@link SoftReference}, for efficient reuse of
107 * underlying input/output buffers.
108 * This usually makes sense on normal J2SE/J2EE server-side processing;
109 * but may not make sense on platforms where {@link SoftReference} handling
110 * is broken (like Android), or if there are retention issues due to
111 * {@link ThreadLocal} (see
112 * <a href="https://github.com/FasterXML/jackson-core/issues/189">Issue #189</a>
113 * for a possible case)
David Andrewseb41b102016-12-01 20:51:32 -0500114 *<p>
115 * This setting is enabled by default.
Tatu Saloranta8891c0c2015-04-23 22:47:05 -0700116 *
117 * @since 2.6
118 */
119 USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING(true)
Tatu Salorantaf4255632017-04-17 22:03:51 -0700120
Tatu07351902012-01-19 13:12:13 -0800121 ;
122
123 /**
124 * Whether feature is enabled or disabled by default.
125 */
126 private final boolean _defaultState;
Tatu Salorantaf4255632017-04-17 22:03:51 -0700127
Tatu07351902012-01-19 13:12:13 -0800128 /**
129 * Method that calculates bit set (flags) of all features that
130 * are enabled by default.
131 */
Tatu Salorantae15b9a82014-01-24 21:01:04 -0800132 public static int collectDefaults() {
Tatu07351902012-01-19 13:12:13 -0800133 int flags = 0;
134 for (Feature f : values()) {
Tatu Salorantae15b9a82014-01-24 21:01:04 -0800135 if (f.enabledByDefault()) { flags |= f.getMask(); }
Tatu07351902012-01-19 13:12:13 -0800136 }
137 return flags;
138 }
139
Tatu Salorantae15b9a82014-01-24 21:01:04 -0800140 private Feature(boolean defaultState) { _defaultState = defaultState; }
Tatu07351902012-01-19 13:12:13 -0800141
142 public boolean enabledByDefault() { return _defaultState; }
Tatu07351902012-01-19 13:12:13 -0800143 public boolean enabledIn(int flags) { return (flags & getMask()) != 0; }
Tatu07351902012-01-19 13:12:13 -0800144 public int getMask() { return (1 << ordinal()); }
Tatu Saloranta7b796a82013-04-27 10:18:30 -0700145 }
146
147 /*
148 /**********************************************************
149 /* Constants
150 /**********************************************************
151 */
152
153 /**
154 * Name used to identify JSON format
155 * (and returned by {@link #getFormatName()}
156 */
157 public final static String FORMAT_NAME_JSON = "JSON";
158
159 /**
160 * Bitfield (set of flags) of all factory features that are enabled by default.
161 */
162 protected final static int DEFAULT_FACTORY_FEATURE_FLAGS = JsonFactory.Feature.collectDefaults();
163
164 /**
165 * Bitfield (set of flags) of all parser features that are enabled
166 * by default.
167 */
168 protected final static int DEFAULT_PARSER_FEATURE_FLAGS = JsonParser.Feature.collectDefaults();
169
170 /**
171 * Bitfield (set of flags) of all generator features that are enabled
172 * by default.
173 */
174 protected final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults();
175
176 private final static SerializableString DEFAULT_ROOT_VALUE_SEPARATOR = DefaultPrettyPrinter.DEFAULT_ROOT_VALUE_SEPARATOR;
177
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800178 /*
179 /**********************************************************
180 /* Buffer, symbol table management
181 /**********************************************************
182 */
183
184 /**
Tatu Saloranta10c3ec82012-09-05 19:38:49 -0700185 * This <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftReference}
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800186 * to a {@link BufferRecycler} used to provide a low-cost
187 * buffer recycling between reader and writer instances.
188 */
189 final protected static ThreadLocal<SoftReference<BufferRecycler>> _recyclerRef
190 = new ThreadLocal<SoftReference<BufferRecycler>>();
191
192 /**
193 * Each factory comes equipped with a shared root symbol table.
194 * It should not be linked back to the original blueprint, to
195 * avoid contents from leaking between factories.
196 */
Tatu Saloranta95f76a42012-10-05 13:04:23 -0700197 protected final transient CharsToNameCanonicalizer _rootCharSymbols = CharsToNameCanonicalizer.createRoot();
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800198
199 /**
200 * Alternative to the basic symbol table, some stream-based
201 * parsers use different name canonicalization method.
202 *<p>
203 * TODO: should clean up this; looks messy having 2 alternatives
204 * with not very clear differences.
Tatu Salorantadccffbe2015-02-05 21:17:57 -0800205 *
206 * @since 2.6.0
207 */
208 protected final transient ByteQuadsCanonicalizer _byteSymbolCanonicalizer = ByteQuadsCanonicalizer.createRoot();
209
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800210 /*
211 /**********************************************************
212 /* Configuration
213 /**********************************************************
214 */
215
216 /**
217 * Object that implements conversion functionality between
218 * Java objects and JSON content. For base JsonFactory implementation
219 * usually not set by default, but can be explicitly set.
220 * Sub-classes (like @link org.codehaus.jackson.map.MappingJsonFactory}
221 * usually provide an implementation.
222 */
223 protected ObjectCodec _objectCodec;
224
225 /**
Tatu07351902012-01-19 13:12:13 -0800226 * Currently enabled factory features.
227 */
228 protected int _factoryFeatures = DEFAULT_FACTORY_FEATURE_FLAGS;
229
230 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800231 * Currently enabled parser features.
232 */
233 protected int _parserFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
234
235 /**
236 * Currently enabled generator features.
237 */
238 protected int _generatorFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
239
240 /**
241 * Definition of custom character escapes to use for generators created
242 * by this factory, if any. If null, standard data format specific
243 * escapes are used.
244 */
245 protected CharacterEscapes _characterEscapes;
246
247 /**
248 * Optional helper object that may decorate input sources, to do
249 * additional processing on input during parsing.
250 */
251 protected InputDecorator _inputDecorator;
252
253 /**
254 * Optional helper object that may decorate output object, to do
255 * additional processing on output during content generation.
256 */
257 protected OutputDecorator _outputDecorator;
Tatu Salorantae6dfc692012-09-28 15:34:05 -0700258
259 /**
260 * Separator used between root-level values, if any; null indicates
261 * "do not add separator".
262 * Default separator is a single space character.
263 *
264 * @since 2.1
265 */
266 protected SerializableString _rootValueSeparator = DEFAULT_ROOT_VALUE_SEPARATOR;
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800267
268 /*
269 /**********************************************************
270 /* Construction
271 /**********************************************************
272 */
273
274 /**
275 * Default constructor used to create factory instances.
276 * Creation of a factory instance is a light-weight operation,
277 * but it is still a good idea to reuse limited number of
278 * factory instances (and quite often just a single instance):
279 * factories are used as context for storing some reused
280 * processing objects (such as symbol tables parsers use)
281 * and this reuse only works within context of a single
282 * factory instance.
283 */
Gonçalo Silva2bba5dd2014-01-25 17:06:21 +0000284 public JsonFactory() { this(null); }
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800285
286 public JsonFactory(ObjectCodec oc) { _objectCodec = oc; }
287
Tatu Saloranta378ecdc2012-08-04 16:27:27 -0700288 /**
Tatu Saloranta7b796a82013-04-27 10:18:30 -0700289 * Constructor used when copy()ing a factory instance.
290 *
291 * @since 2.2.1
292 */
293 protected JsonFactory(JsonFactory src, ObjectCodec codec)
294 {
295 _objectCodec = null;
296 _factoryFeatures = src._factoryFeatures;
297 _parserFeatures = src._parserFeatures;
298 _generatorFeatures = src._generatorFeatures;
299 _characterEscapes = src._characterEscapes;
300 _inputDecorator = src._inputDecorator;
301 _outputDecorator = src._outputDecorator;
302 _rootValueSeparator = src._rootValueSeparator;
303
304 /* 27-Apr-2013, tatu: How about symbol table; should we try to
305 * reuse shared symbol tables? Could be more efficient that way;
306 * although can slightly add to concurrency overhead.
307 */
308 }
309
310 /**
Tatu Saloranta378ecdc2012-08-04 16:27:27 -0700311 * Method for constructing a new {@link JsonFactory} that has
312 * the same settings as this instance, but is otherwise
313 * independent (i.e. nothing is actually shared, symbol tables
314 * are separate).
315 * Note that {@link ObjectCodec} reference is not copied but is
316 * set to null; caller typically needs to set it after calling
Tatu Saloranta7b796a82013-04-27 10:18:30 -0700317 * this method. Reason for this is that the codec is used for
318 * callbacks, and assumption is that there is strict 1-to-1
319 * mapping between codec, factory. Caller has to, then, explicitly
320 * set codec after making the copy.
Tatu Saloranta378ecdc2012-08-04 16:27:27 -0700321 *
322 * @since 2.1
323 */
324 public JsonFactory copy()
325 {
326 _checkInvalidCopy(JsonFactory.class);
Tatu Saloranta7b796a82013-04-27 10:18:30 -0700327 // as per above, do clear ObjectCodec
328 return new JsonFactory(this, null);
Tatu Saloranta378ecdc2012-08-04 16:27:27 -0700329 }
Tatu Saloranta7b796a82013-04-27 10:18:30 -0700330
Tatu Saloranta378ecdc2012-08-04 16:27:27 -0700331 /**
332 * @since 2.1
333 * @param exp
334 */
335 protected void _checkInvalidCopy(Class<?> exp)
336 {
337 if (getClass() != exp) {
338 throw new IllegalStateException("Failed copy(): "+getClass().getName()
339 +" (version: "+version()+") does not override copy(); it has to");
340 }
341 }
Tatu Saloranta95f76a42012-10-05 13:04:23 -0700342
343 /*
344 /**********************************************************
345 /* Serializable overrides
346 /**********************************************************
347 */
348
349 /**
350 * Method that we need to override to actually make restoration go
351 * through constructors etc.
352 * Also: must be overridden by sub-classes as well.
353 */
354 protected Object readResolve() {
Tatu Salorantaf7741c52013-04-27 11:06:30 -0700355 return new JsonFactory(this, _objectCodec);
Tatu Saloranta95f76a42012-10-05 13:04:23 -0700356 }
Tatu Salorantaa9e5c9f2013-08-28 19:39:59 -0700357
358 /*
359 /**********************************************************
360 /* Capability introspection
361 /**********************************************************
362 */
363
364 /**
365 * Introspection method that higher-level functionality may call
366 * to see whether underlying data format requires a stable ordering
367 * of object properties or not.
368 * This is usually used for determining
369 * whether to force a stable ordering (like alphabetic ordering by name)
370 * if no ordering if explicitly specified.
371 *<p>
372 * Default implementation returns <code>false</code> as JSON does NOT
373 * require stable ordering. Formats that require ordering include positional
374 * textual formats like <code>CSV</code>, and schema-based binary formats
375 * like <code>Avro</code>.
376 *
377 * @since 2.3
378 */
Tatu475a99b2014-04-22 14:32:50 -0700379 public boolean requiresPropertyOrdering() { return false; }
Tatu Salorantab8835442013-09-14 12:12:57 -0700380
381 /**
382 * Introspection method that higher-level functionality may call
383 * to see whether underlying data format can read and write binary
384 * data natively; that is, embeded it as-is without using encodings
385 * such as Base64.
386 *<p>
387 * Default implementation returns <code>false</code> as JSON does not
388 * support native access: all binary content must use Base64 encoding.
389 * Most binary formats (like Smile and Avro) support native binary content.
390 *
391 * @since 2.3
392 */
Tatu475a99b2014-04-22 14:32:50 -0700393 public boolean canHandleBinaryNatively() { return false; }
Tatu Salorantab8835442013-09-14 12:12:57 -0700394
Tatu475a99b2014-04-22 14:32:50 -0700395 /**
396 * Introspection method that can be used by base factory to check
397 * whether access using <code>char[]</code> is something that actual
398 * parser implementations can take advantage of, over having to
399 * use {@link java.io.Reader}. Sub-types are expected to override
400 * definition; default implementation (suitable for JSON) alleges
401 * that optimization are possible; and thereby is likely to try
402 * to access {@link java.lang.String} content by first copying it into
403 * recyclable intermediate buffer.
404 *
405 * @since 2.4
406 */
407 public boolean canUseCharArrays() { return true; }
Cowtowncoder2e262b92015-05-27 17:32:17 -0700408
409 /**
410 * Method for accessing kind of {@link FormatFeature} that a parser
411 * {@link JsonParser} produced by this factory would accept, if any;
412 * <code>null</code> returned if none.
413 *
414 * @since 2.6
415 */
416 public Class<? extends FormatFeature> getFormatReadFeatureType() {
417 return null;
418 }
419
420 /**
421 * Method for accessing kind of {@link FormatFeature} that a parser
422 * {@link JsonGenerator} produced by this factory would accept, if any;
423 * <code>null</code> returned if none.
424 *
425 * @since 2.6
426 */
427 public Class<? extends FormatFeature> getFormatWriteFeatureType() {
428 return null;
429 }
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800430 /*
431 /**********************************************************
Cowtowncoder2e262b92015-05-27 17:32:17 -0700432 /* Format detection functionality
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800433 /**********************************************************
434 */
435
436 /**
Tatu Saloranta1bdf0262012-08-24 14:43:17 -0700437 * Method that can be used to quickly check whether given schema
438 * is something that parsers and/or generators constructed by this
439 * factory could use. Note that this means possible use, at the level
440 * of data format (i.e. schema is for same data format as parsers and
441 * generators this factory constructs); individual schema instances
442 * may have further usage restrictions.
443 *
444 * @since 2.1
445 */
446 public boolean canUseSchema(FormatSchema schema) {
Tatu Saloranta244ddd12016-05-14 15:11:04 -0700447 if (schema == null){
448 return false;
449 }
Tatu Saloranta1bdf0262012-08-24 14:43:17 -0700450 String ourFormat = getFormatName();
451 return (ourFormat != null) && ourFormat.equals(schema.getSchemaType());
452 }
453
454 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800455 * Method that returns short textual id identifying format
456 * this factory supports.
457 *<p>
458 * Note: sub-classes should override this method; default
459 * implementation will return null for all sub-classes
460 */
461 public String getFormatName()
462 {
463 /* Somewhat nasty check: since we can't make this abstract
464 * (due to backwards compatibility concerns), need to prevent
465 * format name "leakage"
466 */
467 if (getClass() == JsonFactory.class) {
468 return FORMAT_NAME_JSON;
469 }
470 return null;
471 }
472
Cowtowncoder2e262b92015-05-27 17:32:17 -0700473 /**
474 * Convenience method for trying to determine whether input via given accessor
475 * is of format type supported by this factory.
476 */
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800477 public MatchStrength hasFormat(InputAccessor acc) throws IOException
478 {
479 // since we can't keep this abstract, only implement for "vanilla" instance
480 if (getClass() == JsonFactory.class) {
481 return hasJSONFormat(acc);
482 }
483 return null;
484 }
485
Tatu Salorantaad2df5f2012-08-22 20:55:49 -0700486 /**
487 * Method that can be called to determine if a custom
488 * {@link ObjectCodec} is needed for binding data parsed
489 * using {@link JsonParser} constructed by this factory
490 * (which typically also implies the same for serialization
491 * with {@link JsonGenerator}).
492 *
493 * @return True if custom codec is needed with parsers and
494 * generators created by this factory; false if a general
495 * {@link ObjectCodec} is enough
496 *
497 * @since 2.1
498 */
499 public boolean requiresCustomCodec() {
500 return false;
501 }
502
503 /**
504 * Helper method that can be called to determine if content accessed
505 * using given accessor seems to be JSON content.
506 */
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800507 protected MatchStrength hasJSONFormat(InputAccessor acc) throws IOException
508 {
509 return ByteSourceJsonBootstrapper.hasJSONFormat(acc);
Tatu Salorantaad2df5f2012-08-22 20:55:49 -0700510 }
511
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800512 /*
513 /**********************************************************
514 /* Versioned
515 /**********************************************************
516 */
517
Tatu Saloranta68d79dd2013-01-10 21:13:46 -0800518 @Override
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800519 public Version version() {
Tatu Saloranta68d79dd2013-01-10 21:13:46 -0800520 return PackageVersion.VERSION;
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800521 }
522
523 /*
524 /**********************************************************
Tatu07351902012-01-19 13:12:13 -0800525 /* Configuration, factory features
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800526 /**********************************************************
527 */
528
529 /**
530 * Method for enabling or disabling specified parser feature
531 * (check {@link JsonParser.Feature} for list of features)
532 */
Tatu07351902012-01-19 13:12:13 -0800533 public final JsonFactory configure(JsonFactory.Feature f, boolean state) {
534 return state ? enable(f) : disable(f);
535 }
536
537 /**
538 * Method for enabling specified parser feature
539 * (check {@link JsonFactory.Feature} for list of features)
540 */
541 public JsonFactory enable(JsonFactory.Feature f) {
542 _factoryFeatures |= f.getMask();
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800543 return this;
544 }
545
546 /**
Tatu07351902012-01-19 13:12:13 -0800547 * Method for disabling specified parser features
548 * (check {@link JsonFactory.Feature} for list of features)
549 */
550 public JsonFactory disable(JsonFactory.Feature f) {
551 _factoryFeatures &= ~f.getMask();
552 return this;
553 }
554
555 /**
556 * Checked whether specified parser feature is enabled.
557 */
558 public final boolean isEnabled(JsonFactory.Feature f) {
559 return (_factoryFeatures & f.getMask()) != 0;
560 }
561
562 /*
563 /**********************************************************
564 /* Configuration, parser configuration
565 /**********************************************************
566 */
567
568 /**
569 * Method for enabling or disabling specified parser feature
570 * (check {@link JsonParser.Feature} for list of features)
571 */
572 public final JsonFactory configure(JsonParser.Feature f, boolean state) {
573 return state ? enable(f) : disable(f);
574 }
575
576 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800577 * Method for enabling specified parser feature
578 * (check {@link JsonParser.Feature} for list of features)
579 */
580 public JsonFactory enable(JsonParser.Feature f) {
581 _parserFeatures |= f.getMask();
582 return this;
583 }
584
585 /**
586 * Method for disabling specified parser features
587 * (check {@link JsonParser.Feature} for list of features)
588 */
589 public JsonFactory disable(JsonParser.Feature f) {
590 _parserFeatures &= ~f.getMask();
591 return this;
592 }
593
594 /**
595 * Checked whether specified parser feature is enabled.
596 */
597 public final boolean isEnabled(JsonParser.Feature f) {
598 return (_parserFeatures & f.getMask()) != 0;
599 }
600
601 /**
602 * Method for getting currently configured input decorator (if any;
603 * there is no default decorator).
604 */
605 public InputDecorator getInputDecorator() {
606 return _inputDecorator;
607 }
608
609 /**
610 * Method for overriding currently configured input decorator
611 */
612 public JsonFactory setInputDecorator(InputDecorator d) {
613 _inputDecorator = d;
614 return this;
615 }
616
617 /*
618 /**********************************************************
619 /* Configuration, generator settings
620 /**********************************************************
621 */
622
623 /**
624 * Method for enabling or disabling specified generator feature
625 * (check {@link JsonGenerator.Feature} for list of features)
626 */
627 public final JsonFactory configure(JsonGenerator.Feature f, boolean state) {
Tatu07351902012-01-19 13:12:13 -0800628 return state ? enable(f) : disable(f);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800629 }
630
631
632 /**
633 * Method for enabling specified generator features
634 * (check {@link JsonGenerator.Feature} for list of features)
635 */
636 public JsonFactory enable(JsonGenerator.Feature f) {
637 _generatorFeatures |= f.getMask();
638 return this;
639 }
640
641 /**
642 * Method for disabling specified generator feature
643 * (check {@link JsonGenerator.Feature} for list of features)
644 */
645 public JsonFactory disable(JsonGenerator.Feature f) {
646 _generatorFeatures &= ~f.getMask();
647 return this;
648 }
649
650 /**
651 * Check whether specified generator feature is enabled.
652 */
653 public final boolean isEnabled(JsonGenerator.Feature f) {
654 return (_generatorFeatures & f.getMask()) != 0;
655 }
656
657 /**
658 * Method for accessing custom escapes factory uses for {@link JsonGenerator}s
659 * it creates.
660 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800661 public CharacterEscapes getCharacterEscapes() { return _characterEscapes; }
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800662
663 /**
664 * Method for defining custom escapes factory uses for {@link JsonGenerator}s
665 * it creates.
666 */
667 public JsonFactory setCharacterEscapes(CharacterEscapes esc) {
668 _characterEscapes = esc;
669 return this;
670 }
671
672 /**
673 * Method for getting currently configured output decorator (if any;
674 * there is no default decorator).
675 */
676 public OutputDecorator getOutputDecorator() {
677 return _outputDecorator;
678 }
679
680 /**
681 * Method for overriding currently configured output decorator
682 */
683 public JsonFactory setOutputDecorator(OutputDecorator d) {
684 _outputDecorator = d;
685 return this;
686 }
Tatu Salorantae6dfc692012-09-28 15:34:05 -0700687
688 /**
689 * Method that allows overriding String used for separating root-level
690 * JSON values (default is single space character)
691 *
692 * @param sep Separator to use, if any; null means that no separator is
693 * automatically added
694 *
695 * @since 2.1
696 */
697 public JsonFactory setRootValueSeparator(String sep) {
698 _rootValueSeparator = (sep == null) ? null : new SerializedString(sep);
699 return this;
700 }
701
702 /**
703 * @since 2.1
704 */
705 public String getRootValueSeparator() {
706 return (_rootValueSeparator == null) ? null : _rootValueSeparator.getValue();
707 }
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800708
709 /*
710 /**********************************************************
711 /* Configuration, other
712 /**********************************************************
713 */
714
715 /**
716 * Method for associating a {@link ObjectCodec} (typically
Tatu Salorantad77350e2011-12-22 23:13:13 -0800717 * a <code>com.fasterxml.jackson.databind.ObjectMapper</code>)
718 * with this factory (and more importantly, parsers and generators
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800719 * it constructs). This is needed to use data-binding methods
720 * of {@link JsonParser} and {@link JsonGenerator} instances.
721 */
722 public JsonFactory setCodec(ObjectCodec oc) {
723 _objectCodec = oc;
724 return this;
725 }
726
727 public ObjectCodec getCodec() { return _objectCodec; }
728
729 /*
730 /**********************************************************
Tatu Salorantafeaabd12012-07-22 23:03:41 -0700731 /* Parser factories (new ones, as per [Issue-25])
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800732 /**********************************************************
733 */
734
735 /**
736 * Method for constructing JSON parser instance to parse
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300737 * contents of specified file.
738 *
739 *<p>
740 * Encoding is auto-detected from contents according to JSON
741 * specification recommended mechanism. Json specification
742 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
743 * so auto-detection implemented only for this charsets.
744 * For other charsets use {@link #createParser(java.io.Reader)}.
745 *
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800746 *<p>
747 * Underlying input stream (needed for reading contents)
748 * will be <b>owned</b> (and managed, i.e. closed as need be) by
749 * the parser, since caller has no access to it.
750 *
751 * @param f File that contains JSON content to parse
Tatu Salorantafeaabd12012-07-22 23:03:41 -0700752 *
753 * @since 2.1
754 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800755 public JsonParser createParser(File f) throws IOException, JsonParseException {
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800756 // true, since we create InputStream from File
757 IOContext ctxt = _createContext(f, true);
758 InputStream in = new FileInputStream(f);
Tatu Saloranta896000f2014-04-19 12:53:40 -0700759 return _createParser(_decorate(in, ctxt), ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800760 }
761
762 /**
763 * Method for constructing JSON parser instance to parse
764 * contents of resource reference by given URL.
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300765 *
766 *<p>
767 * Encoding is auto-detected from contents according to JSON
768 * specification recommended mechanism. Json specification
769 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
770 * so auto-detection implemented only for this charsets.
771 * For other charsets use {@link #createParser(java.io.Reader)}.
772 *
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800773 *<p>
774 * Underlying input stream (needed for reading contents)
775 * will be <b>owned</b> (and managed, i.e. closed as need be) by
776 * the parser, since caller has no access to it.
777 *
778 * @param url URL pointing to resource that contains JSON content to parse
Tatu Saloranta68194922012-11-15 20:34:29 -0800779 *
780 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800781 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800782 public JsonParser createParser(URL url) throws IOException, JsonParseException {
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800783 // true, since we create InputStream from URL
784 IOContext ctxt = _createContext(url, true);
785 InputStream in = _optimizedStreamFromURL(url);
Tatu Saloranta896000f2014-04-19 12:53:40 -0700786 return _createParser(_decorate(in, ctxt), ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800787 }
788
789 /**
790 * Method for constructing JSON parser instance to parse
791 * the contents accessed via specified input stream.
792 *<p>
793 * The input stream will <b>not be owned</b> by
794 * the parser, it will still be managed (i.e. closed if
795 * end-of-stream is reacher, or parser close method called)
796 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
797 * is enabled.
798 *<p>
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300799 *
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800800 * Note: no encoding argument is taken since it can always be
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300801 * auto-detected as suggested by JSON RFC. Json specification
802 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
803 * so auto-detection implemented only for this charsets.
804 * For other charsets use {@link #createParser(java.io.Reader)}.
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800805 *
806 * @param in InputStream to use for reading JSON content to parse
Tatu Saloranta68194922012-11-15 20:34:29 -0800807 *
808 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800809 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800810 public JsonParser createParser(InputStream in) throws IOException, JsonParseException {
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800811 IOContext ctxt = _createContext(in, false);
Tatu Saloranta896000f2014-04-19 12:53:40 -0700812 return _createParser(_decorate(in, ctxt), ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800813 }
Tatu Saloranta896000f2014-04-19 12:53:40 -0700814
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800815 /**
816 * Method for constructing parser for parsing
817 * the contents accessed via specified Reader.
818 <p>
819 * The read stream will <b>not be owned</b> by
820 * the parser, it will still be managed (i.e. closed if
821 * end-of-stream is reacher, or parser close method called)
822 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
823 * is enabled.
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800824 *
825 * @param r Reader to use for reading JSON content to parse
Tatu Saloranta68194922012-11-15 20:34:29 -0800826 *
827 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800828 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800829 public JsonParser createParser(Reader r) throws IOException, JsonParseException {
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800830 // false -> we do NOT own Reader (did not create it)
831 IOContext ctxt = _createContext(r, false);
Tatu Saloranta896000f2014-04-19 12:53:40 -0700832 return _createParser(_decorate(r, ctxt), ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800833 }
834
835 /**
836 * Method for constructing parser for parsing
837 * the contents of given byte array.
Tatu Saloranta68194922012-11-15 20:34:29 -0800838 *
839 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800840 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800841 public JsonParser createParser(byte[] data) throws IOException, JsonParseException {
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800842 IOContext ctxt = _createContext(data, true);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800843 if (_inputDecorator != null) {
844 InputStream in = _inputDecorator.decorate(ctxt, data, 0, data.length);
845 if (in != null) {
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -0700846 return _createParser(in, ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800847 }
848 }
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -0700849 return _createParser(data, 0, data.length, ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800850 }
851
852 /**
853 * Method for constructing parser for parsing
854 * the contents of given byte array.
855 *
856 * @param data Buffer that contains data to parse
857 * @param offset Offset of the first data byte within buffer
858 * @param len Length of contents to parse within buffer
Tatu Saloranta68194922012-11-15 20:34:29 -0800859 *
860 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800861 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800862 public JsonParser createParser(byte[] data, int offset, int len) throws IOException, JsonParseException {
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800863 IOContext ctxt = _createContext(data, true);
864 // [JACKSON-512]: allow wrapping with InputDecorator
865 if (_inputDecorator != null) {
866 InputStream in = _inputDecorator.decorate(ctxt, data, offset, len);
867 if (in != null) {
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -0700868 return _createParser(in, ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800869 }
870 }
Tatu Saloranta68194922012-11-15 20:34:29 -0800871 return _createParser(data, offset, len, ctxt);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800872 }
873
874 /**
875 * Method for constructing parser for parsing
876 * contents of given String.
Tatu Saloranta68194922012-11-15 20:34:29 -0800877 *
878 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800879 */
Tatu Saloranta32e4e912014-01-26 19:59:28 -0800880 public JsonParser createParser(String content) throws IOException, JsonParseException {
Tatu64aa9d22014-04-18 14:07:38 -0700881 final int strLen = content.length();
882 // Actually, let's use this for medium-sized content, up to 64kB chunk (32kb char)
Tatu Salorantad7cbb642016-05-13 13:23:04 -0700883 if ((_inputDecorator != null) || (strLen > 0x8000) || !canUseCharArrays()) {
Tatu64aa9d22014-04-18 14:07:38 -0700884 // easier to just wrap in a Reader than extend InputDecorator; or, if content
885 // is too long for us to copy it over
886 return createParser(new StringReader(content));
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800887 }
Tatu64aa9d22014-04-18 14:07:38 -0700888 IOContext ctxt = _createContext(content, true);
Tatu Saloranta84dc1842014-04-18 21:07:57 -0700889 char[] buf = ctxt.allocTokenBuffer(strLen);
Tatu64aa9d22014-04-18 14:07:38 -0700890 content.getChars(0, strLen, buf, 0);
891 return _createParser(buf, 0, strLen, ctxt, true);
892 }
893
894 /**
895 * Method for constructing parser for parsing
896 * contents of given char array.
897 *
898 * @since 2.4
899 */
900 public JsonParser createParser(char[] content) throws IOException {
901 return createParser(content, 0, content.length);
902 }
903
904 /**
Tatu Saloranta896000f2014-04-19 12:53:40 -0700905 * Method for constructing parser for parsing contents of given char array.
Tatu64aa9d22014-04-18 14:07:38 -0700906 *
907 * @since 2.4
908 */
909 public JsonParser createParser(char[] content, int offset, int len) throws IOException {
910 if (_inputDecorator != null) { // easier to just wrap in a Reader than extend InputDecorator
911 return createParser(new CharArrayReader(content, offset, len));
912 }
Tatu Saloranta896000f2014-04-19 12:53:40 -0700913 return _createParser(content, offset, len, _createContext(content, true),
914 // important: buffer is NOT recyclable, as it's from caller
915 false);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800916 }
917
Tatu Salorantad7cbb642016-05-13 13:23:04 -0700918 /**
919 * @since 2.8
920 */
921 public JsonParser createParser(DataInput in) throws IOException {
922 IOContext ctxt = _createContext(in, false);
923 return _createParser(_decorate(in, ctxt), ctxt);
924 }
925
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800926 /*
927 /**********************************************************
Tatu Salorantad302ae02015-12-27 21:53:15 -0800928 /* Parser factories (old ones, pre-2.2)
Tatu Saloranta68194922012-11-15 20:34:29 -0800929 /**********************************************************
930 */
931
932 /**
933 * Method for constructing JSON parser instance to parse
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300934 * contents of specified file.
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300935 *<p>
936 * Encoding is auto-detected from contents according to JSON
937 * specification recommended mechanism. Json specification
938 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
939 * so auto-detection implemented only for this charsets.
940 * For other charsets use {@link #createParser(java.io.Reader)}.
941 *
Tatu Saloranta68194922012-11-15 20:34:29 -0800942 *<p>
943 * Underlying input stream (needed for reading contents)
944 * will be <b>owned</b> (and managed, i.e. closed as need be) by
945 * the parser, since caller has no access to it.
Tatu Saloranta68194922012-11-15 20:34:29 -0800946 *
947 * @param f File that contains JSON content to parse
948 *
949 * @deprecated Since 2.2, use {@link #createParser(File)} instead.
950 */
951 @Deprecated
Tatu Salorantaefc23672013-12-30 19:09:39 -0800952 public JsonParser createJsonParser(File f) throws IOException, JsonParseException {
Tatu Saloranta68194922012-11-15 20:34:29 -0800953 return createParser(f);
954 }
955
956 /**
957 * Method for constructing JSON parser instance to parse
958 * contents of resource reference by given URL.
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300959 *
960 *<p>
961 * Encoding is auto-detected from contents according to JSON
962 * specification recommended mechanism. Json specification
963 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
964 * so auto-detection implemented only for this charsets.
965 * For other charsets use {@link #createParser(java.io.Reader)}.
966 *
Tatu Saloranta68194922012-11-15 20:34:29 -0800967 *<p>
968 * Underlying input stream (needed for reading contents)
969 * will be <b>owned</b> (and managed, i.e. closed as need be) by
970 * the parser, since caller has no access to it.
Tatu Saloranta68194922012-11-15 20:34:29 -0800971 *
972 * @param url URL pointing to resource that contains JSON content to parse
973 *
974 * @deprecated Since 2.2, use {@link #createParser(URL)} instead.
975 */
976 @Deprecated
Tatu Salorantaefc23672013-12-30 19:09:39 -0800977 public JsonParser createJsonParser(URL url) throws IOException, JsonParseException {
Tatu Saloranta68194922012-11-15 20:34:29 -0800978 return createParser(url);
979 }
980
981 /**
982 * Method for constructing JSON parser instance to parse
983 * the contents accessed via specified input stream.
984 *<p>
985 * The input stream will <b>not be owned</b> by
986 * the parser, it will still be managed (i.e. closed if
987 * end-of-stream is reacher, or parser close method called)
988 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
989 * is enabled.
990 *<p>
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300991 *
Tatu Saloranta68194922012-11-15 20:34:29 -0800992 * Note: no encoding argument is taken since it can always be
Dmitry Spikhalskiy5590fcf2015-11-29 20:27:14 +0300993 * auto-detected as suggested by JSON RFC. Json specification
994 * supports only UTF-8, UTF-16 and UTF-32 as valid encodings,
995 * so auto-detection implemented only for this charsets.
996 * For other charsets use {@link #createParser(java.io.Reader)}.
Tatu Saloranta68194922012-11-15 20:34:29 -0800997 *
998 * @param in InputStream to use for reading JSON content to parse
999 *
1000 * @deprecated Since 2.2, use {@link #createParser(InputStream)} instead.
1001 */
1002 @Deprecated
Tatu Salorantaefc23672013-12-30 19:09:39 -08001003 public JsonParser createJsonParser(InputStream in) throws IOException, JsonParseException {
Tatu Saloranta68194922012-11-15 20:34:29 -08001004 return createParser(in);
1005 }
1006
1007 /**
1008 * Method for constructing parser for parsing
1009 * the contents accessed via specified Reader.
1010 <p>
1011 * The read stream will <b>not be owned</b> by
1012 * the parser, it will still be managed (i.e. closed if
1013 * end-of-stream is reacher, or parser close method called)
1014 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
1015 * is enabled.
Tatu Saloranta68194922012-11-15 20:34:29 -08001016 *
1017 * @param r Reader to use for reading JSON content to parse
1018 *
1019 * @deprecated Since 2.2, use {@link #createParser(Reader)} instead.
1020 */
1021 @Deprecated
Tatu Salorantaefc23672013-12-30 19:09:39 -08001022 public JsonParser createJsonParser(Reader r) throws IOException, JsonParseException {
Tatu Saloranta68194922012-11-15 20:34:29 -08001023 return createParser(r);
1024 }
1025
1026 /**
Tatu Salorantaefc23672013-12-30 19:09:39 -08001027 * Method for constructing parser for parsing the contents of given byte array.
Tatu Saloranta68194922012-11-15 20:34:29 -08001028 *
1029 * @deprecated Since 2.2, use {@link #createParser(byte[])} instead.
1030 */
1031 @Deprecated
Tatu Salorantaefc23672013-12-30 19:09:39 -08001032 public JsonParser createJsonParser(byte[] data) throws IOException, JsonParseException {
Tatu Saloranta68194922012-11-15 20:34:29 -08001033 return createParser(data);
1034 }
1035
1036 /**
1037 * Method for constructing parser for parsing
1038 * the contents of given byte array.
Tatu Saloranta68194922012-11-15 20:34:29 -08001039 *
1040 * @param data Buffer that contains data to parse
1041 * @param offset Offset of the first data byte within buffer
1042 * @param len Length of contents to parse within buffer
1043 *
1044 * @deprecated Since 2.2, use {@link #createParser(byte[],int,int)} instead.
1045 */
1046 @Deprecated
Tatu Salorantaefc23672013-12-30 19:09:39 -08001047 public JsonParser createJsonParser(byte[] data, int offset, int len) throws IOException, JsonParseException {
Tatu Saloranta68194922012-11-15 20:34:29 -08001048 return createParser(data, offset, len);
1049 }
1050
1051 /**
1052 * Method for constructing parser for parsing
1053 * contents of given String.
1054 *
1055 * @deprecated Since 2.2, use {@link #createParser(String)} instead.
1056 */
1057 @Deprecated
Tatu Salorantaefc23672013-12-30 19:09:39 -08001058 public JsonParser createJsonParser(String content) throws IOException, JsonParseException {
Tatu Saloranta68194922012-11-15 20:34:29 -08001059 return createParser(content);
1060 }
1061
1062 /*
1063 /**********************************************************
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001064 /* Generator factories, new (as per [Issue-25]
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001065 /**********************************************************
1066 */
1067
1068 /**
1069 * Method for constructing JSON generator for writing JSON content
1070 * using specified output stream.
1071 * Encoding to use must be specified, and needs to be one of available
1072 * types (as per JSON specification).
1073 *<p>
1074 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1075 * so that generator will NOT close the output stream when
1076 * {@link JsonGenerator#close} is called (unless auto-closing
1077 * feature,
1078 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET}
1079 * is enabled).
1080 * Using application needs to close it explicitly if this is the case.
1081 *<p>
1082 * Note: there are formats that use fixed encoding (like most binary data formats)
1083 * and that ignore passed in encoding.
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001084 *
1085 * @param out OutputStream to use for writing JSON content
1086 * @param enc Character encoding to use
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001087 *
1088 * @since 2.1
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001089 */
1090 public JsonGenerator createGenerator(OutputStream out, JsonEncoding enc)
1091 throws IOException
1092 {
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001093 // false -> we won't manage the stream unless explicitly directed to
1094 IOContext ctxt = _createContext(out, false);
1095 ctxt.setEncoding(enc);
1096 if (enc == JsonEncoding.UTF8) {
Tatu Saloranta896000f2014-04-19 12:53:40 -07001097 return _createUTF8Generator(_decorate(out, ctxt), ctxt);
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001098 }
1099 Writer w = _createWriter(out, enc, ctxt);
Tatu Saloranta896000f2014-04-19 12:53:40 -07001100 return _createGenerator(_decorate(w, ctxt), ctxt);
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001101 }
1102
1103 /**
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001104 * Convenience method for constructing generator that uses default
1105 * encoding of the format (UTF-8 for JSON and most other data formats).
1106 *<p>
1107 * Note: there are formats that use fixed encoding (like most binary data formats).
1108 *
1109 * @since 2.1
1110 */
1111 public JsonGenerator createGenerator(OutputStream out) throws IOException {
1112 return createGenerator(out, JsonEncoding.UTF8);
1113 }
1114
1115 /**
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001116 * Method for constructing JSON generator for writing JSON content
1117 * using specified Writer.
1118 *<p>
1119 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1120 * so that generator will NOT close the Reader when
1121 * {@link JsonGenerator#close} is called (unless auto-closing
1122 * feature,
1123 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled).
1124 * Using application needs to close it explicitly.
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001125 *
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001126 * @since 2.1
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001127 *
Tatu Saloranta896000f2014-04-19 12:53:40 -07001128 * @param w Writer to use for writing JSON content
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001129 */
Tatu Saloranta896000f2014-04-19 12:53:40 -07001130 public JsonGenerator createGenerator(Writer w) throws IOException {
1131 IOContext ctxt = _createContext(w, false);
1132 return _createGenerator(_decorate(w, ctxt), ctxt);
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001133 }
1134
1135 /**
1136 * Method for constructing JSON generator for writing JSON content
1137 * to specified file, overwriting contents it might have (or creating
1138 * it if such file does not yet exist).
1139 * Encoding to use must be specified, and needs to be one of available
1140 * types (as per JSON specification).
1141 *<p>
1142 * Underlying stream <b>is owned</b> by the generator constructed,
1143 * i.e. generator will handle closing of file when
1144 * {@link JsonGenerator#close} is called.
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001145 *
1146 * @param f File to write contents to
1147 * @param enc Character encoding to use
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001148 *
1149 * @since 2.1
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001150 */
Tatu Salorantab0a2e192014-04-10 09:36:07 -07001151 public JsonGenerator createGenerator(File f, JsonEncoding enc) throws IOException
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001152 {
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001153 OutputStream out = new FileOutputStream(f);
1154 // true -> yes, we have to manage the stream since we created it
1155 IOContext ctxt = _createContext(out, true);
1156 ctxt.setEncoding(enc);
1157 if (enc == JsonEncoding.UTF8) {
Tatu Saloranta896000f2014-04-19 12:53:40 -07001158 return _createUTF8Generator(_decorate(out, ctxt), ctxt);
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001159 }
1160 Writer w = _createWriter(out, enc, ctxt);
Tatu Saloranta896000f2014-04-19 12:53:40 -07001161 return _createGenerator(_decorate(w, ctxt), ctxt);
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001162 }
1163
Tatu Saloranta38b3ef12016-05-03 18:08:31 -07001164 /**
1165 * Method for constructing generator for writing content using specified
1166 * {@link DataOutput} instance.
1167 *
1168 * @since 2.8
1169 */
1170 public JsonGenerator createGenerator(DataOutput out, JsonEncoding enc) throws IOException {
1171 return createGenerator(_createDataOutputWrapper(out), enc);
1172 }
1173
1174 /**
1175 * Convenience method for constructing generator that uses default
1176 * encoding of the format (UTF-8 for JSON and most other data formats).
1177 *<p>
1178 * Note: there are formats that use fixed encoding (like most binary data formats).
1179 *
1180 * @since 2.8
1181 */
1182 public JsonGenerator createGenerator(DataOutput out) throws IOException {
1183 return createGenerator(_createDataOutputWrapper(out), JsonEncoding.UTF8);
1184 }
1185
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001186 /*
1187 /**********************************************************
Tatu Salorantad302ae02015-12-27 21:53:15 -08001188 /* Generator factories, old (pre-2.2)
Tatu Salorantafeaabd12012-07-22 23:03:41 -07001189 /**********************************************************
1190 */
1191
1192 /**
1193 * Method for constructing JSON generator for writing JSON content
1194 * using specified output stream.
1195 * Encoding to use must be specified, and needs to be one of available
1196 * types (as per JSON specification).
1197 *<p>
1198 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1199 * so that generator will NOT close the output stream when
1200 * {@link JsonGenerator#close} is called (unless auto-closing
1201 * feature,
1202 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET}
1203 * is enabled).
1204 * Using application needs to close it explicitly if this is the case.
1205 *<p>
1206 * Note: there are formats that use fixed encoding (like most binary data formats)
1207 * and that ignore passed in encoding.
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001208 *
1209 * @param out OutputStream to use for writing JSON content
1210 * @param enc Character encoding to use
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001211 *
1212 * @deprecated Since 2.2, use {@link #createGenerator(OutputStream, JsonEncoding)} instead.
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001213 */
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001214 @Deprecated
Tatu Salorantab0a2e192014-04-10 09:36:07 -07001215 public JsonGenerator createJsonGenerator(OutputStream out, JsonEncoding enc) throws IOException {
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001216 return createGenerator(out, enc);
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001217 }
1218
1219 /**
1220 * Method for constructing JSON generator for writing JSON content
1221 * using specified Writer.
1222 *<p>
1223 * Underlying stream <b>is NOT owned</b> by the generator constructed,
1224 * so that generator will NOT close the Reader when
1225 * {@link JsonGenerator#close} is called (unless auto-closing
1226 * feature,
1227 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled).
1228 * Using application needs to close it explicitly.
1229 *
1230 * @param out Writer to use for writing JSON content
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001231 *
1232 * @deprecated Since 2.2, use {@link #createGenerator(Writer)} instead.
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001233 */
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001234 @Deprecated
Tatu Salorantab0a2e192014-04-10 09:36:07 -07001235 public JsonGenerator createJsonGenerator(Writer out) throws IOException {
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001236 return createGenerator(out);
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001237 }
1238
1239 /**
1240 * Convenience method for constructing generator that uses default
1241 * encoding of the format (UTF-8 for JSON and most other data formats).
1242 *<p>
1243 * Note: there are formats that use fixed encoding (like most binary data formats).
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001244 *
1245 * @deprecated Since 2.2, use {@link #createGenerator(OutputStream)} instead.
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001246 */
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001247 @Deprecated
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001248 public JsonGenerator createJsonGenerator(OutputStream out) throws IOException {
Tatu Saloranta4ab04ce2012-11-15 20:42:16 -08001249 return createGenerator(out, JsonEncoding.UTF8);
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001250 }
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001251
1252 /*
1253 /**********************************************************
1254 /* Factory methods used by factory for creating parser instances,
1255 /* overridable by sub-classes
1256 /**********************************************************
1257 */
1258
1259 /**
1260 * Overridable factory method that actually instantiates desired parser
1261 * given {@link InputStream} and context object.
1262 *<p>
1263 * This method is specifically designed to remain
1264 * compatible between minor versions so that sub-classes can count
1265 * on it being called as expected. That is, it is part of official
1266 * interface from sub-class perspective, although not a public
1267 * method available to users of factory implementations.
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -07001268 *
1269 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001270 */
Tatu Salorantab0a2e192014-04-10 09:36:07 -07001271 protected JsonParser _createParser(InputStream in, IOContext ctxt) throws IOException {
Tatu Saloranta68194922012-11-15 20:34:29 -08001272 // As per [JACKSON-259], may want to fully disable canonicalization:
1273 return new ByteSourceJsonBootstrapper(ctxt, in).constructParser(_parserFeatures,
Tatu Salorantadccffbe2015-02-05 21:17:57 -08001274 _objectCodec, _byteSymbolCanonicalizer, _rootCharSymbols, _factoryFeatures);
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -07001275 }
1276
1277 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001278 * Overridable factory method that actually instantiates parser
1279 * using given {@link Reader} object for reading content.
1280 *<p>
1281 * This method is specifically designed to remain
1282 * compatible between minor versions so that sub-classes can count
1283 * on it being called as expected. That is, it is part of official
1284 * interface from sub-class perspective, although not a public
1285 * method available to users of factory implementations.
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -07001286 *
1287 * @since 2.1
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001288 */
Tatu Salorantab0a2e192014-04-10 09:36:07 -07001289 protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException {
Tatu Saloranta68194922012-11-15 20:34:29 -08001290 return new ReaderBasedJsonParser(ctxt, _parserFeatures, r, _objectCodec,
Tatu Saloranta0541b3b2014-05-23 20:20:46 -07001291 _rootCharSymbols.makeChild(_factoryFeatures));
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -07001292 }
1293
1294 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001295 * Overridable factory method that actually instantiates parser
Tatu64aa9d22014-04-18 14:07:38 -07001296 * using given <code>char[]</code> object for accessing content.
1297 *
1298 * @since 2.4
1299 */
1300 protected JsonParser _createParser(char[] data, int offset, int len, IOContext ctxt,
1301 boolean recyclable) throws IOException {
1302 return new ReaderBasedJsonParser(ctxt, _parserFeatures, null, _objectCodec,
Tatu Saloranta0541b3b2014-05-23 20:20:46 -07001303 _rootCharSymbols.makeChild(_factoryFeatures),
1304 data, offset, offset+len, recyclable);
Tatu64aa9d22014-04-18 14:07:38 -07001305 }
1306
1307 /**
1308 * Overridable factory method that actually instantiates parser
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001309 * using given {@link Reader} object for reading content
1310 * passed as raw byte array.
1311 *<p>
1312 * This method is specifically designed to remain
1313 * compatible between minor versions so that sub-classes can count
1314 * on it being called as expected. That is, it is part of official
1315 * interface from sub-class perspective, although not a public
1316 * method available to users of factory implementations.
1317 */
Tatu64aa9d22014-04-18 14:07:38 -07001318 protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001319 {
Tatu Saloranta68194922012-11-15 20:34:29 -08001320 return new ByteSourceJsonBootstrapper(ctxt, data, offset, len).constructParser(_parserFeatures,
Tatu Salorantadccffbe2015-02-05 21:17:57 -08001321 _objectCodec, _byteSymbolCanonicalizer, _rootCharSymbols, _factoryFeatures);
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -07001322 }
1323
Tatu Salorantad7cbb642016-05-13 13:23:04 -07001324 /**
1325 * @since 2.8
1326 */
1327 protected JsonParser _createParser(DataInput input, IOContext ctxt) throws IOException
1328 {
1329 // 13-May-2016, tatu: Need to take care not to accidentally create JSON parser for
1330 // non-JSON input. So, bit unclean but...
1331 String format = getFormatName();
Tatu Salorantacd5b6ff2016-07-21 14:38:42 -07001332 if (format != FORMAT_NAME_JSON) { // NOTE: only ensure override; full equality NOT needed
Tatu Salorantad7cbb642016-05-13 13:23:04 -07001333 throw new UnsupportedOperationException(String.format(
1334 "InputData source not (yet?) support for this format (%s)", format));
1335 }
Tatu Saloranta155babc2016-05-17 16:13:19 -07001336 // Also: while we can't do full bootstrapping (due to read-ahead limitations), should
1337 // at least handle possible UTF-8 BOM
1338 int firstByte = ByteSourceJsonBootstrapper.skipUTF8BOM(input);
Tatu Salorantad7cbb642016-05-13 13:23:04 -07001339 ByteQuadsCanonicalizer can = _byteSymbolCanonicalizer.makeChild(_factoryFeatures);
1340 return new UTF8DataInputJsonParser(ctxt, _parserFeatures, input,
Tatu Saloranta155babc2016-05-17 16:13:19 -07001341 _objectCodec, can, firstByte);
Tatu Salorantad7cbb642016-05-13 13:23:04 -07001342 }
1343
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001344 /*
1345 /**********************************************************
1346 /* Factory methods used by factory for creating generator instances,
1347 /* overridable by sub-classes
1348 /**********************************************************
1349 */
1350
1351 /**
1352 * Overridable factory method that actually instantiates generator for
1353 * given {@link Writer} and context object.
1354 *<p>
1355 * This method is specifically designed to remain
1356 * compatible between minor versions so that sub-classes can count
1357 * on it being called as expected. That is, it is part of official
1358 * interface from sub-class perspective, although not a public
1359 * method available to users of factory implementations.
1360 */
Tatu Salorantaefc23672013-12-30 19:09:39 -08001361 protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -07001362 {
Tatu Salorantae6dfc692012-09-28 15:34:05 -07001363 WriterBasedJsonGenerator gen = new WriterBasedJsonGenerator(ctxt,
1364 _generatorFeatures, _objectCodec, out);
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001365 if (_characterEscapes != null) {
1366 gen.setCharacterEscapes(_characterEscapes);
1367 }
Tatu Salorantae6dfc692012-09-28 15:34:05 -07001368 SerializableString rootSep = _rootValueSeparator;
1369 if (rootSep != DEFAULT_ROOT_VALUE_SEPARATOR) {
1370 gen.setRootValueSeparator(rootSep);
1371 }
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001372 return gen;
1373 }
1374
1375 /**
1376 * Overridable factory method that actually instantiates generator for
1377 * given {@link OutputStream} and context object, using UTF-8 encoding.
1378 *<p>
1379 * This method is specifically designed to remain
1380 * compatible between minor versions so that sub-classes can count
1381 * on it being called as expected. That is, it is part of official
1382 * interface from sub-class perspective, although not a public
1383 * method available to users of factory implementations.
1384 */
Tatu Salorantaeeb2fbd2012-05-28 22:00:08 -07001385 protected JsonGenerator _createUTF8Generator(OutputStream out, IOContext ctxt) throws IOException {
Tatu Salorantae6dfc692012-09-28 15:34:05 -07001386 UTF8JsonGenerator gen = new UTF8JsonGenerator(ctxt,
1387 _generatorFeatures, _objectCodec, out);
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001388 if (_characterEscapes != null) {
1389 gen.setCharacterEscapes(_characterEscapes);
1390 }
Tatu Salorantae6dfc692012-09-28 15:34:05 -07001391 SerializableString rootSep = _rootValueSeparator;
1392 if (rootSep != DEFAULT_ROOT_VALUE_SEPARATOR) {
1393 gen.setRootValueSeparator(rootSep);
1394 }
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001395 return gen;
1396 }
1397
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001398 protected Writer _createWriter(OutputStream out, JsonEncoding enc, IOContext ctxt) throws IOException
1399 {
1400 // note: this should not get called any more (caller checks, dispatches)
1401 if (enc == JsonEncoding.UTF8) { // We have optimized writer for UTF-8
1402 return new UTF8Writer(ctxt, out);
1403 }
1404 // not optimal, but should do unless we really care about UTF-16/32 encoding speed
1405 return new OutputStreamWriter(out, enc.getJavaName());
1406 }
Tatu Saloranta896000f2014-04-19 12:53:40 -07001407
1408 /*
1409 /**********************************************************
1410 /* Internal factory methods, decorator handling
1411 /**********************************************************
1412 */
1413
1414 /**
1415 * @since 2.4
1416 */
1417 protected final InputStream _decorate(InputStream in, IOContext ctxt) throws IOException {
1418 if (_inputDecorator != null) {
1419 InputStream in2 = _inputDecorator.decorate(ctxt, in);
1420 if (in2 != null) {
1421 return in2;
1422 }
1423 }
1424 return in;
1425 }
Tatu Salorantad7cbb642016-05-13 13:23:04 -07001426
Tatu Saloranta896000f2014-04-19 12:53:40 -07001427 /**
1428 * @since 2.4
1429 */
1430 protected final Reader _decorate(Reader in, IOContext ctxt) throws IOException {
1431 if (_inputDecorator != null) {
1432 Reader in2 = _inputDecorator.decorate(ctxt, in);
1433 if (in2 != null) {
1434 return in2;
1435 }
1436 }
1437 return in;
1438 }
1439
1440 /**
Tatu Salorantad7cbb642016-05-13 13:23:04 -07001441 * @since 2.8
1442 */
1443 protected final DataInput _decorate(DataInput in, IOContext ctxt) throws IOException {
1444 if (_inputDecorator != null) {
1445 DataInput in2 = _inputDecorator.decorate(ctxt, in);
1446 if (in2 != null) {
1447 return in2;
1448 }
1449 }
1450 return in;
1451 }
1452
1453 /**
Tatu Saloranta896000f2014-04-19 12:53:40 -07001454 * @since 2.4
1455 */
1456 protected final OutputStream _decorate(OutputStream out, IOContext ctxt) throws IOException {
1457 if (_outputDecorator != null) {
1458 OutputStream out2 = _outputDecorator.decorate(ctxt, out);
1459 if (out2 != null) {
1460 return out2;
1461 }
1462 }
1463 return out;
1464 }
1465
1466 /**
1467 * @since 2.4
1468 */
1469 protected final Writer _decorate(Writer out, IOContext ctxt) throws IOException {
1470 if (_outputDecorator != null) {
1471 Writer out2 = _outputDecorator.decorate(ctxt, out);
1472 if (out2 != null) {
1473 return out2;
1474 }
1475 }
1476 return out;
1477 }
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001478
1479 /*
1480 /**********************************************************
1481 /* Internal factory methods, other
1482 /**********************************************************
1483 */
1484
1485 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001486 * Method used by factory to create buffer recycler instances
1487 * for parsers and generators.
1488 *<p>
1489 * Note: only public to give access for <code>ObjectMapper</code>
1490 */
1491 public BufferRecycler _getBufferRecycler()
1492 {
Tatu Saloranta8891c0c2015-04-23 22:47:05 -07001493 /* 23-Apr-2015, tatu: Let's allow disabling of buffer recycling
1494 * scheme, for cases where it is considered harmful (possibly
1495 * on Android, for example)
1496 */
Tatu Salorantaddec51c2017-02-28 16:07:04 -08001497 if (Feature.USE_THREAD_LOCAL_FOR_BUFFER_RECYCLING.enabledIn(_factoryFeatures)) {
Tatu Saloranta8891c0c2015-04-23 22:47:05 -07001498 SoftReference<BufferRecycler> ref = _recyclerRef.get();
happyelf833de412016-07-23 11:10:21 +08001499 BufferRecycler br = (ref == null) ? null : ref.get();
Tatu Saloranta8891c0c2015-04-23 22:47:05 -07001500
1501 if (br == null) {
1502 br = new BufferRecycler();
1503 _recyclerRef.set(new SoftReference<BufferRecycler>(br));
1504 }
happyelf833de412016-07-23 11:10:21 +08001505 return br;
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001506 }
happyelf833de412016-07-23 11:10:21 +08001507 return new BufferRecycler();
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001508 }
Tatu Salorantad302ae02015-12-27 21:53:15 -08001509
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001510 /**
Tatu Saloranta896000f2014-04-19 12:53:40 -07001511 * Overridable factory method that actually instantiates desired
1512 * context object.
1513 */
1514 protected IOContext _createContext(Object srcRef, boolean resourceManaged) {
1515 return new IOContext(_getBufferRecycler(), srcRef, resourceManaged);
1516 }
Tatu Salorantad302ae02015-12-27 21:53:15 -08001517
Tatu Saloranta896000f2014-04-19 12:53:40 -07001518 /**
Tatu Saloranta38b3ef12016-05-03 18:08:31 -07001519 * @since 2.8
1520 */
1521 protected OutputStream _createDataOutputWrapper(DataOutput out) {
1522 return new DataOutputAsStream(out);
1523 }
1524
1525 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001526 * Helper methods used for constructing an optimal stream for
1527 * parsers to use, when input is to be read from an URL.
1528 * This helps when reading file content via URL.
1529 */
Tatu Salorantaefc23672013-12-30 19:09:39 -08001530 protected InputStream _optimizedStreamFromURL(URL url) throws IOException {
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001531 if ("file".equals(url.getProtocol())) {
1532 /* Can not do this if the path refers
1533 * to a network drive on windows. This fixes the problem;
1534 * might not be needed on all platforms (NFS?), but should not
1535 * matter a lot: performance penalty of extra wrapping is more
1536 * relevant when accessing local file system.
1537 */
1538 String host = url.getHost();
1539 if (host == null || host.length() == 0) {
Tatu Saloranta38b3ef12016-05-03 18:08:31 -07001540 // [core#48]: Let's try to avoid probs with URL encoded stuff
Tatu Saloranta61d5bdd2013-01-11 19:02:01 -08001541 String path = url.getPath();
1542 if (path.indexOf('%') < 0) {
1543 return new FileInputStream(url.getPath());
1544
1545 }
1546 // otherwise, let's fall through and let URL decoder do its magic
Tatu Salorantaf15531c2011-12-22 23:00:40 -08001547 }
1548 }
1549 return url.openStream();
1550 }
1551}