/* * Copyright 2010 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.eclipse.debug; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.StreamException; import org.drools.core.audit.WorkingMemoryLog; import org.drools.core.audit.event.ActivationLogEvent; import org.drools.core.audit.event.LogEvent; import org.drools.core.audit.event.ObjectLogEvent; import org.drools.core.audit.event.RuleBaseLogEvent; import org.drools.core.audit.event.RuleFlowGroupLogEvent; import org.drools.core.audit.event.RuleFlowLogEvent; import org.drools.core.audit.event.RuleFlowNodeLogEvent; import org.drools.eclipse.DroolsEclipsePlugin; import org.drools.eclipse.DroolsPluginImages; import org.drools.eclipse.debug.actions.DeleteLogAction; import org.drools.eclipse.debug.actions.FileAuditDropAdapter; import org.drools.eclipse.debug.actions.OpenLogAction; import org.drools.eclipse.debug.actions.RefreshLogAction; import org.drools.eclipse.debug.actions.ShowEventCauseAction; import org.eclipse.debug.ui.AbstractDebugView; import org.eclipse.jface.action.GroupMarker; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.FileTransfer; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IMemento; import org.eclipse.ui.IViewSite; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.PartInitException; import java.io.EOFException; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.ObjectInputStream; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Stack; public class AuditView extends AbstractDebugView { private static final String LOG_FILE_NAME = "LogFileName"; private static final String CAUSE_EVENT_COLOR = "CauseEventColor"; private String logFileName; private IAction deleteAction; private IAction refreshAction; private boolean drools4 = false; protected Viewer createViewer(Composite parent) { final TreeViewer variablesViewer = new TreeViewer(parent); variablesViewer.setContentProvider(new AuditViewContentProvider()); variablesViewer.setLabelProvider(new AuditLabelProvider()); variablesViewer.setUseHashlookup(true); variablesViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent event) { getViewer().refresh(); } }); int ops = DND.DROP_COPY | DND.DROP_MOVE; Transfer[] transfers = new Transfer[] { FileTransfer.getInstance()}; variablesViewer.addDropSupport(ops, transfers, new FileAuditDropAdapter(variablesViewer,this)); return variablesViewer; } public void setLogFile(String logFileName) { this.logFileName = logFileName; refresh(); deleteAction.setEnabled(logFileName != null); refreshAction.setEnabled(logFileName != null); } @SuppressWarnings("unchecked") public void refresh() { drools4 = false; boolean reteoo = false; if (logFileName == null) { getViewer().setInput(null); return; } List<LogEvent> eventList = new ArrayList<LogEvent>(); try { XStream xstream = new XStream(); ObjectInputStream in = xstream.createObjectInputStream( new FileReader(logFileName) ); try { while (true) { Object object = in.readObject(); if (object instanceof WorkingMemoryLog) { WorkingMemoryLog log = (WorkingMemoryLog) object; eventList.addAll(log.getEvents()); // TODO check drools version based on the content of the xml file // instead of using the actual runtime class. reteoo |= isReteoo( log ); } else if (object instanceof LogEvent) { eventList.add((LogEvent) object); } else if (object instanceof List) { drools4 = true; eventList.addAll((List<LogEvent>) object); } else { throw new IllegalArgumentException("Unexpected element in log: " + object); } } } catch (StreamException e) { if (!(e.getCause() instanceof EOFException)) { throw e; } } catch (EOFException e) { // do nothing } } catch (FileNotFoundException e) { setLogFile(null); } catch (Throwable t) { DroolsEclipsePlugin.log(t); } if (reteoo) { getViewer().setInput(createEventList(eventList)); } else if (drools4) { getViewer().setInput(createDrools4EventList(eventList)); } else { getViewer().setInput(createPhreakEventList(eventList)); } // TODO: this is necessary because otherwise, the show cause action // cannot find the cause event if it hasn't been shown yet ((TreeViewer) getViewer()).expandAll(); } private boolean isReteoo(WorkingMemoryLog log) { // From Drools 7 phreak is the only available engine. // Tries to check via reflection if the WorkingMemoryLog class has a getEngine() method // (only available on drools 6) and use it if so. try { Method m = log.getClass().getMethod( "getEngine" ); return ((String)m.invoke( log )).equalsIgnoreCase("RETEOO"); } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) { return false; } } protected List<Event> createPhreakEventList(List<LogEvent> logEvents) { Map<Long, Event> objectMap = new HashMap<Long, Event>(); Map<String, Event> activationMap = new HashMap<String, Event>(); Stack<Event> beforeEvents = new Stack<Event>(); List<Event> events = new ArrayList<Event>(); for (LogEvent logEvent : logEvents) { Event event = new Event(logEvent.getType()); switch (logEvent.getType()) { case LogEvent.INSERTED: ObjectLogEvent objectEvent = (ObjectLogEvent) logEvent; event.setString("Object inserted (" + objectEvent.getFactId() + "): " + objectEvent.getObjectToString()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } objectMap.put( objectEvent.getFactId(), event ); break; case LogEvent.UPDATED: objectEvent = (ObjectLogEvent) logEvent; event.setString("Object updated (" + objectEvent.getFactId() + "): " + objectEvent.getObjectToString()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } objectMap.put( objectEvent.getFactId(), event ); break; case LogEvent.RETRACTED: objectEvent = (ObjectLogEvent) logEvent; event.setString("Object removed (" + objectEvent.getFactId() + "): " + objectEvent.getObjectToString()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } objectMap.put( objectEvent.getFactId(), event ); break; case LogEvent.ACTIVATION_CREATED: ActivationLogEvent activationEvent = (ActivationLogEvent) logEvent; event.setString("Activation created: Rule " + activationEvent.getRule() + " " + activationEvent.getDeclarations()); Event mostRecentObjEvent = null; for (Long fhId : getEventFactHandleIds(activationEvent)) { Event objEvent = objectMap.get(fhId); if (objEvent != null && (mostRecentObjEvent == null || mostRecentObjEvent.recency < objEvent.recency)) { mostRecentObjEvent = objEvent; } } if (mostRecentObjEvent != null) { mostRecentObjEvent.addSubEvent(event); } activationMap.put(activationEvent.getActivationId(), event); break; case LogEvent.ACTIVATION_CANCELLED: activationEvent = (ActivationLogEvent) logEvent; event.setString("Activation cancelled: Rule " + activationEvent.getRule() + " " + activationEvent.getDeclarations()); mostRecentObjEvent = null; for (Long fhId : getEventFactHandleIds(activationEvent)) { Event objEvent = objectMap.get(fhId); if (objEvent != null && (mostRecentObjEvent == null || mostRecentObjEvent.recency < objEvent.recency)) { mostRecentObjEvent = objEvent; } } if (mostRecentObjEvent != null) { mostRecentObjEvent.addSubEvent(event); } event.setCauseEvent(activationMap.get(activationEvent.getActivationId())); break; case LogEvent.BEFORE_ACTIVATION_FIRE: activationEvent = (ActivationLogEvent) logEvent; event.setString("Activation executed: Rule " + activationEvent.getRule() + " " + activationEvent.getDeclarations()); events.add(event); beforeEvents.push(event); event.setCauseEvent(activationMap.get(activationEvent.getActivationId())); break; case LogEvent.AFTER_ACTIVATION_FIRE: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_CREATED: RuleFlowLogEvent ruleFlowEvent = (RuleFlowLogEvent) logEvent; event.setString("Process started: " + ruleFlowEvent.getProcessName() + "[" + ruleFlowEvent.getProcessId() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_CREATED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_COMPLETED: ruleFlowEvent = (RuleFlowLogEvent) logEvent; event.setString("Process completed: " + ruleFlowEvent.getProcessName() + "[" + ruleFlowEvent.getProcessId() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_COMPLETED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED: RuleFlowNodeLogEvent ruleFlowNodeEvent = (RuleFlowNodeLogEvent) logEvent; event.setString("Process node triggered: " + ruleFlowNodeEvent.getNodeName() + " in process " + ruleFlowNodeEvent.getProcessName() + "[" + ruleFlowNodeEvent.getProcessId() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_NODE_TRIGGERED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED: RuleFlowGroupLogEvent ruleFlowGroupEvent = (RuleFlowGroupLogEvent) logEvent; event.setString("RuleFlow Group activated: " + ruleFlowGroupEvent.getGroupName() + "[size=" + ruleFlowGroupEvent.getSize() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_GROUP_ACTIVATED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED: ruleFlowGroupEvent = (RuleFlowGroupLogEvent) logEvent; event.setString("RuleFlow Group deactivated: " + ruleFlowGroupEvent.getGroupName() + "[size=" + ruleFlowGroupEvent.getSize() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_GROUP_DEACTIVATED: beforeEvents.pop(); break; case LogEvent.BEFORE_PACKAGE_ADDED: RuleBaseLogEvent ruleBaseEvent = (RuleBaseLogEvent) logEvent; event.setString("Package added: " + ruleBaseEvent.getPackageName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_PACKAGE_ADDED: beforeEvents.pop(); break; case LogEvent.BEFORE_PACKAGE_REMOVED: ruleBaseEvent = (RuleBaseLogEvent) logEvent; event.setString("Package removed: " + ruleBaseEvent.getPackageName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_PACKAGE_REMOVED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULE_ADDED: ruleBaseEvent = (RuleBaseLogEvent) logEvent; event.setString("Rule added: " + ruleBaseEvent.getRuleName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULE_ADDED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULE_REMOVED: ruleBaseEvent = (RuleBaseLogEvent) logEvent; event.setString("Rule removed: " + ruleBaseEvent.getRuleName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULE_REMOVED: beforeEvents.pop(); break; default: // do nothing break; } } return events; } private Long[] getEventFactHandleIds(ActivationLogEvent event) { String[] ids = event.getFactHandleIds().split(","); Long[] longIds = new Long[ids.length]; for (int i = 0; i < ids.length; i++) { longIds[i] = Long.parseLong(ids[i]); } return longIds; } protected List<Event> createEventList(List<LogEvent> logEvents) { Iterator<LogEvent> iterator = logEvents.iterator(); List<Event> events = new ArrayList<Event>(); Stack<Event> beforeEvents = new Stack<Event>(); List<Event> newActivations = new ArrayList<Event>(); Map<String, Event> activationMap = new HashMap<String, Event>(); Map<Long, Event> objectMap = new HashMap<Long, Event>(); while (iterator.hasNext()) { LogEvent inEvent = iterator.next(); Event event = new Event(inEvent.getType()); switch (inEvent.getType()) { case LogEvent.INSERTED: ObjectLogEvent inObjectEvent = (ObjectLogEvent) inEvent; event.setString("Object inserted (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); objectMap.put(new Long(((ObjectLogEvent) inEvent).getFactId()), event); break; case LogEvent.UPDATED: inObjectEvent = (ObjectLogEvent) inEvent; event.setString("Object updated (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); Event assertEvent = objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId())); if (assertEvent != null) { event.setCauseEvent(assertEvent); } break; case LogEvent.RETRACTED: inObjectEvent = (ObjectLogEvent) inEvent; event.setString("Object removed (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); assertEvent = objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId())); if (assertEvent != null) { event.setCauseEvent(assertEvent); } break; case LogEvent.ACTIVATION_CREATED: ActivationLogEvent inActivationEvent = (ActivationLogEvent) inEvent; event.setString("Activation created: Rule " + inActivationEvent.getRule() + " " + inActivationEvent.getDeclarations()); newActivations.add(event); activationMap.put(((ActivationLogEvent) inEvent).getActivationId(), event); break; case LogEvent.ACTIVATION_CANCELLED: inActivationEvent = (ActivationLogEvent) inEvent; event.setString("Activation cancelled: Rule " + inActivationEvent.getRule() + " " + inActivationEvent.getDeclarations()); newActivations.add(event); event.setCauseEvent(activationMap.get(((ActivationLogEvent) inEvent).getActivationId())); break; case LogEvent.BEFORE_ACTIVATION_FIRE: inActivationEvent = (ActivationLogEvent) inEvent; event.setString("Activation executed: Rule " + inActivationEvent.getRule() + " " + inActivationEvent.getDeclarations()); events.add(event); beforeEvents.push(event); event.setCauseEvent(activationMap.get(((ActivationLogEvent) inEvent).getActivationId())); break; case LogEvent.AFTER_ACTIVATION_FIRE: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_CREATED: RuleFlowLogEvent inRuleFlowEvent = (RuleFlowLogEvent) inEvent; event.setString("Process started: " + inRuleFlowEvent.getProcessName() + "[" + inRuleFlowEvent.getProcessId() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_CREATED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_COMPLETED: inRuleFlowEvent = (RuleFlowLogEvent) inEvent; event.setString("Process completed: " + inRuleFlowEvent.getProcessName() + "[" + inRuleFlowEvent.getProcessId() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_COMPLETED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED: RuleFlowNodeLogEvent inRuleFlowNodeEvent = (RuleFlowNodeLogEvent) inEvent; event.setString("Process node triggered: " + inRuleFlowNodeEvent.getNodeName() + " in process " + inRuleFlowNodeEvent.getProcessName() + "[" + inRuleFlowNodeEvent.getProcessId() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_NODE_TRIGGERED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED: RuleFlowGroupLogEvent inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent; event.setString("RuleFlow Group activated: " + inRuleFlowGroupEvent.getGroupName() + "[size=" + inRuleFlowGroupEvent.getSize() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_GROUP_ACTIVATED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED: inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent; event.setString("RuleFlow Group deactivated: " + inRuleFlowGroupEvent.getGroupName() + "[size=" + inRuleFlowGroupEvent.getSize() + "]"); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULEFLOW_GROUP_DEACTIVATED: beforeEvents.pop(); break; case LogEvent.BEFORE_PACKAGE_ADDED: RuleBaseLogEvent ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Package added: " + ruleBaseEvent.getPackageName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_PACKAGE_ADDED: beforeEvents.pop(); break; case LogEvent.BEFORE_PACKAGE_REMOVED: ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Package removed: " + ruleBaseEvent.getPackageName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_PACKAGE_REMOVED: beforeEvents.pop(); break; case LogEvent.BEFORE_RULE_ADDED: ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Rule added: " + ruleBaseEvent.getRuleName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULE_ADDED: if (!beforeEvents.isEmpty()) { Event beforeEvent = beforeEvents.pop(); beforeEvent.addSubEvents(newActivations); newActivations.clear(); } break; case LogEvent.BEFORE_RULE_REMOVED: ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Rule removed: " + ruleBaseEvent.getRuleName()); if (!beforeEvents.isEmpty()) { beforeEvents.peek().addSubEvent(event); } else { events.add(event); } beforeEvents.push(event); break; case LogEvent.AFTER_RULE_REMOVED: if (!beforeEvents.isEmpty()) { Event beforeEvent = beforeEvents.pop(); beforeEvent.addSubEvents(newActivations); newActivations.clear(); } break; default: // do nothing break; } } return events; } protected List<Event> createDrools4EventList(List<LogEvent> logEvents) { Iterator<LogEvent> iterator = logEvents.iterator(); List<Event> events = new ArrayList<Event>(); Event currentBeforeActivationEvent = null; Event currentBeforePackageEvent = null; List<Event> newActivations = new ArrayList<Event>(); Map<String, Event> activationMap = new HashMap<String, Event>(); Map<Long, Event> objectMap = new HashMap<Long, Event>(); while (iterator.hasNext()) { LogEvent inEvent = iterator.next(); Event event = new Event(inEvent.getType()); switch (inEvent.getType()) { case LogEvent.INSERTED: ObjectLogEvent inObjectEvent = (ObjectLogEvent) inEvent; event.setString("Object inserted (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString()); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); objectMap.put(new Long(((ObjectLogEvent) inEvent).getFactId()), event); break; case LogEvent.UPDATED: inObjectEvent = (ObjectLogEvent) inEvent; event.setString("Object updated (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString()); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); Event assertEvent = objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId())); if (assertEvent != null) { event.setCauseEvent(assertEvent); } break; case LogEvent.RETRACTED: inObjectEvent = (ObjectLogEvent) inEvent; event.setString("Object removed (" + inObjectEvent.getFactId() + "): " + inObjectEvent.getObjectToString()); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); assertEvent = objectMap.get(new Long(((ObjectLogEvent) inEvent).getFactId())); if (assertEvent != null) { event.setCauseEvent(assertEvent); } break; case LogEvent.ACTIVATION_CREATED: ActivationLogEvent inActivationEvent = (ActivationLogEvent) inEvent; event.setString("Activation created: Rule " + inActivationEvent.getRule() + " " + inActivationEvent.getDeclarations()); newActivations.add(event); activationMap.put(((ActivationLogEvent) inEvent).getActivationId(), event); break; case LogEvent.ACTIVATION_CANCELLED: inActivationEvent = (ActivationLogEvent) inEvent; event.setString("Activation cancelled: Rule " + inActivationEvent.getRule() + " " + inActivationEvent.getDeclarations()); newActivations.add(event); event.setCauseEvent(activationMap.get(((ActivationLogEvent) inEvent).getActivationId())); break; case LogEvent.BEFORE_ACTIVATION_FIRE: inActivationEvent = (ActivationLogEvent) inEvent; event.setString("Activation executed: Rule " + inActivationEvent.getRule() + " " + inActivationEvent.getDeclarations()); events.add(event); currentBeforeActivationEvent = event; event.setCauseEvent(activationMap.get(((ActivationLogEvent) inEvent).getActivationId())); break; case LogEvent.AFTER_ACTIVATION_FIRE: currentBeforeActivationEvent = null; break; case 8: RuleFlowLogEvent inRuleFlowEvent = (RuleFlowLogEvent) inEvent; event.setString("RuleFlow started: " + inRuleFlowEvent.getProcessName() + "[" + inRuleFlowEvent.getProcessId() + "]"); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } break; case 9: inRuleFlowEvent = (RuleFlowLogEvent) inEvent; event.setString("RuleFlow completed: " + inRuleFlowEvent.getProcessName() + "[" + inRuleFlowEvent.getProcessId() + "]"); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } break; case 10: RuleFlowGroupLogEvent inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent; event.setString("RuleFlowGroup activated: " + inRuleFlowGroupEvent.getGroupName() + "[size=" + inRuleFlowGroupEvent.getSize() + "]"); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } break; case 11: inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent; event.setString("RuleFlowGroup deactivated: " + inRuleFlowGroupEvent.getGroupName() + "[size=" + inRuleFlowGroupEvent.getSize() + "]"); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } break; case 12: RuleBaseLogEvent ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Package added: " + ruleBaseEvent.getPackageName()); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } currentBeforePackageEvent = event; break; case 13: currentBeforePackageEvent = null; break; case 14: ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Package removed: " + ruleBaseEvent.getPackageName()); if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } currentBeforePackageEvent = event; break; case 15: currentBeforePackageEvent = null; break; case 17: ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Rule added: " + ruleBaseEvent.getRuleName()); if (currentBeforePackageEvent != null) { currentBeforePackageEvent.addSubEvent(event); } else if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); break; case 19: ruleBaseEvent = (RuleBaseLogEvent) inEvent; event.setString("Rule removed: " + ruleBaseEvent.getRuleName()); if (currentBeforePackageEvent != null) { currentBeforePackageEvent.addSubEvent(event); } else if (currentBeforeActivationEvent != null) { currentBeforeActivationEvent.addSubEvent(event); } else { events.add(event); } event.addSubEvents(newActivations); newActivations.clear(); break; } } return events; } public void deleteLog() { if (logFileName != null) { File file = new File(logFileName); try { file.delete(); // TODO delete file cause this doesn't seem to work setLogFile(null); refresh(); } catch (Throwable t) { t.printStackTrace(); DroolsEclipsePlugin.log(t); } } } protected void becomesVisible() { refresh(); } protected String getHelpContextId() { return null; } public Event getSelectedEvent() { ISelection selection = getViewer().getSelection(); if (selection instanceof IStructuredSelection) { Object selected = ((IStructuredSelection) selection).getFirstElement(); if (selected instanceof Event) { return (Event) selected; } } return null; } public void showEvent(Event event) { ((TreeViewer) getViewer()).reveal(event); } protected void fillContextMenu(IMenuManager menu) { Event selected = getSelectedEvent(); if (selected != null) { Event causeEvent = selected.getCauseEvent(); if (causeEvent != null) { menu.add(getAction("ShowEventCause")); } } menu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); } protected void createActions() { deleteAction = new DeleteLogAction(this); setAction("ClearLog", deleteAction); deleteAction.setEnabled(logFileName != null); refreshAction = new RefreshLogAction(this); setAction("RefreshLog", refreshAction); refreshAction.setEnabled(logFileName != null); IAction action = new OpenLogAction(this); setAction("OpenLog", action); action = new ShowEventCauseAction(this); setAction("ShowEventCause", action); } protected void configureToolBar(IToolBarManager tbm) { tbm.add(getAction("OpenLog")); tbm.add(getAction("RefreshLog")); tbm.add(getAction("ClearLog")); } public void saveState(IMemento memento) { memento.putString(LOG_FILE_NAME, logFileName); } public void init(IViewSite site, IMemento memento) throws PartInitException { super.init(site, memento); if (memento != null) { logFileName = memento.getString(LOG_FILE_NAME); } } public static class Event { private static long counter = 0; private final long recency = counter++; private String toString; private int type; private List<Event> subEvents = new ArrayList<Event>(); private Event causeEvent; public Event(int type) { this.type = type; } public void setString(String toString) { this.toString = toString; } public String toString() { return toString; } public int getType() { return type; } public void addSubEvent(Event subEvent) { subEvents.add(subEvent); } public void addSubEvents(Collection<Event> subEvents) { this.subEvents.addAll(subEvents); } public Object[] getSubEvents() { return subEvents.toArray(); } public boolean hasSubEvents() { return !subEvents.isEmpty(); } public void setCauseEvent(Event causeEvent) { this.causeEvent = causeEvent; } public Event getCauseEvent() { return causeEvent; } } public class AuditLabelProvider extends LabelProvider implements IColorProvider { public Color getForeground(Object element) { return null; } public Color getBackground(Object element) { Event selected = getSelectedEvent(); if (selected != null) { if (element.equals(selected.getCauseEvent())) { Color color = DroolsEclipsePlugin.getDefault().getColor(CAUSE_EVENT_COLOR); if (color == null) { color = new Color(getControl().getDisplay(), 0, 255, 0); DroolsEclipsePlugin.getDefault().setColor(CAUSE_EVENT_COLOR, color); } return color; } } return null; } public Image getImage(Object element) { if (element instanceof Event) { int type = ((Event) element).getType(); if (drools4) { switch (type) { case LogEvent.INSERTED: return DroolsPluginImages.getImage(DroolsPluginImages.INSERT); case LogEvent.UPDATED: return DroolsPluginImages.getImage(DroolsPluginImages.UPDATE); case LogEvent.RETRACTED: return DroolsPluginImages.getImage(DroolsPluginImages.RETRACT); case LogEvent.ACTIVATION_CREATED: return DroolsPluginImages.getImage(DroolsPluginImages.CREATE_ACTIVATION); case LogEvent.ACTIVATION_CANCELLED: return DroolsPluginImages.getImage(DroolsPluginImages.CANCEL_ACTIVATION); case LogEvent.BEFORE_ACTIVATION_FIRE: return DroolsPluginImages.getImage(DroolsPluginImages.EXECUTE_ACTIVATION); case 8: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW); case 9: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW); case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_NODE_TRIGGERED); case 10: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP); case 11: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP); case 12: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); case 14: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); case 17: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); case 19: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); } } switch (type) { case LogEvent.INSERTED: return DroolsPluginImages.getImage(DroolsPluginImages.INSERT); case LogEvent.UPDATED: return DroolsPluginImages.getImage(DroolsPluginImages.UPDATE); case LogEvent.RETRACTED: return DroolsPluginImages.getImage(DroolsPluginImages.RETRACT); case LogEvent.ACTIVATION_CREATED: return DroolsPluginImages.getImage(DroolsPluginImages.CREATE_ACTIVATION); case LogEvent.ACTIVATION_CANCELLED: return DroolsPluginImages.getImage(DroolsPluginImages.CANCEL_ACTIVATION); case LogEvent.BEFORE_ACTIVATION_FIRE: return DroolsPluginImages.getImage(DroolsPluginImages.EXECUTE_ACTIVATION); case LogEvent.BEFORE_RULEFLOW_CREATED: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW); case LogEvent.BEFORE_RULEFLOW_COMPLETED: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW); case LogEvent.BEFORE_RULEFLOW_NODE_TRIGGERED: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_NODE_TRIGGERED); case LogEvent.BEFORE_RULEFLOW_GROUP_ACTIVATED: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP); case LogEvent.BEFORE_RULEFLOW_GROUP_DEACTIVATED: return DroolsPluginImages.getImage(DroolsPluginImages.RULEFLOW_GROUP); case LogEvent.BEFORE_PACKAGE_ADDED: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); case LogEvent.BEFORE_PACKAGE_REMOVED: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); case LogEvent.BEFORE_RULE_ADDED: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); case LogEvent.BEFORE_RULE_REMOVED: return DroolsPluginImages.getImage(DroolsPluginImages.DROOLS); } return null; } return null; } } }