package com.redhat.ceylon.eclipse.core.debug; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.eclipse.core.internal.runtime.AdapterManager; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IAdapterFactory; import org.eclipse.core.runtime.Platform; import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementEditor; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementMementoProvider; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; import org.eclipse.debug.ui.actions.IWatchExpressionFactoryAdapter; import org.eclipse.jdt.debug.core.IJavaStackFrame; import org.eclipse.jdt.debug.core.IJavaValue; import org.eclipse.jdt.debug.core.IJavaVariable; import org.eclipse.jdt.internal.debug.ui.display.JavaInspectExpression; import org.eclipse.jdt.internal.debug.ui.monitors.MonitorsAdapterFactory; import org.eclipse.jdt.internal.debug.ui.variables.ColumnPresentationAdapterFactory; import org.eclipse.jdt.internal.debug.ui.variables.JavaDebugElementAdapterFactory; import com.redhat.ceylon.eclipse.core.debug.model.CeylonJDIDebugTarget; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonDebugTargetContentProvider; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonExpressionContentProvider; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonExpressionLabelProvider; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonModelProxyFactory; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonStackFrameContentProvider; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonStackFrameLabelProvider; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonVariableColumnPresentationFactory; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonVariableContentProvider; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonVariableEditor; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonVariableLabelProvider; import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonWatchExpressionFilter; public class CeylonDebugElementAdapterFactory implements IAdapterFactory { private static final CeylonDebugElementAdapterFactory ceylonDebugAdapterFactory = new CeylonDebugElementAdapterFactory(); private static final TargetAdapterFactory ceylonDebugTargetAdapterFactory = new TargetAdapterFactory(); private static final JavaDebugElementAdapterFactory javaDebugElementAdapterFactory = new JavaDebugElementAdapterFactory(); private static final IElementLabelProvider fgLPVariable = new CeylonVariableLabelProvider(); private static final IElementContentProvider fgCPVariable = new CeylonVariableContentProvider(); private static final IElementLabelProvider fgLPExpression = new CeylonExpressionLabelProvider(); private static final IElementContentProvider fgCPExpression = new CeylonExpressionContentProvider(); private static final IWatchExpressionFactoryAdapter fgWEVariable = new CeylonWatchExpressionFilter(); private static final IElementLabelProvider fgLPFrame = new CeylonStackFrameLabelProvider(); private static final IElementContentProvider fgCPTarget = new CeylonDebugTargetContentProvider(); private static final IModelProxyFactory fgCeylonModelProxyFactory = new CeylonModelProxyFactory(); private static final IElementContentProvider ceylonStackFrameContentProvider = new CeylonStackFrameContentProvider(); private static final IColumnPresentationFactory fgColumnPresentation = new CeylonVariableColumnPresentationFactory(); private static final IElementEditor fgEEJavaVariable = new CeylonVariableEditor(); public static class TargetAdapterFactory implements IAdapterFactory { @Override public Object getAdapter(Object adaptableObject, @SuppressWarnings("rawtypes") Class adapterType) { if (adapterType.equals(IModelProxyFactory.class)) { if (adaptableObject instanceof CeylonJDIDebugTarget) { return fgCeylonModelProxyFactory; } } if (adapterType.equals(IElementContentProvider.class)) { if (adaptableObject instanceof CeylonJDIDebugTarget) { return fgCPTarget; } } return null; } @SuppressWarnings("rawtypes") @Override public Class[] getAdapterList() { return new Class[]{ IModelProxyFactory.class, IElementContentProvider.class}; } } @Override public Object getAdapter(Object adaptableObject, @SuppressWarnings("rawtypes") Class adapterType) { if (IElementLabelProvider.class.equals(adapterType)) { if (adaptableObject instanceof IJavaVariable) { return fgLPVariable; } if (adaptableObject instanceof IJavaStackFrame) { return fgLPFrame; } if (adaptableObject instanceof JavaInspectExpression) { return fgLPExpression; } } if (IElementContentProvider.class.equals(adapterType)) { if (adaptableObject instanceof IJavaVariable) { return fgCPVariable; } if (adaptableObject instanceof JavaInspectExpression) { return fgCPExpression; } if (adaptableObject instanceof IJavaValue) { return fgCPExpression; } if (adaptableObject instanceof IJavaStackFrame) { return ceylonStackFrameContentProvider; } } if (IWatchExpressionFactoryAdapter.class.equals(adapterType)) { if (adaptableObject instanceof IJavaVariable) { return fgWEVariable; } if (adaptableObject instanceof JavaInspectExpression) { return fgWEVariable; } } if (IElementEditor.class.equals(adapterType)) { if (adaptableObject instanceof IJavaVariable) { return fgEEJavaVariable; } } if (IColumnPresentationFactory.class.equals(adapterType)) { if (adaptableObject instanceof IJavaStackFrame) { return fgColumnPresentation; } } return javaDebugElementAdapterFactory.getAdapter(adaptableObject, adapterType); } @Override @SuppressWarnings("rawtypes") public Class[] getAdapterList() { return new Class[] {IElementLabelProvider.class, IElementContentProvider.class, IWatchExpressionFactoryAdapter.class, IElementMementoProvider.class, IElementEditor.class, IColumnPresentationFactory.class}; } private static final Map<Class<? extends IAdaptable>, List<IAdapterFactory>> replacedAdapters = new HashMap<Class<? extends IAdaptable>, List<IAdapterFactory>>(); private static final Class<? extends IAdaptable> stackFrameAdaptableClass = IJavaStackFrame.class; private static final Class<? extends IAdaptable> ceylonDebugTargetAdaptableClass = CeylonJDIDebugTarget.class; private static final Class<? extends IAdaptable> variableAdaptableClass = IJavaVariable.class; private static final Class<? extends IAdaptable> valueAdaptableClass = IJavaValue.class; private static final Class<? extends IAdaptable> inspectExpressionAdaptableClass = JavaInspectExpression.class; private static final List<Class<? extends IAdaptable>> adaptablesToOverride = Arrays.asList(stackFrameAdaptableClass, variableAdaptableClass, valueAdaptableClass, inspectExpressionAdaptableClass); public static synchronized void installCeylonDebugElementAdapters() { try { AdapterManager adapterManager = (AdapterManager) Platform.getAdapterManager(); if (! replacedAdapters.isEmpty()) { System.err.println("WARNING : Ceylon Debug Adapters already installed. Cancelling."); return; } for (Class<? extends IAdaptable> adaptableClass : adaptablesToOverride) { String adaptableName = adaptableClass.getName(); @SuppressWarnings("unchecked") List<IAdapterFactory> factories = (List<IAdapterFactory>) adapterManager.getFactories() .get(adaptableName); ArrayList<IAdapterFactory> removedFactories = new ArrayList<>(); replacedAdapters.put(adaptableClass, removedFactories); for (Iterator<IAdapterFactory> iterator = factories.iterator(); iterator.hasNext();) { IAdapterFactory factory = iterator.next(); boolean remove = false; if (adaptableClass == stackFrameAdaptableClass) { // Remove the IStackFrame JDT adapters added in the JDT Debug UI plugin.xml ( // => for IElementLabelProvider and IElementMementoProvider ) if (factory.getClass().getName().equals("org.eclipse.core.internal.adapter.AdapterFactoryProxy")) { remove = true; } // Remove the other IStackFrame JDT adapters if (factory instanceof MonitorsAdapterFactory) { remove = true; } if (factory instanceof ColumnPresentationAdapterFactory) { remove = true; } } else if (adaptableClass == variableAdaptableClass && factory instanceof ColumnPresentationAdapterFactory) { remove = true; } else { if (factory instanceof JavaDebugElementAdapterFactory) { remove = true; } } if (remove) { iterator.remove(); removedFactories.add(factory); } } } // Add the provided adapters for (Class<? extends IAdaptable> adaptableClass : adaptablesToOverride) { adapterManager.registerAdapters(ceylonDebugAdapterFactory, adaptableClass); } adapterManager.registerAdapters(ceylonDebugTargetAdapterFactory, ceylonDebugTargetAdaptableClass); } catch (Exception e) { e.printStackTrace(); } } public static synchronized void restoreJDTDebugElementAdapters() { try { AdapterManager adapterManager = (AdapterManager) Platform.getAdapterManager(); for (Class<? extends IAdaptable> adaptableClass : adaptablesToOverride) { adapterManager.unregisterAdapters(ceylonDebugAdapterFactory, adaptableClass); } adapterManager.unregisterAdapters(ceylonDebugTargetAdapterFactory, ceylonDebugTargetAdaptableClass); for (Class<? extends IAdaptable> adaptableClass : adaptablesToOverride) { List<IAdapterFactory> factoriesToRestore = replacedAdapters.get(adaptableClass); if (factoriesToRestore != null) { for (IAdapterFactory factoryToRestore : factoriesToRestore) { adapterManager.registerAdapters(factoryToRestore, adaptableClass); } } } replacedAdapters.clear(); } catch (Exception e) { e.printStackTrace(); } } public static synchronized boolean areCeylonDebugElementAdaptersInstalled() { return ! replacedAdapters.isEmpty(); } }