Coverage Report - org.kuali.rice.core.api.util.cache.CopiedObject
 
Classes in this File Line Coverage Branch Coverage Complexity
CopiedObject
0%
0/45
0%
0/10
2
CopiedObject$FastByteArrayInputStream
0%
0/22
0%
0/10
2
CopiedObject$FastByteArrayOutputStream
0%
0/30
0%
0/2
2
 
 1  
 /*
 2  
  * Copyright 2006-2011 The Kuali Foundation
 3  
  *
 4  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  * http://www.opensource.org/licenses/ecl2.php
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package org.kuali.rice.core.api.util.cache;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.InputStream;
 20  
 import java.io.ObjectInputStream;
 21  
 import java.io.ObjectOutputStream;
 22  
 import java.io.OutputStream;
 23  
 import java.io.Serializable;
 24  
 
 25  
 
 26  
 /**
 27  
  * Container class to simplify getting both a deepCopied object and its size returned from a single call to deepCopy.
 28  
  */
 29  
 public class CopiedObject<T extends Serializable> {
 30  
     //private Serializable content;
 31  
     private byte[] content;
 32  
     private int size;
 33  
     private int oldSize;
 34  
 
 35  0
     public CopiedObject() {
 36  0
         oldSize = -1;
 37  0
     }
 38  
 
 39  0
     public CopiedObject( T cacheableObject ) {
 40  0
         oldSize = -1;
 41  0
         setContent( cacheableObject );
 42  0
     }
 43  
 
 44  
     /**
 45  
      * @return current value of bytes.
 46  
      */
 47  
     public int getSize() {
 48  0
         return size;
 49  
     }
 50  
 
 51  
     /**
 52  
      * @return current value of cacheableObject.
 53  
      */
 54  
     public T getContent() {
 55  0
         T copy = null;
 56  0
         if (content != null) {
 57  0
             ObjectInputStream ois = null;
 58  
             try {
 59  0
                 FastByteArrayInputStream deserializer = new FastByteArrayInputStream(content,size);
 60  0
                 ois = new ObjectInputStream(deserializer);
 61  0
                 copy = (T) ois.readObject();
 62  
             }
 63  0
             catch (IOException e) {
 64  0
                 throw new CacheException("unable to complete getContent()", e);
 65  
             }
 66  0
             catch (ClassNotFoundException e) {
 67  0
                 throw new CacheException("unable to complete getContent()", e);
 68  
             }
 69  
             finally {
 70  0
                 try {
 71  0
                     if (ois != null) {
 72  0
                         ois.close();
 73  
                     }
 74  
                 }
 75  0
                 catch (IOException e) {
 76  
                     // ignoring this IOException, since the streams are going to be abandoned now anyway
 77  0
                 }
 78  0
             }
 79  
         }
 80  0
         return copy;
 81  
     }
 82  
 
 83  
     /**
 84  
      * Sets the cacheableObject attribute value.
 85  
      * 
 86  
      * @param cacheableObject The cacheableObject to set.
 87  
      */
 88  
     public void setContent(T cacheableObject) {
 89  0
         int copySize = 0;
 90  0
         if (cacheableObject != null) {
 91  0
             ObjectOutputStream oos = null;
 92  
             try {
 93  0
                 FastByteArrayOutputStream serializer = new FastByteArrayOutputStream();
 94  0
                 oos = new ObjectOutputStream(serializer);
 95  0
                 oos.writeObject(cacheableObject);
 96  
 
 97  0
                 if ( content != null ) {
 98  0
                     oldSize = size;
 99  
                 }
 100  0
                 size = serializer.getSize();
 101  0
                 content = serializer.getByteArray();
 102  0
             } catch (IOException e) {
 103  0
                 throw new CacheException("unable to complete deepCopy from src '" + cacheableObject.toString() + "'", e);
 104  
             }
 105  
             finally {
 106  0
                 try {
 107  0
                     if (oos != null) {
 108  0
                         oos.close();
 109  
                     }
 110  0
                 } catch (IOException e) {
 111  
                     // ignoring this IOException, since the streams are going to be abandoned now anyway
 112  0
                 }
 113  0
             }
 114  
         }
 115  0
     }
 116  
 
 117  
 
 118  
     /**
 119  
      * @return current value of oldSize.
 120  
      */
 121  
     public int getOldSize() {
 122  0
         return oldSize;
 123  
     }
 124  
 
 125  
     /**
 126  
      * ByteArrayOutputStream implementation that doesn't synchronize methods
 127  
      * and doesn't copy the data on toByteArray().
 128  
      */
 129  
     private static class FastByteArrayOutputStream extends OutputStream {
 130  
         /**
 131  
          * Buffer and size
 132  
          */
 133  0
         protected byte[] buf = null;
 134  0
         protected int size = 0;
 135  
 
 136  
         /**
 137  
          * Constructs a stream with buffer capacity size 5K
 138  
          */
 139  
         public FastByteArrayOutputStream() {
 140  0
             this(5 * 1024);
 141  0
         }
 142  
 
 143  
         /**
 144  
          * Constructs a stream with the given initial size
 145  
          */
 146  0
         public FastByteArrayOutputStream(int initSize) {
 147  0
             this.size = 0;
 148  0
             this.buf = new byte[initSize];
 149  0
         }
 150  
 
 151  
         /**
 152  
          * Ensures that we have a large enough buffer for the given size.
 153  
          */
 154  
         private void verifyBufferSize(int sz) {
 155  0
             if (sz > buf.length) {
 156  0
                 byte[] old = buf;
 157  0
                 buf = new byte[Math.max(sz, 2 * buf.length )];
 158  0
                 System.arraycopy(old, 0, buf, 0, old.length);
 159  0
                 old = null;
 160  
             }
 161  0
         }
 162  
 
 163  
         public int getSize() {
 164  0
             return size;
 165  
         }
 166  
 
 167  
         /**
 168  
          * Returns the byte array containing the written data. Note that this
 169  
          * array will almost always be larger than the amount of data actually
 170  
          * written.
 171  
          */
 172  
         public byte[] getByteArray() {
 173  0
             return buf;
 174  
         }
 175  
 
 176  
         public final void write(byte b[]) {
 177  0
             verifyBufferSize(size + b.length);
 178  0
             System.arraycopy(b, 0, buf, size, b.length);
 179  0
             size += b.length;
 180  0
         }
 181  
 
 182  
         public final void write(byte b[], int off, int len) {
 183  0
             verifyBufferSize(size + len);
 184  0
             System.arraycopy(b, off, buf, size, len);
 185  0
             size += len;
 186  0
         }
 187  
 
 188  
         public final void write(int b) {
 189  0
             verifyBufferSize(size + 1);
 190  0
             buf[size++] = (byte) b;
 191  0
         }
 192  
 
 193  
         public void reset() {
 194  0
             size = 0;
 195  0
         }
 196  
 
 197  
         /**
 198  
          * Returns a ByteArrayInputStream for reading back the written data
 199  
          */
 200  
         public InputStream getInputStream() {
 201  0
             return new FastByteArrayInputStream(buf, size);
 202  
         }
 203  
 
 204  
     }
 205  
 
 206  
     /**
 207  
      * ByteArrayInputStream implementation that does not synchronize methods.
 208  
      */
 209  
     private static class FastByteArrayInputStream extends InputStream {
 210  
         /**
 211  
          * Our byte buffer
 212  
          */
 213  0
         protected byte[] buf = null;
 214  
 
 215  
         /**
 216  
          * Number of bytes that we can read from the buffer
 217  
          */
 218  0
         protected int count = 0;
 219  
 
 220  
         /**
 221  
          * Number of bytes that have been read from the buffer
 222  
          */
 223  0
         protected int pos = 0;
 224  
 
 225  0
         public FastByteArrayInputStream(byte[] buf, int count) {
 226  0
             this.buf = buf;
 227  0
             this.count = count;
 228  0
         }
 229  
 
 230  
         public final int available() {
 231  0
             return count - pos;
 232  
         }
 233  
 
 234  
         public final int read() {
 235  0
             return (pos < count) ? (buf[pos++] & 0xff) : -1;
 236  
         }
 237  
 
 238  
         public final int read(byte[] b, int off, int len) {
 239  0
             if (pos >= count)
 240  0
                 return -1;
 241  
 
 242  0
             if ((pos + len) > count)
 243  0
                 len = (count - pos);
 244  
 
 245  0
             System.arraycopy(buf, pos, b, off, len);
 246  0
             pos += len;
 247  0
             return len;
 248  
         }
 249  
 
 250  
         public final long skip(long n) {
 251  0
             if ((pos + n) > count)
 252  0
                 n = count - pos;
 253  0
             if (n < 0)
 254  0
                 return 0;
 255  0
             pos += n;
 256  0
             return n;
 257  
         }
 258  
 
 259  
     }
 260  
 }