/** * Copyright 2010 JBoss Inc * * 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 org.drools.eclipse.DroolsEclipsePlugin; import org.drools.eclipse.debug.actions.ShowLogicalStructureAction; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; import org.eclipse.debug.internal.ui.VariablesViewModelPresentation; import org.eclipse.debug.internal.ui.contexts.DebugContextManager; import org.eclipse.debug.internal.ui.views.variables.VariablesView; import org.eclipse.debug.ui.AbstractDebugView; import org.eclipse.debug.ui.IDebugModelPresentation; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.debug.ui.contexts.DebugContextEvent; import org.eclipse.debug.ui.contexts.IDebugContextListener; import org.eclipse.debug.ui.contexts.IDebugContextService; import org.eclipse.jdt.debug.core.IJavaFieldVariable; import org.eclipse.jdt.debug.core.IJavaObject; import org.eclipse.jdt.debug.core.IJavaStackFrame; import org.eclipse.jdt.debug.core.IJavaThread; 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.resource.JFaceResources; import org.eclipse.jface.viewers.IColorProvider; import org.eclipse.jface.viewers.IContentProvider; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.ISelectionListener; import org.eclipse.ui.IWorkbenchActionConstants; import org.eclipse.ui.IWorkbenchPart; /** * A generic Drools debug view. * * @author <a href="mailto:kris_verlaenen@hotmail.com">kris verlaenen </a> */ public abstract class DroolsDebugEventHandlerView extends AbstractDebugView implements IDebugContextListener, ISelectionListener { private VariablesViewModelPresentation modelPresentation; private boolean showLogical = true; private Object[] oldExpandedElements = new Object[0]; public void dispose() { DebugContextManager.getDefault().removeDebugContextListener(this); getSite().getPage().removeSelectionListener(IDebugUIConstants.ID_VARIABLE_VIEW, this); super.dispose(); } public boolean isShowLogicalStructure() { return showLogical; } public void setShowLogicalStructure(boolean showLogical) { this.showLogical = showLogical; } protected void setViewerInput(Object context) { Object input = null; // if a working memory has been explicitly selected as variable, use this if (context instanceof IVariable) { IVariable variable = (IVariable) context; try { IValue value = ((IVariable) context).getValue(); if (value != null && value instanceof IJavaObject) { if ("org.drools.reteoo.ReteooStatefulSession".equals(variable.getValue().getReferenceTypeName())) { input = value; } else if ("org.drools.impl.StatefulKnowledgeSessionImpl".equals(variable.getValue().getReferenceTypeName())) { IJavaFieldVariable sessionVar = ((IJavaObject) value).getField("session", false); if (sessionVar != null) { input = sessionVar.getValue(); } } } } catch (Throwable t) { DroolsEclipsePlugin.log(t); } } // else get selected thread and determine if any of the stack frames // is executing in a working memory, if so, use that one if (input == null) { IDebugContextService debugContextService = DebugContextManager.getDefault().getContextService(getSite().getWorkbenchWindow()); if (debugContextService != null) { ISelection stackSelection = debugContextService.getActiveContext(); if (stackSelection instanceof IStructuredSelection) { Object selection = ((IStructuredSelection) stackSelection).getFirstElement(); if (selection instanceof IJavaStackFrame) { try { IJavaThread thread = (IJavaThread) ((IJavaStackFrame) selection).getThread(); IStackFrame[] frames = thread.getStackFrames(); for (int i = 0; i < frames.length; i++) { IJavaObject stackObj = ((IJavaStackFrame) frames[i]).getThis(); if ((stackObj != null) && (stackObj.getJavaType() != null) && ("org.drools.reteoo.ReteooStatefulSession".equals(stackObj.getJavaType().getName()) || "org.drools.impl.StatefulKnowledgeSessionImpl".equals(stackObj.getJavaType().getName()))) { input = stackObj; break; } } } catch (Throwable t) { DroolsEclipsePlugin.log(t); } } } } } Object current = getViewer().getInput(); if (current == null && input == null) { return; } Object[] newExpandedElements = ((TreeViewer) getViewer()).getExpandedElements(); if (newExpandedElements.length != 0) { oldExpandedElements = newExpandedElements; } getViewer().setInput(input); if (input != null) { ((TreeViewer) getViewer()).setExpandedElements(oldExpandedElements); ((TreeViewer) getViewer()).expandToLevel(getAutoExpandLevel()); } } protected Viewer createViewer(Composite parent) { TreeViewer variablesViewer = new TreeViewer(parent); variablesViewer.setContentProvider(createContentProvider()); variablesViewer.setLabelProvider(new VariablesViewLabelProvider( getModelPresentation())); variablesViewer.setUseHashlookup(true); DebugContextManager.getDefault().addDebugContextListener(this); getSite().getPage().addSelectionListener(IDebugUIConstants.ID_VARIABLE_VIEW, this); return variablesViewer; } protected int getAutoExpandLevel() { return 0; } protected abstract IContentProvider createContentProvider(); protected String getHelpContextId() { return null; } protected void becomesHidden() { setViewerInput(null); super.becomesHidden(); } protected void becomesVisible() { super.becomesVisible(); ISelection selection = getSite().getPage().getSelection( IDebugUIConstants.ID_VARIABLE_VIEW); if (selection instanceof IStructuredSelection) { setViewerInput(((IStructuredSelection) selection).getFirstElement()); } else { setViewerInput(null); } } protected void createActions() { IAction action = new ShowLogicalStructureAction(this); setAction("ShowLogicalStructure", action); } protected void configureToolBar(IToolBarManager tbm) { tbm.add(getAction("ShowLogicalStructure")); } protected void fillContextMenu(IMenuManager menu) { menu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS)); } public void contextActivated(ISelection selection, IWorkbenchPart part) { if (!isAvailable() || !isVisible()) { return; } if (selection instanceof IStructuredSelection) { setViewerInput(((IStructuredSelection)selection).getFirstElement()); } showViewer(); } public void debugContextChanged(DebugContextEvent event) { //selectionChanged(null, event.getContext()); } public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (!isAvailable()) { return; } // In Eclipse 3.5.x, an additional selection changed event with selection null is // generated when clicking on a process instance in the process instance view // replacing this null by the actual selected element in those cases if (part instanceof VariablesView) { selection = ((VariablesView) part).getCurrentSelection(); } if (selection == null) { setViewerInput(null); } else if (selection instanceof IStructuredSelection) { setViewerInput(((IStructuredSelection) selection).getFirstElement()); } } protected void initActionState(IAction action) { // The show logical structure action is always enabled by default // when (re)starting the view String id = action.getId(); if (id.endsWith("ShowLogicalStructureAction")) { action.setChecked(true); } else { super.initActionState(action); } } protected IDebugModelPresentation getModelPresentation() { if (modelPresentation == null) { modelPresentation = new VariablesViewModelPresentation(); } return modelPresentation; } private class VariablesViewLabelProvider implements ILabelProvider, IColorProvider { private IDebugModelPresentation presentation; public VariablesViewLabelProvider(IDebugModelPresentation presentation) { this.presentation = presentation; } public IDebugModelPresentation getPresentation() { return presentation; } public Image getImage(Object element) { return presentation.getImage(element); } public String getText(Object element) { return presentation.getText(element); } public void addListener(ILabelProviderListener listener) { presentation.addListener(listener); } public void dispose() { presentation.dispose(); } public boolean isLabelProperty(Object element, String property) { return presentation.isLabelProperty(element, property); } public void removeListener(ILabelProviderListener listener) { presentation.removeListener(listener); } public Color getForeground(Object element) { if (element instanceof IVariable) { IVariable variable = (IVariable) element; try { if (variable.hasValueChanged()) { return JFaceResources.getColorRegistry() .get(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR); } } catch (DebugException e) { DroolsEclipsePlugin.log(e); } } return null; } public Color getBackground(Object element) { return null; } } }