| /******************************************************************************* |
| * Copyright (c) 2004, 2012 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.internal.debug.core.logicalstructures; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtensionPoint; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener; |
| import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; |
| import org.eclipse.core.runtime.preferences.InstanceScope; |
| import org.eclipse.debug.core.DebugException; |
| import org.eclipse.debug.core.ILogicalStructureProvider; |
| import org.eclipse.debug.core.ILogicalStructureType; |
| import org.eclipse.debug.core.model.IValue; |
| import org.eclipse.jdt.debug.core.IJavaClassType; |
| import org.eclipse.jdt.debug.core.IJavaInterfaceType; |
| import org.eclipse.jdt.debug.core.IJavaObject; |
| import org.eclipse.jdt.debug.core.IJavaType; |
| import org.eclipse.jdt.debug.core.JDIDebugModel; |
| import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin; |
| import org.osgi.service.prefs.BackingStoreException; |
| |
| public class JavaLogicalStructures implements ILogicalStructureProvider { |
| |
| // preference values |
| static final char IS_SUBTYPE_TRUE = 'T'; |
| static final char IS_SUBTYPE_FALSE = 'F'; |
| |
| /** |
| * The list of java logical structures. |
| */ |
| private static Map<String, List<JavaLogicalStructure>> fJavaLogicalStructureMap; |
| |
| /** |
| * The list of java logical structures in this Eclipse install. |
| */ |
| private static List<JavaLogicalStructure> fPluginContributedJavaLogicalStructures; |
| |
| /** |
| * The list of java logical structures defined by the user. |
| */ |
| private static List<JavaLogicalStructure> fUserDefinedJavaLogicalStructures; |
| |
| /** |
| * The list of java logical structures listeners. |
| */ |
| private static Set<IJavaStructuresListener> fListeners = new HashSet<>(); |
| |
| /** |
| * Preference key for the list of user defined Java logical structures |
| * |
| * @since 3.1 |
| */ |
| private static final String PREF_JAVA_LOGICAL_STRUCTURES = JDIDebugModel |
| .getPluginIdentifier() + ".PREF_JAVA_LOGICAL_STRUCTURES"; //$NON-NLS-1$ |
| |
| /** |
| * Updates user defined logical structures if the preference changes |
| */ |
| static class PreferenceListener implements IPreferenceChangeListener { |
| /* (non-Javadoc) |
| * @see org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener#preferenceChange(org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent) |
| */ |
| @Override |
| public void preferenceChange(PreferenceChangeEvent event) { |
| if (PREF_JAVA_LOGICAL_STRUCTURES.equals(event.getKey())) { |
| initUserDefinedJavaLogicalStructures(); |
| initJavaLogicalStructureMap(); |
| Iterator<IJavaStructuresListener> iter = fListeners.iterator(); |
| while (iter.hasNext()) { |
| iter.next().logicalStructuresChanged(); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Get the logical structure from the extension point and the preference |
| * store, and initialize the map. |
| */ |
| static { |
| initPluginContributedJavaLogicalStructure(); |
| initUserDefinedJavaLogicalStructures(); |
| initJavaLogicalStructureMap(); |
| IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(JDIDebugPlugin.getUniqueIdentifier()); |
| if(prefs != null) { |
| prefs.addPreferenceChangeListener(new PreferenceListener()); |
| } |
| } |
| |
| private static void initJavaLogicalStructureMap() { |
| fJavaLogicalStructureMap = new HashMap<>(); |
| addAllLogicalStructures(fPluginContributedJavaLogicalStructures); |
| addAllLogicalStructures(fUserDefinedJavaLogicalStructures); |
| } |
| |
| /** |
| * @param pluginContributedJavaLogicalStructures |
| */ |
| private static void addAllLogicalStructures( |
| List<JavaLogicalStructure> pluginContributedJavaLogicalStructures) { |
| for (Iterator<JavaLogicalStructure> iter = pluginContributedJavaLogicalStructures.iterator(); iter |
| .hasNext();) { |
| addLogicalStructure(iter.next()); |
| } |
| } |
| |
| /** |
| * @param structure |
| */ |
| private static void addLogicalStructure(JavaLogicalStructure structure) { |
| String typeName = structure.getQualifiedTypeName(); |
| List<JavaLogicalStructure> logicalStructure = fJavaLogicalStructureMap.get(typeName); |
| if (logicalStructure == null) { |
| logicalStructure = new ArrayList<>(); |
| fJavaLogicalStructureMap.put(typeName, logicalStructure); |
| } |
| logicalStructure.add(structure); |
| } |
| |
| /** |
| * Get the configuration elements for the extension point. |
| */ |
| private static void initPluginContributedJavaLogicalStructure() { |
| fPluginContributedJavaLogicalStructures = new ArrayList<>(); |
| IExtensionPoint extensionPoint = Platform.getExtensionRegistry() |
| .getExtensionPoint(JDIDebugPlugin.getUniqueIdentifier(), |
| JDIDebugPlugin.EXTENSION_POINT_JAVA_LOGICAL_STRUCTURES); |
| IConfigurationElement[] javaLogicalStructureElements = extensionPoint |
| .getConfigurationElements(); |
| for (IConfigurationElement javaLogicalStructureElement : javaLogicalStructureElements) { |
| try { |
| fPluginContributedJavaLogicalStructures |
| .add(new JavaLogicalStructure( |
| javaLogicalStructureElement)); |
| } catch (CoreException e) { |
| JDIDebugPlugin.log(e); |
| } |
| } |
| } |
| |
| /** |
| * Get the user defined logical structures (from the preference store). |
| */ |
| private static void initUserDefinedJavaLogicalStructures() { |
| fUserDefinedJavaLogicalStructures = new ArrayList<>(); |
| String logicalStructuresString = Platform.getPreferencesService().getString( |
| JDIDebugPlugin.getUniqueIdentifier(), |
| PREF_JAVA_LOGICAL_STRUCTURES, |
| "", //$NON-NLS-1$ |
| null); |
| StringTokenizer tokenizer = new StringTokenizer( |
| logicalStructuresString, "\0", true); //$NON-NLS-1$ |
| while (tokenizer.hasMoreTokens()) { |
| String type = tokenizer.nextToken(); |
| tokenizer.nextToken(); |
| String description = tokenizer.nextToken(); |
| tokenizer.nextToken(); |
| String isSubtypeValue = tokenizer.nextToken(); |
| boolean isSubtype = isSubtypeValue.charAt(0) == IS_SUBTYPE_TRUE; |
| tokenizer.nextToken(); |
| String value = tokenizer.nextToken(); |
| if (value.charAt(0) == '\0') { |
| value = null; |
| } else { |
| tokenizer.nextToken(); |
| } |
| String variablesCounterValue = tokenizer.nextToken(); |
| int variablesCounter = Integer.parseInt(variablesCounterValue); |
| tokenizer.nextToken(); |
| String[][] variables = new String[variablesCounter][2]; |
| for (int i = 0; i < variablesCounter; i++) { |
| variables[i][0] = tokenizer.nextToken(); |
| tokenizer.nextToken(); |
| variables[i][1] = tokenizer.nextToken(); |
| tokenizer.nextToken(); |
| } |
| fUserDefinedJavaLogicalStructures.add(new JavaLogicalStructure( |
| type, isSubtype, value, description, variables)); |
| } |
| } |
| |
| /** |
| * Save the user defined logical structures in the preference store. |
| */ |
| public static void saveUserDefinedJavaLogicalStructures() { |
| StringBuffer logicalStructuresString = new StringBuffer(); |
| for (Iterator<JavaLogicalStructure> iter = fUserDefinedJavaLogicalStructures.iterator(); iter |
| .hasNext();) { |
| JavaLogicalStructure logicalStructure = iter |
| .next(); |
| logicalStructuresString.append( |
| logicalStructure.getQualifiedTypeName()).append('\0'); |
| logicalStructuresString.append(logicalStructure.getDescription()) |
| .append('\0'); |
| logicalStructuresString.append( |
| logicalStructure.isSubtypes() ? IS_SUBTYPE_TRUE |
| : IS_SUBTYPE_FALSE).append('\0'); |
| String value = logicalStructure.getValue(); |
| if (value != null) { |
| logicalStructuresString.append(value); |
| } |
| logicalStructuresString.append('\0'); |
| String[][] variables = logicalStructure.getVariables(); |
| logicalStructuresString.append(variables.length).append('\0'); |
| for (String[] strings : variables) { |
| logicalStructuresString.append(strings[0]).append('\0'); |
| logicalStructuresString.append(strings[1]).append('\0'); |
| } |
| } |
| IEclipsePreferences node = InstanceScope.INSTANCE.getNode(JDIDebugPlugin.getUniqueIdentifier()); |
| if(node != null) { |
| node.put(PREF_JAVA_LOGICAL_STRUCTURES, logicalStructuresString.toString()); |
| try { |
| node.flush(); |
| } catch (BackingStoreException e) { |
| JDIDebugPlugin.log(e); |
| } |
| } |
| } |
| |
| /** |
| * Return all the defined logical structures. |
| */ |
| public static JavaLogicalStructure[] getJavaLogicalStructures() { |
| JavaLogicalStructure[] logicalStructures = new JavaLogicalStructure[fPluginContributedJavaLogicalStructures |
| .size() + fUserDefinedJavaLogicalStructures.size()]; |
| int i = 0; |
| for (Iterator<JavaLogicalStructure> iter = fPluginContributedJavaLogicalStructures.iterator(); iter |
| .hasNext();) { |
| logicalStructures[i++] = iter.next(); |
| } |
| for (Iterator<JavaLogicalStructure> iter = fUserDefinedJavaLogicalStructures.iterator(); iter |
| .hasNext();) { |
| logicalStructures[i++] = iter.next(); |
| } |
| return logicalStructures; |
| } |
| |
| /** |
| * Set the user defined logical structures. |
| */ |
| public static void setUserDefinedJavaLogicalStructures( |
| JavaLogicalStructure[] logicalStructures) { |
| fUserDefinedJavaLogicalStructures = Arrays.asList(logicalStructures); |
| saveUserDefinedJavaLogicalStructures(); |
| } |
| |
| public static void addStructuresListener(IJavaStructuresListener listener) { |
| fListeners.add(listener); |
| } |
| |
| public static void removeStructuresListener(IJavaStructuresListener listener) { |
| fListeners.remove(listener); |
| } |
| |
| @Override |
| public ILogicalStructureType[] getLogicalStructureTypes(IValue value) { |
| if (!(value instanceof IJavaObject)) { |
| return new ILogicalStructureType[0]; |
| } |
| IJavaObject javaValue = (IJavaObject) value; |
| List<JavaLogicalStructure> logicalStructures = new ArrayList<>(); |
| try { |
| IJavaType type = javaValue.getJavaType(); |
| if (!(type instanceof IJavaClassType)) { |
| return new ILogicalStructureType[0]; |
| } |
| IJavaClassType classType = (IJavaClassType) type; |
| List<JavaLogicalStructure> list = fJavaLogicalStructureMap |
| .get(classType.getName()); |
| if (list != null) { |
| logicalStructures.addAll(list); |
| } |
| IJavaClassType superClass = classType.getSuperclass(); |
| while (superClass != null) { |
| addIfIsSubtype(logicalStructures, |
| fJavaLogicalStructureMap.get(superClass |
| .getName())); |
| superClass = superClass.getSuperclass(); |
| } |
| IJavaInterfaceType[] superInterfaces = classType.getAllInterfaces(); |
| for (IJavaInterfaceType superInterface : superInterfaces) { |
| addIfIsSubtype(logicalStructures, |
| fJavaLogicalStructureMap.get(superInterface |
| .getName())); |
| } |
| } catch (DebugException e) { |
| JDIDebugPlugin.log(e); |
| return new ILogicalStructureType[0]; |
| } |
| return logicalStructures |
| .toArray(new ILogicalStructureType[logicalStructures.size()]); |
| } |
| |
| private void addIfIsSubtype(List<JavaLogicalStructure> logicalStructures, List<JavaLogicalStructure> list) { |
| if (list == null) { |
| return; |
| } |
| for(JavaLogicalStructure jls : list) { |
| if (jls.isSubtypes()) { |
| logicalStructures.add(jls); |
| } |
| } |
| } |
| |
| } |