001    /**
002     * Copyright (c) 2000-2013 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) {
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                    return fileSize < threshold;
089            }
090    
091            @Override
092            public int read() throws IOException {
093                    if (fileSize < threshold) {
094                            initData();
095    
096                            if (index < data.length) {
097                                    return data[index++] & 0xff;
098                            }
099                            else {
100                                    return -1;
101                            }
102                    }
103                    else {
104                            initFileInputStream();
105    
106                            return fileInputStream.read();
107                    }
108            }
109    
110            @Override
111            public int read(byte[] bytes) throws IOException {
112                    return read(bytes, 0, bytes.length);
113            }
114    
115            @Override
116            public int read(byte[] bytes, int offset, int length) throws IOException {
117                    if (length <= 0) {
118                            return 0;
119                    }
120    
121                    if (fileSize < threshold) {
122                            initData();
123    
124                            if (index >= data.length) {
125                                    return -1;
126                            }
127    
128                            int read = length;
129    
130                            if ((index + read) > data.length) {
131                                    read = data.length - index;
132                            }
133    
134                            System.arraycopy(data, index, bytes, offset, read);
135    
136                            index += read;
137    
138                            return read;
139                    }
140    
141                    initFileInputStream();
142    
143                    return fileInputStream.read(bytes, offset, length);
144            }
145    
146            @Override
147            public void reset() throws IOException {
148                    if (data != null) {
149                            index = markIndex;
150                    }
151                    else if (fileInputStream != null) {
152                            fileInputStream.close();
153    
154                            fileInputStream = null;
155                    }
156            }
157    
158            @Override
159            public long skip(long skip) throws IOException {
160                    if (skip < 0) {
161                            return 0;
162                    }
163    
164                    if (fileSize < threshold) {
165                            initData();
166    
167                            if ((skip + index) > data.length) {
168                                    skip = data.length - index;
169                            }
170    
171                            index += skip;
172    
173                            return skip;
174                    }
175    
176                    initFileInputStream();
177    
178                    return fileInputStream.skip(skip);
179            }
180    
181            protected void initData() throws IOException {
182                    if (data != null) {
183                            return;
184                    }
185    
186                    int arraySize = (int)this.fileSize;
187    
188                    data = new byte[arraySize];
189    
190                    FileInputStream fileInputStream = new FileInputStream(file);
191    
192                    int offset = 0;
193                    int length = 0;
194    
195                    try {
196                            while (offset < arraySize) {
197                                    length = fileInputStream.read(data, offset, arraySize - offset);
198    
199                                    offset += length;
200                            }
201                    }
202                    finally {
203                            fileInputStream.close();
204                    }
205            }
206    
207            protected void initFileInputStream() throws IOException {
208                    if (fileInputStream == null) {
209                            fileInputStream = new FileInputStream(file);
210                    }
211            }
212    
213            protected byte[] data;
214            protected boolean deleteOnClose;
215            protected File file;
216            protected FileInputStream fileInputStream;
217            protected long fileSize;
218            protected int index;
219            protected int markIndex;
220            protected int threshold;
221    
222    }