001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.io;
016    
017    import java.io.File;
018    import java.io.FileInputStream;
019    import java.io.IOException;
020    import java.io.InputStream;
021    
022    /**
023     * @author Shuyang Zhou
024     */
025    public class ByteArrayFileInputStream extends InputStream {
026    
027            public ByteArrayFileInputStream(File file, int threshold) {
028                    this(file, threshold, false);
029            }
030    
031            public ByteArrayFileInputStream(
032                    File file, int threshold, boolean deleteOnClose) {
033    
034                    if (!file.exists() || !file.isFile()) {
035                            throw new IllegalArgumentException(
036                                    "File " + file.getAbsolutePath() + " does not exist");
037                    }
038    
039                    this.file = file;
040                    fileSize = file.length();
041                    this.threshold = threshold;
042                    this.deleteOnClose = deleteOnClose;
043            }
044    
045            @Override
046            public int available() throws IOException {
047                    if (data != null) {
048                            return data.length - index;
049                    }
050                    else if (fileInputStream != null) {
051                            return fileInputStream.available();
052                    }
053                    else {
054                            return 0;
055                    }
056            }
057    
058            @Override
059            public void close() throws IOException {
060                    try {
061                            if (fileInputStream != null) {
062                                    fileInputStream.close();
063                            }
064                    }
065                    finally {
066                            data = null;
067                            fileInputStream = null;
068    
069                            if (deleteOnClose && (file != null)) {
070                                    file.delete();
071                            }
072    
073                            file = null;
074                    }
075            }
076    
077            public File getFile() {
078                    return file;
079            }
080    
081            @Override
082            public void mark(int readLimit) {
083                    markIndex = index;
084            }
085    
086            @Override
087            public boolean markSupported() {
088                    if (fileSize < threshold) {
089                            return true;
090                    }
091    
092                    return false;
093            }
094    
095            @Override
096            public int read() throws IOException {
097                    if (fileSize < threshold) {
098                            initData();
099    
100                            if (index < data.length) {
101                                    return data[index++] & 0xff;
102                            }
103                            else {
104                                    return -1;
105                            }
106                    }
107                    else {
108                            initFileInputStream();
109    
110                            return fileInputStream.read();
111                    }
112            }
113    
114            @Override
115            public int read(byte[] bytes) throws IOException {
116                    return read(bytes, 0, bytes.length);
117            }
118    
119            @Override
120            public int read(byte[] bytes, int offset, int length) throws IOException {
121                    if (length <= 0) {
122                            return 0;
123                    }
124    
125                    if (fileSize < threshold) {
126                            initData();
127    
128                            if (index >= data.length) {
129                                    return -1;
130                            }
131    
132                            int read = length;
133    
134                            if ((index + read) > data.length) {
135                                    read = data.length - index;
136                            }
137    
138                            System.arraycopy(data, index, bytes, offset, read);
139    
140                            index += read;
141    
142                            return read;
143                    }
144    
145                    initFileInputStream();
146    
147                    return fileInputStream.read(bytes, offset, length);
148            }
149    
150            @Override
151            public void reset() throws IOException {
152                    if (data != null) {
153                            index = markIndex;
154                    }
155                    else if (fileInputStream != null) {
156                            fileInputStream.close();
157    
158                            fileInputStream = null;
159                    }
160            }
161    
162            @Override
163            public long skip(long skip) throws IOException {
164                    if (skip < 0) {
165                            return 0;
166                    }
167    
168                    if (fileSize < threshold) {
169                            initData();
170    
171                            if ((skip + index) > data.length) {
172                                    skip = data.length - index;
173                            }
174    
175                            index += skip;
176    
177                            return skip;
178                    }
179    
180                    initFileInputStream();
181    
182                    return fileInputStream.skip(skip);
183            }
184    
185            protected void initData() throws IOException {
186                    if (data != null) {
187                            return;
188                    }
189    
190                    int arraySize = (int)this.fileSize;
191    
192                    data = new byte[arraySize];
193    
194                    FileInputStream fileInputStream = new FileInputStream(file);
195    
196                    int offset = 0;
197                    int length = 0;
198    
199                    try {
200                            while (offset < arraySize) {
201                                    length = fileInputStream.read(data, offset, arraySize - offset);
202    
203                                    offset += length;
204                            }
205                    }
206                    finally {
207                            fileInputStream.close();
208                    }
209            }
210    
211            protected void initFileInputStream() throws IOException {
212                    if (fileInputStream == null) {
213                            fileInputStream = new FileInputStream(file);
214                    }
215            }
216    
217            protected byte[] data;
218            protected boolean deleteOnClose;
219            protected File file;
220            protected FileInputStream fileInputStream;
221            protected long fileSize;
222            protected int index;
223            protected int markIndex;
224            protected int threshold;
225    
226    }