/* * NOTE: This copyright does *not* cover user programs that use HQ * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. * This file is part of HQ. * * HQ is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. */ package org.hyperic.util.file.match; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Vector; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.types.selectors.FileSelector; import org.apache.tools.ant.util.FileUtils; class MatcherScanner extends DirectoryScanner { private int maxDepth; private Log log; private MatcherInterruptCallback interruptCB = null; private MatcherProgressCallback progressCB = null; private Map matches; private List errors; private boolean myFollowSymlinks = false; private static final FileUtils myFileUtils = FileUtils.newFileUtils(); private int pauseCounter = 0; public MatcherScanner () { super(); errors = new ArrayList(); } public void initMatches ( Map matches ) { this.matches = matches; } public List getErrors () { return errors; } public void addError ( Exception e ) { errors.add(e); } public void setMaxDepth ( int max ) { maxDepth = max; } public Log getLog () { return this.log; } public void setLog ( Log log ) { this.log = log; } public void setMatcherInterruptCB (MatcherInterruptCallback icb) { interruptCB = icb; } public void setMatcherProgressCB (MatcherProgressCallback pcb) { progressCB = pcb; } protected void addMatch ( Object key, String fullpath ) { // System.err.println("MS--->addMatch(" + key + ", " + fullpath + ")"); List existingList = (List) matches.get(key); if ( existingList == null ) { existingList = new ArrayList(); matches.put(key, existingList); } existingList.add(fullpath); } public Map getMatches () { return matches; } public void setSelectors(FileSelector[] selectors) { super.setSelectors(selectors); for ( int i=0; i<selectors.length; i++ ) { if ( selectors[i] instanceof MatchSelector ) { ((MatchSelector) selectors[i]).setMatcherScanner(this); } } } public void setFollowSymlinks(boolean followSymlinks) { this.myFollowSymlinks = followSymlinks; super.setFollowSymlinks(followSymlinks); } public void doScan() throws MatcherInterruptedException { checkInterrupted(); for ( int i=0; i<selectors.length; i++ ) { if ( selectors[i] instanceof MasterMatchSelector ) { ((MasterMatchSelector) selectors[i]).setScanner(this); } } super.scan(); } private void checkInterrupted () throws MatcherInterruptedException { if ( interruptCB != null ) { if ( interruptCB.getIsInterrupted() ) { throw new MatcherInterruptedException(); } } else { // Just check for thread interruption if ( Thread.currentThread().isInterrupted() ) { throw new MatcherInterruptedException(); } } } /** Override default implementation to track dir depth */ protected void scandir(File dir, String vpath, boolean fast) { pauseCounter = 0; scandir(dir, vpath, 0); } private void pause () { if ( ++pauseCounter % 25 == 0 ) { try { Thread.sleep(50); } catch (InterruptedException ie) { throw new MatcherInterruptedException(); } } } protected void scandir(File dir, String vpath, int depth) { // This is just here to ensure that our scanning doesn't spin-up // the CPU. We sleep briefly every few directories to give other // processes a chance to run. pause(); if ( depth > maxDepth && maxDepth != -1 ) { if ( log != null ) { //log.info("scandir: Skipping dir " + dir.getAbsolutePath() // + " and all subdirs because they are below our " // + "maxDepth of " + maxDepth); } return; } else { checkInterrupted(); if ( isExcluded(dir.getAbsolutePath()) ) { //log.info("scandir: Skipping: " + dir.getAbsolutePath() // + " because it is explicitly excluded from scan."); return; } } if ( !dir.canRead() ) { errors.add(new MatcherException("Don't have permissions to read " + "directory: " + dir.getAbsolutePath())); return; } String[] newfiles = dir.list(); if (newfiles == null) { /* * two reasons are mentioned in the API docs for File.list * (1) dir is not a directory. This is impossible as * we wouldn't get here in this case. * (2) an IO error occurred (why doesn't it throw an exception * then???) */ errors.add(new MatcherException("IO error scanning directory " + dir.getAbsolutePath())); return; } // log.debug("scandir: Scanning: " + dir.getAbsolutePath()); // Tell someone how our scan is progressing... if ( progressCB != null ) progressCB.notifyScanDir(dir); if (!myFollowSymlinks) { Vector noLinks = new Vector(); for (int i = 0; i < newfiles.length; i++) { checkInterrupted(); try { if (myFileUtils.isSymbolicLink(dir, newfiles[i])) { String name = vpath + newfiles[i]; File file = new File(dir, newfiles[i]); if (file.isDirectory()) { dirsExcluded.addElement(name); } else { filesExcluded.addElement(name); } } else { noLinks.addElement(newfiles[i]); } } catch (IOException ioe) { String msg = "IOException caught while checking " + "for links, couldn't get canonical path!"; // will be caught and redirected to Ant's logging system errors.add(new MatcherException(msg, ioe)); } } newfiles = new String[noLinks.size()]; noLinks.copyInto(newfiles); } for (int i = 0; i < newfiles.length; i++) { checkInterrupted(); pause(); String name = vpath + newfiles[i]; File file = new File(dir, newfiles[i]); if (file.isDirectory()) { if (isIncluded(name)) { if (!isExcluded(name)) { // log.info("scandir: checking isSelected(" + name + "," + file.getAbsolutePath() + ")"); if (isSelected(name,file)) { continue; } else { if (/*fast &&*/ couldHoldIncluded(name)) { scandir(file, name + File.separator, depth+1); } } } else { if (/*fast &&*/ couldHoldIncluded(name)) { scandir(file, name + File.separator, depth+1); } } } else { if (/*fast &&*/ couldHoldIncluded(name)) { scandir(file, name + File.separator, depth+1); } } // if (!fast) { // scandir(file, name + File.separator, fast); // } } else if (file.isFile()) { if (isIncluded(name)) { if (!isExcluded(name)) { if (isSelected(name,file)) { continue; } else { // everythingIncluded = false; // filesDeselected.addElement(name); } } else { // everythingIncluded = false; // filesExcluded.addElement(name); } } else { // everythingIncluded = false; // filesNotIncluded.addElement(name); } } } } }