/oneswarm_gwt_ui/src/edu/washington/cs/oneswarm/watchdir/UpdatingFileTree.java

https://github.com/UWNetworksLab/OneSwarm · Java · 214 lines · 173 code · 28 blank · 13 comment · 56 complexity · 5d43b6229afd6e41f985ce34bbf38e8f MD5 · raw file

  1. package edu.washington.cs.oneswarm.watchdir;
  2. import java.io.File;
  3. import java.io.FilenameFilter;
  4. import java.util.ArrayList;
  5. import java.util.Collections;
  6. import java.util.List;
  7. import java.util.logging.Logger;
  8. import org.gudy.azureus2.core3.util.Constants;
  9. import edu.uw.cse.netlab.reputation.GloballyAwareOneHopUnchoker;
  10. public class UpdatingFileTree {
  11. public static final long IDLE_THRESHOLD = 60 * 1000; // 1 minute without
  12. // mods
  13. private static Logger logger = Logger.getLogger(UpdatingFileTree.class.getName());
  14. List<UpdatingFileTree> children = Collections
  15. .synchronizedList(new ArrayList<UpdatingFileTree>());
  16. File thisFile = null;
  17. long lastRefreshed = 0;
  18. boolean gone = false;
  19. private UpdatingFileTreeListener mSpawn;
  20. boolean mHasDirectoryChildren = false;
  21. String mRelativePath = null;
  22. public UpdatingFileTree(File root) {
  23. this(root, new UpdatingFileTreeListener() {
  24. public void broadcastChange(UpdatingFileTree path, boolean isDelete) {
  25. }
  26. }, Integer.MAX_VALUE);
  27. }
  28. public UpdatingFileTree(File root, UpdatingFileTreeListener spawn) {
  29. this(root, spawn, Integer.MAX_VALUE);
  30. }
  31. public UpdatingFileTree(File root, UpdatingFileTreeListener spawn, int maxDepth) {
  32. thisFile = root;
  33. mSpawn = spawn;
  34. lastRefreshed = thisFile.lastModified();
  35. if (thisFile.isDirectory()) {
  36. File[] files = thisFile.listFiles(new FilenameFilter() {
  37. public boolean accept(File dir, String name) {
  38. /**
  39. * We don't want to hash trash on windows
  40. */
  41. if (name.toLowerCase().equals("recycler") && Constants.isWindows)
  42. return false;
  43. return name.startsWith(".") == false; // skip hidden files
  44. }
  45. });
  46. if (files != null && maxDepth > 0) {
  47. List<UpdatingFileTree> children = new ArrayList<UpdatingFileTree>(files.length);
  48. for (int i = 0; i < files.length; i++) {
  49. UpdatingFileTree c = new UpdatingFileTree(files[i], mSpawn);
  50. if (c != null) // we might not have perms everywhere...
  51. {
  52. if (c.thisFile.lastModified() + IDLE_THRESHOLD < System.currentTimeMillis()) {
  53. children.add(c);
  54. if (c.isDirectory()) {
  55. mHasDirectoryChildren = true;
  56. }
  57. } else {
  58. logger.fine("skipping fresh child: " + c.thisFile.getAbsolutePath());
  59. }
  60. }
  61. }
  62. this.children = children;
  63. } else {
  64. gone = true;
  65. }
  66. }
  67. }
  68. public long getLastModified() {
  69. return lastRefreshed;
  70. }
  71. /**
  72. * so we get directories before their files...
  73. */
  74. public void broadcast() {
  75. mSpawn.broadcastChange(this, false);
  76. for (UpdatingFileTree c : children)
  77. c.broadcast();
  78. }
  79. public boolean isDirectory() {
  80. return thisFile.isDirectory();
  81. }
  82. public void update() {
  83. logger.finest("update of: " + this.getThisFile().getAbsolutePath());
  84. if (thisFile.lastModified() != lastRefreshed || mHasDirectoryChildren) {
  85. if (thisFile.exists() == false) {
  86. this.gone = true;
  87. }
  88. /**
  89. * 1. check if children still there
  90. */
  91. mHasDirectoryChildren = false;
  92. if (children != null) {
  93. for (UpdatingFileTree c : children.toArray(new UpdatingFileTree[0])) {
  94. if (c.gone) {
  95. children.remove(c);
  96. logger.finest("child gone this pass: " + c.getThisFile().getAbsolutePath());
  97. } else {
  98. c.update();
  99. if (c.isDirectory()) {
  100. mHasDirectoryChildren = true;
  101. }
  102. }
  103. }
  104. }
  105. /**
  106. * 2. Check if there are new children
  107. */
  108. File[] files = thisFile.listFiles(new FilenameFilter() {
  109. public boolean accept(File dir, String name) {
  110. return name.startsWith(".") == false; // skip hidden files
  111. }
  112. });
  113. if (files != null) {
  114. for (int i = 0; i < files.length; i++) {
  115. boolean newFile = true;
  116. for (UpdatingFileTree c : children) {
  117. if (c.thisFile.equals(files[i]) == true) {
  118. newFile = false;
  119. break;
  120. }
  121. }
  122. if (newFile) {
  123. UpdatingFileTree neu = new UpdatingFileTree(files[i], mSpawn);
  124. long thresh = neu.thisFile.lastModified() + IDLE_THRESHOLD;
  125. if (thresh < System.currentTimeMillis()) {
  126. children.add(neu);
  127. if (neu.isDirectory()) {
  128. mHasDirectoryChildren = true;
  129. }
  130. neu.broadcast();
  131. } else {
  132. logger.fine("skipping too-fresh file: "
  133. + neu.thisFile.getAbsolutePath() + " "
  134. + (thresh - System.currentTimeMillis()) + "s left");
  135. }
  136. }
  137. }
  138. } else if (thisFile.exists() == false) {
  139. logger.finest(getThisFile().getAbsolutePath() + " will be gone next pass");
  140. gone = true; // will get removed during the next pass
  141. mSpawn.broadcastChange(this, true);
  142. }
  143. } else if (thisFile.exists() == false) {
  144. logger.finest(getThisFile().getAbsolutePath() + " will be gone next pass");
  145. gone = true; // will get removed during the next pass
  146. mSpawn.broadcastChange(this, true);
  147. }
  148. }
  149. public List<UpdatingFileTree> getDirectoryChildren() {
  150. if (mHasDirectoryChildren == false) {
  151. return new ArrayList<UpdatingFileTree>(0);
  152. } else {
  153. List<UpdatingFileTree> out = new ArrayList<UpdatingFileTree>();
  154. for (UpdatingFileTree u : children) {
  155. if (u.isDirectory() && !u.gone)
  156. out.add(u);
  157. }
  158. return out;
  159. }
  160. }
  161. public List<UpdatingFileTree> getFileChildren() {
  162. List<UpdatingFileTree> out = new ArrayList<UpdatingFileTree>();
  163. for (UpdatingFileTree u : children) {
  164. if (u.isDirectory() == false && !u.gone)
  165. out.add(u);
  166. }
  167. return out;
  168. }
  169. public List<UpdatingFileTree> getChildren() {
  170. return children;
  171. }
  172. public String toString() {
  173. return thisFile.getName()
  174. + (isDirectory() && children != null ? " (" + children.size() + " children)" : "");
  175. }
  176. public File getThisFile() {
  177. return thisFile;
  178. }
  179. public long modifiedChecksum() {
  180. long sum = getLastModified();
  181. for (UpdatingFileTree k : children) {
  182. sum += k.modifiedChecksum();
  183. }
  184. return sum;
  185. }
  186. }