Coverage Report - org.webslinger.io.JNotifyFileMonitor
 
Classes in this File Line Coverage Branch Coverage Complexity
JNotifyFileMonitor
0%
0/17
0%
0/3
0
JNotifyFileMonitor$1
0%
0/1
N/A
0
JNotifyFileMonitor$WatchedFile
0%
0/59
0%
0/14
0
 
 1  
 package org.webslinger.io;
 2  
 
 3  
 import java.io.File;
 4  
 import java.io.IOException;
 5  
 import java.util.concurrent.ConcurrentHashMap;
 6  
 import java.util.concurrent.atomic.AtomicInteger;
 7  
 
 8  
 import net.contentobjects.jnotify.JNotify;
 9  
 import net.contentobjects.jnotify.JNotifyListener;
 10  
 
 11  0
 public class JNotifyFileMonitor extends AbstractMonitor<File, JNotifyFileMonitor, JNotifyFileMonitor.WatchedFile, FileMonitor.FileListener> implements FileMonitor {
 12  0
     public static final JNotifyFileMonitor SINGLETON = new JNotifyFileMonitor();
 13  
 
 14  
     public JNotifyFileMonitor() {
 15  0
         super();
 16  0
     }
 17  
 
 18  
     protected void activate(WatchedFile watched) throws IOException {
 19  0
         File parent = watched.file.getParentFile();
 20  0
         if (parent != null) {
 21  0
             add(parent, watched);
 22  0
             getWatched(parent).children.put(watched.file.getName(), watched);
 23  
         }
 24  0
         if (watched.file.exists()) watched.startWatch();
 25  0
     }
 26  
 
 27  
     protected void deactivate(WatchedFile watched) throws IOException {
 28  0
         File parent = watched.file.getParentFile();
 29  0
         if (parent != null) {
 30  0
             getWatched(parent).children.remove(watched.file.getName());
 31  0
             remove(parent, watched);
 32  
         }
 33  0
         watched.stopWatch();
 34  0
     }
 35  
 
 36  
     protected WatchedFile createWatched(File item) {
 37  0
         return new WatchedFile(this, item);
 38  
     }
 39  
 
 40  0
     public static final class WatchedFile extends AbstractMonitor.Watched<File, JNotifyFileMonitor, WatchedFile, FileMonitor.FileListener> implements JNotifyListener, FileMonitor.FileListener {
 41  
         protected final File file;
 42  0
         protected AtomicInteger watchId = new AtomicInteger(-1);
 43  0
         protected ConcurrentHashMap<String, WatchedFile> children = new ConcurrentHashMap<String, WatchedFile>();
 44  
 
 45  
         public WatchedFile(JNotifyFileMonitor monitor, File file) {
 46  0
             super(monitor);
 47  0
             this.file = file;
 48  0
         }
 49  
 
 50  
         public int hashCode() {
 51  0
             return WatchedFile.class.hashCode() ^ file.hashCode();
 52  
         }
 53  
 
 54  
         public boolean equals(Object o) {
 55  0
             if (!(o instanceof WatchedFile)) return false;
 56  0
             WatchedFile other = (WatchedFile) o;
 57  0
             return file.equals(other.file);
 58  
         }
 59  
 
 60  
         protected void startWatch() throws IOException {
 61  
             int oldWatchId, newWatchId;
 62  
             do {
 63  0
                 oldWatchId = watchId.get();
 64  0
                 if (oldWatchId != -1) break;
 65  0
                 newWatchId = JNotify.addWatch(file.getPath(), JNotify.FILE_CREATED | JNotify.FILE_DELETED | JNotify.FILE_MODIFIED | JNotify.FILE_RENAMED, false, this);
 66  0
                 if (watchId.compareAndSet(oldWatchId, newWatchId)) {
 67  0
                     if (oldWatchId == -1) break;
 68  0
                     JNotify.removeWatch(oldWatchId);
 69  
                 }
 70  
             } while (true);
 71  0
         }
 72  
 
 73  
         protected void stopWatch() throws IOException {
 74  
             int oldWatchId, newWatchId;
 75  
             do {
 76  0
                 oldWatchId = watchId.get();
 77  0
                 if (oldWatchId == -1) break;
 78  0
                 if (watchId.compareAndSet(oldWatchId, -1)) {
 79  0
                     JNotify.removeWatch(oldWatchId);
 80  0
                     break;
 81  
                 }
 82  
             } while (true);
 83  0
         }
 84  
 
 85  
         // sent when the parent notices something
 86  
         public void acceptEvent(File parent, Listener.Event event) {
 87  0
         }
 88  
 
 89  
         protected void processEvent(Listener.Event event) throws IOException {
 90  0
             switch (event) {
 91  
                 case CHANGE:
 92  0
                     monitor.fireEvent(file, event);
 93  0
                     break;
 94  
                 case CREATE:
 95  0
                     monitor.fireEvent(file, event);
 96  
                     do {
 97  0
                         boolean isEmpty = children.isEmpty();
 98  0
                         if (isEmpty) break;
 99  0
                         startWatch();
 100  0
                         if (isEmpty == children.isEmpty()) break;
 101  0
                         stopWatch();
 102  0
                     } while (true);
 103  
                     break;
 104  
                 case DELETE:
 105  0
                     monitor.fireEvent(file, event);
 106  0
                     stopWatch();
 107  
                     break;
 108  
             }
 109  0
         }
 110  
 
 111  
         protected void fireChildEvent(int watchId, String name, Listener.Event event) {
 112  0
             int thisId = this.watchId.get();
 113  0
             if (thisId != watchId) return;
 114  0
             WatchedFile watched = children.get(name);
 115  0
             if (watched == null) return;
 116  
             try {
 117  0
                 watched.processEvent(event);
 118  0
             } catch (IOException e) {
 119  0
                 e.printStackTrace();
 120  0
             }
 121  0
         }
 122  
 
 123  
         public void fileRenamed(int watchId, String rootPath, String oldName, String newName) {
 124  0
             assert file.getPath() == rootPath;
 125  0
             fireChildEvent(watchId, oldName, Listener.Event.DELETE);
 126  0
             fireChildEvent(watchId, newName, Listener.Event.CREATE);
 127  0
         }
 128  
 
 129  
         public void fileModified(int watchId, String rootPath, String name) {
 130  0
             assert file.getPath() == rootPath;
 131  0
             fireChildEvent(watchId, name, Listener.Event.CHANGE);
 132  0
         }
 133  
 
 134  
         public void fileDeleted(int watchId, String rootPath, String name) {
 135  0
             assert file.getPath() == rootPath;
 136  0
             fireChildEvent(watchId, name, Listener.Event.DELETE);
 137  0
         }
 138  
 
 139  
         public void fileCreated(int watchId, String rootPath, String name) {
 140  0
             assert file.getPath() == rootPath;
 141  0
             fireChildEvent(watchId, name, Listener.Event.CREATE);
 142  0
         }
 143  
     }
 144  
 }