blob: 2d8602b57f790962ad18f81a1be57c9be0a7e8a9 [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
4 *
5 * Licensed under the License specified in file LICENSE, included with
6 * the source code and binary code bundles.
7 * You may not use this file except in compliance with the License.
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15package com.fasterxml.jackson.core;
16
17import java.io.*;
18import java.lang.ref.SoftReference;
19import java.net.URL;
20
21import com.fasterxml.jackson.core.format.InputAccessor;
22import com.fasterxml.jackson.core.format.MatchStrength;
23import com.fasterxml.jackson.core.io.*;
Tatu07351902012-01-19 13:12:13 -080024import com.fasterxml.jackson.core.json.*;
Tatu Salorantaf15531c2011-12-22 23:00:40 -080025import com.fasterxml.jackson.core.sym.BytesToNameCanonicalizer;
26import com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer;
27import com.fasterxml.jackson.core.util.BufferRecycler;
Tatu Salorantaf15531c2011-12-22 23:00:40 -080028
29/**
30 * The main factory class of Jackson package, used to configure and
31 * construct reader (aka parser, {@link JsonParser})
32 * and writer (aka generator, {@link JsonGenerator})
33 * instances.
34 *<p>
35 * Factory instances are thread-safe and reusable after configuration
36 * (if any). Typically applications and services use only a single
37 * globally shared factory instance, unless they need differently
38 * configured factories. Factory reuse is important if efficiency matters;
39 * most recycling of expensive construct is done on per-factory basis.
40 *<p>
41 * Creation of a factory instance is a light-weight operation,
42 * and since there is no need for pluggable alternative implementations
43 * (as there is no "standard" JSON processor API to implement),
44 * the default constructor is used for constructing factory
45 * instances.
46 *
47 * @author Tatu Saloranta
48 */
49public class JsonFactory implements Versioned
50{
51 /**
52 * Name used to identify JSON format
53 * (and returned by {@link #getFormatName()}
54 */
55 public final static String FORMAT_NAME_JSON = "JSON";
56
57 /**
Tatu07351902012-01-19 13:12:13 -080058 * Bitfield (set of flags) of all factory features that are enabled by default.
59 */
60 protected final static int DEFAULT_FACTORY_FEATURE_FLAGS = JsonFactory.Feature.collectDefaults();
61
62 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -080063 * Bitfield (set of flags) of all parser features that are enabled
64 * by default.
65 */
Tatu07351902012-01-19 13:12:13 -080066 protected final static int DEFAULT_PARSER_FEATURE_FLAGS = JsonParser.Feature.collectDefaults();
67
Tatu Salorantaf15531c2011-12-22 23:00:40 -080068 /**
69 * Bitfield (set of flags) of all generator features that are enabled
70 * by default.
71 */
Tatu07351902012-01-19 13:12:13 -080072 protected final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults();
Tatu Salorantaf15531c2011-12-22 23:00:40 -080073
Tatu07351902012-01-19 13:12:13 -080074 /**
75 * Enumeration that defines all on/off features that can only be
76 * changed for {@link JsonFactory}.
77 */
78 public enum Feature {
79
80 // // // Symbol handling (interning etc)
81
82 /**
83 * Feature that determines whether JSON object field names are
84 * to be canonicalized using {@link String#intern} or not:
85 * if enabled, all field names will be intern()ed (and caller
86 * can count on this being true for all such names); if disabled,
87 * no intern()ing is done. There may still be basic
88 * canonicalization (that is, same String will be used to represent
89 * all identical object property names for a single document).
90 *<p>
91 * Note: this setting only has effect if
92 * {@link #CANONICALIZE_FIELD_NAMES} is true -- otherwise no
93 * canonicalization of any sort is done.
94 *<p>
95 * This setting is enabled by default.
96 */
97 INTERN_FIELD_NAMES(true),
98
99 /**
100 * Feature that determines whether JSON object field names are
101 * to be canonicalized (details of how canonicalization is done
102 * then further specified by
103 * {@link #INTERN_FIELD_NAMES}).
104 *<p>
105 * This setting is enabled by default.
106 */
107 CANONICALIZE_FIELD_NAMES(true)
108
109 ;
110
111 /**
112 * Whether feature is enabled or disabled by default.
113 */
114 private final boolean _defaultState;
115
116 /**
117 * Method that calculates bit set (flags) of all features that
118 * are enabled by default.
119 */
120 public static int collectDefaults()
121 {
122 int flags = 0;
123 for (Feature f : values()) {
124 if (f.enabledByDefault()) {
125 flags |= f.getMask();
126 }
127 }
128 return flags;
129 }
130
131 private Feature(boolean defaultState)
132 {
133 _defaultState = defaultState;
134 }
135
136 public boolean enabledByDefault() { return _defaultState; }
137
138 public boolean enabledIn(int flags) { return (flags & getMask()) != 0; }
139
140 public int getMask() { return (1 << ordinal()); }
141 }
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800142 /*
143 /**********************************************************
144 /* Buffer, symbol table management
145 /**********************************************************
146 */
147
148 /**
149 * This <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftRerefence}
150 * to a {@link BufferRecycler} used to provide a low-cost
151 * buffer recycling between reader and writer instances.
152 */
153 final protected static ThreadLocal<SoftReference<BufferRecycler>> _recyclerRef
154 = new ThreadLocal<SoftReference<BufferRecycler>>();
155
156 /**
157 * Each factory comes equipped with a shared root symbol table.
158 * It should not be linked back to the original blueprint, to
159 * avoid contents from leaking between factories.
160 */
161 protected CharsToNameCanonicalizer _rootCharSymbols = CharsToNameCanonicalizer.createRoot();
162
163 /**
164 * Alternative to the basic symbol table, some stream-based
165 * parsers use different name canonicalization method.
166 *<p>
167 * TODO: should clean up this; looks messy having 2 alternatives
168 * with not very clear differences.
169 */
170 protected BytesToNameCanonicalizer _rootByteSymbols = BytesToNameCanonicalizer.createRoot();
171
172 /*
173 /**********************************************************
174 /* Configuration
175 /**********************************************************
176 */
177
178 /**
179 * Object that implements conversion functionality between
180 * Java objects and JSON content. For base JsonFactory implementation
181 * usually not set by default, but can be explicitly set.
182 * Sub-classes (like @link org.codehaus.jackson.map.MappingJsonFactory}
183 * usually provide an implementation.
184 */
185 protected ObjectCodec _objectCodec;
186
187 /**
Tatu07351902012-01-19 13:12:13 -0800188 * Currently enabled factory features.
189 */
190 protected int _factoryFeatures = DEFAULT_FACTORY_FEATURE_FLAGS;
191
192 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800193 * Currently enabled parser features.
194 */
195 protected int _parserFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
196
197 /**
198 * Currently enabled generator features.
199 */
200 protected int _generatorFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
201
202 /**
203 * Definition of custom character escapes to use for generators created
204 * by this factory, if any. If null, standard data format specific
205 * escapes are used.
206 */
207 protected CharacterEscapes _characterEscapes;
208
209 /**
210 * Optional helper object that may decorate input sources, to do
211 * additional processing on input during parsing.
212 */
213 protected InputDecorator _inputDecorator;
214
215 /**
216 * Optional helper object that may decorate output object, to do
217 * additional processing on output during content generation.
218 */
219 protected OutputDecorator _outputDecorator;
220
221 /*
222 /**********************************************************
223 /* Construction
224 /**********************************************************
225 */
226
227 /**
228 * Default constructor used to create factory instances.
229 * Creation of a factory instance is a light-weight operation,
230 * but it is still a good idea to reuse limited number of
231 * factory instances (and quite often just a single instance):
232 * factories are used as context for storing some reused
233 * processing objects (such as symbol tables parsers use)
234 * and this reuse only works within context of a single
235 * factory instance.
236 */
237 public JsonFactory() { this(null); }
238
239 public JsonFactory(ObjectCodec oc) { _objectCodec = oc; }
240
241 /*
242 /**********************************************************
243 /* Format detection functionality (since 1.8)
244 /**********************************************************
245 */
246
247 /**
248 * Method that returns short textual id identifying format
249 * this factory supports.
250 *<p>
251 * Note: sub-classes should override this method; default
252 * implementation will return null for all sub-classes
253 */
254 public String getFormatName()
255 {
256 /* Somewhat nasty check: since we can't make this abstract
257 * (due to backwards compatibility concerns), need to prevent
258 * format name "leakage"
259 */
260 if (getClass() == JsonFactory.class) {
261 return FORMAT_NAME_JSON;
262 }
263 return null;
264 }
265
266 public MatchStrength hasFormat(InputAccessor acc) throws IOException
267 {
268 // since we can't keep this abstract, only implement for "vanilla" instance
269 if (getClass() == JsonFactory.class) {
270 return hasJSONFormat(acc);
271 }
272 return null;
273 }
274
275 protected MatchStrength hasJSONFormat(InputAccessor acc) throws IOException
276 {
277 return ByteSourceJsonBootstrapper.hasJSONFormat(acc);
278 }
279
280 /*
281 /**********************************************************
282 /* Versioned
283 /**********************************************************
284 */
285
286 @Override
287 public Version version() {
Tatu Saloranta5a1bd992011-12-28 23:18:23 -0800288 return CoreVersion.instance.version();
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800289 }
290
291 /*
292 /**********************************************************
Tatu07351902012-01-19 13:12:13 -0800293 /* Configuration, factory features
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800294 /**********************************************************
295 */
296
297 /**
298 * Method for enabling or disabling specified parser feature
299 * (check {@link JsonParser.Feature} for list of features)
300 */
Tatu07351902012-01-19 13:12:13 -0800301 public final JsonFactory configure(JsonFactory.Feature f, boolean state) {
302 return state ? enable(f) : disable(f);
303 }
304
305 /**
306 * Method for enabling specified parser feature
307 * (check {@link JsonFactory.Feature} for list of features)
308 */
309 public JsonFactory enable(JsonFactory.Feature f) {
310 _factoryFeatures |= f.getMask();
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800311 return this;
312 }
313
314 /**
Tatu07351902012-01-19 13:12:13 -0800315 * Method for disabling specified parser features
316 * (check {@link JsonFactory.Feature} for list of features)
317 */
318 public JsonFactory disable(JsonFactory.Feature f) {
319 _factoryFeatures &= ~f.getMask();
320 return this;
321 }
322
323 /**
324 * Checked whether specified parser feature is enabled.
325 */
326 public final boolean isEnabled(JsonFactory.Feature f) {
327 return (_factoryFeatures & f.getMask()) != 0;
328 }
329
330 /*
331 /**********************************************************
332 /* Configuration, parser configuration
333 /**********************************************************
334 */
335
336 /**
337 * Method for enabling or disabling specified parser feature
338 * (check {@link JsonParser.Feature} for list of features)
339 */
340 public final JsonFactory configure(JsonParser.Feature f, boolean state) {
341 return state ? enable(f) : disable(f);
342 }
343
344 /**
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800345 * Method for enabling specified parser feature
346 * (check {@link JsonParser.Feature} for list of features)
347 */
348 public JsonFactory enable(JsonParser.Feature f) {
349 _parserFeatures |= f.getMask();
350 return this;
351 }
352
353 /**
354 * Method for disabling specified parser features
355 * (check {@link JsonParser.Feature} for list of features)
356 */
357 public JsonFactory disable(JsonParser.Feature f) {
358 _parserFeatures &= ~f.getMask();
359 return this;
360 }
361
362 /**
363 * Checked whether specified parser feature is enabled.
364 */
365 public final boolean isEnabled(JsonParser.Feature f) {
366 return (_parserFeatures & f.getMask()) != 0;
367 }
368
369 /**
370 * Method for getting currently configured input decorator (if any;
371 * there is no default decorator).
372 */
373 public InputDecorator getInputDecorator() {
374 return _inputDecorator;
375 }
376
377 /**
378 * Method for overriding currently configured input decorator
379 */
380 public JsonFactory setInputDecorator(InputDecorator d) {
381 _inputDecorator = d;
382 return this;
383 }
384
385 /*
386 /**********************************************************
387 /* Configuration, generator settings
388 /**********************************************************
389 */
390
391 /**
392 * Method for enabling or disabling specified generator feature
393 * (check {@link JsonGenerator.Feature} for list of features)
394 */
395 public final JsonFactory configure(JsonGenerator.Feature f, boolean state) {
Tatu07351902012-01-19 13:12:13 -0800396 return state ? enable(f) : disable(f);
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800397 }
398
399
400 /**
401 * Method for enabling specified generator features
402 * (check {@link JsonGenerator.Feature} for list of features)
403 */
404 public JsonFactory enable(JsonGenerator.Feature f) {
405 _generatorFeatures |= f.getMask();
406 return this;
407 }
408
409 /**
410 * Method for disabling specified generator feature
411 * (check {@link JsonGenerator.Feature} for list of features)
412 */
413 public JsonFactory disable(JsonGenerator.Feature f) {
414 _generatorFeatures &= ~f.getMask();
415 return this;
416 }
417
418 /**
419 * Check whether specified generator feature is enabled.
420 */
421 public final boolean isEnabled(JsonGenerator.Feature f) {
422 return (_generatorFeatures & f.getMask()) != 0;
423 }
424
425 /**
426 * Method for accessing custom escapes factory uses for {@link JsonGenerator}s
427 * it creates.
428 */
429 public CharacterEscapes getCharacterEscapes() {
430 return _characterEscapes;
431 }
432
433 /**
434 * Method for defining custom escapes factory uses for {@link JsonGenerator}s
435 * it creates.
436 */
437 public JsonFactory setCharacterEscapes(CharacterEscapes esc) {
438 _characterEscapes = esc;
439 return this;
440 }
441
442 /**
443 * Method for getting currently configured output decorator (if any;
444 * there is no default decorator).
445 */
446 public OutputDecorator getOutputDecorator() {
447 return _outputDecorator;
448 }
449
450 /**
451 * Method for overriding currently configured output decorator
452 */
453 public JsonFactory setOutputDecorator(OutputDecorator d) {
454 _outputDecorator = d;
455 return this;
456 }
457
458 /*
459 /**********************************************************
460 /* Configuration, other
461 /**********************************************************
462 */
463
464 /**
465 * Method for associating a {@link ObjectCodec} (typically
Tatu Salorantad77350e2011-12-22 23:13:13 -0800466 * a <code>com.fasterxml.jackson.databind.ObjectMapper</code>)
467 * with this factory (and more importantly, parsers and generators
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800468 * it constructs). This is needed to use data-binding methods
469 * of {@link JsonParser} and {@link JsonGenerator} instances.
470 */
471 public JsonFactory setCodec(ObjectCodec oc) {
472 _objectCodec = oc;
473 return this;
474 }
475
476 public ObjectCodec getCodec() { return _objectCodec; }
477
478 /*
479 /**********************************************************
480 /* Reader factories
481 /**********************************************************
482 */
483
484 /**
485 * Method for constructing JSON parser instance to parse
486 * contents of specified file. Encoding is auto-detected
487 * from contents according to JSON specification recommended
488 * mechanism.
489 *<p>
490 * Underlying input stream (needed for reading contents)
491 * will be <b>owned</b> (and managed, i.e. closed as need be) by
492 * the parser, since caller has no access to it.
493 *
494 * @param f File that contains JSON content to parse
495 */
496 public JsonParser createJsonParser(File f)
497 throws IOException, JsonParseException
498 {
499 // true, since we create InputStream from File
500 IOContext ctxt = _createContext(f, true);
501 InputStream in = new FileInputStream(f);
502 // [JACKSON-512]: allow wrapping with InputDecorator
503 if (_inputDecorator != null) {
504 in = _inputDecorator.decorate(ctxt, in);
505 }
506 return _createJsonParser(in, ctxt);
507 }
508
509 /**
510 * Method for constructing JSON parser instance to parse
511 * contents of resource reference by given URL.
512 * Encoding is auto-detected
513 * from contents according to JSON specification recommended
514 * mechanism.
515 *<p>
516 * Underlying input stream (needed for reading contents)
517 * will be <b>owned</b> (and managed, i.e. closed as need be) by
518 * the parser, since caller has no access to it.
519 *
520 * @param url URL pointing to resource that contains JSON content to parse
521 */
522 public JsonParser createJsonParser(URL url)
523 throws IOException, JsonParseException
524 {
525 // true, since we create InputStream from URL
526 IOContext ctxt = _createContext(url, true);
527 InputStream in = _optimizedStreamFromURL(url);
528 // [JACKSON-512]: allow wrapping with InputDecorator
529 if (_inputDecorator != null) {
530 in = _inputDecorator.decorate(ctxt, in);
531 }
532 return _createJsonParser(in, ctxt);
533 }
534
535 /**
536 * Method for constructing JSON parser instance to parse
537 * the contents accessed via specified input stream.
538 *<p>
539 * The input stream will <b>not be owned</b> by
540 * the parser, it will still be managed (i.e. closed if
541 * end-of-stream is reacher, or parser close method called)
542 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
543 * is enabled.
544 *<p>
545 * Note: no encoding argument is taken since it can always be
546 * auto-detected as suggested by Json RFC.
547 *
548 * @param in InputStream to use for reading JSON content to parse
549 */
550 public JsonParser createJsonParser(InputStream in)
551 throws IOException, JsonParseException
552 {
553 IOContext ctxt = _createContext(in, false);
554 // [JACKSON-512]: allow wrapping with InputDecorator
555 if (_inputDecorator != null) {
556 in = _inputDecorator.decorate(ctxt, in);
557 }
558 return _createJsonParser(in, ctxt);
559 }
560
561 /**
562 * Method for constructing parser for parsing
563 * the contents accessed via specified Reader.
564 <p>
565 * The read stream will <b>not be owned</b> by
566 * the parser, it will still be managed (i.e. closed if
567 * end-of-stream is reacher, or parser close method called)
568 * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
569 * is enabled.
570 *<p>
571 *
572 * @param r Reader to use for reading JSON content to parse
573 */
574 public JsonParser createJsonParser(Reader r)
575 throws IOException, JsonParseException
576 {
577 // false -> we do NOT own Reader (did not create it)
578 IOContext ctxt = _createContext(r, false);
579 // [JACKSON-512]: allow wrapping with InputDecorator
580 if (_inputDecorator != null) {
581 r = _inputDecorator.decorate(ctxt, r);
582 }
583 return _createJsonParser(r, ctxt);
584 }
585
586 /**
587 * Method for constructing parser for parsing
588 * the contents of given byte array.
589 */
590 public JsonParser createJsonParser(byte[] data)
591 throws IOException, JsonParseException
592 {
593 IOContext ctxt = _createContext(data, true);
594 // [JACKSON-512]: allow wrapping with InputDecorator
595 if (_inputDecorator != null) {
596 InputStream in = _inputDecorator.decorate(ctxt, data, 0, data.length);
597 if (in != null) {
598 return _createJsonParser(in, ctxt);
599 }
600 }
601 return _createJsonParser(data, 0, data.length, ctxt);
602 }
603
604 /**
605 * Method for constructing parser for parsing
606 * the contents of given byte array.
607 *
608 * @param data Buffer that contains data to parse
609 * @param offset Offset of the first data byte within buffer
610 * @param len Length of contents to parse within buffer
611 */
612 public JsonParser createJsonParser(byte[] data, int offset, int len)
613 throws IOException, JsonParseException
614 {
615 IOContext ctxt = _createContext(data, true);
616 // [JACKSON-512]: allow wrapping with InputDecorator
617 if (_inputDecorator != null) {
618 InputStream in = _inputDecorator.decorate(ctxt, data, offset, len);
619 if (in != null) {
620 return _createJsonParser(in, ctxt);
621 }
622 }
623 return _createJsonParser(data, offset, len, ctxt);
624 }
625
626 /**
627 * Method for constructing parser for parsing
628 * contents of given String.
629 */
630 public JsonParser createJsonParser(String content)
631 throws IOException, JsonParseException
632 {
633 Reader r = new StringReader(content);
634 // true -> we own the Reader (and must close); not a big deal
635 IOContext ctxt = _createContext(r, true);
636 // [JACKSON-512]: allow wrapping with InputDecorator
637 if (_inputDecorator != null) {
638 r = _inputDecorator.decorate(ctxt, r);
639 }
640 return _createJsonParser(r, ctxt);
641 }
642
643 /*
644 /**********************************************************
645 /* Generator factories
646 /**********************************************************
647 */
648
649 /**
650 * Method for constructing JSON generator for writing JSON content
651 * using specified output stream.
652 * Encoding to use must be specified, and needs to be one of available
653 * types (as per JSON specification).
654 *<p>
655 * Underlying stream <b>is NOT owned</b> by the generator constructed,
656 * so that generator will NOT close the output stream when
657 * {@link JsonGenerator#close} is called (unless auto-closing
658 * feature,
659 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET}
660 * is enabled).
661 * Using application needs to close it explicitly if this is the case.
662 *<p>
663 * Note: there are formats that use fixed encoding (like most binary data formats)
664 * and that ignore passed in encoding.
665 *
666 * @param out OutputStream to use for writing JSON content
667 * @param enc Character encoding to use
668 */
669 public JsonGenerator createJsonGenerator(OutputStream out, JsonEncoding enc)
670 throws IOException
671 {
672 // false -> we won't manage the stream unless explicitly directed to
673 IOContext ctxt = _createContext(out, false);
674 ctxt.setEncoding(enc);
675 if (enc == JsonEncoding.UTF8) {
676 // [JACKSON-512]: allow wrapping with _outputDecorator
677 if (_outputDecorator != null) {
678 out = _outputDecorator.decorate(ctxt, out);
679 }
680 return _createUTF8JsonGenerator(out, ctxt);
681 }
682 Writer w = _createWriter(out, enc, ctxt);
683 // [JACKSON-512]: allow wrapping with _outputDecorator
684 if (_outputDecorator != null) {
685 w = _outputDecorator.decorate(ctxt, w);
686 }
687 return _createJsonGenerator(w, ctxt);
688 }
689
690 /**
691 * Method for constructing JSON generator for writing JSON content
692 * using specified Writer.
693 *<p>
694 * Underlying stream <b>is NOT owned</b> by the generator constructed,
695 * so that generator will NOT close the Reader when
696 * {@link JsonGenerator#close} is called (unless auto-closing
697 * feature,
698 * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled).
699 * Using application needs to close it explicitly.
700 *
701 * @param out Writer to use for writing JSON content
702 */
703 public JsonGenerator createJsonGenerator(Writer out)
704 throws IOException
705 {
706 IOContext ctxt = _createContext(out, false);
707 // [JACKSON-512]: allow wrapping with _outputDecorator
708 if (_outputDecorator != null) {
709 out = _outputDecorator.decorate(ctxt, out);
710 }
711 return _createJsonGenerator(out, ctxt);
712 }
713
714 /**
715 * Convenience method for constructing generator that uses default
716 * encoding of the format (UTF-8 for JSON and most other data formats).
717 *<p>
718 * Note: there are formats that use fixed encoding (like most binary data formats).
719 */
720 public JsonGenerator createJsonGenerator(OutputStream out) throws IOException {
721 return createJsonGenerator(out, JsonEncoding.UTF8);
722 }
723
724 /**
725 * Method for constructing JSON generator for writing JSON content
726 * to specified file, overwriting contents it might have (or creating
727 * it if such file does not yet exist).
728 * Encoding to use must be specified, and needs to be one of available
729 * types (as per JSON specification).
730 *<p>
731 * Underlying stream <b>is owned</b> by the generator constructed,
732 * i.e. generator will handle closing of file when
733 * {@link JsonGenerator#close} is called.
734 *
735 * @param f File to write contents to
736 * @param enc Character encoding to use
737 */
738 public JsonGenerator createJsonGenerator(File f, JsonEncoding enc)
739 throws IOException
740 {
741 OutputStream out = new FileOutputStream(f);
742 // true -> yes, we have to manage the stream since we created it
743 IOContext ctxt = _createContext(out, true);
744 ctxt.setEncoding(enc);
745 if (enc == JsonEncoding.UTF8) {
746 // [JACKSON-512]: allow wrapping with _outputDecorator
747 if (_outputDecorator != null) {
748 out = _outputDecorator.decorate(ctxt, out);
749 }
750 return _createUTF8JsonGenerator(out, ctxt);
751 }
752 Writer w = _createWriter(out, enc, ctxt);
753 // [JACKSON-512]: allow wrapping with _outputDecorator
754 if (_outputDecorator != null) {
755 w = _outputDecorator.decorate(ctxt, w);
756 }
757 return _createJsonGenerator(w, ctxt);
758 }
759
760 /*
761 /**********************************************************
762 /* Factory methods used by factory for creating parser instances,
763 /* overridable by sub-classes
764 /**********************************************************
765 */
766
767 /**
768 * Overridable factory method that actually instantiates desired parser
769 * given {@link InputStream} and context object.
770 *<p>
771 * This method is specifically designed to remain
772 * compatible between minor versions so that sub-classes can count
773 * on it being called as expected. That is, it is part of official
774 * interface from sub-class perspective, although not a public
775 * method available to users of factory implementations.
776 */
777 protected JsonParser _createJsonParser(InputStream in, IOContext ctxt)
778 throws IOException, JsonParseException
779 {
Tatu07351902012-01-19 13:12:13 -0800780 // As per [JACKSON-259], may want to fully disable canonicalization:
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800781 return new ByteSourceJsonBootstrapper(ctxt, in).constructParser(_parserFeatures,
Tatu07351902012-01-19 13:12:13 -0800782 _objectCodec, _rootByteSymbols, _rootCharSymbols,
783 isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES),
784 isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES));
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800785 }
786
787 /**
788 * Overridable factory method that actually instantiates parser
789 * using given {@link Reader} object for reading content.
790 *<p>
791 * This method is specifically designed to remain
792 * compatible between minor versions so that sub-classes can count
793 * on it being called as expected. That is, it is part of official
794 * interface from sub-class perspective, although not a public
795 * method available to users of factory implementations.
796 */
797 protected JsonParser _createJsonParser(Reader r, IOContext ctxt)
798 throws IOException, JsonParseException
799 {
800 return new ReaderBasedJsonParser(ctxt, _parserFeatures, r, _objectCodec,
Tatu07351902012-01-19 13:12:13 -0800801 _rootCharSymbols.makeChild(isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES),
802 isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES)));
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800803 }
804
805 /**
806 * Overridable factory method that actually instantiates parser
807 * using given {@link Reader} object for reading content
808 * passed as raw byte array.
809 *<p>
810 * This method is specifically designed to remain
811 * compatible between minor versions so that sub-classes can count
812 * on it being called as expected. That is, it is part of official
813 * interface from sub-class perspective, although not a public
814 * method available to users of factory implementations.
815 */
816 protected JsonParser _createJsonParser(byte[] data, int offset, int len, IOContext ctxt)
817 throws IOException, JsonParseException
818 {
819 return new ByteSourceJsonBootstrapper(ctxt, data, offset, len).constructParser(_parserFeatures,
Tatu07351902012-01-19 13:12:13 -0800820 _objectCodec, _rootByteSymbols, _rootCharSymbols,
821 isEnabled(JsonFactory.Feature.CANONICALIZE_FIELD_NAMES),
822 isEnabled(JsonFactory.Feature.INTERN_FIELD_NAMES));
Tatu Salorantaf15531c2011-12-22 23:00:40 -0800823 }
824
825 /*
826 /**********************************************************
827 /* Factory methods used by factory for creating generator instances,
828 /* overridable by sub-classes
829 /**********************************************************
830 */
831
832 /**
833 * Overridable factory method that actually instantiates generator for
834 * given {@link Writer} and context object.
835 *<p>
836 * This method is specifically designed to remain
837 * compatible between minor versions so that sub-classes can count
838 * on it being called as expected. That is, it is part of official
839 * interface from sub-class perspective, although not a public
840 * method available to users of factory implementations.
841 */
842 protected JsonGenerator _createJsonGenerator(Writer out, IOContext ctxt)
843 throws IOException
844 {
845 WriterBasedJsonGenerator gen = new WriterBasedJsonGenerator(ctxt, _generatorFeatures, _objectCodec, out);
846 if (_characterEscapes != null) {
847 gen.setCharacterEscapes(_characterEscapes);
848 }
849 return gen;
850 }
851
852 /**
853 * Overridable factory method that actually instantiates generator for
854 * given {@link OutputStream} and context object, using UTF-8 encoding.
855 *<p>
856 * This method is specifically designed to remain
857 * compatible between minor versions so that sub-classes can count
858 * on it being called as expected. That is, it is part of official
859 * interface from sub-class perspective, although not a public
860 * method available to users of factory implementations.
861 */
862 protected JsonGenerator _createUTF8JsonGenerator(OutputStream out, IOContext ctxt)
863 throws IOException
864 {
865 UTF8JsonGenerator gen = new UTF8JsonGenerator(ctxt, _generatorFeatures, _objectCodec, out);
866 if (_characterEscapes != null) {
867 gen.setCharacterEscapes(_characterEscapes);
868 }
869 return gen;
870 }
871
872 protected Writer _createWriter(OutputStream out, JsonEncoding enc, IOContext ctxt) throws IOException
873 {
874 // note: this should not get called any more (caller checks, dispatches)
875 if (enc == JsonEncoding.UTF8) { // We have optimized writer for UTF-8
876 return new UTF8Writer(ctxt, out);
877 }
878 // not optimal, but should do unless we really care about UTF-16/32 encoding speed
879 return new OutputStreamWriter(out, enc.getJavaName());
880 }
881
882 /*
883 /**********************************************************
884 /* Internal factory methods, other
885 /**********************************************************
886 */
887
888 /**
889 * Overridable factory method that actually instantiates desired
890 * context object.
891 */
892 protected IOContext _createContext(Object srcRef, boolean resourceManaged)
893 {
894 return new IOContext(_getBufferRecycler(), srcRef, resourceManaged);
895 }
896
897 /**
898 * Method used by factory to create buffer recycler instances
899 * for parsers and generators.
900 *<p>
901 * Note: only public to give access for <code>ObjectMapper</code>
902 */
903 public BufferRecycler _getBufferRecycler()
904 {
905 SoftReference<BufferRecycler> ref = _recyclerRef.get();
906 BufferRecycler br = (ref == null) ? null : ref.get();
907
908 if (br == null) {
909 br = new BufferRecycler();
910 _recyclerRef.set(new SoftReference<BufferRecycler>(br));
911 }
912 return br;
913 }
914
915 /**
916 * Helper methods used for constructing an optimal stream for
917 * parsers to use, when input is to be read from an URL.
918 * This helps when reading file content via URL.
919 */
920 protected InputStream _optimizedStreamFromURL(URL url)
921 throws IOException
922 {
923 if ("file".equals(url.getProtocol())) {
924 /* Can not do this if the path refers
925 * to a network drive on windows. This fixes the problem;
926 * might not be needed on all platforms (NFS?), but should not
927 * matter a lot: performance penalty of extra wrapping is more
928 * relevant when accessing local file system.
929 */
930 String host = url.getHost();
931 if (host == null || host.length() == 0) {
932 return new FileInputStream(url.getPath());
933 }
934 }
935 return url.openStream();
936 }
937}