/* * Copyright (C) 2006-2008 Alfresco Software Limited. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * As a special exception to the terms and conditions of version 2.0 of * the GPL, you may redistribute this Program in connection with Free/Libre * and Open Source Software ("FLOSS") applications as described in Alfresco's * FLOSS exception. You should have recieved a copy of the text describing * the FLOSS exception, and it is also available here: * http://www.alfresco.com/legal/licensing" */ package org.alfresco.jlan.smb.server.disk; import java.io.File; import org.alfresco.jlan.server.filesys.FileAttribute; import org.alfresco.jlan.server.filesys.FileInfo; import org.alfresco.jlan.server.filesys.FileName; import org.alfresco.jlan.server.filesys.SearchContext; import org.alfresco.jlan.util.WildCard; /** * Java File Search Context Class * * @author gkspencer */ public class JavaFileSearchContext extends SearchContext { // Directory that we are searching private File m_root; // List of files private String[] m_list; private int m_idx; // File attributes private int m_attr; // Single file/directory search flag private boolean m_single; // Wildcard checker private WildCard m_wildcard; // Relative path to folder being searched private String m_relPath; /** * Class constructor */ protected JavaFileSearchContext() { } /** * Return the list of file names for a directory. * * @param file java.io.File * @return java.lang.String[] */ protected final String[] getListForDirectory(File file) { // Check if the file is a directory if (isDirectory(file) == false) return null; // Get the file list for the directory String[] fileList = file.list(); if (fileList == null) { // Try and get the file list another way File file2 = new File(file.getPath().substring(0, file.getPath().length() - 1)); fileList = file2.list(); } // Return the file list return fileList; } /** * Return the resume id for the current file/directory. We return the index of the next file, * this is the file/directory that will be returned if the search is restarted. * * @return int Resume id. */ public int getResumeId() { return m_idx; } /** * Determine if there are more files to return for this search * * @return boolean */ public boolean hasMoreFiles() { // Determine if there are any more files to be returned if (m_single == true && m_idx > 0) return false; else if (m_list != null && m_idx >= m_list.length) return false; return true; } /** * Start a directory search. * * @param path java.lang.String * @param attr int */ public final void initSearch(String path, int attr) throws java.io.FileNotFoundException { // Store the search attributes m_attr = attr; // Split the path, check if there is a filename String[] pathStr = FileName.splitPath(path, java.io.File.separatorChar); // Set the search string for the context if (pathStr[1] != null) setSearchString(pathStr[1]); // Create the root file if (pathStr[1] != null && WildCard.containsWildcards(pathStr[1]) == false) { // Indicate that the search is for a single file/directory setSingleFileSearch(true); // Path may be a file m_root = new File(pathStr[0], pathStr[1]); if (m_root.exists() == false) { // Rebuild the path, looks like it is a directory m_root = new File(FileName.buildPath(pathStr[0], pathStr[1], null, java.io.File.separatorChar)); if (m_root.exists() == false) throw new java.io.FileNotFoundException(path); } } else { // Wildcard search of a directory String root = pathStr[0]; if ( root.endsWith(":")) root = root + java.io.File.separator; m_root = new File(root); if (isDirectory(m_root)) { // Check if there is a file spec, if not then the search is for the directory only if (pathStr[1] == null) { // Single file directory search setSingleFileSearch(true); } else { // Multi file search, get the file list for the directory m_list = getListForDirectory(m_root); // If there is not file list, the path does not exist if (m_list == null) throw new java.io.FileNotFoundException(path); // Indicate a multi-file search setSingleFileSearch(false); // Create the wildcard checker m_wildcard = new WildCard(pathStr[1],false); } } } // Clear the current file index m_idx = 0; } /** * Test if the specified file is a file or directory. * * @param file java.io.File * @return boolean */ protected final boolean isDirectory(File file) { // If the file object says it is a directory then it's a directory ! if (file.isDirectory()) return true; // If we can produce a file list then the file is a directory if (file.list() != null) return true; // Looks like it's a file then ! return false; } /** * Determine if this is a wildcard or single file/directory type search. * * @return boolean */ protected final boolean isSingleFileSearch() { return m_single; } /** * Determine if the search is valid. The directory may not exist or the file may not exist for a * single file search. * * @return boolean */ public final boolean isValidSearch() { return m_root != null ? true : false; } /** * Return the next file information for this search * * @param info FileInfo * @return boolean */ public boolean nextFileInfo(FileInfo info) { // Get the next file information boolean infoValid = false; if (isSingleFileSearch()) { // Check if we have already returned the root file details if (m_idx == 0) { // Update the file index, indicates that we have returned the single file/directory // details. m_idx++; // Determine if the search is for a file or directory int fattr = 0; long flen = 0L; if (isDirectory(m_root)) fattr = FileAttribute.Directory; else flen = m_root.length(); // Check if the file/folder is read-only if ( m_root.canWrite() == false) fattr += FileAttribute.ReadOnly; // Return the file information info.setFileName(m_root.getName()); info.setSize(flen); info.setFileAttributes(fattr); info.setFileId(m_root.getAbsolutePath().hashCode()); long modifyDate = m_root.lastModified(); info.setModifyDateTime(modifyDate); info.setChangeDateTime(modifyDate); long dummyCreate = JavaFileDiskDriver.getGlobalCreateDateTime(); if ( dummyCreate > modifyDate) dummyCreate = modifyDate; info.setCreationDateTime(dummyCreate); // Indicate that the file information is valid infoValid = true; } } else if (m_list != null && m_idx < m_list.length) { // Find a file/directory that matches the search attributes boolean foundMatch = false; File curFile = new File(m_root, m_list[m_idx++]); while (foundMatch == false && curFile != null) { // Check if the file name matches the search pattern if ( m_wildcard.matchesPattern(curFile.getName()) == true) { // Check if the file matches the search attributes if (FileAttribute.hasAttribute(m_attr, FileAttribute.Directory) && isDirectory(curFile)) { // Found a match foundMatch = true; } else if ( curFile.isFile()) { // && SMBFileAttribute.hasAttribute(m_attr,SMBFileAttribute.System) == false) { // Found a match foundMatch = true; } } // Check if we found a match if ( foundMatch == false) { // Get the next file from the list if (m_idx < m_list.length) curFile = new File(m_root, m_list[m_idx++]); else curFile = null; } } // Check if there is a file to return if (curFile != null) { // Create a file information object for the file int fattr = 0; long flen = 0L; String fname = curFile.getName(); if (isDirectory(curFile)) { // Set the directory attribute fattr = FileAttribute.Directory; // Check if the diretory should be hidden if ( fname.startsWith( ".")) fattr += FileAttribute.Hidden; } else { // Set the file length flen = curFile.length(); // Check if the file/folder is read-only if ( curFile.canWrite() == false) fattr += FileAttribute.ReadOnly; // Check for common hidden files if ( fname.equalsIgnoreCase("Desktop.ini") || fname.equalsIgnoreCase("Thumbs.db") || fname.startsWith( ".")) fattr += FileAttribute.Hidden; } // Create the file information object info.setFileName(curFile.getName()); info.setSize(flen); info.setFileAttributes(fattr); // Build the share relative file path to generate the file id StringBuffer relPath = new StringBuffer(); relPath.append(m_relPath); relPath.append(curFile.getName()); info.setFileId(relPath.toString().hashCode()); // Set the file timestamps long modifyDate = m_root.lastModified(); info.setModifyDateTime(modifyDate); info.setChangeDateTime(modifyDate); long dummyCreate = JavaFileDiskDriver.getGlobalCreateDateTime(); if ( dummyCreate > modifyDate) dummyCreate = modifyDate; info.setCreationDateTime(dummyCreate); // Indicate that the file information is valid infoValid = true; } } // Return the file information valid state return infoValid; } /** * Return the next file name for this search * * @return String */ public String nextFileName() { // Get the next file name if (isDirectory(m_root) == false) { // Check if we have already returned the root file name if (m_idx == 0) { // Return the root file name m_idx++; return m_root.getName(); } else return null; } // Return the next file name from the list else if (m_list != null && m_idx < m_list.length) { // Find the next matching file name while ( m_idx < m_list.length) { // Check if the current file name matches the search pattern String fname = m_list[m_idx++]; if ( m_wildcard.matchesPattern(fname)) return fname; } } // No more file names return null; } /** * Restart the search at the specified resume point. * * @param resumeId Resume point. * @return true if the search can be restarted, else false. */ public boolean restartAt(int resumeId) { // Check if the resume point is valid if (m_list == null || resumeId >= m_list.length) return false; // Reset the current search point m_idx = resumeId; return true; } /** * Restart the file search at the specified file * * @param info FileInfo * @return boolean */ public boolean restartAt(FileInfo info) { // Check if the file list is valid boolean restartOK = false; m_idx--; if (m_list != null) { // Step backwards through the file list until we find the required restart file while (m_idx > 0 && restartOK == false) { // Check if we found the restart file if (m_list[m_idx].compareTo(info.getFileName()) == 0) restartOK = true; else m_idx--; } } // Return the restart status return restartOK; } /** * Set the wildcard/single file search flag. * * @param single boolean */ protected final void setSingleFileSearch(boolean single) { m_single = single; } /** * Return the total number of file entries for this search if known, else return -1 * * @return int */ public int numberOfEntries() { // return the count of file entries to be returned by this search if ( isSingleFileSearch()) return 1; else if ( m_list != null) return m_list.length; else return -1; } /** * Set the share relative path to the search folder * * @param relPath String */ public final void setRelativePath(String relPath) { m_relPath = relPath; if ( m_relPath != null && m_relPath.endsWith( FileName.DOS_SEPERATOR_STR) == false) m_relPath = m_relPath + FileName.DOS_SEPERATOR_STR; } }