/*! * Copyright 2010 - 2013 Pentaho Corporation. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.apache.commons.vfs.util; import org.apache.commons.vfs.Capability; import org.apache.commons.vfs.FileObject; import org.apache.commons.vfs.FileSystemException; import org.apache.commons.vfs.RandomAccessContent; import javax.mail.internet.SharedInputStream; import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.util.HashSet; import java.util.Set; /** * A wrapper to an FileObject to get a {@link javax.mail.internet.SharedInputStream} * * @author <a href="mailto:imario@apache.org">imario@apache.org</a> * @version $Revision: 480428 $ $Date: 2006-11-29 01:15:24 -0500 (Wed, 29 Nov 2006) $ */ public class SharedRandomContentInputStream extends BufferedInputStream implements SharedInputStream { private final Set createdStreams; private final FileObject fo; private final long fileStart; private final long fileEnd; private long pos; private long resetCount; private SharedRandomContentInputStream(final Set createdStreams, final FileObject fo, final long fileStart, final long fileEnd, final InputStream is) throws FileSystemException { super(is); if (!fo.getFileSystem().hasCapability(Capability.RANDOM_ACCESS_READ)) { throw new FileSystemException("vfs.util/missing-capability.error", Capability.RANDOM_ACCESS_READ); } this.fo = fo; this.fileStart = fileStart; this.fileEnd = fileEnd; this.createdStreams = createdStreams; synchronized(createdStreams) { createdStreams.add(this); } } public SharedRandomContentInputStream(final FileObject fo) throws FileSystemException { this(new HashSet(), fo, 0, -1, fo.getContent().getInputStream()); } public synchronized int read() throws IOException { if (checkEnd()) { return -1; } int r = super.read(); pos++; resetCount++; return r; } public synchronized int read(byte b[], int off, int len) throws IOException { if (checkEnd()) { return -1; } if (fileEnd > -1 && calcFilePosition(len) > fileEnd) { // we can not read past our end len = (int) (fileEnd - getFilePosition()); } int nread = super.read(b, off, len); pos+=nread; resetCount+=nread; return nread; } public synchronized long skip(long n) throws IOException { if (checkEnd()) { return -1; } if (fileEnd > -1 && calcFilePosition(n) > fileEnd) { // we can not skip past our end n = fileEnd - getFilePosition(); } long nskip = super.skip(n); pos+=nskip; resetCount+=nskip; return nskip; } /* public synchronized int available() throws IOException { long realFileEnd = fileEnd; if (realFileEnd < 0) { realFileEnd = fo.getContent().getSize(); } if (realFileEnd < 0) { // we cant determine if there is really something available return 8192; } long available = realFileEnd - (fileStart + pos); if (available > Integer.MAX_VALUE) { return Integer.MAX_VALUE; } return (int) available; } */ private boolean checkEnd() { return fileEnd > -1 && (getFilePosition() >= fileEnd); } protected long getFilePosition() { return fileStart + pos; } protected long calcFilePosition(long nadd) { return getFilePosition()+nadd; } public synchronized void mark(int readlimit) { super.mark(readlimit); resetCount = 0; } public synchronized void reset() throws IOException { super.reset(); pos-=resetCount; resetCount=0; } public long getPosition() { return pos; } public void close() throws IOException { super.close(); synchronized(createdStreams) { createdStreams.remove(this); } } public InputStream newStream(long start, long end) { try { long newFileStart = this.fileStart+start; long newFileEnd = end<0?this.fileEnd:this.fileStart+end; RandomAccessContent rac = fo.getContent().getRandomAccessContent(RandomAccessMode.READ); rac.seek(newFileStart); return new SharedRandomContentInputStream( createdStreams, fo, newFileStart, newFileEnd, rac.getInputStream()); } catch (IOException e) { throw new RuntimeException(e); } } public void closeAll() throws IOException { synchronized(createdStreams) { SharedRandomContentInputStream[] streams = new SharedRandomContentInputStream[createdStreams.size()]; createdStreams.toArray(streams); for (int i = 0; i<streams.length; i++) { streams[i].close(); } } } }