From: <ls...@us...> - 2009-04-01 15:03:34
|
Revision: 5208 http://jnode.svn.sourceforge.net/jnode/?rev=5208&view=rev Author: lsantha Date: 2009-04-01 15:03:30 +0000 (Wed, 01 Apr 2009) Log Message: ----------- 'find' command implementation - by Alexander Kerner Modified Paths: -------------- trunk/fs/descriptors/org.jnode.fs.command.xml Added Paths: ----------- trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java Modified: trunk/fs/descriptors/org.jnode.fs.command.xml =================================================================== --- trunk/fs/descriptors/org.jnode.fs.command.xml 2009-04-01 13:44:48 UTC (rev 5207) +++ trunk/fs/descriptors/org.jnode.fs.command.xml 2009-04-01 15:03:30 UTC (rev 5208) @@ -33,6 +33,7 @@ <alias name="touch" class="org.jnode.fs.command.TouchCommand"/> <alias name="hexdump" class="org.jnode.fs.command.HexdumpCommand"/> <alias name="md5sum" class="org.jnode.fs.command.Md5SumCommand"/> + <alias name="find" class="org.jnode.fs.command.FindCommand"/> </extension> <extension point="org.jnode.shell.syntaxes"> @@ -112,6 +113,20 @@ <syntax alias="touch"> <argument argLabel="file" description="touch the given file"/> </syntax> + <syntax alias="find"> + <sequence description="find files or directories"> + <repeat minCount="1"> + <argument argLabel="directory"/> + </repeat> + <optionSet> + <option argLabel="type" longName="type"/> + <option argLabel="maxdepth" longName="maxdepth"/> + <option argLabel="mindepth" longName="mindepth"/> + <option argLabel="name" longName="name"/> + <option argLabel="iname" longName="iname"/> + </optionSet> + </sequence> + </syntax> </extension> <extension point="org.jnode.security.permissions"> Added: trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java (rev 0) +++ trunk/fs/src/fs/org/jnode/fs/command/AbstractDirectoryWalker.java 2009-04-01 15:03:30 UTC (rev 5208) @@ -0,0 +1,113 @@ +package org.jnode.fs.command; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; + +public abstract class AbstractDirectoryWalker { + + private class FileObject { + final File file; + final Long depth; + + FileObject(File file, Long depth) { + this.file = file; + this.depth = depth; + } + } + + private final Stack<FileObject> stack = new Stack<FileObject>(); + private final Set<FileFilter> filters = new HashSet<FileFilter>(); + private volatile boolean cancelled = false; + private volatile Long maxDepth = null; + private volatile Long minDepth = null; + + public synchronized void walk(final File... dirs) throws IOException { + for (File dir : dirs) { + if (dir == null) + throw new IOException("No such directroy " + dir); + dir = dir.getAbsoluteFile(); // to be able to handle relative paths + if (!dir.canRead() || !dir.isDirectory()) { + throw new IOException("Cannot read directroy " + dir); + } + stack.push(new FileObject(dir, 0L)); + while (!cancelled && !stack.isEmpty()) { + go1(stack.pop()); + } + } + } + + private void go1(final FileObject file) throws IOException { + if ((minDepth != null && file.depth < minDepth) || (maxDepth != null && file.depth > maxDepth)) { + // out of boundaries + } else if (!file.file.canRead()) { + // ignore for now + } else if (validFileOrDirectory(file)) { + handleFileOrDir(file); + } else { + // filtered out + } + go2(file); + } + + private void go2(final FileObject file) throws IOException { + final Stack<File> stack = new Stack<File>(); + final File[] content = file.file.listFiles(); + if (content != null) { + for (File f : content) { + if (f.toString().equals(f.getCanonicalPath())) { + stack.push(f); + } else { + // dont follow symlinks + } + } + while (!stack.isEmpty()) { + File tmp = stack.pop(); + // addToStack(stack.pop(), file.depth + 1); + this.stack.push(new FileObject(tmp, file.depth + 1)); + } + } + } + + private void handleFileOrDir(final FileObject file) { + if (file.file.isDirectory()) + handleDir(file.file); + else if (file.file.isFile()) + handleFile(file.file); + else { + // ignore unknown file type + } + } + + private boolean validFileOrDirectory(final FileObject file) { + if (!filters.isEmpty()) + for (FileFilter filter : filters) + if (!filter.accept(file.file)) + return false; + return true; + } + + public void stoppWalking() { + cancelled = true; + } + + public void setMinDepth(Long min) { + minDepth = min; + } + + public void setMaxDepth(Long max) { + maxDepth = max; + } + + public synchronized void addFilter(FileFilter filter) { + filters.add(filter); + } + + public abstract void handleDir(File f); + + public abstract void handleFile(File f); + +} Added: trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java =================================================================== --- trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java (rev 0) +++ trunk/fs/src/fs/org/jnode/fs/command/FindCommand.java 2009-04-01 15:03:30 UTC (rev 5208) @@ -0,0 +1,108 @@ +package org.jnode.fs.command; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.jnode.shell.AbstractCommand; +import org.jnode.shell.syntax.Argument; +import org.jnode.shell.syntax.FileArgument; +import org.jnode.shell.syntax.LongArgument; +import org.jnode.shell.syntax.StringArgument; + +public class FindCommand extends AbstractCommand { + + private class Walker extends AbstractDirectoryWalker { + + @Override + public void handleDir(File f) { + out.println(f); + } + + @Override + public void handleFile(File f) { + out.println(f); + } + + } + + private final StringArgument nameArg = new StringArgument("name", Argument.OPTIONAL); + private final StringArgument inameArg = new StringArgument("iname", Argument.OPTIONAL); + private final LongArgument maxdepthArg = new LongArgument("maxdepth", Argument.OPTIONAL); + private final LongArgument mindepthArg = new LongArgument("mindepth", Argument.OPTIONAL); + private final StringArgument typeArg = new StringArgument("type", Argument.OPTIONAL); + private final FileArgument dirArg = + new FileArgument("directory", Argument.MANDATORY | Argument.EXISTING + | Argument.MULTIPLE); + private PrintWriter out = null; + + public FindCommand() { + super("Find files and directories"); + registerArguments(dirArg, mindepthArg, maxdepthArg, inameArg, nameArg, typeArg); + } + + public static void main(String[] args) throws IOException { + + new FindCommand().execute(); + } + + public void execute() throws IOException { + out = getOutput().getPrintWriter(); + final Walker walker = new Walker(); + + if (maxdepthArg.isSet()) { + walker.setMaxDepth(maxdepthArg.getValue()); + } + + if (mindepthArg.isSet()) { + walker.setMinDepth(mindepthArg.getValue()); + } + + if (nameArg.isSet()) { + final String value = nameArg.getValue(); + walker.addFilter(new FileFilter() { + @Override + public boolean accept(File file) { + Pattern p = Pattern.compile(value); + Matcher m = p.matcher(file.getName()); + return m.matches(); + } + }); + } + + if (inameArg.isSet()) { + final String value = inameArg.getValue(); + walker.addFilter(new FileFilter() { + @Override + public boolean accept(File file) { + Pattern p = Pattern.compile(value, Pattern.CASE_INSENSITIVE); + Matcher m = p.matcher(file.getName()); + return m.matches(); + } + }); + } + + if (typeArg.isSet()) { + final Character value = typeArg.getValue().charAt(0); + if (value.equals(Character.valueOf('f'))) { + walker.addFilter(new FileFilter() { + @Override + public boolean accept(File file) { + return file.isFile(); + } + }); + } else if (value.equals(Character.valueOf('d'))) { + walker.addFilter(new FileFilter() { + @Override + public boolean accept(File file) { + return file.isDirectory(); + } + }); + } + } + walker.walk(dirArg.getValues()); + } +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |