Initial commit
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..06a84e9
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+/target/
+/.classpath
+/.project
+/.settings
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..b9cbcfa
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,6 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.maven.studies</groupId>
+ <artifactId>basedir-filesystem</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+</project>
\ No newline at end of file
diff --git a/src/main/java/org/apache/maven/filesystem/BasedirClassLoader.java b/src/main/java/org/apache/maven/filesystem/BasedirClassLoader.java
new file mode 100644
index 0000000..5e2ba4f
--- /dev/null
+++ b/src/main/java/org/apache/maven/filesystem/BasedirClassLoader.java
@@ -0,0 +1,77 @@
+package org.apache.maven.filesystem;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Path;
+import java.util.Enumeration;
+
+public class BasedirClassLoader extends ClassLoader
+{
+ private final ClassLoader classLoader;
+
+ private final Path basedir;
+
+ public BasedirClassLoader( ClassLoader classLoader , Path basedir )
+ {
+ this.classLoader = classLoader;
+ this.basedir = basedir;
+ }
+
+ public final Path getBasedir()
+ {
+ return basedir;
+ }
+
+ public int hashCode()
+ {
+ return classLoader.hashCode();
+ }
+
+ public boolean equals( Object obj )
+ {
+ return classLoader.equals( obj );
+ }
+
+ public String toString()
+ {
+ return classLoader.toString();
+ }
+
+ public Class<?> loadClass( String name )
+ throws ClassNotFoundException
+ {
+ return classLoader.loadClass( name );
+ }
+
+ public Enumeration<URL> getResources( String name )
+ throws IOException
+ {
+ return classLoader.getResources( name );
+ }
+
+ public InputStream getResourceAsStream( String name )
+ {
+ return classLoader.getResourceAsStream( name );
+ }
+
+ public void setDefaultAssertionStatus( boolean enabled )
+ {
+ classLoader.setDefaultAssertionStatus( enabled );
+ }
+
+ public void setPackageAssertionStatus( String packageName, boolean enabled )
+ {
+ classLoader.setPackageAssertionStatus( packageName, enabled );
+ }
+
+ public void setClassAssertionStatus( String className, boolean enabled )
+ {
+ classLoader.setClassAssertionStatus( className, enabled );
+ }
+
+ public void clearAssertionStatus()
+ {
+ classLoader.clearAssertionStatus();
+ }
+}
diff --git a/src/main/java/org/apache/maven/filesystem/BasedirFileSystem.java b/src/main/java/org/apache/maven/filesystem/BasedirFileSystem.java
new file mode 100644
index 0000000..77d0a62
--- /dev/null
+++ b/src/main/java/org/apache/maven/filesystem/BasedirFileSystem.java
@@ -0,0 +1,120 @@
+package org.apache.maven.filesystem;
+
+import java.io.IOException;
+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.Set;
+
+public class BasedirFileSystem extends FileSystem
+{
+ private final FileSystem fileSystem;
+
+ public BasedirFileSystem( FileSystem fileSystem )
+ {
+ this.fileSystem = fileSystem;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return fileSystem.hashCode();
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ return fileSystem.equals( obj );
+ }
+
+ @Override
+ public FileSystemProvider provider()
+ {
+ return fileSystem.provider();
+ }
+
+ @Override
+ public void close()
+ throws IOException
+ {
+ fileSystem.close();
+ }
+
+ @Override
+ public boolean isOpen()
+ {
+ return fileSystem.isOpen();
+ }
+
+ @Override
+ public boolean isReadOnly()
+ {
+ return fileSystem.isReadOnly();
+ }
+
+ @Override
+ public String getSeparator()
+ {
+ return fileSystem.getSeparator();
+ }
+
+ @Override
+ public Iterable<Path> getRootDirectories()
+ {
+ return fileSystem.getRootDirectories();
+ }
+
+ @Override
+ public Iterable<FileStore> getFileStores()
+ {
+ return fileSystem.getFileStores();
+ }
+
+ @Override
+ public String toString()
+ {
+ return fileSystem.toString();
+ }
+
+ @Override
+ public Set<String> supportedFileAttributeViews()
+ {
+ return fileSystem.supportedFileAttributeViews();
+ }
+
+ @Override
+ public Path getPath( String first, String... more )
+ {
+ Path p = fileSystem.getPath( first, more );
+
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ if ( cl instanceof BasedirClassLoader )
+ {
+ p = new BasedirPath( p, ( (BasedirClassLoader) cl ).getBasedir() );
+ }
+ return p;
+ }
+
+ @Override
+ public PathMatcher getPathMatcher( String syntaxAndPattern )
+ {
+ return fileSystem.getPathMatcher( syntaxAndPattern );
+ }
+
+ @Override
+ public UserPrincipalLookupService getUserPrincipalLookupService()
+ {
+ return fileSystem.getUserPrincipalLookupService();
+ }
+
+ @Override
+ public WatchService newWatchService()
+ throws IOException
+ {
+ return fileSystem.newWatchService();
+ }
+}
diff --git a/src/main/java/org/apache/maven/filesystem/BasedirFileSystemProvider.java b/src/main/java/org/apache/maven/filesystem/BasedirFileSystemProvider.java
new file mode 100644
index 0000000..e8104d6
--- /dev/null
+++ b/src/main/java/org/apache/maven/filesystem/BasedirFileSystemProvider.java
@@ -0,0 +1,244 @@
+package org.apache.maven.filesystem;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.nio.channels.AsynchronousFileChannel;
+import java.nio.channels.FileChannel;
+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.LinkOption;
+import java.nio.file.OpenOption;
+import java.nio.file.Path;
+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.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+public class BasedirFileSystemProvider extends FileSystemProvider
+{
+ private final FileSystemProvider defaultFileSystemProvider;
+
+ public BasedirFileSystemProvider()
+ {
+ defaultFileSystemProvider = null;
+ }
+
+ public BasedirFileSystemProvider( FileSystemProvider fileSystemProvider )
+ {
+ this.defaultFileSystemProvider = fileSystemProvider;
+ }
+
+ @Override
+ public void checkAccess( Path path, AccessMode... modes )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void copy( Path source, Path target, CopyOption... options )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void createDirectory( Path dir, FileAttribute<?>... attrs )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void createLink( Path link, Path existing )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void createSymbolicLink( Path link, Path target, FileAttribute<?>... attrs )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void delete( Path path )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean deleteIfExists( Path path )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean equals( Object obj )
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <V extends FileAttributeView> V getFileAttributeView( Path path, Class<V> type, LinkOption... options )
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileStore getFileStore( Path path )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileSystem getFileSystem( URI uri )
+ {
+ return new BasedirFileSystem( defaultFileSystemProvider.getFileSystem( uri ) );
+ }
+
+ @Override
+ public Path getPath( URI uri )
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getScheme()
+ {
+ return defaultFileSystemProvider.getScheme();
+ }
+
+ @Override
+ public int hashCode()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isHidden( Path path )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isSameFile( Path path, Path path2 )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void move( Path source, Path target, CopyOption... options )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public AsynchronousFileChannel newAsynchronousFileChannel( Path path, Set<? extends OpenOption> options,
+ ExecutorService executor, FileAttribute<?>... attrs )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SeekableByteChannel newByteChannel( Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public DirectoryStream<Path> newDirectoryStream( Path dir, Filter<? super Path> filter )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileChannel newFileChannel( Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileSystem newFileSystem( Path path, Map<String, ?> env )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public FileSystem newFileSystem( URI uri, Map<String, ?> env )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public InputStream newInputStream( Path path, OpenOption... options )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public OutputStream newOutputStream( Path path, OpenOption... options )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public <A extends BasicFileAttributes> A readAttributes( Path path, Class<A> type, LinkOption... options )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Map<String, Object> readAttributes( Path path, String attributes, LinkOption... options )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Path readSymbolicLink( Path link )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void setAttribute( Path path, String attribute, Object value, LinkOption... options )
+ throws IOException
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String toString()
+ {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/src/main/java/org/apache/maven/filesystem/BasedirPath.java b/src/main/java/org/apache/maven/filesystem/BasedirPath.java
new file mode 100644
index 0000000..8dcc0a3
--- /dev/null
+++ b/src/main/java/org/apache/maven/filesystem/BasedirPath.java
@@ -0,0 +1,177 @@
+package org.apache.maven.filesystem;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+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.Iterator;
+
+class BasedirPath implements Path
+{
+ private final Path basedir;
+
+ private Path path;
+
+ BasedirPath( Path path, Path basedir ) {
+ this.path = path;
+ this.basedir = basedir;
+ }
+
+ public FileSystem getFileSystem()
+ {
+ return path.getFileSystem();
+ }
+
+ public boolean isAbsolute()
+ {
+ return path.isAbsolute();
+ }
+
+ public Path getRoot()
+ {
+ return path.getRoot();
+ }
+
+ public Path getFileName()
+ {
+ return path.getFileName();
+ }
+
+ public Path getParent()
+ {
+ return path.getParent();
+ }
+
+ public int getNameCount()
+ {
+ return path.getNameCount();
+ }
+
+ public Path getName( int index )
+ {
+ return path.getName( index );
+ }
+
+ public Path subpath( int beginIndex, int endIndex )
+ {
+ return path.subpath( beginIndex, endIndex );
+ }
+
+ public boolean startsWith( Path other )
+ {
+ return path.startsWith( other );
+ }
+
+ public boolean startsWith( String other )
+ {
+ return path.startsWith( other );
+ }
+
+ public boolean endsWith( Path other )
+ {
+ return path.endsWith( other );
+ }
+
+ public boolean endsWith( String other )
+ {
+ return path.endsWith( other );
+ }
+
+ public Path normalize()
+ {
+ return path.normalize();
+ }
+
+ public Path resolve( Path other )
+ {
+ return path.resolve( other );
+ }
+
+ public Path resolve( String other )
+ {
+ return path.resolve( other );
+ }
+
+ public Path resolveSibling( Path other )
+ {
+ return path.resolveSibling( other );
+ }
+
+ public Path resolveSibling( String other )
+ {
+ return path.resolveSibling( other );
+ }
+
+ public Path relativize( Path other )
+ {
+ return path.relativize( other );
+ }
+
+ public URI toUri()
+ {
+ return path.toUri();
+ }
+
+ public Path toAbsolutePath()
+ {
+ if ( !path.isAbsolute() )
+ {
+ path = basedir.resolve( path );
+ }
+ return path.toAbsolutePath();
+ }
+
+ public Path toRealPath( LinkOption... options )
+ throws IOException
+ {
+ return path.toRealPath( options );
+ }
+
+ public File toFile()
+ {
+ return path.toFile();
+ }
+
+ public WatchKey register( WatchService watcher, Kind<?>[] events, Modifier... modifiers )
+ throws IOException
+ {
+ return path.register( watcher, events, modifiers );
+ }
+
+ public WatchKey register( WatchService watcher, Kind<?>... events )
+ throws IOException
+ {
+ return path.register( watcher, events );
+ }
+
+ public Iterator<Path> iterator()
+ {
+ return path.iterator();
+ }
+
+ public int compareTo( Path other )
+ {
+ return path.compareTo( other );
+ }
+
+ public boolean equals( Object other )
+ {
+ return path.equals( other );
+ }
+
+ public int hashCode()
+ {
+ return path.hashCode();
+ }
+
+ public String toString()
+ {
+ return path.toString();
+ }
+}
diff --git a/src/main/java/org/apache/maven/filesystem/Main.java b/src/main/java/org/apache/maven/filesystem/Main.java
new file mode 100644
index 0000000..09c3eab
--- /dev/null
+++ b/src/main/java/org/apache/maven/filesystem/Main.java
@@ -0,0 +1,43 @@
+package org.apache.maven.filesystem;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+/**
+ * Ensure to start java with {@code -Djava.nio.file.spi.DefaultFileSystemProvider=org.apache.maven.filesystem.BasedirFilesystemProvider}
+ *
+ * @see <a href="https://docs.oracle.com/javase/8/docs/api/index.html?java/nio/file/spi/FileSystemProvider.html">java.nio.file.spi.FileSystemProvider</a>
+ */
+public class Main
+{
+
+ public static void main( String[] args )
+ {
+ ClassLoader old = Thread.currentThread().getContextClassLoader();
+ try
+ {
+ System.out.println( "--- ORIGINAL ---" );
+ tests();
+ System.out.println();
+
+ Path basedir = Paths.get( "/a/b/c" ).toAbsolutePath();
+ ClassLoader c1 = new BasedirClassLoader( old, basedir );
+ Thread.currentThread().setContextClassLoader( c1 );
+ System.out.println( "--- With BasedirClassloader ( " + basedir + " ) ---" );
+ tests();
+ }
+ finally
+ {
+ Thread.currentThread().setContextClassLoader( old );
+ }
+ }
+
+ public static void tests() {
+ System.out.println( "Path: " + Paths.get( "src/main/java" ) ); // good
+ System.out.println( "Path.toAbsolutePath(): " + Paths.get( "src/main/java" ).toAbsolutePath() ); // good
+ System.out.println( "File.getAbsoluteFile(): " + new File( "src/main/java" ).getAbsoluteFile() ); // bad
+ }
+
+
+}
diff --git a/src/main/resources/META-INF/services/java.nio.file.spi.FileSystemProvider b/src/main/resources/META-INF/services/java.nio.file.spi.FileSystemProvider
new file mode 100644
index 0000000..3fa97be
--- /dev/null
+++ b/src/main/resources/META-INF/services/java.nio.file.spi.FileSystemProvider
@@ -0,0 +1 @@
+org.apache.maven.filesystem.BasedirFilesystemProvider
\ No newline at end of file