1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.akubraproject.fs;
23
24 import com.google.common.collect.AbstractIterator;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import java.io.File;
29 import java.net.URI;
30 import java.net.URISyntaxException;
31
32
33
34
35
36
37 class FSBlobIdIterator extends AbstractIterator<URI> {
38 private final Logger log = LoggerFactory.getLogger(FSBlobIdIterator.class);
39 private final File baseDir;
40 private final String filterPrefix;
41 private DirectoryNode currentDir;
42
43 FSBlobIdIterator(File baseDir, String filterPrefix) {
44 this.baseDir = baseDir;
45 this.filterPrefix = filterPrefix;
46 currentDir = new DirectoryNode(null, "");
47 }
48
49 @Override
50 protected URI computeNext() {
51 while (currentDir != null) {
52 DirectoryNode child = currentDir.nextChild();
53 if (child == null) {
54
55 currentDir = currentDir.parent;
56 } else if (child.isDirectory()) {
57
58 currentDir = child;
59 } else {
60
61 try {
62 URI uri = new URI(FSBlob.scheme + ":" + child.path);
63 if (filterPrefix == null || uri.toString().startsWith(filterPrefix)) {
64 return uri;
65 }
66 } catch (URISyntaxException e) {
67 log.warn("Skipping non-URI-safe file: {}", child.path);
68 }
69 }
70 }
71
72 return endOfData();
73 }
74
75 private class DirectoryNode {
76
77 final DirectoryNode parent;
78
79 final String path;
80
81 private String[] childPaths;
82
83 private int childNum;
84
85 DirectoryNode(DirectoryNode parent,
86 String path) {
87 this.parent = parent;
88 this.path = path;
89 if (isDirectory()) {
90 setChildPaths();
91 }
92 }
93
94 private void setChildPaths() {
95 File dir;
96 if (path.length() == 0) {
97 dir = baseDir;
98 } else {
99 dir = new File(baseDir, path);
100 }
101 File[] childFiles = dir.listFiles();
102 childPaths = new String[childFiles.length];
103 for (int i = 0; i < childFiles.length; i++) {
104 StringBuilder childPath = new StringBuilder(path);
105 childPath.append(childFiles[i].getName());
106 if (childFiles[i].isDirectory()) {
107 childPath.append("/");
108 }
109 childPaths[i] = childPath.toString();
110 }
111 }
112
113 boolean isDirectory() {
114 return path.length() == 0 || path.endsWith("/");
115 }
116
117 DirectoryNode nextChild() {
118 if (isDirectory()) {
119 if (childNum == childPaths.length) {
120 return null;
121 } else {
122 return new DirectoryNode(this, childPaths[childNum++]);
123 }
124 } else {
125 return null;
126 }
127 }
128 }
129 }