Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
febeb00
commit c3498d7
Showing
32 changed files
with
912 additions
and
1,150 deletions.
There are no files selected for viewing
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
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
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
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
94 changes: 94 additions & 0 deletions
94
community/io/src/main/java/org/neo4j/io/fs/StreamFilesRecursive.java
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,94 @@ | |||
/* | |||
* Copyright (c) 2002-2017 "Neo Technology," | |||
* Network Engine for Objects in Lund AB [http://neotechnology.com] | |||
* | |||
* This file is part of Neo4j. | |||
* | |||
* Neo4j is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program 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 General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
package org.neo4j.io.fs; | |||
|
|||
import java.io.File; | |||
import java.io.IOException; | |||
import java.io.UncheckedIOException; | |||
import java.nio.file.NoSuchFileException; | |||
import java.util.List; | |||
import java.util.stream.Stream; | |||
|
|||
import static java.util.stream.Collectors.toList; | |||
|
|||
public class StreamFilesRecursive | |||
{ | |||
private StreamFilesRecursive() | |||
{ | |||
//This is a helper class, do not instantiate it. | |||
} | |||
|
|||
/** | |||
* Static implementation of {@link FileSystemAbstraction#streamFilesRecursive(File)} that does not require | |||
* any external state, other than what is presented through the given {@link FileSystemAbstraction}. | |||
* | |||
* Return a stream of {@link FileHandle file handles} for every file in the given directory, and its | |||
* sub-directories. | |||
* <p> | |||
* Alternatively, if the {@link File} given as an argument refers to a file instead of a directory, then a stream | |||
* will be returned with a file handle for just that file. | |||
* <p> | |||
* The stream is based on a snapshot of the file tree, so changes made to the tree using the returned file handles | |||
* will not be reflected in the stream. | |||
* <p> | |||
* No directories will be returned. Only files. If a file handle ends up leaving a directory empty through a | |||
* rename or a delete, then the empty directory will automatically be deleted as well. | |||
* Likewise, if a file is moved to a path where not all of the directories in the path exists, then those missing | |||
* directories will be created prior to the file rename. | |||
* | |||
* @param directory The base directory to start streaming files from, or the specific individual file to stream. | |||
* @param fs The {@link FileSystemAbstraction} to use for manipulating files. | |||
* @return A {@link Stream} of {@link FileHandle}s | |||
* @throws NoSuchFileException If the given base directory or file does not exists. | |||
* @throws IOException If an I/O error occurs, possibly with the canonicalisation of the paths. | |||
*/ | |||
public static Stream<FileHandle> streamFilesRecursive( File directory, FileSystemAbstraction fs ) throws IOException | |||
{ | |||
try | |||
{ | |||
// We grab a snapshot of the file tree to avoid seeing the same file twice or more due to renames. | |||
List<File> snapshot = streamFilesRecursiveInner( directory.getCanonicalFile(), fs ).collect( toList() ); | |||
return snapshot.stream().map( f -> new WrappingFileHandle( f, directory, fs ) ); | |||
} | |||
catch ( UncheckedIOException e ) | |||
{ | |||
// We sneak checked IOExceptions through UncheckedIOExceptions due to our use of streams and lambdas. | |||
throw e.getCause(); | |||
} | |||
} | |||
|
|||
private static Stream<File> streamFilesRecursiveInner( File directory, FileSystemAbstraction fs ) | |||
{ | |||
File[] files = fs.listFiles( directory ); | |||
if ( files == null ) | |||
{ | |||
if ( !fs.fileExists( directory ) ) | |||
{ | |||
throw new UncheckedIOException( new NoSuchFileException( directory.getPath() ) ); | |||
} | |||
return Stream.of( directory ); | |||
} | |||
else | |||
{ | |||
return Stream.of( files ) | |||
.flatMap( f -> fs.isDirectory( f ) ? streamFilesRecursiveInner( f, fs ) : Stream.of( f ) ); | |||
} | |||
} | |||
} |
91 changes: 91 additions & 0 deletions
91
community/io/src/main/java/org/neo4j/io/fs/WrappingFileHandle.java
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
Original file line number | Original file line | Diff line number | Diff line change |
---|---|---|---|
@@ -0,0 +1,91 @@ | |||
/* | |||
* Copyright (c) 2002-2017 "Neo Technology," | |||
* Network Engine for Objects in Lund AB [http://neotechnology.com] | |||
* | |||
* This file is part of Neo4j. | |||
* | |||
* Neo4j is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU General Public License as published by | |||
* the Free Software Foundation, either version 3 of the License, or | |||
* (at your option) any later version. | |||
* | |||
* This program 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 General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU General Public License | |||
* along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
*/ | |||
package org.neo4j.io.fs; | |||
|
|||
import java.io.File; | |||
import java.io.IOException; | |||
import java.nio.file.CopyOption; | |||
|
|||
class WrappingFileHandle implements FileHandle | |||
{ | |||
private final File file; | |||
private final File baseDirectory; | |||
private final FileSystemAbstraction fs; | |||
|
|||
WrappingFileHandle( File file, File baseDirectory, FileSystemAbstraction fs ) | |||
{ | |||
this.file = file; | |||
this.baseDirectory = baseDirectory; | |||
this.fs = fs; | |||
} | |||
|
|||
@Override | |||
public File getFile() | |||
{ | |||
return file; | |||
} | |||
|
|||
@Override | |||
public File getRelativeFile() | |||
{ | |||
int baseLength = baseDirectory.getPath().length(); | |||
if ( baseDirectory.getParent() != null ) | |||
{ | |||
baseLength++; | |||
} | |||
return new File( file.getPath().substring( baseLength ) ); | |||
} | |||
|
|||
@Override | |||
public void rename( File to, CopyOption... options ) throws IOException | |||
{ | |||
File parentFile = file.getParentFile(); | |||
File cannonicalTarget = to.getCanonicalFile(); | |||
fs.mkdirs( cannonicalTarget.getParentFile() ); | |||
fs.renameFile( file, cannonicalTarget, options ); | |||
removeEmptyParent( parentFile ); | |||
} | |||
|
|||
private void removeEmptyParent( File parentFile ) | |||
{ | |||
// delete up to and including the base directory, but not above. | |||
// Note that this may be 'null' if 'baseDirectory' is the top directory. | |||
// Fortunately, 'File.equals(other)' handles 'null' and returns 'false' when 'other' is 'null'. | |||
File end = baseDirectory.getParentFile(); | |||
while ( parentFile != null && !parentFile.equals( end ) ) | |||
{ | |||
File[] files = fs.listFiles( parentFile ); | |||
if ( files == null || files.length > 0 ) | |||
{ | |||
return; | |||
} | |||
fs.deleteFile( parentFile ); | |||
parentFile = parentFile.getParentFile(); | |||
} | |||
} | |||
|
|||
@Override | |||
public void delete() throws IOException | |||
{ | |||
File parentFile = file.getParentFile(); | |||
fs.deleteFileOrThrow( file ); | |||
removeEmptyParent( parentFile ); | |||
} | |||
} |
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
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
Oops, something went wrong.