| /* |
| *(c) Copyright QNX Software Systems Ltd. 2002. |
| * All Rights Reserved. |
| * |
| */ |
| package org.eclipse.cdt.debug.internal.core.sourcelookup; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.text.MessageFormat; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.LinkedList; |
| |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import org.apache.xerces.dom.DocumentImpl; |
| import org.eclipse.cdt.debug.core.CDebugCorePlugin; |
| import org.eclipse.cdt.debug.core.CDebugUtils; |
| import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation; |
| import org.eclipse.cdt.debug.core.sourcelookup.IProjectSourceLocation; |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceProxy; |
| import org.eclipse.core.resources.IResourceProxyVisitor; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IPath; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.core.runtime.Status; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * |
| * Locates source elements in a Java project. Returns instances of <code>IFile</code>. |
| * |
| * @since Sep 23, 2002 |
| */ |
| public class CProjectSourceLocation implements IProjectSourceLocation |
| { |
| private static final String ELEMENT_NAME = "cProjectSourceLocation"; |
| private static final String ATTR_PROJECT = "project"; |
| private static final String ATTR_GENERIC = "generic"; |
| |
| /** |
| * The project associated with this source location |
| */ |
| private IProject fProject; |
| |
| private IResource[] fFolders; |
| |
| private HashMap fCache = new HashMap( 20 ); |
| |
| private HashSet fNotFoundCache = new HashSet( 20 ); |
| |
| private boolean fGenerated = true; |
| |
| private boolean fSearchForDuplicateFiles = false; |
| |
| /** |
| * Constructor for CProjectSourceLocation. |
| */ |
| public CProjectSourceLocation() |
| { |
| } |
| |
| /** |
| * Constructor for CProjectSourceLocation. |
| */ |
| public CProjectSourceLocation( IProject project ) |
| { |
| setProject( project ); |
| fGenerated = true; |
| } |
| |
| /** |
| * Constructor for CProjectSourceLocation. |
| */ |
| public CProjectSourceLocation( IProject project, boolean generated ) |
| { |
| setProject( project ); |
| fGenerated = generated; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation#findSourceElement(String) |
| */ |
| public Object findSourceElement( String name ) throws CoreException |
| { |
| Object result = null; |
| if ( !isEmpty( name ) && getProject() != null && !notFoundCacheLookup( name ) ) |
| { |
| result = cacheLookup( name ); |
| if ( result == null ) |
| { |
| result = doFindSourceElement( name ); |
| if ( result != null ) |
| { |
| cacheSourceElement( name, result ); |
| } |
| } |
| if ( result == null ) |
| { |
| cacheNotFound( name ); |
| } |
| } |
| return result; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.core.runtime.IAdaptable#getAdapter(Class) |
| */ |
| public Object getAdapter( Class adapter ) |
| { |
| if ( adapter.equals( ICSourceLocation.class ) ) |
| return this; |
| if ( adapter.equals( CProjectSourceLocation.class ) ) |
| return this; |
| if ( adapter.equals( IProject.class ) ) |
| return getProject(); |
| return null; |
| } |
| |
| /** |
| * Sets the project in which source elements will be searched for. |
| * |
| * @param project the project |
| */ |
| private void setProject( IProject project ) |
| { |
| fProject = project; |
| } |
| |
| /** |
| * Returns the project associated with this source location. |
| * |
| * @return project |
| */ |
| public IProject getProject() |
| { |
| return fProject; |
| } |
| |
| private Object doFindSourceElement( String name ) |
| { |
| File file = new File( name ); |
| return ( file.isAbsolute() ) ? findFileByAbsolutePath( file ) : findFileByRelativePath( name ); |
| } |
| |
| private Object findFileByAbsolutePath( File file ) |
| { |
| LinkedList list = new LinkedList(); |
| if ( file.exists() ) |
| { |
| IPath path = new Path( file.getAbsolutePath() ); |
| IFile[] wsFiles = CDebugCorePlugin.getWorkspace().getRoot().findFilesForLocation( path ); |
| for ( int i = 0; i < wsFiles.length; ++i ) |
| if ( wsFiles[i].getProject().equals( getProject() ) && wsFiles[i].exists() ) |
| if ( !searchForDuplicateFiles() ) |
| return wsFiles[i]; |
| else |
| list.add( wsFiles[i] ); |
| } |
| return ( list.size() > 0 ) ? ( ( list.size() == 1 ) ? list.getFirst() : list ) : null; |
| } |
| |
| private Object findFileByRelativePath( String fileName ) |
| { |
| IResource[] folders = getFolders(); |
| LinkedList list = new LinkedList(); |
| for ( int i = 0; i < folders.length; ++i ) |
| { |
| if ( list.size() > 0 && !searchForDuplicateFiles() ) |
| break; |
| IPath path = folders[i].getLocation().append( fileName ); |
| File file = new File( path.toOSString() ); |
| if ( file.exists() ) |
| { |
| IFile[] wsFiles = CDebugCorePlugin.getWorkspace().getRoot().findFilesForLocation( path ); |
| for ( int j = 0; j < wsFiles.length; ++j ) |
| if ( wsFiles[j].exists() ) |
| if ( !searchForDuplicateFiles() ) |
| return wsFiles[j]; |
| else |
| list.add( wsFiles[j] ); |
| } |
| } |
| return ( list.size() > 0 ) ? ( ( list.size() == 1 ) ? list.getFirst() : list ) : null; |
| } |
| |
| private Object cacheLookup( String name ) |
| { |
| return fCache.get( name ); |
| } |
| |
| private boolean notFoundCacheLookup( String name ) |
| { |
| return fNotFoundCache.contains( name ); |
| } |
| |
| private void cacheSourceElement( String name, Object element ) |
| { |
| fCache.put( name, element ); |
| } |
| |
| private void cacheNotFound( String name ) |
| { |
| fNotFoundCache.add( name ); |
| } |
| |
| public void dispose() |
| { |
| fCache.clear(); |
| fNotFoundCache.clear(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation#getMemento() |
| */ |
| public String getMemento() throws CoreException |
| { |
| Document doc = new DocumentImpl(); |
| Element node = doc.createElement( ELEMENT_NAME ); |
| doc.appendChild( node ); |
| node.setAttribute( ATTR_PROJECT, getProject().getName() ); |
| node.setAttribute( ATTR_GENERIC, new Boolean( isGeneric() ).toString() ); |
| try |
| { |
| return CDebugUtils.serializeDocument( doc, " " ); |
| } |
| catch( IOException e ) |
| { |
| abort( MessageFormat.format( "Unable to create memento for C/C++ project source location {0}.", new String[] { getProject().getName() } ), e ); |
| } |
| // execution will not reach here |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation#initializeFrom(java.lang.String) |
| */ |
| public void initializeFrom( String memento ) throws CoreException |
| { |
| Exception ex = null; |
| try |
| { |
| Element root = null; |
| DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder(); |
| StringReader reader = new StringReader( memento ); |
| InputSource source = new InputSource( reader ); |
| root = parser.parse( source ).getDocumentElement(); |
| |
| String name = root.getAttribute( ATTR_PROJECT ); |
| if ( isEmpty( name ) ) |
| { |
| abort( "Unable to initialize source location - missing project name", null ); |
| } |
| else |
| { |
| IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject( name ); |
| setProject( project ); |
| } |
| String isGeneric = root.getAttribute( ATTR_GENERIC ); |
| if ( isGeneric == null || isGeneric.trim().length() == 0 ) |
| isGeneric = Boolean.FALSE.toString(); |
| setGenerated( isGeneric.equals( Boolean.TRUE.toString() ) ); |
| return; |
| } |
| catch( ParserConfigurationException e ) |
| { |
| ex = e; |
| } |
| catch( SAXException e ) |
| { |
| ex = e; |
| } |
| catch( IOException e ) |
| { |
| ex = e; |
| } |
| abort( "Exception occurred initializing source location.", ex ); |
| } |
| |
| /** |
| * Throws an internal error exception |
| */ |
| private void abort( String message, Throwable e ) throws CoreException |
| { |
| IStatus s = new Status( IStatus.ERROR, |
| CDebugCorePlugin.getUniqueIdentifier(), |
| CDebugCorePlugin.INTERNAL_ERROR, |
| message, |
| e ); |
| throw new CoreException( s ); |
| } |
| |
| private boolean isEmpty( String string ) |
| { |
| return string == null || string.length() == 0; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.core.sourcelookup.IProjectSourceLocation#isGenerated() |
| */ |
| public boolean isGeneric() |
| { |
| return fGenerated; |
| } |
| |
| public void setGenerated( boolean b ) |
| { |
| fGenerated = b; |
| } |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#equals(java.lang.Object) |
| */ |
| public boolean equals( Object obj ) |
| { |
| if ( obj instanceof IProjectSourceLocation && getProject() != null ) |
| return getProject().equals( ((IProjectSourceLocation)obj).getProject() ); |
| return false; |
| } |
| |
| private void initializeFolders() |
| { |
| final LinkedList list = new LinkedList(); |
| if ( getProject() != null ) |
| { |
| list.add( getProject() ); |
| try |
| { |
| getProject().accept( |
| new IResourceProxyVisitor() |
| { |
| public boolean visit( IResourceProxy proxy ) throws CoreException |
| { |
| switch( proxy.getType() ) |
| { |
| case IResource.FILE: |
| return false; |
| case IResource.FOLDER: |
| list.addLast( proxy.requestResource() ); |
| return true; |
| } |
| return true; |
| } |
| |
| }, |
| IResource.NONE ); |
| } |
| catch( CoreException e ) |
| { |
| } |
| } |
| fFolders = (IResource[])list.toArray( new IResource[list.size()] ); |
| } |
| |
| protected IResource[] getFolders() |
| { |
| if ( fFolders == null ) |
| initializeFolders(); |
| return fFolders; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation#searchForDuplicateFiles() |
| */ |
| public boolean searchForDuplicateFiles() |
| { |
| return fSearchForDuplicateFiles; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocation#setSearchForDuplicateFiles(boolean) |
| */ |
| public void setSearchForDuplicateFiles( boolean search ) |
| { |
| fCache.clear(); |
| fNotFoundCache.clear(); |
| fSearchForDuplicateFiles = search; |
| } |
| |
| public String toString() |
| { |
| return ( getProject() != null ) ? fProject.toString() : ""; |
| } |
| } |