Coverage Report - org.webslinger.ext.commons.vfs.plan9.Plan9RandomAccessContent
 
Classes in this File Line Coverage Branch Coverage Complexity
Plan9RandomAccessContent
0%
0/167
0%
0/23
0
Plan9RandomAccessContent$Plan9RandomAccessContentInputStream
0%
0/77
0%
0/11
0
 
 1  
 package org.webslinger.ext.commons.vfs.plan9;
 2  
 
 3  
 import java.io.EOFException;
 4  
 import java.io.InputStream;
 5  
 import java.io.IOException;
 6  
 import java.io.OutputStream;
 7  
 import java.io.UTFDataFormatException;
 8  
 import java.security.cert.Certificate;
 9  
 import java.util.Map;
 10  
 
 11  
 import org.apache.mina.common.ByteBuffer;
 12  
 
 13  
 import org.apache.commons.vfs.FileName;
 14  
 import org.apache.commons.vfs.FileObject;
 15  
 import org.apache.commons.vfs.FileSystem;
 16  
 import org.apache.commons.vfs.FileSystemException;
 17  
 import org.apache.commons.vfs.FileSystemOptions;
 18  
 import org.apache.commons.vfs.FileType;
 19  
 import org.apache.commons.vfs.RandomAccessContent;
 20  
 import org.apache.commons.vfs.provider.AbstractFileObject;
 21  
 import org.apache.commons.vfs.util.RandomAccessMode;
 22  
 
 23  
 import uk.ac.rdg.resc.jstyx.StyxUtils;
 24  
 import uk.ac.rdg.resc.jstyx.client.CStyxFile;
 25  
 import uk.ac.rdg.resc.jstyx.client.CStyxFileInputStream;
 26  
 import uk.ac.rdg.resc.jstyx.client.CStyxFileOutputStream;
 27  
 import uk.ac.rdg.resc.jstyx.types.DirEntry;
 28  
 import uk.ac.rdg.resc.jstyx.client.StyxConnection;
 29  
 
 30  
 public class Plan9RandomAccessContent implements RandomAccessContent {
 31  
     protected CStyxFile styxFile;
 32  
     protected long offset;
 33  0
     protected ByteBuffer buffer = ByteBuffer.allocate(16384);
 34  
 
 35  0
     public Plan9RandomAccessContent(CStyxFile styxFile) throws IOException {
 36  0
         this.styxFile = styxFile.getConnection().openFile(styxFile.getPath(), StyxUtils.OREAD);
 37  0
     }
 38  
 
 39  
     public long getFilePointer() {
 40  0
         synchronized (this) {
 41  0
             return offset;
 42  0
         }
 43  
     }
 44  
 
 45  
     public void seek(long pos) {
 46  0
         synchronized (this) {
 47  0
             offset = pos;
 48  0
         }
 49  0
     }
 50  
 
 51  
     public long length() throws IOException {
 52  0
         return styxFile.getLength();
 53  
     }
 54  
 
 55  
     public void close() throws IOException {
 56  0
         styxFile.close();
 57  0
     }
 58  
 
 59  
     protected void fill() throws IOException {
 60  
         ByteBuffer newBuffer;
 61  0
         synchronized (this) {
 62  0
             newBuffer = styxFile.read(offset);
 63  0
             offset += newBuffer.remaining();
 64  0
         }
 65  0
         buffer.compact();
 66  
         // check for memleak, might need to .release();
 67  0
         buffer.put(newBuffer);
 68  0
     }
 69  
 
 70  
     protected void fill(int required) throws IOException {
 71  0
         if (buffer.remaining() < required) fill();
 72  0
         if (buffer.remaining() < required) throw new EOFException();
 73  0
     }
 74  
 
 75  
     protected void drain(int required) throws IOException {
 76  0
     }
 77  
 
 78  
     public void readFully(byte[] b) throws IOException {
 79  0
         readFully(b, 0, b.length);
 80  0
     }
 81  
 
 82  
     public void write(byte[] b) throws IOException {
 83  0
         write(b, 0, b.length);
 84  0
     }
 85  
     
 86  
     public void readFully(byte[] b, int offset, int length) throws IOException {
 87  0
     }
 88  
 
 89  
     public void write(byte[] b, int offset, int length) throws IOException {
 90  0
     }
 91  
 
 92  
     public void write(int b) throws IOException {
 93  0
         writeByte(b);
 94  0
     }
 95  
 
 96  
     public boolean readBoolean() throws IOException {
 97  0
         return readByte() != 0;
 98  
     }
 99  
 
 100  
     public void writeBoolean(boolean value) throws IOException {
 101  0
         write(value ? 1 : 0);
 102  0
     }
 103  
 
 104  
     public byte readByte() throws IOException {
 105  0
         fill(1);
 106  0
         return buffer.get();
 107  
     }
 108  
         
 109  
     public void writeByte(int value) throws IOException {
 110  0
         drain(1);
 111  0
         buffer.put((byte) (value & 0xff));
 112  0
     }
 113  
 
 114  
     public void writeBytes(String value) throws IOException {
 115  0
         write(value.getBytes());
 116  0
     }
 117  
 
 118  
     public char readChar() throws IOException {
 119  0
         fill(2);
 120  0
         return (char) (buffer.get() << 8 | buffer.get());
 121  
     }
 122  
 
 123  
     public void writeChar(int value) throws IOException {
 124  0
         drain(2);
 125  0
         buffer.put((byte) ((value >> 8) & 0xFF));
 126  0
         buffer.put((byte) (value & 0xFF));
 127  0
     }
 128  
 
 129  
     public void writeChars(String value) throws IOException {
 130  0
         char[] chars = value.toCharArray();
 131  0
         for (char c: chars) {
 132  0
             drain(2);
 133  0
             buffer.put((byte) ((c >> 8) & 0xFF));
 134  0
             buffer.put((byte) (c & 0xFF));
 135  
         }
 136  0
     }
 137  
 
 138  
     public double readDouble() throws IOException {
 139  0
         return Double.longBitsToDouble(readLong());
 140  
     }
 141  
 
 142  
     public void writeDouble(double value) throws IOException {
 143  0
         writeLong(Double.doubleToLongBits(value));
 144  0
     }
 145  
 
 146  
     public float readFloat() throws IOException {
 147  0
         return Float.intBitsToFloat(readInt());
 148  
     }
 149  
 
 150  
     public void writeFloat(float value) throws IOException {
 151  0
         writeInt(Float.floatToIntBits(value));
 152  0
     }
 153  
 
 154  
     public int readInt() throws IOException {
 155  0
         byte[] data = new byte[4];
 156  0
         fill(4);
 157  0
         buffer.get(data);
 158  0
         return data[0] << 24 | data[1] << 16 |
 159  
                data[2] << 8 | data[3];
 160  
     }
 161  
 
 162  
     public void writeInt(int value) throws IOException {
 163  0
         drain(4);
 164  0
         buffer.put((byte) ((value >> 24) & 0xFF));
 165  0
         buffer.put((byte) ((value >> 16) & 0xFF));
 166  0
         buffer.put((byte) ((value >> 8) & 0xFF));
 167  0
         buffer.put((byte) (value & 0xFF));
 168  0
     }
 169  
 
 170  
     public long readLong() throws IOException {
 171  0
         byte[] data = new byte[8];
 172  0
         fill(8);
 173  0
         buffer.get(data);
 174  0
         return data[0] << 56 | data[1] << 48 |
 175  
                data[2] << 40 | data[3] << 32 |
 176  
                data[4] << 24 | data[5] << 16 |
 177  
                data[6] << 8 | data[7];
 178  
     }
 179  
 
 180  
     public void writeLong(long value) throws IOException {
 181  0
         drain(8);
 182  0
         buffer.put((byte) ((value >> 56) & 0xFF));
 183  0
         buffer.put((byte) ((value >> 48) & 0xFF));
 184  0
         buffer.put((byte) ((value >> 40) & 0xFF));
 185  0
         buffer.put((byte) ((value >> 32) & 0xFF));
 186  0
         buffer.put((byte) ((value >> 24) & 0xFF));
 187  0
         buffer.put((byte) ((value >> 16) & 0xFF));
 188  0
         buffer.put((byte) ((value >> 8) & 0xFF));
 189  0
         buffer.put((byte) (value & 0xFF));
 190  0
     }
 191  
 
 192  
     public short readShort() throws IOException {
 193  0
         fill(2);
 194  0
         return (short) (buffer.get() << 8 | buffer.get());
 195  
     }
 196  
 
 197  
     public void writeShort(int value) throws IOException {
 198  0
         drain(2);
 199  0
         buffer.put((byte) ((value >> 8) & 0xFF));
 200  0
         buffer.put((byte) (value & 0xFF));
 201  0
     }
 202  
 
 203  
     public String readLine() throws IOException {
 204  0
         int b = -1;
 205  0
         StringBuilder sb = new StringBuilder();
 206  
         try {
 207  
 LINE:
 208  
             while (true) {
 209  0
                 while (buffer.remaining() > 0) {
 210  0
                     b = buffer.get();
 211  0
                     if (b < 0) b += 256;
 212  0
                     if (b == '\n') break LINE;
 213  0
                     if (b == '\r') {
 214  0
                         buffer.mark();
 215  
                         try {
 216  0
                             fill(1);
 217  0
                             b = buffer.get();
 218  0
                             if (b != '\n') buffer.reset();
 219  0
                             break LINE;
 220  0
                         } catch (EOFException e) {
 221  0
                             buffer.reset();
 222  0
                             break LINE;
 223  
                         }
 224  
                     }
 225  0
                     sb.append((char) b);
 226  
                 }
 227  
             }
 228  0
         } catch (EOFException e) {
 229  0
             if (b == -1) throw e;
 230  0
         }
 231  0
         return sb.toString();
 232  
     }
 233  
 
 234  
     public String readUTF() throws IOException {
 235  0
         int left = readUnsignedShort();
 236  0
         StringBuilder sb = new StringBuilder(left);
 237  0
         while (left > 0) {
 238  0
             fill(1);
 239  0
             byte b1 = buffer.get();
 240  
             try {
 241  0
                 if ((b1 & 0x80) == 0) {
 242  0
                     sb.append((char) b1);
 243  0
                 } else if ((b1 & 0xE0) == 0xC0) {
 244  0
                     fill(1);
 245  0
                     sb.append((char) (((b1 & 0x1F) << 6) | (buffer.get() & 0x3F)));
 246  0
                 } else if ((b1 & 0xF0) == 0xE0) {
 247  0
                     fill(2);
 248  0
                     sb.append((char)(((b1 & 0x0F) << 12) | ((buffer.get() & 0x3F) << 6) | (buffer.get() & 0x3F)));
 249  0
                 } else if ((b1 & 0xF0) == 0xF0) {
 250  0
                     throw new UTFDataFormatException();
 251  0
                 } else if ((b1 & 0xB0) == 0x80) {
 252  0
                     throw new UTFDataFormatException();
 253  
                 } else {
 254  
                     // should not happen
 255  0
                     throw new InternalError();
 256  
                 }
 257  0
             } catch (EOFException e) {
 258  0
                 throw new UTFDataFormatException();
 259  0
             }
 260  0
             left--;
 261  0
         }
 262  0
         return sb.toString();
 263  
     }
 264  
 
 265  
     public void writeUTF(String value) throws IOException {
 266  0
         char[] chars = value.toCharArray();
 267  0
         writeChar(chars.length);
 268  0
         for (char c: chars) {
 269  0
             if (0x0001 <= c && c <= 0x007F) {
 270  0
                 drain(1);
 271  0
                 buffer.put((byte) c);
 272  0
             } else if (0 == c || (0x0080 <= c && c <= 0x07FF)) {
 273  0
                 drain(2);
 274  0
                 buffer.put((byte) (0xC0 | (0x1F & (c >> 6))));
 275  0
                 buffer.put((byte) (0x80 | (0x3F & c)));
 276  0
             } else if (0x0800 <= c && c <= 0xFFFF) {
 277  0
                 drain(3);
 278  0
                 buffer.put((byte) (0xE0 | (0x0F & (c >> 12))));
 279  0
                 buffer.put((byte) (0x80 | (0x3F & (c >> 6))));
 280  0
                 buffer.put((byte) (0x80 | (0x3F & c)));
 281  
             } else {
 282  
                 // should not happen
 283  0
                 throw new InternalError();
 284  
             }
 285  
         }
 286  0
     }
 287  
 
 288  
     public int readUnsignedByte() throws IOException {
 289  0
         fill(1);
 290  0
         int value = buffer.get();
 291  0
         if (value < 0) value += 256;
 292  0
         return value;
 293  
     }
 294  
 
 295  
     public int readUnsignedShort() throws IOException {
 296  0
         fill(2);
 297  0
         return buffer.get() << 8 | buffer.get();
 298  
     }
 299  
 
 300  
     public int skipBytes(int count) throws IOException {
 301  0
         long length = length();
 302  0
         synchronized (this) {
 303  0
             offset += count;
 304  0
             if (offset > length) {
 305  0
                 count -= (offset - length);
 306  0
                 offset = length;
 307  
             }
 308  0
         }
 309  0
         return count;
 310  
     }
 311  
 
 312  
     public InputStream getInputStream() throws IOException {
 313  0
         return new Plan9RandomAccessContentInputStream();
 314  
     }
 315  
 
 316  
     protected class Plan9RandomAccessContentInputStream extends InputStream {
 317  
         protected long offset, markOffset;
 318  
         protected int readLimit;
 319  
         protected CStyxFile styxFile;
 320  
 
 321  0
         protected Plan9RandomAccessContentInputStream() throws IOException {
 322  0
             styxFile = Plan9RandomAccessContent.this.styxFile.getConnection().openFile(Plan9RandomAccessContent.this.styxFile.getPath(), StyxUtils.OREAD);
 323  0
             synchronized (Plan9RandomAccessContent.this) {
 324  0
                 markOffset = offset = Plan9RandomAccessContent.this.offset;
 325  0
             }
 326  0
         }
 327  
         
 328  
         public int available() throws IOException {
 329  
             long available;
 330  0
             synchronized (this) {
 331  0
                 available = styxFile.getLength() - offset;
 332  0
             }
 333  0
             if (available > Integer.MAX_VALUE) return Integer.MAX_VALUE;
 334  0
             return (int) available;
 335  
         }
 336  
 
 337  
         public void close() throws IOException {
 338  0
             styxFile.close();
 339  0
             styxFile = null;
 340  0
         }
 341  
 
 342  
         public boolean markSupported() {
 343  0
             return true;
 344  
         }
 345  
 
 346  
         public void mark(int readLimit) {
 347  0
             synchronized (this) {
 348  0
                 markOffset = offset;
 349  0
             }
 350  0
         }
 351  
 
 352  
         public int read() throws IOException {
 353  0
             byte[] b = new byte[1];
 354  0
             int r = read(b, 0, 1);
 355  0
             if (r == 0) return -1;
 356  0
             if (b[0] < 0) {
 357  0
                 return b[0] + 256;
 358  
             } else {
 359  0
                 return b[0];
 360  
             }
 361  
         }
 362  
 
 363  
         public int read(byte[] b, int offset, int length) throws IOException {
 364  0
             if (length == 0) return 0;
 365  
             int count;
 366  0
             synchronized (this) {
 367  0
                 if (buffer != null) {
 368  0
                     int remaining = buffer.remaining();
 369  0
                     if (remaining >= length) {
 370  0
                         buffer.get(b, offset, length);
 371  0
                         return length;
 372  0
                     } else if (remaining != 0) {
 373  0
                         buffer.get(b, offset, remaining);
 374  0
                         count = remaining;
 375  0
                         length -= remaining;
 376  0
                         offset += remaining;
 377  
                     } else {
 378  0
                         count = 0;
 379  
                     }
 380  0
                     buffer.release();
 381  0
                     buffer = null;
 382  0
                 } else {
 383  0
                     count = 0;
 384  
                 }
 385  
                 while (true) {
 386  0
                     buffer = styxFile.read(this.offset);
 387  0
                     int remaining = buffer.remaining();
 388  0
                     if (remaining == 0) break;
 389  0
                     if (remaining >= length) {
 390  0
                         buffer.get(b, offset, length);
 391  0
                         count += length;
 392  0
                         break;
 393  0
                     } else if (remaining != 0) {
 394  0
                         buffer.get(b, offset, remaining);
 395  0
                         count += remaining;
 396  0
                         length -= remaining;
 397  0
                         offset += remaining;
 398  0
                         buffer.release();
 399  0
                         buffer = null;
 400  
                     } else {
 401  0
                         buffer.release();
 402  0
                         buffer = null;
 403  0
                         break;
 404  
                     }
 405  0
                 }
 406  0
                 return count;
 407  0
             }
 408  
         }
 409  
         
 410  
         public void reset() {
 411  0
             synchronized (this) {
 412  0
                 offset = markOffset;
 413  0
             }
 414  0
         }
 415  
 
 416  
         public long skip(long count) {
 417  
             try {
 418  0
                 synchronized (this) {
 419  0
                     long length = styxFile.getLength() - offset;
 420  0
                     offset += count;
 421  0
                     if (offset > length) {
 422  0
                         count -= (offset - length);
 423  0
                         offset = length;
 424  
                     }
 425  0
                 }
 426  0
             } catch (IOException e) {
 427  0
                 return 0;
 428  0
             }
 429  0
             return count;
 430  
         }
 431  
     }
 432  
 }