blob: 08911a38d7daddf0f629414be9186b793e17baf9 [file] [log] [blame]
/*
* Copyright (c) 2011, the Dart project authors.
*
* Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.eclipse.org/legal/epl-v10.html
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package com.google.dart.indexer.pagedstorage.filesystem;
import com.google.dart.indexer.pagedstorage.exceptions.PagedStorageException;
import com.google.dart.indexer.pagedstorage.util.IOUtils;
import com.google.dart.indexer.pagedstorage.util.ObjectArray;
import com.google.dart.indexer.pagedstorage.util.RandomUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Iterator;
/**
* This file system keeps files fully in memory. There is an option to compress file blocks to safe
* memory.
*/
public class InMemoryFileSystem extends FileSystem {
private static final InMemoryFileSystem INSTANCE = new InMemoryFileSystem();
private static final HashMap<String, InMemoryFileObject> MEMORY_FILES = new HashMap<String, InMemoryFileObject>();
public static InMemoryFileSystem getInstance() {
return INSTANCE;
}
private InMemoryFileSystem() {
// don't allow construction
}
@Override
public boolean canWrite(String fileName) {
return true;
}
@Override
public void copy(String original, String copy) throws PagedStorageException {
try {
OutputStream out = openFileOutputStream(copy, false);
InputStream in = openFileInputStream(original);
IOUtils.copyAndClose(in, out);
} catch (IOException e) {
throw new RuntimeException(e);
// throw Message.convertIOException(e, "Can not copy " + original + " to "
// + copy);
}
}
@Override
public void createDirs(String fileName) {
// TODO directories are not really supported
}
@Override
public boolean createNewFile(String fileName) {
synchronized (MEMORY_FILES) {
if (exists(fileName)) {
return false;
}
getObjectFile(fileName);
}
return true;
}
@Override
public String createTempFile(String name, String suffix, boolean deleteOnExit, boolean inTempDir) {
name += ".";
synchronized (MEMORY_FILES) {
while (true) {
String n = name + (RandomUtils.getSecureLong() >>> 1) + suffix;
if (!exists(n)) {
getObjectFile(n);
return n;
}
}
}
}
@Override
public void delete(String fileName) {
fileName = normalize(fileName);
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
}
}
@Override
public void deleteRecursive(String fileName) {
fileName = normalize(fileName);
synchronized (MEMORY_FILES) {
Iterator<String> it = MEMORY_FILES.keySet().iterator();
while (it.hasNext()) {
String name = it.next();
if (name.startsWith(fileName)) {
it.remove();
}
}
}
}
@Override
public boolean exists(String fileName) {
fileName = normalize(fileName);
synchronized (MEMORY_FILES) {
return MEMORY_FILES.get(fileName) != null;
}
}
public boolean fileStartsWith(String fileName, String prefix) {
fileName = normalize(fileName);
prefix = normalize(prefix);
return fileName.startsWith(prefix);
}
@Override
public String getAbsolutePath(String fileName) {
// TODO relative files are not supported
return normalize(fileName);
}
@Override
public String getFileName(String name) {
// TODO directories are not supported
return name;
}
@Override
public long getLastModified(String fileName) {
return getObjectFile(fileName).getLastModified();
}
@Override
public String getParent(String fileName) {
fileName = normalize(fileName);
int idx = fileName.lastIndexOf('/');
if (idx < 0) {
idx = fileName.indexOf(':') + 1;
}
return fileName.substring(0, idx);
}
@Override
public boolean isAbsolute(String fileName) {
// TODO relative files are not supported
return true;
}
@Override
public boolean isDirectory(String fileName) {
// TODO in memory file system currently doesn't support directories
return false;
}
@Override
public boolean isReadOnly(String fileName) {
return false;
}
@Override
public long length(String fileName) {
return getObjectFile(fileName).length();
}
@Override
public String[] listFiles(String path) {
ObjectArray<String> list = ObjectArray.newInstance();
synchronized (MEMORY_FILES) {
for (Iterator<String> iterator = MEMORY_FILES.keySet().iterator(); iterator.hasNext();) {
String name = iterator.next();
if (name.startsWith(path)) {
list.add(name);
}
}
String[] array = new String[list.size()];
list.toArray(array);
return array;
}
}
@Override
public String normalize(String fileName) {
fileName = fileName.replace('\\', '/');
int idx = fileName.indexOf(":/");
if (idx > 0) {
fileName = fileName.substring(0, idx + 1) + fileName.substring(idx + 2);
}
return fileName;
}
@Override
public InputStream openFileInputStream(String fileName) {
InMemoryFileObject obj = getObjectFile(fileName);
obj.seek(0);
return new FileObjectInputStream(obj);
}
@Override
public FileObject openFileObject(String fileName, AccessMode mode) {
InMemoryFileObject obj = getObjectFile(fileName);
obj.seek(0);
return obj;
}
@Override
public OutputStream openFileOutputStream(String fileName, boolean append)
throws PagedStorageException {
try {
InMemoryFileObject obj = getObjectFile(fileName);
obj.seek(0);
return new FileObjectOutputStream(obj, append);
} catch (IOException e) {
throw new RuntimeException(e);
// throw Message.convertIOException(e, fileName);
}
}
@Override
public void rename(String oldName, String newName) {
oldName = normalize(oldName);
newName = normalize(newName);
synchronized (MEMORY_FILES) {
InMemoryFileObject f = getObjectFile(oldName);
f.setName(newName);
MEMORY_FILES.remove(oldName);
MEMORY_FILES.put(newName, f);
}
}
@Override
public boolean tryDelete(String fileName) {
fileName = normalize(fileName);
synchronized (MEMORY_FILES) {
MEMORY_FILES.remove(fileName);
}
return true;
}
private InMemoryFileObject getObjectFile(String fileName) {
fileName = normalize(fileName);
synchronized (MEMORY_FILES) {
InMemoryFileObject m = MEMORY_FILES.get(fileName);
if (m == null) {
m = new InMemoryFileObject(fileName);
MEMORY_FILES.put(fileName, m);
}
return m;
}
}
}