001    package org.wdssii.core.fam;
002    
003    import java.io.File;
004    import java.io.FilenameFilter;
005    import java.util.ArrayList;
006    import java.util.Arrays;
007    import java.util.List;
008    
009    import net.contentobjects.jnotify.JNotify;
010    import net.contentobjects.jnotify.JNotifyException;
011    import net.contentobjects.jnotify.JNotifyListener;
012    
013    import org.apache.commons.logging.Log;
014    import org.apache.commons.logging.LogFactory;
015    
016    public class FamIndexHelperInotifyImpl implements FamIndexHelper,
017                    JNotifyListener {
018    
019            private final Log log = LogFactory.getLog(getClass());
020            private List<File> files = new ArrayList<File>();
021            private int wd;
022            private final FilenameFilter filenamePattern;
023    
024            /** By default look only at files that end with .fml */
025            public FamIndexHelperInotifyImpl() {
026                    this(new FmlFilesOnlyFilter());
027            }
028            
029            public FamIndexHelperInotifyImpl(FilenameFilter pattern) {
030                    // this will cause a class-load exception if JNotify is not in classpath
031                    try{
032                            JNotify.removeWatch(-1);
033                    } catch (JNotifyException e){
034                            // ok
035                    }
036                    filenamePattern = pattern;
037            }
038            
039            @Override
040            public File[] getInitialFiles(String indexDir) {
041                    try {
042                            // JNotify maps IN_CREATE and IN_MOVED_TO to these constants
043                            final int mask = JNotify.FILE_CREATED | JNotify.FILE_RENAMED;
044                            this.wd = JNotify.addWatch(indexDir, mask, false, this);
045                            if (log.isInfoEnabled()) {
046                                    log.info("Successfully created inotify watch for " + indexDir
047                                                    + " wd=" + wd);
048                            }
049                    } catch (JNotifyException e) {
050                            log
051                                            .error("Make sure that the jnotify jar file and .so are in Tomcat's shared/lib");
052                            log
053                                            .error(
054                                                            "Otherwise, you could try using WebIndexDirectoryListingDAO instead",
055                                                            e);
056                            throw new UnsupportedOperationException(e);
057                    }
058                    // existing files
059                    File[] files = new File(indexDir).listFiles(filenamePattern);
060                    Arrays.sort(files);
061                    return files;
062            }
063    
064            @Override
065            public synchronized void fileCreated(int watch, String indexDir,
066                            String filename) {
067                    if (filename != null && filenamePattern.accept(null, filename)) {
068                            File f = new File(indexDir, filename);
069                            files.add(f);
070                    }
071            }
072    
073            @Override
074            public synchronized void fileDeleted(int arg0, String arg1, String arg2) {
075            }
076    
077            @Override
078            public synchronized void fileModified(int arg0, String arg1, String arg2) {
079            }
080    
081            @Override
082            public synchronized void fileRenamed(int wd, String indexDir,
083                            String oldName, String newName) {
084                    if (newName != null && filenamePattern.accept(null, newName)) {
085                            File f = new File(indexDir, newName);
086                            files.add(f);
087                    }
088            }
089    
090            @Override
091            /**
092             * returns new files in watched directory since previous call to this
093             * method.
094             */
095            public synchronized File[] getNewFiles() {
096                    File[] newfiles = files.toArray(new File[0]);
097                    files.clear(); // start accumulating again
098                    return newfiles;
099            }
100    
101            /**
102             * De-registers from the watch so that the servlet container does not keep
103             * receiving events.
104             */
105            @Override
106            public void close() {
107                    if (wd >= 0) {
108                            try {
109                                    JNotify.removeWatch(wd);
110                                    if (log.isInfoEnabled()) {
111                                            log.info("Removed inotify watch wd=" + wd);
112                                    }
113                            } catch (JNotifyException e) {
114                                    // ok
115                            }
116                    }
117            }
118    
119            @Override
120            public void pruneToMaxSize(long m, long n){
121                    // nothing to do
122            }
123    }