2626
2727import com .google .auto .service .AutoService ;
2828import com .google .cloud .storage .Acl ;
29+ import com .google .cloud .storage .Blob ;
2930import com .google .cloud .storage .BlobId ;
3031import com .google .cloud .storage .BlobInfo ;
3132import com .google .cloud .storage .CopyWriter ;
3536import com .google .common .annotations .VisibleForTesting ;
3637import com .google .common .base .MoreObjects ;
3738import com .google .common .base .Throwables ;
39+ import com .google .common .collect .AbstractIterator ;
3840import com .google .common .primitives .Ints ;
3941
4042import java .io .BufferedInputStream ;
4547import java .nio .file .AccessMode ;
4648import java .nio .file .AtomicMoveNotSupportedException ;
4749import java .nio .file .CopyOption ;
50+ import java .nio .file .DirectoryIteratorException ;
4851import java .nio .file .DirectoryStream ;
4952import java .nio .file .DirectoryStream .Filter ;
5053import java .nio .file .FileAlreadyExistsException ;
6366import java .util .ArrayList ;
6467import java .util .Collections ;
6568import java .util .HashMap ;
69+ import java .util .Iterator ;
6670import java .util .List ;
6771import java .util .Map ;
6872import java .util .Objects ;
6973import java .util .Set ;
70-
7174import javax .annotation .Nullable ;
7275import javax .annotation .concurrent .ThreadSafe ;
7376
@@ -83,6 +86,33 @@ public final class CloudStorageFileSystemProvider extends FileSystemProvider {
8386 // used only when we create a new instance of CloudStorageFileSystemProvider.
8487 private static StorageOptions storageOptions ;
8588
89+ private static class LazyPathIterator extends AbstractIterator <Path > {
90+ private final Iterator <Blob > blobIterator ;
91+ private final Filter <? super Path > filter ;
92+ private final CloudStorageFileSystem fileSystem ;
93+
94+ LazyPathIterator (CloudStorageFileSystem fileSystem , Iterator <Blob > blobIterator , Filter <? super Path > filter ) {
95+ this .blobIterator = blobIterator ;
96+ this .filter = filter ;
97+ this .fileSystem = fileSystem ;
98+ }
99+
100+ @ Override
101+ protected Path computeNext () {
102+ while (blobIterator .hasNext ()) {
103+ Path path = fileSystem .getPath (blobIterator .next ().name ());
104+ try {
105+ if (filter .accept (path )) {
106+ return path ;
107+ }
108+ } catch (IOException ex ) {
109+ throw new DirectoryIteratorException (ex );
110+ }
111+ }
112+ return endOfData ();
113+ }
114+ }
115+
86116 /**
87117 * Sets options that are only used by the constructor.
88118 */
@@ -527,13 +557,23 @@ public void createDirectory(Path dir, FileAttribute<?>... attrs) {
527557 checkNotNullArray (attrs );
528558 }
529559
530- /**
531- * Throws {@link UnsupportedOperationException} because this feature hasn't been implemented yet.
532- */
533560 @ Override
534- public DirectoryStream <Path > newDirectoryStream (Path dir , Filter <? super Path > filter ) {
535- // TODO: Implement me.
536- throw new UnsupportedOperationException ();
561+ public DirectoryStream <Path > newDirectoryStream (Path dir , final Filter <? super Path > filter ) {
562+ final CloudStoragePath cloudPath = checkPath (dir );
563+ checkNotNull (filter );
564+ String prefix = cloudPath .toString ();
565+ final Iterator <Blob > blobIterator = storage .list (cloudPath .bucket (), Storage .BlobListOption .prefix (prefix ), Storage .BlobListOption .fields ()).iterateAll ();
566+ return new DirectoryStream <Path >() {
567+ @ Override
568+ public Iterator <Path > iterator () {
569+ return new LazyPathIterator (cloudPath .getFileSystem (), blobIterator , filter );
570+ }
571+
572+ @ Override
573+ public void close () throws IOException {
574+ // Does nothing since there's nothing to close. Commenting this method to quiet codacy.
575+ }
576+ };
537577 }
538578
539579 /**
0 commit comments