# HG changeset patch # User Alexander Stipsits # Date 1340399614 -7200 # Node ID 6a812002a91876c10994a9eea4b3a9d3eb9de0d5 # Parent 2558ff0945f8ac0eab627cfc4bc4e5e8e6b80b42 Initial commit: LogViewer backend diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/build.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/build.xml Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,8 @@ + + + + + + Builds, tests, and runs the project at.ssw.visualizer.logviewer. + + diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/manifest.mf --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/manifest.mf Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,6 @@ +Manifest-Version: 1.0 +OpenIDE-Module: at.ssw.visualizer.logviewer +OpenIDE-Module-Layer: at/ssw/visualizer/logviewer/layer.xml +OpenIDE-Module-Localizing-Bundle: at/ssw/visualizer/logviewer/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/nbproject/build-impl.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/build-impl.xml Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,45 @@ + + + + + + + + + + + + + You must set 'suite.dir' to point to your containing module suite + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/nbproject/genfiles.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/genfiles.properties Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,8 @@ +build.xml.data.CRC32=979ec129 +build.xml.script.CRC32=1c914106 +build.xml.stylesheet.CRC32=a56c6a5b@2.47.2 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=979ec129 +nbproject/build-impl.xml.script.CRC32=712ab216 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.47.2 diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/nbproject/project.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/project.properties Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,2 @@ +javac.source=1.7 +javac.compilerargs=-Xlint -Xlint:-serial diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/nbproject/project.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/nbproject/project.xml Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,146 @@ + + + org.netbeans.modules.apisupport.project + + + at.ssw.visualizer.logviewer + + + + com.oracle.graal.visualizer.editor + + + + 1.0 + + + + com.oracle.graal.visualizer.sharedactions + + + + 1.0 + + + + com.sun.hotspot.igv.data + + + + 1.0 + + + + org.eclipse.draw2d + + + + 1.0 + + + + org.jdesktop.layout + + + + 1 + 1.19.1 + + + + org.netbeans.api.visual + + + + 2.30.1 + + + + org.netbeans.modules.options.api + + + + 1 + 1.24.1 + + + + org.netbeans.modules.projectapi + + + + 1 + 1.40.1 + + + + org.openide.actions + + + + 6.24.1 + + + + org.openide.awt + + + + 7.39.1 + + + + org.openide.dialogs + + + + 7.23.1 + + + + org.openide.loaders + + + + 7.32.1 + + + + org.openide.nodes + + + + 7.25.1 + + + + org.openide.util + + + + 8.19.1 + + + + org.openide.util.lookup + + + + 8.11.1 + + + + org.openide.windows + + + + 6.48.2 + + + + + at.ssw.visualizer.logviewer + + + + diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/LogLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/LogLine.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,71 @@ +package at.ssw.visualizer.logviewer.model; + +/** + * + * @author Alexander Stipsits + */ +public class LogLine { + + private final int lineNum; + private final CharSequence text; + private final Method method; + private final Scope scope; + private final Node node; + + LogLine(int lineNum, CharSequence text, Method method, Scope scope, Node node) { + this.lineNum = lineNum; + this.text = text; + this.method = method; + this.scope = scope; + this.node = node; + } + + /** + * Returns the number of the line in the log file + * @return file line number + */ + public int getLineNumber() { + return lineNum; + } + + /** + * Returns the text of the log line + * @return log line text + */ + public String getText() { + return text.toString(); + } + + /** + * Returns the parent method + * @return the parent method + */ + public Method getMethod() { + return method; + } + + /** + * Returns the parent scope + * @return the parent scope + */ + public Scope getScope() { + return scope; + } + + /** + * Returns the parent node + * @return the parent node (or null if the log is not in a node's context) + */ + public Node getNode() { + return node; + } + + /** + * The string representation of a log line is the text of it. + */ + @Override + public String toString() { + return getText(); + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/LogModel.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/LogModel.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,107 @@ +package at.ssw.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.NoSuchElementException; + +/** + * + * @author Alexander Stipsits + */ +public class LogModel { + + private List methods = new ArrayList<>(); + private List logs = new ArrayList<>(); + + void add(Method method) { + methods.add(method); + } + + /** + * Returns a list of all methods within the log model. + * @return list of methods + */ + public List getMethods() { + return Collections.unmodifiableList(methods); + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs + * @return list of log lines + */ + public List getLogs() { + return Collections.unmodifiableList(logs); + } + + /** + * Returns a list of logs which are before and after a specific log line (and the line itself). + * @param log reference log line + * @param pre number of lines before the reference line + * @param post number of lines after the reference line + * @return list of log lines (size: pre + post + 1) + */ + public List range(LogLine log, int pre, int post) { + if(log == null) throw new NoSuchElementException(); + + List logs = getLogs(); + int index = logs.indexOf(log); + + if(index == -1) throw new NoSuchElementException(); + + int fromIndex = index - pre; + int toIndex = index + post + 1; + + return getLogs().subList(fromIndex > 0 ? fromIndex : 0, toIndex < logs.size() ? toIndex : logs.size()); + } + + /** + * Returns a string with log l which are before and after a specific log line (and the line itself). + * @param log reference log line + * @param pre number of lines before the reference line + * @param post number of lines after the reference line + * @return list of log lines (size: pre + post + 1) + */ + public String rangeAsString(LogLine log, int pre, int post) { + List list = range(log, pre, post); + + String ls = System.getProperty("line.separator"); + + boolean first = true; + StringBuilder buf = new StringBuilder(); + for(LogLine line : list) { + if(!first) buf.append(ls); + else first = false; + + buf.append(line); + } + + return buf.toString(); + } + + public LogLine getLogLine(int lineNum) { + int index = lineNum; + if(index >= logs.size()) index = logs.size()-1; + + LogLine logLine = logs.get(lineNum); + while(logLine.getLineNumber() > lineNum) { + logLine = logs.get(--index); + } + while(logLine.getLineNumber() < lineNum) { + logLine = logs.get(++index); + } + + return logLine; + } + + public List range(int lineNum, int pre, int post) { + LogLine logLine = getLogLine(lineNum); + return range(logLine, pre, post); + } + + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/LogParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/LogParser.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,210 @@ +package at.ssw.visualizer.logviewer.model; + +import at.ssw.visualizer.logviewer.model.io.FileLine; +import at.ssw.visualizer.logviewer.model.io.ProgressMonitor; +import at.ssw.visualizer.logviewer.model.io.SeekableFile; +import at.ssw.visualizer.logviewer.model.io.SeekableFileReader; +import java.io.BufferedReader; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Alexander Stipsits + */ +public class LogParser { + + private static final Pattern METHOD_PATTERN = + Pattern.compile("Finished target method HotSpotMethod<(.+?)>, isStub (true|false)"); + private static final Pattern SCOPE_PATTERN = + Pattern.compile("scope: (.+?)"); + private static final Pattern NODE_PATTERN = + Pattern.compile(".*?([0-9]+)\\|([0-9a-zA-Z.]+).*?"); + + private final List errorListeners = new ArrayList<>(); + private final List errors = new ArrayList<>(); + + /** + * Parses a log file without any feedback. When the parsing process is finished, the method returns a LogModel-object. + * @param file log file + * @return model-object + * @throws IOException + * @throws LogParserException + */ + public LogModel parse(File file) throws IOException { + return parse(file, null); + } + + /** + * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object. + * @param file log file + * @param monitor monitor for progress monitoring (uses default gap) + * @return model-object + * @throws IOException + * @throws LogParserException + */ + public LogModel parse(File file, ProgressMonitor monitor) throws IOException { + return parse(file, monitor, SeekableFileReader.DEFAULT_GAP); + } + + /** + * Parses a log file and uses a ProgressMonitor to give the caller a progress feedback. It returns a LogModel-object. + * @param file log file + * @param monitor monitor for progress monitoring (uses custom gap) + * @param gap custom gap (every x bytes read from the file, the monitor will be informed) + * @return model-object + * @throws IOException + * @throws LogParserException + */ + public LogModel parse(File file, ProgressMonitor monitor, int gap) throws IOException { + errors.clear(); + SeekableFileReader reader = new SeekableFileReader(file, monitor, gap); + SeekableFile seekableFile = reader.getSeekableFile(); + BufferedReader r = new BufferedReader(reader); + + LogModel model = new LogModel(); + Method currentMethod = new Method(model); + Scope currentScope = null; + + Matcher matcher; + boolean methodNameSet = false; + + int lineNum = -1; + String line; + while((line = r.readLine()) != null) { + lineNum++; + + methodNameSet = false; + + matcher = SCOPE_PATTERN.matcher(line); + if(matcher.matches()) { + String name = matcher.group(1); + currentScope = new Scope(name, currentMethod); + currentMethod.add(currentScope); + } + + matcher = METHOD_PATTERN.matcher(line); + boolean methodPatternMatches = matcher.matches(); + + if(methodPatternMatches){ + currentScope = null; + String name = matcher.group(1); + boolean isStub = Boolean.parseBoolean(matcher.group(2)); + currentMethod.init(name, isStub); + model.add(currentMethod); + methodNameSet = true; + } + + Node currentNode = null; + matcher = NODE_PATTERN.matcher(line); + if(matcher.matches()) { + if(currentScope == null){ + raiseError(lineNum, line, "scope is missing"); + continue; + } + int number = Integer.parseInt(matcher.group(1)); + currentNode = currentScope.getNode(number); + if(currentNode == null) { + String name = matcher.group(2); + currentNode = new Node(number, name, currentScope); + currentScope.add(currentNode); + } + } + + FileLine fileLine = seekableFile.get(lineNum); + LogLine log = new LogLine(lineNum, fileLine, currentMethod, currentScope, currentNode); + if(currentNode != null) currentNode.add(log); + if(currentScope != null) currentScope.add(log); + currentMethod.add(log); + model.add(log); + + if(methodPatternMatches) { + currentMethod = new Method(model); + } + } + + if(!methodNameSet) raiseError(lineNum, line, "unexpected end of stream"); + + return model; + } + + private void raiseError(int lineNum, String line, String message) { + ParseError error = new ParseError(lineNum, line, message); + errors.add(error); + for(ParseErrorListener listener : errorListeners) { + listener.errorOccurred(error); + } + } + + /** + * Adds a ParseErrorListener to the listeners + * @param listener + */ + public void addParseErrorListener(ParseErrorListener listener) { + errorListeners.add(listener); + } + + public void removeParseErrorListener(ParseErrorListener listener) { + errorListeners.remove(listener); + } + + /** + * Checks if errors occurred during the parsing process + * @return true if there are errors stored, false otherwise + */ + public boolean hasErrors() { + return !errors.isEmpty(); + } + + /** + * Returns a list of all errors. + * @return error list + */ + public List getErrors() { + return Collections.unmodifiableList(errors); + } + + public static class ParseError { + + private final int lineNum; + private final String line; + private final String message; + + private ParseError(int lineNum, String line, String message) { + this.lineNum = lineNum; + this.message = message; + this.line = line; + } + + public int getLineNumber() { + return lineNum; + } + + public String getLine() { + return line; + } + + public String getMessage() { + return message; + } + + } + + public static interface ParseErrorListener { + + /** + * Called when a new error occurs.

+ * Attention: This method runs on the same thread as the parsing process. + * If time-consuming tasks should be executed, please consider multithreading. + * @param error + */ + public void errorOccurred(ParseError error); + + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/Method.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/Method.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,86 @@ +package at.ssw.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Alexander Stipsits + */ +public class Method { + + private String name; + private boolean isStub; + private final LogModel model; + private List scopes = new ArrayList<>(); + private List logs = new ArrayList<>(); + + Method(LogModel model) { + name = null; + isStub = false; + this.model = model; + } + + void init(String name, boolean isStub) { + this.name = name; + this.isStub = isStub; + } + + /** + * Returns the name of the method + * @return the method name + */ + public String getName() { + return name; + } + + /** + * Returns true if this is a stub method. + * @return true if is stub, false otherwise + */ + public boolean isStub() { + return isStub; + } + + /** + * Returns the model which holds this method. + * @return model-object + */ + public LogModel getModel() { + return model; + } + + void add(Scope scope) { + scopes.add(scope); + } + + /** + * Returns a list of all scopes inside a target method. + * @return list of scopes + */ + public List getScopes() { + return scopes; + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs in the context of the method. + * @return list of log lines + */ + public List getLogs() { + return Collections.unmodifiableList(logs); + } + + /** + * The string representation of a method is its name. + */ + @Override + public String toString() { + return getName(); + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/Node.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/Node.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,68 @@ +package at.ssw.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Alexander Stipsits + */ +public class Node { + + private final int number; + private final String name; + private final Scope scope; + private List logs = new ArrayList<>(); + + + Node(int number, String name, Scope scope) { + this.number = number; + this.name = name; + this.scope = scope; + } + + /** + * Returns the node number. + * @return the node number + */ + public int getNumber() { + return number; + } + + /** + * Returns the node name. + * @return the node name + */ + public String getName() { + return name; + } + + /** + * Returns the parent scope. + * @return the parent scope + */ + public Scope getScope() { + return scope; + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs within a nodes context. + * @return list of log lines + */ + public List getLogs() { + return Collections.unmodifiableList(logs); + } + + /** + * The string represenation of a node is "<name> (<number>)". + */ + @Override + public String toString() { + return getName() + "(" + getNumber() + ")"; + } +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/Scope.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/Scope.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,84 @@ +package at.ssw.visualizer.logviewer.model; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * + * @author Alexander Stipsits + */ +public class Scope { + + private final String name; + private final Method method; + private List nodes = new ArrayList<>(); + private List logs = new ArrayList<>(); + + Scope(String name, Method method) { + this.name = name; + this.method = method; + } + + /** + * Returns the scope name. + * @return the scope name + */ + public String getName() { + return name; + } + + /** + * Returns the parent method. + * @return the parent method + */ + public Method getMethod() { + return method; + } + + void add(Node node) { + nodes.add(node); + } + + /** + * Returns a list of all node-objects inside a scope. + * @return list of nodes + */ + public List getNodes() { + return Collections.unmodifiableList(nodes); + } + + void add(LogLine log) { + logs.add(log); + } + + /** + * Returns a list of all logs inside a scope. + * @return list of log lines + */ + public List getLogs() { + return logs; + } + + /** + * Returns the node inside a scope with the given number. + * @param number node number + * @return node-object + */ + public Node getNode(int number) { + for(Node node : nodes) { + if(node.getNumber() == number) return node; + } + return null; + } + + /** + * The string representation of a scope is its name. + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + return getName(); + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/Filter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/Filter.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,40 @@ +package at.ssw.visualizer.logviewer.model.filter; + +import at.ssw.visualizer.logviewer.model.LogLine; + +/** + * + * @author Alexander Stipsits + */ +public interface Filter { + + /** + * Sets the constraints for a filter.
+ * They can be every type of objects. In general these are strings, but it can also be + * a Integer (like in the NodeFilter):
+ * Filter nodeFilter = filterManager.getNodeFilter(); + * filter.setConstraints((String)nodeName, (Integer)nodeNumber); + * @param constraints filter constraints + */ + void setConstraints(Object ... constraints); + + /** + * Indicates whether to keep a log line in the filter results, or not. + * @param line log line which should be checked + * @return true if the line should be kept, false otherwise + */ + boolean keep(LogLine line); + + /** + * Activates or deactivates a filter. Deactivated filters will be ignored. + * @param active true to activate, false to deactivate + */ + void setActive(boolean active); + + /** + * Returns the activation status + * @return true for an active filter, false otherwise + */ + boolean isActive(); + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/FilterManager.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/FilterManager.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,92 @@ +package at.ssw.visualizer.logviewer.model.filter; + +import at.ssw.visualizer.logviewer.model.LogLine; +import at.ssw.visualizer.logviewer.model.LogModel; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Alexander Stipsits + */ +public class FilterManager { + + private final List filters = new ArrayList<>(); + private final Filter methodFilter, scopeFilter, nodeFilter, fulltextFilter; + + /** + * Creates a new instance of the filter manager. + */ + public FilterManager() { + add(methodFilter = new MethodFilter()); + add(scopeFilter = new ScopeFilter()); + add(nodeFilter = new NodeFilter()); + add(fulltextFilter = new FullTextFilter()); + } + + /** + * Executes a filtering process with the given log model as subject. Inactive filters will be ignored. + * @param model subject + * @return filtered list of log lines + * @throws InterruptedException + */ + public List execute(LogModel model) throws InterruptedException { + List input = model.getLogs(); + List output = new ArrayList<>(); + + for(LogLine line : input) { + if(Thread.interrupted()) throw new InterruptedException(); + if(keep(line)) output.add(line); + } + + if(Thread.interrupted()) throw new InterruptedException(); + + return output; + } + + private boolean keep(LogLine line) { + boolean keep = true; + for(Filter filter : filters) { + keep = keep && (!filter.isActive() || filter.keep(line)); + } + return keep; + } + + private Filter add(Filter filter) { + filters.add(filter); + return filter; + } + + /** + * Returns the instance of a method filter + * @return method filter + */ + public Filter getMethodFilter() { + return methodFilter; + } + + /** + * Returns the instance of a scope filter + * @return scope filter + */ + public Filter getScopeFilter() { + return scopeFilter; + } + + /** + * Returns the instance of a node filter + * @return node filter + */ + public Filter getNodeFilter() { + return nodeFilter; + } + + /** + * Returns the instance of a full text filter + * @return full text filter + */ + public Filter getFullTextFilter() { + return fulltextFilter; + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/FullTextFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/FullTextFilter.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,53 @@ +package at.ssw.visualizer.logviewer.model.filter; + +import at.ssw.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Alexander Stipsits + */ +class FullTextFilter implements Filter { + + private Pattern p; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + } + + @Override + public boolean keep(LogLine line) { + if(p == null) return true; + + Matcher matcher = p.matcher(line.getText()); + return matcher.find(); + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/MethodFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/MethodFilter.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,53 @@ +package at.ssw.visualizer.logviewer.model.filter; + +import at.ssw.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Alexander Stipsits + */ +class MethodFilter implements Filter { + + private Pattern p; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + } + + @Override + public boolean keep(LogLine line) { + if(p == null) return true; + + Matcher matcher = p.matcher(line.getMethod().getName()); + return matcher.find(); + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/NodeFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/NodeFilter.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,71 @@ +package at.ssw.visualizer.logviewer.model.filter; + +import at.ssw.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Alexander Stipsits + */ +class NodeFilter implements Filter { + + private Pattern p; + private Integer nodeNum; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.nodeNum = null; + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + else if(constraint instanceof Integer) { + this.nodeNum = (Integer)constraint; + } + + } + + @Override + public boolean keep(LogLine line) { + if(p == null && nodeNum == null) return true; + + if(line.getNode() == null) return false; + + boolean keep = false; + + if(p != null) { + Matcher matcher = p.matcher(line.getNode().getName()); + keep = keep || matcher.find(); + } + if(nodeNum != null) { + keep = keep || nodeNum.equals(line.getNode().getNumber()); + } + + return keep; + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/ScopeFilter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/filter/ScopeFilter.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,55 @@ +package at.ssw.visualizer.logviewer.model.filter; + +import at.ssw.visualizer.logviewer.model.LogLine; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * + * @author Alexander Stipsits + */ +class ScopeFilter implements Filter { + + private Pattern p; + private boolean active = true; + + @Override + public void setConstraints(Object ... constraints) { + this.p = null; + for(Object constraint : constraints) { + setConstraint(constraint); + } + } + + private void setConstraint(Object constraint) { + if(constraint instanceof String) { + if(((String)constraint).trim().length() > 0) { + this.p = Pattern.compile((String)constraint); + } + else { + this.p = null; + } + } + } + + @Override + public boolean keep(LogLine line) { + if(p == null) return true; + + if(line.getScope() == null) return false; + + Matcher matcher = p.matcher(line.getScope().getName()); + return matcher.find(); + } + + @Override + public void setActive(boolean active) { + this.active = active; + } + + @Override + public boolean isActive() { + return active; + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/FileLine.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/FileLine.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,58 @@ +package at.ssw.visualizer.logviewer.model.io; + +import java.io.IOException; +import java.lang.ref.WeakReference; + +/** + * + * @author Alexander Stipsits + */ +public class FileLine implements CharSequence { + + private final SeekableFile seekableFile; + private WeakReference cache; + public final long off; + public final int len; + + public FileLine(SeekableFile seekableFile, long off, int len) { + this.seekableFile = seekableFile; + this.off = off; + this.len = len; + } + + @Override + public String toString() { + String line = null; + + if(cache != null) line = cache.get(); + + if(line == null) { + try { + line = seekableFile.read(this); + cache = new WeakReference<>(line); + } catch (IOException e) { + e.printStackTrace(); + } + } + + return line; + } + + @Override + public int length() { + return len; + } + + @Override + public char charAt(int index) { + String line = toString(); + return line != null ? line.charAt(index) : 0; + } + + @Override + public CharSequence subSequence(int start, int end) { + String line = toString(); + return line != null ? line.subSequence(start, end) : ""; + } + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/ProgressMonitor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/ProgressMonitor.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,24 @@ +package at.ssw.visualizer.logviewer.model.io; + +/** + * + * @author Alexander Stipsits + */ +public interface ProgressMonitor { + + /** + * Triggered when some work has been done.

+ * Attention: This method runs on the same thread as the reading process. + * If time-consuming tasks should be executed, please consider multithreading. + * @param percentage Value in range between 0 and 1 to indicate how much work has been done. + */ + public void worked(float percentage); + + /** + * Triggered when work is done completely.

+ * Attention: This method runs on the same thread as the reading process. + * If time-consuming tasks should be executed, please consider multithreading. + */ + public void finished(); + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/SeekableFile.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/SeekableFile.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,50 @@ +package at.ssw.visualizer.logviewer.model.io; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +/** + * + * @author Alexander Stipsits + */ +public class SeekableFile implements Closeable { + + private final RandomAccessFile raf; + private List lines = new ArrayList<>(); + + SeekableFile(File file) throws FileNotFoundException { + raf = new RandomAccessFile(file, "r"); + } + + void addLine(long off, int len) { + lines.add(new FileLine(this, off, len)); + } + + public int size() { + return lines.size(); + } + + public FileLine get(int lineNum) throws IOException { + FileLine line = lines.get(lineNum); + return line; + } + + String read(FileLine line) throws IOException { + if(line == null) throw new IllegalArgumentException("line is null"); + raf.seek(line.off); + + byte [] buf = new byte[line.len]; + + if(raf.read(buf) != line.len) throw new IOException("error while reading line"); + + return new String(buf); + } + + @Override + public void close() throws IOException { + raf.close(); + } + + +} diff -r 2558ff0945f8 -r 6a812002a918 visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/SeekableFileReader.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/visualizer/LogViewer/src/at/ssw/visualizer/logviewer/model/io/SeekableFileReader.java Fri Jun 22 23:13:34 2012 +0200 @@ -0,0 +1,101 @@ +package at.ssw.visualizer.logviewer.model.io; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +/** + * + * @author Alexander Stipsits + */ +public class SeekableFileReader extends Reader { + + public static final int DEFAULT_GAP = 1024; // in bytes + + private final FileReader reader; + private SeekableFile seekableFile; + private ProgressMonitor monitor; + private long filelen; + private int gap; + + public SeekableFileReader(File file) throws IOException { + super(file); + reader = new FileReader(file); + seekableFile = new SeekableFile(file); + } + + public SeekableFileReader(File file, ProgressMonitor monitor, int gap) throws IOException { + this(file); + this.monitor = monitor; + this.filelen = file.length(); + this.gap = gap; + } + + public SeekableFileReader(File file, ProgressMonitor monitor) throws IOException { + this(file, monitor, DEFAULT_GAP); + } + + public SeekableFile getSeekableFile() { + return seekableFile; + } + + @Override + public void close() throws IOException { + reader.close(); + } + + private long bytes = 0; + private boolean skipLF = false; + private long off; + private long lastGapped = 0; + private boolean finished = false; + + @Override + public int read(char[] cbuf, int offset, int length) throws IOException { + + int l = reader.read(cbuf, offset, length); + + if(l == -1 && !finished) { + seekableFile.addLine(off, (int)(bytes-off)); + finished = true; + if(monitor != null) { + monitor.worked(1); + monitor.finished(); + } + } + + for(int i = 0; i < l; ++i) { + Character ch = new Character(cbuf[i]); + int chlen = ch.toString().getBytes(reader.getEncoding()).length; + + if(skipLF && ch != '\n') { + seekableFile.addLine(off, (int)(bytes-off-chlen)); + off = bytes; + skipLF = false; + } + + bytes += chlen; + + if(monitor != null) { + if(bytes > lastGapped+gap) { + lastGapped = bytes; + monitor.worked(((float)bytes)/((float)filelen)); + } + } + + if(ch == '\r') { + skipLF = true; + } + if(ch == '\n') { + seekableFile.addLine(off, (int)(bytes-off-(skipLF ? 2*chlen : chlen))); + off = bytes; + skipLF = false; + } + } + + return l; + } + + +}