Last active
March 2, 2023 20:19
-
-
Save ag88/5d8c5246bf200f25159348d315109552 to your computer and use it in GitHub Desktop.
webdav-nio-filesystem-provider
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright 2012-2013 University of Stavanger, Norway | |
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. | |
note: codes has been edited by ag88 and is not original | |
*/ | |
package no.maddin.niofs.webdav; | |
import java.io.IOException; | |
import java.net.URI; | |
import java.net.ProxySelector; | |
import java.nio.file.FileStore; | |
import java.nio.file.FileSystem; | |
import java.nio.file.Path; | |
import java.nio.file.PathMatcher; | |
import java.nio.file.WatchService; | |
import java.nio.file.attribute.UserPrincipalLookupService; | |
import java.nio.file.spi.FileSystemProvider; | |
import java.util.ArrayList; | |
import java.util.Iterator; | |
import java.util.Set; | |
import java.util.concurrent.TimeUnit; | |
import com.github.benmanes.caffeine.cache.Cache; | |
import com.github.benmanes.caffeine.cache.Caffeine; | |
import com.github.sardine.Sardine; | |
import com.github.sardine.SardineFactory; | |
/** | |
* WebDAV implementation of a FileSystem. | |
*/ | |
public class WebdavFileSystem extends FileSystem { | |
private final FileSystemProvider provider; | |
private final int port; | |
private final String host; | |
private final String password; | |
private final String username; | |
private String rootpath; | |
Cache<Path, WebdavFileAttributes> attcache; | |
/** | |
* | |
* @param provider an instance of a WebdavFileSystemProvided. This can be a shared instance. | |
* @param serverUri URI for the WEBDAV server, the scheme is ignored. | |
*/ | |
public WebdavFileSystem(WebdavFileSystemProvider provider, URI serverUri) { | |
this.provider = provider; | |
this.host = serverUri.getHost(); | |
this.port = serverUri.getPort(); | |
if (serverUri.getUserInfo() != null) { | |
String[] ui = serverUri.getUserInfo().split(":"); | |
this.username = ui[0]; | |
if(ui.length > 1) | |
this.password = ui[1]; | |
else | |
this.password = null; | |
} else { | |
this.username = null; | |
this.password = null; | |
} | |
this.rootpath = getSeparator(); | |
if( serverUri.getPath() != null && ! serverUri.getPath().equals("")) | |
this.rootpath = serverUri.getPath(); | |
this.attcache = Caffeine.newBuilder() | |
.expireAfterWrite(5, TimeUnit.MINUTES) | |
.maximumSize(1000) | |
.build(); | |
} | |
@Override | |
public FileSystemProvider provider() { | |
return provider; | |
} | |
/** | |
* Not implemented | |
*/ | |
@Override | |
public void close() throws IOException { | |
} | |
/** | |
* Not implemented | |
* @return null | |
*/ | |
@Override | |
public Iterable<FileStore> getFileStores() { | |
return null; | |
} | |
@Override | |
public Path getPath(String first, String... more) { | |
String path; | |
if (more.length == 0) { | |
path = first; | |
} else { | |
StringBuilder sb = new StringBuilder(); | |
sb.append(first); | |
for (String segment: more) { | |
if (segment.length() > 0) { | |
if (sb.length() > 0) { | |
sb.append(getSeparator()); | |
} | |
sb.append(segment); | |
} | |
} | |
path = sb.toString(); | |
} | |
return new WebdavPath(this, path); | |
} | |
/** | |
* Not implemented | |
* @return null | |
*/ | |
@Override | |
public PathMatcher getPathMatcher(String syntaxAndPattern) { | |
return null; | |
} | |
/** | |
* Not implemented | |
* @return null | |
*/ | |
@Override | |
public Iterable<Path> getRootDirectories() { | |
final Path rootp = new WebdavPath(this, rootpath); | |
Iterable<Path> ret = new Iterable<Path>() { | |
@Override | |
public Iterator<Path> iterator() { | |
ArrayList<Path> ap = new ArrayList<Path>(1); | |
ap.add(rootp); | |
return ap.iterator(); | |
} | |
}; | |
return ret; | |
} | |
@Override | |
public String getSeparator() { | |
return "/"; | |
} | |
/** | |
* Not implemented | |
* @return null | |
*/ | |
@Override | |
public UserPrincipalLookupService getUserPrincipalLookupService() { | |
return null; | |
} | |
/** | |
* Not implemented | |
* @return false | |
*/ | |
@Override | |
public boolean isOpen() { | |
return false; | |
} | |
/** | |
* Not implemented | |
* @return false | |
*/ | |
@Override | |
public boolean isReadOnly() { | |
return false; | |
} | |
/** | |
* Not implemented | |
* @return null | |
*/ | |
@Override | |
public WatchService newWatchService() throws IOException { | |
return null; | |
} | |
/** | |
* Not implemented | |
* @return null | |
*/ | |
@Override | |
public Set<String> supportedFileAttributeViews() { | |
return null; | |
} | |
/** | |
* Check if one filesystem is equal to another. Checks Host, username and Port. | |
*/ | |
@Override | |
public boolean equals(Object other) { | |
if (!(other instanceof WebdavFileSystem)) { | |
throw new IllegalArgumentException("Argument must be of instance WebdavFileSystem"); | |
} | |
WebdavFileSystem current = (WebdavFileSystem)other; | |
return current.host.equals(this.host) && current.username.equals(this.username) && current.port == this.port; | |
} | |
@Override | |
public int hashCode() { | |
return super.hashCode(); | |
} | |
public String getUserName() { | |
return this.username; | |
} | |
String getHost() { | |
return this.host; | |
} | |
int getPort() { | |
return this.port; | |
} | |
public String getPassword() { | |
return this.password; | |
} | |
Sardine getSardine() throws IOException { | |
if(!(username == null && password == null)) | |
return SardineFactory.begin(username, password, ProxySelector.getDefault()); | |
else | |
return SardineFactory.begin(); | |
} | |
public Cache<Path, WebdavFileAttributes> getAttcache() { | |
return attcache; | |
} | |
public void setAttcache(Cache<Path, WebdavFileAttributes> attcache) { | |
this.attcache = attcache; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright 2012-2013 University of Stavanger, Norway | |
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. | |
note: codes has been edited by ag88 and is not original | |
*/ | |
package no.maddin.niofs.webdav; | |
import java.io.IOException; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
import java.nio.channels.SeekableByteChannel; | |
import java.nio.file.AccessMode; | |
import java.nio.file.CopyOption; | |
import java.nio.file.DirectoryStream; | |
import java.nio.file.DirectoryStream.Filter; | |
import java.nio.file.FileStore; | |
import java.nio.file.FileSystem; | |
import java.nio.file.FileSystemException; | |
import java.nio.file.FileSystemNotFoundException; | |
import java.nio.file.Files; | |
import java.nio.file.LinkOption; | |
import java.nio.file.NoSuchFileException; | |
import java.nio.file.OpenOption; | |
import java.nio.file.Path; | |
import java.nio.file.ProviderMismatchException; | |
import java.nio.file.attribute.BasicFileAttributes; | |
import java.nio.file.attribute.FileAttribute; | |
import java.nio.file.attribute.FileAttributeView; | |
import java.nio.file.spi.FileSystemProvider; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Objects; | |
import java.util.Set; | |
import java.util.TreeMap; | |
import java.util.TreeSet; | |
import java.util.concurrent.TimeUnit; | |
import javax.xml.namespace.QName; | |
import org.apache.logging.log4j.LogManager; | |
import org.apache.logging.log4j.Logger; | |
import org.apache.logging.log4j.Marker; | |
import org.apache.logging.log4j.MarkerManager; | |
import com.github.benmanes.caffeine.cache.Cache; | |
import com.github.benmanes.caffeine.cache.Caffeine; | |
import com.github.sardine.DavResource; | |
import com.github.sardine.Sardine; | |
import com.github.sardine.impl.SardineException; | |
import com.github.sardine.model.Allprop; | |
import com.github.sardine.model.Propfind; | |
/** | |
* The WebDAV FileSystemProvider based on Sardine. | |
*/ | |
public class WebdavFileSystemProvider extends FileSystemProvider { | |
Logger log = LogManager.getLogger(WebdavFileSystemProvider.class); | |
private static final String NEED_TO_BE_AN_INSTANCE_OF_WEBDAV_PATH = "Need to be an instance of WebdavPath"; | |
private static final int DEFAULT_PORT = 80; | |
private final Map<URI, WebdavFileSystem> hosts = new HashMap<>(); | |
public WebdavFileSystemProvider() { | |
super(); | |
} | |
@Override | |
public void copy(Path fileFrom, Path fileTo, CopyOption... options) throws IOException { | |
if (!(fileFrom instanceof WebdavPath)) { | |
throw new IllegalArgumentException(fileFrom.toString()); | |
} | |
if (!(fileTo instanceof WebdavPath)) { | |
throw new IllegalArgumentException(fileTo.toString()); | |
} | |
WebdavPath wPathTo = (WebdavPath)fileTo; | |
WebdavFileSystem webdavHost = (WebdavFileSystem)fileTo.getFileSystem(); | |
Sardine webdav = webdavHost.getSardine(); | |
webdav.put(wPathTo.toUri().toString(), Files.readAllBytes(fileFrom)); | |
} | |
@Override | |
public void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException { | |
if (!(dir instanceof WebdavPath)) { | |
throw new IllegalArgumentException(dir.toString()); | |
} | |
WebdavPath wDir = (WebdavPath)dir; | |
WebdavFileSystem webdavHost = (WebdavFileSystem)dir.getFileSystem(); | |
Sardine webdav = webdavHost.getSardine(); | |
createDirectoryRecursive(webdav, wDir, attrs); | |
} | |
private void createDirectoryRecursive(Sardine webdav, WebdavPath wDir, FileAttribute<?>[] attrs) throws IOException { | |
if (webdav.exists(wDir.toUri().toString())) { | |
return; | |
} | |
WebdavPath parent = (WebdavPath)wDir.getParent(); | |
if (parent != null) { | |
createDirectoryRecursive(webdav, parent, attrs); | |
} | |
webdav.createDirectory(wDir.toUri().toString()); | |
} | |
@Override | |
public void delete(Path dir) throws IOException { | |
if (!(dir instanceof WebdavPath)) { | |
throw new IllegalArgumentException(dir.toString()); | |
} | |
WebdavPath wDir = (WebdavPath)dir; | |
WebdavFileSystem webdavHost = (WebdavFileSystem)dir.getFileSystem(); | |
Sardine webdav = webdavHost.getSardine(); | |
String dirString = ""; | |
try { | |
dirString = wDir.toUri().toString(); | |
webdav.delete(dirString); | |
} catch(SardineException se) { | |
if (se.getCause() instanceof IOException) { | |
throw (IOException)se.getCause(); | |
} | |
if (Objects.equals(se.getResponsePhrase(), "Not Found")) { | |
throw new NoSuchFileException(dirString); | |
} | |
throw new IOException(se); | |
} | |
} | |
/** | |
* The default implementation in FileSystemProvider will simply call | |
* delete() in deleteIfExists() and silently ignore any NoSuchFileException. | |
* In case of Nexus, trying to delete() will result in 503 (Not allowed) | |
* even if the path points to nowhere. | |
*/ | |
@Override | |
public boolean deleteIfExists(Path path) throws IOException { | |
WebdavFileSystem webdavFs = (WebdavFileSystem)path.getFileSystem(); | |
final String s = path.toUri().toString(); | |
return webdavFs.getSardine().exists(s); | |
} | |
@Override | |
public FileSystem getFileSystem(URI uri) { | |
try { | |
return getWebdavHost(uri, true); | |
} catch(URISyntaxException ex) { | |
throw new FileSystemNotFoundException(uri.toString()); | |
} | |
} | |
@Override | |
public Path getPath(URI uri) { | |
try { | |
WebdavFileSystem host = getWebdavHost(uri, true); | |
return new WebdavPath(host, uri.getPath()); | |
} catch(URISyntaxException e) { | |
throw new FileSystemNotFoundException(uri.toString()); | |
} | |
} | |
private WebdavFileSystem getWebdavHost(URI uri, boolean create) throws URISyntaxException { | |
String host = uri.getHost(); | |
int port = uri.getPort(); | |
if (port == -1) { | |
port = DEFAULT_PORT; | |
} | |
String userInfo = uri.getUserInfo(); | |
URI serverUri = new URI(getScheme(), userInfo, host, port, uri.getPath(), null, null); | |
synchronized (hosts) { | |
WebdavFileSystem fs = hosts.get(serverUri); | |
if (fs == null && create) { | |
fs = new WebdavFileSystem(this, serverUri); | |
hosts.put(serverUri, fs); | |
} | |
return fs; | |
} | |
} | |
@Override | |
public String getScheme() { | |
return "webdav"; | |
} | |
/** | |
* Unsupported | |
*/ | |
@Override | |
public <V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption... options) { | |
throw new UnsupportedOperationException(); | |
} | |
/** | |
* Unsupported | |
*/ | |
@Override | |
public FileStore getFileStore(Path path) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public void checkAccess(Path path, AccessMode... modes) throws IOException { | |
WebdavFileSystem webdavFs = (WebdavFileSystem)path.getFileSystem(); | |
final String s = path.toUri().toString(); | |
final boolean exists = webdavFs.getSardine().exists(s); | |
if (!exists) { | |
throw new NoSuchFileException(s); | |
} | |
} | |
/** | |
* Unsupported | |
*/ | |
@Override | |
public boolean isHidden(Path path) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
/** | |
* Unsupported | |
*/ | |
@Override | |
public boolean isSameFile(Path path, Path path2) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
/** | |
* Unsupported | |
*/ | |
@Override | |
public void move(Path source, Path target, CopyOption... options) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) | |
throws IOException | |
{ | |
return new SardineChannel((WebdavPath)path); | |
} | |
class DirStream implements DirectoryStream<Path> { | |
ArrayList<Path> paths; | |
public DirStream(ArrayList<Path> paths) { | |
this.paths = paths; | |
} | |
@Override | |
public void close() throws IOException { | |
} | |
@Override | |
public Iterator<Path> iterator() { | |
return paths.iterator(); | |
} | |
} | |
@Override | |
public DirectoryStream<Path> newDirectoryStream(Path path, Filter<? super Path> filter) throws IOException { | |
// throw new UnsupportedOperationException(); | |
Marker marker = MarkerManager.getMarker("newDirectoryStream"); | |
log.debug(marker, ""); | |
try { | |
if (!(path instanceof WebdavPath)) { | |
IOException e = new IOException(NEED_TO_BE_AN_INSTANCE_OF_WEBDAV_PATH); | |
log.error(marker, "path {}", path.toString()); | |
log.error(e); | |
throw e; | |
} | |
WebdavFileSystem wfs = (WebdavFileSystem) path.getFileSystem(); | |
Cache<Path, WebdavFileAttributes> cache = wfs.getAttcache(); | |
List<DavResource> resources = wfs.getSardine().list(path.toUri().toString(), 1, true); | |
ArrayList<Path> paths = new ArrayList<Path>(10); | |
Iterator<DavResource> iter = resources.iterator(); | |
boolean first = true; | |
while (iter.hasNext()) { | |
DavResource res = iter.next(); | |
if (first) { | |
first = false; | |
if (res.isDirectory()) { | |
/* | |
* in a canonical directory listing, the parent directory queried isn't included | |
* only its contents this omits that entry so that it 'looks' like a | |
* conventional directory listing | |
*/ | |
WebdavPath dp = new WebdavPath((WebdavFileSystem) path.getFileSystem(), res.getPath()); | |
if (dp.equals(path)) | |
continue; | |
} | |
} | |
WebdavPath wpath = new WebdavPath((WebdavFileSystem) path.getFileSystem(), res.getPath()); | |
if(filter != null && !filter.accept(wpath)) | |
continue; | |
if (cache.getIfPresent(wpath) == null) { | |
WebdavFileAttributes attr = new WebdavFileAttributes(res); | |
cache.put(wpath, attr); | |
} | |
paths.add(wpath); | |
} | |
DirStream dirstream = new DirStream(paths); | |
return dirstream; | |
} catch (IOException e) { | |
log.error(marker, "path {}", path.toString()); | |
log.error(e); | |
throw e; | |
} | |
} | |
@Override | |
public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException { | |
try { | |
return getWebdavHost(uri, true); | |
} catch(URISyntaxException e) { | |
throw new FileSystemException(e.toString()); | |
} | |
} | |
@SuppressWarnings("unchecked") | |
@Override | |
public <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options) | |
throws IOException { | |
Marker marker = MarkerManager.getMarker("readAttributes(path,type)"); | |
if(!(path.getFileSystem() instanceof WebdavFileSystem)) { | |
log.error(marker, "Invalid filesystem"); | |
throw new FileSystemException("Invalid filesystem"); | |
} | |
Cache<Path, WebdavFileAttributes> cache = ((WebdavFileSystem) path.getFileSystem()).getAttcache(); | |
if (cache.getIfPresent(path) != null) { | |
return (A) cache.getIfPresent(path); | |
} | |
List<DavResource> resources; | |
try { | |
WebdavFileSystem wfs = (WebdavFileSystem)path.getFileSystem(); | |
resources = wfs.getSardine().list(path.toUri().toString(),0,true); | |
//List<DavResource> resources = wfs.getSardine().list(path.toUri().toString()); | |
if (resources.size() != 1) { | |
throw new IllegalArgumentException(); | |
} | |
final DavResource res = resources.get(0); | |
if (!type.isAssignableFrom(WebdavFileAttributes.class)) { | |
throw new ProviderMismatchException(); | |
} | |
WebdavFileAttributes attr = new WebdavFileAttributes(res); | |
cache.put(path, attr); | |
return (A) attr; | |
} catch (IOException e) { | |
log.warn(marker, "error connecting: {}", path.toUri().toString()); | |
log.error(e); | |
throw e; | |
} | |
} | |
@Override | |
public Map<String, Object> readAttributes(Path path, String attributes, LinkOption... arg2) throws IOException { | |
//throw new UnsupportedOperationException(); | |
Marker marker = MarkerManager.getMarker("readAttributes(path,sattr)"); | |
WebdavFileAttributes wattr; | |
if(!(path.getFileSystem() instanceof WebdavFileSystem)) { | |
log.error(marker, "Invalid filesystem"); | |
throw new FileSystemException("Invalid filesystem"); | |
} | |
Cache<Path, WebdavFileAttributes> cache = ((WebdavFileSystem) path.getFileSystem()).getAttcache(); | |
if (cache.getIfPresent(path) != null) | |
wattr = cache.getIfPresent(path); | |
else { | |
WebdavFileSystem wfs = (WebdavFileSystem)path.getFileSystem(); | |
List<DavResource> resources = wfs.getSardine().list(path.toUri().toString(),0,true); | |
//List<DavResource> resources = wfs.getSardine().list(path.toUri().toString()); | |
if (resources.size() != 1) { | |
throw new IllegalArgumentException(); | |
} | |
final DavResource res = resources.get(0); | |
wattr = new WebdavFileAttributes(res); | |
cache.put(path, wattr); | |
} | |
TreeMap<String, Object> map = new TreeMap<String, Object>(); | |
String attr[] = attributes.split(","); | |
for(String a: attr) { | |
switch(a) { | |
case "lastModifiedTime": | |
map.put("lastModifiedTime", wattr.lastModifiedTime()); | |
break; | |
case "lastAccessTime": | |
map.put("lastAccessTime", wattr.lastAccessTime()); | |
break; | |
case "creationTime": | |
map.put("creationTime", wattr.creationTime()); | |
break; | |
case "size": | |
map.put("size", wattr.size()); | |
break; | |
case "isRegularFile": | |
map.put("isRegularFile", wattr.isRegularFile()); | |
break; | |
case "isDirectory": | |
map.put("isDirectory", wattr.isDirectory()); | |
break; | |
case "isSymbolicLink": | |
map.put("isSymbolicLink", wattr.isSymbolicLink()); | |
break; | |
case "isOther": | |
map.put("isOther", wattr.isSymbolicLink()); | |
break; | |
case "fileKey": | |
map.put("fileKey", wattr.fileKey()); | |
break; | |
} | |
} | |
return map; | |
} | |
/** | |
* Unsupported | |
*/ | |
@Override | |
public void setAttribute(Path arg0, String arg1, Object arg2, LinkOption... arg3) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
Copyright 2012-2013 University of Stavanger, Norway | |
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. | |
note: codes has been edited by ag88 and is not original | |
*/ | |
package no.maddin.niofs.webdav; | |
import java.io.File; | |
import java.io.IOError; | |
import java.io.IOException; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
import java.nio.file.FileSystem; | |
import java.nio.file.LinkOption; | |
import java.nio.file.Path; | |
import java.nio.file.WatchEvent.Kind; | |
import java.nio.file.WatchEvent.Modifier; | |
import java.nio.file.WatchKey; | |
import java.nio.file.WatchService; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Deque; | |
import java.util.Iterator; | |
import java.util.LinkedList; | |
import java.util.List; | |
import java.util.ListIterator; | |
import java.util.StringTokenizer; | |
import org.apache.commons.codec.digest.UnixCrypt; | |
/** | |
* Denotes a WebDAV Path. | |
*/ | |
/** | |
* @author andrew | |
* | |
*/ | |
public class WebdavPath implements Path { | |
private static final String NEED_TO_BE_AN_INSTANCE_OF_WEBDAV_PATH = "Need to be an instance of WebdavPath"; | |
private static final String PARENT_PATH = ".."; | |
//private static final String PATH_SEP = "/"; | |
final String PATH_SEP; | |
//private static final String DEFAULT_ROOT_PATH = PATH_SEP; | |
private final String DEFAULT_ROOT_PATH; | |
private ArrayList<String> elements; | |
private final WebdavFileSystem host; | |
private boolean isabsolute = false; | |
WebdavPath(WebdavFileSystem webdavHost, String path) { | |
this.host = webdavHost; | |
this.elements = new ArrayList<String>(); | |
PATH_SEP = webdavHost.getSeparator(); | |
DEFAULT_ROOT_PATH = PATH_SEP; | |
parsePathStr(path); | |
} | |
WebdavPath(WebdavFileSystem webdavHost, ArrayList<String> elements, boolean absolute) { | |
this.host = webdavHost; | |
PATH_SEP = webdavHost.getSeparator(); | |
DEFAULT_ROOT_PATH = PATH_SEP; | |
this.elements = elements; | |
this.isabsolute = absolute; | |
} | |
private void parsePathStr(String path) { | |
if (path == null) { | |
//this.pathf.add(DEFAULT_ROOT_PATH); | |
//empty path empty elements, not necessary absolute | |
} else if (path.equals(DEFAULT_ROOT_PATH)) { | |
//this.elements.add(DEFAULT_ROOT_PATH); | |
this.isabsolute = true; | |
//empty path elements | |
} else { | |
String p = path.trim(); | |
if(p.startsWith(PATH_SEP)) { | |
this.isabsolute = true; | |
p = p.substring(1); | |
} | |
if(p.endsWith(PATH_SEP)) | |
p = p.substring(0,p.length()-1); //omit trailing slash | |
String ps[] = p.split(PATH_SEP); | |
for (String s : ps) | |
elements.add(s); | |
} | |
} | |
public String getPathString() { | |
StringBuilder sb = new StringBuilder(100); | |
if (isabsolute) | |
sb.append(PATH_SEP); | |
boolean first = true; | |
for(String f : elements) { | |
if(first) { | |
first = false; | |
} else | |
sb.append(PATH_SEP); | |
sb.append(f); | |
} | |
return sb.toString(); | |
} | |
@Override | |
public String toString() { | |
return getPathString(); | |
} | |
@Override | |
public FileSystem getFileSystem() { | |
return this.host; | |
} | |
@Override | |
public Path getRoot() { | |
Iterator<Path> iter = this.host.getRootDirectories().iterator(); | |
Path p = null; | |
while(iter.hasNext()) { | |
p = iter.next(); | |
return p; | |
} | |
return new WebdavPath(this.host, DEFAULT_ROOT_PATH); | |
} | |
@Override | |
public boolean isAbsolute() { | |
return isabsolute; | |
} | |
@Override | |
public int compareTo(Path other) { | |
//throw new UnsupportedOperationException(); | |
if(!(other instanceof WebdavPath)) | |
throw new ClassCastException(); | |
WebdavPath ow = (WebdavPath) other; | |
if(elements.size() > ow.getElements().size()) | |
return 1; | |
else if(elements.size() < ow.getElements().size()) | |
return -1; | |
ArrayList<String> oe = ow.getElements(); | |
for(int i=0; i<elements.size(); i++) { | |
if(elements.get(i).equals(oe.get(i))) | |
continue; | |
return elements.get(i).compareTo(oe.get(i)); | |
} | |
return 0; | |
} | |
@Override | |
public boolean equals(Object other) { | |
if(!(other instanceof WebdavPath)) | |
return false; | |
WebdavPath ow = (WebdavPath) other; | |
if(ow.getElements().size() > elements.size() || | |
ow.getElements().size() < elements.size()) | |
return false; | |
ArrayList<String> oe = ow.getElements(); | |
for(int i=0; i<elements.size(); i++) { | |
if(elements.get(i).equals(oe.get(i))) | |
continue; | |
return false; | |
} | |
return true; | |
} | |
@Override | |
public boolean startsWith(Path other) { | |
//throw new UnsupportedOperationException(); | |
if(!(other instanceof WebdavPath)) | |
return false; | |
if(other.getNameCount() > getNameCount()) | |
return false; | |
WebdavPath wp = (WebdavPath) other; | |
if (!((WebdavFileSystem) wp.getFileSystem()).equals(host)) | |
return false; | |
ListIterator<String> io = wp.getElements().listIterator(); | |
while(io.hasNext()) { | |
int i = io.nextIndex(); | |
if(io.next().equals(elements.get(i))) | |
continue; | |
return false; | |
} | |
return true; | |
} | |
@Override | |
public boolean startsWith(String other) { | |
//throw new UnsupportedOperationException(); | |
return startsWith(new WebdavPath(this.host, other)); | |
} | |
@Override | |
public boolean endsWith(Path other) { | |
//throw new UnsupportedOperationException(); | |
if(!(other instanceof WebdavPath)) | |
return false; | |
if(other.getNameCount() > getNameCount()) | |
return false; | |
WebdavPath wp = (WebdavPath) other; | |
if (!((WebdavFileSystem) wp.getFileSystem()).equals(host)) | |
return false; | |
int si = getNameCount() - other.getNameCount(); | |
ListIterator<String> io = wp.getElements().listIterator(); | |
for(int i=si; i<getNameCount(); i++) { | |
if(io.hasNext()) | |
if(elements.get(i).equals(io.next())) | |
continue; | |
return false; | |
} | |
return true; | |
} | |
@Override | |
public boolean endsWith(String other) { | |
//throw new UnsupportedOperationException(); | |
return endsWith(new WebdavPath(this.host, other)); | |
} | |
@Override | |
public Path getFileName() { | |
if(elements.size()==0) | |
return null; | |
else | |
return new WebdavPath(this.host, elements.get(elements.size()-1)); | |
} | |
@Override | |
public Path getName(int index) { | |
if(elements.size() == 0) | |
throw new IllegalArgumentException(); | |
if(index >= elements.size() || index < 0) | |
throw new IllegalArgumentException(); | |
return new WebdavPath(host, elements.get(index)); | |
} | |
@Override | |
public int getNameCount() { | |
return elements.size(); | |
} | |
@Override | |
public Path getParent() { | |
if (elements.size()<=1) | |
return null; | |
ArrayList<String> elms = new ArrayList<>(elements.size()-1); | |
elms.addAll(elements.subList(0, elements.size()-1)); | |
return new WebdavPath(host, elms, true ); | |
} | |
@Override | |
public Iterator<Path> iterator() { | |
List<Path> plist = new LinkedList<>(); | |
for (Path p = this; p != null; p = p.getParent()) { | |
plist.add(0, p); | |
} | |
return plist.iterator(); | |
} | |
@Override | |
public Path normalize() { | |
try { | |
URI normal = new URI(getPathString()).normalize(); | |
return new WebdavPath(this.host, normal.getPath()); | |
} catch (URISyntaxException e) { | |
throw new IllegalArgumentException(getPathString(), e); | |
} | |
} | |
@Override | |
public WatchKey register(WatchService watcher, Kind<?>... events) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public WatchKey register(WatchService watcher, Kind<?>[] events, Modifier... arg2) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
/* | |
* Constructs a relative path between this path and a given path. | |
* | |
* relativize() is the inverse of resolve(). | |
* This method attempts to construct a relative path that is less this path as preceeding path | |
* e.g. this "a/b" , other "a/b/c/d" - relativize() = "c/d" | |
* | |
* this and other path needs to be both relative | |
* or both absolute | |
* | |
*/ | |
@Override | |
public Path relativize(Path other) { | |
if(!(other instanceof WebdavPath)) | |
throw new IllegalArgumentException(NEED_TO_BE_AN_INSTANCE_OF_WEBDAV_PATH); | |
if( (isAbsolute() && !other.isAbsolute()) || | |
(!isAbsolute() && other.isAbsolute())) | |
throw new IllegalArgumentException( | |
"Both this path and the other path has to be both absolute or relative"); | |
if (other.getNameCount() < this.getNameCount()) | |
throw new IllegalArgumentException( | |
"the other path is short than this path"); | |
WebdavPath wp = (WebdavPath) other; | |
ListIterator<String> io = wp.getElements().listIterator(); | |
ListIterator<String> ia = elements.listIterator(); | |
while(ia.hasNext()) { | |
String a = ia.next(); | |
if(io.hasNext()) { | |
String so = io.next(); | |
if(!so.equals(a)) | |
break; | |
} | |
} | |
ArrayList<String> re = new ArrayList<String>(wp.getElements().size() - elements.size()); | |
//copy remaining elements | |
while(io.hasNext()) { | |
re.add(io.next()); | |
} | |
//returns a relative path | |
return new WebdavPath(host, re, false); | |
} | |
/* | |
* Resolve the given path against this path. | |
* | |
* In the simplest case, this method joins the given path to this path | |
* and returns a resulting path that ends with the given path. | |
* | |
* @param other The other path to resolved against this | |
* | |
* @return If the other parameter is an absolute path, returns other. | |
* If other is an empty path, returns this path. | |
* Otherwise this method considers this path to be a directory and | |
* resolves the given path against this path. | |
*/ | |
@Override | |
public Path resolve(Path other) { | |
if (other == null) { | |
return this; | |
} | |
if (other.isAbsolute()) | |
return other; | |
if(!(other instanceof WebdavPath)) | |
throw new IllegalArgumentException(NEED_TO_BE_AN_INSTANCE_OF_WEBDAV_PATH); | |
WebdavPath wp = (WebdavPath) other; | |
ArrayList<String> ret = new ArrayList<String>(elements.size() + wp.getElements().size()); | |
ret.addAll(elements); | |
ret.addAll(wp.getElements()); | |
return new WebdavPath(host, ret, isAbsolute()); | |
} | |
@Override | |
public Path resolve(String other) { | |
return resolve(new WebdavPath(this.host, other)); | |
} | |
/* | |
* Resolves the given path against this path's parent path. | |
*/ | |
@Override | |
public Path resolveSibling(Path other) { | |
//throw new UnsupportedOperationException(); | |
if(!(other instanceof WebdavPath)) | |
throw new IllegalArgumentException(NEED_TO_BE_AN_INSTANCE_OF_WEBDAV_PATH); | |
if(getParent()==null) | |
return null; | |
else | |
return getParent().resolve(other); | |
} | |
@Override | |
public Path resolveSibling(String other) { | |
//throw new UnsupportedOperationException(); | |
return resolveSibling(new WebdavPath(this.host, other)); | |
} | |
/* | |
* Returns a relative Path that is a subsequence of the name elements of this path. | |
* | |
* @param beginIndex begin index | |
* @param endIndex end index | |
* @return a relative path with elements from elements[beingIndex] to elements[endIndex-1] | |
* elements[endIndex-1] is included. | |
*/ | |
@Override | |
public Path subpath(int beginIndex, int endIndex) { | |
//throw new UnsupportedOperationException(); | |
if(elements.size() == 0) | |
throw new IllegalArgumentException(); | |
if( beginIndex < 0 || endIndex <= beginIndex || endIndex > elements.size() ) | |
throw new IllegalArgumentException(); | |
ArrayList<String> subp = new ArrayList<String>(elements.subList(beginIndex, endIndex)); | |
return new WebdavPath(this.host, | |
subp, false); | |
} | |
/* | |
* if this is not absolute path, returns this path resolved (appended) on root path | |
*/ | |
@Override | |
public Path toAbsolutePath() { | |
if(isAbsolute()) | |
return this; | |
return getRoot().resolve(this); | |
} | |
@Override | |
public File toFile() { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public Path toRealPath(LinkOption... options) throws IOException { | |
throw new UnsupportedOperationException(); | |
} | |
@Override | |
public URI toUri() { | |
String scheme = (host.provider() instanceof WebdavsFileSystemProvider) ? "https" : "http"; | |
String server = host.getHost(); | |
int port = host.getPort(); | |
URI sardineUri; | |
try { | |
sardineUri = new URI(scheme, null, server, port, getPathString(), null, null); | |
return sardineUri; | |
} catch(URISyntaxException e) { | |
throw new IOError(e); | |
} | |
} | |
public ArrayList<String> getElements() { | |
return elements; | |
} | |
public void setElements(ArrayList<String> elements) { | |
this.elements = elements; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package no.maddin.niofs.webdav; | |
//CHECKSTYLE:OFF | |
import java.net.URI; | |
import java.nio.file.FileSystem; | |
import java.nio.file.FileSystems; | |
import java.nio.file.Path; | |
import java.nio.file.Paths; | |
import java.util.Iterator; | |
import java.util.logging.Logger; | |
import org.junit.jupiter.api.Test; | |
import org.junit.jupiter.api.TestReporter; | |
import static org.hamcrest.CoreMatchers.*; | |
import static org.hamcrest.MatcherAssert.assertThat; | |
/** | |
* These are the tests that don't require a running server. | |
*/ | |
public class WebdavPathTest { | |
private int webdavPort = -1; | |
@Test | |
public void newFileSystemWebdav() throws Exception { | |
URI uri = new URI("webdav", "user:password","localhost", webdavPort, "/", null, null); | |
FileSystem fs = FileSystems.newFileSystem(uri, null); | |
assertThat(fs, is(notNullValue())); | |
} | |
@Test | |
public void newFileSystemWebdavs() throws Exception { | |
URI uri = new URI("webdavs", "user:password","localhost", webdavPort, "/", null, null); | |
FileSystem fs = FileSystems.newFileSystem(uri, null); | |
assertThat(fs, is(notNullValue())); | |
} | |
@Test | |
public void getURI() throws Exception { | |
URI uri = new URI("webdav", "user:password","localhost", webdavPort, "/", null, null); | |
Path path = Paths.get(uri); | |
assertThat(path, is(notNullValue())); | |
} | |
@Test | |
public void normalize() throws Exception { | |
String dottedPath = "/webdav/../test/something"; | |
URI uri = new URI("webdav", "username:password", "anyhost", webdavPort, dottedPath, null, null); | |
Path path = Paths.get(uri); | |
Path result = path.normalize(); | |
assertThat(result, is(instanceOf(WebdavPath.class))); | |
String resultUri = result.toUri().toString(); | |
assertThat(resultUri, not(containsString(".."))); | |
assertThat(result.isAbsolute(), is(true)); | |
} | |
final boolean checkclass = true; | |
private URI makeURI(String path) throws Exception { | |
URI uri = new URI("webdav", "username:password", "anyhost", webdavPort, path, null, null); | |
//URI uri = new URI("file", null, null, 0, path, null, null); | |
return uri; | |
} | |
@Test | |
public void testgetRoot() throws Exception { | |
Path root = Paths.get(makeURI("/")); | |
assertThat(root.getRoot().toString().equals("/"), is(true)); | |
if(checkclass) | |
assertThat(root, is(instanceOf(WebdavPath.class))); | |
} | |
@Test | |
public void testgetParent() throws Exception { | |
Path a = Paths.get(makeURI("/a/b/c")); | |
assertThat(a.getParent().toString().equals("/a/b"), is(true)); | |
if(checkclass) | |
assertThat(a, is(instanceOf(WebdavPath.class))); | |
} | |
@Test | |
public void testiterator_getname() throws Exception { | |
Path a = Paths.get(makeURI("/a/b/c")); | |
assertThat(a.getFileName().toString().equals("c"), is(true)); | |
Path root = Paths.get(makeURI("/")); | |
assertThat(root.getFileName(), nullValue()); | |
try { | |
root.getName(0); | |
assertThat(false,is(true)); | |
} catch (IllegalArgumentException e) { | |
//Logger log = Logger.getLogger("testok"); | |
//log.info("getName empty elements passed"); | |
} | |
int n = a.getNameCount(); | |
assertThat(n,equalTo(3)); | |
Iterator<Path> iter = a.iterator(); | |
int i = 0; | |
Path b = null; | |
while(iter.hasNext()) { | |
b = iter.next(); | |
assertThat(a.getName(i).toString().equals(b.getFileName().toString()), is(true)); | |
i++; | |
} | |
if(checkclass) { | |
assertThat(a, is(instanceOf(WebdavPath.class))); | |
assertThat(b, is(instanceOf(WebdavPath.class))); | |
assertThat(root, is(instanceOf(WebdavPath.class))); | |
} | |
} | |
@Test | |
public void testtoAbsPath() throws Exception { | |
Path a = Paths.get(makeURI("/a/b/c")); | |
assertThat(a.toAbsolutePath().toString().equals("/a/b/c"), is(true)); | |
Path root = Paths.get(makeURI("/")); | |
Path b = root.relativize(a); | |
assertThat(b.toString().equals("a/b/c"), is(true)); | |
assertThat(b.toAbsolutePath().toString().equals("/a/b/c"), is(true)); | |
if(checkclass) { | |
assertThat(a, is(instanceOf(WebdavPath.class))); | |
assertThat(b, is(instanceOf(WebdavPath.class))); | |
assertThat(root, is(instanceOf(WebdavPath.class))); | |
} | |
} | |
@Test | |
public void testequals() throws Exception { | |
Path a = Paths.get(makeURI("/a/b/c")); | |
Path b = Paths.get(makeURI("/a/b/e")); | |
Path c = Paths.get(makeURI("/a/b/c/e")); | |
Path d = Paths.get(makeURI("/a/b")); | |
Path e = Paths.get(makeURI("/a/b/c")); | |
assertThat(a.equals(b), is(false)); | |
assertThat(a.equals(c), is(false)); | |
assertThat(a.equals(d), is(false)); | |
assertThat(a.equals(e), is(true)); | |
if(checkclass) { | |
assertThat(a, is(instanceOf(WebdavPath.class))); | |
assertThat(b, is(instanceOf(WebdavPath.class))); | |
assertThat(c, is(instanceOf(WebdavPath.class))); | |
assertThat(d, is(instanceOf(WebdavPath.class))); | |
assertThat(e, is(instanceOf(WebdavPath.class))); | |
} | |
} | |
@Test | |
public void testcompareTo() throws Exception { | |
Path a = Paths.get(makeURI("/a/b/c")); | |
Path b = Paths.get(makeURI("/a/b/e")); | |
Path c = Paths.get(makeURI("/a/b/c/e")); | |
Path d = Paths.get(makeURI("/a/b")); | |
Path e = Paths.get(makeURI("/a/b/c")); | |
assertThat(a.compareTo(b) < 0, is(true)); | |
assertThat(a.compareTo(c) < 0, is(true)); | |
assertThat(a.compareTo(d) > 0, is(true)); | |
assertThat(a.compareTo(e) == 0, is(true)); | |
if(checkclass) { | |
assertThat(a, is(instanceOf(WebdavPath.class))); | |
assertThat(b, is(instanceOf(WebdavPath.class))); | |
assertThat(c, is(instanceOf(WebdavPath.class))); | |
assertThat(d, is(instanceOf(WebdavPath.class))); | |
assertThat(e, is(instanceOf(WebdavPath.class))); | |
} | |
} | |
@Test | |
public void relativizeresolve() throws Exception { | |
Path root = Paths.get(makeURI("/")); | |
assertThat(root.toString().equals("/"), is(true)); | |
String ps = "/a/b"; | |
Path p = Paths.get(makeURI(ps)); | |
assertThat(p.toString().equals("/a/b"), is(true)); | |
String qs = "/c/d"; | |
Path qa =Paths.get(makeURI(qs));; | |
assertThat(qa.toString().equals("/c/d"), is(true)); | |
Path q = root.relativize(qa); //gets relative path "c/d" | |
assertThat(q.toString().equals("c/d"), is(true)); | |
assertThat(p.resolve(q).toString().equals("/a/b/c/d"), is(true)); | |
assertThat(p.resolve(q).equals(p.resolve("c/d")), is(true)); | |
assertThat(p.relativize(p.resolve(q)).equals(q), is(true)); | |
if(checkclass) { | |
assertThat(root, is(instanceOf(WebdavPath.class))); | |
assertThat(p, is(instanceOf(WebdavPath.class))); | |
assertThat(q, is(instanceOf(WebdavPath.class))); | |
} | |
} | |
@Test | |
public void teststartendswith() throws Exception { | |
Path a = Paths.get(makeURI("/a/b/c")); | |
Path b = Paths.get(makeURI("/a/b")); | |
assertThat(a.startsWith(b), is(true)); | |
assertThat(a.startsWith("/a/b"), is(true)); | |
Path root = Paths.get(makeURI("/")); | |
Path c = root.relativize(Paths.get(makeURI("/b/c"))); | |
assertThat(c.toString().equals("b/c"), is(true)); | |
assertThat(a.endsWith(c), is(true)); | |
assertThat(a.endsWith("b/c"), is(true)); | |
assertThat(a.endsWith(b), is(false)); | |
if(checkclass) { | |
assertThat(a, is(instanceOf(WebdavPath.class))); | |
assertThat(b, is(instanceOf(WebdavPath.class))); | |
assertThat(c, is(instanceOf(WebdavPath.class))); | |
} | |
} | |
@Test | |
public void testresolvsib_subpath() throws Exception { | |
Path root = Paths.get(makeURI("/")); | |
Path a = Paths.get(makeURI("/a/b/c")); | |
Path b = root.relativize(Paths.get(makeURI("/sib"))); | |
assertThat(a.resolveSibling(b).toString().equals("/a/b/sib"), is(true)); | |
assertThat(a.resolveSibling("sib").toString().equals("/a/b/sib"), is(true)); | |
assertThat(a.subpath(1, 3).toString().equals("b/c"), is(true)); | |
if(checkclass) { | |
assertThat(a, is(instanceOf(WebdavPath.class))); | |
assertThat(b, is(instanceOf(WebdavPath.class))); | |
assertThat(root, is(instanceOf(WebdavPath.class))); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment