-
Notifications
You must be signed in to change notification settings - Fork 56
Class FileSystemVisitor
Ori Roth edited this page Apr 2, 2017
·
3 revisions
public class FileSystemVisitor {
/*
* Forge (6)
*/
FileSystemVisitor(File[] from, Action visitor, String[] extensions);
FileSystemVisitor(File from, Action visitor, String[] extensions);
FileSystemVisitor(String[] from, Action visitor, String[] extensions);
FileSystemVisitor(String from, Searcher visitor, String[] extensions);
FileSystemVisitor(String from, Action visitor, String[] extensions);
FileSystemVisitor(Collection<String> from, Action visitor, String[] extensions);
/*
* Type (1)
*/
void go() throws IOException, StopTraversal;
/*
* Nested types (3)
*/
abstract static interface Action { ... }
abstract static class EmptyAction implements NonStopAction { ... }
abstract static class FileOnlyAction extends EmptyAction { ... }
}
Input types: Action, Collection, File, Searcher.
Exception types: IOException, StopTraversal.
public interface FileSystemVisitor.Action {
/*
* Type (5)
*/
void visitFile(File f) throws StopTraversal;
void visitZipEntry(String zipName, String entryName, InputStream stream) throws StopTraversal;
void visitDirectory(File f) throws StopTraversal;
void visitZip(File f) throws StopTraversal;
void visitZipDirectory(String zipName, String entryName, InputStream stream) throws StopTraversal;
/*
* Nested types (1)
*/
static class StopTraversal extends Exception { ... }
}
Input types: File, InputStream.
Exception types: StopTraversal.
public static class FileSystemVisitor.Action.StopTraversal extends Exception {
/*
* Forge (2)
*/
StopTraversal();
StopTraversal(String message);
}
interface FileSystemVisitor.NonStopAction extends Action {
/*
* Type (5)
*/
void visitFile(File f);
void visitZipEntry(String zipName, String entryName, InputStream stream);
void visitDirectory(File f);
void visitZip(File f);
void visitZipDirectory(String zipName, String entryName, InputStream stream);
}
Input types: File, InputStream.
public abstract static class FileSystemVisitor.EmptyAction implements NonStopAction {
/*
* Forge (1)
*/
EmptyAction();
/*
* Type (5)
*/
void visitDirectory(File _);
void visitZip(File _);
void visitZipDirectory(String _, String __, InputStream ___);
void visitZipEntry(String _, String __, InputStream ___);
void visitFile(File _);
}
Input types: File, InputStream.
public abstract static class FileSystemVisitor.FileOnlyAction extends EmptyAction {
/*
* Forge (1)
*/
FileOnlyAction();
/*
* Type (3)
*/
final void visitZipEntry(String zipName, String entryName, InputStream stream);
abstract void visitFile(File f);
abstract void visitZipEntry(String entryName, InputStream stream);
}
Input types: File, InputStream.
protected abstract static class FileSystemVisitor.DirectoryOnlyAction extends EmptyAction {
/*
* Type (2)
*/
final void visitZipDirectory(String zipName, String entryName, InputStream stream);
abstract void visitDirectory(File d);
}
Input types: File, InputStream.
// SSDLPedia
package il.ac.technion.cs.ssdl.files.visitors;
import static il.ac.technion.cs.ssdl.utils.DBC.nonnull;
import static il.ac.technion.cs.ssdl.utils.DBC.require;
import static il.ac.technion.cs.ssdl.utils.DBC.unused;
import il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action.StopTraversal;
import il.ac.technion.cs.ssdl.files.visitors.FindClassFile.Searcher;
import il.ac.technion.cs.ssdl.strings.Suffixed;
import il.ac.technion.cs.ssdl.utils.All;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* A class realizing a file system traversal algorithm, including delving into
* archives such as ZIP and JAR files.
*
* The traversal is carried out by calling the class constructor
* {@link FileSystemVisitor#FileSystemVisitor(String[], il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action, String[])}
* to set up the traversal parameters, and then function #go() to
* conduct the actual traversal.
*
*
* Author: Yossi Gil @since 21/05/2007
* @see #go()
* See: FileSystemVisitor#FileSystemVisitor(String[],
* il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action,
* String[])
* See: Action
*/
public class FileSystemVisitor {
/**
* Create a new visitor object to scan an array of Files naming the
* search locations.
*
* from a non-null specifying the names of the
* directories where the traversal should begin. If this array is
* of length 0, then no traversal shall be carried out. Also, if
* the supplied directories are not disjoint, then the same file
* may be visited more than once.
* visitor a non-null specifying what to do in
* each visited file
* extensions an array of non-null String
* s specifying which file extensions the visitor should call,
* e.g., ".class", ".csv", etc. If this parameter is
* null, or of length 0, or contains a
* String of length 0, then the visitor is invoked for
* all files found in the supplied path.
* @see #go
* @see #FileSystemVisitor(Collection,
* il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action,
* String[])
*/
public FileSystemVisitor(final File[] from, final Action visitor, final String... extensions) {
nonnull(from);
nonnull(visitor);
nonnull(extensions);
require(All.notNull((Object[]) from));
require(All.notNull((Object[]) extensions));
this.from = from;
this.visitor = visitor;
this.extensions = extensions;
}
/**
* Create a new visitor object to scan an array of Files naming the
* search locations.
*
* from a non-null specifying the directory or
* archive file where the traversal should begin.
* visitor a non-null specifying what to do in
* each visited file
* extensions an array of non-null String
* s specifying which file extensions the visitor should call,
* e.g., ".class", ".csv", etc. If this parameter is
* null, or of length 0, or contains a
* String of length 0, then the visitor is invoked for
* all files found in the supplied path.
* @see #go
* @see #FileSystemVisitor(Collection,
* il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action,
* String[])
*/
public FileSystemVisitor(final File from, final Action visitor, final String... extensions) {
this(new File[] { from }, visitor, extensions);
}
/**
* Create a new visitor object to scan an array of Strings naming
* the search locations.
*
* from a non-null specifying where the traversal
* should begin. If this array is of length 0, then no traversal
* shall be carried out. Also, if the supplied directories are
* not disjoint, then the same file may be visited more than
* once.
* visitor a non-null specifying what to do in
* each visited file
* extensions an array of non-null String
* s specifying which file extensions the visitor shold call,
* e.g., ".class", ".csv", etc. If this parameter is
* null, or of length 0, or contains a
* String of length 0, then the visitor is invoked for
* all files found in the supplied path.
* @see #go
* @see #FileSystemVisitor(Collection,
* il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action,
* String[])
*/
public FileSystemVisitor(final String[] from, final Action visitor, final String... extensions) {
this(asFiles(from), visitor, extensions);
}
/**
* Create a new visitor object to scan a String naming the search
* location.
*
* from a non-null specifying where the traversal
* should begin.
* visitor a non-null specifying what to do in
* each visited file
* extensions an array of non-null String
* s specifying which file extensions the visitor shold call,
* e.g., ".class", ".csv", etc. If this parameter is
* null, or of length 0, or contains a
* String of length 0, then the visitor is invoked for
* all files found in the supplied path.
* @see #go
* @see #FileSystemVisitor(Collection,
* il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action,
* String[])
*/
public FileSystemVisitor(final String from, final Searcher visitor, final String... extensions) {
this(new String[] { from }, visitor, extensions);
}
private static File[] asFiles(final String[] ss) {
final File[] $ = new File[ss.length];
for (int i = 0; i < ss.length; i++)
$[i] = new File(ss[i]);
return $;
}
/**
* Create a new visitor object to scan a single directory.
*
* from a non-null specifying where the traversal
* should begin.
* visitor a non-null specifying what to do in
* each visited file
* extensions an array of non-null String
* s specifying which file extensions the visitor shold call,
* e.g., ".class", ".csv", etc. If this parameter is
* null, or of length 0, or contains a
* String of length 0, then the visitor is invoked for
* all files found in the supplied path.
* @see #go
* @see #FileSystemVisitor(Collection,
* il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action,
* String[])
*/
public FileSystemVisitor(final String from, final Action visitor, final String[] extensions) {
this(new String[] { from }, visitor, extensions);
}
/**
* Create a new visitor object to scan an array of Strings naming
* the search locations.
*
* from a non-null specifying where the traversal
* should begin. If this collection is empty, then no traversal
* shall be carried out. Also, if the supplied directories are
* not disjoint, then the same file may be visited more than
* once.
* visitor a non-null specifying what to do in
* each visited file
* extensions an array of non-null String
* s specifying which file extensions the visitor shold call,
* e.g., ".class", ".csv", etc. If this parameter is
* null, or of length 0, or contains a
* String of length 0, then the visitor is invoked for
* all files found in the supplied path.
* @see #go
* @see #FileSystemVisitor(String[],
* il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action,
* String[])
*/
public FileSystemVisitor(final Collection<String> from, final Action visitor, final String... extensions) {
this(from.toArray(new String[from.size()]), visitor, extensions);
}
/**
* Conduct the traversal. For each file encountered during the traversal,
* the FileSystemVisitor invokes one of
*
* 1.Action#visitFile(File), 2.
* Action#visitDirectory(File), 3.{@ink #visitZipEntry(String,
* String, InputStreamReader)}, or 4.Action#visitZip(File)
*
* functions, depending on the file type. If this function throws
* Action.StopTraversal exception, then the traversal stops:
* completely if the current file was a plain file, i.e.,
* Action#visitFile(File) or {@ink #visitZipEntry(String, String,
* InputStreamReader)} was called, or just of the contained files, if this
* was an archive or a directory file.
*
* IOException if the file system could not traversed for some
* reason
* StopTraversal if the visitor object requested to stop the
* visitation.
*/
public void go() throws IOException, StopTraversal {
for (final File f : from)
recurse(f);
}
/**
* Conduct recursive traversal starting at a given file
*
* f a file, which may be a directory, a ZIP, or a plain file, at
* which the traversal begins
* IOException if the file system could not traversed for some
* reason
* StopTraversal if the visitor object requested to stop the
* visitation.
*/
private void recurse(final File f) throws IOException, StopTraversal {
if (f.isDirectory()) {
recurseDirectory(f);
return;
}
if (Zip.isZipFile(f)) {
scanZip(f);
return;
}
if (Suffixed.by(f, extensions))
visitor.visitFile(f);
}
/**
* conduct recursive traversal of a directory
*
* d a directory
* IOException if the file system could not be traversed for some
* reason
*/
private void recurseDirectory(final File d) throws IOException {
try {
visitor.visitDirectory(d);
if (d.list() == null) // Weird directories such as
// "System Volume Information"
return;
for (final String name : d.list())
if (name != null)
recurse(new File(d, name));
} catch (final Action.StopTraversal _) {
// do not visit children of this directory
}
}
/**
* Scan entries of a ZIP file.
*
* f a ZIP or other archive file
* IOException if the file system could not traversed for some
* reason
* StopTraversal if the visitor object requested to stop the
* visitation. However, if the visitor requested to stop the
* visitation of the ZIP file itself, the scanning of this ZIP
* file will stop, but the no exception is thrown, and the
* entire traversal continue.
*/
private void scanZip(final File f) throws StopTraversal {
try {
visitor.visitZip(f);
} catch (final Action.StopTraversal e) {
return; // do not visit any elements of this ZIP file, but continue
// traversal.
}
ZipFile Z;
try {
Z = new ZipFile(f.getAbsoluteFile());
} catch (final Exception z) {
System.err.println(f.getAbsolutePath() + ": " + z.getMessage());
return;
}
for (final Enumeration<? extends ZipEntry> es = Z.entries(); es.hasMoreElements();) {
final ZipEntry e = es.nextElement();
try {
final InputStream is = Z.getInputStream(e);
if (e.isDirectory()) {
visitor.visitZipDirectory(Z.getName(), e.getName(), is);
continue;
}
if (Suffixed.by(e.getName(), extensions))
visitor.visitZipEntry(Z.getName(), e.getName(), is);
} catch (final StopTraversal x) {
System.out.println("Found at ZIP!!!");
throw x;
} catch (final IOException exception) {
System.err.println("Error reading " + Z + ": " + exception.getMessage());
continue;
}
}
}
/**
* at which directories in the file system should the traversal start?
*/
private final File[] from;
/**
* what should be done for each file traversed?
*/
private final Action visitor;
/**
* for which extensions should the Action object be invoked.
*/
private final String[] extensions;
/**
* Author: Yossi Gil @since 21/05/2007
*/
public static interface Action {
/**
* action to conduct for each ordinary, i.e., non-ZIP and non-directory,
* file.
*
* f the file to visit
* StopTraversal in case the visitor wishes to completely
* stop the traversal
* @see #visitDirectory(File)
* @see #visitZip(File)
*/
void visitFile(File f) throws StopTraversal;
/**
* action to conduct for each entry found in a ZIP file, encountered
* throughout the traversal
*
* zipName the name of the ZIP file from which this entry was
* taken
* entryName the name of the visited entry in the ZIP file
* stream an open stream into the content of this entry
* StopTraversal in case the visitor wishes to terminate the
* entire traversal process
*/
void visitZipEntry(String zipName, String entryName, InputStream stream) throws StopTraversal;
/**
* action to conduct for each directory encountered throught the
* traversal.
*
* f the directory file object
* StopTraversal in case the visitor wishes to stop the
* traversal of this directory.
* @see #visitFile(File)
* @see #visitZip(File)
* @see #visitZipEntry(String, String, InputStream)
*/
void visitDirectory(File f) throws StopTraversal;
/**
* action to conduct for each ZIP and other archive files encountered
* throughout the traversal.
*
* f the archive file object
* StopTraversal in case the visitor wishes to stop the
* traversal of this archive file.
* @see #visitFile(File)
* @see #visitDirectory(File)
*/
void visitZip(File f) throws StopTraversal;
/**
* action to conduct for each directory encountered in an archival file
* scanned through the traversal.
*
* zipName the name of the ZIP file from which this entry was
* taken
* entryName the name of the visited entry in the ZIP file
* stream an open stream into the content of this entry
* StopTraversal in case the visitor wishes to terminate the
* entire traversal process
* @see #visitFile(File)
* @see #visitDirectory(File)
*/
void visitZipDirectory(String zipName, String entryName, InputStream stream) throws StopTraversal;
/**
* Author: Yossi Gil @since 21/05/2007
*/
class StopTraversal extends Exception {
/**
* Create a new StopTraversal object
*/
public StopTraversal() {
super();
}
/**
* Create a new StopTraversal object with a specific message
*
* message a message to record
* See: Exception
*/
public StopTraversal(final String message) {
super(message);
}
private static final long serialVersionUID = -4658857180021394864L;
}
}
static interface NonStopAction extends Action {
void visitFile(File f);
void visitZipEntry(String zipName, String entryName, InputStream stream);
void visitDirectory(File f);
void visitZip(File f);
void visitZipDirectory(String zipName, String entryName, InputStream stream);
}
/**
* A simplified Action with no exceptions thrown whose
* implementation does absolutely nothing. It leaves it to the extending
* class to re-implement concrete actions.
*
* Author: Yossi Gil @since 18/06/2007
*/
public abstract static class EmptyAction implements NonStopAction {
/**
* A do-nothing function, ignoring its arguments
*
* _ ignored
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action#visitDirectory(java.io.File)
*/
public void visitDirectory(final File _) {
unused(_);
}
/**
* A do-nothing function, ignoring its arguments
*
* _ ignored
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action#visitZip(java.io.File)
*/
public void visitZip(final File _) {
unused(_);
}
/**
* A do-nothing function, ignoring its arguments
*
* _ ignored
* __ ignored
* ___ ignored
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action#visitZipDirectory(java.lang.String,
* java.lang.String, java.io.InputStream)
*/
public void visitZipDirectory(final String _, final String __, final InputStream ___) {
unused(_, __, ___);
}
/**
* A do-nothing function, ignoring its arguments
*
* _ ignored
* __ ignored
* ___ ignored
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action#visitZipEntry(java.lang.String,
* java.lang.String, java.io.InputStream)
*/
public void visitZipEntry(final String _, final String __, final InputStream ___) {
unused(_, __, ___);
}
/**
* A do-nothing function, ignoring its arguments
*
* _ ignored
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.Action#visitFile(java.io.File)
*/
public void visitFile(final File _) {
unused(_);
}
}
/**
* An abstract class, to be extended by those clients
* interested in examining files only during a file system traversal as
* carried out by class FileSystemVisitor. Such clients must give
* body to two functions only:
*
* 1. #visitFile(File) - action to carry out on ordinary files,
* 2. {@link #visitZipEntry(String, InputStream)} - action for files found
* in an archive.
*
* Class FileOnlyAction is in fact a Facade offering a simplified
* interface to the more general Action. Simplifications are:
*
* 1.no exceptions thrown 2.partial implementation that does nothing for
* directories and archives, and leaves it to the extending class to
* implement a concrete action for files and archive entries visitation.
* 3.In visiting archive entries it invokes function
* #visitZip(File) (instead of
* {@link #visitZipDirectory(String, String, InputStream)}), i.e., the
* implementor of this function does is not bothered with the archive name.
*
*
* Author: Yossi Gil @since 18/06/2007
*/
public abstract static class FileOnlyAction extends EmptyAction {
/**
* Not to be used by clients.
*
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.EmptyAction#visitZipEntry(java.lang.String,
* java.lang.String, java.io.InputStream)
*/
@Override public final void visitZipEntry(@SuppressWarnings("unused") final String zipName, final String entryName,
final InputStream stream) {
visitZipEntry(entryName, stream);
}
@Override public abstract void visitFile(File f);
public abstract void visitZipEntry(String entryName, InputStream stream);
}
/**
* An abstract class, to be extended by those clients
* interested in examining directories only during a file system traversal
* as carried out by class FileSystemVisitor. Such clients must give
* body to two functions only:
*
</font>
*
#visitDirectory(File)</dt>
Action for ordinary
* directories</dd>
{@link #visitZipDirectory(String, InputStream)}</dt>
*
Action for directories found in an archive.</dd>
* </dl>
*
* Class DirectoryOnlyAction is in fact a Facade offering a
* simplified interface to the more general Action. Simplifcation
* are:
*
* 1.no exceptions thrown
* 2.partial implementation that does nothing for files and archives, and
* leaves it to the extending class to implement concrete a concrete action
* for directories and archived directories encountered in the course of the
* visitation.
* 3.in visiting directories found in archive entries it uses the
* {@link #visitZipDirectory(String, InputStream)} (instead of the more
* general {@link #visitZipDirectory(String, String, InputStream)}), that
* is, the implementor is not supplied with the directory name.
*
*
* Author: Yossi Gil @since 18/06/2007
*/
protected abstract static class DirectoryOnlyAction extends EmptyAction {
/**
* Not to be called by clients
*
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.EmptyAction#visitZipDirectory(java.lang.String,
* java.lang.String, java.io.InputStream)
*/
@Override public final void visitZipDirectory(final String zipName, final String entryName, final InputStream stream) {
unused(zipName);
visitZipDirectory(entryName, stream);
}
/**
* Visit a directory entry contained in an archive.
*
* entryName the name of the discovered directory
* stream to be used for opening it if necessary
*/
protected abstract void visitZipDirectory(String entryName, InputStream stream);
/**
* A function to be realized by an extending class, with actions to be
* carried out for each encountered directory.
*
* d the directory currently being visited.
* See: il.ac.technion.cs.ssdl.files.visitors.FileSystemVisitor.EmptyAction#visitDirectory(java.io.File)
*/
@Override public abstract void visitDirectory(File d);
}
}
Metric | Value | Acronym | Explanation |
---|---|---|---|
LOC | 596 | Lines Of Code | Total number of lines in the code |
SCC | 87 | SemiColons Count | Total number of semicolon tokens found in the code. |
NOT | 1346 | Number Of Tokens | Comments, whitespace and text which cannot be made into a token not included. |
VCC | 17126 | Visible Characters Count | The total number of non-white (i.e., not space, tab, newline, carriage return, form feed) characters. |
CCC | 4890 | Code Characters Count | Total number of non-white characters in tokens. White space characters in string and character literals are not counted. |
UIC | 93 | Unique Identifiers Count | The number of different identifiers found in the code |
WHC | 5 | Weighted Horizontal Complexity | A heuritistic on horizontal complexity |
Statistic | Value |
---|---|
Average token length | 3.6 |
Tokens/line | 2.3 |
Visible characters/line | 29 |
Code characters/line | 8.2 |
Semicolons/tokens | 6% |
Comment text percentage | 71% |
Token Kind | Occurrences |
---|---|
KEYWORD | 218 |
OPERATOR | 26 |
LITERAL | 7 |
ID | 476 |
PUNCTUATION | 619 |
COMMENT | 41 |
OTHER | 654 |