001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.store.fs;
007:
008: import java.io.FileNotFoundException;
009: import java.io.IOException;
010: import java.io.InputStream;
011: import java.io.OutputStream;
012: import java.sql.SQLException;
013: import java.util.ArrayList;
014: import java.util.Enumeration;
015: import java.util.zip.ZipEntry;
016: import java.util.zip.ZipFile;
017:
018: import org.h2.message.Message;
019:
020: /**
021: * This is a read-only file system that allows
022: * to access databases stored in a .zip or .jar file.
023: */
024: public class FileSystemZip extends FileSystem {
025:
026: private static final FileSystemZip INSTANCE = new FileSystemZip();
027:
028: private FileSystemZip() {
029: }
030:
031: public static FileSystemZip getInstance() {
032: return INSTANCE;
033: }
034:
035: public boolean canWrite(String fileName) {
036: return false;
037: }
038:
039: public void copy(String original, String copy) throws SQLException {
040: throw Message.getUnsupportedException();
041: }
042:
043: public void createDirs(String fileName) throws SQLException {
044: // ignore
045: }
046:
047: public boolean createNewFile(String fileName) throws SQLException {
048: throw Message.getUnsupportedException();
049: }
050:
051: public String createTempFile(String prefix, String suffix,
052: boolean deleteOnExit, boolean inTempDir) throws IOException {
053: throw new IOException("File system is read-only");
054: }
055:
056: public void delete(String fileName) throws SQLException {
057: throw Message.getUnsupportedException();
058: }
059:
060: public void deleteRecursive(String fileName) throws SQLException {
061: throw Message.getUnsupportedException();
062: }
063:
064: public boolean exists(String fileName) {
065: try {
066: String entryName = getEntryName(fileName);
067: if (entryName.length() == 0) {
068: return true;
069: }
070: ZipFile file = openZipFile(fileName);
071: return file.getEntry(entryName) != null;
072: } catch (IOException e) {
073: return false;
074: }
075: }
076:
077: public boolean fileStartsWith(String fileName, String prefix) {
078: return fileName.startsWith(prefix);
079: }
080:
081: public String getAbsolutePath(String fileName) {
082: return fileName;
083: }
084:
085: public String getFileName(String name) throws SQLException {
086: name = getEntryName(name);
087: if (name.endsWith("/")) {
088: name = name.substring(0, name.length() - 1);
089: }
090: int idx = name.lastIndexOf('/');
091: if (idx >= 0) {
092: name = name.substring(idx + 1);
093: }
094: return name;
095: }
096:
097: public long getLastModified(String fileName) {
098: return 0;
099: }
100:
101: public String getParent(String fileName) {
102: int idx = fileName.lastIndexOf('/');
103: if (idx > 0) {
104: fileName = fileName.substring(0, idx);
105: }
106: return fileName;
107: }
108:
109: public boolean isAbsolute(String fileName) {
110: return true;
111: }
112:
113: public boolean isDirectory(String fileName) {
114: try {
115: String entryName = getEntryName(fileName);
116: if (entryName.length() == 0) {
117: return true;
118: }
119: ZipFile file = openZipFile(fileName);
120: Enumeration en = file.entries();
121: while (en.hasMoreElements()) {
122: ZipEntry entry = (ZipEntry) en.nextElement();
123: String n = entry.getName();
124: if (n.equals(entryName)) {
125: return entry.isDirectory();
126: } else if (n.startsWith(entryName)) {
127: if (n.length() == entryName.length() + 1) {
128: if (n.equals(entryName + "/")) {
129: return true;
130: }
131: }
132: }
133: }
134: return false;
135: } catch (IOException e) {
136: return false;
137: }
138: }
139:
140: public boolean isReadOnly(String fileName) {
141: return true;
142: }
143:
144: public long length(String fileName) {
145: try {
146: ZipFile file = openZipFile(fileName);
147: ZipEntry entry = file.getEntry(getEntryName(fileName));
148: return entry == null ? 0 : entry.getSize();
149: } catch (IOException e) {
150: return 0;
151: }
152: }
153:
154: public String[] listFiles(String path) throws SQLException {
155: try {
156: if (path.indexOf('!') < 0) {
157: path += "!";
158: }
159: if (!path.endsWith("/")) {
160: path += "/";
161: }
162: ZipFile file = openZipFile(path);
163: String dirName = getEntryName(path);
164: String prefix = path.substring(0, path.length()
165: - dirName.length());
166: Enumeration en = file.entries();
167: ArrayList list = new ArrayList();
168: while (en.hasMoreElements()) {
169: ZipEntry entry = (ZipEntry) en.nextElement();
170: String name = entry.getName();
171: if (!name.startsWith(dirName)) {
172: continue;
173: }
174: if (name.length() <= dirName.length()) {
175: continue;
176: }
177: int idx = name.indexOf('/', dirName.length());
178: if (idx < 0 || idx >= name.length() - 1) {
179: list.add(prefix + name);
180: }
181: }
182: String[] result = new String[list.size()];
183: list.toArray(result);
184: return result;
185: } catch (IOException e) {
186: throw Message.convertIOException(e, "listFiles " + path);
187: }
188: }
189:
190: public String normalize(String fileName) throws SQLException {
191: return fileName;
192: }
193:
194: public InputStream openFileInputStream(String fileName)
195: throws IOException {
196: FileObject file = openFileObject(fileName, "r");
197: return new FileObjectInputStream(file);
198: }
199:
200: public FileObject openFileObject(String fileName, String mode)
201: throws IOException {
202: ZipFile file = openZipFile(translateFileName(fileName));
203: ZipEntry entry = file.getEntry(getEntryName(fileName));
204: if (entry == null) {
205: throw new FileNotFoundException(fileName);
206: }
207: return new FileObjectZip(file, entry);
208: }
209:
210: public OutputStream openFileOutputStream(String fileName,
211: boolean append) throws SQLException {
212: throw Message.getUnsupportedException();
213: }
214:
215: public void rename(String oldName, String newName)
216: throws SQLException {
217: throw Message.getUnsupportedException();
218: }
219:
220: public boolean tryDelete(String fileName) {
221: return false;
222: }
223:
224: private String translateFileName(String fileName) {
225: if (fileName.startsWith(FileSystem.ZIP_PREFIX)) {
226: fileName = fileName.substring(FileSystem.ZIP_PREFIX
227: .length());
228: }
229: int idx = fileName.indexOf('!');
230: if (idx >= 0) {
231: fileName = fileName.substring(0, idx);
232: }
233: return fileName;
234: }
235:
236: private String getEntryName(String fileName) {
237: int idx = fileName.indexOf('!');
238: if (idx <= 0) {
239: fileName = "";
240: } else {
241: fileName = fileName.substring(idx + 1);
242: }
243: fileName = fileName.replace('\\', '/');
244: if (fileName.startsWith("/")) {
245: fileName = fileName.substring(1);
246: }
247: return fileName;
248: }
249:
250: private ZipFile openZipFile(String fileName) throws IOException {
251: fileName = translateFileName(fileName);
252: return new ZipFile(fileName);
253: }
254: }
|