package jetbrains.mps.debugger.java.runtime.state.customViewers; /*Generated by MPS */ import jetbrains.mps.debugger.java.api.state.customViewers.CustomViewersManager; import org.apache.log4j.Logger; import org.apache.log4j.LogManager; import com.intellij.openapi.project.ProjectManager; import java.util.Map; import jetbrains.mps.debugger.java.api.state.proxy.ValueWrapperFactory; import jetbrains.mps.internal.collections.runtime.MapSequence; import java.util.HashMap; import jetbrains.mps.debugger.java.runtime.state.DebugSession; import jetbrains.mps.debug.api.DebugSessionManagerComponent; import com.intellij.openapi.project.ProjectManagerListener; import org.jetbrains.annotations.NotNull; import java.util.Set; import jetbrains.mps.debugger.java.api.evaluation.proxies.IValueProxy; import jetbrains.mps.internal.collections.runtime.SetSequence; import java.util.LinkedHashSet; import com.sun.jdi.VirtualMachine; import jetbrains.mps.baseLanguage.tuples.runtime.Tuples; import com.sun.jdi.Type; import jetbrains.mps.baseLanguage.tuples.runtime.MultiTuple; import jetbrains.mps.debugger.java.api.evaluation.EvaluationUtils; import com.sun.jdi.InterfaceType; import com.sun.jdi.ClassType; import jetbrains.mps.debugger.java.api.evaluation.EvaluationException; import org.apache.log4j.Level; import jetbrains.mps.debugger.java.api.state.proxy.ValueWrapper; import com.sun.jdi.ThreadReference; import jetbrains.mps.debugger.java.api.evaluation.proxies.INullValueProxy; import jetbrains.mps.debugger.java.api.evaluation.proxies.IObjectValueProxy; import com.sun.jdi.ObjectReference; import com.intellij.openapi.project.Project; import jetbrains.mps.debug.api.AbstractDebugSession; import jetbrains.mps.debugger.java.api.state.proxy.JavaValue; import org.jetbrains.annotations.Nullable; import com.sun.jdi.Value; import jetbrains.mps.debugger.java.api.evaluation.proxies.MirrorUtil; import com.intellij.openapi.project.ProjectManagerAdapter; public class CustomViewersManagerImpl extends CustomViewersManager { private static final Logger LOG = LogManager.getLogger(CustomViewersManagerImpl.class); private final ProjectManager myProjectManager; private final Map<String, ValueWrapperFactory> myFactories = MapSequence.fromMap(new HashMap<String, ValueWrapperFactory>()); private final Map<DebugSession, Map<Long, String>> myObjectIdToFactory = MapSequence.fromMap(new HashMap<DebugSession, Map<Long, String>>()); private final DebugSessionManagerComponent.DebugSessionAdapter myDebugSessionListener = new CustomViewersManagerImpl.MyDebugSessionAdapter(); private final ProjectManagerListener myProjectManagerListener = new CustomViewersManagerImpl.MyProjectManagerAdapter(); public CustomViewersManagerImpl(ProjectManager projectManager) { myProjectManager = projectManager; } @Override public void initComponent() { myProjectManager.addProjectManagerListener(myProjectManagerListener); } @Override public void disposeComponent() { myProjectManager.removeProjectManagerListener(myProjectManagerListener); } @Override public void addFactory(@NotNull ValueWrapperFactory factory) { MapSequence.fromMap(myFactories).put(factory.getClass().getName(), factory); } @Override public void removeFactory(@NotNull ValueWrapperFactory factory) { MapSequence.fromMap(myFactories).removeKey(factory.getClass().getName()); } public Set<ValueWrapperFactory> getValueWrapperFactories(@NotNull final IValueProxy originalValue) { Set<ValueWrapperFactory> result = SetSequence.fromSet(new LinkedHashSet<ValueWrapperFactory>()); for (ValueWrapperFactory factory : MapSequence.fromMap(myFactories).values()) { if (factory.canWrapValue(originalValue)) { SetSequence.fromSet(result).addElement(factory); } } return result; } private ValueWrapperFactory getBestFactory(Set<ValueWrapperFactory> factories, DebugSession session) { VirtualMachine vm = session.getEventsProcessor().getVirtualMachine(); Tuples._2<ValueWrapperFactory, Type> currentBest = MultiTuple.<ValueWrapperFactory,Type>from(null, null); for (ValueWrapperFactory factory : SetSequence.fromSet(factories)) { try { if (currentBest._0() == null) { currentBest._0(factory); currentBest._1(EvaluationUtils.getInstance().findTypeSilently(factory.getWrappedType(), vm)); } else if (!(EvaluationUtils.getInstance().instanceOf(currentBest._1(), factory.getWrappedType(), vm))) { Type newType = EvaluationUtils.getInstance().findTypeSilently(factory.getWrappedType(), vm); if (newType instanceof InterfaceType && currentBest._1() instanceof ClassType && !(currentBest._0().getWrappedType().equals(EvaluationUtils.JAVA_LANG_OBJECT))) { continue; } currentBest._0(factory); currentBest._1(newType); } } catch (EvaluationException e) { if (LOG.isEnabledFor(Level.ERROR)) { LOG.error("Error while trying to select best custom viewer. Current factory is " + factory, e); } } } return currentBest._0(); } public synchronized ValueWrapper getValueWrapper(@NotNull IValueProxy proxy, ThreadReference threadReference) { if (proxy instanceof INullValueProxy) { return MapSequence.fromMap(myFactories).get(ObjectWrapperFactory.class.getName()).createValueWrapper(proxy, threadReference); } ValueWrapperFactory factory = null; DebugSession session = getSession(proxy); if (proxy instanceof IObjectValueProxy) { Map<Long, String> objectIdToFactory = MapSequence.fromMap(myObjectIdToFactory).get(session); if (objectIdToFactory == null) { objectIdToFactory = MapSequence.fromMap(new HashMap<Long, String>()); MapSequence.fromMap(myObjectIdToFactory).put(session, objectIdToFactory); } long uniqueID = getValueId(proxy); String factoryId = MapSequence.fromMap(objectIdToFactory).get(uniqueID); if ((factoryId != null && factoryId.length() > 0)) { factory = MapSequence.fromMap(myFactories).get(factoryId); } } if (factory == null) { Set<ValueWrapperFactory> factories = getValueWrapperFactories(proxy); if (factories.isEmpty()) { return null; } factory = (factories.size() > 1 ? getBestFactory(factories, session) : factories.iterator().next()); } return factory.createValueWrapper(proxy, threadReference); } public synchronized void setValueWrapper(@NotNull IValueProxy value, @NotNull ValueWrapperFactory factory, @NotNull DebugSession session) { Map<Long, String> objectIdToFactory = MapSequence.fromMap(myObjectIdToFactory).get(session); if (objectIdToFactory == null) { objectIdToFactory = MapSequence.fromMap(new HashMap<Long, String>()); MapSequence.fromMap(myObjectIdToFactory).put(session, objectIdToFactory); } String oldFactory = MapSequence.fromMap(objectIdToFactory).get(getValueId(value)); String newFactory = factory.getClass().getName(); if (neq_2btpdq_a0e0o(oldFactory, newFactory)) { MapSequence.fromMap(objectIdToFactory).put(getValueId(value), newFactory); session.refresh(); } } public static CustomViewersManagerImpl getInstanceImpl() { return (CustomViewersManagerImpl) CustomViewersManager.getInstance(); } private long getValueId(@NotNull IValueProxy originalValue) { return ((ObjectReference) originalValue.getJDIValue()).uniqueID(); } private DebugSession getSession(@NotNull IValueProxy value) { // this is just wrong for (Project project : ProjectManager.getInstance().getOpenProjects()) { for (AbstractDebugSession session : SetSequence.fromSet(DebugSessionManagerComponent.getInstance(project).getDebugSessions())) { if (session instanceof DebugSession) { if (((DebugSession) session).getEventsProcessor().getVirtualMachine() == value.getJDIValue().virtualMachine()) { return (DebugSession) session; } } } } return null; } public JavaValue fromJdi(@Nullable Value value, @NotNull ThreadReference threadReference) { return getValueWrapper(MirrorUtil.getInstance().getValueProxy(value), threadReference); } private class MyProjectManagerAdapter extends ProjectManagerAdapter { public MyProjectManagerAdapter() { } @Override public void projectOpened(Project project) { DebugSessionManagerComponent.getInstance(project).addDebugSessionListener(myDebugSessionListener); } @Override public void projectClosing(Project project) { DebugSessionManagerComponent.getInstance(project).removeDebugSessionListener(CustomViewersManagerImpl.this.myDebugSessionListener); } } private class MyDebugSessionAdapter extends DebugSessionManagerComponent.DebugSessionAdapter { public MyDebugSessionAdapter() { } @Override public void detached(AbstractDebugSession session) { if (session instanceof DebugSession) { MapSequence.fromMap(myObjectIdToFactory).removeKey((DebugSession) session); } } } private static boolean neq_2btpdq_a0e0o(Object a, Object b) { return !(((a != null ? a.equals(b) : a == b))); } }