/*
* Copyright 2013 eXo Platform SAS
*
* Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
*
* 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 juzu.impl.fs.spi.disk;
import juzu.impl.common.Name;
import juzu.impl.common.Resource;
import juzu.impl.common.Timestamped;
import juzu.impl.fs.spi.PathType;
import juzu.impl.fs.spi.ReadWriteFileSystem;
import juzu.impl.common.Tools;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class DiskFileSystem extends ReadWriteFileSystem<File> {
/** . */
private final File root;
/** . */
private FilenameFilter filter;
/** . */
private Charset encoding;
public DiskFileSystem(File root) {
this(root, new FilenameFilter() {
public boolean accept(File dir, String name) {
return true;
}
});
}
public DiskFileSystem(File root, FilenameFilter filter) {
this.root = root;
this.filter = filter;
this.encoding = Charset.defaultCharset();
}
public DiskFileSystem(final File root, final Name path) {
this(root, new FilterImpl(root, path));
}
public DiskFileSystem(final File root, final String path) {
this(root, new FilterImpl(root, Name.parse(path)));
}
public void applyFilter(String path) {
filter = new FilterImpl(root, Name.parse(path));
}
@Override
public Class<File> getType() {
return File.class;
}
@Override
public String getDescription() {
return "disk[" + root.getAbsolutePath() + "]";
}
@Override
public boolean equals(File left, File right) {
return left.equals(right);
}
@Override
public File getRoot() {
return root;
}
@Override
public PathType typeOf(File path) throws IOException {
if (path.isDirectory()) {
return PathType.DIR;
} else if (path.isFile()) {
return PathType.FILE;
} else {
return null;
}
}
@Override
public String getName(File path) {
if (path.equals(root)) {
return "";
}
else {
return path.getName();
}
}
@Override
public Iterable<String> getNames(File path) {
LinkedList<String> names = new LinkedList<String>();
while (!path.equals(root)) {
names.addFirst(path.getName());
path = path.getParentFile();
}
return names;
}
@Override
public Iterator<File> getChildren(File dir) throws IOException {
File[] children = dir.listFiles(filter);
return children == null ? Tools.<File>emptyIterator() : Arrays.asList(children).iterator();
}
@Override
public File getChild(File dir, String name) throws IOException {
if (filter.accept(dir, name)) {
File child = new File(dir, name);
if (child.exists()) {
return child;
}
}
return null;
}
@Override
public Timestamped<Resource> getResource(File file) throws IOException {
FileInputStream in = new FileInputStream(file);
try {
ByteArrayOutputStream resource = new ByteArrayOutputStream();
byte[] buffer = new byte[256];
for (int l = in.read(buffer);l != -1;l = in.read(buffer)) {
resource.write(buffer, 0, l);
}
return new Timestamped<Resource>(file.lastModified(), new Resource(resource.toByteArray(), encoding));
}
finally {
Tools.safeClose(in);
}
}
@Override
public long getLastModified(File path) throws IOException {
return path.lastModified();
}
@Override
public URL getURL(File path) throws IOException {
return path.toURI().toURL();
}
@Override
public File getFile(File path) {
return path;
}
@Override
public File makePath(File parent, String name) throws IOException {
return new File(parent, name);
}
@Override
public void createDir(File dir) throws IOException {
if (dir.exists()) {
if (dir.isDirectory()) {
// Ok
} else {
throw new IOException("Dir already exists and is a file " + dir.getCanonicalPath());
}
} else {
if (dir.mkdirs()) {
// Ok
} else {
throw new IOException("Could not create dir " + dir.getCanonicalPath());
}
}
}
@Override
public long updateResource(File file, Resource resource) throws IOException {
File parent = file.getParentFile();
if (parent != null) {
if (!parent.exists()) {
if (!parent.mkdirs()) {
throw new IOException("Could not create parent directory " + parent.getCanonicalPath());
}
}
}
InputStream in = resource.getInputStream();
FileOutputStream out = new FileOutputStream(file);
try {
Tools.copy(in, out);
}
finally {
Tools.safeClose(out);
}
return file.lastModified();
}
@Override
public boolean removePath(File path) throws IOException {
return path.delete();
}
@Override
public String toString() {
return "DiskFileSystem[root=" + root.getAbsolutePath() + "]";
}
}