/*
* Copyright (c) 2008-2019 Emmanuel Dupuy.
* This project is distributed under the GPLv3 license.
* This is a Copyleft license that gives the user the right to use,
* copy and modify the code freely for non-commercial purposes.
*/
package org.jd.gui.model.container;
import org.jd.gui.api.API;
import org.jd.gui.api.model.Container;
import org.jd.gui.spi.ContainerFactory;
import org.jd.gui.util.exception.ExceptionUtil;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
public class GenericContainer implements Container {
protected static final long TIMESTAMP = System.currentTimeMillis();
protected static long tmpFileCounter = 0;
protected API api;
protected int rootNameCount;
protected Container.Entry root;
public GenericContainer(API api, Container.Entry parentEntry, Path rootPath) {
try {
URI uri = parentEntry.getUri();
this.api = api;
this.rootNameCount = rootPath.getNameCount();
this.root = new Entry(parentEntry, rootPath, new URI(uri.getScheme(), uri.getHost(), uri.getPath() + "!/", null)) {
public Entry newChildEntry(Path fsPath) {
return new Entry(parent, fsPath, null);
}
};
} catch (URISyntaxException e) {
assert ExceptionUtil.printStackTrace(e);
}
}
public String getType() { return "generic"; }
public Container.Entry getRoot() { return root; }
protected class Entry implements Container.Entry {
protected Container.Entry parent;
protected Path fsPath;
protected String strPath;
protected URI uri;
protected Boolean isDirectory;
protected Collection<Container.Entry> children;
public Entry(Container.Entry parent, Path fsPath, URI uri) {
this.parent = parent;
this.fsPath = fsPath;
this.strPath = null;
this.uri = uri;
this.isDirectory = null;
this.children = null;
}
public Entry newChildEntry(Path fsPath) { return new Entry(this, fsPath, null); }
public Container getContainer() { return GenericContainer.this; }
public Container.Entry getParent() { return parent; }
public URI getUri() {
if (uri == null) {
try {
URI rootUri = root.getUri();
uri = new URI(rootUri.getScheme(), rootUri.getHost(), rootUri.getPath() + getPath(), null);
} catch (URISyntaxException e) {
assert ExceptionUtil.printStackTrace(e);
}
}
return uri;
}
public String getPath() {
if (strPath == null) {
int nameCount = fsPath.getNameCount();
if (rootNameCount == nameCount) {
strPath = "";
} else {
strPath = fsPath.subpath(rootNameCount, nameCount).toString().replace(fsPath.getFileSystem().getSeparator(), "/");
int strPathLength = strPath.length();
if ((strPathLength > 0) && strPath.charAt(strPathLength-1) == '/') {
// Cut last separator
strPath = strPath.substring(0, strPathLength-1);
}
}
}
return strPath;
}
public boolean isDirectory() {
if (isDirectory == null) {
isDirectory = Boolean.valueOf(Files.isDirectory(fsPath));
}
return isDirectory;
}
public long length() {
try {
return Files.size(fsPath);
} catch (IOException e) {
assert ExceptionUtil.printStackTrace(e);
return -1L;
}
}
public InputStream getInputStream() {
try {
return Files.newInputStream(fsPath);
} catch (IOException e) {
assert ExceptionUtil.printStackTrace(e);
return null;
}
}
public Collection<Container.Entry> getChildren() {
if (children == null) {
try {
if (Files.isDirectory(fsPath)) {
children = loadChildrenFromDirectoryEntry();
} else {
children = loadChildrenFromFileEntry();
}
} catch (IOException e) {
assert ExceptionUtil.printStackTrace(e);
}
}
return children;
}
protected Collection<Container.Entry> loadChildrenFromDirectoryEntry() throws IOException {
try (DirectoryStream<Path> stream = Files.newDirectoryStream(fsPath)) {
ArrayList<Container.Entry> children = new ArrayList<>();
int parentNameCount = fsPath.getNameCount();
for (Path subPath : stream) {
if (subPath.getNameCount() > parentNameCount) {
children.add(newChildEntry(subPath));
}
}
children.sort(ContainerEntryComparator.COMPARATOR);
return Collections.unmodifiableCollection(children);
}
}
protected Collection<Container.Entry> loadChildrenFromFileEntry() throws IOException {
StringBuilder suffix = new StringBuilder(".").append(TIMESTAMP).append('.').append(tmpFileCounter++).append('.').append(fsPath.getFileName().toString());
File tmpFile = File.createTempFile("jd-gui.tmp.", suffix.toString());
Path tmpPath = Paths.get(tmpFile.toURI());
tmpFile.delete();
tmpFile.deleteOnExit();
Files.copy(fsPath, tmpPath);
FileSystem subFileSystem = FileSystems.newFileSystem(tmpPath, null);
if (subFileSystem != null) {
Iterator<Path> rootDirectories = subFileSystem.getRootDirectories().iterator();
if (rootDirectories.hasNext()) {
Path rootPath = rootDirectories.next();
ContainerFactory containerFactory = api.getContainerFactory(rootPath);
if (containerFactory != null) {
Container container = containerFactory.make(api, this, rootPath);
if (container != null) {
return container.getRoot().getChildren();
}
}
}
}
tmpFile.delete();
return Collections.emptyList();
}
}
}