| /******************************************************************************* |
| * Copyright (c) 2004, 2009 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 |
| * QNX Software Systems - Mikhail Khodjaiants - Bug 88232 |
| *******************************************************************************/ |
| package org.eclipse.debug.core.sourcelookup; |
| |
| 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.runtime.CoreException; |
| import org.eclipse.core.runtime.ISafeRunnable; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.MultiStatus; |
| import org.eclipse.core.runtime.SafeRunner; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunch; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationListener; |
| import org.eclipse.debug.core.ILaunchListener; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.debug.core.IStatusHandler; |
| import org.eclipse.debug.core.model.IStackFrame; |
| import org.eclipse.debug.core.sourcelookup.containers.DefaultSourceContainer; |
| import org.eclipse.debug.internal.core.sourcelookup.SourceLookupMessages; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.Node; |
| import org.w3c.dom.NodeList; |
| |
| import com.ibm.icu.text.MessageFormat; |
| |
| /** |
| * Directs source lookup among a collection of source lookup participants, |
| * and a common collection of source containers. |
| * Each source lookup participant is a source locator itself, which allows |
| * more than one source locator to participate in source lookup for a |
| * launch. Each source lookup participant searches for source in the source |
| * containers managed by this director, and each participant is notified |
| * of changes in the source containers (i.e. when the set of source |
| * containers changes). |
| * <p> |
| * When a source director is initialized, it adds it self as a launch listener, |
| * and automatically disposes itself when its associated launch is removed |
| * from the launch manager. If a source director is instantiated by a client |
| * that is not part of a launch, that client is responsible for disposing |
| * the source director. |
| * </p> |
| * <p> |
| * Clients may subclass this class. |
| * </p> |
| * @since 3.0 |
| * @see org.eclipse.debug.core.model.ISourceLocator |
| * @see org.eclipse.debug.core.sourcelookup.ISourceContainer |
| * @see org.eclipse.debug.core.sourcelookup.ISourceContainerType |
| * @see org.eclipse.debug.core.sourcelookup.ISourcePathComputer |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant |
| */ |
| public abstract class AbstractSourceLookupDirector implements ISourceLookupDirector, ILaunchConfigurationListener, ILaunchListener { |
| |
| // source locator type identifier |
| protected String fId; |
| //ISourceLocatorParticipants that are listening for container changes |
| protected ArrayList fParticipants = new ArrayList(); |
| //list of current source containers |
| protected ISourceContainer[] fSourceContainers = null; |
| //the launch config associated with this director |
| protected ILaunchConfiguration fConfig; |
| //whether duplicates should be searched for or not |
| protected boolean fDuplicates = false; |
| // source path computer, or null if default |
| protected ISourcePathComputer fComputer = null; |
| /** |
| * Cache of resolved source elements when duplicates exist. |
| * Keys are the duplicates, values are the source element to use. |
| */ |
| protected Map fResolvedElements = null; |
| // current participant performing lookup or <code>null</code> |
| private ISourceLookupParticipant fCurrentParticipant; |
| |
| protected static final IStatus fPromptStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 200, "", null); //$NON-NLS-1$//$NON-NLS-2$ |
| protected static final IStatus fResolveDuplicatesStatus = new Status(IStatus.INFO, "org.eclipse.debug.ui", 205, "", null); //$NON-NLS-1$//$NON-NLS-2$ |
| |
| // XML nodes & attributes for persistence |
| protected static final String DIRECTOR_ROOT_NODE = "sourceLookupDirector"; //$NON-NLS-1$ |
| protected static final String CONTAINERS_NODE = "sourceContainers"; //$NON-NLS-1$ |
| protected static final String DUPLICATES_ATTR = "duplicates"; //$NON-NLS-1$ |
| protected static final String CONTAINER_NODE = "container"; //$NON-NLS-1$ |
| protected static final String CONTAINER_TYPE_ATTR = "typeId"; //$NON-NLS-1$ |
| protected static final String CONTAINER_MEMENTO_ATTR = "memento"; //$NON-NLS-1$ |
| |
| class SourceLookupQuery implements ISafeRunnable { |
| |
| private List fSourceElements = new ArrayList(); |
| private Object fElement = null; |
| private Throwable fException = null; |
| |
| SourceLookupQuery(Object element) { |
| fElement = element; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.core.runtime.ISafeRunnable#handleException(java.lang.Throwable) |
| */ |
| public void handleException(Throwable exception) { |
| fException = exception; |
| } |
| |
| /** |
| * Returns any exception that occurred during source lookup. |
| * |
| * @return the (any) exception that occured during source lookup |
| */ |
| public Throwable getException() { |
| return fException; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.core.runtime.ISafeRunnable#run() |
| */ |
| public void run() throws Exception { |
| MultiStatus multiStatus = null; |
| CoreException single = null; |
| ISourceLookupParticipant[] participants = getParticipants(); |
| try { |
| for(int i=0; i < participants.length; i++) { |
| setCurrentParticipant(participants[i]); |
| Object[] sourceArray; |
| try { |
| sourceArray = participants[i].findSourceElements(fElement); |
| if (sourceArray !=null && sourceArray.length > 0) { |
| if (isFindDuplicates()) { |
| for(int j=0; j<sourceArray.length; j++) |
| if(!checkDuplicate(sourceArray[j], fSourceElements)) |
| fSourceElements.add(sourceArray[j]); |
| } else { |
| fSourceElements.add(sourceArray[0]); |
| return; |
| } |
| } |
| } catch (CoreException e) { |
| if (single == null) { |
| single = e; |
| } else if (multiStatus == null) { |
| multiStatus = new MultiStatus(DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR, new IStatus[]{single.getStatus()}, SourceLookupMessages.Source_Lookup_Error, null); |
| multiStatus.add(e.getStatus()); |
| } else { |
| multiStatus.add(e.getStatus()); |
| } |
| } |
| } |
| } finally { |
| setCurrentParticipant(null); |
| } |
| if (fSourceElements.isEmpty()) { |
| // set exception if there was one |
| if (multiStatus != null) { |
| fException = new CoreException(multiStatus); |
| } else if (single != null) { |
| fException = single; |
| } |
| } |
| } |
| |
| public List getSourceElements() { |
| return fSourceElements; |
| } |
| |
| public void dispose() { |
| fElement = null; |
| fSourceElements = null; |
| fException = null; |
| } |
| |
| } |
| |
| /** |
| * Constructs source lookup director |
| */ |
| public AbstractSourceLookupDirector() { |
| } |
| |
| /** |
| * Sets the type identifier for this source locator's type |
| * |
| * @param id corresponds to source locator type identifier for a |
| * persistable source locator |
| */ |
| public void setId(String id) { |
| fId = id; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2#dispose() |
| */ |
| public synchronized void dispose() { |
| ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); |
| launchManager.removeLaunchConfigurationListener(this); |
| launchManager.removeLaunchListener(this); |
| Iterator iterator = fParticipants.iterator(); |
| while (iterator.hasNext()) { |
| ISourceLookupParticipant participant = (ISourceLookupParticipant) iterator.next(); |
| //director may also be a participant |
| if(participant != this) |
| participant.dispose(); |
| } |
| fParticipants.clear(); |
| if (fSourceContainers != null) { |
| for (int i = 0; i < fSourceContainers.length; i++) { |
| fSourceContainers[i].dispose(); |
| } |
| } |
| fSourceContainers = null; |
| fResolvedElements = null; |
| } |
| |
| /** |
| * Throws an exception with the given message and underlying exception. |
| * |
| * @param message error message |
| * @param exception underlying exception, or <code>null</code> |
| * @throws CoreException |
| */ |
| protected void abort(String message, Throwable exception) throws CoreException { |
| IStatus status = new Status(IStatus.ERROR, DebugPlugin.getUniqueIdentifier(), DebugPlugin.ERROR, message, exception); |
| throw new CoreException(status); |
| } |
| |
| /** |
| * Constructs source containers from a list of container mementos. |
| * |
| * @param list the list of nodes to be parsed |
| * @exception CoreException if parsing encounters an error |
| * @return a list of source containers |
| */ |
| private List parseSourceContainers(NodeList list) throws CoreException { |
| List containers = new ArrayList(); |
| for (int i=0; i < list.getLength(); i++) { |
| if(!(list.item(i).getNodeType() == Node.ELEMENT_NODE)) |
| continue; |
| Element element = (Element)list.item(i); |
| String typeId = element.getAttribute(CONTAINER_TYPE_ATTR); |
| if (typeId == null || typeId.equals("")) { //$NON-NLS-1$ |
| abort(SourceLookupMessages.AbstractSourceLookupDirector_11, null); |
| } |
| ISourceContainerType type = DebugPlugin.getDefault().getLaunchManager().getSourceContainerType(typeId); |
| if(type != null) { |
| String memento = element.getAttribute(CONTAINER_MEMENTO_ATTR); |
| if (memento == null || memento.equals("")) { //$NON-NLS-1$ |
| abort(SourceLookupMessages.AbstractSourceLookupDirector_13, null); |
| } |
| ISourceContainer container = type.createSourceContainer(memento); |
| containers.add(container); |
| } |
| else { |
| abort(MessageFormat.format(SourceLookupMessages.AbstractSourceLookupDirector_12, new String[]{typeId}), null); |
| } |
| } |
| return containers; |
| } |
| |
| /** |
| * Registers the given source lookup participant. Has no effect if an identical |
| * participant is already registered. Participants receive notification |
| * when the source containers associated with this source director change. |
| * |
| * @param participant the participant to register |
| */ |
| private synchronized void addSourceLookupParticipant(ISourceLookupParticipant participant) { |
| if (!fParticipants.contains(participant)) { |
| fParticipants.add(participant); |
| participant.init(this); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#getSourceContainers() |
| */ |
| public synchronized ISourceContainer[] getSourceContainers() { |
| if (fSourceContainers == null) { |
| return new ISourceContainer[0]; |
| } |
| ISourceContainer[] copy = new ISourceContainer[fSourceContainers.length]; |
| System.arraycopy(fSourceContainers, 0, copy, 0, fSourceContainers.length); |
| return copy; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#isFindDuplicates() |
| */ |
| public boolean isFindDuplicates() { |
| return fDuplicates; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#setFindDuplicates(boolean) |
| */ |
| public void setFindDuplicates(boolean duplicates) { |
| fDuplicates = duplicates; |
| } |
| |
| /** |
| * Removes the given participant from the list of registered participants. |
| * Has no effect if an identical participant is not already registered. |
| * |
| * @param participant the participant to remove |
| */ |
| private synchronized void removeSourceLookupParticipant(ISourceLookupParticipant participant) { |
| if (fParticipants.remove(participant)) { |
| participant.dispose(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationAdded(org.eclipse.debug.core.ILaunchConfiguration) |
| */ |
| public void launchConfigurationAdded(ILaunchConfiguration configuration) { |
| ILaunchConfiguration from = DebugPlugin.getDefault().getLaunchManager().getMovedFrom(configuration); |
| if (from != null && from.equals(getLaunchConfiguration())) { |
| fConfig = configuration; |
| } |
| } |
| |
| /* (non-Javadoc) |
| * |
| * Updates source containers in response to changes in underlying launch |
| * configuration. Only responds to changes in non-working copies. |
| * |
| * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationChanged(org.eclipse.debug.core.ILaunchConfiguration) |
| */ |
| public void launchConfigurationChanged(ILaunchConfiguration configuration) { |
| if (fConfig == null || configuration.isWorkingCopy()) { |
| return; |
| } |
| if(fConfig.equals(configuration)) { |
| try{ |
| String locatorMemento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO,(String)null); |
| if (locatorMemento == null) { |
| initializeDefaults(configuration); |
| } else { |
| initializeFromMemento(locatorMemento, configuration); |
| } |
| } catch (CoreException e){ |
| } |
| } |
| } |
| |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.ILaunchConfigurationListener#launchConfigurationRemoved(org.eclipse.debug.core.ILaunchConfiguration) |
| */ |
| public void launchConfigurationRemoved(ILaunchConfiguration configuration) { |
| if (configuration.equals(getLaunchConfiguration())) { |
| if (DebugPlugin.getDefault().getLaunchManager().getMovedTo(configuration) == null) { |
| fConfig = null; |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.IPersistableSourceLocator#getMemento() |
| */ |
| public synchronized String getMemento() throws CoreException { |
| Document doc = DebugPlugin.newDocument(); |
| Element rootNode = doc.createElement(DIRECTOR_ROOT_NODE); |
| doc.appendChild(rootNode); |
| |
| Element pathNode = doc.createElement(CONTAINERS_NODE); |
| if(fDuplicates) { |
| pathNode.setAttribute(DUPLICATES_ATTR, "true"); //$NON-NLS-1$ |
| } else { |
| pathNode.setAttribute(DUPLICATES_ATTR, "false"); //$NON-NLS-1$ |
| } |
| rootNode.appendChild(pathNode); |
| if(fSourceContainers !=null){ |
| for(int i=0; i<fSourceContainers.length; i++){ |
| Element node = doc.createElement(CONTAINER_NODE); |
| ISourceContainer container = fSourceContainers[i]; |
| ISourceContainerType type = container.getType(); |
| node.setAttribute(CONTAINER_TYPE_ATTR, type.getId()); |
| node.setAttribute(CONTAINER_MEMENTO_ATTR, type.getMemento(container)); |
| pathNode.appendChild(node); |
| } |
| } |
| return DebugPlugin.serializeDocument(doc); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeFromMemento(java.lang.String) |
| */ |
| public void initializeFromMemento(String memento) throws CoreException { |
| doInitializeFromMemento(memento, true); |
| } |
| |
| /** |
| * Initializes this source lookup director from the given memento. |
| * Disposes itself before initialization if specified. |
| * |
| * @param memento source locator memento |
| * @param dispose whether to dispose any current source containers and participants |
| * before initializing |
| * @throws CoreException if an exception occurs during initialization |
| * @since 3.1 |
| */ |
| protected void doInitializeFromMemento(String memento, boolean dispose) throws CoreException { |
| if (dispose) { |
| dispose(); |
| } |
| Element rootElement = DebugPlugin.parseDocument(memento); |
| if (!rootElement.getNodeName().equalsIgnoreCase(DIRECTOR_ROOT_NODE)) { |
| abort(SourceLookupMessages.AbstractSourceLookupDirector_14, null); |
| } |
| NodeList list = rootElement.getChildNodes(); |
| int length = list.getLength(); |
| for (int i = 0; i < length; ++i) { |
| Node node = list.item(i); |
| short type = node.getNodeType(); |
| if (type == Node.ELEMENT_NODE) { |
| Element entry = (Element) node; |
| if(entry.getNodeName().equalsIgnoreCase(CONTAINERS_NODE)){ |
| setFindDuplicates("true".equals(entry.getAttribute(DUPLICATES_ATTR))); //$NON-NLS-1$ |
| NodeList children = entry.getChildNodes(); |
| List containers = parseSourceContainers(children); |
| setSourceContainers((ISourceContainer[]) containers.toArray(new ISourceContainer[containers.size()])); |
| } |
| } |
| } |
| initializeParticipants(); |
| } |
| |
| /** |
| * Sets the source containers used by this source lookup |
| * director. |
| * |
| * @param containers source containers to search |
| */ |
| public void setSourceContainers(ISourceContainer[] containers) { |
| synchronized (this) { |
| List list = Arrays.asList( containers ); |
| ISourceContainer[] old = getSourceContainers(); |
| for (int i = 0; i < old.length; i++) { |
| // skip overlapping containers |
| if (!list.contains(old[i])) |
| old[i].dispose(); |
| } |
| fSourceContainers = containers; |
| for (int i = 0; i < containers.length; i++) { |
| ISourceContainer container = containers[i]; |
| container.init(this); |
| } |
| } |
| // clear resolved duplicates |
| fResolvedElements = null; |
| // notify participants |
| ISourceLookupParticipant[] participants = getParticipants(); |
| for (int i = 0; i < participants.length; i++) { |
| ISourceLookupParticipant participant = participants[i]; |
| participant.sourceContainersChanged(this); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.ISourceLocator#getSourceElement(org.eclipse.debug.core.model.IStackFrame) |
| * Would be better to accept Object so this can be used for breakpoints and other objects. |
| */ |
| public Object getSourceElement(IStackFrame stackFrame) { |
| return getSourceElement((Object)stackFrame); |
| } |
| |
| /** |
| * Performs a source lookup query for the given element |
| * returning the source elements associated with the element. |
| * |
| * @param element stack frame |
| * @return list of associated source elements |
| */ |
| protected List doSourceLookup(Object element) { |
| SourceLookupQuery query = new SourceLookupQuery(element); |
| SafeRunner.run(query); |
| List sources = query.getSourceElements(); |
| Throwable exception = query.getException(); |
| if (exception != null) { |
| if (exception instanceof CoreException) { |
| CoreException ce = (CoreException) exception; |
| if (ce.getStatus().getSeverity() == IStatus.ERROR) { |
| DebugPlugin.log(ce); |
| } |
| } else { |
| DebugPlugin.log(exception); |
| } |
| } |
| query.dispose(); |
| return sources; |
| } |
| |
| /** |
| * Returns the source element to associate with the given element. |
| * This method is called when more than one source element has been found |
| * for an element, and allows the source director to select a single |
| * source element to associate with the element. |
| * <p> |
| * Subclasses should override this method as appropriate. For example, |
| * to prompt the user to choose a source element. |
| * </p> |
| * @param element the debug artifact for which source is being searched for |
| * @param sources the source elements found for the given element |
| * @return a single source element for the given element |
| */ |
| public Object resolveSourceElement(Object element, List sources) { |
| // check the duplicates cache first |
| Iterator duplicates = sources.iterator(); |
| while (duplicates.hasNext()) { |
| Object dup = duplicates.next(); |
| Object resolved = getCachedElement(dup); |
| if (resolved != null) { |
| return resolved; |
| } |
| } |
| // consult a status handler |
| IStatusHandler prompter = DebugPlugin.getDefault().getStatusHandler(fPromptStatus); |
| if (prompter != null) { |
| try { |
| Object result = prompter.handleStatus(fResolveDuplicatesStatus, new Object[]{element, sources}); |
| if (result != null) { |
| cacheResolvedElement(sources, result); |
| return result; |
| } |
| } catch (CoreException e) { |
| } |
| } |
| return sources.get(0); |
| } |
| |
| /** |
| * Checks if the object being added to the list of sources is a duplicate of what's already in the list |
| * @param sourceToAdd the new source file to be added |
| * @param sources the list that the source will be compared against |
| * @return true if it is already in the list, false if it is a new object |
| */ |
| private boolean checkDuplicate(Object sourceToAdd, List sources){ |
| if(sources.size() == 0) |
| return false; |
| Iterator iterator = sources.iterator(); |
| while(iterator.hasNext()) |
| if(iterator.next().equals(sourceToAdd)) |
| return true; |
| return false; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.IPersistableSourceLocator2#initializeFromMemento(java.lang.String, org.eclipse.debug.core.ILaunchConfiguration) |
| */ |
| public void initializeFromMemento(String memento, ILaunchConfiguration configuration) throws CoreException { |
| dispose(); |
| setLaunchConfiguration(configuration); |
| doInitializeFromMemento(memento, false); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.model.IPersistableSourceLocator#initializeDefaults(org.eclipse.debug.core.ILaunchConfiguration) |
| */ |
| public void initializeDefaults(ILaunchConfiguration configuration) throws CoreException { |
| dispose(); |
| setLaunchConfiguration(configuration); |
| setSourceContainers(new ISourceContainer[]{new DefaultSourceContainer()}); |
| initializeParticipants(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#getLaunchConfiguration() |
| */ |
| public ILaunchConfiguration getLaunchConfiguration() { |
| return fConfig; |
| } |
| |
| /** |
| * Sets the launch configuration associated with this source lookup |
| * director. If the given configuration is a working copy, this director |
| * will respond to changes the working copy. If the given configuration |
| * is a persisted launch configuration, this director will respond to changes |
| * in the persisted launch configuration. |
| * |
| * @param configuration launch configuration to associate with this |
| * source lookup director, or <code>null</code> if none |
| */ |
| protected void setLaunchConfiguration(ILaunchConfiguration configuration) { |
| fConfig = configuration; |
| ILaunchManager launchManager = DebugPlugin.getDefault().getLaunchManager(); |
| launchManager.addLaunchConfigurationListener(this); |
| launchManager.addLaunchListener(this); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.ILaunchListener#launchAdded(org.eclipse.debug.core.ILaunch) |
| */ |
| public void launchAdded(ILaunch launch) { |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.ILaunchListener#launchChanged(org.eclipse.debug.core.ILaunch) |
| */ |
| public void launchChanged(ILaunch launch) { |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.ILaunchListener#launchRemoved(org.eclipse.debug.core.ILaunch) |
| */ |
| public void launchRemoved(ILaunch launch) { |
| if (this.equals(launch.getSourceLocator())) { |
| dispose(); |
| } |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#getParticipants() |
| */ |
| public synchronized ISourceLookupParticipant[] getParticipants() { |
| return (ISourceLookupParticipant[]) fParticipants.toArray(new ISourceLookupParticipant[fParticipants.size()]); |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#supportsSourceContainerType(org.eclipse.debug.core.sourcelookup.ISourceContainerType) |
| */ |
| public boolean supportsSourceContainerType(ISourceContainerType type) { |
| return true; |
| } |
| |
| /** |
| * Caches the resolved source element to use when one of the following |
| * duplicates is found. |
| * |
| * @param duplicates duplicates source elements |
| * @param sourceElement chosen source element to use in place of the |
| * duplicates |
| */ |
| protected void cacheResolvedElement(List duplicates, Object sourceElement) { |
| if (fResolvedElements == null) { |
| fResolvedElements = new HashMap(10); |
| } |
| Iterator iterator = duplicates.iterator(); |
| while (iterator.hasNext()) { |
| Object dup = iterator.next(); |
| fResolvedElements.put(dup, sourceElement); |
| } |
| |
| } |
| |
| /** |
| * Returns the cached source element to use when the given duplicate |
| * is encountered. |
| * |
| * @param duplicate duplicates source element |
| * @return element to use in the duplicate's place |
| */ |
| protected Object getCachedElement(Object duplicate) { |
| if (fResolvedElements != null) { |
| return fResolvedElements.get(duplicate); |
| } |
| return null; |
| } |
| |
| /** |
| * Clears any cached source element associated with the given duplicate |
| * is source element. |
| * |
| * @param duplicate duplicate source element to cache resolved results |
| * for |
| */ |
| protected void clearCachedElement(Object duplicate) { |
| if (fResolvedElements != null) { |
| fResolvedElements.remove(duplicate); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#clearSourceElements(java.lang.Object) |
| */ |
| public void clearSourceElements(Object element) { |
| List list = doSourceLookup(element); |
| if (list.size() > 0) { |
| Iterator iterator = list.iterator(); |
| while (iterator.hasNext()) { |
| clearCachedElement(iterator.next()); |
| } |
| } |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#addParticipants(org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant[]) |
| */ |
| public void addParticipants(ISourceLookupParticipant[] participants) { |
| for (int i = 0; i < participants.length; i++) { |
| ISourceLookupParticipant participant = participants[i]; |
| addSourceLookupParticipant(participant); |
| participant.sourceContainersChanged(this); |
| } |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#removeParticipants(org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant[]) |
| */ |
| public void removeParticipants(ISourceLookupParticipant[] participants) { |
| for (int i = 0; i < participants.length; i++) { |
| removeSourceLookupParticipant(participants[i]); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#getId() |
| */ |
| public String getId() { |
| return fId; |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#getSourcePathComputer() |
| */ |
| public ISourcePathComputer getSourcePathComputer() { |
| if (fComputer == null && getLaunchConfiguration() != null) { |
| try { |
| return DebugPlugin.getDefault().getLaunchManager().getSourcePathComputer(getLaunchConfiguration()); |
| } catch (CoreException e) { |
| } |
| } |
| return fComputer; |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#setSourcePathComputer(org.eclipse.debug.core.sourcelookup.ISourcePathComputer) |
| */ |
| public void setSourcePathComputer(ISourcePathComputer computer) { |
| fComputer = computer; |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#findSourceElements(java.lang.Object) |
| */ |
| public Object[] findSourceElements(Object object) throws CoreException { |
| SourceLookupQuery query = new SourceLookupQuery(object); |
| SafeRunner.run(query); |
| List sources = query.getSourceElements(); |
| Throwable exception = query.getException(); |
| query.dispose(); |
| if (exception != null && sources.isEmpty()) { |
| if (exception instanceof CoreException) { |
| throw (CoreException)exception; |
| } |
| abort(SourceLookupMessages.AbstractSourceLookupDirector_10, exception); |
| } |
| return sources.toArray(); |
| } |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.core.sourcelookup.ISourceLookupDirector#getSourceElement(java.lang.Object) |
| */ |
| public Object getSourceElement(Object element) { |
| List sources = doSourceLookup(element); |
| if(sources.size() == 1) { |
| return sources.get(0); |
| } else if(sources.size() > 1) { |
| return resolveSourceElement(element, sources); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Sets the current participant or <code>null</code> if none. |
| * |
| * @param participant active participant or <code>null</code> |
| */ |
| private void setCurrentParticipant(ISourceLookupParticipant participant) { |
| fCurrentParticipant = participant; |
| } |
| |
| /** |
| * Returns the participant currently looking up source or <code>null</code> |
| * if none. |
| * |
| * @return the participant currently looking up source or <code>null</code> |
| * if none |
| * @since 3.5 |
| */ |
| public ISourceLookupParticipant getCurrentParticipant() { |
| return fCurrentParticipant; |
| } |
| } |