001: package org.drools.eclipse.debug;
002:
003: import java.io.File;
004: import java.io.FileNotFoundException;
005: import java.io.FileReader;
006: import java.io.ObjectInputStream;
007: import java.util.ArrayList;
008: import java.util.Collection;
009: import java.util.HashMap;
010: import java.util.Iterator;
011: import java.util.List;
012: import java.util.Map;
013:
014: import org.drools.audit.event.ActivationLogEvent;
015: import org.drools.audit.event.LogEvent;
016: import org.drools.audit.event.ObjectLogEvent;
017: import org.drools.audit.event.RuleFlowGroupLogEvent;
018: import org.drools.audit.event.RuleFlowLogEvent;
019: import org.drools.eclipse.DroolsEclipsePlugin;
020: import org.drools.eclipse.DroolsPluginImages;
021: import org.drools.eclipse.debug.actions.DeleteLogAction;
022: import org.drools.eclipse.debug.actions.OpenLogAction;
023: import org.drools.eclipse.debug.actions.RefreshLogAction;
024: import org.drools.eclipse.debug.actions.ShowEventCauseAction;
025: import org.eclipse.debug.ui.AbstractDebugView;
026: import org.eclipse.jface.action.GroupMarker;
027: import org.eclipse.jface.action.IAction;
028: import org.eclipse.jface.action.IMenuManager;
029: import org.eclipse.jface.action.IToolBarManager;
030: import org.eclipse.jface.viewers.IColorProvider;
031: import org.eclipse.jface.viewers.ISelection;
032: import org.eclipse.jface.viewers.ISelectionChangedListener;
033: import org.eclipse.jface.viewers.IStructuredSelection;
034: import org.eclipse.jface.viewers.LabelProvider;
035: import org.eclipse.jface.viewers.SelectionChangedEvent;
036: import org.eclipse.jface.viewers.TreeViewer;
037: import org.eclipse.jface.viewers.Viewer;
038: import org.eclipse.swt.graphics.Color;
039: import org.eclipse.swt.graphics.Image;
040: import org.eclipse.swt.widgets.Composite;
041: import org.eclipse.ui.IMemento;
042: import org.eclipse.ui.IViewSite;
043: import org.eclipse.ui.IWorkbenchActionConstants;
044: import org.eclipse.ui.PartInitException;
045:
046: import com.thoughtworks.xstream.XStream;
047:
048: public class AuditView extends AbstractDebugView {
049:
050: private static final String LOG_FILE_NAME = "LogFileName";
051: private static final String CAUSE_EVENT_COLOR = "CauseEventColor";
052:
053: private String logFileName;
054: private IAction deleteAction;
055: private IAction refreshAction;
056:
057: protected Viewer createViewer(Composite parent) {
058: final TreeViewer variablesViewer = new TreeViewer(parent);
059: variablesViewer
060: .setContentProvider(new AuditViewContentProvider());
061: variablesViewer.setLabelProvider(new AuditLabelProvider());
062: variablesViewer.setUseHashlookup(true);
063: variablesViewer
064: .addSelectionChangedListener(new ISelectionChangedListener() {
065: public void selectionChanged(
066: SelectionChangedEvent event) {
067: getViewer().refresh();
068: }
069: });
070: return variablesViewer;
071: }
072:
073: public void setLogFile(String logFileName) {
074: this .logFileName = logFileName;
075: refresh();
076: deleteAction.setEnabled(logFileName != null);
077: refreshAction.setEnabled(logFileName != null);
078: }
079:
080: public void refresh() {
081: if (logFileName == null) {
082: getViewer().setInput(null);
083: return;
084: }
085: try {
086: XStream xstream = new XStream();
087: ObjectInputStream in = xstream
088: .createObjectInputStream(new FileReader(logFileName));
089: getViewer().setInput(
090: createEventList((List) in.readObject()));
091: // TODO: this is necessary because otherwise, the show cause action
092: // cannot find the cause event if it hasn't been shown yet
093: ((TreeViewer) getViewer()).expandAll();
094: } catch (FileNotFoundException e) {
095: setLogFile(null);
096: getViewer().setInput(null);
097: } catch (Throwable t) {
098: DroolsEclipsePlugin.log(t);
099: getViewer().setInput(null);
100: }
101: }
102:
103: protected List createEventList(List logEvents) {
104: Iterator iterator = logEvents.iterator();
105: List events = new ArrayList();
106: Event currentBeforeActivationEvent = null;
107: List newActivations = new ArrayList();
108: Map activationMap = new HashMap();
109: Map objectMap = new HashMap();
110: while (iterator.hasNext()) {
111: LogEvent inEvent = (LogEvent) iterator.next();
112: Event event = new Event(inEvent.getType());
113: switch (inEvent.getType()) {
114: case LogEvent.INSERTED:
115: ObjectLogEvent inObjectEvent = (ObjectLogEvent) inEvent;
116: event.setString("Object asserted ("
117: + inObjectEvent.getFactId() + "): "
118: + inObjectEvent.getObjectToString());
119: if (currentBeforeActivationEvent != null) {
120: currentBeforeActivationEvent.addSubEvent(event);
121: } else {
122: events.add(event);
123: }
124: event.addSubEvents(newActivations);
125: newActivations.clear();
126: objectMap.put(new Long(((ObjectLogEvent) inEvent)
127: .getFactId()), event);
128: break;
129: case LogEvent.UPDATED:
130: inObjectEvent = (ObjectLogEvent) inEvent;
131: event.setString("Object modified ("
132: + inObjectEvent.getFactId() + "): "
133: + inObjectEvent.getObjectToString());
134: if (currentBeforeActivationEvent != null) {
135: currentBeforeActivationEvent.addSubEvent(event);
136: } else {
137: events.add(event);
138: }
139: event.addSubEvents(newActivations);
140: newActivations.clear();
141: Event assertEvent = (Event) objectMap.get(new Long(
142: ((ObjectLogEvent) inEvent).getFactId()));
143: if (assertEvent != null) {
144: event.setCauseEvent(assertEvent);
145: }
146: break;
147: case LogEvent.RETRACTED:
148: inObjectEvent = (ObjectLogEvent) inEvent;
149: event.setString("Object retracted ("
150: + inObjectEvent.getFactId() + "): "
151: + inObjectEvent.getObjectToString());
152: if (currentBeforeActivationEvent != null) {
153: currentBeforeActivationEvent.addSubEvent(event);
154: } else {
155: events.add(event);
156: }
157: event.addSubEvents(newActivations);
158: newActivations.clear();
159: assertEvent = (Event) objectMap.get(new Long(
160: ((ObjectLogEvent) inEvent).getFactId()));
161: if (assertEvent != null) {
162: event.setCauseEvent(assertEvent);
163: }
164: break;
165: case LogEvent.ACTIVATION_CREATED:
166: ActivationLogEvent inActivationEvent = (ActivationLogEvent) inEvent;
167: event.setString("Activation created: Rule "
168: + inActivationEvent.getRule() + " "
169: + inActivationEvent.getDeclarations());
170: newActivations.add(event);
171: activationMap.put(((ActivationLogEvent) inEvent)
172: .getActivationId(), event);
173: break;
174: case LogEvent.ACTIVATION_CANCELLED:
175: inActivationEvent = (ActivationLogEvent) inEvent;
176: event.setString("Activation cancelled: Rule "
177: + inActivationEvent.getRule() + " "
178: + inActivationEvent.getDeclarations());
179: newActivations.add(event);
180: event.setCauseEvent((Event) activationMap
181: .get(((ActivationLogEvent) inEvent)
182: .getActivationId()));
183: break;
184: case LogEvent.BEFORE_ACTIVATION_FIRE:
185: inActivationEvent = (ActivationLogEvent) inEvent;
186: event.setString("Activation executed: Rule "
187: + inActivationEvent.getRule() + " "
188: + inActivationEvent.getDeclarations());
189: events.add(event);
190: currentBeforeActivationEvent = event;
191: event.setCauseEvent((Event) activationMap
192: .get(((ActivationLogEvent) inEvent)
193: .getActivationId()));
194: break;
195: case LogEvent.AFTER_ACTIVATION_FIRE:
196: currentBeforeActivationEvent = null;
197: break;
198: case LogEvent.RULEFLOW_CREATED:
199: RuleFlowLogEvent inRuleFlowEvent = (RuleFlowLogEvent) inEvent;
200: event.setString("RuleFlow started: "
201: + inRuleFlowEvent.getProcessName() + "["
202: + inRuleFlowEvent.getProcessId() + "]");
203: if (currentBeforeActivationEvent != null) {
204: currentBeforeActivationEvent.addSubEvent(event);
205: } else {
206: events.add(event);
207: }
208: break;
209: case LogEvent.RULEFLOW_COMPLETED:
210: inRuleFlowEvent = (RuleFlowLogEvent) inEvent;
211: event.setString("RuleFlow completed: "
212: + inRuleFlowEvent.getProcessName() + "["
213: + inRuleFlowEvent.getProcessId() + "]");
214: if (currentBeforeActivationEvent != null) {
215: currentBeforeActivationEvent.addSubEvent(event);
216: } else {
217: events.add(event);
218: }
219: break;
220: case LogEvent.RULEFLOW_GROUP_ACTIVATED:
221: RuleFlowGroupLogEvent inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent;
222: event.setString("RuleFlowGroup activated: "
223: + inRuleFlowGroupEvent.getGroupName()
224: + "[size=" + inRuleFlowGroupEvent.getSize()
225: + "]");
226: event.addSubEvents(newActivations);
227: newActivations.clear();
228: if (currentBeforeActivationEvent != null) {
229: currentBeforeActivationEvent.addSubEvent(event);
230: } else {
231: events.add(event);
232: }
233: break;
234: case LogEvent.RULEFLOW_GROUP_DEACTIVATED:
235: inRuleFlowGroupEvent = (RuleFlowGroupLogEvent) inEvent;
236: event.setString("RuleFlowGroup deactivated: "
237: + inRuleFlowGroupEvent.getGroupName()
238: + "[size=" + inRuleFlowGroupEvent.getSize()
239: + "]");
240: event.addSubEvents(newActivations);
241: newActivations.clear();
242: if (currentBeforeActivationEvent != null) {
243: currentBeforeActivationEvent.addSubEvent(event);
244: } else {
245: events.add(event);
246: }
247: break;
248: }
249: }
250: return events;
251: }
252:
253: public void deleteLog() {
254: if (logFileName != null) {
255: File file = new File(logFileName);
256: try {
257: file.delete();
258: // TODO delete file cause this doesn't seem to work
259: setLogFile(null);
260: refresh();
261: } catch (Throwable t) {
262: t.printStackTrace();
263: DroolsEclipsePlugin.log(t);
264: }
265: }
266: }
267:
268: protected void becomesVisible() {
269: refresh();
270: }
271:
272: protected String getHelpContextId() {
273: return null;
274: }
275:
276: public Event getSelectedEvent() {
277: ISelection selection = getViewer().getSelection();
278: if (selection instanceof IStructuredSelection) {
279: Object selected = ((IStructuredSelection) selection)
280: .getFirstElement();
281: if (selected instanceof Event) {
282: return (Event) selected;
283: }
284: }
285: return null;
286: }
287:
288: public void showEvent(Event event) {
289: ((TreeViewer) getViewer()).reveal(event);
290: }
291:
292: protected void fillContextMenu(IMenuManager menu) {
293: Event selected = getSelectedEvent();
294: if (selected != null) {
295: Event causeEvent = selected.getCauseEvent();
296: if (causeEvent != null) {
297: menu.add(getAction("ShowEventCause"));
298: }
299: }
300: menu
301: .add(new GroupMarker(
302: IWorkbenchActionConstants.MB_ADDITIONS));
303: }
304:
305: protected void createActions() {
306: deleteAction = new DeleteLogAction(this );
307: setAction("ClearLog", deleteAction);
308: deleteAction.setEnabled(logFileName != null);
309: refreshAction = new RefreshLogAction(this );
310: setAction("RefreshLog", refreshAction);
311: refreshAction.setEnabled(logFileName != null);
312: IAction action = new OpenLogAction(this );
313: setAction("OpenLog", action);
314: action = new ShowEventCauseAction(this );
315: setAction("ShowEventCause", action);
316: }
317:
318: protected void configureToolBar(IToolBarManager tbm) {
319: tbm.add(getAction("OpenLog"));
320: tbm.add(getAction("RefreshLog"));
321: tbm.add(getAction("ClearLog"));
322: }
323:
324: public void saveState(IMemento memento) {
325: memento.putString(LOG_FILE_NAME, logFileName);
326: }
327:
328: public void init(IViewSite site, IMemento memento)
329: throws PartInitException {
330: super .init(site, memento);
331: if (memento != null) {
332: logFileName = memento.getString(LOG_FILE_NAME);
333: }
334: }
335:
336: public class Event {
337:
338: private String toString;
339: private int type;
340: private List subEvents = new ArrayList();
341: private Event causeEvent;
342:
343: public Event(int type) {
344: this .type = type;
345: }
346:
347: public void setString(String toString) {
348: this .toString = toString;
349: }
350:
351: public String toString() {
352: return toString;
353: }
354:
355: public int getType() {
356: return type;
357: }
358:
359: public void addSubEvent(Event subEvent) {
360: subEvents.add(subEvent);
361: }
362:
363: public void addSubEvents(Collection subEvents) {
364: this .subEvents.addAll(subEvents);
365: }
366:
367: public Object[] getSubEvents() {
368: return subEvents.toArray();
369: }
370:
371: public boolean hasSubEvents() {
372: return !subEvents.isEmpty();
373: }
374:
375: public void setCauseEvent(Event causeEvent) {
376: this .causeEvent = causeEvent;
377: }
378:
379: public Event getCauseEvent() {
380: return causeEvent;
381: }
382: }
383:
384: public class AuditLabelProvider extends LabelProvider implements
385: IColorProvider {
386:
387: public Color getForeground(Object element) {
388: return null;
389: }
390:
391: public Color getBackground(Object element) {
392: Event selected = getSelectedEvent();
393: if (selected != null) {
394: if (element.equals(selected.getCauseEvent())) {
395: Color color = DroolsEclipsePlugin.getDefault()
396: .getColor(CAUSE_EVENT_COLOR);
397: if (color == null) {
398: color = new Color(getControl().getDisplay(), 0,
399: 255, 0);
400: DroolsEclipsePlugin.getDefault().setColor(
401: CAUSE_EVENT_COLOR, color);
402: }
403: return color;
404: }
405: }
406: return null;
407: }
408:
409: public Image getImage(Object element) {
410: if (element instanceof Event) {
411: int type = ((Event) element).getType();
412: switch (type) {
413: case LogEvent.INSERTED:
414: return DroolsPluginImages
415: .getImage(DroolsPluginImages.INSERT);
416: case LogEvent.UPDATED:
417: return DroolsPluginImages
418: .getImage(DroolsPluginImages.UPDATE);
419: case LogEvent.RETRACTED:
420: return DroolsPluginImages
421: .getImage(DroolsPluginImages.RETRACT);
422: case LogEvent.ACTIVATION_CREATED:
423: return DroolsPluginImages
424: .getImage(DroolsPluginImages.CREATE_ACTIVATION);
425: case LogEvent.ACTIVATION_CANCELLED:
426: return DroolsPluginImages
427: .getImage(DroolsPluginImages.CANCEL_ACTIVATION);
428: case LogEvent.BEFORE_ACTIVATION_FIRE:
429: return DroolsPluginImages
430: .getImage(DroolsPluginImages.EXECUTE_ACTIVATION);
431: case LogEvent.RULEFLOW_CREATED:
432: return DroolsPluginImages
433: .getImage(DroolsPluginImages.RULEFLOW);
434: case LogEvent.RULEFLOW_COMPLETED:
435: return DroolsPluginImages
436: .getImage(DroolsPluginImages.RULEFLOW);
437: case LogEvent.RULEFLOW_GROUP_ACTIVATED:
438: return DroolsPluginImages
439: .getImage(DroolsPluginImages.RULEFLOW);
440: case LogEvent.RULEFLOW_GROUP_DEACTIVATED:
441: return DroolsPluginImages
442: .getImage(DroolsPluginImages.RULEFLOW);
443: }
444: return null;
445: }
446: return null;
447: }
448: }
449: }
|