Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
BsonOutputStream |
|
| 1.4545454545454546;1.455 |
1 | /* | |
2 | * #%L | |
3 | * BsonOutputStream.java - mongodb-async-driver - Allanbank Consulting, Inc. | |
4 | * %% | |
5 | * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc. | |
6 | * %% | |
7 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
8 | * you may not use this file except in compliance with the License. | |
9 | * You may obtain a copy of the License at | |
10 | * | |
11 | * http://www.apache.org/licenses/LICENSE-2.0 | |
12 | * | |
13 | * Unless required by applicable law or agreed to in writing, software | |
14 | * distributed under the License is distributed on an "AS IS" BASIS, | |
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
16 | * See the License for the specific language governing permissions and | |
17 | * limitations under the License. | |
18 | * #L% | |
19 | */ | |
20 | package com.allanbank.mongodb.bson.io; | |
21 | ||
22 | import java.io.IOException; | |
23 | import java.io.OutputStream; | |
24 | import java.nio.charset.Charset; | |
25 | ||
26 | import com.allanbank.mongodb.bson.Document; | |
27 | ||
28 | /** | |
29 | * A wrapper for an {@link OutputStream} to handle writing BSON primitives. | |
30 | * | |
31 | * @api.yes This class is part of the driver's API. Public and protected members | |
32 | * will be deprecated for at least 1 non-bugfix release (version | |
33 | * numbers are <major>.<minor>.<bugfix>) before being | |
34 | * removed or modified. | |
35 | * @copyright 2011-2013, Allanbank Consulting, Inc., All Rights Reserved | |
36 | */ | |
37 | public class BsonOutputStream { | |
38 | ||
39 | /** UTF-8 Character set for encoding strings. */ | |
40 | 1 | public final static Charset UTF8 = StringDecoder.UTF8; |
41 | ||
42 | /** Any thrown exceptions. */ | |
43 | protected IOException myError; | |
44 | ||
45 | /** Output buffer for spooling the written document. */ | |
46 | protected final OutputStream myOutput; | |
47 | ||
48 | /** The encoder for strings. */ | |
49 | protected final StringEncoder myStringEncoder; | |
50 | ||
51 | /** The visitor for writing BSON documents. */ | |
52 | protected final WriteVisitor myWriteVisitor; | |
53 | ||
54 | /** | |
55 | * Creates a new {@link BsonOutputStream}. | |
56 | * | |
57 | * @param output | |
58 | * The underlying Stream to write to. | |
59 | */ | |
60 | public BsonOutputStream(final OutputStream output) { | |
61 | 3328 | this(output, new StringEncoderCache()); |
62 | 3328 | } |
63 | ||
64 | /** | |
65 | * Creates a new {@link BsonOutputStream}. | |
66 | * | |
67 | * @param output | |
68 | * The underlying Stream to write to. | |
69 | * @param cache | |
70 | * The cache for encoding string. | |
71 | */ | |
72 | public BsonOutputStream(final OutputStream output, | |
73 | 3328 | final StringEncoderCache cache) { |
74 | 3328 | myOutput = output; |
75 | 3328 | myStringEncoder = new StringEncoder(cache); |
76 | 3328 | myWriteVisitor = new WriteVisitor(this); |
77 | 3328 | } |
78 | ||
79 | /** | |
80 | * Returns the I/O exception encountered by the visitor. | |
81 | * | |
82 | * @return The I/O exception encountered by the visitor. | |
83 | */ | |
84 | public IOException getError() { | |
85 | 0 | return myError; |
86 | } | |
87 | ||
88 | /** | |
89 | * Returns the maximum number of strings that may have their encoded form | |
90 | * cached. | |
91 | * | |
92 | * @return The maximum number of strings that may have their encoded form | |
93 | * cached. | |
94 | * @deprecated The cache {@link StringEncoderCache} should be controlled | |
95 | * directory. This method will be removed after the 2.1.0 | |
96 | * release. | |
97 | */ | |
98 | @Deprecated | |
99 | public int getMaxCachedStringEntries() { | |
100 | 0 | return myStringEncoder.getCache().getMaxCacheEntries(); |
101 | } | |
102 | ||
103 | /** | |
104 | * Returns the maximum length for a string that the stream is allowed to | |
105 | * cache. | |
106 | * | |
107 | * @return The maximum length for a string that the stream is allowed to | |
108 | * cache. | |
109 | * @deprecated The cache {@link StringDecoderCache} should be controlled | |
110 | * directory. This method will be removed after the 2.1.0 | |
111 | * release. | |
112 | */ | |
113 | @Deprecated | |
114 | public int getMaxCachedStringLength() { | |
115 | 0 | return myStringEncoder.getCache().getMaxCacheLength(); |
116 | } | |
117 | ||
118 | /** | |
119 | * Returns the encoder value. | |
120 | * | |
121 | * @return The encoder value. | |
122 | */ | |
123 | public StringEncoder getStringEncoder() { | |
124 | 0 | return myStringEncoder; |
125 | } | |
126 | ||
127 | /** | |
128 | * Returns true if the visitor had an I/O error. | |
129 | * | |
130 | * @return True if the visitor had an I/O error, false otherwise. | |
131 | */ | |
132 | public boolean hasError() { | |
133 | 4766 | return (myError != null); |
134 | } | |
135 | ||
136 | /** | |
137 | * Clears any errors. | |
138 | */ | |
139 | public void reset() { | |
140 | 4766 | myError = null; |
141 | 4766 | } |
142 | ||
143 | /** | |
144 | * Sets the value of maximum number of strings that may have their encoded | |
145 | * form cached. | |
146 | * | |
147 | * @param maxCacheEntries | |
148 | * The new value for the maximum number of strings that may have | |
149 | * their encoded form cached. | |
150 | * @deprecated The cache {@link StringEncoderCache} should be controlled | |
151 | * directory. This method will be removed after the 2.1.0 | |
152 | * release. | |
153 | */ | |
154 | @Deprecated | |
155 | public void setMaxCachedStringEntries(final int maxCacheEntries) { | |
156 | 0 | myStringEncoder.getCache().setMaxCacheEntries(maxCacheEntries); |
157 | 0 | } |
158 | ||
159 | /** | |
160 | * Sets the value of length for a string that the stream is allowed to cache | |
161 | * to the new value. This can be used to stop a single long string from | |
162 | * pushing useful values out of the cache. | |
163 | * | |
164 | * @param maxlength | |
165 | * The new value for the length for a string that the encoder is | |
166 | * allowed to cache. | |
167 | * @deprecated The cache {@link StringEncoderCache} should be controlled | |
168 | * directory. This method will be removed after the 2.1.0 | |
169 | * release. | |
170 | */ | |
171 | @Deprecated | |
172 | public void setMaxCachedStringLength(final int maxlength) { | |
173 | 0 | myStringEncoder.getCache().setMaxCacheLength(maxlength); |
174 | ||
175 | 0 | } |
176 | ||
177 | /** | |
178 | * Returns the size of the writing the {@link Document} as a BSON document. | |
179 | * | |
180 | * @param document | |
181 | * The document to determine the size of. | |
182 | * @return The size of the writing {@link Document} as a BSON document. | |
183 | * @deprecated Replaced with {@link Document#size()}. This method will be | |
184 | * removed after the 2.2.0 release. | |
185 | */ | |
186 | @Deprecated | |
187 | public int sizeOf(final Document document) { | |
188 | 0 | return (int) document.size(); |
189 | } | |
190 | ||
191 | /** | |
192 | * Returns the size of the writing the <tt>strings</tt> as a c-string. | |
193 | * | |
194 | * @param strings | |
195 | * The 'C' strings to determine the size of. | |
196 | * @return The size of the writing the <tt>strings</tt> as a c-string. | |
197 | */ | |
198 | public int sizeOfCString(final String... strings) { | |
199 | 2017 | int size = 0; |
200 | 7506 | for (final String string : strings) { |
201 | 5489 | size += myWriteVisitor.utf8Size(string); |
202 | } | |
203 | 2017 | return (size + 1); |
204 | } | |
205 | ||
206 | /** | |
207 | * Returns the size of the writing the <tt>string</tt> as a string. | |
208 | * | |
209 | * @param string | |
210 | * The 'UTF8' string to determine the size of. | |
211 | * @return The size of the writing the <tt>string</tt> as a string. | |
212 | */ | |
213 | public int sizeOfString(final String string) { | |
214 | 0 | return 4 + myWriteVisitor.utf8Size(string) + 1; |
215 | } | |
216 | ||
217 | /** | |
218 | * Writes a single byte to the stream. | |
219 | * | |
220 | * @param b | |
221 | * The byte to write. | |
222 | */ | |
223 | public void writeByte(final byte b) { | |
224 | try { | |
225 | 16315 | myOutput.write(b); |
226 | } | |
227 | 0 | catch (final IOException ioe) { |
228 | 0 | myError = ioe; |
229 | 16316 | } |
230 | 16316 | } |
231 | ||
232 | /** | |
233 | * Writes a sequence of bytes to the under lying stream. | |
234 | * | |
235 | * @param data | |
236 | * The bytes to write. | |
237 | */ | |
238 | public void writeBytes(final byte[] data) { | |
239 | try { | |
240 | 13 | myOutput.write(data); |
241 | } | |
242 | 0 | catch (final IOException ioe) { |
243 | 0 | myError = ioe; |
244 | 13 | } |
245 | 13 | } |
246 | ||
247 | /** | |
248 | * Writes a "Cstring" to the stream. | |
249 | * | |
250 | * @param strings | |
251 | * The CString to write. The strings are concatenated into a | |
252 | * single CString value. | |
253 | */ | |
254 | public void writeCString(final String... strings) { | |
255 | 15806 | for (final String string : strings) { |
256 | 9639 | writeUtf8(string); |
257 | } | |
258 | 6167 | writeByte((byte) 0); |
259 | 6167 | } |
260 | ||
261 | /** | |
262 | * Writes a BSON {@link Document} to the stream. | |
263 | * | |
264 | * @param document | |
265 | * The {@link Document} to write. | |
266 | * @throws IOException | |
267 | * On a failure writing the document. | |
268 | */ | |
269 | public void writeDocument(final Document document) throws IOException { | |
270 | try { | |
271 | 4766 | document.accept(myWriteVisitor); |
272 | 4766 | if (myWriteVisitor.hasError()) { |
273 | 0 | throw myWriteVisitor.getError(); |
274 | } | |
275 | } | |
276 | finally { | |
277 | 4766 | myWriteVisitor.reset(); |
278 | 4766 | } |
279 | 4766 | } |
280 | ||
281 | /** | |
282 | * Write the integer value in little-endian byte order. | |
283 | * | |
284 | * @param value | |
285 | * The integer to write. | |
286 | */ | |
287 | public void writeInt(final int value) { | |
288 | try { | |
289 | 30871 | myOutput.write(value); |
290 | 30871 | myOutput.write(value >> 8); |
291 | 30871 | myOutput.write(value >> 16); |
292 | 30871 | myOutput.write(value >> 24); |
293 | } | |
294 | 0 | catch (final IOException ioe) { |
295 | 0 | myError = ioe; |
296 | 30871 | } |
297 | 30871 | } |
298 | ||
299 | /** | |
300 | * Write the long value in little-endian byte order. | |
301 | * | |
302 | * @param value | |
303 | * The long to write. | |
304 | */ | |
305 | public void writeLong(final long value) { | |
306 | try { | |
307 | 2297 | myOutput.write((int) value); |
308 | 2297 | myOutput.write((int) (value >> 8)); |
309 | 2297 | myOutput.write((int) (value >> 16)); |
310 | 2297 | myOutput.write((int) (value >> 24)); |
311 | 2297 | myOutput.write((int) (value >> 32)); |
312 | 2297 | myOutput.write((int) (value >> 40)); |
313 | 2297 | myOutput.write((int) (value >> 48)); |
314 | 2297 | myOutput.write((int) (value >> 56)); |
315 | } | |
316 | 0 | catch (final IOException ioe) { |
317 | 0 | myError = ioe; |
318 | 2297 | } |
319 | 2297 | } |
320 | ||
321 | /** | |
322 | * Writes a "string" to the stream. | |
323 | * | |
324 | * @param string | |
325 | * The String to write. | |
326 | */ | |
327 | public void writeString(final String string) { | |
328 | 518 | writeInt(myStringEncoder.encodeSize(string) + 1); |
329 | 518 | writeUtf8(string); |
330 | 518 | writeByte((byte) 0); |
331 | 518 | } |
332 | ||
333 | /** | |
334 | * Writes a sequence of bytes to the under lying stream. | |
335 | * | |
336 | * @param data | |
337 | * The bytes to write. | |
338 | * @param offset | |
339 | * The offset into the buffer to start writing data from. | |
340 | * @param length | |
341 | * The number of bytes to write. | |
342 | */ | |
343 | protected void writeBytes(final byte[] data, final int offset, | |
344 | final int length) { | |
345 | try { | |
346 | 0 | myOutput.write(data, offset, length); |
347 | } | |
348 | 0 | catch (final IOException ioe) { |
349 | 0 | myError = ioe; |
350 | 0 | } |
351 | 0 | } |
352 | ||
353 | /** | |
354 | * Writes the string as a UTF-8 string. This method handles the | |
355 | * "normal/easy" cases and delegates to the full character set if things get | |
356 | * complicated. | |
357 | * | |
358 | * @param string | |
359 | * The string to encode. | |
360 | */ | |
361 | protected void writeUtf8(final String string) { | |
362 | try { | |
363 | 10157 | myStringEncoder.encode(string, myOutput); |
364 | } | |
365 | 0 | catch (final IOException ioe) { |
366 | 0 | myError = ioe; |
367 | 10157 | } |
368 | 10157 | } |
369 | ||
370 | } |