📄 directorymanager.java
字号:
/*------------------------------------------------------------------------------Name: DirectoryManager.javaProject: xmlBlaster.orgCopyright: xmlBlaster.org, see xmlBlaster-LICENSE file------------------------------------------------------------------------------*/package org.xmlBlaster.client.filepoller;import java.io.BufferedInputStream;import java.io.File;import java.io.FileFilter;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.TreeSet;import java.util.logging.Logger;import java.util.logging.Level;import org.xmlBlaster.util.Global;import org.xmlBlaster.util.XmlBlasterException;import org.xmlBlaster.util.def.ErrorCode;/** * DirectoryManager * @author <a href="mailto:michele@laghi.eu">Michele Laghi</a> * @deprectated it is now replaced by the corresponding class in org.xmlBlaster.contrib.filewatcher */public class DirectoryManager { private String ME = "DirectoryManager"; private Global global; private static Logger log = Logger.getLogger(DirectoryManager.class.getName()); private long delaySinceLastFileChange; private String directoryName; private File directory; /** this is the the directory where files are moved to after successful publishing. If null they will be erased */ private File sentDirectory; /** this is the name of the directory where files are moved if they could not be send (too big) */ private File discardedDirectory; private Map directoryEntries; /** all files matching the filter will be processed. Null means everything will be processed */ private FileFilter fileFilter; /** if set, then files will only be published when the lock-file has been removed. */ private FileFilter lockExtention; /** convenience for performance: if lockExtention is '*.gif', then this will be '.gif' */ private String lockExt; private Set lockFiles; private boolean copyOnMove; public DirectoryManager(Global global, String name, String directoryName, long delaySinceLastFileChange, String filter, String sent, String discarded, String lockExtention, boolean trueRegex, boolean copyOnMove) throws XmlBlasterException { ME += "-" + name; this.global = global; if (filter != null) this.fileFilter = new FilenameFilter(filter, trueRegex); this.delaySinceLastFileChange = delaySinceLastFileChange; this.directoryEntries = new HashMap(); this.directoryName = directoryName; this.directory = initDirectory(null, "directoryName", directoryName); if (this.directory == null) throw new XmlBlasterException(this.global, ErrorCode.INTERNAL_NULLPOINTER, ME + ".constructor", "the directory '" + directoryName + "' is null"); this.sentDirectory = initDirectory(this.directory, "sent", sent); this.discardedDirectory = initDirectory(this.directory, "discarded", discarded); if (lockExtention != null) { String tmp = lockExtention.trim(); if (!tmp.startsWith("*.")) { throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_CONFIGURATION, ME, "lockExtention must start with '*.' and be of the kind '*.lck'"); } this.lockExtention = new FilenameFilter(tmp, false); this.lockExt = tmp.substring(1); // '*.gif' -> '.gif' } this.lockFiles = new HashSet(); this.copyOnMove = copyOnMove; } /** * Returns the specified directory or null or if needed it will create one * @param propName * @param dirName * @return * @throws XmlBlasterException */ private File initDirectory(File parent, String propNameForLogging, String dirName) throws XmlBlasterException { File dir = null; if (dirName != null) { File tmp = new File(dirName); if (tmp.isAbsolute() || parent == null) { dir = new File(dirName); } else { dir = new File(parent, dirName); } if (!dir.exists()) { String absDirName = null; try { absDirName = dir.getCanonicalPath(); } catch (IOException ex) { absDirName = dir.getAbsolutePath(); } log.info(ME+": Constructor: directory '" + absDirName + "' does not yet exist. I will create it"); boolean ret = dir.mkdir(); if (!ret) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME, "could not create directory '" + absDirName + "'"); } if (!dir.isDirectory()) { throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME, "'" + dir.getAbsolutePath() + "' is not a directory"); } if (!dir.canRead()) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME + ".constructor", "no rights to read from the directory '" + dir.getAbsolutePath() + "'"); if (!dir.canWrite()) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME + ".constructor", "no rights to write to the directory '" + dir.getAbsolutePath() + "'"); } else { log.info(ME+": Constructor: the '" + propNameForLogging + "' property is not set. Instead of moving concerned entries they will be deleted"); } return dir; } /** * Retrieves all files from the specified directory * @param directory * @return never returns null. * @throws XmlBlasterException */ private Map getNewFiles(File directory) throws XmlBlasterException { if (this.lockExtention != null) { // reset lockFile set this.lockFiles.clear(); } this.directory = initDirectory(null, "directoryName", this.directoryName); if (!directory.canRead()) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME + ".scan", "I don't have rights to read from '" + directory.getName() + "'"); if (!directory.canWrite()) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME + ".scan", "I don't have rights to write to '" + directory.getName() + "'"); File[] files = directory.listFiles(this.fileFilter); if (files == null || files.length == 0) return new HashMap(); if (this.lockExtention != null) { // and then retrieve all lock files (this must be done after having got 'files' to avoid any gaps File[] lckFiles = directory.listFiles(this.lockExtention); if (lckFiles != null) { for (int i=0; i < lckFiles.length; i++) { String name = null; try { name = lckFiles[i].getCanonicalPath(); } catch (IOException ex) { throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME + ".getNewFiles", " could not get the canonical name of file '" + files[i].getName() + "'"); } int pos = -1; if (this.lockExt != null) pos = (isFileNameCasesensitive() ? name.lastIndexOf(this.lockExt) : name.toUpperCase().lastIndexOf(this.lockExt.toUpperCase())); if (pos < 0) throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_CONFIGURATION, ME, "can not handle lckExtention '*" + this.lockExt + "'"); this.lockFiles.add(name.substring(0, pos)); } } } Map map = new HashMap(files.length); for (int i=0; i < files.length; i++) { try { String name = files[i].getCanonicalPath(); if (files[i].isFile()) { boolean endsWithLockExt = false; if (this.lockExt != null) endsWithLockExt = (isFileNameCasesensitive() ? name.endsWith(this.lockExt) : name.toUpperCase().endsWith(this.lockExt.toUpperCase())); if (this.lockExtention == null || (!this.lockFiles.contains(name) && !endsWithLockExt)) map.put(name, files[i]); } } catch (IOException ex) { throw new XmlBlasterException(this.global, ErrorCode.RESOURCE_FILEIO, ME + ".getNewFiles", " could not get the canonical name of file '" + files[i].getName() + "'"); } } return map; } /** * On Windows sometimes the file is not deleted (even if the stream.close() were called before) * We try as long until the file is away * See http://forum.java.sun.com/thread.jspa?forumID=4&threadID=158689 * @param tempFile * @return true if successfully deleted */ private boolean deleteFile(File tempFile) { if (!tempFile.exists()) return true; final int MAX = 100; boolean warn = false; int i=0; for (i=0; i<MAX; i++) { if (!tempFile.delete()) { warn = true; if (!tempFile.exists()) // calling double delete fails, so check here break; if (i == 0) log.fine(ME+": Deleting file " + tempFile.getAbsolutePath() + " failed"); System.gc(); if (!tempFile.delete()) { if (i == 0) log.warning(ME+": Deleting file " + tempFile.getAbsolutePath() + " failed even after GC"); try { Thread.sleep(100); } catch (InterruptedException e) { } } else break; } else break; } if (i >= MAX) { log.severe(ME+": Deleting file " + tempFile.getAbsolutePath() + " failed, giving up"); return false; } else { if (warn) log.info(ME+": Deleting file " + tempFile.getAbsolutePath() + " finally succeeded after " + (i+1) + " tries"); return true; } } public static boolean isFileNameCasesensitive() { String osName = System.getProperty("os.name"); if (osName == null) return true; if (osName.startsWith("Windows")) return false; return true; } /** * Returns false if the info object is null, if the size is zero or * if it has not passed sufficient time since the last change. * * @param info * @param currentTime * @return */ private boolean isReady(FileInfo info, long currentTime) { if (info == null) return false; //if (info.getSize() < 1L) // return false; if (this.lockExtention != null) { return !this.lockFiles.contains(info.getName()); } long delta = currentTime - info.getLastChange(); if (log.isLoggable(Level.FINEST)) { log.finest(ME+": isReady '" + info.getName() + "' delta='" + delta + "' constant='" + this.delaySinceLastFileChange + "'"); } return delta > this.delaySinceLastFileChange; } private TreeSet prepareEntries(File directory, Map existingFiles) { if (log.isLoggable(Level.FINER)) log.finer(ME+": prepareEntries"); TreeSet chronologicalSet = new TreeSet(new FileComparator()); if (existingFiles == null || existingFiles.size() < 1) { if (log.isLoggable(Level.FINEST)) { log.finest(ME+": prepareEntries: nothing to do"); } } Iterator iter = existingFiles.values().iterator(); long currentTime = System.currentTimeMillis(); while (iter.hasNext()) { FileInfo info = (FileInfo)iter.next(); if (isReady(info, currentTime)) { chronologicalSet.add(info); } } return chronologicalSet; } /** * It updates the existing list of files: *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -