### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core.tests.compiler Index: src/org/eclipse/jdt/core/tests/util/Util.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/util/Util.java,v retrieving revision 1.60 diff -u -r1.60 Util.java --- src/org/eclipse/jdt/core/tests/util/Util.java 9 Jan 2008 14:49:28 -0000 1.60 +++ src/org/eclipse/jdt/core/tests/util/Util.java 26 Feb 2008 09:54:51 -0000 @@ -328,15 +328,18 @@ } public static void createSourceZip(String[] pathsAndContents, String zipPath) throws IOException { String sourcesPath = getOutputDirectory() + File.separator + "sources"; - File sourcesDir = new File(sourcesPath); - flushDirectoryContent(sourcesDir); + createSourceDir(pathsAndContents, sourcesPath); + zip(new File(sourcesPath), zipPath); +} + +public static void createSourceDir(String[] pathsAndContents, String sourcesPath) throws IOException { + flushDirectoryContent(new File(sourcesPath)); for (int i = 0, length = pathsAndContents.length; i < length; i+=2) { String sourcePath = sourcesPath + File.separator + pathsAndContents[i]; File sourceFile = new File(sourcePath); sourceFile.getParentFile().mkdirs(); createFile(sourcePath, pathsAndContents[i+1]); } - zip(sourcesDir, zipPath); } /** * Delete a file or directory and insure that the file is no longer present #P org.eclipse.jdt.core.tests.builder Index: src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java,v retrieving revision 1.58 diff -u -r1.58 TestingEnvironment.java --- src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java 23 Oct 2007 11:31:42 -0000 1.58 +++ src/org/eclipse/jdt/core/tests/builder/TestingEnvironment.java 26 Feb 2008 09:54:52 -0000 @@ -232,6 +232,18 @@ addEntry(projectPath, JavaCore.newProjectEntry(requiredProjectPath, null, true, attributes, false)); } + public void addExternalFolders(IPath projectPath, String[] folders) throws JavaModelException { + addExternalFolders(projectPath, folders, false); + } + + public void addExternalFolders(IPath projectPath, String[] folders, boolean isExported) throws JavaModelException { + for (int i = 0, max = folders.length; i < max; i++) { + String folder = folders[i]; + checkAssertion("folder name must not end with .zip or .jar", !folder.endsWith(".zip") && !folder.endsWith(".jar")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + addEntry(projectPath, JavaCore.newLibraryEntry(new Path(folder), null, null, isExported)); + } + } + public void addExternalJars(IPath projectPath, String[] jars) throws JavaModelException { addExternalJars(projectPath, jars, false); } Index: src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.builder/src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java,v retrieving revision 1.42 diff -u -r1.42 BuildpathTests.java --- src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java 20 Dec 2007 16:01:14 -0000 1.42 +++ src/org/eclipse/jdt/core/tests/builder/BuildpathTests.java 26 Feb 2008 09:54:52 -0000 @@ -13,6 +13,8 @@ import junit.framework.*; import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.preferences.IEclipsePreferences; @@ -38,7 +40,7 @@ } private String getJdkLevelProblem(String expectedRuntime, String path, int severity) { - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), new Path(path).makeAbsolute(), true); + Object target = JavaModel.getTarget(new Path(path).makeAbsolute(), true); long libraryJDK = org.eclipse.jdt.internal.core.util.Util.getJdkLevel(target); String jclRuntime = CompilerOptions.versionFromJdkLevel(libraryJDK); StringBuffer jdkLevelProblem = new StringBuffer("Problem : Incompatible .class files version in required binaries. Project 'Project' is targeting a "); @@ -258,6 +260,69 @@ } /* + * Ensures that the changing a type in an external folder and refreshing triggers a rebuild + */ +public void testChangeExternalFolder() throws CoreException { + String externalLib = Util.getOutputDirectory() + File.separator + "externalLib"; + try { + new File(externalLib).mkdirs(); + Util.compile( + new String[] { + "p/X.java", + "package p;\n" + + "public class X {\n" + + " public void foo() {\n" + + " }\n" + + "}" + }, + new HashMap(), + externalLib + ); + + IPath projectPath = env.addProject("Project"); + env.addExternalJars(projectPath, Util.getJavaClassLibs()); + env.addExternalFolders(projectPath, new String[] {externalLib}); + + IPath root = env.getPackageFragmentRootPath(projectPath, ""); //$NON-NLS-1$ + env.setOutputFolder(projectPath, ""); + + IPath classY = env.addClass(root, "q", "Y", + "package q;\n"+ + "public class Y {\n" + + " void bar(p.X x) {\n" + + " x.foo();\n" + + " }\n" + + "}" + ); + + fullBuild(projectPath); + expectingNoProblems(); + + Util.compile( + new String[] { + "p/X.java", + "package p;\n" + + "public class X {\n" + + "}" + }, + new HashMap(), + externalLib + ); + // work around for https://bugs.eclipse.org/bugs/show_bug.cgi?id=219566 + IProject externalFoldersProject = JavaModelManager.getExternalManager().getExternalFoldersProject(); + externalFoldersProject.refreshLocal(IResource.DEPTH_INFINITE, null); + + incrementalBuild(projectPath); + expectingProblemsFor( + classY, + "Problem : The method foo() is undefined for the type X [ resource : range : <54,57> category : <50> severity : <2>]" + ); + } finally { + new File(externalLib).delete(); + } +} + +/* * Ensures that changing an external jar and refreshing the projects triggers a rebuild * (regression test for bug 50207 Compile errors fixed by 'refresh' do not reset problem list or package explorer error states) */ @@ -565,7 +630,7 @@ List expectedProblems = new ArrayList(); for (int i = 0; i < max; i++) { String path = project.getPackageFragmentRoot(classlibs[i]).getPath().makeRelative().toString(); - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), new Path(path).makeAbsolute(), true); + Object target = JavaModel.getTarget(new Path(path).makeAbsolute(), true); long libraryJDK = org.eclipse.jdt.internal.core.util.Util.getJdkLevel(target); if (libraryJDK > projectRuntimeJDKLevel) { expectedProblems.add(getJdkLevelProblem(projectRuntime, path, IMarker.SEVERITY_WARNING)); @@ -580,7 +645,7 @@ expectedProblems = new ArrayList(); for (int i = 0; i < max; i++) { String path = project.getPackageFragmentRoot(classlibs[i]).getPath().makeRelative().toString(); - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), new Path(path).makeAbsolute(), true); + Object target = JavaModel.getTarget(new Path(path).makeAbsolute(), true); long libraryJDK = org.eclipse.jdt.internal.core.util.Util.getJdkLevel(target); if (libraryJDK > projectRuntimeJDKLevel) { expectedProblems.add(getJdkLevelProblem(projectRuntime, path, IMarker.SEVERITY_ERROR)); @@ -625,7 +690,7 @@ int max = classlibs.length; for (int i = 0; i < max; i++) { String path = project.getPackageFragmentRoot(classlibs[i]).getPath().makeRelative().toString(); - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), new Path(path).makeAbsolute(), true); + Object target = JavaModel.getTarget(new Path(path).makeAbsolute(), true); long libraryJDK = org.eclipse.jdt.internal.core.util.Util.getJdkLevel(target); if (libraryJDK > wkspRuntimeJDKLevel) { expectedProblems.add(getJdkLevelProblem(wkspRuntime, path, IMarker.SEVERITY_WARNING)); @@ -640,7 +705,7 @@ expectedProblems = new ArrayList(); for (int i = 0; i < max; i++) { String path = project.getPackageFragmentRoot(classlibs[i]).getPath().makeRelative().toString(); - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), new Path(path).makeAbsolute(), true); + Object target = JavaModel.getTarget(new Path(path).makeAbsolute(), true); long libraryJDK = org.eclipse.jdt.internal.core.util.Util.getJdkLevel(target); if (libraryJDK > wkspRuntimeJDKLevel) { expectedProblems.add(getJdkLevelProblem(wkspRuntime, path, IMarker.SEVERITY_ERROR)); #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java,v retrieving revision 1.39 diff -u -r1.39 DeleteResourceElementsOperation.java --- model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java 10 May 2006 18:03:47 -0000 1.39 +++ model/org/eclipse/jdt/internal/core/DeleteResourceElementsOperation.java 26 Feb 2008 09:54:56 -0000 @@ -11,9 +11,6 @@ package org.eclipse.jdt.internal.core; import org.eclipse.core.resources.*; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IFolder; -import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModelStatusConstants; @@ -43,7 +40,7 @@ */ private void deletePackageFragment(IPackageFragment frag) throws JavaModelException { - IResource res = frag.getResource(); + IResource res = ((JavaElement) frag).resource(); if (res != null) { // collect the children to remove IJavaElement[] childrenOfInterest = frag.getChildren(); @@ -51,7 +48,7 @@ IResource[] resources = new IResource[childrenOfInterest.length]; // remove the children for (int i = 0; i < childrenOfInterest.length; i++) { - resources[i] = childrenOfInterest[i].getCorrespondingResource(); + resources[i] = ((JavaElement) childrenOfInterest[i]).resource(); } deleteResources(resources, force); } @@ -86,7 +83,7 @@ } if (isEmpty && !frag.isDefaultPackage()/*don't delete default package's folder: see https://bugs.eclipse.org/bugs/show_bug.cgi?id=38450*/) { // delete recursively empty folders - IResource fragResource = frag.getResource(); + IResource fragResource = ((JavaElement) frag).resource(); if (fragResource != null) { deleteEmptyPackageFragment(frag, false, fragResource.getParent()); } @@ -132,7 +129,7 @@ error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element); else if (type == IJavaElement.PACKAGE_FRAGMENT && element instanceof JarPackageFragment) error(IJavaModelStatusConstants.INVALID_ELEMENT_TYPES, element); - IResource resource = element.getResource(); + IResource resource = ((JavaElement) element).resource(); if (resource instanceof IFolder) { if (resource.isLinked()) { error(IJavaModelStatusConstants.INVALID_RESOURCE, element); Index: model/org/eclipse/jdt/internal/core/SourceRefElement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceRefElement.java,v retrieving revision 1.49 diff -u -r1.49 SourceRefElement.java --- model/org/eclipse/jdt/internal/core/SourceRefElement.java 24 Oct 2007 13:50:51 -0000 1.49 +++ model/org/eclipse/jdt/internal/core/SourceRefElement.java 26 Feb 2008 09:54:59 -0000 @@ -187,8 +187,8 @@ /* * @see IJavaElement */ -public IResource getResource() { - return this.getParent().getResource(); +public IResource resource() { + return this.parent.resource(); } /** * @see ISourceReference Index: model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java,v retrieving revision 1.17 diff -u -r1.17 MovePackageFragmentRootOperation.java --- model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java 27 Apr 2007 15:51:38 -0000 1.17 +++ model/org/eclipse/jdt/internal/core/MovePackageFragmentRootOperation.java 26 Feb 2008 09:54:59 -0000 @@ -118,7 +118,7 @@ } protected void executeOperation() throws JavaModelException { - IPackageFragmentRoot root = (IPackageFragmentRoot)this.getElementToProcess(); + IPackageFragmentRoot root = (IPackageFragmentRoot) getElementToProcess(); IClasspathEntry rootEntry = root.getRawClasspathEntry(); IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); @@ -160,7 +160,7 @@ throws JavaModelException { final char[][] exclusionPatterns = ((ClasspathEntry)rootEntry).fullExclusionPatternChars(); - IResource rootResource = root.getResource(); + IResource rootResource = ((JavaElement) root).resource(); if (rootEntry.getEntryKind() != IClasspathEntry.CPE_SOURCE || exclusionPatterns == null) { try { IResource destRes; Index: model/org/eclipse/jdt/internal/core/JavaModelOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelOperation.java,v retrieving revision 1.69 diff -u -r1.69 JavaModelOperation.java --- model/org/eclipse/jdt/internal/core/JavaModelOperation.java 11 Oct 2007 11:32:48 -0000 1.69 +++ model/org/eclipse/jdt/internal/core/JavaModelOperation.java 26 Feb 2008 09:54:58 -0000 @@ -145,13 +145,6 @@ protected JavaModelOperation(IJavaElement element) { this.elementsToProcess = new IJavaElement[]{element}; } - /** - * A common constructor for all Java Model operations. - */ - protected JavaModelOperation(IJavaElement element, boolean force) { - this.elementsToProcess = new IJavaElement[]{element}; - this.force= force; - } /* * Registers the given action at the end of the list of actions to run. @@ -292,7 +285,7 @@ IResource rootResource) throws JavaModelException { - IContainer resource = (IContainer) fragment.getResource(); + IContainer resource = (IContainer) ((JavaElement)fragment).resource(); try { resource.delete( @@ -438,13 +431,6 @@ return new DocumentAdapter(buffer); } /** - * Returns the elements to which this operation applies, - * or null if not applicable. - */ - protected IJavaElement[] getElementsToProcess() { - return elementsToProcess; - } - /** * Returns the element to which this operation applies, * or null if not applicable. */ Index: model/org/eclipse/jdt/internal/core/BufferManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/BufferManager.java,v retrieving revision 1.28 diff -u -r1.28 BufferManager.java --- model/org/eclipse/jdt/internal/core/BufferManager.java 9 May 2007 18:53:13 -0000 1.28 +++ model/org/eclipse/jdt/internal/core/BufferManager.java 26 Feb 2008 09:54:55 -0000 @@ -16,7 +16,6 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.jdt.core.IBuffer; -import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IOpenable; /** @@ -64,8 +63,8 @@ } } public static IBuffer createBuffer(IOpenable owner) { - IJavaElement element = (IJavaElement)owner; - IResource resource = element.getResource(); + JavaElement element = (JavaElement) owner; + IResource resource = element.resource(); return new Buffer( resource instanceof IFile ? (IFile)resource : null, @@ -73,8 +72,8 @@ element.isReadOnly()); } public static IBuffer createNullBuffer(IOpenable owner) { - IJavaElement element = (IJavaElement)owner; - IResource resource = element.getResource(); + JavaElement element = (JavaElement) owner; + IResource resource = element.resource(); return new NullBuffer( resource instanceof IFile ? (IFile)resource : null, Index: model/org/eclipse/jdt/internal/core/ClassFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFile.java,v retrieving revision 1.138 diff -u -r1.138 ClassFile.java --- model/org/eclipse/jdt/internal/core/ClassFile.java 30 Nov 2007 15:31:22 -0000 1.138 +++ model/org/eclipse/jdt/internal/core/ClassFile.java 26 Feb 2008 09:54:55 -0000 @@ -321,7 +321,7 @@ JavaModelManager.getJavaModelManager().closeZipFile(zip); } } else { - IFile file = (IFile) getResource(); + IFile file = (IFile) resource(); return Util.getResourceContentsAsByteArray(file); } } @@ -348,7 +348,7 @@ return super.getBuffer(); } else { // .class file not on classpath, create a new buffer to be nice (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=41444) - Object info = ((ClassFile) getClassFile()).getBinaryTypeInfo((IFile) getResource()); + Object info = ((ClassFile) getClassFile()).getBinaryTypeInfo((IFile) resource()); IBuffer buffer = openBuffer(null, info); if (buffer != null && !(buffer instanceof NullBuffer)) return buffer; @@ -488,13 +488,8 @@ /* * @see IJavaElement */ -public IResource getResource() { - PackageFragmentRoot root = this.getPackageFragmentRoot(); - if (root.isArchive()) { - return root.getResource(); - } else { - return ((IContainer)this.getParent().getResource()).getFile(new Path(this.getElementName())); - } +public IResource resource(PackageFragmentRoot root) { + return ((IContainer) ((Openable) this.parent).resource(root)).getFile(new Path(this.getElementName())); } /** * @see ISourceReference Index: model/org/eclipse/jdt/internal/core/Openable.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/Openable.java,v retrieving revision 1.114 diff -u -r1.114 Openable.java --- model/org/eclipse/jdt/internal/core/Openable.java 21 Sep 2007 13:16:47 -0000 1.114 +++ model/org/eclipse/jdt/internal/core/Openable.java 26 Feb 2008 09:54:59 -0000 @@ -197,7 +197,7 @@ } break; } - return validateExistence(getResource()).isOK(); + return validateExistence(resource()).isOK(); } public String findRecommendedLineSeparator() throws JavaModelException { IBuffer buffer = getBuffer(); @@ -234,7 +234,7 @@ openAncestors(newElements, monitor); // validate existence - IResource underlResource = getResource(); + IResource underlResource = resource(); IStatus status = validateExistence(underlResource); if (!status.isOK()) throw newJavaModelException(status); @@ -436,6 +436,26 @@ return null; } +public IResource getResource() { + PackageFragmentRoot root = getPackageFragmentRoot(); + if (root != null) { + if (root.isExternal()) + return null; + if (root.isArchive()) + return root.resource(root); + } + return resource(root); +} + +public IResource resource() { + PackageFragmentRoot root = getPackageFragmentRoot(); + if (root != null && root.isArchive()) + return root.resource(root); + return resource(root); +} + +protected abstract IResource resource(PackageFragmentRoot root); + /** * Returns whether the corresponding resource or associated file exists */ Index: model/org/eclipse/jdt/internal/core/SourceMapper.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/SourceMapper.java,v retrieving revision 1.131 diff -u -r1.131 SourceMapper.java --- model/org/eclipse/jdt/internal/core/SourceMapper.java 21 Jan 2008 10:36:14 -0000 1.131 +++ model/org/eclipse/jdt/internal/core/SourceMapper.java 26 Feb 2008 09:54:59 -0000 @@ -10,8 +10,6 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core; -import java.io.File; -import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -78,14 +76,6 @@ public static boolean VERBOSE = false; /** - * Specifies the file name filter use to compute the root paths. - */ - private static final FilenameFilter FILENAME_FILTER = new FilenameFilter() { - public boolean accept(File dir, String name) { - return org.eclipse.jdt.internal.core.util.Util.isJavaLikeFileName(name); - } - }; - /** * Specifies the location of the package fragment roots within * the zip (empty specifies the default root). null is * not a valid root path. @@ -401,7 +391,7 @@ manager.closeZipFile(zip); // handle null case } } else { - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), root.getPath(), true); + Object target = JavaModel.getTarget(root.getPath(), true); if (target instanceof IResource) { IResource resource = (IResource) target; if (resource instanceof IContainer) { @@ -419,19 +409,6 @@ // ignore } } - } else if (target instanceof File) { - File file = (File)target; - if (file.isDirectory()) { - File[] files = file.listFiles(); - for (int i = 0, max = files.length; i < max; i++) { - File currentFile = files[i]; - if (currentFile.isDirectory()) { - firstLevelPackageNames.add(currentFile.getName()); - } else if (Util.isClassFileName(currentFile.getName())) { - containsADefaultPackage = true; - } - } - } } } @@ -467,16 +444,9 @@ manager.closeZipFile(zip); // handle null case } } else { - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), this.sourcePath, true); - if (target instanceof IResource) { - if (target instanceof IContainer) { - computeRootPath((IContainer)target, firstLevelPackageNames, containsADefaultPackage, tempRoots); - } - } else if (target instanceof File) { - File file = (File)target; - if (file.isDirectory()) { - computeRootPath(file, firstLevelPackageNames, containsADefaultPackage, tempRoots); - } + Object target = JavaModel.getTarget(this.sourcePath, true); + if (target instanceof IContainer) { + computeRootPath((IContainer)target, firstLevelPackageNames, containsADefaultPackage, tempRoots); } } int size = tempRoots.size(); @@ -517,32 +487,6 @@ } } - private void computeRootPath(File directory, HashSet firstLevelPackageNames, boolean hasDefaultPackage, Set set) { - File[] files = directory.listFiles(); - boolean hasSubDirectories = false; - loop: for (int i = 0, max = files.length; i < max; i++) { - File file = files[i]; - if (file.isDirectory()) { - hasSubDirectories = true; - if (firstLevelPackageNames.contains(file.getName())) { - IPath fullPath = new Path(file.getParentFile().getPath()); - IPath rootPathEntry = fullPath.removeFirstSegments(this.sourcePath.segmentCount()).setDevice(null); - set.add(rootPathEntry); - break loop; - } else { - computeRootPath(file, firstLevelPackageNames, hasDefaultPackage, set); - } - } else if (i == max - 1 && !hasSubDirectories && hasDefaultPackage) { - File parentDir = file.getParentFile(); - if (parentDir.list(FILENAME_FILTER).length != 0) { - IPath fullPath = new Path(parentDir.getPath()); - IPath rootPathEntry = fullPath.removeFirstSegments(this.sourcePath.segmentCount()).setDevice(null); - set.add(rootPathEntry); - } - } - } - } - private void computeRootPath(IContainer container, HashSet firstLevelPackageNames, boolean hasDefaultPackage, Set set) { try { IResource[] resources = container.members(); @@ -958,28 +902,14 @@ manager.closeZipFile(zip); // handle null case } } else { - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), this.sourcePath, true); - if (target instanceof IResource) { - if (target instanceof IContainer) { - IResource res = ((IContainer)target).findMember(fullName); - if (res instanceof IFile) { - try { - source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res); - } catch (JavaModelException e) { - // ignore - } - } - } - } else if (target instanceof File) { - File file = (File)target; - if (file.isDirectory()) { - File sourceFile = new File(file, fullName); - if (sourceFile.isFile()) { - try { - source = Util.getFileCharContent(sourceFile, this.encoding); - } catch (IOException e) { - // ignore - } + Object target = JavaModel.getTarget(this.sourcePath, true); + if (target instanceof IContainer) { + IResource res = ((IContainer)target).findMember(fullName); + if (res instanceof IFile) { + try { + source = org.eclipse.jdt.internal.core.util.Util.getResourceContentsAsCharArray((IFile)res); + } catch (JavaModelException e) { + // ignore } } } Index: model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java,v retrieving revision 1.28 diff -u -r1.28 CopyPackageFragmentRootOperation.java --- model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java 27 Apr 2007 15:51:38 -0000 1.28 +++ model/org/eclipse/jdt/internal/core/CopyPackageFragmentRootOperation.java 26 Feb 2008 09:54:56 -0000 @@ -58,7 +58,7 @@ final IWorkspaceRoot workspaceRoot) throws JavaModelException { final char[][] exclusionPatterns = ((ClasspathEntry)rootEntry).fullExclusionPatternChars(); - IResource rootResource = root.getResource(); + IResource rootResource = ((JavaElement) root).resource(); if (root.getKind() == IPackageFragmentRoot.K_BINARY || exclusionPatterns == null) { try { IResource destRes; @@ -212,12 +212,12 @@ if (!status.isOK()) { return status; } - IPackageFragmentRoot root = (IPackageFragmentRoot)getElementToProcess(); + PackageFragmentRoot root = (PackageFragmentRoot)getElementToProcess(); if (root == null || !root.exists()) { return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, root); } - IResource resource = root.getResource(); + IResource resource = root.resource(); if (resource instanceof IFolder) { if (resource.isLinked()) { return new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE, root); Index: model/org/eclipse/jdt/internal/core/LocalVariable.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/LocalVariable.java,v retrieving revision 1.23 diff -u -r1.23 LocalVariable.java --- model/org/eclipse/jdt/internal/core/LocalVariable.java 22 Nov 2007 15:05:51 -0000 1.23 +++ model/org/eclipse/jdt/internal/core/LocalVariable.java 26 Feb 2008 09:54:59 -0000 @@ -251,8 +251,8 @@ return this.parent.getPath(); } - public IResource getResource() { - return this.parent.getResource(); + public IResource resource() { + return this.parent.resource(); } /** Index: model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java,v retrieving revision 1.6 diff -u -r1.6 ChangeClasspathOperation.java --- model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java 17 Dec 2007 11:08:02 -0000 1.6 +++ model/org/eclipse/jdt/internal/core/ChangeClasspathOperation.java 26 Feb 2008 09:54:55 -0000 @@ -60,6 +60,9 @@ // since some clients rely on the project references when run inside an IWorkspaceRunnable new ProjectReferenceChange(project, change.oldResolvedClasspath).updateProjectReferencesIfNecessary(); + // and ensure that external folders are updated as well + new ExternalFolderChange(project, change.oldResolvedClasspath).updateExternalFoldersIfNecessary(null); + } else { JavaElementDelta delta = new JavaElementDelta(getJavaModel()); int result = change.generateDelta(delta); @@ -77,6 +80,10 @@ // ensure project references are updated on next build state.addProjectReferenceChange(project, change.oldResolvedClasspath); } + if ((result & ClasspathChange.HAS_LIBRARY_CHANGE) != 0) { + // ensure external folders are updated on next build + state.addExternalFolderChange(project, change.oldResolvedClasspath); + } } } Index: model/org/eclipse/jdt/internal/core/CompilationUnit.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CompilationUnit.java,v retrieving revision 1.244 diff -u -r1.244 CompilationUnit.java --- model/org/eclipse/jdt/internal/core/CompilationUnit.java 21 Jan 2008 10:36:13 -0000 1.244 +++ model/org/eclipse/jdt/internal/core/CompilationUnit.java 26 Feb 2008 09:54:56 -0000 @@ -833,17 +833,12 @@ if (checkOwner && isPrimary()) return this; return new CompilationUnit((PackageFragment)getParent(), getElementName(), DefaultWorkingCopyOwner.PRIMARY); } -/** - * @see IJavaElement#getResource() +/* + * @see Openable#resource(PackageFragmentRoot) */ -public IResource getResource() { - PackageFragmentRoot root = getPackageFragmentRoot(); +public IResource resource(PackageFragmentRoot root) { if (root == null) return null; // working copy not in workspace - if (root.isArchive()) { - return root.getResource(); - } else { - return ((IContainer) getParent().getResource()).getFile(new Path(getElementName())); - } + return ((IContainer) ((Openable) this.parent).resource(root)).getFile(new Path(getElementName())); } /** * @see ISourceReference#getSource() Index: model/org/eclipse/jdt/internal/core/JavaProject.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProject.java,v retrieving revision 1.394 diff -u -r1.394 JavaProject.java --- model/org/eclipse/jdt/internal/core/JavaProject.java 1 Feb 2008 17:09:09 -0000 1.394 +++ model/org/eclipse/jdt/internal/core/JavaProject.java 26 Feb 2008 09:54:59 -0000 @@ -503,7 +503,7 @@ if (projectPath.isPrefixOf(entryPath)){ if (checkExistency) { - Object target = JavaModel.getTarget(workspaceRoot, entryPath, checkExistency); + Object target = JavaModel.getTarget(entryPath, checkExistency); if (target == null) return; if (target instanceof IFolder || target instanceof IProject){ @@ -521,16 +521,18 @@ if (referringEntry != null && !resolvedEntry.isExported()) return; if (checkExistency) { - Object target = JavaModel.getTarget(workspaceRoot, entryPath, checkExistency); + Object target = JavaModel.getTarget(entryPath, checkExistency); if (target == null) return; if (target instanceof IResource){ // internal target - root = getPackageFragmentRoot((IResource) target); - } else { - // external target - only JARs allowed + root = getPackageFragmentRoot((IResource) target, entryPath); + } else if (target instanceof File) { + // external target if (JavaModel.isFile(target) && (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(entryPath.lastSegment()))) { root = new JarPackageFragmentRoot(entryPath, this); + } else if (((File) target).isDirectory()) { + root = new ExternalPackageFragmentRoot(entryPath, this); } } } else { @@ -672,10 +674,16 @@ IPath fullPath = resource.getFullPath(); IPath innerMostOutput = output.isPrefixOf(fullPath) ? output : null; IClasspathEntry innerMostEntry = null; + ExternalFoldersManager foldersManager = JavaModelManager.getExternalManager(); for (int j = 0, cpLength = classpath.length; j < cpLength; j++) { IClasspathEntry entry = classpath[j]; IPath entryPath = entry.getPath(); + if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + IResource linkedFolder = foldersManager.getFolder(entryPath); + if (linkedFolder != null) + entryPath = linkedFolder.getFullPath(); + } if ((innerMostEntry == null || innerMostEntry.getPath().isPrefixOf(entryPath)) && entryPath.isPrefixOf(fullPath)) { innerMostEntry = entry; @@ -1641,7 +1649,10 @@ * @see IJavaProject */ public IPackageFragmentRoot getPackageFragmentRoot(IResource resource) { - + return getPackageFragmentRoot(resource, null/*no entry path*/); + } + + private IPackageFragmentRoot getPackageFragmentRoot(IResource resource, IPath entryPath) { switch (resource.getType()) { case IResource.FILE: if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(resource.getName())) { @@ -1650,6 +1661,8 @@ return null; } case IResource.FOLDER: + if (ExternalFoldersManager.isExternal(resource.getFullPath())) + return new ExternalPackageFragmentRoot(resource, entryPath, this); return new PackageFragmentRoot(resource, this); case IResource.PROJECT: return new PackageFragmentRoot(resource, this); @@ -1661,17 +1674,19 @@ /** * @see IJavaProject */ - public IPackageFragmentRoot getPackageFragmentRoot(String jarPath) { + public IPackageFragmentRoot getPackageFragmentRoot(String libraryPath) { - return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(jarPath))); + return getPackageFragmentRoot0(JavaProject.canonicalizedPath(new Path(libraryPath))); } /* * no path canonicalization */ - public IPackageFragmentRoot getPackageFragmentRoot0(IPath jarPath) { - - return new JarPackageFragmentRoot(jarPath, this); + public IPackageFragmentRoot getPackageFragmentRoot0(IPath libraryPath) { + if (!org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(libraryPath.lastSegment())) + return new ExternalPackageFragmentRoot(libraryPath, this); + return new JarPackageFragmentRoot(libraryPath, this); + } /** @@ -1879,7 +1894,7 @@ /** * @see IJavaElement */ - public IResource getResource() { + public IResource resource(PackageFragmentRoot root) { return this.project; } Index: model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java,v retrieving revision 1.38 diff -u -r1.38 PackageFragmentRootInfo.java --- model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java 6 Nov 2006 14:13:45 -0000 1.38 +++ model/org/eclipse/jdt/internal/core/PackageFragmentRootInfo.java 26 Feb 2008 09:54:59 -0000 @@ -54,6 +54,8 @@ * @exception JavaModelException The resource associated with this package fragment does not exist */ static Object[] computeFolderNonJavaResources(JavaProject project, IContainer folder, char[][] inclusionPatterns, char[][] exclusionPatterns) throws JavaModelException { + if (ExternalFoldersManager.isExternal(folder.getFullPath())) + return NO_NON_JAVA_RESOURCES; Object[] nonJavaResources = new IResource[5]; int nonJavaResourcesCounter = 0; try { Index: model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java,v retrieving revision 1.50 diff -u -r1.50 ClassFileWorkingCopy.java --- model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java 12 Dec 2006 17:13:59 -0000 1.50 +++ model/org/eclipse/jdt/internal/core/ClassFileWorkingCopy.java 26 Feb 2008 09:54:55 -0000 @@ -14,7 +14,6 @@ import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IBuffer; -import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaModelStatusConstants; import org.eclipse.jdt.core.JavaModelException; @@ -31,10 +30,10 @@ */ public class ClassFileWorkingCopy extends CompilationUnit { - public IClassFile classFile; + public ClassFile classFile; -public ClassFileWorkingCopy(IClassFile classFile, WorkingCopyOwner owner) { - super((PackageFragment) classFile.getParent(), ((BinaryType) ((ClassFile) classFile).getType()).getSourceFileName(null/*no info available*/), owner); +public ClassFileWorkingCopy(ClassFile classFile, WorkingCopyOwner owner) { + super((PackageFragment) classFile.getParent(), ((BinaryType) classFile.getType()).getSourceFileName(null/*no info available*/), owner); this.classFile = classFile; } @@ -70,8 +69,10 @@ return new ClassFileWorkingCopy(this.classFile, DefaultWorkingCopyOwner.PRIMARY); } -public IResource getResource() { - return this.classFile.getResource(); +public IResource resource(PackageFragmentRoot root) { + if (root.isArchive()) + return root.resource(root); + return this.classFile.resource(root); } /** Index: model/org/eclipse/jdt/internal/core/JavaModel.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModel.java,v retrieving revision 1.91 diff -u -r1.91 JavaModel.java --- model/org/eclipse/jdt/internal/core/JavaModel.java 21 Sep 2007 13:16:47 -0000 1.91 +++ model/org/eclipse/jdt/internal/core/JavaModel.java 26 Feb 2008 09:54:57 -0000 @@ -15,7 +15,6 @@ import java.util.HashSet; import java.util.Map; -import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -235,7 +234,7 @@ /* * @see IJavaElement */ -public IResource getResource() { +public IResource resource(PackageFragmentRoot root) { return ResourcesPlugin.getWorkspace().getRoot(); } /** @@ -313,46 +312,60 @@ * or null if unbound * Internal items must be referred to using container relative paths. */ -public static Object getTarget(IContainer container, IPath path, boolean checkResourceExistence) { - - if (path == null) return null; - - // lookup - inside the container - if (path.getDevice() == null) { // container relative paths should not contain a device - // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=18684) - // (case of a workspace rooted at d:\ ) - IResource resource = container.findMember(path); - if (resource != null){ - if (!checkResourceExistence ||resource.exists()) return resource; - return null; +public static Object getTarget(IPath path, boolean checkResourceExistence) { + Object target = getWorkspaceTarget(path); // Implicitly checks resource existence + if (target != null) + return target; + return getExternalTarget(path, checkResourceExistence); +} +public static Object getWorkspaceTarget(IPath path) { + if (path == null || path.getDevice() != null) + return null; + IWorkspace workspace = ResourcesPlugin.getWorkspace(); + if (workspace == null) + return null; + return workspace.getRoot().findMember(path); +} +public static Object getExternalTarget(IPath path, boolean checkResourceExistence) { + if (path == null) + return null; + ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager(); + Object linkedFolder = externalFoldersManager.getFolder(path); + if (linkedFolder != null) { + if (checkResourceExistence) { + // check if external folder is present + File externalFile = new File(path.toOSString()); + if (!externalFile.isDirectory()) { + return null; + } } + return linkedFolder; } - - // if path is relative, it cannot be an external path - // (see http://dev.eclipse.org/bugs/show_bug.cgi?id=22517) - if (!path.isAbsolute()) return null; - - // lookup - outside the container - return getTargetAsExternalFile(path, checkResourceExistence); -} -private synchronized static Object getTargetAsExternalFile(IPath path, boolean checkResourceExistence) { File externalFile = new File(path.toOSString()); if (!checkResourceExistence) { return externalFile; - } else if (existingExternalFiles.contains(externalFile)) { + } else if (existingExternalFilesContains(externalFile)) { return externalFile; } else { if (JavaModelManager.ZIP_ACCESS_VERBOSE) { System.out.println("(" + Thread.currentThread() + ") [JavaModel.getTarget(...)] Checking existence of " + path.toString()); //$NON-NLS-1$ //$NON-NLS-2$ } - if (externalFile.exists()) { + if (externalFile.isFile()) { // isFile() checks for existence (it returns false if a directory) // cache external file - existingExternalFiles.add(externalFile); + existingExternalFilesAdd(externalFile); return externalFile; + } else if (externalFile.isDirectory()) { + return externalFoldersManager.addFolder(path); } } return null; } +private synchronized static void existingExternalFilesAdd(File externalFile) { + existingExternalFiles.add(externalFile); +} +private synchronized static boolean existingExternalFilesContains(File externalFile) { + return existingExternalFiles.contains(externalFile); +} /** * Helper method - returns whether an object is afile (ie. which returns true to {@link java.io.File#isFile()}. Index: model/org/eclipse/jdt/internal/core/PackageFragment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragment.java,v retrieving revision 1.81 diff -u -r1.81 PackageFragment.java --- model/org/eclipse/jdt/internal/core/PackageFragment.java 21 Sep 2007 13:16:47 -0000 1.81 +++ model/org/eclipse/jdt/internal/core/PackageFragment.java 26 Feb 2008 09:54:59 -0000 @@ -297,7 +297,7 @@ // We don't want to show non java resources of the default package (see PR #1G58NB8) return JavaElementInfo.NO_NON_JAVA_RESOURCES; } else { - return ((PackageFragmentInfo) getElementInfo()).getNonJavaResources(getResource(), getPackageFragmentRoot()); + return ((PackageFragmentInfo) getElementInfo()).getNonJavaResources(resource(), getPackageFragmentRoot()); } } /** @@ -317,22 +317,17 @@ } } /** - * @see IJavaElement#getResource() + * @see JavaElement#resource() */ -public IResource getResource() { - PackageFragmentRoot root = this.getPackageFragmentRoot(); - if (root.isArchive()) { - return root.getResource(); +public IResource resource(PackageFragmentRoot root) { + int length = this.names.length; + if (length == 0) { + return root.resource(root); } else { - int length = this.names.length; - if (length == 0) { - return root.getResource(); - } else { - IPath path = new Path(this.names[0]); - for (int i = 1; i < length; i++) - path = path.append(this.names[i]); - return ((IContainer)root.getResource()).getFolder(path); - } + IPath path = new Path(this.names[0]); + for (int i = 1; i < length; i++) + path = path.append(this.names[i]); + return ((IContainer)root.resource(root)).getFolder(path); } } /** Index: model/org/eclipse/jdt/internal/core/DeltaProcessor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeltaProcessor.java,v retrieving revision 1.312 diff -u -r1.312 DeltaProcessor.java --- model/org/eclipse/jdt/internal/core/DeltaProcessor.java 29 Jan 2008 18:02:22 -0000 1.312 +++ model/org/eclipse/jdt/internal/core/DeltaProcessor.java 26 Feb 2008 09:54:57 -0000 @@ -13,6 +13,7 @@ import java.io.File; import java.util.*; +import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; @@ -112,7 +113,7 @@ if (resource != null) { this.root = this.project.getPackageFragmentRoot(resource); } else { - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), this.rootPath, false/*don't check existence*/); + Object target = JavaModel.getTarget(this.rootPath, false/*don't check existence*/); if (target instanceof IResource) { this.root = this.project.getPackageFragmentRoot((IResource)target); } else { @@ -340,6 +341,8 @@ readRawClasspath(javaProject); // ensure project references are updated (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=121569) checkProjectReferenceChange(project, javaProject); + // and external folders as well + checkExternalFolderChange(project, javaProject); } this.state.rootsAreStale = true; @@ -359,6 +362,8 @@ readRawClasspath(javaProject); // ensure project references are updated checkProjectReferenceChange(project, javaProject); + // and external folders as well + checkExternalFolderChange(project, javaProject); } } else { try { @@ -386,6 +391,8 @@ readRawClasspath(javaProject); // ensure project references are updated (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=172666) checkProjectReferenceChange(project, javaProject); + // and external folders as well + checkExternalFolderChange(project, javaProject); } else { // remove classpath cache so that initializeRoots() will not consider the project has a classpath this.manager.removePerProjectInfo(javaProject); @@ -471,6 +478,11 @@ } } + private void checkExternalFolderChange(IProject project, JavaProject javaProject) { + ClasspathChange change = (ClasspathChange) this.classpathChanges.get(project); + this.state.addExternalFolderChange(javaProject, change == null ? null : change.oldResolvedClasspath); + } + private void checkProjectReferenceChange(IProject project, JavaProject javaProject) { ClasspathChange change = (ClasspathChange) this.classpathChanges.get(project); this.state.addProjectReferenceChange(javaProject, change == null ? null : change.oldResolvedClasspath); @@ -487,14 +499,14 @@ } } private void checkSourceAttachmentChange(IResourceDelta delta, IResource res) { - IPath rootPath = (IPath)this.state.sourceAttachments.get(res.getFullPath()); + IPath rootPath = (IPath)this.state.sourceAttachments.get(externalPath(res)); if (rootPath != null) { RootInfo rootInfo = this.rootInfo(rootPath, delta.getKind()); if (rootInfo != null) { IJavaProject projectOfRoot = rootInfo.project; IPackageFragmentRoot root = null; try { - // close the root so that source attachement cache is flushed + // close the root so that source attachment cache is flushed root = projectOfRoot.findPackageFragmentRoot(rootPath); if (root != null) { root.close(); @@ -610,7 +622,7 @@ if (rootInfo.project.contains(resource)) { PackageFragmentRoot root = (PackageFragmentRoot) rootInfo.getPackageFragmentRoot(null); // create package handle - IPath pkgPath = path.removeFirstSegments(rootInfo.rootPath.segmentCount()); + IPath pkgPath = path.removeFirstSegments(root.resource().getFullPath().segmentCount()); String[] pkgName = pkgPath.segments(); element = root.getPackageFragment(pkgName); } @@ -834,7 +846,7 @@ if (status == null){ // compute shared status - Object targetLibrary = JavaModel.getTarget(wksRoot, entryPath, true); + Object targetLibrary = JavaModel.getTarget(entryPath, true); if (targetLibrary == null){ // missing JAR if (this.state.getExternalLibTimeStamps().remove(entryPath) != null){ @@ -1047,7 +1059,8 @@ } // find the element type of the moved from element - RootInfo movedFromInfo = this.enclosingRootInfo(movedFromPath, IResourceDelta.REMOVED); + IPath rootPath = externalPath(movedFromRes); + RootInfo movedFromInfo = this.enclosingRootInfo(rootPath, IResourceDelta.REMOVED); int movedFromType = this.elementType( movedFromRes, @@ -1133,7 +1146,8 @@ } // find the element type of the moved from element - RootInfo movedToInfo = this.enclosingRootInfo(movedToPath, IResourceDelta.ADDED); + IPath rootPath = externalPath(movedToRes); + RootInfo movedToInfo = this.enclosingRootInfo(rootPath, IResourceDelta.ADDED); int movedToType = this.elementType( movedToRes, @@ -1208,7 +1222,8 @@ case IJavaElement.PACKAGE_FRAGMENT_ROOT: case IJavaElement.PACKAGE_FRAGMENT: if (rootInfo == null) { - rootInfo = this.enclosingRootInfo(res.getFullPath(), kind); + IPath rootPath = externalPath(res); + rootInfo = this.enclosingRootInfo(rootPath, kind); } if (rootInfo == null) { return NON_JAVA_RESOURCE; @@ -1235,12 +1250,15 @@ return IJavaElement.COMPILATION_UNIT; } else if (Util.isValidClassFileName(fileName, sourceLevel, complianceLevel)) { return IJavaElement.CLASS_FILE; - } else if ((rootInfo = this.rootInfo(res.getFullPath(), kind)) != null - && rootInfo.project.getProject().getFullPath().isPrefixOf(res.getFullPath()) /*ensure root is a root of its project (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185310) */) { - // case of proj=src=bin and resource is a jar file on the classpath - return IJavaElement.PACKAGE_FRAGMENT_ROOT; } else { - return NON_JAVA_RESOURCE; + IPath rootPath = externalPath(res); + if ((rootInfo = this.rootInfo(rootPath, kind)) != null + && rootInfo.project.getProject().getFullPath().isPrefixOf(rootPath) /*ensure root is a root of its project (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=185310) */) { + // case of proj=src=bin and resource is a jar file on the classpath + return IJavaElement.PACKAGE_FRAGMENT_ROOT; + } else { + return NON_JAVA_RESOURCE; + } } default: @@ -1253,7 +1271,7 @@ public void flush() { this.javaModelDeltas = new ArrayList(); } - + private SourceElementParser getSourceElementParser(Openable element) { if (this.sourceElementParserCache == null) this.sourceElementParserCache = this.manager.indexManager.getSourceElementParser(element.getJavaProject(), null/*requestor will be set by indexer*/); @@ -1271,6 +1289,14 @@ } return null; } + + private IPath externalPath(IResource res) { + IPath resourcePath = res.getFullPath(); + if (ExternalFoldersManager.isExternal(resourcePath)) + return res.getLocation(); + return resourcePath; + } + /* * Fire Java Model delta, flushing them after the fact after post_change notification. * If the firing mode has been turned off, this has no effect. @@ -1391,7 +1417,8 @@ } return true; } - }); + }, + IContainer.INCLUDE_HIDDEN); } catch(FoundRelevantDeltaException e) { //System.out.println("RELEVANT DELTA detected in: "+ (System.currentTimeMillis() - start)); return true; @@ -1556,8 +1583,9 @@ *
  • An entry is made in the delta reporting a content change (K_CHANGE with F_CONTENT flag set). * */ - private void nonJavaResourcesChanged(Openable element, IResourceDelta delta) - throws JavaModelException { + private void nonJavaResourcesChanged(Openable element, IResourceDelta delta) throws JavaModelException { + if (ExternalFoldersManager.isExternal(delta.getFullPath())) + return; // reset non-java resources if element was open if (element.isOpen()) { @@ -1655,7 +1683,7 @@ if (this.currentElement instanceof IPackageFragmentRoot) { currentElementPath = ((IPackageFragmentRoot)this.currentElement).getPath(); } else { - IResource currentElementResource = this.currentElement.getResource(); + IResource currentElementResource = this.currentElement.resource(); if (currentElementResource != null) { currentElementPath = currentElementResource.getFullPath(); } @@ -1698,7 +1726,7 @@ this.currentElement = null; // get the workspace delta, and start processing there. - IResourceDelta[] deltas = changes.getAffectedChildren(); + IResourceDelta[] deltas = changes.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.REMOVED | IResourceDelta.CHANGED, IContainer.INCLUDE_HIDDEN); for (int i = 0; i < deltas.length; i++) { IResourceDelta delta = deltas[i]; IResource res = delta.getResource(); @@ -1712,8 +1740,9 @@ if (!wasJavaProject && !isJavaProject) { elementType = NON_JAVA_RESOURCE; } else { - rootInfo = this.enclosingRootInfo(res.getFullPath(), delta.getKind()); - if (rootInfo != null && rootInfo.isRootOfProject(res.getFullPath())) { + IPath rootPath = externalPath(res); + rootInfo = this.enclosingRootInfo(rootPath, delta.getKind()); + if (rootInfo != null && rootInfo.isRootOfProject(rootPath)) { elementType = IJavaElement.PACKAGE_FRAGMENT_ROOT; } else { elementType = IJavaElement.JAVA_PROJECT; @@ -1843,6 +1872,9 @@ if ((result & ClasspathChange.HAS_PROJECT_CHANGE) != 0) { this.state.addProjectReferenceChange(change.project, change.oldResolvedClasspath); } + if ((result & ClasspathChange.HAS_LIBRARY_CHANGE) != 0) { + state.addExternalFolderChange(change.project, change.oldResolvedClasspath); + } } this.classpathChanges.clear(); if (!hasDelta) @@ -1853,10 +1885,9 @@ if (elementsToRefresh == null) { elementsToRefresh = this.state.removeExternalElementsToRefresh(); } else { - HashSet existingElements = this.state.removeExternalElementsToRefresh(); - if (existingElements != null) { - elementsToRefresh.addAll(existingElements); - } + HashSet newElementsToRefresh = this.state.removeExternalElementsToRefresh(); + if (newElementsToRefresh != null) + elementsToRefresh.addAll(newElementsToRefresh); } // generate external archive change deltas @@ -1893,6 +1924,19 @@ boolean isAffected = isAffectedBy(delta); boolean needCycleValidation = isAffected && validateClasspaths(delta); + // update external folders if necessary + ExternalFolderChange[] folderChanges = this.state.removeExternalFolderChanges(); + if (folderChanges != null) { + for (int i = 0, length = folderChanges.length; i < length; i++) { + try { + folderChanges[i].updateExternalFoldersIfNecessary(null); + } catch (JavaModelException e) { + if (!e.isDoesNotExist()) + Util.log(e, "Exception while updating external folders"); //$NON-NLS-1$ + } + } + } + // create classpath markers if necessary ClasspathValidation[] validations = this.state.removeClasspathValidations(); if (validations != null) { @@ -1910,6 +1954,8 @@ projectRefChanges[i].updateProjectReferencesIfNecessary(); } catch(JavaModelException e) { // project doesn't exist any longer, continue with next one + if (!e.isDoesNotExist()) + Util.log(e, "Exception while updating project references"); //$NON-NLS-1$ } } } @@ -2016,9 +2062,10 @@ this.checkSourceAttachmentChange(child, childRes); // find out whether the child is a package fragment root of the current project - IPath childPath = childRes.getFullPath(); + IPath childPath = externalPath(childRes); int childKind = child.getKind(); RootInfo childRootInfo = this.rootInfo(childPath, childKind); + RootInfo originalChildRootInfo = childRootInfo; if (childRootInfo != null && !childRootInfo.isRootOfProject(childPath)) { // package fragment root of another project (dealt with later) childRootInfo = null; @@ -2091,8 +2138,8 @@ // or if it is not a package fragment root of the current project // but it is a package fragment root of another project, traverse delta too if (isNestedRoot - || (childRootInfo == null && (childRootInfo = this.rootInfo(childPath, childKind)) != null)) { - this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root + || (childRootInfo == null && originalChildRootInfo != null)) { + this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, originalChildRootInfo, null); // binary output of childRootInfo.project cannot be this root } // if the child is a package fragment root of one or several other projects @@ -2100,9 +2147,9 @@ if ((rootList = this.otherRootsInfo(childPath, childKind)) != null) { Iterator iterator = rootList.iterator(); while (iterator.hasNext()) { - childRootInfo = (RootInfo) iterator.next(); + originalChildRootInfo = (RootInfo) iterator.next(); this.currentElement = null; // ensure that 2 roots refering to the same resource don't share the current element (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=210746 ) - this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, childRootInfo, null); // binary output of childRootInfo.project cannot be this root + this.traverseDelta(child, IJavaElement.PACKAGE_FRAGMENT_ROOT, originalChildRootInfo, null); // binary output of childRootInfo.project cannot be this root } } } @@ -2285,7 +2332,21 @@ return elementType == IJavaElement.PACKAGE_FRAGMENT; case IResourceDelta.CHANGED : int flags = delta.getFlags(); - if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) { + if (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT && (flags & IResourceDelta.LOCAL_CHANGED) != 0) { + // external folder added or removed + deltaRes = delta.getResource(); + Object target = JavaModel.getExternalTarget(deltaRes.getLocation(), true/*check resource existence*/); + element = createElement(deltaRes, elementType, rootInfo); + updateIndex(element, delta); + if (target != null) { + // external folder added + elementAdded(element, delta, rootInfo); + } else { + // external folder removed + elementRemoved(element, delta, rootInfo); + } + this.state.addClasspathValidation(rootInfo.project); + } else if ((flags & IResourceDelta.CONTENT) != 0 || (flags & IResourceDelta.ENCODING) != 0) { // content or encoding has changed element = createElement(delta.getResource(), elementType, rootInfo); if (element == null) return false; @@ -2397,7 +2458,7 @@ break; } int kind = delta.getKind(); - if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED) { + if (kind == IResourceDelta.ADDED || kind == IResourceDelta.REMOVED || (kind == IResourceDelta.CHANGED && (delta.getFlags() & IResourceDelta.LOCAL_CHANGED) != 0)) { PackageFragmentRoot root = (PackageFragmentRoot)element; this.updateRootIndex(root, CharOperation.NO_STRINGS, delta); break; @@ -2405,6 +2466,9 @@ // don't break as packages of the package fragment root can be indexed below case IJavaElement.PACKAGE_FRAGMENT : switch (delta.getKind()) { + case IResourceDelta.CHANGED: + if ((delta.getFlags() & IResourceDelta.LOCAL_CHANGED) == 0) + break; case IResourceDelta.ADDED: case IResourceDelta.REMOVED: IPackageFragment pkg = null; @@ -2442,7 +2506,8 @@ case IJavaElement.CLASS_FILE : IFile file = (IFile) delta.getResource(); IJavaProject project = element.getJavaProject(); - IPath binaryFolderPath = element.getPackageFragmentRoot().getPath(); + PackageFragmentRoot root = element.getPackageFragmentRoot(); + IPath binaryFolderPath = root.isExternal() && !root.isArchive() ? root.resource().getFullPath() : root.getPath(); // if the class file is part of the binary output, it has been created by // the java builder -> ignore try { Index: model/org/eclipse/jdt/internal/core/JavaElement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaElement.java,v retrieving revision 1.127 diff -u -r1.127 JavaElement.java --- model/org/eclipse/jdt/internal/core/JavaElement.java 24 Oct 2007 13:50:51 -0000 1.127 +++ model/org/eclipse/jdt/internal/core/JavaElement.java 26 Feb 2008 09:54:57 -0000 @@ -350,6 +350,10 @@ public IJavaElement getPrimaryElement(boolean checkOwner) { return this; } + public IResource getResource() { + return resource(); + } + public abstract IResource resource(); /** * Returns the element that is located at the given source position * in this element. This is a helper method for ICompilationUnit#getElementAt, @@ -410,7 +414,7 @@ * @see org.eclipse.jdt.core.IJavaElement#getSchedulingRule() */ public ISchedulingRule getSchedulingRule() { - IResource resource = getResource(); + IResource resource = resource(); if (resource == null) { class NoResourceSchedulingRule implements ISchedulingRule { public IPath path; Index: model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java,v retrieving revision 1.126 diff -u -r1.126 PackageFragmentRoot.java --- model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java 27 Sep 2007 11:09:40 -0000 1.126 +++ model/org/eclipse/jdt/internal/core/PackageFragmentRoot.java 26 Feb 2008 09:54:59 -0000 @@ -62,7 +62,6 @@ monitor.beginTask(Messages.element_attachingSource, 2); } SourceMapper oldMapper= getSourceMapper(); - IWorkspace workspace = ResourcesPlugin.getWorkspace(); boolean rootNeedsToBeClosed= false; if (sourcePath == null) { @@ -80,7 +79,7 @@ */ } else { /* - // fire a delta to notify the UI about the source attachement. + // fire a delta to notify the UI about the source attachment. JavaModelManager manager = (JavaModelManager) JavaModelManager.getJavaModelManager(); JavaModel model = (JavaModel) getJavaModel(); JavaElementDelta attachedSourceDelta = new JavaElementDelta(model); @@ -101,7 +100,7 @@ } } // check if source path is valid - Object target = JavaModel.getTarget(workspace.getRoot(), sourcePath, false); + Object target = JavaModel.getTarget(sourcePath, false); if (target == null) { throw new JavaModelException(new JavaModelStatus(IJavaModelStatusConstants.INVALID_PATH, sourcePath)); } @@ -153,7 +152,7 @@ */ protected boolean buildStructure(OpenableElementInfo info, IProgressMonitor pm, Map newElements, IResource underlyingResource) throws JavaModelException { ((PackageFragmentRootInfo) info).setRootKind(determineKind(underlyingResource)); - return computeChildren(info); + return computeChildren(info, underlyingResource); } SourceMapper createSourceMapper(IPath sourcePath, IPath rootPath) { @@ -181,13 +180,12 @@ * * @exception JavaModelException The resource associated with this package fragment root does not exist */ -protected boolean computeChildren(OpenableElementInfo info) throws JavaModelException { +protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException { // Note the children are not opened (so not added to newElements) for a regular package fragment root - // Howver they are opened for a Jar package fragment root (see JarPackageFragmentRoot#computeChildren) + // However they are opened for a Jar package fragment root (see JarPackageFragmentRoot#computeChildren) try { // the underlying resource may be a folder or a project (in the case that the project folder // is actually the package fragment root) - IResource underlyingResource = getResource(); if (underlyingResource.getType() == IResource.FOLDER || underlyingResource.getType() == IResource.PROJECT) { ArrayList vChildren = new ArrayList(5); IContainer rootFolder = (IContainer) underlyingResource; @@ -324,7 +322,7 @@ if (!(o instanceof PackageFragmentRoot)) return false; PackageFragmentRoot other = (PackageFragmentRoot) o; - return getResource().equals(other.getResource()) && + return resource().equals(other.resource()) && this.parent.equals(other.parent); } @@ -332,14 +330,13 @@ try { IPath rootPath = this.getPath(); IClasspathEntry entry; - IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); // try on enclosing project first JavaProject parentProject = (JavaProject) getJavaProject(); try { entry = parentProject.getClasspathEntryFor(rootPath); if (entry != null){ - Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true); + Object target = JavaModel.getTarget(entry.getSourceAttachmentPath(), true); if (target instanceof IResource) { if (target instanceof IFile) { IFile file = (IFile) target; @@ -374,7 +371,7 @@ try { entry = jProject.getClasspathEntryFor(rootPath); if (entry != null){ - Object target = JavaModel.getTarget(workspaceRoot, entry.getSourceAttachmentPath(), true); + Object target = JavaModel.getTarget(entry.getSourceAttachmentPath(), true); if (target instanceof IResource) { if (target instanceof IFile){ IFile file = (IFile) target; @@ -386,12 +383,7 @@ } } else if (target instanceof java.io.File){ java.io.File file = (java.io.File) target; - if (file.isFile()) { - if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())){ - return entry; - } - } else { - // external directory + if (org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(file.getName())){ return entry; } } @@ -441,7 +433,7 @@ } } public String getElementName() { - IResource res = getResource(); + IResource res = resource(); if (res instanceof IFolder) return ((IFolder) res).getName(); return ""; //$NON-NLS-1$ @@ -492,10 +484,10 @@ */ protected void getHandleMemento(StringBuffer buff) { IPath path; - IResource underlyingResource = getResource(); + IResource underlyingResource = resource(); if (underlyingResource != null) { // internal jar or regular root - if (getResource().getProject().equals(getJavaProject().getProject())) { + if (resource().getProject().equals(getJavaProject().getProject())) { path = underlyingResource.getProjectRelativePath(); } else { path = underlyingResource.getFullPath(); @@ -519,7 +511,7 @@ * Returns an array of non-java resources contained in the receiver. */ public Object[] getNonJavaResources() throws JavaModelException { - return ((PackageFragmentRootInfo) getElementInfo()).getNonJavaResources(getJavaProject(), getResource(), this); + return ((PackageFragmentRootInfo) getElementInfo()).getNonJavaResources(getJavaProject(), resource(), this); } /** @@ -556,9 +548,12 @@ * @see IJavaElement */ public IPath getPath() { - return getResource().getFullPath(); + return internalPath(); } +public IPath internalPath() { + return resource().getFullPath(); +} /* * @see IPackageFragmentRoot */ @@ -580,7 +575,7 @@ /* * @see IJavaElement */ -public IResource getResource() { +public IResource resource(PackageFragmentRoot root) { return (IResource)this.resource; } @@ -692,7 +687,7 @@ */ public IResource getUnderlyingResource() throws JavaModelException { if (!exists()) throw newNotPresentException(); - return getResource(); + return resource(); } /** @@ -704,7 +699,7 @@ } public int hashCode() { - return getResource().hashCode(); + return resource().hashCode(); } /** Index: model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java,v retrieving revision 1.17 diff -u -r1.17 DeletePackageFragmentRootOperation.java --- model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java 27 Apr 2007 15:51:38 -0000 1.17 +++ model/org/eclipse/jdt/internal/core/DeletePackageFragmentRootOperation.java 26 Feb 2008 09:54:56 -0000 @@ -62,7 +62,7 @@ IClasspathEntry rootEntry) throws JavaModelException { final char[][] exclusionPatterns = ((ClasspathEntry)rootEntry).fullExclusionPatternChars(); - IResource rootResource = root.getResource(); + IResource rootResource = ((JavaElement) root).resource(); if (rootEntry.getEntryKind() != IClasspathEntry.CPE_SOURCE || exclusionPatterns == null) { try { rootResource.delete(this.updateResourceFlags, progressMonitor); @@ -147,12 +147,12 @@ if (!status.isOK()) { return status; } - IPackageFragmentRoot root = (IPackageFragmentRoot) this.getElementToProcess(); + IJavaElement root = getElementToProcess(); if (root == null || !root.exists()) { return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, root); } - IResource resource = root.getResource(); + IResource resource = ((JavaElement) root).resource(); if (resource instanceof IFolder) { if (resource.isLinked()) { return new JavaModelStatus(IJavaModelStatusConstants.INVALID_RESOURCE, root); Index: model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java,v retrieving revision 1.51 diff -u -r1.51 JavaProjectElementInfo.java --- model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java 1 Feb 2008 15:52:48 -0000 1.51 +++ model/org/eclipse/jdt/internal/core/JavaProjectElementInfo.java 26 Feb 2008 09:54:59 -0000 @@ -248,7 +248,7 @@ try { if (!root.isOpen()) { PackageFragmentRootInfo info = root.isArchive() ? new JarPackageFragmentRootInfo() : new PackageFragmentRootInfo(); - ((PackageFragmentRoot) root).computeChildren(info); + ((PackageFragmentRoot) root).computeChildren(info, ((JavaElement) root).resource()); frags = info.children; } else frags = root.getChildren(); Index: model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java,v retrieving revision 1.36 diff -u -r1.36 CreatePackageFragmentOperation.java --- model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java 4 Jul 2007 14:11:12 -0000 1.36 +++ model/org/eclipse/jdt/internal/core/CreatePackageFragmentOperation.java 26 Feb 2008 09:54:56 -0000 @@ -74,7 +74,7 @@ JavaElementDelta delta = null; PackageFragmentRoot root = (PackageFragmentRoot) getParentElement(); beginTask(Messages.operation_createPackageFragmentProgress, this.pkgName.length); - IContainer parentFolder = (IContainer) root.getResource(); + IContainer parentFolder = (IContainer) root.resource(); String[] sideEffectPackageName = CharOperation.NO_STRINGS; ArrayList results = new ArrayList(this.pkgName.length); char[][] inclusionPatterns = root.fullInclusionPatternChars(); @@ -114,7 +114,7 @@ protected ISchedulingRule getSchedulingRule() { if (this.pkgName.length == 0) return null; // no resource is going to be created - IResource parentResource = getParentElement().getResource(); + IResource parentResource = ((JavaElement) getParentElement()).resource(); IResource resource = ((IContainer) parentResource).getFolder(new Path(this.pkgName[0])); return resource.getWorkspace().getRuleFactory().createRule(resource); } @@ -143,11 +143,11 @@ if (this.pkgName == null || (this.pkgName.length > 0 && JavaConventions.validatePackageName(packageName, project.getOption(JavaCore.COMPILER_SOURCE, true), project.getOption(JavaCore.COMPILER_COMPLIANCE, true)).getSeverity() == IStatus.ERROR)) { return new JavaModelStatus(IJavaModelStatusConstants.INVALID_NAME, packageName); } - IPackageFragmentRoot root = (IPackageFragmentRoot) getParentElement(); + IJavaElement root = getParentElement(); if (root.isReadOnly()) { return new JavaModelStatus(IJavaModelStatusConstants.READ_ONLY, root); } - IContainer parentFolder = (IContainer) root.getResource(); + IContainer parentFolder = (IContainer) ((JavaElement) root).resource(); int i; for (i = 0; i < this.pkgName.length; i++) { IResource subFolder = parentFolder.findMember(this.pkgName[i]); Index: model/org/eclipse/jdt/internal/core/ClasspathEntry.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ClasspathEntry.java,v retrieving revision 1.98 diff -u -r1.98 ClasspathEntry.java --- model/org/eclipse/jdt/internal/core/ClasspathEntry.java 15 Oct 2007 17:39:34 -0000 1.98 +++ model/org/eclipse/jdt/internal/core/ClasspathEntry.java 26 Feb 2008 09:54:56 -0000 @@ -233,8 +233,8 @@ classpathEntryName = manager.intern(getPath().segment(0)); } else { classpathEntryType = AccessRestriction.LIBRARY; - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, false); - if (target instanceof java.io.File) { + Object target = JavaModel.getWorkspaceTarget(path); + if (target == null) { classpathEntryName = manager.intern(path.toOSString()); } else { classpathEntryName = manager.intern(path.makeRelative().toString()); @@ -1624,7 +1624,7 @@ case IClasspathEntry.CPE_LIBRARY : if (path.isAbsolute() && !path.isEmpty()) { IPath sourceAttachment = entry.getSourceAttachmentPath(); - Object target = JavaModel.getTarget(workspaceRoot, path, true); + Object target = JavaModel.getTarget(path, true); if (target != null && !JavaCore.IGNORE.equals(project.getOption(JavaCore.CORE_INCOMPATIBLE_JDK_LEVEL, true))) { long projectTargetJDK = CompilerOptions.versionToJdkLevel(project.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, true)); long libraryJDK = Util.getJdkLevel(target); @@ -1640,7 +1640,7 @@ if (checkSourceAttachment && sourceAttachment != null && !sourceAttachment.isEmpty() - && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){ + && JavaModel.getTarget(sourceAttachment, true) == null){ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName})); } } else { @@ -1651,7 +1651,7 @@ if (checkSourceAttachment && sourceAttachment != null && !sourceAttachment.isEmpty() - && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){ + && JavaModel.getTarget(sourceAttachment, true) == null){ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toString(), projectName})); } } @@ -1664,7 +1664,7 @@ } else if (checkSourceAttachment && sourceAttachment != null && !sourceAttachment.isEmpty() - && JavaModel.getTarget(workspaceRoot, sourceAttachment, true) == null){ + && JavaModel.getTarget(sourceAttachment, true) == null){ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceAttachment, new String [] {sourceAttachment.toString(), path.toOSString(), projectName})); } } else { @@ -1719,7 +1719,7 @@ } if (path.isAbsolute() && !path.isEmpty()) { IPath projectPath= project.getProject().getFullPath(); - if (!projectPath.isPrefixOf(path) || JavaModel.getTarget(workspaceRoot, path, true) == null){ + if (!projectPath.isPrefixOf(path) || JavaModel.getTarget(path, true) == null){ return new JavaModelStatus(IJavaModelStatusConstants.INVALID_CLASSPATH, Messages.bind(Messages.classpath_unboundSourceFolder, new String[] {entryPathMsg, projectName})); } } else { Index: model/org/eclipse/jdt/internal/core/JavaModelManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavaModelManager.java,v retrieving revision 1.384 diff -u -r1.384 JavaModelManager.java --- model/org/eclipse/jdt/internal/core/JavaModelManager.java 11 Feb 2008 16:50:39 -0000 1.384 +++ model/org/eclipse/jdt/internal/core/JavaModelManager.java 26 Feb 2008 09:54:58 -0000 @@ -407,6 +407,8 @@ /* whether an AbortCompilationUnit should be thrown when the source of a compilation unit cannot be retrieved */ public ThreadLocal abortOnMissingSource = new ThreadLocal(); + private ExternalFoldersManager externalFoldersManager = new ExternalFoldersManager(); + /** * Returns whether the given full path (for a package) conflicts with the output location * of the given project. @@ -899,11 +901,12 @@ * the package fragment the given resource is located in, or null * if the given resource is not on the classpath of the given project. */ - public static IJavaElement determineIfOnClasspath( - IResource resource, - IJavaProject project) { - + public static IJavaElement determineIfOnClasspath(IResource resource, IJavaProject project) { IPath resourcePath = resource.getFullPath(); + boolean isExternal = ExternalFoldersManager.isExternal(resourcePath); + if (isExternal) + resourcePath = resource.getLocation(); + try { JavaProjectElementInfo projectInfo = (JavaProjectElementInfo) getJavaModelManager().getInfo(project); ProjectCache projectCache = projectInfo == null ? null : projectInfo.projectCache; @@ -927,7 +930,10 @@ // allow creation of package fragment if it contains a .java file that is included if (!Util.isExcluded(resource, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars())) { // given we have a resource child of the root, it cannot be a JAR pkg root - PackageFragmentRoot root =(PackageFragmentRoot) ((JavaProject) project).getFolderPackageFragmentRoot(rootPath); + PackageFragmentRoot root = + isExternal ? + new ExternalPackageFragmentRoot(rootPath, (JavaProject) project) : + (PackageFragmentRoot) ((JavaProject) project).getFolderPackageFragmentRoot(rootPath); if (root == null) return null; IPath pkgPath = resourcePath.removeFirstSegments(rootPath.segmentCount()); @@ -1031,15 +1037,14 @@ public void rememberExternalLibTimestamps() { IClasspathEntry[] classpath = this.resolvedClasspath; if (classpath == null) return; - IWorkspaceRoot wRoot = ResourcesPlugin.getWorkspace().getRoot(); Map externalTimeStamps = JavaModelManager.getJavaModelManager().deltaState.getExternalLibTimeStamps(); for (int i = 0, length = classpath.length; i < length; i++) { IClasspathEntry entry = classpath[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { IPath path = entry.getPath(); if (externalTimeStamps.get(path) == null) { - Object target = JavaModel.getTarget(wRoot, path, true); - if (target instanceof java.io.File) { + Object target = JavaModel.getExternalTarget(path, true); + if (target instanceof File) { long timestamp = DeltaProcessor.getTimeStamp((java.io.File)target); externalTimeStamps.put(path, new Long(timestamp)); } @@ -1643,6 +1648,10 @@ return this.elementsOutOfSynchWithBuffers; } + public static ExternalFoldersManager getExternalManager() { + return MANAGER.externalFoldersManager; + } + public static IndexManager getIndexManager() { return MANAGER.indexManager; } @@ -3653,6 +3662,9 @@ && this.workspaceScope != null) { manager.cleanUpIndexes(); } + + // clean up external folders on full save + this.externalFoldersManager.cleanUp(null); } IProject savedProject = context.getProject(); @@ -3689,6 +3701,7 @@ // save external libs timestamps this.deltaState.saveExternalLibTimeStamps(); + } /** @@ -4073,8 +4086,8 @@ while (names.hasNext()) { Map.Entry entry2 = (Map.Entry) names.next(); String typeName = (String) entry2.getKey(); - IType type = (IType) entry2.getValue(); - if (file.equals(type.getResource())) { + JavaElement type = (JavaElement) entry2.getValue(); + if (file.equals(type.resource())) { if (removedNames == null) removedNames = new String[namesSize]; namesSize--; removedNames[removedNamesCount++] = typeName; Index: model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java,v retrieving revision 1.67 diff -u -r1.67 JarPackageFragmentRoot.java --- model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java 21 Sep 2007 13:16:47 -0000 1.67 +++ model/org/eclipse/jdt/internal/core/JarPackageFragmentRoot.java 26 Feb 2008 09:54:57 -0000 @@ -15,7 +15,6 @@ import java.util.zip.ZipFile; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.*; @@ -67,7 +66,7 @@ * These are all of the directory zip entries, and any directories implied * by the path of class files contained in the jar of this package fragment root. */ - protected boolean computeChildren(OpenableElementInfo info) throws JavaModelException { + protected boolean computeChildren(OpenableElementInfo info, IResource underlyingResource) throws JavaModelException { HashtableOfArrayToObject rawPackageInfo = new HashtableOfArrayToObject(); IJavaElement[] children; ZipFile jar = null; @@ -168,22 +167,19 @@ public PackageFragment getPackageFragment(String[] pkgName) { return new JarPackageFragment(this, pkgName); } - /** - * @see IPackageFragmentRoot - */ - public IPath getPath() { + public IPath internalPath() { if (isExternal()) { return this.jarPath; } else { - return super.getPath(); + return super.internalPath(); } - } - public IResource getResource() { - if (this.resource == null) { - this.resource = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), this.jarPath, false); + } + public IResource resource(PackageFragmentRoot root) { + if (this.resource == null && org.eclipse.jdt.internal.compiler.util.Util.isArchiveFileName(this.jarPath.lastSegment())) { + this.resource = JavaModel.getTarget(this.jarPath, false); } if (this.resource instanceof IResource) { - return super.getResource(); + return super.resource(root); } else { // external jar return null; @@ -257,7 +253,7 @@ * @see IPackageFragmentRoot */ public boolean isExternal() { - return getResource() == null; + return resource() == null; } /** * Jars and jar entries are all read only @@ -273,7 +269,6 @@ if (underlyingResource == null) { return JavaModel.getTarget( - ResourcesPlugin.getWorkspace().getRoot(), getPath(), // don't make the path relative as this is an external archive true) != null; } else { Index: model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java,v retrieving revision 1.105 diff -u -r1.105 CopyResourceElementsOperation.java --- model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java 27 Apr 2007 15:51:38 -0000 1.105 +++ model/org/eclipse/jdt/internal/core/CopyResourceElementsOperation.java 26 Feb 2008 09:54:56 -0000 @@ -108,7 +108,7 @@ for (int i = 0; i < children.length; i++) { IJavaElement child = children[i]; if (child.getElementType() == childOfInterest) { - correctKindChildren.add(child.getResource()); + correctKindChildren.add(((JavaElement) child).resource()); } } // Gather non-java resources @@ -140,7 +140,7 @@ */ private boolean createNeededPackageFragments(IContainer sourceFolder, PackageFragmentRoot root, String[] newFragName, boolean moveFolder) throws JavaModelException { boolean containsReadOnlyPackageFragment = false; - IContainer parentFolder = (IContainer) root.getResource(); + IContainer parentFolder = (IContainer) root.resource(); JavaElementDelta projectDelta = null; String[] sideEffectPackageName = null; char[][] inclusionPatterns = root.fullInclusionPatternChars(); @@ -368,12 +368,12 @@ private void processPackageFragmentResource(PackageFragment source, PackageFragmentRoot root, String newName) throws JavaModelException { try { String[] newFragName = (newName == null) ? source.names : Util.getTrimmedSimpleNames(newName); - IPackageFragment newFrag = root.getPackageFragment(newFragName); + PackageFragment newFrag = root.getPackageFragment(newFragName); IResource[] resources = collectResourcesOfInterest(source); // if isMove() can we move the folder itself ? (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=22458) - boolean shouldMoveFolder = isMove() && !newFrag.getResource().exists(); // if new pkg fragment exists, it is an override - IFolder srcFolder = (IFolder)source.getResource(); + boolean shouldMoveFolder = isMove() && !newFrag.resource().exists(); // if new pkg fragment exists, it is an override + IFolder srcFolder = (IFolder)source.resource(); IPath destPath = newFrag.getPath(); if (shouldMoveFolder) { // check if destination is not included in source @@ -390,7 +390,7 @@ } } } - boolean containsReadOnlySubPackageFragments = createNeededPackageFragments((IContainer) source.getParent().getResource(), root, newFragName, shouldMoveFolder); + boolean containsReadOnlySubPackageFragments = createNeededPackageFragments((IContainer) source.parent.resource(), root, newFragName, shouldMoveFolder); boolean sourceIsReadOnly = Util.isReadOnly(srcFolder); // Process resources @@ -479,7 +479,7 @@ if (isMove()) { // delete remaining files in this package (.class file in the case where Proj=src=bin) // in case of a copy - updateReadOnlyPackageFragmentsForMove((IContainer) source.getParent().getResource(), root, newFragName, sourceIsReadOnly); + updateReadOnlyPackageFragmentsForMove((IContainer) source.parent.resource(), root, newFragName, sourceIsReadOnly); if (srcFolder.exists()) { IResource[] remaining = srcFolder.members(); for (int i = 0, length = remaining.length; i < length; i++) { @@ -498,9 +498,9 @@ IResource rootResource; // check if source is included in destination if (destPath.isPrefixOf(srcFolder.getFullPath())) { - rootResource = newFrag.getResource(); + rootResource = newFrag.resource(); } else { - rootResource = source.getParent().getResource(); + rootResource = source.parent.resource(); } // delete recursively empty folders @@ -508,7 +508,7 @@ } } else if (containsReadOnlySubPackageFragments) { // in case of a copy - updateReadOnlyPackageFragmentsForCopy((IContainer) source.getParent().getResource(), root, newFragName); + updateReadOnlyPackageFragmentsForCopy((IContainer) source.parent.resource(), root, newFragName); } // workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=24505 if (isEmpty && isMove() && !(Util.isExcluded(source) || Util.isExcluded(newFrag))) { @@ -592,8 +592,8 @@ } } - private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, IPackageFragmentRoot root, String[] newFragName) { - IContainer parentFolder = (IContainer) root.getResource(); + private void updateReadOnlyPackageFragmentsForCopy(IContainer sourceFolder, PackageFragmentRoot root, String[] newFragName) { + IContainer parentFolder = (IContainer) root.resource(); for (int i = 0, length = newFragName.length; i java.io.File - * may or may not exist. No resource is associated with this local JAR + * may or may not exist. No resource is associated with this local library * package fragment root. * - * @param jarPath the jars's file system path - * @return a package fragment root for the JAR at the specified file system path + * @param libraryPath the library's file system path + * @return a package fragment root for the library at the specified file system path */ - IPackageFragmentRoot getPackageFragmentRoot(String jarPath); + IPackageFragmentRoot getPackageFragmentRoot(String libraryPath); /** * Returns a package fragment root for the given resource, which Index: model/org/eclipse/jdt/core/JavaCore.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/JavaCore.java,v retrieving revision 1.602 diff -u -r1.602 JavaCore.java --- model/org/eclipse/jdt/core/JavaCore.java 18 Feb 2008 08:58:21 -0000 1.602 +++ model/org/eclipse/jdt/core/JavaCore.java 26 Feb 2008 09:54:55 -0000 @@ -3168,12 +3168,11 @@ if (entry.getEntryKind() != IClasspathEntry.CPE_VARIABLE) return entry; - IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); IPath resolvedPath = JavaCore.getResolvedVariablePath(entry.getPath()); if (resolvedPath == null) return null; - Object target = JavaModel.getTarget(workspaceRoot, resolvedPath, false); + Object target = JavaModel.getTarget(resolvedPath, false); if (target == null) return null; @@ -3214,10 +3213,10 @@ entry.isExported()); } } - // outside the workspace if (target instanceof File) { File externalFile = JavaModel.getFile(target); if (externalFile != null) { + // outside the workspace String fileName = externalFile.getName().toLowerCase(); if (fileName.endsWith(SuffixConstants.SUFFIX_STRING_jar) || fileName.endsWith(SuffixConstants.SUFFIX_STRING_zip)) { // external binary archive @@ -3229,7 +3228,8 @@ entry.getExtraAttributes(), entry.isExported()); } - } else { // external binary folder + } else { + // non-existing file if (resolvedPath.isAbsolute()){ return JavaCore.newLibraryEntry( resolvedPath, @@ -3240,7 +3240,7 @@ entry.isExported()); } } - } + } return null; } @@ -3385,19 +3385,23 @@ } // avoid leaking source attachment properties (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=183413 ) + // and recreate links for external folders if needed if (monitor != null) monitor.subTask(Messages.javamodel_resetting_source_attachment_properties); + boolean externalFoldersProjectExists = JavaModelManager.getExternalManager().getExternalFoldersProject().isAccessible(); final IJavaProject[] projects = manager.getJavaModel().getJavaProjects(); HashSet visitedPaths = new HashSet(); for (int i = 0, length = projects.length; i < length; i++) { + JavaProject javaProject = (JavaProject) projects[i]; IClasspathEntry[] classpath; try { - classpath = ((JavaProject) projects[i]).getResolvedClasspath(); + classpath = javaProject.getResolvedClasspath(); } catch (JavaModelException e) { // project no longer exist: ignore continue; } if (classpath != null) { + boolean needExternalFolderCreation = false; for (int j = 0, length2 = classpath.length; j < length2; j++) { IClasspathEntry entry = classpath[j]; if (entry.getSourceAttachmentPath() != null) { @@ -3407,7 +3411,14 @@ } } // else source might have been attached by IPackageFragmentRoot#attachSource(...), we keep it + if (!needExternalFolderCreation && !externalFoldersProjectExists && entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + Object target = JavaModel.getTarget(entry.getPath(), false/*don't check existence*/); + if (target instanceof IFolder && ExternalFoldersManager.isExternal(((IFolder) target).getFullPath())) + needExternalFolderCreation = true; + } } + if (needExternalFolderCreation) + manager.deltaState.addExternalFolderChange(javaProject, null/*act as if all external folders were new*/); } } @@ -3842,6 +3853,7 @@ * @param path the absolute path of the binary archive * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, * or null if none. Note, since 3.0, an empty path is allowed to denote no source attachment. + * Since 3.4, this path can also denote a path external to the workspace. * and will be automatically converted to null. * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder * or null if this location should be automatically detected. @@ -3872,7 +3884,8 @@ * @param path the absolute path of the binary archive * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, * or null if none. Note, since 3.0, an empty path is allowed to denote no source attachment. - * and will be automatically converted to null. + * and will be automatically converted to null. Since 3.4, this path can also denote a path external + * to the workspace. * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder * or null if this location should be automatically detected. * @param isExported indicates whether this entry is contributed to dependent @@ -3902,15 +3915,15 @@ *

    * A library entry is used to denote a prerequisite JAR or root folder containing binaries. * The target JAR can either be defined internally to the workspace (absolute path relative - * to the workspace root) or externally to the workspace (absolute path in the file system). - * The target root folder can only be defined internally to the workspace (absolute path relative - * to the workspace root). To use a binary folder external to the workspace, it must first be - * linked (see IFolder#createLink(...)). + * to the workspace root), or externally to the workspace (absolute path in the file system). + * The target root folder can also be defined internally to the workspace (absolute path relative + * to the workspace root), or - since 3.4 - externally to the workspace (absolute path in the file system). *

    * e.g. Here are some examples of binary path usage

    * Note that on non-Windows platform, a path "/some/lib.jar" is ambiguous. * It can be a path to an external JAR (its file system path being "/some/lib.jar") @@ -3943,7 +3956,8 @@ * @param path the absolute path of the binary archive * @param sourceAttachmentPath the absolute path of the corresponding source archive or folder, * or null if none. Note, since 3.0, an empty path is allowed to denote no source attachment. - * and will be automatically converted to null. + * and will be automatically converted to null. Since 3.4, this path can also denote a path external + * to the workspace. * @param sourceAttachmentRootPath the location of the root of the source files within the source archive or folder * or null if this location should be automatically detected. * @param accessRules the possibly empty list of access rules for this entry Index: model/org/eclipse/jdt/core/ToolFactory.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/ToolFactory.java,v retrieving revision 1.75 diff -u -r1.75 ToolFactory.java --- model/org/eclipse/jdt/core/ToolFactory.java 28 May 2007 17:17:59 -0000 1.75 +++ model/org/eclipse/jdt/core/ToolFactory.java 26 Feb 2008 09:54:55 -0000 @@ -31,6 +31,7 @@ import org.eclipse.jdt.internal.compiler.util.SuffixConstants; import org.eclipse.jdt.internal.compiler.util.Util; import org.eclipse.jdt.internal.core.JarPackageFragmentRoot; +import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.PackageFragment; import org.eclipse.jdt.internal.core.util.ClassFileReader; @@ -226,7 +227,7 @@ } else { InputStream in = null; try { - in = ((IFile) classfile.getResource()).getContents(); + in = ((IFile) ((JavaElement) classfile).resource()).getContents(); return createDefaultClassFileReader(in, decodingFlag); } finally { if (in != null) Index: model/org/eclipse/jdt/core/IJavaElement.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/IJavaElement.java,v retrieving revision 1.39 diff -u -r1.39 IJavaElement.java --- model/org/eclipse/jdt/core/IJavaElement.java 24 Oct 2007 13:50:50 -0000 1.39 +++ model/org/eclipse/jdt/core/IJavaElement.java 26 Feb 2008 09:54:53 -0000 @@ -310,7 +310,7 @@ * Returns the innermost resource enclosing this element. * If this element is included in an archive and this archive is not external, * this is the underlying resource corresponding to the archive. - * If this element is included in an external archive, null + * If this element is included in an external library, null * is returned. * This is a handle-only method. * Index: search/org/eclipse/jdt/internal/core/search/IndexSelector.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/IndexSelector.java,v retrieving revision 1.38 diff -u -r1.38 IndexSelector.java --- search/org/eclipse/jdt/internal/core/search/IndexSelector.java 28 Aug 2007 10:03:39 -0000 1.38 +++ search/org/eclipse/jdt/internal/core/search/IndexSelector.java 26 Feb 2008 09:55:01 -0000 @@ -10,6 +10,7 @@ *******************************************************************************/ package org.eclipse.jdt.internal.core.search; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaElement; @@ -20,6 +21,7 @@ import org.eclipse.jdt.core.search.SearchPattern; import org.eclipse.jdt.internal.compiler.util.SimpleSet; import org.eclipse.jdt.internal.core.JarPackageFragmentRoot; +import org.eclipse.jdt.internal.core.JavaModel; import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.search.indexing.IndexManager; @@ -122,8 +124,13 @@ SimpleSet locations = new SimpleSet(); IJavaElement focus = MatchLocator.projectOrJarFocus(this.pattern); if (focus == null) { - for (int i = 0; i < projectsAndJars.length; i++) - locations.add(manager.computeIndexLocation(projectsAndJars[i])); + for (int i = 0; i < projectsAndJars.length; i++) { + IPath path = projectsAndJars[i]; + Object target = JavaModel.getTarget(path, false/*don't check existence*/); + if (target instanceof IFolder) // case of an external folder + path = ((IFolder) target).getFullPath(); + locations.add(manager.computeIndexLocation(path)); + } } else { try { // find the projects from projectsAndJars that see the focus then walk those projects looking for the jars from projectsAndJars @@ -131,7 +138,7 @@ JavaProject[] projectsCanSeeFocus = new JavaProject[length]; SimpleSet visitedProjects = new SimpleSet(length); int projectIndex = 0; - SimpleSet jarsToCheck = new SimpleSet(length); + SimpleSet externalLibsToCheck = new SimpleSet(length); IClasspathEntry[] focusEntries = null; if (this.pattern instanceof MethodPattern) { // should consider polymorphic search for method patterns JavaProject focusProject = focus instanceof JarPackageFragmentRoot ? (JavaProject) focus.getParent() : (JavaProject) focus; @@ -148,26 +155,28 @@ projectsCanSeeFocus[projectIndex++] = project; } } else { - jarsToCheck.add(path); + externalLibsToCheck.add(path); } } - for (int i = 0; i < projectIndex && jarsToCheck.elementSize > 0; i++) { + for (int i = 0; i < projectIndex && externalLibsToCheck.elementSize > 0; i++) { IClasspathEntry[] entries = projectsCanSeeFocus[i].getResolvedClasspath(); for (int j = entries.length; --j >= 0;) { IClasspathEntry entry = entries[j]; if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { IPath path = entry.getPath(); - if (jarsToCheck.includes(path)) { - locations.add(manager.computeIndexLocation(entry.getPath())); - jarsToCheck.remove(path); + if (externalLibsToCheck.remove(path) != null) { + Object target = JavaModel.getTarget(path, false/*don't check existence*/); + if (target instanceof IFolder) // case of an external folder + path = ((IFolder) target).getFullPath(); + locations.add(manager.computeIndexLocation(path)); } } } } // jar files can be included in the search scope without including one of the projects that references them, so scan all projects that have not been visited - if (jarsToCheck.elementSize > 0) { + if (externalLibsToCheck.elementSize > 0) { IJavaProject[] allProjects = model.getJavaProjects(); - for (int i = 0, l = allProjects.length; i < l && jarsToCheck.elementSize > 0; i++) { + for (int i = 0, l = allProjects.length; i < l && externalLibsToCheck.elementSize > 0; i++) { JavaProject project = (JavaProject) allProjects[i]; if (!visitedProjects.includes(project)) { IClasspathEntry[] entries = project.getResolvedClasspath(); @@ -175,9 +184,11 @@ IClasspathEntry entry = entries[j]; if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { IPath path = entry.getPath(); - if (jarsToCheck.includes(path)) { - locations.add(manager.computeIndexLocation(entry.getPath())); - jarsToCheck.remove(path); + if (externalLibsToCheck.remove(path) != null) { + Object target = JavaModel.getTarget(path, false/*don't check existence*/); + if (target instanceof IFolder) // case of an external folder + path = ((IFolder) target).getFullPath(); + locations.add(manager.computeIndexLocation(path)); } } } Index: search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java,v retrieving revision 1.8 diff -u -r1.8 TypeNameMatchRequestorWrapper.java --- search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java 6 Mar 2007 02:38:51 -0000 1.8 +++ search/org/eclipse/jdt/internal/core/search/TypeNameMatchRequestorWrapper.java 26 Feb 2008 09:55:02 -0000 @@ -153,10 +153,10 @@ || !(resourcePath.startsWith(this.lastPkgFragmentRootPath) && (rootPathLength = this.lastPkgFragmentRootPath.length()) > 0 && resourcePath.charAt(rootPathLength) == '/')) { - IPackageFragmentRoot root = ((JavaSearchScope)this.scope).packageFragmentRoot(resourcePath); + PackageFragmentRoot root = (PackageFragmentRoot) ((JavaSearchScope)this.scope).packageFragmentRoot(resourcePath); if (root == null) return null; this.lastPkgFragmentRoot = root; - this.lastPkgFragmentRootPath = this.lastPkgFragmentRoot.getPath().toString(); + this.lastPkgFragmentRootPath = root.internalPath().toString(); this.packageHandles = new HashtableOfArrayToObject(5); } // create handle Index: search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java,v retrieving revision 1.65 diff -u -r1.65 JavaSearchScope.java --- search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java 5 Feb 2008 15:35:14 -0000 1.65 +++ search/org/eclipse/jdt/internal/core/search/JavaSearchScope.java 26 Feb 2008 09:55:01 -0000 @@ -14,6 +14,7 @@ import java.util.HashSet; import java.util.Map; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; @@ -36,6 +37,7 @@ import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.PackageFragment; +import org.eclipse.jdt.internal.core.PackageFragmentRoot; import org.eclipse.jdt.internal.core.util.Util; /** @@ -146,9 +148,12 @@ if ((includeMask & APPLICATION_LIBRARIES) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { + Object target = JavaModel.getTarget(path, false/*don't check existence*/); + if (target instanceof IFolder) // case of an external folder + path = ((IFolder) target).getFullPath(); String pathToString = path.getDevice() == null ? path.toString() : path.toOSString(); add(projectPath.toString(), "", pathToString, false/*not a package*/, access); //$NON-NLS-1$ - addEnclosingProjectOrJar(path); + addEnclosingProjectOrJar(entry.getPath()); } } break; @@ -168,9 +173,12 @@ } IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { + Object target = JavaModel.getTarget(path, false/*don't check existence*/); + if (target instanceof IFolder) // case of an external folder + path = ((IFolder) target).getFullPath(); String pathToString = path.getDevice() == null ? path.toString() : path.toOSString(); add(projectPath.toString(), "", pathToString, false/*not a package*/, access); //$NON-NLS-1$ - addEnclosingProjectOrJar(path); + addEnclosingProjectOrJar(entry.getPath()); } break; } @@ -179,7 +187,7 @@ if ((includeMask & REFERENCED_PROJECTS) != 0) { IPath path = entry.getPath(); if (pathToAdd == null || pathToAdd.equals(path)) { - add((JavaProject) model.getJavaProject(entry.getPath().lastSegment()), null, includeMask, visitedProjects, cpEntry); + add((JavaProject) model.getJavaProject(path.lastSegment()), null, includeMask, visitedProjects, cpEntry); } } break; @@ -202,6 +210,7 @@ public void add(IJavaElement element) throws JavaModelException { IPath containerPath = null; String containerPathToString = null; + PackageFragmentRoot root = null; int includeMask = SOURCES | APPLICATION_LIBRARIES | SYSTEM_LIBRARIES; switch (element.getElementType()) { case IJavaElement.JAVA_MODEL: @@ -211,11 +220,11 @@ add((JavaProject)element, null, includeMask, new HashSet(2), null); break; case IJavaElement.PACKAGE_FRAGMENT_ROOT: - IPackageFragmentRoot root = (IPackageFragmentRoot)element; - IPath rootPath = root.getPath(); + root = (PackageFragmentRoot)element; + IPath rootPath = root.internalPath(); containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : rootPath; containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString(); - IResource rootResource = root.getResource(); + IResource rootResource = root.resource(); String projectPath = root.getJavaProject().getPath().toString(); if (rootResource != null && rootResource.isAccessible()) { String relativePath = Util.relativePath(rootResource.getFullPath(), containerPath.segmentCount()); @@ -225,7 +234,7 @@ } break; case IJavaElement.PACKAGE_FRAGMENT: - root = (IPackageFragmentRoot)element.getParent(); + root = (PackageFragmentRoot)element.getParent(); projectPath = root.getJavaProject().getPath().toString(); if (root.isArchive()) { String relativePath = Util.concatWith(((PackageFragment) element).names, '/'); @@ -233,10 +242,10 @@ containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString(); add(projectPath, relativePath, containerPathToString, true/*package*/, null); } else { - IResource resource = element.getResource(); + IResource resource = ((JavaElement) element).resource(); if (resource != null) { if (resource.isAccessible()) { - containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.getPath(); + containerPath = root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.internalPath(); } else { // for working copies, get resource container full path containerPath = resource.getParent().getFullPath(); @@ -255,22 +264,22 @@ } this.elements.add(element); } - root = (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + root = (PackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); projectPath = root.getJavaProject().getPath().toString(); String relativePath; if (root.getKind() == IPackageFragmentRoot.K_SOURCE) { containerPath = root.getParent().getPath(); - relativePath = Util.relativePath(getPath(element, false/*full path*/), 1/*remove project segmet*/); + relativePath = Util.relativePath(getPath(element, false/*full path*/), 1/*remove project segment*/); } else { - containerPath = root.getPath(); + containerPath = root.internalPath(); relativePath = getPath(element, true/*relative path*/).toString(); } containerPathToString = containerPath.getDevice() == null ? containerPath.toString() : containerPath.toOSString(); add(projectPath, relativePath, containerPathToString, false/*not a package*/, null); } - if (containerPath != null) - addEnclosingProjectOrJar(containerPath); + if (root != null) + addEnclosingProjectOrJar(root.getKind() == IPackageFragmentRoot.K_SOURCE ? root.getParent().getPath() : root.getPath()); } /** @@ -597,12 +606,12 @@ if (isJarFile) { return project.getPackageFragmentRoot(this.containerPaths[index]); } - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), new Path(this.containerPaths[index]+'/'+this.relativePaths[index]), false); + Object target = JavaModel.getWorkspaceTarget(new Path(this.containerPaths[index]+'/'+this.relativePaths[index])); if (target instanceof IProject) { return project.getPackageFragmentRoot((IProject) target); } if (target instanceof IResource) { - IJavaElement element = JavaCore.create((IResource)target); + IJavaElement element = JavaModelManager.create((IResource) target, project); return (IPackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); } } Index: search/org/eclipse/jdt/internal/core/search/HierarchyScope.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/HierarchyScope.java,v retrieving revision 1.43 diff -u -r1.43 HierarchyScope.java --- search/org/eclipse/jdt/internal/core/search/HierarchyScope.java 27 Sep 2007 16:33:52 -0000 1.43 +++ search/org/eclipse/jdt/internal/core/search/HierarchyScope.java 26 Feb 2008 09:55:01 -0000 @@ -72,7 +72,7 @@ IPackageFragmentRoot root = (IPackageFragmentRoot)type.getPackageFragment().getParent(); if (root.isArchive()) { IPath jarPath = root.getPath(); - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), jarPath, true); + Object target = JavaModel.getTarget(jarPath, true); String zipFileName; if (target instanceof IFile) { // internal jar @@ -101,10 +101,9 @@ HashMap resources = new HashMap(); HashMap paths = new HashMap(); this.types = this.hierarchy.getAllTypes(); - IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); for (int i = 0; i < this.types.length; i++) { IType type = this.types[i]; - IResource resource = type.getResource(); + IResource resource = ((JavaElement) type).resource(); if (resource != null && resources.get(resource) == null) { resources.put(resource, resource); add(resource); @@ -115,7 +114,7 @@ // type in a jar JarPackageFragmentRoot jar = (JarPackageFragmentRoot) root; IPath jarPath = jar.getPath(); - Object target = JavaModel.getTarget(workspaceRoot, jarPath, true); + Object target = JavaModel.getTarget(jarPath, true); String zipFileName; if (target instanceof IFile) { // internal jar Index: search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java,v retrieving revision 1.52 diff -u -r1.52 BasicSearchEngine.java --- search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java 15 Jan 2008 10:00:51 -0000 1.52 +++ search/org/eclipse/jdt/internal/core/search/BasicSearchEngine.java 26 Feb 2008 09:55:01 -0000 @@ -1140,7 +1140,7 @@ Util.verbose(" - java element: "+enclosingElement); //$NON-NLS-1$ } IJavaSearchScope scope = createJavaSearchScope(new IJavaElement[] {enclosingElement}); - IResource resource = enclosingElement.getResource(); + IResource resource = ((JavaElement) enclosingElement).resource(); if (enclosingElement instanceof IMember) { IMember member = (IMember) enclosingElement; ICompilationUnit cu = member.getCompilationUnit(); Index: model/org/eclipse/jdt/internal/core/util/Util.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/Util.java,v retrieving revision 1.115 diff -u -r1.115 Util.java --- model/org/eclipse/jdt/internal/core/util/Util.java 16 Jan 2008 11:52:53 -0000 1.115 +++ model/org/eclipse/jdt/internal/core/util/Util.java 26 Feb 2008 09:55:00 -0000 @@ -50,6 +50,7 @@ import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.JavaModelManager; import org.eclipse.jdt.internal.core.MemberValuePair; +import org.eclipse.jdt.internal.core.PackageFragment; import org.eclipse.jdt.internal.core.PackageFragmentRoot; import org.eclipse.jface.text.BadLocationException; import org.eclipse.text.edits.MalformedTreeException; @@ -1312,12 +1313,12 @@ return false; case IJavaElement.PACKAGE_FRAGMENT: - PackageFragmentRoot root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); - IResource resource = element.getResource(); + PackageFragmentRoot root = (PackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + IResource resource = ((PackageFragment) element).resource(); return resource != null && isExcluded(resource, root.fullInclusionPatternChars(), root.fullExclusionPatternChars()); case IJavaElement.COMPILATION_UNIT: - root = (PackageFragmentRoot)element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); + root = (PackageFragmentRoot) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT); resource = element.getResource(); if (resource == null) return false; Index: model/org/eclipse/jdt/internal/core/util/HandleFactory.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/util/HandleFactory.java,v retrieving revision 1.43 diff -u -r1.43 HandleFactory.java --- model/org/eclipse/jdt/internal/core/util/HandleFactory.java 10 Jan 2008 15:45:03 -0000 1.43 +++ model/org/eclipse/jdt/internal/core/util/HandleFactory.java 26 Feb 2008 09:55:00 -0000 @@ -33,18 +33,10 @@ import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.internal.compiler.ast.*; -import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; -import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; -import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.Scope; import org.eclipse.jdt.internal.core.*; -import org.eclipse.jdt.internal.core.JavaModel; -import org.eclipse.jdt.internal.core.JavaModelManager; -import org.eclipse.jdt.internal.core.JavaProject; -import org.eclipse.jdt.internal.core.Openable; -import org.eclipse.jdt.internal.core.PackageFragmentRoot; import org.eclipse.jdt.internal.core.util.Util; /** @@ -128,7 +120,7 @@ if (root == null) return null; // match is outside classpath this.lastPkgFragmentRoot = root; - this.lastPkgFragmentRootPath = this.lastPkgFragmentRoot.getPath().toString(); + this.lastPkgFragmentRootPath = this.lastPkgFragmentRoot.internalPath().toString(); this.packageHandles = new HashtableOfArrayToObject(5); } // create handle @@ -252,7 +244,7 @@ IPath jarPath= new Path(jarPathString); - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), jarPath, false); + Object target = JavaModel.getTarget(jarPath, false); if (target instanceof IFile) { // internal jar: is it on the classpath of its project? // e.g. org.eclipse.swt.win32/ws/win32/swt.jar @@ -341,7 +333,7 @@ IPackageFragmentRoot[] roots= javaProject.getPackageFragmentRoots(); for (int j= 0, rootCount= roots.length; j < rootCount; j++) { PackageFragmentRoot root= (PackageFragmentRoot)roots[j]; - if (root.getPath().isPrefixOf(path) && !Util.isExcluded(path, root.fullInclusionPatternChars(), root.fullExclusionPatternChars(), false)) { + if (root.internalPath().isPrefixOf(path) && !Util.isExcluded(path, root.fullInclusionPatternChars(), root.fullExclusionPatternChars(), false)) { return root; } } Index: search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java,v retrieving revision 1.309 diff -u -r1.309 MatchLocator.java --- search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java 30 Jan 2008 15:58:34 -0000 1.309 +++ search/org/eclipse/jdt/internal/core/search/matching/MatchLocator.java 26 Feb 2008 09:55:03 -0000 @@ -278,7 +278,7 @@ IPackageFragmentRoot root = (IPackageFragmentRoot) pkg.getParent(); try { if (!root.isArchive()) - return Util.newClassFileReader(type.getResource()); + return Util.newClassFileReader(((JavaElement) type).resource()); ZipFile zipFile = null; try { @@ -425,7 +425,7 @@ if (binaryType == null) { ClassFile classFile = (ClassFile) type.getClassFile(); try { - binaryType = getBinaryInfo(classFile, classFile.getResource()); + binaryType = getBinaryInfo(classFile, classFile.resource()); } catch (CoreException e) { if (e instanceof JavaModelException) { throw (JavaModelException) e; @@ -1186,7 +1186,7 @@ JavaProject javaProject = (JavaProject) openable.getJavaProject(); resource = workingCopy != null ? workingCopy.getResource() : openable.getResource(); if (resource == null) - resource = javaProject.getProject(); // case of a file in an external jar + resource = javaProject.getProject(); // case of a file in an external jar or external folder if (!javaProject.equals(previousJavaProject)) { // locate matches in previous project if (previousJavaProject != null) { @@ -1559,7 +1559,7 @@ if (unit.isEmpty()) { if (this.currentPossibleMatch.openable instanceof ClassFile) { ClassFile classFile = (ClassFile) this.currentPossibleMatch.openable; - IBinaryType info = getBinaryInfo(classFile, this.currentPossibleMatch.resource); + IBinaryType info = getBinaryInfo(classFile, classFile.resource()); if (info != null) { boolean mayBeGeneric = this.patternLocator.mayBeGeneric; this.patternLocator.mayBeGeneric = false; // there's no longer generics in class files Index: search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java,v retrieving revision 1.25 diff -u -r1.25 JavaSearchNameEnvironment.java --- search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java 29 Mar 2006 03:13:59 -0000 1.25 +++ search/org/eclipse/jdt/internal/core/search/matching/JavaSearchNameEnvironment.java 26 Feb 2008 09:55:02 -0000 @@ -98,7 +98,7 @@ ZipFile zipFile = manager.getZipFile(path); cpLocations[index++] = new ClasspathJar(zipFile, ((ClasspathEntry) root.getRawClasspathEntry()).getAccessRuleSet()); } else { - Object target = JavaModel.getTarget(workspaceRoot, path, false); + Object target = JavaModel.getTarget(path, true); if (target == null) { // target doesn't exist any longer // just resize cpLocations Index: model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java,v retrieving revision 1.60 diff -u -r1.60 NameEnvironment.java --- model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java 9 May 2007 14:21:18 -0000 1.60 +++ model/org/eclipse/jdt/internal/core/builder/NameEnvironment.java 26 Feb 2008 09:55:00 -0000 @@ -96,7 +96,7 @@ nextEntry : for (int i = 0, l = classpathEntries.length; i < l; i++) { ClasspathEntry entry = (ClasspathEntry) classpathEntries[i]; IPath path = entry.getPath(); - Object target = JavaModel.getTarget(root, path, true); + Object target = JavaModel.getTarget(path, true); if (target == null) continue nextEntry; switch(entry.getEntryKind()) { @@ -128,7 +128,7 @@ nextPrereqEntry: for (int j = 0, m = prereqClasspathEntries.length; j < m; j++) { IClasspathEntry prereqEntry = prereqClasspathEntries[j]; if (prereqEntry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { - Object prereqTarget = JavaModel.getTarget(root, prereqEntry.getPath(), true); + Object prereqTarget = JavaModel.getTarget(prereqEntry.getPath(), true); if (!(prereqTarget instanceof IContainer)) continue nextPrereqEntry; IPath prereqOutputPath = prereqEntry.getOutputLocation() != null ? prereqEntry.getOutputLocation() Index: model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java,v retrieving revision 1.137 diff -u -r1.137 JavaBuilder.java --- model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java 17 Oct 2007 19:16:29 -0000 1.137 +++ model/org/eclipse/jdt/internal/core/builder/JavaBuilder.java 26 Feb 2008 09:54:59 -0000 @@ -429,6 +429,7 @@ if (javaProject == null || workspaceRoot == null) return new IProject[0]; ArrayList projects = new ArrayList(); + ExternalFoldersManager externalFoldersManager = JavaModelManager.getExternalManager(); try { IClasspathEntry[] entries = javaProject.getExpandedClasspath(); for (int i = 0, l = entries.length; i < l; i++) { @@ -445,8 +446,13 @@ if (includeBinaryPrerequisites && path.segmentCount() > 1) { // some binary resources on the class path can come from projects that are not included in the project references IResource resource = workspaceRoot.findMember(path.segment(0)); - if (resource instanceof IProject) + if (resource instanceof IProject) { p = (IProject) resource; + } else { + resource = externalFoldersManager.getFolder(path); + if (resource != null) + p = resource.getProject(); + } } } if (p != null && !projects.contains(p)) Index: search/org/eclipse/jdt/core/search/SearchParticipant.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/core/search/SearchParticipant.java,v retrieving revision 1.24 diff -u -r1.24 SearchParticipant.java --- search/org/eclipse/jdt/core/search/SearchParticipant.java 28 Aug 2007 10:03:38 -0000 1.24 +++ search/org/eclipse/jdt/core/search/SearchParticipant.java 26 Feb 2008 09:55:00 -0000 @@ -11,8 +11,6 @@ package org.eclipse.jdt.core.search; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IWorkspaceRoot; -import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.*; import org.eclipse.jdt.internal.core.JavaModel; import org.eclipse.jdt.internal.core.JavaModelManager; @@ -196,8 +194,7 @@ */ public final void scheduleDocumentIndexing(SearchDocument document, IPath indexLocation) { IPath documentPath = new Path(document.getPath()); - IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); - Object file = JavaModel.getTarget(root, documentPath, true); + Object file = JavaModel.getTarget(documentPath, true); IPath containerPath = documentPath; if (file instanceof IResource) { containerPath = ((IResource)file).getProject().getFullPath(); Index: model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java,v retrieving revision 1.82 diff -u -r1.82 HierarchyResolver.java --- model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java 22 Feb 2008 12:35:09 -0000 1.82 +++ model/org/eclipse/jdt/internal/core/hierarchy/HierarchyResolver.java 26 Feb 2008 09:55:00 -0000 @@ -697,7 +697,7 @@ if (classFile.getPackageFragmentRoot().isArchive()) { binaryType = this.builder.createInfoFromClassFileInJar(classFile); } else { - IResource file = classFile.getResource(); + IResource file = classFile.resource(); binaryType = this.builder.createInfoFromClassFile(classFile, file); } } Index: codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java,v retrieving revision 1.143 diff -u -r1.143 SelectionEngine.java --- codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java 22 Feb 2008 09:49:37 -0000 1.143 +++ codeassist/org/eclipse/jdt/internal/codeassist/SelectionEngine.java 26 Feb 2008 09:54:53 -0000 @@ -1133,7 +1133,7 @@ } } else { // binary type ClassFile classFile = (ClassFile) context.getClassFile(); - ClassFileReader reader = (ClassFileReader) classFile.getBinaryTypeInfo((IFile) classFile.getResource(), false/*don't fully initialize so as to keep constant pool (used below)*/); + ClassFileReader reader = (ClassFileReader) classFile.getBinaryTypeInfo((IFile) classFile.resource(), false/*don't fully initialize so as to keep constant pool (used below)*/); CompilationResult result = new CompilationResult(reader.getFileName(), 1, 1, this.compilerOptions.maxProblemsPerUnit); parsedUnit = new CompilationUnitDeclaration(this.parser.problemReporter(), result, 0); HashSetOfCharArrayArray typeNames = new HashSetOfCharArrayArray(); Index: search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java,v retrieving revision 1.155 diff -u -r1.155 IndexManager.java --- search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java 1 Mar 2007 18:38:55 -0000 1.155 +++ search/org/eclipse/jdt/internal/core/search/indexing/IndexManager.java 26 Feb 2008 09:55:02 -0000 @@ -353,16 +353,12 @@ // requestingProject is no longer used to cancel jobs but leave it here just in case if (JavaCore.getPlugin() == null) return; - Object target = JavaModel.getTarget(ResourcesPlugin.getWorkspace().getRoot(), path, true); + Object target = JavaModel.getTarget(path, true); IndexRequest request = null; if (target instanceof IFile) { request = new AddJarFileToIndex((IFile) target, this); } else if (target instanceof File) { - if (((File) target).isFile()) { - request = new AddJarFileToIndex(path, this); - } else { - return; - } + request = new AddJarFileToIndex(path, this); } else if (target instanceof IContainer) { request = new IndexBinaryFolder((IContainer) target, this); } else { @@ -417,9 +413,7 @@ return Messages.process_name; } private void rebuildIndex(IPath indexLocation, IPath containerPath) { - IWorkspace workspace = ResourcesPlugin.getWorkspace(); - if (workspace == null) return; - Object target = JavaModel.getTarget(workspace.getRoot(), containerPath, true); + Object target = JavaModel.getTarget(containerPath, true); if (target == null) return; if (VERBOSE) Index: model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java =================================================================== RCS file: model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java diff -N model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ model/org/eclipse/jdt/internal/core/ExternalFoldersManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,187 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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.core; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; + +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.IWorkspaceRunnable; +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.jdt.core.IJavaProject; +import org.eclipse.jdt.core.JavaCore; +import org.eclipse.jdt.internal.core.util.Util; + +public class ExternalFoldersManager { + private static final boolean DEBUG = false; + private static final String EXTERNAL_PROJECT_NAME = ".org.eclipse.jdt.core.external.folders"; //$NON-NLS-1$ + private static final String LINKED_FOLDER_NAME = ".link"; //$NON-NLS-1$ + private HashMap folders; + private int counter = 0; + + { + this.folders = new HashMap(); + IProject project = getExternalFoldersProject(); + if (project.isAccessible()) { + try { + 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(); + this.folders.put(externalFolderPath, member); + } + } + } catch (CoreException e) { + Util.log(e, "Exception while initializing external folders"); //$NON-NLS-1$ + } + } + } + + public static boolean isExternal(IPath resourcePath) { + return EXTERNAL_PROJECT_NAME.equals(resourcePath.segment(0)); + } + + public IFolder addFolder(IPath externalFolderPath) { + return addFolder(externalFolderPath, getExternalFoldersProject()); + } + + private synchronized IFolder addFolder(IPath externalFolderPath, IProject externalFoldersProject) { + Object existing = this.folders.get(externalFolderPath); + if (existing != null) { + return (IFolder) existing; + } + IFolder result; + do { + result = externalFoldersProject.getFolder(LINKED_FOLDER_NAME + this.counter++); + } while (result.exists()); + this.folders.put(externalFolderPath, result); + return result; + } + + public IFolder createLinkFolder(IPath externalFolderPath, IProgressMonitor monitor) throws CoreException { + IProject externalFoldersProject = createExternalFoldersProject(monitor); // run outside synchronized as this can create a resource + IFolder result = addFolder(externalFolderPath, externalFoldersProject); + if (!result.exists()) + result.createLink(externalFolderPath, IResource.ALLOW_MISSING_LOCAL, monitor); + else + result.refreshLocal(IResource.DEPTH_INFINITE, monitor); + return result; + } + + public synchronized void cleanUp(IProgressMonitor monitor) throws CoreException { + DeltaProcessingState state = JavaModelManager.getDeltaState(); + HashMap roots = state.roots; + HashMap sourceAttachments = state.sourceAttachments; + if (roots == null && sourceAttachments == null) + return; + Iterator iterator = this.folders.keySet().iterator(); + while (iterator.hasNext()) { + IPath path = (IPath) iterator.next(); + if ((roots != null && !roots.containsKey(path)) + && (sourceAttachments != null && !sourceAttachments.containsKey(path))) { + IFolder folder = (IFolder) this.folders.get(path); + if (folder != null) + folder.delete(true, monitor); + } + } + IProject project = getExternalFoldersProject(); + if (project.isAccessible() && project.members().length == 1/*remaining member is .project*/) + project.delete(true, monitor); + } + + public IProject getExternalFoldersProject() { + return ResourcesPlugin.getWorkspace().getRoot().getProject(EXTERNAL_PROJECT_NAME); + } + private IProject createExternalFoldersProject(IProgressMonitor monitor) { + IProject project = getExternalFoldersProject(); + if (!project.isAccessible()) { + try { + if (!project.exists()) { + IProjectDescription desc = project.getWorkspace().newProjectDescription(project.getName()); + IPath stateLocation = JavaCore.getPlugin().getStateLocation(); + desc.setLocation(stateLocation.append(EXTERNAL_PROJECT_NAME)); + project.create(DEBUG ? null : desc, DEBUG ? IResource.NONE : IResource.HIDDEN, monitor); + } + try { + project.open(monitor); + } catch (CoreException e1) { + // .project or folder on disk have been deleted, recreate them + IPath stateLocation = DEBUG ? ResourcesPlugin.getWorkspace().getRoot().getLocation() : JavaCore.getPlugin().getStateLocation(); + IPath projectPath = stateLocation.append(EXTERNAL_PROJECT_NAME); + projectPath.toFile().mkdirs(); + FileOutputStream output = new FileOutputStream(projectPath.append(".project").toOSString()); //$NON-NLS-1$ + try { + output.write(( + "\n" + //$NON-NLS-1$ + "\n" + //$NON-NLS-1$ + " " + EXTERNAL_PROJECT_NAME + "\n" + //$NON-NLS-1$ //$NON-NLS-2$ + " \n" + //$NON-NLS-1$ + " \n" + //$NON-NLS-1$ + " \n" + //$NON-NLS-1$ + " \n" + //$NON-NLS-1$ + " \n" + //$NON-NLS-1$ + " \n" + //$NON-NLS-1$ + " \n" + //$NON-NLS-1$ + "").getBytes()); //$NON-NLS-1$ + } finally { + output.close(); + } + project.open(null); + } + } catch (CoreException e) { + Util.log(e, "Problem creating hidden project for external folders"); //$NON-NLS-1$ + return project; + } catch (IOException e) { + Util.log(e, "Problem creating hidden project for external folders"); //$NON-NLS-1$ + return project; + } + } + return project; + } + + public synchronized IFolder getFolder(IPath externalFolderPath) { + return (IFolder) this.folders.get(externalFolderPath); + } + + public void refreshExternalFolders(IProgressMonitor monitor) throws CoreException { + final IProject project = getExternalFoldersProject(); + + // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=63782 + JavaModelManager manager = JavaModelManager.getJavaModelManager(); + IJavaProject[] projects = manager.getJavaModel().getJavaProjects(); + DeltaProcessingState deltaState = JavaModelManager.getDeltaState(); + for (int i = 0, length = projects.length; i < length; i++) { + JavaProject javaProject = (JavaProject) projects[i]; + deltaState.addClasspathValidation(javaProject); + } + + ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable(){ + public void run(IProgressMonitor pm) throws CoreException { + project.touch(pm); + project.refreshLocal(IResource.DEPTH_INFINITE, pm); + } + }, monitor); + } + + public synchronized IFolder removeFolder(IPath externalFolderPath) { + return (IFolder) this.folders.remove(externalFolderPath); + } + +} Index: model/org/eclipse/jdt/internal/core/ExternalFolderChange.java =================================================================== RCS file: model/org/eclipse/jdt/internal/core/ExternalFolderChange.java diff -N model/org/eclipse/jdt/internal/core/ExternalFolderChange.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ model/org/eclipse/jdt/internal/core/ExternalFolderChange.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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.core; + +import java.io.File; +import java.util.HashSet; +import java.util.Iterator; + +import org.eclipse.core.resources.IFolder; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.core.IClasspathEntry; +import org.eclipse.jdt.core.JavaModelException; +import org.eclipse.jdt.internal.compiler.util.Util; + +public class ExternalFolderChange { + + private JavaProject project; + private IClasspathEntry[] oldResolvedClasspath; + + public ExternalFolderChange(JavaProject project, IClasspathEntry[] oldResolvedClasspath) { + this.project = project; + this.oldResolvedClasspath = oldResolvedClasspath; + } + + private HashSet getExternalFolders(IClasspathEntry[] classpath) { + HashSet folders = new HashSet(); + for (int i = 0; i < classpath.length; i++) { + IClasspathEntry entry = classpath[i]; + if (entry.getEntryKind() == IClasspathEntry.CPE_LIBRARY) { + addExternalFolder(entry.getPath(), folders); + addExternalFolder(entry.getSourceAttachmentPath(), folders); + } + } + return folders; + } + + private void addExternalFolder(IPath path, HashSet folders) { + if (path == null || Util.isArchiveFileName(path.lastSegment())) + return; + Object target = JavaModel.getTarget(path, false/*don't check resource existence*/); + if (target instanceof File) { + if (!((File) target).isFile()) { + folders.add(path); + } + } else if (target instanceof IFolder && ExternalFoldersManager.isExternal(((IFolder) target).getFullPath())) { + folders.add(path); + } + } + + /* + * Update external folders + */ + public void updateExternalFoldersIfNecessary(IProgressMonitor monitor) throws JavaModelException { + HashSet oldFolders = this.oldResolvedClasspath == null ? new HashSet() : getExternalFolders(this.oldResolvedClasspath); + IClasspathEntry[] newResolvedClasspath = this.project.getResolvedClasspath(); + HashSet newFolders = getExternalFolders(newResolvedClasspath); + ExternalFoldersManager foldersManager = JavaModelManager.getExternalManager(); + Iterator iterator = newFolders.iterator(); + while (iterator.hasNext()) { + Object folderPath = iterator.next(); + if (!oldFolders.remove(folderPath)) { + try { + foldersManager.createLinkFolder((IPath) folderPath, monitor); + } catch (CoreException e) { + throw new JavaModelException(e); + } + } + } + // removal of linked folders is done during save + } + public String toString() { + return "ExternalFolderChange: " + this.project.getElementName(); //$NON-NLS-1$ + } +} Index: model/org/eclipse/jdt/internal/core/ExternalPackageFragmentRoot.java =================================================================== RCS file: model/org/eclipse/jdt/internal/core/ExternalPackageFragmentRoot.java diff -N model/org/eclipse/jdt/internal/core/ExternalPackageFragmentRoot.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ model/org/eclipse/jdt/internal/core/ExternalPackageFragmentRoot.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,112 @@ +/******************************************************************************* + * Copyright (c) 2000, 2008 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.core; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.core.IJavaElement; +import org.eclipse.jdt.core.IPackageFragmentRoot; +import org.eclipse.jdt.core.JavaModelException; + +/** + * A package fragment root that corresponds to an external class folder. + * + *

    NOTE: An external package fragment root never has an associated resource. + * + * @see org.eclipse.jdt.core.IPackageFragmentRoot + * @see org.eclipse.jdt.internal.core.PackageFragmentRootInfo + */ +public class ExternalPackageFragmentRoot extends PackageFragmentRoot { + + /** + * The path to the external folder + * (an OS path) + */ + protected final IPath externalPath; + + /** + * Constructs a package fragment root which is the root of the Java package directory hierarchy + * based on an external folder that is not contained in a IJavaProject and + * does not have an associated IResource. + */ + protected ExternalPackageFragmentRoot(IPath externalPath, JavaProject project) { + super(null, project); + this.externalPath = externalPath; + } + + protected ExternalPackageFragmentRoot(IResource linkedFolder, IPath externalPath, JavaProject project) { + super(linkedFolder, project); + this.externalPath = externalPath == null ? linkedFolder.getLocation() : externalPath; + } + + /** + * An external class folder is always K_BINARY. + */ + protected int determineKind(IResource underlyingResource) { + return IPackageFragmentRoot.K_BINARY; + } + /** + * Returns true if this handle represents the same external folder + * as the given handle. + * + * @see Object#equals + */ + public boolean equals(Object o) { + if (this == o) + return true; + if (o instanceof ExternalPackageFragmentRoot) { + ExternalPackageFragmentRoot other= (ExternalPackageFragmentRoot) o; + return this.externalPath.equals(other.externalPath); + } + return false; + } + public String getElementName() { + return this.externalPath.lastSegment(); + } + /** + * @see IPackageFragmentRoot + */ + public int getKind() { + return IPackageFragmentRoot.K_BINARY; + } + /** + * @see IPackageFragmentRoot + */ + public IPath getPath() { + return this.externalPath; + } + + /** + * @see IJavaElement + */ + public IResource getUnderlyingResource() throws JavaModelException { + return null; + } + public int hashCode() { + return this.externalPath.hashCode(); + } + /** + * @see IPackageFragmentRoot + */ + public boolean isExternal() { + return true; + } + + public IResource resource(PackageFragmentRoot root) { + if (this.resource == null) + return (IResource) (this.resource = JavaModelManager.getExternalManager().getFolder(this.externalPath)); + return super.resource(root); + } + + protected void toStringAncestors(StringBuffer buffer) { + // don't show project as it is irrelevant for external folders. + } +} #P org.eclipse.jdt.core.tests.model Index: src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java,v retrieving revision 1.55 diff -u -r1.55 ClasspathInitializerTests.java --- src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java 11 Oct 2007 11:32:42 -0000 1.55 +++ src/org/eclipse/jdt/core/tests/model/ClasspathInitializerTests.java 26 Feb 2008 09:55:06 -0000 @@ -890,6 +890,26 @@ } } +public void testContainerInitializer21() throws CoreException { + try { + createProject("P1"); + createExternalFolder("externalLib"); + ContainerInitializer.setInitializer(new DefaultContainerInitializer(new String[] {"P2", getExternalFolderPath("externalLib")})); + IJavaProject p2 = createJavaProject( + "P2", + new String[] {}, + new String[] {"org.eclipse.jdt.core.tests.model.TEST_CONTAINER"}, + ""); + IPackageFragmentRoot root = p2.getPackageFragmentRoot(getExternalFolderPath("externalLib")); + assertTrue(getExternalFolderPath("externalLib") + " should exist", root.exists()); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P1"); + deleteProject("P2"); + } +} + public void testVariableInitializer01() throws CoreException { try { createProject("P1"); Index: src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java,v retrieving revision 1.33 diff -u -r1.33 ExternalJarDeltaTests.java --- src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java 18 Dec 2007 16:32:55 -0000 1.33 +++ src/org/eclipse/jdt/core/tests/model/ExternalJarDeltaTests.java 26 Feb 2008 09:55:07 -0000 @@ -44,9 +44,6 @@ // TESTS_NUMBERS = new int[] { 79860, 80918, 91078 }; // TESTS_RANGE = new int[] { 83304, -1 }; } -private void touch(File f) { - f.setLastModified(f.lastModified() + 10000); -} /* * Ensures that passing an empty scope to refreshExternalArchives(..) doesn't throw a NPE Index: src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java,v retrieving revision 1.90 diff -u -r1.90 JavaProjectTests.java --- src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java 17 Dec 2007 11:08:07 -0000 1.90 +++ src/org/eclipse/jdt/core/tests/model/JavaProjectTests.java 26 Feb 2008 09:55:08 -0000 @@ -55,6 +55,116 @@ super.tearDownSuite(); } +/* + * Ensures that adding a library entry for an existing empty external library folder updates the model + */ +public void testAddExternalLibFolder1() throws CoreException { + try { + IJavaProject p = createJavaProject("P"); + createExternalFolder("externalLib"); + setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path(getExternalFolderPath("externalLib")), null, null)}); + assertElementDescendants( + "Unexpected project content", + "P\n" + + " "+ getExternalPath() + "externalLib\n" + + " (...)", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that adding a library entry for an non-existing external library folder updates the model + */ +public void testAddExternalLibFolder2() throws CoreException { + try { + IJavaProject p = createJavaProject("P"); + IPath path = new Path(getExternalFolderPath("externalLib")); + setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(path, null, null)}); + assertElementDescendants( + "Unexpected project content", + "P", + p + ); + } finally { + deleteProject("P"); + } +} + +/* + * Ensures that adding a library entry for an existing non-empty external library folder updates the model + */ +public void testAddExternalLibFolder3() throws CoreException, IOException { + try { + IJavaProject p = createJavaProject("P"); + createExternalFolder("externalLib/p"); + createExternalFile("externalLib/p/X.class", ""); + setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path(getExternalFolderPath("externalLib")), null, null)}); + assertElementDescendants( + "Unexpected project content", + "P\n" + + " "+ getExternalPath() + "externalLib\n" + + " (...)\n" + + " p (...)\n" + + " X.class", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that creating an external library folder referenced by a library entry and refreshing updates the model + */ +public void testAddExternalLibFolder4() throws CoreException { + try { + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + expandAll(p); + createExternalFolder("externalLib"); + refresh(p); + assertElementDescendants( + "Unexpected project content", + "P\n" + + " "+ getExternalPath() + "externalLib\n" + + " (...)", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that importing a Java project with a library entry for an existing empty external library folder after restart + * updates the model + */ +public void testAddExternalLibFolder5() throws CoreException { + try { + simulateExitRestart(); + createExternalFolder("externalLib/p"); + createExternalFile("externalLib/p/X.class", ""); + IJavaProject p = importJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); + assertElementDescendants( + "Unexpected project content", + "P\n" + + " "+ getExternalPath() + "externalLib\n" + + " (...)\n" + + " p (...)\n" + + " X.class", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} /** * Test adding a non-java resource in a package fragment root that correspond to @@ -140,6 +250,59 @@ IResource corr= type.getCorrespondingResource(); assertTrue("incorrect corresponding resource", corr == null); } + +/* + * Ensures that changing the content of an external library folder and refreshing updates the model + */ +public void testChangeExternalLibFolder1() throws CoreException, IOException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, "bin"); + expandAll(p); + + createExternalFolder("externalLib/p"); + createExternalFile("externalLib/p/X.class", ""); + refresh(p); + assertElementDescendants( + "Unexpected project content", + "P\n" + + " "+ getExternalPath() + "externalLib\n" + + " (...)\n" + + " p (...)\n" + + " X.class", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that changing the content of an external library folder and refreshing updates the model + */ +public void testChangeExternalLibFolder2() throws CoreException, IOException { + try { + createExternalFolder("externalLib/p"); + createExternalFile("externalLib/p/X.class", ""); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, "bin"); + expandAll(p); + + deleteExternalFolder("externalLib/p"); + refresh(p); + assertElementDescendants( + "Unexpected project content", + "P\n" + + " "+ getExternalPath() + "externalLib\n" + + " (...)", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + /** * When the output location is changed, package fragments can be added/removed */ @@ -856,6 +1019,26 @@ } /* + * Ensure that the non-Java resources of a package in an external library folder are correct. + */ +public void testPackageFragmentNonJavaResources12() throws CoreException { + try { + createExternalFolder("externalLib/p/META-INF"); + createExternalFile("externalLib/p/test.txt", "test"); + createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + IPackageFragment pkg = getPackageFragmentRoot("P", getExternalFolderPath("externalLib")).getPackageFragment("p"); + Object[] resources = pkg.getNonJavaResources(); + assertResourceTreeEquals( + "unexpected non java resources", + "", + resources); + } finally { + deleteProject("P"); + deleteExternalFolder("externalLib"); + } +} + +/* * Ensures that the package-info.class file doesn't appear as a child of a package if proj=src * (regression test for bug 99654 [5.0] JavaModel returns both IClassFile and ICompilationUnit for package-info.java) */ @@ -997,6 +1180,25 @@ "lib.jar [in JavaProjectTests]", parentRoot); } +/* + * Ensures that the non-Java resources of an external library package fragment root are correct + */ +public void testPackageFragmentRootNonJavaResources8() throws CoreException { + try { + createExternalFolder("externalLib/META-INF"); + createExternalFile("externalLib/test.txt", "test"); + createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + IPackageFragmentRoot root = getPackageFragmentRoot("P", getExternalFolderPath("externalLib")); + Object[] resources = root.getNonJavaResources(); + assertResourceTreeEquals( + "unexpected non java resources", + "", + resources); + } finally { + deleteProject("P"); + deleteExternalFolder("externalLib"); + } +} /** * Test raw entry inference performance for package fragment root */ @@ -1395,6 +1597,66 @@ } } +/* + * Ensures that removing a library entry for an existing external library folder updates the model + */ +public void testRemoveExternalLibFolder1() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + expandAll(p); + setClasspath(p, new IClasspathEntry[] {}); + assertElementDescendants( + "Unexpected project content", + "P", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that removing a library entry for a non-existing external library folder updates the model + */ +public void testRemoveExternalLibFolder2() throws CoreException { + try { + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + expandAll(p); + setClasspath(p, new IClasspathEntry[] {}); + assertElementDescendants( + "Unexpected project content", + "P", + p + ); + } finally { + deleteProject("P"); + } +} + + +/* + * Ensures that removing an external library folder referenced by a library entry and refreshing updates the model + */ +public void testRemoveExternalLibFolder3() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + expandAll(p); + deleteExternalFolder("externalLib"); + refresh(p); + assertElementDescendants( + "Unexpected project content", + "P", + p + ); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + /** * Test that the correct package fragments exist in the project. */ Index: src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java,v retrieving revision 1.81 diff -u -r1.81 TypeHierarchyTests.java --- src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java 23 Jan 2008 12:42:37 -0000 1.81 +++ src/org/eclipse/jdt/core/tests/model/TypeHierarchyTests.java 26 Feb 2008 09:55:09 -0000 @@ -696,6 +696,39 @@ } } /* + * Ensures that subtypes are found in an external library folder + */ +public void testExternalFolder() throws CoreException, IOException { + try { + createExternalFolder("externalLib"); + Util.compile( + new String[] { + "p/X.java", + "package p;\n" + + "public class X {\n" + + "}", + "p/Y.java", + "package p;\n" + + "public class Y extends X {\n" + + "}", + }, + new HashMap(), + getExternalFolderPath("externalLib")); + createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + IClassFile classFile = getClassFile("P", getExternalFolderPath("externalLib"), "p", "X.class"); + ITypeHierarchy hierarchy = classFile.getType().newTypeHierarchy(null); + assertHierarchyEquals( + "Focus: X [in X.class [in p [in "+ getExternalPath() + "externalLib]]]\n" + + "Super types:\n" + + "Sub types:\n" + + " Y [in Y.class [in p [in "+ getExternalPath() + "externalLib]]]\n", + hierarchy); + } finally { + deleteProject("P"); + deleteExternalFolder("externalLib"); + } +} +/* * Ensures that a call to IJavaProject.findType("java.lang.Object") doesn't cause the hierarchy * computation to throw a StackOverFlow * (regression test for https://bugs.eclipse.org/bugs/show_bug.cgi?id=209222) Index: src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java,v retrieving revision 1.50 diff -u -r1.50 AttachSourceTests.java --- src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java 30 Nov 2007 11:48:27 -0000 1.50 +++ src/org/eclipse/jdt/core/tests/model/AttachSourceTests.java 26 Feb 2008 09:55:06 -0000 @@ -10,11 +10,14 @@ *******************************************************************************/ package org.eclipse.jdt.core.tests.model; +import java.io.File; import java.io.IOException; import junit.framework.Test; import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IncrementalProjectBuilder; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; @@ -52,6 +55,9 @@ public AttachSourceTests(String name) { super(name); } +protected String getExternalFolder() { + return getExternalFolderPath("externalFolder"); +} public ASTNode runConversion(IClassFile classFile, boolean resolveBindings) { ASTParser parser = ASTParser.newParser(AST_INTERNAL_JLS2); parser.setSource(classFile); @@ -74,6 +80,19 @@ this.pkgFragmentRoot = this.currentProject.getPackageFragmentRoot(this.getFile("/AttachSourceTests/attach.jar")); setUpGenericJar(); setUpInnerClassesJar(); + setupExternalLibrary(); +} +private void setupExternalLibrary() throws IOException { + String externalFolder = getExternalFolder(); + String[] pathsAndContents = + new String[] { + "p/X.java", + "package p;\n" + + "public class X {\n" + + "}" + }; + org.eclipse.jdt.core.tests.util.Util.createClassFolder(pathsAndContents, externalFolder + "lib", "1.4"); + org.eclipse.jdt.core.tests.util.Util.createSourceDir(pathsAndContents, externalFolder + "src"); } private void setUpGenericJar() throws IOException, CoreException { String[] pathAndContents = new String[] { @@ -161,6 +180,7 @@ * Reset the jar placeholder and delete project. */ public void tearDownSuite() throws Exception { + org.eclipse.jdt.core.tests.util.Util.flushDirectoryContent(new File(getExternalFolder())); deleteProject(this.currentProject); super.tearDownSuite(); } @@ -323,6 +343,70 @@ assertTrue("Source attachment root path should be null", null ==this.pkgFragmentRoot.getSourceAttachmentRootPath()); } /* + * Ensures that one can attach an external source folder to a library folder. + */ +public void testExternalFolder1() throws CoreException { + try { + IProject p = createProject("P1"); + IFolder lib = p.getFolder("lib"); + lib.createLink(new Path(getExternalFolder() + "lib"), IResource.NONE, null); + IJavaProject javaProject = createJavaProject("P2", new String[0], new String[] {"/P1/lib"}, ""); + IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(lib); + attachSource(root, getExternalFolder() + "src", ""); + IType type = root.getPackageFragment("p").getClassFile("X.class").getType(); + assertSourceEquals( + "Unexpected source", + "public class X {\n" + + "}", + type.getSource()); + } finally { + deleteProject("P1"); + deleteProject("P2"); + } +} +/* + * Ensures that one can attach a source folder to an external library folder. + */ +public void testExternalFolder2() throws CoreException { + try { + IProject p = createProject("P1"); + IFolder src = p.getFolder("src"); + src.createLink(new Path(getExternalFolder() + "src"), IResource.NONE, null); + String externalLib = getExternalFolder() + "lib"; + IJavaProject javaProject = createJavaProject("P2", new String[0], new String[] {externalLib}, ""); + IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(externalLib); + attachSource(root, "/P1/src", ""); + IType type = root.getPackageFragment("p").getClassFile("X.class").getType(); + assertSourceEquals( + "Unexpected source", + "public class X {\n" + + "}", + type.getSource()); + } finally { + deleteProject("P1"); + deleteProject("P2"); + } +} +/* + * Ensures that one can attach an external source folder to an external library folder. + */ +public void testExternalFolder3() throws CoreException { + try { + String externalLib = getExternalFolder() + "lib"; + IJavaProject javaProject = createJavaProject("P", new String[0], new String[] {externalLib}, ""); + IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(externalLib); + attachSource(root, getExternalFolder() + "src", ""); + IType type = root.getPackageFragment("p").getClassFile("X.class").getType(); + assertSourceEquals( + "Unexpected source", + "public class X {\n" + + "}", + type.getSource()); + } finally { + deleteProject("P"); + } +} +/* * Ensures that the source of a generic method can be retrieved. */ public void testGeneric1() throws JavaModelException { Index: src/org/eclipse/jdt/core/tests/model/ClasspathTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClasspathTests.java,v retrieving revision 1.168 diff -u -r1.168 ClasspathTests.java --- src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 29 Jan 2008 18:02:17 -0000 1.168 +++ src/org/eclipse/jdt/core/tests/model/ClasspathTests.java 26 Feb 2008 09:55:07 -0000 @@ -142,11 +142,6 @@ file.setLastModified(System.currentTimeMillis() + 2000); return file; } -protected File createFolder(File parent, String name) { - File file = new File(parent, name); - file.mkdirs(); - return file; -} protected int numberOfCycleMarkers(IJavaProject javaProject) throws CoreException { IMarker[] markers = javaProject.getProject().findMarkers(IJavaModelMarker.BUILDPATH_PROBLEM_MARKER, false, IResource.DEPTH_ZERO); int result = 0; @@ -161,6 +156,103 @@ } /* + * Ensures that adding a library entry for an existing external library folder doesn't generate a marker + */ +public void testAddExternalLibFolder1() throws CoreException { + try { + IJavaProject p = createJavaProject("P"); + createExternalFolder("externalLib"); + setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path(getExternalFolderPath("externalLib")), null, null)}); + assertMarkers("Unexpected markers", "", p); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that creating a project with a library entry for an existing external library folder doesn't generate a marker + */ +public void testAddExternalLibFolder2() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + assertMarkers("Unexpected markers", "", p); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that adding a library entry for a non-existing external library folder generates a marker + */ +public void testAddExternalLibFolder3() throws CoreException { + try { + waitForAutoBuild(); + IJavaProject p = createJavaProject("P"); + IPath path = new Path(getExternalFolderPath("externalLib")); + setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(path, null, null)}); + assertMarkers( + "Unexpected markers", + "Project \'P\' is missing required library: \'"+ getExternalPath() + "externalLib\'", + p); + } finally { + deleteProject("P"); + } +} + +/* + * Ensures that creating a project with a library entry for a non-existing external library folder generates a marker + */ +public void testAddExternalLibFolder4() throws CoreException { + try { + waitForAutoBuild(); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + assertMarkers( + "Unexpected markers", + "Project \'P\' is missing required library: \'"+ getExternalPath() + "externalLib\'", + p); + } finally { + deleteProject("P"); + } +} + +/* + * Ensures that creating an external library folder referenced by a library entry and refreshing removes the marker + */ +public void testAddExternalLibFolder5() throws CoreException { + try { + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); + createExternalFolder("externalLib"); + refresh(p); + assertMarkers("Unexpected markers", "", p); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that creating an external library folder referenced by a library entry and refreshing after a restart + * removes the marker + */ +public void testAddExternalLibFolder6() throws CoreException { + try { + simulateExitRestart(); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); + createExternalFolder("externalLib"); + refresh(p); + assertMarkers("Unexpected markers", "", p); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* * Ensures that adding a project to a container triggers a classpath delta * (regression test for 154071 No notification of change if a project is added or removed from a container) */ @@ -2528,18 +2620,19 @@ } } /* - * Ensures that an external class folder cannot be put on the classpath. + * Ensures that an attempting to put a non-existing external class folder on the classpath + * creates the correct marker. */ public void testInvalidExternalClassFolder() throws CoreException { try { - String externalPath = getExternalPath(); + String externalPath = getExternalPath() + "nonExisting"; // remove trailing slash if (Path.fromOSString(externalPath).segmentCount() > 0) externalPath = externalPath.substring(0, externalPath.length()-1); IJavaProject proj = createJavaProject("P", new String[] {}, new String[] {externalPath}, "bin"); assertMarkers( "Unexpected markers", - "Required library cannot denote external folder: \'" + externalPath + "\' for project 'P'", + "Project \'P\' is missing required library: \'" + externalPath + "\'", proj); } finally { deleteProject("P"); @@ -3842,6 +3935,81 @@ } /* + * Ensures that removing a library entry for an existing external library folder doesn't generate a marker + */ +public void testRemoveExternalLibFolder1() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); + setClasspath(p, new IClasspathEntry[] {}); + assertMarkers("Unexpected markers", "", p); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that removing a library entry for a non-existing external library folder removes the marker + */ +public void testRemoveExternalLibFolder2() throws CoreException { + try { + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); + setClasspath(p, new IClasspathEntry[] {}); + assertMarkers( + "Unexpected markers", + "", + p); + } finally { + deleteProject("P"); + } +} + +/* + * Ensures that removing an external library folder referenced by a library entry creates a marker + */ +public void testRemoveExternalLibFolder3() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); + deleteExternalFolder("externalLib"); + refresh(p); + assertMarkers( + "Unexpected markers", + "Project \'P\' is missing required library: \'"+ getExternalPath() + "externalLib\'", + p); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that removing an external library folder referenced by a library entry and refreshing after a restart + * creates a marker + */ +public void testRemoveExternalLibFolder4() throws CoreException { + try { + simulateExitRestart(); + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); + deleteExternalFolder("externalLib"); + refresh(p); + assertMarkers( + "Unexpected markers", + "Project \'P\' is missing required library: \'"+ getExternalPath() + "externalLib\'", + p); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* * Ensures that renaming a .jar file and updating the classpath in a PRE_BUILD event doesn't leave markers * (regression test for bug 177922 FlexibleProjectContainer refresh logic sporadically leaves project with "missing library" error on rename/delete) */ Index: src/org/eclipse/jdt/core/tests/model/OverflowingCacheTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/OverflowingCacheTests.java,v retrieving revision 1.13 diff -u -r1.13 OverflowingCacheTests.java --- src/org/eclipse/jdt/core/tests/model/OverflowingCacheTests.java 21 Sep 2007 13:16:32 -0000 1.13 +++ src/org/eclipse/jdt/core/tests/model/OverflowingCacheTests.java 26 Feb 2008 09:55:08 -0000 @@ -229,7 +229,7 @@ return null; } - public IResource getResource() { + public IResource resource(PackageFragmentRoot root) { return null; } Index: src/org/eclipse/jdt/core/tests/model/ModifyingResourceTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ModifyingResourceTests.java,v retrieving revision 1.47 diff -u -r1.47 ModifyingResourceTests.java --- src/org/eclipse/jdt/core/tests/model/ModifyingResourceTests.java 26 Mar 2007 11:35:31 -0000 1.47 +++ src/org/eclipse/jdt/core/tests/model/ModifyingResourceTests.java 26 Feb 2008 09:55:08 -0000 @@ -31,7 +31,8 @@ protected void assertElementDescendants(String message, String expected, IJavaElement element) throws CoreException { String actual = expandAll(element); if (!expected.equals(actual)){ - System.out.println(Util.displayString(actual, 4)); + System.out.print(displayString(actual, 3)); + System.out.println(","); } assertEquals( message, @@ -85,6 +86,14 @@ } } +protected boolean createExternalFolder(String relativePath) { + return new File(getExternalPath(), relativePath).mkdirs(); +} + +protected void createExternalFile(String relativePath, String contents) { + Util.writeToFile(contents, getExternalPath() + relativePath); +} + protected IFile createFile(String path, InputStream content) throws CoreException { IFile file = getFile(path); file.create(content, true, null); @@ -106,9 +115,17 @@ protected IFile createFile(String path, String content, String charsetName) throws CoreException, UnsupportedEncodingException { return createFile(path, content.getBytes(charsetName)); } +protected File createFolder(File parent, String name) { + File file = new File(parent, name); + file.mkdirs(); + return file; +} protected IFolder createFolder(String path) throws CoreException { return createFolder(new Path(path)); } +protected void deleteExternalFolder(String relativePath) { + deleteFile(new File(getExternalPath() + relativePath)); +} protected void deleteFile(String filePath) throws CoreException { deleteResource(this.getFile(filePath)); } Index: src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java,v retrieving revision 1.126 diff -u -r1.126 ReconcilerTests.java --- src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java 22 Feb 2008 09:46:44 -0000 1.126 +++ src/org/eclipse/jdt/core/tests/model/ReconcilerTests.java 26 Feb 2008 09:55:09 -0000 @@ -338,7 +338,7 @@ createJavaProject("P2", new String[] {}, new String[] {}, null, null, new String[] {"/P1"}, null, null, new boolean[] {true}, "", null, null, null, "1.4"); - createJavaProject("P3", new String[] {"src"}, new String[] {"JCL_LIB"}, null, null, new String[] {"/P2"}, null, new String[][] {new String[] {"**/X"}}, false/*don't combine access restrictions*/, new boolean[] {true}, "bin", null, null, null, "1.4"); + createJavaProject("P3", new String[] {"src"}, new String[] {"JCL_LIB"}, null, null, new String[] {"/P2"}, null, new String[][] {new String[] {"**/X"}}, false/*don't combine access restrictions*/, new boolean[] {true}, "bin", null, null, null, "1.4", false/*don't import*/); setUpWorkingCopy("/P3/src/Y.java", "public class Y extends p.X {}"); assertProblems( "Unexpected problems", @@ -361,7 +361,7 @@ createJavaProject("P2", new String[] {}, new String[] {}, null, null, new String[] {"/P1"}, null, null, new boolean[] {true}, "", null, null, null, "1.4"); - createJavaProject("P3", new String[] {"src"}, new String[] {"JCL_LIB"}, null, null, new String[] {"/P2"}, null, new String[][] {new String[] {"**/X"}}, true/*combine access restrictions*/, new boolean[] {true}, "bin", null, null, null, "1.4"); + createJavaProject("P3", new String[] {"src"}, new String[] {"JCL_LIB"}, null, null, new String[] {"/P2"}, null, new String[][] {new String[] {"**/X"}}, true/*combine access restrictions*/, new boolean[] {true}, "bin", null, null, null, "1.4", false/*don't import*/); setUpWorkingCopy("/P3/src/Y.java", "public class Y extends p.X {}"); assertProblems( "Unexpected problems", Index: src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java,v retrieving revision 1.80 diff -u -r1.80 JavaElementDeltaTests.java --- src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java 29 Nov 2007 14:10:10 -0000 1.80 +++ src/org/eclipse/jdt/core/tests/model/JavaElementDeltaTests.java 26 Feb 2008 09:55:07 -0000 @@ -13,26 +13,12 @@ import java.util.ArrayList; import org.eclipse.core.resources.*; -import org.eclipse.core.resources.IFile; -import org.eclipse.core.resources.IProject; -import org.eclipse.core.resources.IWorkspaceRunnable; -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.Path; import org.eclipse.jdt.core.*; -import org.eclipse.jdt.core.ElementChangedEvent; -import org.eclipse.jdt.core.IClasspathEntry; -import org.eclipse.jdt.core.ICompilationUnit; -import org.eclipse.jdt.core.IElementChangedListener; -import org.eclipse.jdt.core.IJavaElementDelta; -import org.eclipse.jdt.core.IJavaProject; -import org.eclipse.jdt.core.IPackageFragment; -import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.internal.core.*; -import org.eclipse.jdt.internal.core.JavaModelManager; -import org.eclipse.jdt.internal.core.JavaProject; import junit.framework.Test; @@ -275,6 +261,100 @@ deleteProject("P"); } } + +/* + * Ensures that adding a library entry for an existing external library folder triggers the correct delta + */ +public void testAddExternalLibFolder1() throws CoreException { + try { + IJavaProject p = createJavaProject("P"); + createExternalFolder("externalLib"); + refresh(p); + startDeltas(); + setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(new Path(getExternalFolderPath("externalLib")), null, null)}); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN | CONTENT | RAW CLASSPATH CHANGED | RESOLVED CLASSPATH CHANGED}\n" + + " [*]: {REMOVED FROM CLASSPATH}\n" + + " "+ getExternalPath() + "externalLib[*]: {ADDED TO CLASSPATH}\n" + + " "+ getExternalJCLPathString() + "[*]: {REMOVED FROM CLASSPATH}\n" + + " ResourceDelta(/P/.classpath)[*]" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that adding a library entry for a non-existing external library folder triggers the correct delta + */ +public void testAddExternalLibFolder2() throws CoreException { + try { + IJavaProject p = createJavaProject("P"); + refresh(p); + IPath path = new Path(getExternalFolderPath("externalLib")); + startDeltas(); + setClasspath(p, new IClasspathEntry[] {JavaCore.newLibraryEntry(path, null, null)}); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN | CONTENT | RAW CLASSPATH CHANGED | RESOLVED CLASSPATH CHANGED}\n" + + " [*]: {REMOVED FROM CLASSPATH}\n" + + " "+ getExternalJCLPathString() + "[*]: {REMOVED FROM CLASSPATH}\n" + + " ResourceDelta(/P/.classpath)[*]" + ); + } finally { + stopDeltas(); + deleteProject("P"); + } +} + +/* + * Ensures that creating an external library folder referenced by a library entry and refreshing triggers the correct delta + */ +public void testAddExternalLibFolder3() throws CoreException { + try { + IJavaProject p =createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); // wait for the creation of the linked folder + startDeltas(); + createExternalFolder("externalLib"); + refresh(p); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[+]: {}" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that creating an external library folder referenced by a library entry and refreshing after a restart triggers the correct delta + */ +public void testAddExternalLibFolder4() throws CoreException { + try { + simulateExitRestart(); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); // wait for the creation of the linked folder + startDeltas(); + createExternalFolder("externalLib"); + refresh(p); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[+]: {}" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + /* * Ensure that a resource delta is fired when a file is added to a non-java project. * (regression test for bug 18698 Seeing non-java projects in package view) @@ -698,6 +778,124 @@ } } +/* + * Ensures that changing an external library folder referenced by a library entry and refreshing triggers the correct delta + */ +public void testChangeExternalLibFolder1() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + startDeltas(); + createExternalFolder("externalLib/p"); + refresh(p); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[*]: {CHILDREN}\n" + + " p[+]: {}" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that changing an external library folder referenced by a library entry and refreshing triggers the correct delta + */ +public void testChangeExternalLibFolder2() throws CoreException { + try { + createExternalFolder("externalLib/p"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + startDeltas(); + createExternalFile("externalLib/p/X.class", ""); + refresh(p); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[*]: {CHILDREN}\n" + + " p[*]: {CHILDREN}\n" + + " X.class[+]: {}" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that changing an external library folder referenced by a library entry and refreshing triggers the correct delta + */ +public void testChangeExternalLibFolder3() throws CoreException { + try { + createExternalFolder("externalLib/p"); + createExternalFile("externalLib/p/X.class", ""); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + startDeltas(); + touch(getExternalFile("externalLib/p/X.class")); + refresh(p); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[*]: {CHILDREN}\n" + + " p[*]: {CHILDREN}\n" + + " X.class[*]: {CONTENT}" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that changing an external library folder referenced by a library entry and refreshing triggers the correct delta + */ +public void testChangeExternalLibFolder4() throws CoreException { + try { + createExternalFolder("externalLib/p"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + startDeltas(); + createExternalFile("externalLib/p/test.txt", "test"); + refresh(p); + assertDeltas( + "Unexpected delta", + "" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that changing an external source folder referenced by a library entry as source attachment and refreshing triggers the correct delta + */ +public void testChangeExternalSourceAttachment() throws CoreException { + try { + createExternalFolder("externalLib"); + createExternalFolder("externalSrc"); + IJavaProject project = createJavaProject("P"); + addLibraryEntry(project, getExternalFolderPath("externalLib"), getExternalFolderPath("externalSrc")); + startDeltas(); + createExternalFile("externalSrc/X.java", "public class X {}"); + refresh(project); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[*]: {SOURCE ATTACHED | SOURCE DETACHED}" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteExternalFolder("externalSrc"); + deleteProject("P"); + } +} + /** * Ensures that the setting the classpath with a library entry * triggers a F_REMOVED_FROM_CLASSPATH and F_ADDED_TO_CLASSPATH delta. @@ -2053,9 +2251,98 @@ " src[*]: {REMOVED FROM CLASSPATH}\n" + " ResourceDelta(/P/.classpath)[-]\n" + " ResourceDelta(/P/.classpath2)[+]" - ); + ); + } finally { + stopDeltas(); + deleteProject("P"); + } +} + +/* + * Ensures that removing a library entry for an existing external library folder triggers the correct delta + */ +public void testRemoveExternalLibFolder1() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + startDeltas(); + setClasspath(p, new IClasspathEntry[] {}); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN | CONTENT | RAW CLASSPATH CHANGED | RESOLVED CLASSPATH CHANGED}\n" + + " "+ getExternalPath() + "externalLib[*]: {REMOVED FROM CLASSPATH}\n" + + " ResourceDelta(/P/.classpath)[*]" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that removing a library entry for a non-existing external library folder triggers the correct delta + */ +public void testRemoveExternalLibFolder2() throws CoreException { + try { + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + startDeltas(); + setClasspath(p, new IClasspathEntry[] {}); + assertDeltas( + "Unexpected delta", + "P[*]: {CONTENT | RAW CLASSPATH CHANGED | RESOLVED CLASSPATH CHANGED}\n" + + " ResourceDelta(/P/.classpath)[*]" + ); + } finally { + stopDeltas(); + deleteProject("P"); + } +} + +/* + * Ensures that removing an external library folder referenced by a library entry triggers the correct delta + */ +public void testRemoveExternalLibFolder3() throws CoreException { + try { + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); // wait for the creation of the linked folder + startDeltas(); + deleteExternalFolder("externalLib"); + refresh(p); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[-]: {}" + ); + } finally { + stopDeltas(); + deleteExternalFolder("externalLib"); + deleteProject("P"); + } +} + +/* + * Ensures that removing an external library folder referenced by a library entry after a restart + * triggers the correct delta + */ +public void testRemoveExternalLibFolder4() throws CoreException { + try { + simulateExitRestart(); + createExternalFolder("externalLib"); + IJavaProject p = createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + waitForAutoBuild(); // wait for the creation of the linked folder + startDeltas(); + deleteExternalFolder("externalLib"); + refresh(p); + assertDeltas( + "Unexpected delta", + "P[*]: {CHILDREN}\n" + + " "+ getExternalPath() + "externalLib[-]: {}" + ); } finally { stopDeltas(); + deleteExternalFolder("externalLib"); deleteProject("P"); } } Index: src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java,v retrieving revision 1.170 diff -u -r1.170 JavaSearchTests.java --- src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java 22 Feb 2008 09:46:44 -0000 1.170 +++ src/org/eclipse/jdt/core/tests/model/JavaSearchTests.java 26 Feb 2008 09:55:08 -0000 @@ -12,6 +12,7 @@ import java.io.File; import java.io.IOException; +import java.util.HashMap; import java.util.Hashtable; import junit.framework.Test; @@ -527,6 +528,76 @@ "", this.resultCollector); } +/* + * Ensures that a method declaration in an external library folder can be found + */ +public void testExternalFolder1() throws CoreException { + try { + createExternalFolder("externalLib"); + Util.compile( + new String[] { + "p/X.java", + "package p;\n" + + "public class X {\n" + + " public void foo() {\n" + + " }\n" + + "}" + }, + new HashMap(), + getExternalFolderPath("externalLib") + ); + createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + IJavaSearchScope scope = SearchEngine.createJavaSearchScope(new IJavaProject[] {getJavaProject("P")}); + search("foo", METHOD, DECLARATIONS, scope); + assertSearchResults( + getExternalPath() + "externalLib void p.X.foo()", + this.resultCollector); + } finally { + deleteProject("P"); + deleteExternalFolder("externalLib"); + } +} + +/* + * Ensures that search all type names returns the types in an external library folder + */ +public void testExternalFolder2() throws CoreException { + try { + createExternalFolder("externalLib"); + Util.compile( + new String[] { + "p/ExternalType.java", + "package p;\n" + + "public class ExternalType {\n" + + "}" + }, + new HashMap(), + getExternalFolderPath("externalLib") + ); + createJavaProject("P", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + + TypeNameMatchCollector collector = new TypeNameMatchCollector(); + new SearchEngine(this.workingCopies).searchAllTypeNames( + null, + SearchPattern.R_EXACT_MATCH, + "ExternalType".toCharArray(), + SearchPattern.R_EXACT_MATCH, + TYPE, + SearchEngine.createJavaSearchScope(new IJavaProject[] {getJavaProject("P")}), + collector, + IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, + null + ); + assertSearchResults( + "ExternalType (not open) [in ExternalType.class [in p [in "+ getExternalPath() + "externalLib]]]", + collector + ); + } finally { + deleteProject("P"); + deleteExternalFolder("externalLib"); + } + +} /** * Simple field declaration test. */ Index: src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java,v retrieving revision 1.199 diff -u -r1.199 AbstractJavaModelTests.java --- src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java 11 Jan 2008 12:42:49 -0000 1.199 +++ src/org/eclipse/jdt/core/tests/model/AbstractJavaModelTests.java 26 Feb 2008 09:55:06 -0000 @@ -32,6 +32,7 @@ import org.eclipse.jdt.internal.core.JavaCorePreferenceInitializer; import org.eclipse.jdt.internal.core.JavaElement; import org.eclipse.jdt.internal.core.JavaModelManager; +import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.NameLookup; import org.eclipse.jdt.internal.core.ResolvedSourceMethod; import org.eclipse.jdt.internal.core.ResolvedSourceType; @@ -323,16 +324,16 @@ protected void addLibraryEntry(IJavaProject project, IPath path, boolean exported) throws JavaModelException { addLibraryEntry(project, path, null, null, null, null, exported); } - protected void addLibraryEntry(IJavaProject project, String path, String srcAttachmentPath, String srcAttachmentPathRoot, boolean exported) throws JavaModelException{ + protected void addLibraryEntry(IJavaProject project, String path, String srcAttachmentPath) throws JavaModelException{ addLibraryEntry( project, new Path(path), srcAttachmentPath == null ? null : new Path(srcAttachmentPath), - srcAttachmentPathRoot == null ? null : new Path(srcAttachmentPathRoot), + null, null, null, new IClasspathAttribute[0], - exported + false ); } protected void addLibraryEntry(IJavaProject project, IPath path, IPath srcAttachmentPath, IPath srcAttachmentPathRoot, IPath[] accessibleFiles, IPath[] nonAccessibleFiles, boolean exported) throws JavaModelException{ @@ -543,7 +544,7 @@ } String actual = buffer.toString(); if (!expectedMarkers.equals(actual)) { - System.out.println(org.eclipse.jdt.core.tests.util.Util.displayString(actual, 2)); + System.out.println(displayString(actual, 2)); } assertEquals(message, expectedMarkers, actual); } @@ -1042,12 +1043,14 @@ null/*no project*/, null/*no inclusion pattern*/, null/*no exclusion pattern*/, + true/*combine access restrictions by default*/, null/*no exported project*/, output, null/*no source outputs*/, null/*no inclusion pattern*/, null/*no exclusion pattern*/, - "1.4" + "1.4", + false/*don't import*/ ); } protected IJavaProject createJavaProject(String projectName, String[] sourceFolders, String[] libraries, String output, String compliance) throws CoreException { @@ -1185,7 +1188,8 @@ sourceOutputs, inclusionPatterns, exclusionPatterns, - compliance); + compliance, + false/*don't import*/); } protected IJavaProject createJavaProject( final String projectName, @@ -1202,7 +1206,8 @@ final String[] sourceOutputs, final String[][] inclusionPatterns, final String[][] exclusionPatterns, - final String compliance) throws CoreException { + final String compliance, + final boolean simulateImport) throws CoreException { final IJavaProject[] result = new IJavaProject[1]; IWorkspaceRunnable create = new IWorkspaceRunnable() { public void run(IProgressMonitor monitor) throws CoreException { @@ -1390,13 +1395,16 @@ if (outputPath.segmentCount() > 0) { IFolder output = project.getFolder(outputPath); if (!output.exists()) { - output.create(true, true, null); + output.create(true, true, monitor); } } // set classpath and output location - IJavaProject javaProject = JavaCore.create(project); - javaProject.setRawClasspath(entries, projectPath.append(outputPath), null); + JavaProject javaProject = (JavaProject) JavaCore.create(project); + if (simulateImport) + javaProject.saveClasspath(entries, projectPath.append(outputPath)); + else + javaProject.setRawClasspath(entries, projectPath.append(outputPath), monitor); // set compliance level options if ("1.5".equals(compliance)) { @@ -1413,6 +1421,27 @@ getWorkspace().run(create, null); return result[0]; } + protected IJavaProject importJavaProject(String projectName, String[] sourceFolders, String[] libraries, String output) throws CoreException { + return + createJavaProject( + projectName, + sourceFolders, + libraries, + null/*no inclusion pattern*/, + null/*no exclusion pattern*/, + null/*no project*/, + null/*no inclusion pattern*/, + null/*no exclusion pattern*/, + true/*combine access restrictions by default*/, + null/*no exported project*/, + output, + null/*no source outputs*/, + null/*no inclusion pattern*/, + null/*no exclusion pattern*/, + "1.4", + true/*import*/ + ); + } /* * Create simple project. */ @@ -1604,6 +1633,14 @@ } return result; } + + protected File getExternalFile(String relativePath) { + return new File(getExternalPath(), relativePath); + } + + protected String getExternalFolderPath(String name) { + return getExternalPath() + name + File.separatorChar; + } /** * Returns the IPath to the external java class library (e.g. jclMin.jar) @@ -1886,6 +1923,12 @@ toDisplay = CharOperation.replace( toDisplay, + getExternalPath().toCharArray(), + "getExternalPath()".toCharArray()); + + toDisplay = + CharOperation.replace( + toDisplay, org.eclipse.jdt.core.tests.util.Util.displayString(getExternalJCLSourcePathString(), 0).toCharArray(), "getExternalJCLSourcePathString()".toCharArray()); toDisplay = @@ -1893,7 +1936,9 @@ toDisplay, org.eclipse.jdt.core.tests.util.Util.displayString(getExternalJCLSourcePathString("1.5"), 0).toCharArray(), "getExternalJCLSourcePathString(\"1.5\")".toCharArray()); + toDisplay = org.eclipse.jdt.core.tests.util.Util.displayString(new String(toDisplay), indent).toCharArray(); + toDisplay = CharOperation.replace( toDisplay, @@ -1914,6 +1959,11 @@ toDisplay, "getExternalJCLSourcePathString(\\\"1.5\\\")".toCharArray(), ("\"+ getExternalJCLSourcePathString(\"1.5\") + \"").toCharArray()); + toDisplay = + CharOperation.replace( + toDisplay, + "getExternalPath()".toCharArray(), + ("\"+ getExternalPath() + \"").toCharArray()); return new String(toDisplay); } @@ -1962,6 +2012,19 @@ stream.close(); return fileBytes; } + + public void refresh(final IJavaProject javaProject) throws CoreException { + ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() { + public void run(IProgressMonitor pm) throws CoreException { + // work around for https://bugs.eclipse.org/bugs/show_bug.cgi?id=219566 + IProject externalFoldersProject = JavaModelManager.getExternalManager().getExternalFoldersProject(); + externalFoldersProject.refreshLocal(IResource.DEPTH_INFINITE, pm); + + javaProject.getProject().refreshLocal(IResource.DEPTH_INFINITE, pm); + } + }, null); + } + protected void removeJavaNature(String projectName) throws CoreException { IProject project = this.getProject(projectName); IProjectDescription description = project.getDescription(); @@ -2552,7 +2615,10 @@ } return result; } - protected String toString(String[] strings) { + protected void touch(File f) { + f.setLastModified(f.lastModified() + 10000); + } +protected String toString(String[] strings) { return toString(strings, false/*don't add extra new line*/); } protected String toString(String[] strings, boolean addExtraNewLine) { Index: src/org/eclipse/jdt/core/tests/model/ClassFileTests.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/ClassFileTests.java,v retrieving revision 1.32 diff -u -r1.32 ClassFileTests.java --- src/org/eclipse/jdt/core/tests/model/ClassFileTests.java 22 Nov 2007 11:51:55 -0000 1.32 +++ src/org/eclipse/jdt/core/tests/model/ClassFileTests.java 26 Feb 2008 09:55:06 -0000 @@ -720,6 +720,25 @@ } /* + * Ensures that the resource of a .class file in an external folder is null + */ +public void testGetResource() throws Exception { + try { + createExternalFolder("externalLib/p"); + createExternalFile("externalLib/p/X.class", ""); + createJavaProject("P1", new String[0], new String[] {getExternalFolderPath("externalLib")}, ""); + IClassFile classFile1 = getClassFile("P1", getExternalFolderPath("externalLib"), "p", "X.class"); + assertEquals( + "Unexpected resource", + null, + classFile1.getResource()); + } finally { + deleteExternalFolder("externalLib"); + deleteProject("P1"); + } +} + +/* * Ensures that IType#getSuperclassTypeSignature() is correct for a binary type. * (regression test for bug 78520 [model] IType#getSuperInterfaceTypeSignatures() doesn't include type arguments) */ @@ -761,7 +780,7 @@ // create an invalid package fragment root and an invalid package fragment IPackageFragment invalidPkg = p.getPackageFragmentRoot("/P1/classFolder.jar").getPackageFragment("p"); - // ensure that the class fille cannot be opened with a valid excepption + // ensure that the class file cannot be opened with a valid exception IClassFile openable = invalidPkg.getClassFile("X.class"); JavaModelException expected = null; try {