private static void registerDefaultProviders() { if (providers == null || defaultProvider == null) { Map<String, FilePath> map = Collections.synchronizedMap(New.<String, FilePath>hashMap()); // 默认是org.h2.store.fs.FilePathDisk, 所以这里不包含它 // 但是少了org.h2.store.fs.FilePathRec、org.h2.mvstore.cache.FilePathCache // 不过org.h2.store.fs.FilePathRec是通过org.h2.store.fs.FilePath.register(FilePath)这个方法注册 // 见org.h2.store.fs.FilePathRec.register(), // 在org.h2.engine.ConnectionInfo.ConnectionInfo(String, Properties)调用它了 for (String c : new String[] { "org.h2.store.fs.FilePathDisk", "org.h2.store.fs.FilePathMem", "org.h2.store.fs.FilePathMemLZF", "org.h2.store.fs.FilePathNioMem", "org.h2.store.fs.FilePathNioMemLZF", "org.h2.store.fs.FilePathSplit", "org.h2.store.fs.FilePathNio", "org.h2.store.fs.FilePathNioMapped", "org.h2.store.fs.FilePathZip" }) { try { FilePath p = (FilePath) Class.forName(c).newInstance(); map.put(p.getScheme(), p); if (defaultProvider == null) { defaultProvider = p; } } catch (Exception e) { // ignore - the files may be excluded in purpose } } providers = map; } }
@Override public FileChannel open(String mode) throws IOException { InputStream in = newInputStream(); FilePath copy = FilePath.get(getBase().toString() + ".copy"); OutputStream out = copy.newOutputStream(false); IOUtils.copy(in, out); FileChannel base = getBase().open(mode); FileChannel readBase = copy.open(mode); return new FileReorderWrites(this, base, readBase); }
public void delete() { for (int i = 0; ; i++) { FilePath f = getBase(i); if (f.exists()) { f.delete(); } else { break; } } }
public ArrayList<FilePath> newDirectoryStream() { List<FilePath> list = getBase().newDirectoryStream(); ArrayList<FilePath> newList = New.arrayList(); for (int i = 0, size = list.size(); i < size; i++) { FilePath f = list.get(i); if (!f.getName().endsWith(PART_SUFFIX)) { newList.add(wrap(f)); } } return newList; }
public void moveTo(FilePath path) { FilePathSplit newName = (FilePathSplit) path; for (int i = 0; ; i++) { FilePath o = getBase(i); if (o.exists()) { o.moveTo(newName.getBase(i)); } else { break; } } }
public long size() { long length = 0; for (int i = 0; ; i++) { FilePath f = getBase(i); if (f.exists()) { length += f.size(); } else { break; } } return length; }
public boolean setReadOnly() { boolean result = false; for (int i = 0; ; i++) { FilePath f = getBase(i); if (f.exists()) { result = f.setReadOnly(); } else { break; } } return result; }
private FileChannel getFileChannel() throws IOException { int id = (int) (filePointer / maxLength); while (id >= list.length) { int i = list.length; FileChannel[] newList = new FileChannel[i + 1]; System.arraycopy(list, 0, newList, 0, i); FilePath f = file.getBase(i); newList[i] = f.open(mode); list = newList; } return list[id]; }
public long lastModified() { long lastModified = 0; for (int i = 0; ; i++) { FilePath f = getBase(i); if (f.exists()) { long l = f.lastModified(); lastModified = Math.max(lastModified, l); } else { break; } } return lastModified; }
public InputStream newInputStream() throws IOException { InputStream input = getBase().newInputStream(); for (int i = 1; ; i++) { FilePath f = getBase(i); if (f.exists()) { InputStream i2 = f.newInputStream(); input = new SequenceInputStream(input, i2); } else { break; } } return input; }
/** * Create a new temporary file. * * @param suffix the suffix * @param deleteOnExit if the file should be deleted when the virtual machine exists * @param inTempDir if the file should be stored in the temporary directory * @return the name of the created file */ public FilePath createTempFile(String suffix, boolean deleteOnExit, boolean inTempDir) throws IOException { while (true) { FilePath p = getPath(name + getNextTempFileNamePart(false) + suffix); if (p.exists() || !p.createFile()) { // in theory, the random number could collide getNextTempFileNamePart(true); continue; } p.open("rw").close(); return p; } }
public FileChannel open(String mode) throws IOException { ArrayList<FileChannel> list = New.arrayList(); list.add(getBase().open(mode)); for (int i = 1; ; i++) { FilePath f = getBase(i); if (f.exists()) { list.add(f.open(mode)); } else { break; } } FileChannel[] array = new FileChannel[list.size()]; list.toArray(array); long maxLength = array[0].size(); long length = maxLength; if (array.length == 1) { long defaultMaxLength = getDefaultMaxLength(); if (maxLength < defaultMaxLength) { maxLength = defaultMaxLength; } } else { if (maxLength == 0) { closeAndThrow(0, array, array[0], maxLength); } for (int i = 1; i < array.length - 1; i++) { FileChannel c = array[i]; long l = c.size(); length += l; if (l != maxLength) { closeAndThrow(i, array, c, maxLength); } } FileChannel c = array[array.length - 1]; long l = c.size(); length += l; if (l > maxLength) { closeAndThrow(array.length - 1, array, c, maxLength); } } return new FileSplit(this, mode, array, length, maxLength); }
/** * Get the file path object for the given path. Windows-style '\' is replaced with '/'. * * @param path the path * @return the file path object */ public static FilePath get(String path) { path = path.replace('\\', '/'); int index = path.indexOf(':'); // 如E:\\H2\\tmp\\FileStoreTest\\my.txt // 此时index为1,所以要用FilePathDisk // 而memFS:E:\\H2\\tmp\\FileStoreTest\\my.txt // index是5,所以用FilePathMem registerDefaultProviders(); if (index < 2) { // use the default provider if no prefix or // only a single character (drive name) return defaultProvider.getPath(path); } String scheme = path.substring(0, index); FilePath p = providers.get(scheme); if (p == null) { // provider not found - use the default p = defaultProvider; } return p.getPath(path); }
/** * Register the file system. * * @return the instance */ public static FilePathReorderWrites register() { FilePath.register(INSTANCE); return INSTANCE; }
/** * Unregister a file provider. * * @param provider the file provider */ public static void unregister(FilePath provider) { registerDefaultProviders(); providers.remove(provider.getScheme()); }
/** * Register a file provider. * * @param provider the file provider */ public static void register(FilePath provider) { registerDefaultProviders(); providers.put(provider.getScheme(), provider); }
@Override public FilePath unwrap(String fileName) { return FilePath.get(parse(fileName)[1]); }
/** Register this file system. */ public static void register() { FilePath.register(new FilePathEncrypt()); }
/** * Try to open the file. * * @param fileName the file name * @param readOnly whether the file should only be opened in read-only mode, even if the file is * writable * @param encryptionKey the encryption key, or null if encryption is not used */ public void open(String fileName, boolean readOnly, char[] encryptionKey) { if (file != null) { return; } if (fileName != null) { FilePath p = FilePath.get(fileName); // if no explicit scheme was specified, NIO is used if (p instanceof FilePathDisk && !fileName.startsWith(p.getScheme() + ":")) { // ensure the NIO file system is registered FilePathNio.class.getName(); fileName = "nio:" + fileName; } } this.fileName = fileName; FilePath f = FilePath.get(fileName); FilePath parent = f.getParent(); if (parent != null && !parent.exists()) { throw DataUtils.newIllegalArgumentException("Directory does not exist: {0}", parent); } if (f.exists() && !f.canWrite()) { readOnly = true; } this.readOnly = readOnly; try { file = f.open(readOnly ? "r" : "rw"); if (encryptionKey != null) { byte[] key = FilePathEncrypt.getPasswordBytes(encryptionKey); encryptedFile = file; file = new FilePathEncrypt.FileEncrypt(fileName, key, file); } file = FilePathCache.wrap(file); try { if (readOnly) { fileLock = file.tryLock(0, Long.MAX_VALUE, true); } else { fileLock = file.tryLock(); } } catch (OverlappingFileLockException e) { throw DataUtils.newIllegalStateException( DataUtils.ERROR_FILE_LOCKED, "The file is locked: {0}", fileName, e); } if (fileLock == null) { throw DataUtils.newIllegalStateException( DataUtils.ERROR_FILE_LOCKED, "The file is locked: {0}", fileName); } fileSize = file.size(); } catch (IOException e) { throw DataUtils.newIllegalStateException( DataUtils.ERROR_READING_FAILED, "Could not open file {0}", fileName, e); } }
/** * Get the file name of a part file. * * @param id the part id * @return the file name including the part id */ FilePath getBase(int id) { return FilePath.get(getName(id)); }