001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html.
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012: package org.tmatesoft.svn.core.internal.io.dav.http;
013:
014: import java.io.BufferedInputStream;
015: import java.io.BufferedOutputStream;
016: import java.io.File;
017: import java.io.FileInputStream;
018: import java.io.FileNotFoundException;
019: import java.io.FileOutputStream;
020: import java.io.IOException;
021: import java.io.InputStream;
022: import java.io.OutputStream;
023: import java.util.Iterator;
024: import java.util.LinkedList;
025:
026: import org.tmatesoft.svn.core.SVNException;
027: import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
028:
029: /**
030: * @version 1.1.2
031: * @author TMate Software Ltd.
032: */
033: public class SpoolFile {
034:
035: private static final long LIMIT = 1024 * 1024 * 512; // 1/2GB.
036:
037: private File myDirectory;
038: private LinkedList myFiles;
039:
040: public SpoolFile(File directory) {
041: myDirectory = directory;
042: myFiles = new LinkedList();
043: }
044:
045: public OutputStream openForWriting() {
046: return new SpoolOutputStream();
047: }
048:
049: public InputStream openForReading() {
050: return new SpoolInputStream();
051: }
052:
053: public void delete() throws SVNException {
054: for (Iterator files = myFiles.iterator(); files.hasNext();) {
055: File file = (File) files.next();
056: SVNFileUtil.deleteFile(file);
057: }
058: }
059:
060: private class SpoolInputStream extends InputStream {
061:
062: private File myCurrentFile;
063: private long myCurrentSize;
064: private InputStream myCurrentInput;
065:
066: public int read() throws IOException {
067: byte[] buffer = new byte[1];
068: int read = read(buffer);
069: if (read <= 0) {
070: return -1;
071: }
072: return read;
073: }
074:
075: public int read(byte[] b) throws IOException {
076: return read(b, 0, b.length);
077: }
078:
079: public int read(byte[] b, int off, int len) throws IOException {
080: if (myCurrentFile == null) {
081: if (myFiles.isEmpty()) {
082: return -1;
083: }
084: openNextFile();
085: }
086: int toRead = (int) Math.min(len, myCurrentSize);
087: toRead = myCurrentInput.read(b, off, toRead);
088: myCurrentSize -= toRead;
089: if (myCurrentSize == 0) {
090: closeCurrentFile();
091: }
092: return toRead;
093: }
094:
095: private void openNextFile() throws FileNotFoundException {
096: myCurrentFile = (File) myFiles.removeFirst();
097: myCurrentSize = myCurrentFile.length();
098: myCurrentInput = new BufferedInputStream(
099: new FileInputStream(myCurrentFile));
100: }
101:
102: public long skip(long n) throws IOException {
103: if (myCurrentFile == null) {
104: if (myFiles.isEmpty()) {
105: return -1;
106: }
107: openNextFile();
108: }
109: long toSkip = Math.min(myCurrentSize, n);
110: toSkip = myCurrentInput.skip(toSkip);
111: myCurrentSize -= toSkip;
112: if (myCurrentSize == 0) {
113: closeCurrentFile();
114: }
115: return toSkip;
116: }
117:
118: private void closeCurrentFile() throws IOException {
119: try {
120: myCurrentInput.close();
121: } finally {
122: try {
123: SVNFileUtil.deleteFile(myCurrentFile);
124: } catch (SVNException e) {
125: //
126: }
127: myCurrentFile = null;
128: }
129: }
130:
131: public void close() throws IOException {
132: if (myCurrentFile != null) {
133: closeCurrentFile();
134: }
135: }
136: }
137:
138: private class SpoolOutputStream extends OutputStream {
139:
140: private OutputStream myCurrentOutput;
141: private long myCurrentSize;
142:
143: public void write(int b) throws IOException {
144: write(new byte[] { (byte) (b & 0xFF) });
145: }
146:
147: public void write(byte[] b) throws IOException {
148: write(b, 0, b.length);
149: }
150:
151: public void write(byte[] b, int off, int len)
152: throws IOException {
153: if (myCurrentOutput == null) {
154: // open first file.
155: File file = createNextFile();
156: myFiles.add(file);
157: myCurrentOutput = new BufferedOutputStream(
158: new FileOutputStream(file));
159: }
160: myCurrentOutput.write(b, off, len);
161: myCurrentSize += len;
162: if (myCurrentSize >= LIMIT) {
163: close();
164: }
165: }
166:
167: public void close() throws IOException {
168: if (myCurrentOutput != null) {
169: try {
170: myCurrentOutput.close();
171: } finally {
172: myCurrentOutput = null;
173: }
174: }
175: myCurrentSize = 0;
176: }
177:
178: public void flush() throws IOException {
179: if (myCurrentOutput != null) {
180: myCurrentOutput.flush();
181: }
182: }
183:
184: private File createNextFile() throws IOException {
185: File file = File.createTempFile(".svnkit.", ".spool",
186: myDirectory);
187: file.createNewFile();
188: return file;
189: }
190:
191: }
192:
193: }
|