• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.core.io;
2 
3 import com.fasterxml.jackson.core.JsonEncoding;
4 import com.fasterxml.jackson.core.util.BufferRecycler;
5 import com.fasterxml.jackson.core.util.TextBuffer;
6 
7 /**
8  * To limit number of configuration and state objects to pass, all
9  * contextual objects that need to be passed by the factory to
10  * readers and writers are combined under this object. One instance
11  * is created for each reader and writer.
12  *<p>
13  * NOTE: non-final since 2.4, to allow sub-classing.
14  */
15 public class IOContext
16 {
17     /*
18     /**********************************************************
19     /* Configuration
20     /**********************************************************
21      */
22 
23     /**
24      * Reference to the source object, which can be used for displaying
25      * location information
26      */
27     protected final Object _sourceRef;
28 
29     /**
30      * Encoding used by the underlying stream, if known.
31      */
32     protected JsonEncoding _encoding;
33 
34     /**
35      * Flag that indicates whether underlying input/output source/target
36      * object is fully managed by the owner of this context (parser or
37      * generator). If true, it is, and is to be closed by parser/generator;
38      * if false, calling application has to do closing (unless auto-closing
39      * feature is enabled for the parser/generator in question; in which
40      * case it acts like the owner).
41      */
42     protected final boolean _managedResource;
43 
44     /*
45     /**********************************************************
46     /* Buffer handling, recycling
47     /**********************************************************
48      */
49 
50     /**
51      * Recycler used for actual allocation/deallocation/reuse
52      */
53     protected final BufferRecycler _bufferRecycler;
54 
55     /**
56      * Reference to the allocated I/O buffer for low-level input reading,
57      * if any allocated.
58      */
59     protected byte[] _readIOBuffer;
60 
61     /**
62      * Reference to the allocated I/O buffer used for low-level
63      * encoding-related buffering.
64      */
65     protected byte[] _writeEncodingBuffer;
66 
67     /**
68      * Reference to the buffer allocated for temporary use with
69      * base64 encoding or decoding.
70      */
71     protected byte[] _base64Buffer;
72 
73     /**
74      * Reference to the buffer allocated for tokenization purposes,
75      * in which character input is read, and from which it can be
76      * further returned.
77      */
78     protected char[] _tokenCBuffer;
79 
80     /**
81      * Reference to the buffer allocated for buffering it for
82      * output, before being encoded: generally this means concatenating
83      * output, then encoding when buffer fills up.
84      */
85     protected char[] _concatCBuffer;
86 
87     /**
88      * Reference temporary buffer Parser instances need if calling
89      * app decides it wants to access name via 'getTextCharacters' method.
90      * Regular text buffer can not be used as it may contain textual
91      * representation of the value token.
92      */
93     protected char[] _nameCopyBuffer;
94 
95     /*
96     /**********************************************************
97     /* Life-cycle
98     /**********************************************************
99      */
100 
IOContext(BufferRecycler br, Object sourceRef, boolean managedResource)101     public IOContext(BufferRecycler br, Object sourceRef, boolean managedResource)
102     {
103         _bufferRecycler = br;
104         _sourceRef = sourceRef;
105         _managedResource = managedResource;
106     }
107 
setEncoding(JsonEncoding enc)108     public void setEncoding(JsonEncoding enc) {
109         _encoding = enc;
110     }
111 
112     /**
113      * @since 1.6
114      */
withEncoding(JsonEncoding enc)115     public IOContext withEncoding(JsonEncoding enc) {
116         _encoding = enc;
117         return this;
118     }
119 
120     /*
121     /**********************************************************
122     /* Public API, accessors
123     /**********************************************************
124      */
125 
getSourceReference()126     public Object getSourceReference() { return _sourceRef; }
getEncoding()127     public JsonEncoding getEncoding() { return _encoding; }
isResourceManaged()128     public boolean isResourceManaged() { return _managedResource; }
129 
130     /*
131     /**********************************************************
132     /* Public API, buffer management
133     /**********************************************************
134      */
135 
constructTextBuffer()136     public TextBuffer constructTextBuffer() {
137         return new TextBuffer(_bufferRecycler);
138     }
139 
140     /**
141      *<p>
142      * Note: the method can only be called once during its life cycle.
143      * This is to protect against accidental sharing.
144      */
allocReadIOBuffer()145     public byte[] allocReadIOBuffer() {
146         _verifyAlloc(_readIOBuffer);
147         return (_readIOBuffer = _bufferRecycler.allocByteBuffer(BufferRecycler.BYTE_READ_IO_BUFFER));
148     }
149 
150     /**
151      * @since 2.4
152      */
allocReadIOBuffer(int minSize)153     public byte[] allocReadIOBuffer(int minSize) {
154         _verifyAlloc(_readIOBuffer);
155         return (_readIOBuffer = _bufferRecycler.allocByteBuffer(BufferRecycler.BYTE_READ_IO_BUFFER, minSize));
156     }
157 
allocWriteEncodingBuffer()158     public byte[] allocWriteEncodingBuffer() {
159         _verifyAlloc(_writeEncodingBuffer);
160         return (_writeEncodingBuffer = _bufferRecycler.allocByteBuffer(BufferRecycler.BYTE_WRITE_ENCODING_BUFFER));
161     }
162 
163     /**
164      * @since 2.4
165      */
allocWriteEncodingBuffer(int minSize)166     public byte[] allocWriteEncodingBuffer(int minSize) {
167         _verifyAlloc(_writeEncodingBuffer);
168         return (_writeEncodingBuffer = _bufferRecycler.allocByteBuffer(BufferRecycler.BYTE_WRITE_ENCODING_BUFFER, minSize));
169     }
170 
171     /**
172      * @since 2.1
173      */
allocBase64Buffer()174     public byte[] allocBase64Buffer() {
175         _verifyAlloc(_base64Buffer);
176         return (_base64Buffer = _bufferRecycler.allocByteBuffer(BufferRecycler.BYTE_BASE64_CODEC_BUFFER));
177     }
178 
179     /**
180      * @since 2.9
181      */
allocBase64Buffer(int minSize)182     public byte[] allocBase64Buffer(int minSize) {
183         _verifyAlloc(_base64Buffer);
184         return (_base64Buffer = _bufferRecycler.allocByteBuffer(BufferRecycler.BYTE_BASE64_CODEC_BUFFER, minSize));
185     }
186 
allocTokenBuffer()187     public char[] allocTokenBuffer() {
188         _verifyAlloc(_tokenCBuffer);
189         return (_tokenCBuffer = _bufferRecycler.allocCharBuffer(BufferRecycler.CHAR_TOKEN_BUFFER));
190     }
191 
192     /**
193      * @since 2.4
194      */
allocTokenBuffer(int minSize)195     public char[] allocTokenBuffer(int minSize) {
196         _verifyAlloc(_tokenCBuffer);
197         return (_tokenCBuffer = _bufferRecycler.allocCharBuffer(BufferRecycler.CHAR_TOKEN_BUFFER, minSize));
198     }
199 
allocConcatBuffer()200     public char[] allocConcatBuffer() {
201         _verifyAlloc(_concatCBuffer);
202         return (_concatCBuffer = _bufferRecycler.allocCharBuffer(BufferRecycler.CHAR_CONCAT_BUFFER));
203     }
204 
allocNameCopyBuffer(int minSize)205     public char[] allocNameCopyBuffer(int minSize) {
206         _verifyAlloc(_nameCopyBuffer);
207         return (_nameCopyBuffer = _bufferRecycler.allocCharBuffer(BufferRecycler.CHAR_NAME_COPY_BUFFER, minSize));
208     }
209 
210     /**
211      * Method to call when all the processing buffers can be safely
212      * recycled.
213      */
releaseReadIOBuffer(byte[] buf)214     public void releaseReadIOBuffer(byte[] buf) {
215         if (buf != null) {
216             /* Let's do sanity checks to ensure once-and-only-once release,
217              * as well as avoiding trying to release buffers not owned
218              */
219             _verifyRelease(buf, _readIOBuffer);
220             _readIOBuffer = null;
221             _bufferRecycler.releaseByteBuffer(BufferRecycler.BYTE_READ_IO_BUFFER, buf);
222         }
223     }
224 
releaseWriteEncodingBuffer(byte[] buf)225     public void releaseWriteEncodingBuffer(byte[] buf) {
226         if (buf != null) {
227             /* Let's do sanity checks to ensure once-and-only-once release,
228              * as well as avoiding trying to release buffers not owned
229              */
230             _verifyRelease(buf, _writeEncodingBuffer);
231             _writeEncodingBuffer = null;
232             _bufferRecycler.releaseByteBuffer(BufferRecycler.BYTE_WRITE_ENCODING_BUFFER, buf);
233         }
234     }
235 
releaseBase64Buffer(byte[] buf)236     public void releaseBase64Buffer(byte[] buf) {
237         if (buf != null) { // sanity checks, release once-and-only-once, must be one owned
238             _verifyRelease(buf, _base64Buffer);
239             _base64Buffer = null;
240             _bufferRecycler.releaseByteBuffer(BufferRecycler.BYTE_BASE64_CODEC_BUFFER, buf);
241         }
242     }
243 
releaseTokenBuffer(char[] buf)244     public void releaseTokenBuffer(char[] buf) {
245         if (buf != null) {
246             _verifyRelease(buf, _tokenCBuffer);
247             _tokenCBuffer = null;
248             _bufferRecycler.releaseCharBuffer(BufferRecycler.CHAR_TOKEN_BUFFER, buf);
249         }
250     }
251 
releaseConcatBuffer(char[] buf)252     public void releaseConcatBuffer(char[] buf) {
253         if (buf != null) {
254             // 14-Jan-2014, tatu: Let's actually allow upgrade of the original buffer.
255             _verifyRelease(buf, _concatCBuffer);
256             _concatCBuffer = null;
257             _bufferRecycler.releaseCharBuffer(BufferRecycler.CHAR_CONCAT_BUFFER, buf);
258         }
259     }
260 
releaseNameCopyBuffer(char[] buf)261     public void releaseNameCopyBuffer(char[] buf) {
262         if (buf != null) {
263             // 14-Jan-2014, tatu: Let's actually allow upgrade of the original buffer.
264             _verifyRelease(buf, _nameCopyBuffer);
265             _nameCopyBuffer = null;
266             _bufferRecycler.releaseCharBuffer(BufferRecycler.CHAR_NAME_COPY_BUFFER, buf);
267         }
268     }
269 
270     /*
271     /**********************************************************
272     /* Internal helpers
273     /**********************************************************
274      */
275 
_verifyAlloc(Object buffer)276     protected final void _verifyAlloc(Object buffer) {
277         if (buffer != null) { throw new IllegalStateException("Trying to call same allocXxx() method second time"); }
278     }
279 
_verifyRelease(byte[] toRelease, byte[] src)280     protected final void _verifyRelease(byte[] toRelease, byte[] src) {
281         // 07-Mar-2016, tatu: As per [core#255], only prevent shrinking of buffer
282         if ((toRelease != src) && (toRelease.length < src.length)) { throw wrongBuf(); }
283     }
284 
_verifyRelease(char[] toRelease, char[] src)285     protected final void _verifyRelease(char[] toRelease, char[] src) {
286         // 07-Mar-2016, tatu: As per [core#255], only prevent shrinking of buffer
287         if ((toRelease != src) && (toRelease.length < src.length)) { throw wrongBuf(); }
288     }
289 
wrongBuf()290     private IllegalArgumentException wrongBuf() {
291         // sanity check failed; trying to return different, smaller buffer.
292         return new IllegalArgumentException("Trying to release buffer smaller than original");
293     }
294 }
295