<s> package org . eclipse . jdt . internal . core ; import java . io . File ; import java . io . FileOutputStream ; import java . io . IOException ; import java . util . ArrayList ; import java . util . Collection ; import java . util . Collections ; import java . util . HashMap ; import java . util . HashSet ; import java . util . Iterator ; import java . util . Map ; import java . util . Set ; import java . util . Vector ; import org . eclipse . core . resources . IFolder ; import org . eclipse . core . resources . IProject ; import org . eclipse . core . resources . IProjectDescription ; import org . eclipse . core . resources . IResource ; import org . eclipse . core . resources . IResourceStatus ; import org . eclipse . core . resources . ResourcesPlugin ; import org . eclipse . core . runtime . CoreException ; import org . eclipse . core . runtime . IPath ; import org . eclipse . core . runtime . IProgressMonitor ; import org . eclipse . core . runtime . IStatus ; import org . eclipse . core . runtime . Status ; import org . eclipse . core . runtime . jobs . Job ; import org . eclipse . jdt . core . IClasspathEntry ; import org . eclipse . jdt . core . JavaCore ; import org . eclipse . jdt . core . JavaModelException ; import org . eclipse . jdt . internal . core . util . Messages ; import org . eclipse . jdt . internal . core . util . Util ; public class ExternalFoldersManager { private static final String EXTERNAL_PROJECT_NAME = "" ; private static final String LINKED_FOLDER_NAME = ".link" ; private Map folders ; private Set pendingFolders ; private int counter = 0 ; private static ExternalFoldersManager MANAGER = new ExternalFoldersManager ( ) ; private ExternalFoldersManager ( ) { } public static ExternalFoldersManager getExternalFoldersManager ( ) { return MANAGER ; } public static HashSet getExternalFolders ( IClasspathEntry [ ] classpath ) { if ( classpath == null ) return null ; HashSet folders = null ; for ( int i = 0 ; i < classpath . length ; i ++ ) { IClasspathEntry entry = classpath [ i ] ; if ( entry . getEntryKind ( ) == IClasspathEntry . CPE_LIBRARY ) { IPath entryPath = entry . getPath ( ) ; if ( isExternalFolderPath ( entryPath ) ) { if ( folders == null ) folders = new HashSet ( ) ; folders . add ( entryPath ) ; } IPath attachmentPath = entry . getSourceAttachmentPath ( ) ; if ( isExternalFolderPath ( attachmentPath ) ) { if ( folders == null ) folders = new HashSet ( ) ; folders . add ( attachmentPath ) ; } } } return folders ; } public static boolean isExternalFolderPath ( IPath externalPath ) { if ( externalPath == null ) return false ; String firstSegment = externalPath . segment ( 0 ) ; if ( firstSegment != null && ResourcesPlugin . getWorkspace ( ) . getRoot ( ) . getProject ( firstSegment ) . exists ( ) ) return false ; File externalFolder = externalPath . toFile ( ) ; if ( externalFolder . isFile ( ) ) return false ; if ( externalPath . getFileExtension ( ) != null && ! externalFolder . exists ( ) ) return false ; return true ; } public static boolean isInternalPathForExternalFolder ( IPath resourcePath ) { return EXTERNAL_PROJECT_NAME . equals ( resourcePath . segment ( 0 ) ) ; } public IFolder addFolder ( IPath externalFolderPath , boolean scheduleForCreation ) { return addFolder ( externalFolderPath , getExternalFoldersProject ( ) , scheduleForCreation ) ; } private IFolder addFolder ( IPath externalFolderPath , IProject externalFoldersProject , boolean scheduleForCreation ) { Map knownFolders = getFolders ( ) ; Object existing = knownFolders . get ( externalFolderPath ) ; if ( existing != null ) { return ( IFolder ) existing ; } IFolder result ; do { result = externalFoldersProject . getFolder ( LINKED_FOLDER_NAME + this . counter ++ ) ; } while ( result . exists ( ) ) ; if ( scheduleForCreation ) { if ( this . pendingFolders == null ) this . pendingFolders = new HashSet ( ) ; this . pendingFolders . add ( externalFolderPath ) ; } knownFolders . put ( externalFolderPath , result ) ; return result ; } public boolean removePendingFolder ( Object externalPath ) { if ( this . pendingFolders == null ) return false ; return this . pendingFolders . remove ( externalPath ) ; } public IFolder createLinkFolder ( IPath externalFolderPath , boolean refreshIfExistAlready , IProgressMonitor monitor ) throws CoreException { IProject externalFoldersProject = createExternalFoldersProject ( monitor ) ; return createLinkFolder ( externalFolderPath , refreshIfExistAlready , externalFoldersProject , monitor ) ; } private IFolder createLinkFolder ( IPath externalFolderPath , boolean refreshIfExistAlready , IProject externalFoldersProject , IProgressMonitor monitor ) throws CoreException { IFolder result = addFolder ( externalFolderPath , externalFoldersProject , false ) ; if ( ! result . exists ( ) ) result . createLink ( externalFolderPath , IResource . ALLOW_MISSING_LOCAL , monitor ) ; else if ( refreshIfExistAlready ) result . refreshLocal ( IResource . DEPTH_INFINITE , monitor ) ; return result ; } public void createPendingFolders ( IProgressMonitor monitor ) throws JavaModelException { if ( this . pendingFolders == null || this . pendingFolders . isEmpty ( ) ) return ; IProject externalFoldersProject = null ; try { externalFoldersProject = createExternalFoldersProject ( monitor ) ; } catch ( CoreException e ) { throw new JavaModelException ( e ) ; } Iterator iterator = this . pendingFolders . iterator ( ) ; while ( iterator . hasNext ( ) ) { Object folderPath = iterator . next ( ) ; try { createLinkFolder ( ( IPath ) folderPath , false , externalFoldersProject , monitor ) ; } catch ( CoreException e ) { Util . log ( e , "" + folderPath ) ; } } this . pendingFolders . clear ( ) ; } public void cleanUp ( IProgressMonitor monitor ) throws CoreException { ArrayList toDelete = getFoldersToCleanUp ( monitor ) ; if ( toDelete == null ) return ; for ( Iterator iterator = toDelete . iterator ( ) ; iterator . hasNext ( ) ; ) { Map . Entry entry = ( Map . Entry ) iterator . next ( ) ; IFolder folder = ( IFolder ) entry . getValue ( ) ; folder . delete ( true , monitor ) ; IPath key = ( IPath ) entry . getKey ( ) ; this . folders . remove ( key ) ; } IProject project = getExternalFoldersProject ( ) ; if ( project . isAccessible ( ) && project . members ( ) . length == 1 ) project . delete ( true , monitor ) ; } private ArrayList getFoldersToCleanUp ( IProgressMonitor monitor ) throws CoreException { DeltaProcessingState state = JavaModelManager . getDeltaState ( ) ; HashMap roots = state . roots ; HashMap sourceAttachments = state . sourceAttachments ; if ( roots == null && sourceAttachments == null ) return null ; Map knownFolders = getFolders ( ) ; ArrayList result = null ; synchronized ( knownFolders ) { Iterator iterator = knownFolders . entrySet ( ) . iterator ( ) ; while ( iterator . hasNext ( ) ) { Map . Entry entry = ( Map . Entry ) iterator . next ( ) ; IPath path = ( IPath ) entry . getKey ( ) ; if ( ( roots != null && ! roots . containsKey ( path ) ) && ( sourceAttachments != null && ! sourceAttachments . containsKey ( path ) ) ) { if ( entry . getValue ( ) != null ) { if ( result == null ) result = new ArrayList ( ) ; result . add ( entry ) ; } } } } return result ; } public IProject getExternalFoldersProject ( ) { return ResourcesPlugin . getWorkspace ( ) . getRoot ( ) . getProject ( EXTERNAL_PROJECT_NAME ) ; } public IProject createExternalFoldersProject ( IProgressMonitor monitor ) throws CoreException { IProject project = getExternalFoldersProject ( ) ; if ( ! project . isAccessible ( ) ) { if ( ! project . exists ( ) ) { createExternalFoldersProject ( project , monitor ) ; } openExternalFoldersProject ( project , monitor ) ; } return project ; } private void openExternalFoldersProject ( IProject project , IProgressMonitor monitor ) throws CoreException { try { project . open ( monitor ) ; } catch ( CoreException e1 ) { if ( e1 . getStatus ( ) . getCode ( ) == IResourceStatus . FAILED_READ_METADATA ) { project . delete ( false , true , monitor ) ; createExternalFoldersProject ( project , monitor ) ; } else { IPath stateLocation = JavaCore . getPlugin ( ) . getStateLocation ( ) ; IPath projectPath = stateLocation . append ( EXTERNAL_PROJECT_NAME ) ; projectPath . toFile ( ) . mkdirs ( ) ; try { FileOutputStream output = new FileOutputStream ( projectPath . append ( ".project" ) . toOSString ( ) ) ; try { output . write ( ( "" + "" + "t<name>" + EXTERNAL_PROJECT_NAME + "</name>n" + "" + "t<projects>n" + "" + "" + "" + "t<natures>n" + "t</natures>n" + "" ) . getBytes ( ) ) ; } finally { output . close ( ) ; } } catch ( IOException e ) { project . delete ( false , true , monitor ) ; createExternalFoldersProject ( project , monitor ) ; } } project . open ( monitor ) ; } } private void createExternalFoldersProject ( IProject project , IProgressMonitor monitor ) throws CoreException { IProjectDescription desc = project . getWorkspace ( ) . newProjectDescription ( project . getName ( ) ) ; IPath stateLocation = JavaCore . getPlugin ( ) . getStateLocation ( ) ; desc . setLocation ( stateLocation . append ( EXTERNAL_PROJECT_NAME ) ) ; project . create ( desc , IResource . HIDDEN , monitor ) ; } public IFolder getFolder ( IPath externalFolderPath ) { return ( IFolder ) getFolders ( ) . get ( externalFolderPath ) ; } private Map getFolders ( ) { if ( this . folders == null ) { Map tempFolders = new HashMap ( ) ; IProject project = getExternalFoldersProject ( ) ; try { if ( ! project . isAccessible ( ) ) { if ( project . exists ( ) ) { openExternalFoldersProject ( project , null ) ; } else { return this . folders = Collections . synchronizedMap ( tempFolders ) ; } } IResource [ ] members = project . members ( ) ; for ( int i = 0 , length = members . length ; i < length ; i ++ ) { IResource member = members [ i ] ; if ( member . getType ( ) == IResource . FOLDER && member . isLinked ( ) && member . getName ( ) . startsWith ( LINKED_FOLDER_NAME ) ) { IPath externalFolderPath = member . getLocation ( ) ; tempFolders . put ( externalFolderPath , member ) ; } } } catch ( CoreException e ) { Util . log ( e , "" ) ; } this . folders = Collections . synchronizedMap ( tempFolders ) ; } return this . folders ; } private void runRefreshJob ( Collection paths ) { Job [ ] jobs = Job . getJobManager ( ) . find ( ResourcesPlugin . FAMILY_MANUAL_REFRESH ) ; RefreshJob refreshJob = null ; if ( jobs != null ) { for ( int index = 0 ; index < jobs . length ; index ++ ) { if ( jobs [ index ] instanceof RefreshJob ) { refreshJob = ( RefreshJob ) jobs [ index ] ; refreshJob . addFoldersToRefresh ( paths ) ; if ( refreshJob . getState ( ) == Job . NONE ) { refreshJob . schedule ( ) ; } break ; } } } if ( refreshJob == null ) { refreshJob = new RefreshJob ( new Vector ( paths ) ) ; refreshJob . schedule ( ) ; } } public void refreshReferences ( final IProject [ ] sourceProjects , IProgressMonitor monitor ) { IProject externalProject = getExternalFoldersProject ( ) ; try { HashSet externalFolders = null ; for ( int index = 0 ; index < sourceProjects . length ; index ++ ) { if ( sourceProjects [ index ] . equals ( externalProject ) ) continue ; if ( ! JavaProject . hasJavaNature ( sourceProjects [ index ] ) ) continue ; HashSet foldersInProject = getExternalFolders ( ( ( JavaProject ) JavaCore . create ( sourceProjects [ index ] ) ) . getResolvedClasspath ( ) ) ; if ( foldersInProject == null || foldersInProject . size ( ) == 0 ) continue ; if ( externalFolders == null ) externalFolders = new HashSet ( ) ; externalFolders . addAll ( foldersInProject ) ; } if ( externalFolders == null ) return ; runRefreshJob ( externalFolders ) ; } catch ( CoreException e ) { Util . log ( e , "" ) ; } return ; } public void refreshReferences ( IProject source , IProgressMonitor monitor ) { IProject externalProject = getExternalFoldersProject ( ) ; if ( source . equals ( externalProject ) ) return ; if ( ! JavaProject . hasJavaNature ( source ) ) return ; try { HashSet externalFolders = getExternalFolders ( ( ( JavaProject ) JavaCore . create ( source ) ) . getResolvedClasspath ( ) ) ; if ( externalFolders == null ) return ; runRefreshJob ( externalFolders ) ; } catch ( CoreException e ) { Util . log ( e , "" ) ; } return ; } public IFolder removeFolder ( IPath externalFolderPath ) { return ( IFolder ) getFolders ( ) . remove ( externalFolderPath ) ; } class RefreshJob extends Job { Vector externalFolders = null ; RefreshJob ( Vector externalFolders ) { super ( Messages . refreshing_external_folders ) ; this . externalFolders = externalFolders ; } public boolean belongsTo ( Object family ) { return family == ResourcesPlugin . FAMILY_MANUAL_REFRESH ; } public void addFoldersToRefresh ( Collection paths ) { if ( ! paths . isEmpty ( ) && this . externalFolders == null ) { this . externalFolders = new Vector ( ) ; } Iterator it = paths . iterator ( ) ; while ( it . hasNext ( ) ) { Object path = it . next ( ) ; if ( ! this . externalFolders . contains ( path ) ) { this . externalFolders . add ( path ) ; } } } protected IStatus run ( IProgressMonitor pm ) { try { if ( this . externalFolders == null ) return Status . OK_STATUS ; IPath externalPath = null ; for ( int index = 0 ; index < this . externalFolders . size ( ) ; index ++ ) { if ( ( externalPath = ( IPath ) this . externalFolders . get ( index ) ) != null ) { IFolder folder = getFolder ( externalPath ) ; if ( folder != null ) folder . refreshLocal ( IResource . DEPTH_INFINITE , pm ) ; } this . externalFolders . setElementAt ( null , index ) ; } } catch ( CoreException e ) { return e . getStatus ( ) ; } return Status . OK_STATUS ; } } } </s>