Coverage Report - com.allanbank.mongodb.bson.io.BsonOutputStream
 
Classes in this File Line Coverage Branch Coverage Complexity
BsonOutputStream
67%
53/79
75%
6/8
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  
 }