blob: e5a28922f949e550b98a876540a8283902ba7c25 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2004, 2007 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 com.ibm.icu.text.MessageFormat;
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;
/**
* 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;
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();
for(int i=0; i < participants.length; 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());
}
}
}
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) {
abort(MessageFormat.format(SourceLookupMessages.AbstractSourceLookupDirector_12, new String[]{typeId}), 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);
}
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();
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;
}
}
}