Check in actual sources, moved to the new package, cleaned up a bit
diff --git a/src/main/java/com/fasterxml/jackson/core/JsonFactory.java b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java
new file mode 100644
index 0000000..4ad28ca
--- /dev/null
+++ b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java
@@ -0,0 +1,831 @@
+/* Jackson JSON-processor.
+ *
+ * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi
+ *
+ * Licensed under the License specified in file LICENSE, included with
+ * the source code and binary code bundles.
+ * You may not use this file except in compliance with the License.
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.fasterxml.jackson.core;
+
+import java.io.*;
+import java.lang.ref.SoftReference;
+import java.net.URL;
+
+import com.fasterxml.jackson.core.format.InputAccessor;
+import com.fasterxml.jackson.core.format.MatchStrength;
+import com.fasterxml.jackson.core.io.*;
+import com.fasterxml.jackson.core.json.ByteSourceJsonBootstrapper;
+import com.fasterxml.jackson.core.json.ReaderBasedJsonParser;
+import com.fasterxml.jackson.core.json.UTF8JsonGenerator;
+import com.fasterxml.jackson.core.json.WriterBasedJsonGenerator;
+import com.fasterxml.jackson.core.sym.BytesToNameCanonicalizer;
+import com.fasterxml.jackson.core.sym.CharsToNameCanonicalizer;
+import com.fasterxml.jackson.core.util.BufferRecycler;
+import com.fasterxml.jackson.core.util.VersionUtil;
+
+/**
+ * The main factory class of Jackson package, used to configure and
+ * construct reader (aka parser, {@link JsonParser})
+ * and writer (aka generator, {@link JsonGenerator})
+ * instances.
+ *<p>
+ * Factory instances are thread-safe and reusable after configuration
+ * (if any). Typically applications and services use only a single
+ * globally shared factory instance, unless they need differently
+ * configured factories. Factory reuse is important if efficiency matters;
+ * most recycling of expensive construct is done on per-factory basis.
+ *<p>
+ * Creation of a factory instance is a light-weight operation,
+ * and since there is no need for pluggable alternative implementations
+ * (as there is no "standard" JSON processor API to implement),
+ * the default constructor is used for constructing factory
+ * instances.
+ *
+ * @author Tatu Saloranta
+ */
+public class JsonFactory implements Versioned
+{
+ /**
+ * Name used to identify JSON format
+ * (and returned by {@link #getFormatName()}
+ */
+ public final static String FORMAT_NAME_JSON = "JSON";
+
+ /**
+ * Bitfield (set of flags) of all parser features that are enabled
+ * by default.
+ */
+ final static int DEFAULT_PARSER_FEATURE_FLAGS = JsonParser.Feature.collectDefaults();
+
+ /**
+ * Bitfield (set of flags) of all generator features that are enabled
+ * by default.
+ */
+ final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults();
+
+ /*
+ /**********************************************************
+ /* Buffer, symbol table management
+ /**********************************************************
+ */
+
+ /**
+ * This <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftRerefence}
+ * to a {@link BufferRecycler} used to provide a low-cost
+ * buffer recycling between reader and writer instances.
+ */
+ final protected static ThreadLocal<SoftReference<BufferRecycler>> _recyclerRef
+ = new ThreadLocal<SoftReference<BufferRecycler>>();
+
+ /**
+ * Each factory comes equipped with a shared root symbol table.
+ * It should not be linked back to the original blueprint, to
+ * avoid contents from leaking between factories.
+ */
+ protected CharsToNameCanonicalizer _rootCharSymbols = CharsToNameCanonicalizer.createRoot();
+
+ /**
+ * Alternative to the basic symbol table, some stream-based
+ * parsers use different name canonicalization method.
+ *<p>
+ * TODO: should clean up this; looks messy having 2 alternatives
+ * with not very clear differences.
+ */
+ protected BytesToNameCanonicalizer _rootByteSymbols = BytesToNameCanonicalizer.createRoot();
+
+ /*
+ /**********************************************************
+ /* Configuration
+ /**********************************************************
+ */
+
+ /**
+ * Object that implements conversion functionality between
+ * Java objects and JSON content. For base JsonFactory implementation
+ * usually not set by default, but can be explicitly set.
+ * Sub-classes (like @link org.codehaus.jackson.map.MappingJsonFactory}
+ * usually provide an implementation.
+ */
+ protected ObjectCodec _objectCodec;
+
+ /**
+ * Currently enabled parser features.
+ */
+ protected int _parserFeatures = DEFAULT_PARSER_FEATURE_FLAGS;
+
+ /**
+ * Currently enabled generator features.
+ */
+ protected int _generatorFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS;
+
+ /**
+ * Definition of custom character escapes to use for generators created
+ * by this factory, if any. If null, standard data format specific
+ * escapes are used.
+ */
+ protected CharacterEscapes _characterEscapes;
+
+ /**
+ * Optional helper object that may decorate input sources, to do
+ * additional processing on input during parsing.
+ */
+ protected InputDecorator _inputDecorator;
+
+ /**
+ * Optional helper object that may decorate output object, to do
+ * additional processing on output during content generation.
+ */
+ protected OutputDecorator _outputDecorator;
+
+ /*
+ /**********************************************************
+ /* Construction
+ /**********************************************************
+ */
+
+ /**
+ * Default constructor used to create factory instances.
+ * Creation of a factory instance is a light-weight operation,
+ * but it is still a good idea to reuse limited number of
+ * factory instances (and quite often just a single instance):
+ * factories are used as context for storing some reused
+ * processing objects (such as symbol tables parsers use)
+ * and this reuse only works within context of a single
+ * factory instance.
+ */
+ public JsonFactory() { this(null); }
+
+ public JsonFactory(ObjectCodec oc) { _objectCodec = oc; }
+
+ /*
+ /**********************************************************
+ /* Format detection functionality (since 1.8)
+ /**********************************************************
+ */
+
+ /**
+ * Method that returns short textual id identifying format
+ * this factory supports.
+ *<p>
+ * Note: sub-classes should override this method; default
+ * implementation will return null for all sub-classes
+ */
+ public String getFormatName()
+ {
+ /* Somewhat nasty check: since we can't make this abstract
+ * (due to backwards compatibility concerns), need to prevent
+ * format name "leakage"
+ */
+ if (getClass() == JsonFactory.class) {
+ return FORMAT_NAME_JSON;
+ }
+ return null;
+ }
+
+ public MatchStrength hasFormat(InputAccessor acc) throws IOException
+ {
+ // since we can't keep this abstract, only implement for "vanilla" instance
+ if (getClass() == JsonFactory.class) {
+ return hasJSONFormat(acc);
+ }
+ return null;
+ }
+
+ protected MatchStrength hasJSONFormat(InputAccessor acc) throws IOException
+ {
+ return ByteSourceJsonBootstrapper.hasJSONFormat(acc);
+ }
+
+ /*
+ /**********************************************************
+ /* Versioned
+ /**********************************************************
+ */
+
+ @Override
+ public Version version() {
+ // VERSION is included under impl, so can't pass this class:
+ return VersionUtil.versionFor(UTF8JsonGenerator.class);
+ }
+
+ /*
+ /**********************************************************
+ /* Configuration, parser settings
+ /**********************************************************
+ */
+
+ /**
+ * Method for enabling or disabling specified parser feature
+ * (check {@link JsonParser.Feature} for list of features)
+ */
+ public final JsonFactory configure(JsonParser.Feature f, boolean state)
+ {
+ if (state) {
+ enable(f);
+ } else {
+ disable(f);
+ }
+ return this;
+ }
+
+ /**
+ * Method for enabling specified parser feature
+ * (check {@link JsonParser.Feature} for list of features)
+ */
+ public JsonFactory enable(JsonParser.Feature f) {
+ _parserFeatures |= f.getMask();
+ return this;
+ }
+
+ /**
+ * Method for disabling specified parser features
+ * (check {@link JsonParser.Feature} for list of features)
+ */
+ public JsonFactory disable(JsonParser.Feature f) {
+ _parserFeatures &= ~f.getMask();
+ return this;
+ }
+
+ /**
+ * Checked whether specified parser feature is enabled.
+ */
+ public final boolean isEnabled(JsonParser.Feature f) {
+ return (_parserFeatures & f.getMask()) != 0;
+ }
+
+ /**
+ * Method for getting currently configured input decorator (if any;
+ * there is no default decorator).
+ */
+ public InputDecorator getInputDecorator() {
+ return _inputDecorator;
+ }
+
+ /**
+ * Method for overriding currently configured input decorator
+ */
+ public JsonFactory setInputDecorator(InputDecorator d) {
+ _inputDecorator = d;
+ return this;
+ }
+
+ /*
+ /**********************************************************
+ /* Configuration, generator settings
+ /**********************************************************
+ */
+
+ /**
+ * Method for enabling or disabling specified generator feature
+ * (check {@link JsonGenerator.Feature} for list of features)
+ */
+ public final JsonFactory configure(JsonGenerator.Feature f, boolean state) {
+ if (state) {
+ enable(f);
+ } else {
+ disable(f);
+ }
+ return this;
+ }
+
+
+ /**
+ * Method for enabling specified generator features
+ * (check {@link JsonGenerator.Feature} for list of features)
+ */
+ public JsonFactory enable(JsonGenerator.Feature f) {
+ _generatorFeatures |= f.getMask();
+ return this;
+ }
+
+ /**
+ * Method for disabling specified generator feature
+ * (check {@link JsonGenerator.Feature} for list of features)
+ */
+ public JsonFactory disable(JsonGenerator.Feature f) {
+ _generatorFeatures &= ~f.getMask();
+ return this;
+ }
+
+ /**
+ * Check whether specified generator feature is enabled.
+ */
+ public final boolean isEnabled(JsonGenerator.Feature f) {
+ return (_generatorFeatures & f.getMask()) != 0;
+ }
+
+ /**
+ * Method for accessing custom escapes factory uses for {@link JsonGenerator}s
+ * it creates.
+ */
+ public CharacterEscapes getCharacterEscapes() {
+ return _characterEscapes;
+ }
+
+ /**
+ * Method for defining custom escapes factory uses for {@link JsonGenerator}s
+ * it creates.
+ */
+ public JsonFactory setCharacterEscapes(CharacterEscapes esc) {
+ _characterEscapes = esc;
+ return this;
+ }
+
+ /**
+ * Method for getting currently configured output decorator (if any;
+ * there is no default decorator).
+ */
+ public OutputDecorator getOutputDecorator() {
+ return _outputDecorator;
+ }
+
+ /**
+ * Method for overriding currently configured output decorator
+ */
+ public JsonFactory setOutputDecorator(OutputDecorator d) {
+ _outputDecorator = d;
+ return this;
+ }
+
+ /*
+ /**********************************************************
+ /* Configuration, other
+ /**********************************************************
+ */
+
+ /**
+ * Method for associating a {@link ObjectCodec} (typically
+ * a {@link org.codehaus.jackson.map.ObjectMapper}) with
+ * this factory (and more importantly, parsers and generators
+ * it constructs). This is needed to use data-binding methods
+ * of {@link JsonParser} and {@link JsonGenerator} instances.
+ */
+ public JsonFactory setCodec(ObjectCodec oc) {
+ _objectCodec = oc;
+ return this;
+ }
+
+ public ObjectCodec getCodec() { return _objectCodec; }
+
+ /*
+ /**********************************************************
+ /* Reader factories
+ /**********************************************************
+ */
+
+ /**
+ * Method for constructing JSON parser instance to parse
+ * contents of specified file. Encoding is auto-detected
+ * from contents according to JSON specification recommended
+ * mechanism.
+ *<p>
+ * Underlying input stream (needed for reading contents)
+ * will be <b>owned</b> (and managed, i.e. closed as need be) by
+ * the parser, since caller has no access to it.
+ *
+ * @param f File that contains JSON content to parse
+ */
+ public JsonParser createJsonParser(File f)
+ throws IOException, JsonParseException
+ {
+ // true, since we create InputStream from File
+ IOContext ctxt = _createContext(f, true);
+ InputStream in = new FileInputStream(f);
+ // [JACKSON-512]: allow wrapping with InputDecorator
+ if (_inputDecorator != null) {
+ in = _inputDecorator.decorate(ctxt, in);
+ }
+ return _createJsonParser(in, ctxt);
+ }
+
+ /**
+ * Method for constructing JSON parser instance to parse
+ * contents of resource reference by given URL.
+ * Encoding is auto-detected
+ * from contents according to JSON specification recommended
+ * mechanism.
+ *<p>
+ * Underlying input stream (needed for reading contents)
+ * will be <b>owned</b> (and managed, i.e. closed as need be) by
+ * the parser, since caller has no access to it.
+ *
+ * @param url URL pointing to resource that contains JSON content to parse
+ */
+ public JsonParser createJsonParser(URL url)
+ throws IOException, JsonParseException
+ {
+ // true, since we create InputStream from URL
+ IOContext ctxt = _createContext(url, true);
+ InputStream in = _optimizedStreamFromURL(url);
+ // [JACKSON-512]: allow wrapping with InputDecorator
+ if (_inputDecorator != null) {
+ in = _inputDecorator.decorate(ctxt, in);
+ }
+ return _createJsonParser(in, ctxt);
+ }
+
+ /**
+ * Method for constructing JSON parser instance to parse
+ * the contents accessed via specified input stream.
+ *<p>
+ * The input stream will <b>not be owned</b> by
+ * the parser, it will still be managed (i.e. closed if
+ * end-of-stream is reacher, or parser close method called)
+ * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
+ * is enabled.
+ *<p>
+ * Note: no encoding argument is taken since it can always be
+ * auto-detected as suggested by Json RFC.
+ *
+ * @param in InputStream to use for reading JSON content to parse
+ */
+ public JsonParser createJsonParser(InputStream in)
+ throws IOException, JsonParseException
+ {
+ IOContext ctxt = _createContext(in, false);
+ // [JACKSON-512]: allow wrapping with InputDecorator
+ if (_inputDecorator != null) {
+ in = _inputDecorator.decorate(ctxt, in);
+ }
+ return _createJsonParser(in, ctxt);
+ }
+
+ /**
+ * Method for constructing parser for parsing
+ * the contents accessed via specified Reader.
+ <p>
+ * The read stream will <b>not be owned</b> by
+ * the parser, it will still be managed (i.e. closed if
+ * end-of-stream is reacher, or parser close method called)
+ * if (and only if) {@link com.fasterxml.jackson.core.JsonParser.Feature#AUTO_CLOSE_SOURCE}
+ * is enabled.
+ *<p>
+ *
+ * @param r Reader to use for reading JSON content to parse
+ */
+ public JsonParser createJsonParser(Reader r)
+ throws IOException, JsonParseException
+ {
+ // false -> we do NOT own Reader (did not create it)
+ IOContext ctxt = _createContext(r, false);
+ // [JACKSON-512]: allow wrapping with InputDecorator
+ if (_inputDecorator != null) {
+ r = _inputDecorator.decorate(ctxt, r);
+ }
+ return _createJsonParser(r, ctxt);
+ }
+
+ /**
+ * Method for constructing parser for parsing
+ * the contents of given byte array.
+ */
+ public JsonParser createJsonParser(byte[] data)
+ throws IOException, JsonParseException
+ {
+ IOContext ctxt = _createContext(data, true);
+ // [JACKSON-512]: allow wrapping with InputDecorator
+ if (_inputDecorator != null) {
+ InputStream in = _inputDecorator.decorate(ctxt, data, 0, data.length);
+ if (in != null) {
+ return _createJsonParser(in, ctxt);
+ }
+ }
+ return _createJsonParser(data, 0, data.length, ctxt);
+ }
+
+ /**
+ * Method for constructing parser for parsing
+ * the contents of given byte array.
+ *
+ * @param data Buffer that contains data to parse
+ * @param offset Offset of the first data byte within buffer
+ * @param len Length of contents to parse within buffer
+ */
+ public JsonParser createJsonParser(byte[] data, int offset, int len)
+ throws IOException, JsonParseException
+ {
+ IOContext ctxt = _createContext(data, true);
+ // [JACKSON-512]: allow wrapping with InputDecorator
+ if (_inputDecorator != null) {
+ InputStream in = _inputDecorator.decorate(ctxt, data, offset, len);
+ if (in != null) {
+ return _createJsonParser(in, ctxt);
+ }
+ }
+ return _createJsonParser(data, offset, len, ctxt);
+ }
+
+ /**
+ * Method for constructing parser for parsing
+ * contents of given String.
+ */
+ public JsonParser createJsonParser(String content)
+ throws IOException, JsonParseException
+ {
+ Reader r = new StringReader(content);
+ // true -> we own the Reader (and must close); not a big deal
+ IOContext ctxt = _createContext(r, true);
+ // [JACKSON-512]: allow wrapping with InputDecorator
+ if (_inputDecorator != null) {
+ r = _inputDecorator.decorate(ctxt, r);
+ }
+ return _createJsonParser(r, ctxt);
+ }
+
+ /*
+ /**********************************************************
+ /* Generator factories
+ /**********************************************************
+ */
+
+ /**
+ * Method for constructing JSON generator for writing JSON content
+ * using specified output stream.
+ * Encoding to use must be specified, and needs to be one of available
+ * types (as per JSON specification).
+ *<p>
+ * Underlying stream <b>is NOT owned</b> by the generator constructed,
+ * so that generator will NOT close the output stream when
+ * {@link JsonGenerator#close} is called (unless auto-closing
+ * feature,
+ * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET}
+ * is enabled).
+ * Using application needs to close it explicitly if this is the case.
+ *<p>
+ * Note: there are formats that use fixed encoding (like most binary data formats)
+ * and that ignore passed in encoding.
+ *
+ * @param out OutputStream to use for writing JSON content
+ * @param enc Character encoding to use
+ */
+ public JsonGenerator createJsonGenerator(OutputStream out, JsonEncoding enc)
+ throws IOException
+ {
+ // false -> we won't manage the stream unless explicitly directed to
+ IOContext ctxt = _createContext(out, false);
+ ctxt.setEncoding(enc);
+ if (enc == JsonEncoding.UTF8) {
+ // [JACKSON-512]: allow wrapping with _outputDecorator
+ if (_outputDecorator != null) {
+ out = _outputDecorator.decorate(ctxt, out);
+ }
+ return _createUTF8JsonGenerator(out, ctxt);
+ }
+ Writer w = _createWriter(out, enc, ctxt);
+ // [JACKSON-512]: allow wrapping with _outputDecorator
+ if (_outputDecorator != null) {
+ w = _outputDecorator.decorate(ctxt, w);
+ }
+ return _createJsonGenerator(w, ctxt);
+ }
+
+ /**
+ * Method for constructing JSON generator for writing JSON content
+ * using specified Writer.
+ *<p>
+ * Underlying stream <b>is NOT owned</b> by the generator constructed,
+ * so that generator will NOT close the Reader when
+ * {@link JsonGenerator#close} is called (unless auto-closing
+ * feature,
+ * {@link com.fasterxml.jackson.core.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled).
+ * Using application needs to close it explicitly.
+ *
+ * @param out Writer to use for writing JSON content
+ */
+ public JsonGenerator createJsonGenerator(Writer out)
+ throws IOException
+ {
+ IOContext ctxt = _createContext(out, false);
+ // [JACKSON-512]: allow wrapping with _outputDecorator
+ if (_outputDecorator != null) {
+ out = _outputDecorator.decorate(ctxt, out);
+ }
+ return _createJsonGenerator(out, ctxt);
+ }
+
+ /**
+ * Convenience method for constructing generator that uses default
+ * encoding of the format (UTF-8 for JSON and most other data formats).
+ *<p>
+ * Note: there are formats that use fixed encoding (like most binary data formats).
+ */
+ public JsonGenerator createJsonGenerator(OutputStream out) throws IOException {
+ return createJsonGenerator(out, JsonEncoding.UTF8);
+ }
+
+ /**
+ * Method for constructing JSON generator for writing JSON content
+ * to specified file, overwriting contents it might have (or creating
+ * it if such file does not yet exist).
+ * Encoding to use must be specified, and needs to be one of available
+ * types (as per JSON specification).
+ *<p>
+ * Underlying stream <b>is owned</b> by the generator constructed,
+ * i.e. generator will handle closing of file when
+ * {@link JsonGenerator#close} is called.
+ *
+ * @param f File to write contents to
+ * @param enc Character encoding to use
+ */
+ public JsonGenerator createJsonGenerator(File f, JsonEncoding enc)
+ throws IOException
+ {
+ OutputStream out = new FileOutputStream(f);
+ // true -> yes, we have to manage the stream since we created it
+ IOContext ctxt = _createContext(out, true);
+ ctxt.setEncoding(enc);
+ if (enc == JsonEncoding.UTF8) {
+ // [JACKSON-512]: allow wrapping with _outputDecorator
+ if (_outputDecorator != null) {
+ out = _outputDecorator.decorate(ctxt, out);
+ }
+ return _createUTF8JsonGenerator(out, ctxt);
+ }
+ Writer w = _createWriter(out, enc, ctxt);
+ // [JACKSON-512]: allow wrapping with _outputDecorator
+ if (_outputDecorator != null) {
+ w = _outputDecorator.decorate(ctxt, w);
+ }
+ return _createJsonGenerator(w, ctxt);
+ }
+
+ /*
+ /**********************************************************
+ /* Factory methods used by factory for creating parser instances,
+ /* overridable by sub-classes
+ /**********************************************************
+ */
+
+ /**
+ * Overridable factory method that actually instantiates desired parser
+ * given {@link InputStream} and context object.
+ *<p>
+ * This method is specifically designed to remain
+ * compatible between minor versions so that sub-classes can count
+ * on it being called as expected. That is, it is part of official
+ * interface from sub-class perspective, although not a public
+ * method available to users of factory implementations.
+ */
+ protected JsonParser _createJsonParser(InputStream in, IOContext ctxt)
+ throws IOException, JsonParseException
+ {
+ return new ByteSourceJsonBootstrapper(ctxt, in).constructParser(_parserFeatures,
+ _objectCodec, _rootByteSymbols, _rootCharSymbols);
+ }
+
+ /**
+ * Overridable factory method that actually instantiates parser
+ * using given {@link Reader} object for reading content.
+ *<p>
+ * This method is specifically designed to remain
+ * compatible between minor versions so that sub-classes can count
+ * on it being called as expected. That is, it is part of official
+ * interface from sub-class perspective, although not a public
+ * method available to users of factory implementations.
+ */
+ protected JsonParser _createJsonParser(Reader r, IOContext ctxt)
+ throws IOException, JsonParseException
+ {
+ return new ReaderBasedJsonParser(ctxt, _parserFeatures, r, _objectCodec,
+ _rootCharSymbols.makeChild(isEnabled(JsonParser.Feature.CANONICALIZE_FIELD_NAMES),
+ isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)));
+ }
+
+ /**
+ * Overridable factory method that actually instantiates parser
+ * using given {@link Reader} object for reading content
+ * passed as raw byte array.
+ *<p>
+ * This method is specifically designed to remain
+ * compatible between minor versions so that sub-classes can count
+ * on it being called as expected. That is, it is part of official
+ * interface from sub-class perspective, although not a public
+ * method available to users of factory implementations.
+ */
+ protected JsonParser _createJsonParser(byte[] data, int offset, int len, IOContext ctxt)
+ throws IOException, JsonParseException
+ {
+ return new ByteSourceJsonBootstrapper(ctxt, data, offset, len).constructParser(_parserFeatures,
+ _objectCodec, _rootByteSymbols, _rootCharSymbols);
+ }
+
+ /*
+ /**********************************************************
+ /* Factory methods used by factory for creating generator instances,
+ /* overridable by sub-classes
+ /**********************************************************
+ */
+
+ /**
+ * Overridable factory method that actually instantiates generator for
+ * given {@link Writer} and context object.
+ *<p>
+ * This method is specifically designed to remain
+ * compatible between minor versions so that sub-classes can count
+ * on it being called as expected. That is, it is part of official
+ * interface from sub-class perspective, although not a public
+ * method available to users of factory implementations.
+ */
+ protected JsonGenerator _createJsonGenerator(Writer out, IOContext ctxt)
+ throws IOException
+ {
+ WriterBasedJsonGenerator gen = new WriterBasedJsonGenerator(ctxt, _generatorFeatures, _objectCodec, out);
+ if (_characterEscapes != null) {
+ gen.setCharacterEscapes(_characterEscapes);
+ }
+ return gen;
+ }
+
+ /**
+ * Overridable factory method that actually instantiates generator for
+ * given {@link OutputStream} and context object, using UTF-8 encoding.
+ *<p>
+ * This method is specifically designed to remain
+ * compatible between minor versions so that sub-classes can count
+ * on it being called as expected. That is, it is part of official
+ * interface from sub-class perspective, although not a public
+ * method available to users of factory implementations.
+ */
+ protected JsonGenerator _createUTF8JsonGenerator(OutputStream out, IOContext ctxt)
+ throws IOException
+ {
+ UTF8JsonGenerator gen = new UTF8JsonGenerator(ctxt, _generatorFeatures, _objectCodec, out);
+ if (_characterEscapes != null) {
+ gen.setCharacterEscapes(_characterEscapes);
+ }
+ return gen;
+ }
+
+ protected Writer _createWriter(OutputStream out, JsonEncoding enc, IOContext ctxt) throws IOException
+ {
+ // note: this should not get called any more (caller checks, dispatches)
+ if (enc == JsonEncoding.UTF8) { // We have optimized writer for UTF-8
+ return new UTF8Writer(ctxt, out);
+ }
+ // not optimal, but should do unless we really care about UTF-16/32 encoding speed
+ return new OutputStreamWriter(out, enc.getJavaName());
+ }
+
+ /*
+ /**********************************************************
+ /* Internal factory methods, other
+ /**********************************************************
+ */
+
+ /**
+ * Overridable factory method that actually instantiates desired
+ * context object.
+ */
+ protected IOContext _createContext(Object srcRef, boolean resourceManaged)
+ {
+ return new IOContext(_getBufferRecycler(), srcRef, resourceManaged);
+ }
+
+ /**
+ * Method used by factory to create buffer recycler instances
+ * for parsers and generators.
+ *<p>
+ * Note: only public to give access for <code>ObjectMapper</code>
+ */
+ public BufferRecycler _getBufferRecycler()
+ {
+ SoftReference<BufferRecycler> ref = _recyclerRef.get();
+ BufferRecycler br = (ref == null) ? null : ref.get();
+
+ if (br == null) {
+ br = new BufferRecycler();
+ _recyclerRef.set(new SoftReference<BufferRecycler>(br));
+ }
+ return br;
+ }
+
+ /**
+ * Helper methods used for constructing an optimal stream for
+ * parsers to use, when input is to be read from an URL.
+ * This helps when reading file content via URL.
+ */
+ protected InputStream _optimizedStreamFromURL(URL url)
+ throws IOException
+ {
+ if ("file".equals(url.getProtocol())) {
+ /* Can not do this if the path refers
+ * to a network drive on windows. This fixes the problem;
+ * might not be needed on all platforms (NFS?), but should not
+ * matter a lot: performance penalty of extra wrapping is more
+ * relevant when accessing local file system.
+ */
+ String host = url.getHost();
+ if (host == null || host.length() == 0) {
+ return new FileInputStream(url.getPath());
+ }
+ }
+ return url.openStream();
+ }
+}