org.eclipse.linuxtools.tmf.core.trace.indexer,
org.eclipse.linuxtools.tmf.core.trace.indexer.checkpoint,
org.eclipse.linuxtools.tmf.core.trace.location,
+ org.eclipse.linuxtools.tmf.core.trace.text,
org.eclipse.linuxtools.tmf.core.uml2sd,
org.eclipse.linuxtools.tmf.core.util
package org.eclipse.linuxtools.tmf.core.project.model;
-import org.eclipse.core.runtime.Status;
import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
/**
}
private boolean standardValidate(String path) {
- final boolean valid = fTrace.validate(null, path).equals(Status.OK_STATUS);
+ final boolean valid = fTrace.validate(null, path).isOK();
return valid;
}
return fName;
}
-}
\ No newline at end of file
+}
/*******************************************************************************
- * Copyright (c) 2009, 2013 Ericsson, École Polytechnique de Montréal
+ * Copyright (c) 2009, 2014 Ericsson, École Polytechnique de Montréal
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
void initTrace(IResource resource, String path, Class<? extends ITmfEvent> type) throws TmfTraceException;
/**
- * Validate that the trace is of the correct type.
+ * Validate that the trace is of the correct type. The implementation should
+ * return a TraceValidationStatus to indicate success with a certain level
+ * of confidence.
*
* @param project
* the eclipse project
* @param path
* the trace path
+ *
* @return an IStatus object with validation result. Use severity OK to
* indicate success.
+ * @see {@link TraceValidationStatus}
* @since 2.0
*/
IStatus validate(IProject project, String path);
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2014 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.core.trace;
+
+import org.eclipse.core.runtime.Status;
+
+/**
+ * A class representing the validation status of a trace against a particular
+ * trace type.
+ *
+ * @since 3.0
+ */
+public class TraceValidationStatus extends Status {
+
+ private int fConfidence;
+
+ /**
+ * Construct a successful validation status with a confidence level
+ *
+ * @param confidence the confidence level, 0 is lowest
+ * @param pluginId the unique identifier of the relevant plug-in
+ */
+ public TraceValidationStatus(int confidence, String pluginId) {
+ super(OK, pluginId, OK_STATUS.getMessage());
+ if (confidence < 0) {
+ throw new IllegalArgumentException();
+ }
+ fConfidence = confidence;
+ }
+
+ /**
+ * Gets the confidence level
+ *
+ * @return the confidence level, 0 is lowest
+ */
+ public int getConfidence() {
+ return fConfidence;
+ }
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2012, 2014 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.core.trace.text;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.linuxtools.internal.tmf.core.Activator;
+import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
+import org.eclipse.linuxtools.tmf.core.event.TmfEvent;
+import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException;
+import org.eclipse.linuxtools.tmf.core.io.BufferedRandomAccessFile;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfContext;
+import org.eclipse.linuxtools.tmf.core.trace.ITmfEventParser;
+import org.eclipse.linuxtools.tmf.core.trace.TmfContext;
+import org.eclipse.linuxtools.tmf.core.trace.TmfTrace;
+import org.eclipse.linuxtools.tmf.core.trace.TraceValidationStatus;
+import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
+import org.eclipse.linuxtools.tmf.core.trace.location.TmfLongLocation;
+
+/**
+ * Extension of TmfTrace for handling of line-based text traces parsed using
+ * regular expressions. Each line that matches the first line pattern indicates
+ * the start of a new event. The subsequent lines can contain additional
+ * information that is added to the current event.
+ *
+ * @param <T>
+ * TmfEvent class returned by this trace
+ *
+ * @since 3.0
+ */
+public abstract class TextTrace<T extends TmfEvent> extends TmfTrace implements ITmfEventParser {
+
+ private static final TmfLongLocation NULL_LOCATION = new TmfLongLocation((Long) null);
+ private static final int MAX_LINES = 100;
+ private static final int MAX_CONFIDENCE = 100;
+
+ /** The default separator used for multi-line fields */
+ protected static final String SEPARATOR = " | "; //$NON-NLS-1$
+
+ /** The text file */
+ protected BufferedRandomAccessFile fFile;
+
+ /**
+ * Constructor
+ */
+ public TextTrace() {
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * The default implementation computes the confidence as the percentage of
+ * lines in the first 100 lines of the file which match the first line
+ * pattern.
+ */
+ @Override
+ public IStatus validate(IProject project, String path) {
+ File file = new File(path);
+ if (!file.exists()) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "File not found: " + path); //$NON-NLS-1$
+ }
+ if (!file.isFile()) {
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Not a file. It's a directory: " + path); //$NON-NLS-1$
+ }
+ int confidence = 0;
+ try (BufferedRandomAccessFile rafile = new BufferedRandomAccessFile(path, "r")) { //$NON-NLS-1$
+ int lineCount = 0;
+ int matches = 0;
+ String line = rafile.getNextLine();
+ while ((line != null) && (lineCount++ < MAX_LINES)) {
+ Matcher matcher = getFirstLinePattern().matcher(line);
+ if (matcher.find()) {
+ matches++;
+ }
+ confidence = MAX_CONFIDENCE * matches / lineCount;
+ line = rafile.getNextLine();
+ }
+ } catch (IOException e) {
+ Activator.logError("Error validating file: " + path, e); //$NON-NLS-1$
+ return new Status(IStatus.ERROR, Activator.PLUGIN_ID, "IOException validating file: " + path, e); //$NON-NLS-1$
+ }
+
+ return new TraceValidationStatus(confidence, Activator.PLUGIN_ID);
+
+ }
+
+ @Override
+ public void initTrace(IResource resource, String path, Class<? extends ITmfEvent> type) throws TmfTraceException {
+ super.initTrace(resource, path, type);
+ try {
+ fFile = new BufferedRandomAccessFile(getPath(), "r"); //$NON-NLS-1$
+ } catch (IOException e) {
+ throw new TmfTraceException(e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public synchronized void dispose() {
+ super.dispose();
+ if (fFile != null) {
+ try {
+ fFile.close();
+ } catch (IOException e) {
+ } finally {
+ fFile = null;
+ }
+ }
+ }
+
+ @Override
+ public synchronized TmfContext seekEvent(ITmfLocation location) {
+ TextTraceContext context = new TextTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
+ if (NULL_LOCATION.equals(location) || fFile == null) {
+ return context;
+ }
+ try {
+ if (location == null) {
+ fFile.seek(0);
+ } else if (location.getLocationInfo() instanceof Long) {
+ fFile.seek((Long) location.getLocationInfo());
+ }
+ long rawPos = fFile.getFilePointer();
+ String line = fFile.getNextLine();
+ while (line != null) {
+ Matcher matcher = getFirstLinePattern().matcher(line);
+ if (matcher.find()) {
+ context.setLocation(new TmfLongLocation(rawPos));
+ context.firstLineMatcher = matcher;
+ context.firstLine = line;
+ context.nextLineLocation = fFile.getFilePointer();
+ return context;
+ }
+ rawPos = fFile.getFilePointer();
+ line = fFile.getNextLine();
+ }
+ return context;
+ } catch (IOException e) {
+ Activator.logError("Error seeking file: " + getPath(), e); //$NON-NLS-1$
+ return context;
+ }
+ }
+
+ @Override
+ public synchronized TmfContext seekEvent(double ratio) {
+ if (fFile == null) {
+ return new TextTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
+ }
+ try {
+ long pos = (long) (ratio * fFile.length());
+ while (pos > 0) {
+ fFile.seek(pos - 1);
+ if (fFile.read() == '\n') {
+ break;
+ }
+ pos--;
+ }
+ ITmfLocation location = new TmfLongLocation(Long.valueOf(pos));
+ TmfContext context = seekEvent(location);
+ context.setRank(ITmfContext.UNKNOWN_RANK);
+ return context;
+ } catch (IOException e) {
+ Activator.logError("Error seeking file: " + getPath(), e); //$NON-NLS-1$
+ return new TextTraceContext(NULL_LOCATION, ITmfContext.UNKNOWN_RANK);
+ }
+ }
+
+ @Override
+ public double getLocationRatio(ITmfLocation location) {
+ if (fFile == null) {
+ return 0;
+ }
+ try {
+ long length = fFile.length();
+ if (length == 0) {
+ return 0;
+ }
+ if (location.getLocationInfo() instanceof Long) {
+ return (double) ((Long) location.getLocationInfo()) / length;
+ }
+ } catch (IOException e) {
+ Activator.logError("Error reading file: " + getPath(), e); //$NON-NLS-1$
+ }
+ return 0;
+ }
+
+ @Override
+ public ITmfLocation getCurrentLocation() {
+ return null;
+ }
+
+ @Override
+ public ITmfEvent parseEvent(ITmfContext tmfContext) {
+ ITmfContext context = seekEvent(tmfContext.getLocation());
+ return parse(context);
+ }
+
+ @Override
+ public synchronized T getNext(ITmfContext context) {
+ ITmfContext savedContext = new TmfContext(context.getLocation(), context.getRank());
+ T event = parse(context);
+ if (event != null) {
+ updateAttributes(savedContext, event.getTimestamp());
+ context.increaseRank();
+ }
+ return event;
+ }
+
+ /**
+ * Parse the next event. The context is advanced.
+ *
+ * @param tmfContext
+ * the context
+ * @return the next event or null
+ */
+ protected synchronized T parse(ITmfContext tmfContext) {
+ if (fFile == null) {
+ return null;
+ }
+ if (!(tmfContext instanceof TextTraceContext)) {
+ return null;
+ }
+ TextTraceContext context = (TextTraceContext) tmfContext;
+ if (context.getLocation() == null || !(context.getLocation().getLocationInfo() instanceof Long) || NULL_LOCATION.equals(context.getLocation())) {
+ return null;
+ }
+
+ T event = parseFirstLine(context.firstLineMatcher, context.firstLine);
+
+ try {
+ if (fFile.getFilePointer() != context.nextLineLocation) {
+ fFile.seek(context.nextLineLocation);
+ }
+ long rawPos = fFile.getFilePointer();
+ String line = fFile.getNextLine();
+ while (line != null) {
+ Matcher matcher = getFirstLinePattern().matcher(line);
+ if (matcher.find()) {
+ context.setLocation(new TmfLongLocation(rawPos));
+ context.firstLineMatcher = matcher;
+ context.firstLine = line;
+ context.nextLineLocation = fFile.getFilePointer();
+ return event;
+ }
+ parseNextLine(event, line);
+ rawPos = fFile.getFilePointer();
+ line = fFile.getNextLine();
+ }
+ } catch (IOException e) {
+ Activator.logError("Error reading file: " + getPath(), e); //$NON-NLS-1$
+ }
+
+ context.setLocation(NULL_LOCATION);
+ return event;
+ }
+
+ /**
+ * Gets the first line pattern.
+ *
+ * @return The first line pattern
+ */
+ protected abstract Pattern getFirstLinePattern();
+
+ /**
+ * Parses the first line data and returns a new event.
+ *
+ * @param matcher
+ * The matcher
+ * @param line
+ * The line to parse
+ * @return The parsed event
+ */
+ protected abstract T parseFirstLine(Matcher matcher, String line);
+
+ /**
+ * Parses the next line data for the current event.
+ *
+ * @param event
+ * The current event being parsed
+ * @param line
+ * The line to parse
+ */
+ protected abstract void parseNextLine(T event, String line);
+
+ // ------------------------------------------------------------------------
+ // Helper methods
+ // ------------------------------------------------------------------------
+
+ /**
+ * Strip quotes surrounding a string
+ *
+ * @param input
+ * The input string
+ * @return The string without quotes
+ */
+ protected static String replaceQuotes(String input) {
+ String out = input.replaceAll("^\"|(\"\\s*)$", ""); //$NON-NLS-1$//$NON-NLS-2$
+ return out;
+ }
+
+ /**
+ * Strip brackets surrounding a string
+ *
+ * @param input
+ * The input string
+ * @return The string without brackets
+ */
+ protected static String replaceBrackets(String input) {
+ String out = input.replaceAll("^\\{|(\\}\\s*)$", ""); //$NON-NLS-1$//$NON-NLS-2$
+ return out;
+ }
+
+}
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2012, 2014 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tasse - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.core.trace.text;
+
+import java.util.regex.Matcher;
+
+import org.eclipse.linuxtools.tmf.core.trace.TmfContext;
+import org.eclipse.linuxtools.tmf.core.trace.location.ITmfLocation;
+
+/**
+ * Implementation of a TmfContext for text traces.
+ *
+ * @since 3.0
+ */
+public class TextTraceContext extends TmfContext {
+
+ /** The Matcher object for the first line. */
+ public Matcher firstLineMatcher;
+ /** The first line string */
+ public String firstLine;
+ /** The location of the next line */
+ public long nextLineLocation;
+
+ /**
+ * Constructor
+ *
+ * @param location
+ * Trace location
+ * @param rank
+ * Event rank
+ */
+ public TextTraceContext(final ITmfLocation location, final long rank) {
+ super(location, rank);
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = super.hashCode();
+ result = prime * result + ((firstLine == null) ? 0 : firstLine.hashCode());
+ result = prime * result + ((firstLineMatcher == null) ? 0 : firstLineMatcher.hashCode());
+ result = prime * result + (int) (nextLineLocation ^ (nextLineLocation >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (!super.equals(obj)) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ TextTraceContext other = (TextTraceContext) obj;
+ if (firstLine == null) {
+ if (other.firstLine != null) {
+ return false;
+ }
+ } else if (!firstLine.equals(other.firstLine)) {
+ return false;
+ }
+ if (firstLineMatcher == null) {
+ if (other.firstLineMatcher != null) {
+ return false;
+ }
+ } else if (!firstLineMatcher.equals(other.firstLineMatcher)) {
+ return false;
+ }
+ if (nextLineLocation != other.nextLineLocation) {
+ return false;
+ }
+ return true;
+ }
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2012, 2014 Ericsson
+ *
+ * All rights reserved. This program and the accompanying materials are
+ * made available under the terms of the Eclipse Public License v1.0 which
+ * accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Patrick Tasse - Initial API and implementation
+ * Bernd Hufmann - Updated equals, clone and hashCode to consider StringBuffer values
+ *******************************************************************************/
+
+package org.eclipse.linuxtools.tmf.core.trace.text;
+
+import java.util.Arrays;
+
+import org.eclipse.linuxtools.tmf.core.event.ITmfEventField;
+
+/**
+ * Implementation of ITmfEventField for Text Traces.
+ *
+ * @since 3.0
+ */
+public class TextTraceEventContent implements ITmfEventField, Cloneable {
+
+ private String fName;
+ private Object fValue;
+ private TextTraceEventContent[] fFields;
+
+ // ------------------------------------------------------------------------
+ // Constructors
+ // ------------------------------------------------------------------------
+
+ /**
+ * Constructor for a root event content
+ *
+ * @param fieldNames
+ * the array of field names
+ */
+ public TextTraceEventContent(String[] fieldNames) {
+ this(ITmfEventField.ROOT_FIELD_ID);
+ fFields = new TextTraceEventContent[fieldNames.length];
+ for (int i = 0; i < fFields.length; i++) {
+ fFields[i] = new TextTraceEventContent(fieldNames[i]);
+ }
+ }
+
+ /**
+ * Constructor for a subfield
+ *
+ * @param fieldNames
+ * the array of field names
+ */
+ private TextTraceEventContent(String fieldName) {
+ fName = fieldName;
+ }
+
+ // ------------------------------------------------------------------------
+ // ITmfEventField
+ // ------------------------------------------------------------------------
+
+ @Override
+ public String getName() {
+ return fName;
+ }
+
+ @Override
+ public Object getValue() {
+ return fValue;
+ }
+
+ @Override
+ public String[] getFieldNames() {
+ String[] fieldNames = new String[fFields.length];
+ for (int i = 0; i < fieldNames.length; i++) {
+ fieldNames[i] = fFields[i].getName();
+ }
+ return fieldNames;
+ }
+
+ @Override
+ public String getFieldName(int index) {
+ if (index >= 0 && index < fFields.length) {
+ return fFields[index].getName();
+ }
+ return null;
+ }
+
+ @Override
+ public ITmfEventField[] getFields() {
+ return fFields;
+ }
+
+ @Override
+ public ITmfEventField getField(String name) {
+ for (int i = 0; i < fFields.length; i++) {
+ if (fFields[i].getName().equals(name)) {
+ return fFields[i];
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ITmfEventField getField(int index) {
+ if (index >= 0 && index < fFields.length) {
+ return fFields[index];
+ }
+ return null;
+ }
+
+ @Override
+ public String getFormattedValue() {
+ return fValue.toString();
+ }
+
+ @Override
+ public ITmfEventField getSubField(String[] names) {
+ ITmfEventField field = this;
+ for (String name : names) {
+ field = field.getField(name);
+ if (field == null) {
+ return null;
+ }
+ }
+ return field;
+ }
+
+ // ------------------------------------------------------------------------
+ // Convenience getters and setters
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get a subfield value by name
+ *
+ * @param name
+ * a subfield name
+ * @return field value object
+ */
+ public Object getFieldValue(String name) {
+ for (int i = 0; i < fFields.length; i++) {
+ if (fFields[i].getName().equals(name)) {
+ return fFields[i].getValue();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get a subfield value by index
+ *
+ * @param index
+ * a subfield index
+ * @return field value object
+ */
+ public Object getFieldValue(int index) {
+ if (index >= 0 && index < fFields.length) {
+ return fFields[index].getValue();
+ }
+ return null;
+ }
+
+ /**
+ * Set the content value
+ *
+ * @param value
+ * the content value
+ */
+ public void setValue(Object value) {
+ fValue = value;
+ }
+
+ /**
+ * Set a subfield value by name
+ *
+ * @param name
+ * a subfield name
+ * @param value
+ * the subfield value
+ */
+ public void setFieldValue(String name, Object value) {
+ for (int i = 0; i < fFields.length; i++) {
+ if (fFields[i].getName().equals(name)) {
+ fFields[i].fValue = value;
+ }
+ }
+ }
+
+ /**
+ * Set a subfield value by index
+ *
+ * @param index
+ * a subfield index
+ * @param value
+ * the subfield value
+ */
+ public void setFieldValue(int index, Object value) {
+ if (index >= 0 && index < fFields.length) {
+ fFields[index].fValue = value;
+ }
+ }
+
+ // ------------------------------------------------------------------------
+ // Cloneable
+ // ------------------------------------------------------------------------
+
+ @Override
+ public TextTraceEventContent clone() {
+ TextTraceEventContent clone = null;
+ try {
+ clone = (TextTraceEventContent) super.clone();
+ clone.fName = fName;
+ if (fValue instanceof StringBuffer) {
+ StringBuffer value = new StringBuffer(fValue.toString());
+ clone.fValue = value;
+ } else {
+ clone.fValue = fValue;
+ }
+ clone.fFields = (fFields != null) ? fFields.clone() : null;
+ if (fFields != null) {
+ for (int i = 0; i < fFields.length; i++) {
+ clone.fFields[i] = fFields[i].clone();
+ }
+ }
+ } catch (CloneNotSupportedException e) {
+ }
+ return clone;
+ }
+
+ // ------------------------------------------------------------------------
+ // Object
+ // ------------------------------------------------------------------------
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + Arrays.hashCode(fFields);
+ result = prime * result + ((fName == null) ? 0 : fName.hashCode());
+ int tmpHash = 0; // initialize for fValue equals null;
+ if (fValue != null) {
+ if (fValue instanceof StringBuffer) {
+ tmpHash = fValue.toString().hashCode();
+ } else {
+ tmpHash = fValue.hashCode();
+ }
+ }
+ result = prime * result + tmpHash;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ TextTraceEventContent other = (TextTraceEventContent) obj;
+ if (!Arrays.equals(fFields, other.fFields)) {
+ return false;
+ }
+ if (fName == null) {
+ if (other.fName != null) {
+ return false;
+ }
+ } else if (!fName.equals(other.fName)) {
+ return false;
+ }
+ if (fValue == null) {
+ if (other.fValue != null) {
+ return false;
+ }
+ } else {
+ if ((fValue instanceof StringBuffer) && (other.fValue instanceof StringBuffer)) {
+ if (!fValue.toString().equals(other.fValue.toString())) {
+ return false;
+ }
+ } else if (!fValue.equals(other.fValue)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ if (fName == ITmfEventField.ROOT_FIELD_ID) {
+ for (int i = 0; i < getFields().length; i++) {
+ ITmfEventField field = getFields()[i];
+ if (i != 0) {
+ sb.append(", "); //$NON-NLS-1$
+ }
+ sb.append(field.toString());
+ }
+ } else {
+ sb.append(fName);
+ sb.append('=');
+ sb.append(fValue);
+ }
+ return sb.toString();
+ }
+
+}