blob: e0e42424b73dc6ccda41affe3237a99bede5e48d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010, 2015 Ericsson
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License 2.0 which
* accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Yuriy Vashchuk (yvashchuk@gmail.com) - Initial API and implementation
* based on http://smeric.developpez.com/java/cours/xml/sax/
* Patrick Tasse - Refactoring
*******************************************************************************/
package org.eclipse.tracecompass.tmf.core.filter.xml;
import java.util.ArrayDeque;
import java.util.Deque;
import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfBaseAspects;
import org.eclipse.tracecompass.tmf.core.event.aspect.TmfEventFieldAspect;
import org.eclipse.tracecompass.tmf.core.filter.model.ITmfFilterTreeNode;
import org.eclipse.tracecompass.tmf.core.filter.model.ITmfFilterWithNot;
import org.eclipse.tracecompass.tmf.core.filter.model.ITmfFilterWithValue;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterAndNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterAspectNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterCompareNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterCompareNode.Type;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterContainsNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterEqualsNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterMatchesNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterOrNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterRootNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterTraceTypeNode;
import org.eclipse.tracecompass.tmf.core.filter.model.TmfFilterTreeNode;
import org.eclipse.tracecompass.tmf.core.project.model.TmfTraceType;
import org.eclipse.tracecompass.tmf.core.project.model.TraceTypeHelper;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* The SAX Content Handler
*
* @version 1.0
* @author Yuriy Vashchuk
* @author Patrick Tasse
*/
public class TmfFilterContentHandler extends DefaultHandler {
// Backward compatibility strings
private static final String EVENTTYPE_NODE_NAME = "EVENTTYPE"; //$NON-NLS-1$
private static final String NAME_ATTR = "name"; //$NON-NLS-1$
private static final String LTTNG_KERNEL_TRACE = "Common Trace Format : LTTng Kernel Trace"; //$NON-NLS-1$
private static final String LINUX_KERNEL_TRACE = "Common Trace Format : Linux Kernel Trace"; //$NON-NLS-1$
private static final String FIELD_ATTR = "field"; //$NON-NLS-1$
private static final String EVENT_FIELD_TIMESTAMP = ":timestamp:"; //$NON-NLS-1$
private static final String EVENT_FIELD_TYPE = ":type:"; //$NON-NLS-1$
private static final String EVENT_FIELD_CONTENT = ":content:"; //$NON-NLS-1$
private ITmfFilterTreeNode fRoot = null;
private final Deque<ITmfFilterTreeNode> fFilterTreeStack = new ArrayDeque<>();
/**
* The default constructor
*/
public TmfFilterContentHandler() {
super();
}
/**
* Getter of tree
*
* @return The builded tree
*/
public ITmfFilterTreeNode getTree() {
return fRoot;
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
ITmfFilterTreeNode node = null;
if (localName.equalsIgnoreCase(TmfFilterRootNode.NODE_NAME)) {
node = new TmfFilterRootNode();
} else if (localName.equals(TmfFilterNode.NODE_NAME)) {
node = new TmfFilterNode(atts.getValue(TmfFilterNode.NAME_ATTR));
} else if (localName.equals(TmfFilterTraceTypeNode.NODE_NAME)) {
node = new TmfFilterTraceTypeNode(null);
String traceTypeId = atts.getValue(TmfFilterTraceTypeNode.TYPE_ATTR);
traceTypeId = TmfTraceType.buildCompatibilityTraceTypeId(traceTypeId);
((TmfFilterTraceTypeNode) node).setTraceTypeId(traceTypeId);
TraceTypeHelper helper = TmfTraceType.getTraceType(traceTypeId);
if (helper != null) {
((TmfFilterTraceTypeNode) node).setTraceClass(helper.getTraceClass());
}
((TmfFilterTraceTypeNode) node).setName(atts.getValue(TmfFilterTraceTypeNode.NAME_ATTR));
} else if (localName.equals(TmfFilterAndNode.NODE_NAME)) {
node = new TmfFilterAndNode(null);
} else if (localName.equals(TmfFilterOrNode.NODE_NAME)) {
node = new TmfFilterOrNode(null);
} else if (localName.equals(TmfFilterContainsNode.NODE_NAME)) {
node = new TmfFilterContainsNode(null);
createEventAspect((TmfFilterAspectNode) node, atts);
String value = atts.getValue(TmfFilterContainsNode.IGNORECASE_ATTR);
if (value != null && value.equalsIgnoreCase(Boolean.TRUE.toString())) {
((TmfFilterContainsNode) node).setIgnoreCase(true);
}
} else if (localName.equals(TmfFilterEqualsNode.NODE_NAME)) {
node = new TmfFilterEqualsNode(null);
createEventAspect((TmfFilterAspectNode) node, atts);
String value = atts.getValue(TmfFilterEqualsNode.IGNORECASE_ATTR);
if (value != null && value.equalsIgnoreCase(Boolean.TRUE.toString())) {
((TmfFilterEqualsNode) node).setIgnoreCase(true);
}
} else if (localName.equals(TmfFilterMatchesNode.NODE_NAME)) {
node = new TmfFilterMatchesNode(null);
createEventAspect((TmfFilterAspectNode) node, atts);
((TmfFilterMatchesNode) node).setRegex(atts.getValue(TmfFilterMatchesNode.REGEX_ATTR));
} else if (localName.equals(TmfFilterCompareNode.NODE_NAME)) {
node = new TmfFilterCompareNode(null);
createEventAspect((TmfFilterAspectNode) node, atts);
String value = atts.getValue(TmfFilterCompareNode.TYPE_ATTR);
if (value != null) {
((TmfFilterCompareNode) node).setType(Type.valueOf(value));
}
value = atts.getValue(TmfFilterCompareNode.RESULT_ATTR);
if (value != null) {
if (value.equals(Integer.toString(-1))) {
((TmfFilterCompareNode) node).setResult(-1);
} else if (value.equals(Integer.toString(1))) {
((TmfFilterCompareNode) node).setResult(1);
} else {
((TmfFilterCompareNode) node).setResult(0);
}
}
// Backward compatibility with event type filter node
} else if (localName.equals(EVENTTYPE_NODE_NAME)) {
node = new TmfFilterTraceTypeNode(null);
String label = atts.getValue(NAME_ATTR);
if (label != null) {
// Backward compatibility with renamed LTTng Kernel Trace
if (label.equals(LTTNG_KERNEL_TRACE)) {
label = LINUX_KERNEL_TRACE;
}
String traceTypeId = TmfTraceType.getTraceTypeId(label);
TraceTypeHelper helper = TmfTraceType.getTraceType(traceTypeId);
if (helper == null) {
// Backward compatibility with category-less custom trace types
for (TraceTypeHelper h : TmfTraceType.getTraceTypeHelpers()) {
if (h.getName().equals(label)) {
label = h.getLabel();
helper = h;
break;
}
}
}
if (helper != null) {
((TmfFilterTraceTypeNode) node).setTraceTypeId(helper.getTraceTypeId());
((TmfFilterTraceTypeNode) node).setTraceClass(helper.getTraceClass());
}
((TmfFilterTraceTypeNode) node).setName(label);
}
}
String value = atts.getValue(ITmfFilterWithNot.NOT_ATTRIBUTE);
if (node instanceof ITmfFilterWithNot && Boolean.TRUE.toString().equalsIgnoreCase(value)) {
((ITmfFilterWithNot) node).setNot(true);
}
if (node instanceof ITmfFilterWithValue) {
((ITmfFilterWithValue) node).setValue(atts.getValue(ITmfFilterWithValue.VALUE_ATTRIBUTE));
}
fFilterTreeStack.addFirst(node);
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
ITmfFilterTreeNode node = fFilterTreeStack.removeFirst();
ITmfFilterTreeNode last = fFilterTreeStack.peekFirst();
if (fFilterTreeStack.isEmpty()) {
fRoot = node;
} else {
if (last instanceof TmfFilterTreeNode &&
node instanceof TmfFilterTreeNode) {
last.addChild(node);
}
}
}
private static void createEventAspect(TmfFilterAspectNode node, Attributes atts) {
String traceTypeId = atts.getValue(TmfFilterAspectNode.TRACE_TYPE_ID_ATTR);
traceTypeId = TmfTraceType.buildCompatibilityTraceTypeId(traceTypeId);
String name = atts.getValue(TmfFilterAspectNode.EVENT_ASPECT_ATTR);
if (TmfFilterAspectNode.BASE_ASPECT_ID.equals(traceTypeId)) {
for (ITmfEventAspect<?> eventAspect : TmfBaseAspects.getBaseAspects()) {
if (eventAspect.getName().equals(name)) {
node.setEventAspect(eventAspect);
node.setTraceTypeId(traceTypeId);
if (eventAspect instanceof TmfEventFieldAspect) {
String field = atts.getValue(TmfFilterAspectNode.FIELD_ATTR);
if (field != null && !field.isEmpty()) {
node.setEventAspect(((TmfEventFieldAspect) eventAspect).forField(field));
}
}
break;
}
}
} else if (traceTypeId != null && name != null) {
TraceTypeHelper helper = TmfTraceType.getTraceType(traceTypeId);
if (helper != null) {
for (ITmfEventAspect<?> eventAspect : helper.getTrace().getEventAspects()) {
if (eventAspect.getName().equals(name)) {
node.setEventAspect(eventAspect);
node.setTraceTypeId(traceTypeId);
if (eventAspect instanceof TmfEventFieldAspect) {
String field = atts.getValue(TmfFilterAspectNode.FIELD_ATTR);
if (field != null && !field.isEmpty()) {
node.setEventAspect(((TmfEventFieldAspect) eventAspect).forField(field));
}
}
break;
}
}
}
} else {
// Backward compatibility with field-based filters
String field = atts.getValue(FIELD_ATTR);
if (field != null) {
if (field.equals(EVENT_FIELD_TIMESTAMP)) {
node.setEventAspect(TmfBaseAspects.getTimestampAspect());
node.setTraceTypeId(TmfFilterAspectNode.BASE_ASPECT_ID);
} else if (field.equals(EVENT_FIELD_TYPE)) {
node.setEventAspect(TmfBaseAspects.getEventTypeAspect());
node.setTraceTypeId(TmfFilterAspectNode.BASE_ASPECT_ID);
} else if (field.equals(EVENT_FIELD_CONTENT)) {
node.setEventAspect(TmfBaseAspects.getContentsAspect());
node.setTraceTypeId(TmfFilterAspectNode.BASE_ASPECT_ID);
} else {
node.setEventAspect(TmfBaseAspects.getContentsAspect().forField(field));
node.setTraceTypeId(TmfFilterAspectNode.BASE_ASPECT_ID);
}
}
}
}
}