/**
* Copyright (C) 2010-2017 Structr GmbH
*
* This file is part of Structr <http://structr.org>.
*
* Structr is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Structr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Structr. If not, see <http://www.gnu.org/licenses/>.
*/
package org.structr.files.ssh.filesystem;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.channels.FileChannel;
import java.nio.file.AccessMode;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.LinkOption;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.structr.common.error.FrameworkException;
import org.structr.files.ssh.filesystem.path.file.StructrFilePath;
import org.structr.web.entity.dom.DOMElement;
import org.structr.web.entity.dom.DOMNode;
/**
*
*/
public abstract class StructrPath implements Path {
private static final Logger logger = LoggerFactory.getLogger(StructrPath.class.getName());
public static final Map<String, HiddenFileEntry> HIDDEN_PROPERTY_FILES = new ConcurrentHashMap<>();
public static final String ROOT_DIRECTORY = "/";
public static final String CURRENT_DIRECTORY = ".";
public static final String SCHEMA_DIRECTORY = "schema";
public static final String PAGE_DIRECTORY = "pages";
public static final String GRAPH_DIRECTORY = "graph";
public static final String FILES_DIRECTORY = "files";
public static final String COMPONENTS_DIRECTORY = "components";
protected StructrFilesystem fs = null;
protected StructrPath parent = null;
protected String name = null;
public StructrPath(final StructrFilesystem fs) {
this(fs, null, null);
}
public StructrPath(final StructrFilesystem fs, final StructrPath parent, final String name) {
this.parent = parent;
this.name = name;
this.fs = fs;
}
// ----- public abstract methods -----
public abstract DirectoryStream<Path> getDirectoryStream(final DirectoryStream.Filter<? super Path> filter);
public abstract FileChannel newFileChannel(final Set<? extends OpenOption> options, final FileAttribute<?>... attrs) throws IOException;
public abstract <T extends BasicFileAttributes> T getAttributes(final Class<T> type, final LinkOption... options) throws IOException;
public abstract <V extends FileAttributeView> V getFileAttributeView(final Class<V> type, final LinkOption... options) throws IOException;
public abstract Map<String, Object> getAttributes(final String attributes, final LinkOption... options) throws IOException;
public abstract void createDirectory(final FileAttribute<?>... attrs) throws IOException;
public abstract void delete() throws IOException;
public abstract void copy(final Path target, final CopyOption... options) throws IOException;
public abstract void move(final Path target, final CopyOption... options) throws IOException;
public abstract void setAttribute(final String attribute, final Object value, LinkOption... options) throws IOException;
public abstract boolean isSameFile(final Path path2) throws IOException;
public abstract StructrPath resolveStructrPath(final String pathComponent) throws FrameworkException;
// ----- public methods -----
public void checkAccess(final AccessMode... modes) {
//logger.info("{}: {}", new Object[] { toString(), Arrays.asList(modes) });
}
public void enablePropertyFile(final String name) {
}
public boolean hasPropertyFile(final String name) {
return true;
}
public boolean dontCache() {
return false;
}
// ----- interface Path -----
@Override
public String toString() {
final StringBuilder buf = new StringBuilder();
if (parent != null) {
final String parentPath = parent.toString();
if (!"/".equals(parentPath)) {
buf.append(parentPath);
}
buf.append("/");
}
if (name != null) {
buf.append(name);
}
return buf.toString();
}
@Override
public FileSystem getFileSystem() {
return fs;
}
@Override
public boolean isAbsolute() {
// ask parent
if (parent != null) {
return parent.isAbsolute();
}
return name == null;
}
@Override
public Path getRoot() {
if (isAbsolute()) {
return parent.getRoot();
}
return null;
}
@Override
public Path getParent() {
return parent;
}
@Override
public Path getFileName() {
if (name != null) {
return new StructrFilePath(fs, null, name);
}
return null;
}
@Override
public int getNameCount() {
if (parent != null) {
return parent.getNameCount() + 1;
}
if (name != null) {
return 1;
}
return 0;
}
@Override
public Path getName(int index) {
final List<Path> paths = new ArrayList<>();
Path path = this;
paths.add(this);
// find root
while (path.getParent() != null) {
path = path.getParent();
paths.add(0, path);
}
return paths.get(index);
}
@Override
public Path subpath(int beginIndex, int endIndex) {
logger.info("{}, {}", new Object[] { beginIndex, endIndex });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean startsWith(Path other) {
logger.info("{}, {}", new Object[] { other });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean startsWith(String other) {
logger.info("{}, {}", new Object[] { other });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean endsWith(Path other) {
logger.info("{}, {}", new Object[] { other });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public boolean endsWith(String other) {
logger.info("{}, {}", new Object[] { other });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Path normalize() {
return this;
}
@Override
public Path resolve(Path other) {
if (other.isAbsolute()) {
return other;
}
logger.info("{}", new Object[] { other });
return null;
}
@Override
public Path resolve(final String other) {
if (other.startsWith(ROOT_DIRECTORY)) {
return fs.getPath(other);
}
if (CURRENT_DIRECTORY.equals(other)) {
return this;
}
logger.info("{}", new Object[] { other });
return null;
}
@Override
public Path resolveSibling(Path other) {
logger.info("{}, {}", new Object[] { other });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Path resolveSibling(String other) {
logger.info("{}, {}", new Object[] { other });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Path relativize(Path other) {
logger.info("{}, {}", new Object[] { other });
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public URI toUri() {
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Path toAbsolutePath() {
if (isAbsolute()) {
return this;
}
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Path toRealPath(LinkOption... options) throws IOException {
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public File toFile() {
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public WatchKey register(WatchService watcher, WatchEvent.Kind<?>[] events, WatchEvent.Modifier... modifiers) throws IOException {
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public WatchKey register(WatchService watcher, WatchEvent.Kind<?>... events) throws IOException {
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public Iterator<Path> iterator() {
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@Override
public int compareTo(Path other) {
logger.info("x");
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
// ----- protected methods -----
protected String normalizeFileNameForJavaIdentifier(final String src) {
String dst = src;
dst = dst.replace('/', '_');
dst = dst.replace('.', '_');
dst = dst.replace('-', '_');
dst = dst.replace('+', '_');
dst = dst.replace('~', '_');
dst = dst.replace('#', '_');
dst = dst.replace('\'', '_');
dst = dst.replace('\"', '_');
dst = dst.replace('`', '_');
dst = dst.replace('(', '_');
dst = dst.replace(')', '_');
dst = dst.replace('[', '_');
dst = dst.replace(']', '_');
dst = dst.replace('{', '_');
dst = dst.replace('}', '_');
dst = dst.replace('!', '_');
dst = dst.replace('$', '_');
dst = dst.replace('§', '_');
dst = dst.replace('%', '_');
dst = dst.replace('&', '_');
dst = dst.replace('=', '_');
dst = dst.replace(':', '_');
dst = dst.replace('<', '_');
dst = dst.replace('>', '_');
dst = dst.replace('|', '_');
dst = dst.replace('^', '_');
dst = dst.replace('°', '_');
return dst;
}
protected String getName(final String tagName, final DOMNode node, final int position) {
final StringBuilder buf = new StringBuilder();
final int localPosition = getDomPosition(node, position);
if (localPosition < 10) {
buf.append("0");
}
if (localPosition < 100) {
buf.append("0");
}
if (localPosition < 1000) {
buf.append("0");
}
buf.append(localPosition);
buf.append("-");
if (node != null) {
if(node instanceof DOMElement) {
final DOMElement elem = (DOMElement)node;
buf.append(elem.getTagName());
} else {
// test
buf.append(node.getType().toLowerCase());
}
} else if (tagName != null) {
buf.append(tagName);
}
return buf.toString();
}
protected int getDomPosition(final DOMNode node, final int index) {
Integer localPosition = (index + 1) * 100;
if (node != null) {
final Integer storedPosition = node.getProperty(DOMNode.domSortPosition);
if (storedPosition != null) {
localPosition = storedPosition;
}
}
return localPosition;
}
// ----- nested classes -----
public static class HiddenFileEntry {
private final Set<String> dynamicNames = new LinkedHashSet<>();
private final Set<String> names = new LinkedHashSet<>();
public void add(final String name) {
names.add(name);
}
public boolean has(final String name) {
return names.contains(name);
}
public void remove(final String name) {
names.remove(name);
}
public boolean isEmpty() {
return names.isEmpty();
}
public void addDynamicWithValue(final String name) {
dynamicNames.add(name);
}
public boolean hasDynamicWithValue(final String name) {
return dynamicNames.contains(name);
}
public void removeDynamicWithValue(final String name) {
dynamicNames.remove(name);
}
}
}