001/*
002 * (C) Copyright 2011 Nuxeo SA (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     matic
016 */
017package org.nuxeo.ecm.automation.jaxrs.io;
018
019import java.io.BufferedInputStream;
020import java.io.File;
021import java.io.FileInputStream;
022import java.io.IOException;
023import java.io.InputStream;
024
025import javax.mail.internet.SharedInputStream;
026
027public class SharedFileInputStream extends InputStream implements SharedInputStream {
028
029    protected final InputStream in;
030
031    protected final SharedFileInputStream parent;
032
033    protected final File file;
034
035    protected final long length;
036
037    protected final long start;
038
039    protected long current;
040
041    protected long marked;
042
043    public SharedFileInputStream(File file) throws IOException {
044        this.in = new BufferedInputStream(new FileInputStream(file));
045        this.parent = null;
046        this.file = file;
047        this.start = 0;
048        this.length = file.length();
049        this.in.skip(start);
050    }
051
052    protected SharedFileInputStream(SharedFileInputStream parent, long start, long len) throws IOException {
053        this.in = new BufferedInputStream(new FileInputStream(parent.file));
054        this.parent = parent;
055        this.file = parent.file;
056        this.start = start;
057        this.length = len;
058        this.in.skip(start);
059    }
060
061    public long getPosition() {
062        return this.current;
063    }
064
065    public SharedFileInputStream newStream(long start, long end) {
066        try {
067            long length;
068            if (end == -1L) {
069                length = this.length - start;
070            } else {
071                length = end - start;
072            }
073            return new SharedFileInputStream(this, this.start + start, length);
074        } catch (IOException localIOException) {
075            throw new IllegalStateException("unable to create shared stream: " + localIOException);
076        }
077    }
078
079    public int read(byte[] buffer) throws IOException {
080        return read(buffer, 0, buffer.length);
081    }
082
083    public int read(byte[] buffer, int offset, int len) throws IOException {
084        int i = 0;
085        if (len == 0)
086            return 0;
087        while (i < len) {
088            int j = read();
089            if (j < 0)
090                break;
091            buffer[(offset + i)] = (byte) j;
092            ++i;
093        }
094        if (i == 0)
095            return -1;
096        return i;
097    }
098
099    public int read() throws IOException {
100        if (this.current == this.length)
101            return -1;
102        this.current += 1L;
103        return this.in.read();
104    }
105
106    public boolean markSupported() {
107        return true;
108    }
109
110    public long skip(long len) throws IOException {
111        for (int count = 0; count < len; ++count) {
112            if (read() < 0)
113                return count;
114        }
115        return len;
116    }
117
118    public void mark(int limit) {
119        this.marked = this.current;
120        this.in.mark(limit);
121    }
122
123    public void reset() throws IOException {
124        current = marked;
125        in.reset();
126    }
127
128    public SharedFileInputStream getRoot() {
129        if (parent != null)
130            return parent.getRoot();
131        return this;
132    }
133}