### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: model/org/eclipse/jdt/core/package.html =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/core/package.html,v retrieving revision 1.3 diff -u -r1.3 package.html --- model/org/eclipse/jdt/core/package.html 1 Jul 2002 11:20:31 -0000 1.3 +++ model/org/eclipse/jdt/core/package.html 26 Aug 2008 14:25:42 -0000 @@ -13,7 +13,15 @@ Package Specification


This package contains the Java model classes, which implement Java -specific behaviour for resources and further decompose java resources into +specific behaviour for resources and further decompose Java resources into model elements. +

+Note that a lot of Java model operations require a Java project's classpath resolution. +For example IJavaProject#getResolvedClasspath(boolean) or JavaCore#setClasspathContainer() +will require to resolve the classpath of one or more projects. Client should be aware that +this resolution may require to take project modification rule +(see IResourceRuleFactory#modifyRule(IResource)). +

+ 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.325 diff -u -r1.325 DeltaProcessor.java --- model/org/eclipse/jdt/internal/core/DeltaProcessor.java 27 Jun 2008 16:03:50 -0000 1.325 +++ model/org/eclipse/jdt/internal/core/DeltaProcessor.java 26 Aug 2008 14:25:42 -0000 @@ -1963,6 +1963,11 @@ return; case IResourceChangeEvent.PRE_BUILD : + // force initialization of roots before builders run to avoid deadlock in another thread + // (note this is no-op if already initialized) + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=241751 + this.state.initializeRoots(false/*not initiAfterLoad*/); + boolean isAffected = isAffectedBy(delta); boolean needCycleValidation = isAffected && validateClasspaths(delta); Index: model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java,v retrieving revision 1.7 diff -u -r1.7 ProjectReferenceChange.java --- model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java 27 Jun 2008 16:03:51 -0000 1.7 +++ model/org/eclipse/jdt/internal/core/ProjectReferenceChange.java 26 Aug 2008 14:25:42 -0000 @@ -41,69 +41,72 @@ * Update projects references so that the build order is consistent with the classpath */ public void updateProjectReferencesIfNecessary() throws JavaModelException { - - final String[] oldRequired = this.oldResolvedClasspath == null ? CharOperation.NO_STRINGS : this.project.projectPrerequisites(this.oldResolvedClasspath); + + String[] oldRequired = this.oldResolvedClasspath == null ? CharOperation.NO_STRINGS : this.project.projectPrerequisites(this.oldResolvedClasspath); IClasspathEntry[] newResolvedClasspath = this.project.getResolvedClasspath(); - final String[] newRequired = this.project.projectPrerequisites(newResolvedClasspath); + String[] newRequired = this.project.projectPrerequisites(newResolvedClasspath); final IProject projectResource = this.project.getProject(); - IWorkspaceRunnable runnable = new IWorkspaceRunnable() { - public void run(IProgressMonitor monitor) throws CoreException { - IProjectDescription description = projectResource.getDescription(); - - IProject[] projectReferences = description.getDynamicReferences(); - - HashSet oldReferences = new HashSet(projectReferences.length); - for (int i = 0; i < projectReferences.length; i++){ - String projectName = projectReferences[i].getName(); - oldReferences.add(projectName); - } - HashSet newReferences = (HashSet)oldReferences.clone(); - - for (int i = 0; i < oldRequired.length; i++){ - String projectName = oldRequired[i]; - newReferences.remove(projectName); - } - for (int i = 0; i < newRequired.length; i++){ - String projectName = newRequired[i]; - newReferences.add(projectName); - } - - Iterator iter; - int newSize = newReferences.size(); - - checkIdentity: { - if (oldReferences.size() == newSize){ - iter = newReferences.iterator(); - while (iter.hasNext()){ - if (!oldReferences.contains(iter.next())){ - break checkIdentity; - } + + try { + IProject[] projectReferences = projectResource.getDescription().getDynamicReferences(); + + HashSet oldReferences = new HashSet(projectReferences.length); + for (int i = 0; i < projectReferences.length; i++){ + String projectName = projectReferences[i].getName(); + oldReferences.add(projectName); + } + HashSet newReferences = (HashSet)oldReferences.clone(); + + for (int i = 0; i < oldRequired.length; i++){ + String projectName = oldRequired[i]; + newReferences.remove(projectName); + } + for (int i = 0; i < newRequired.length; i++){ + String projectName = newRequired[i]; + newReferences.add(projectName); + } + + Iterator iter; + int newSize = newReferences.size(); + + checkIdentity: { + if (oldReferences.size() == newSize){ + iter = newReferences.iterator(); + while (iter.hasNext()){ + if (!oldReferences.contains(iter.next())){ + break checkIdentity; } - return; } + return; } - String[] requiredProjectNames = new String[newSize]; - int index = 0; - iter = newReferences.iterator(); - while (iter.hasNext()){ - requiredProjectNames[index++] = (String)iter.next(); - } - Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent - - IProject[] requiredProjectArray = new IProject[newSize]; - IWorkspaceRoot wksRoot = projectResource.getWorkspace().getRoot(); - for (int i = 0; i < newSize; i++){ - requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]); - } - description.setDynamicReferences(requiredProjectArray); - projectResource.setDescription(description, IResource.AVOID_NATURE_CONFIG, null); } - }; - try { - // ensure that a sheduling rule is used so that the project description is not modified by another thread while we update it + String[] requiredProjectNames = new String[newSize]; + int index = 0; + iter = newReferences.iterator(); + while (iter.hasNext()){ + requiredProjectNames[index++] = (String)iter.next(); + } + Util.sort(requiredProjectNames); // ensure that if changed, the order is consistent + + final IProject[] requiredProjectArray = new IProject[newSize]; + IWorkspaceRoot wksRoot = projectResource.getWorkspace().getRoot(); + for (int i = 0; i < newSize; i++){ + requiredProjectArray[i] = wksRoot.getProject(requiredProjectNames[i]); + } + + // ensure that a scheduling rule is used so that the project description is not modified by another thread while we update it // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=214981 + // also ensure that if no change (checkIdentify block returned above) we don't reach here + // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=241751 IWorkspace workspace = projectResource.getWorkspace(); - ISchedulingRule rule = workspace.getRuleFactory().modifyRule(projectResource); // sheduling rule for modifying the project + ISchedulingRule rule = workspace.getRuleFactory().modifyRule(projectResource); // scheduling rule for modifying the project + IWorkspaceRunnable runnable = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + IProjectDescription description = projectResource.getDescription(); + description.setDynamicReferences(requiredProjectArray); + projectResource.setDescription(description, IResource.AVOID_NATURE_CONFIG, null); + } + }; workspace.run(runnable, rule, IWorkspace.AVOID_UPDATE, null); } catch(CoreException e){ if (!ExternalJavaProject.EXTERNAL_PROJECT_NAME.equals(this.project.getElementName()))