Parser detects wrong include files now
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / JavaModelManager.java
index 1838edf..01d7c40 100644 (file)
@@ -18,6 +18,7 @@ import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.text.NumberFormat;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -39,10 +40,11 @@ import net.sourceforge.phpdt.core.IPackageFragment;
 import net.sourceforge.phpdt.core.IPackageFragmentRoot;
 import net.sourceforge.phpdt.core.IWorkingCopy;
 import net.sourceforge.phpdt.core.JavaModelException;
+import net.sourceforge.phpdt.core.JavaCore;
 import net.sourceforge.phpdt.internal.ui.util.PHPFileUtil;
-import net.sourceforge.phpeclipse.PHPCore;
 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
 import net.sourceforge.phpdt.internal.core.builder.PHPBuilder;
+import net.sourceforge.phpdt.internal.core.util.Util;
 
 import org.eclipse.core.resources.IFile;
 import org.eclipse.core.resources.IFolder;
@@ -57,7 +59,6 @@ import org.eclipse.core.resources.IWorkspaceRoot;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IPluginDescriptor;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.ISafeRunnable;
 import org.eclipse.core.runtime.IStatus;
@@ -68,6 +69,23 @@ import org.eclipse.core.runtime.Plugin;
 import org.eclipse.core.runtime.Preferences;
 import org.eclipse.core.runtime.Status;
 
+import net.sourceforge.phpdt.internal.core.DefaultWorkingCopyOwner;
+
+import net.sourceforge.phpdt.internal.core.DeltaProcessingState;
+
+import net.sourceforge.phpdt.internal.core.DeltaProcessor;
+
+import net.sourceforge.phpdt.core.IParent;
+import net.sourceforge.phpdt.internal.core.JavaElementInfo;
+
+import net.sourceforge.phpdt.core.IProblemRequestor;
+import net.sourceforge.phpdt.core.WorkingCopyOwner;
+import net.sourceforge.phpdt.core.compiler.IProblem;
+import net.sourceforge.phpdt.internal.core.CompilationUnit;
+import net.sourceforge.phpdt.internal.core.JavaElement;
+import net.sourceforge.phpdt.internal.core.JavaElementDeltaBuilder;
+import net.sourceforge.phpdt.internal.core.JavaModelManager.PerWorkingCopyInfo;
+
 /**
  * The <code>JavaModelManager</code> manages instances of <code>IJavaModel</code>.
  * <code>IElementChangedListener</code>s register with the <code>JavaModelManager</code>,
@@ -143,6 +161,11 @@ public class JavaModelManager implements ISaveParticipant {
        public final static IWorkingCopy[] NoWorkingCopy = new IWorkingCopy[0];
        
        /**
+        * Table from WorkingCopyOwner to a table of ICompilationUnit (working copy handle) to PerWorkingCopyInfo.
+        * NOTE: this object itself is used as a lock to synchronize creation/removal of per working copy infos
+        */
+       protected Map perWorkingCopyInfos = new HashMap(5);
+       /**
         * Returns whether the given full path (for a package) conflicts with the output location
         * of the given project.
         */
@@ -248,13 +271,13 @@ public class JavaModelManager implements ISaveParticipant {
                int type = resource.getType();
                switch (type) {
                        case IResource.PROJECT :
-                               return PHPCore.create((IProject) resource);
+                               return JavaCore.create((IProject) resource);
                        case IResource.FILE :
                                return create((IFile) resource, project);
                        case IResource.FOLDER :
                                return create((IFolder) resource, project);
                        case IResource.ROOT :
-                               return PHPCore.create((IWorkspaceRoot) resource);
+                               return JavaCore.create((IWorkspaceRoot) resource);
                        default :
                                return null;
                }
@@ -280,17 +303,17 @@ public class JavaModelManager implements ISaveParticipant {
                        return null;
                }
                if (project == null) {
-                       project = PHPCore.create(file.getProject());
+                       project = JavaCore.create(file.getProject());
                }
        
                if (file.getFileExtension() != null) {
                        String name = file.getName();
-//                     if (Util.isValidCompilationUnitName(name))
-                       if (PHPFileUtil.isPHPFile(file))
+                       if (PHPFileUtil.isValidPHPUnitName(name))
+                       //if (PHPFileUtil.isPHPFile(file))
                                return createCompilationUnitFrom(file, project);
-//                     if (Util.isValidClassFileName(name))
+//                     if (ProjectPrefUtil.isValidClassFileName(name))
 //                             return createClassFileFrom(file, project);
-//                     if (Util.isArchiveFileName(name))
+//                     if (ProjectPrefUtil.isArchiveFileName(name))
 //                             return createJarPackageFragmentRootFrom(file, project);
                }
                return null;
@@ -311,7 +334,7 @@ public class JavaModelManager implements ISaveParticipant {
                        return null;
                }
                if (project == null) {
-                       project = PHPCore.create(folder.getProject());
+                       project = JavaCore.create(folder.getProject());
                }
                IJavaElement element = determineIfOnClasspath(folder, project);
                if (conflictsWithOutputLocation(folder.getFullPath(), (JavaProject)project)
@@ -355,7 +378,7 @@ public class JavaModelManager implements ISaveParticipant {
                if (file == null) return null;
 
                if (project == null) {
-                       project = PHPCore.create(file.getProject());
+                       project = JavaCore.create(file.getProject());
                }
                IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file, project);
                if (pkg == null) {
@@ -412,7 +435,7 @@ public class JavaModelManager implements ISaveParticipant {
                IPath resourcePath = resource.getFullPath();
                try {
                        IClasspathEntry[] entries = 
-                               Util.isJavaFileName(resourcePath.lastSegment())
+                               net.sourceforge.phpdt.internal.compiler.util.Util.isJavaFileName(resourcePath.lastSegment())
                                        ? project.getRawClasspath() // JAVA file can only live inside SRC folder (on the raw path)
                                        : ((JavaProject)project).getResolvedClasspath(true);
                                
@@ -433,7 +456,8 @@ public class JavaModelManager implements ISaveParticipant {
                                                pkgPath = pkgPath.removeLastSegments(1);
                                                
                                                // don't check validity of package name (see http://bugs.eclipse.org/bugs/show_bug.cgi?id=26706)
-                                               String pkgName = pkgPath.toString().replace('/', '.');
+//                                             String pkgName = pkgPath.toString().replace('/', '.');
+                                               String pkgName = pkgPath.toString();
                                                return root.getPackageFragment(pkgName);
                                        } else {
                                                String pkgName = Util.packageName(pkgPath);
@@ -460,11 +484,18 @@ public class JavaModelManager implements ISaveParticipant {
         */
        protected JavaModelCache cache = new JavaModelCache();
 
+       /*
+        * Temporary cache of newly opened elements
+        */
+       private ThreadLocal temporaryCache = new ThreadLocal();
        /**
         * Set of elements which are out of sync with their buffers.
         */
        protected Map elementsOutOfSynchWithBuffers = new HashMap(11);
-       
+       /**
+        * Holds the state used for delta processing.
+        */
+       public DeltaProcessingState deltaState = new DeltaProcessingState();
        /**
         * Turns delta firing on/off. By default it is on.
         */
@@ -496,7 +527,7 @@ public class JavaModelManager implements ISaveParticipant {
        /**
         * Used to convert <code>IResourceDelta</code>s into <code>IJavaElementDelta</code>s.
         */
-       public final DeltaProcessor deltaProcessor = new DeltaProcessor(this);
+//     public final DeltaProcessor deltaProcessor = new DeltaProcessor(this);
        /**
         * Used to update the JavaModel for <code>IJavaElementDelta</code>s.
         */
@@ -540,7 +571,44 @@ public class JavaModelManager implements ISaveParticipant {
                        this.project = project;
                }
        }
-       public static boolean VERBOSE = true;
+       public static class PerWorkingCopyInfo implements IProblemRequestor {
+               int useCount = 0;
+               IProblemRequestor problemRequestor;
+               ICompilationUnit workingCopy;
+               public PerWorkingCopyInfo(ICompilationUnit workingCopy, IProblemRequestor problemRequestor) {
+                       this.workingCopy = workingCopy;
+                       this.problemRequestor = problemRequestor;
+               }
+               public void acceptProblem(IProblem problem) {
+                       if (this.problemRequestor == null) return;
+                       this.problemRequestor.acceptProblem(problem);
+               }
+               public void beginReporting() {
+                       if (this.problemRequestor == null) return;
+                       this.problemRequestor.beginReporting();
+               }
+               public void endReporting() {
+                       if (this.problemRequestor == null) return;
+                       this.problemRequestor.endReporting();
+               }
+               public ICompilationUnit getWorkingCopy() {
+                       return this.workingCopy;
+               }
+               public boolean isActive() {
+                       return this.problemRequestor != null && this.problemRequestor.isActive();
+               }
+               public String toString() {
+                       StringBuffer buffer = new StringBuffer();
+                       buffer.append("Info for "); //$NON-NLS-1$
+                       buffer.append(((JavaElement)workingCopy).toStringWithAncestors());
+                       buffer.append("\nUse count = "); //$NON-NLS-1$
+                       buffer.append(this.useCount);
+                       buffer.append("\nProblem requestor:\n  "); //$NON-NLS-1$
+                       buffer.append(this.problemRequestor);
+                       return buffer.toString();
+               }
+       }
+       public static boolean VERBOSE = false;
        public static boolean CP_RESOLVE_VERBOSE = false;
        public static boolean ZIP_ACCESS_VERBOSE = false;
        
@@ -560,18 +628,17 @@ public class JavaModelManager implements ISaveParticipant {
                 * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(PropertyChangeEvent)
                 */
                public void propertyChange(Preferences.PropertyChangeEvent event) {
-
-                       String propertyName = event.getProperty();
-                       if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
-                               String varName = propertyName.substring(CP_VARIABLE_PREFERENCES_PREFIX.length());
-                               String newValue = (String)event.getNewValue();
-                               if (newValue != null && !(newValue = newValue.trim()).equals(CP_ENTRY_IGNORE)) {
-                                       Variables.put(varName, new Path(newValue));
-                               } else {
-                                       Variables.remove(varName);
-                               }
-                       }
-//             TODO khartlage temp-del
+//                     TODO : jsurfer temp-del
+//                     String propertyName = event.getProperty();
+//                     if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)) {
+//                             String varName = propertyName.substring(CP_VARIABLE_PREFERENCES_PREFIX.length());
+//                             String newValue = (String)event.getNewValue();
+//                             if (newValue != null && !(newValue = newValue.trim()).equals(CP_ENTRY_IGNORE)) {
+//                                     Variables.put(varName, new Path(newValue));
+//                             } else {
+//                                     Variables.remove(varName);
+//                             }
+//                     }
 //                     if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)) {
 //                             recreatePersistedContainer(propertyName, (String)event.getNewValue(), false);
 //                     }
@@ -655,8 +722,9 @@ public class JavaModelManager implements ISaveParticipant {
         * Configure the plugin with respect to option settings defined in ".options" file
         */
        public void configurePluginDebugOptions(){
-               if(PHPCore.getPlugin().isDebugging()){
-//             TODO khartlage temp-del
+               if(JavaCore.getPlugin().isDebugging()){
+//             TODO jsurfer temp-del
+                       
                        String option = Platform.getDebugOption(BUILDER_DEBUG);
 //                     if(option != null) JavaBuilder.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
 //                     
@@ -690,15 +758,60 @@ public class JavaModelManager implements ISaveParticipant {
 //                     option = Platform.getDebugOption(SELECTION_DEBUG);
 //                     if(option != null) SelectionEngine.DEBUG = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
 
-                       option = Platform.getDebugOption(SHARED_WC_DEBUG);
-                       if(option != null) CompilationUnit.SHARED_WC_VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
-
                        option = Platform.getDebugOption(ZIP_ACCESS_DEBUG);
                        if(option != null) JavaModelManager.ZIP_ACCESS_VERBOSE = option.equalsIgnoreCase("true") ; //$NON-NLS-1$
                }
        }
        
 
+       /*
+        * Discards the per working copy info for the given working copy (making it a compilation unit)
+        * if its use count was 1. Otherwise, just decrement the use count.
+        * If the working copy is primary, computes the delta between its state and the original compilation unit
+        * and register it.
+        * Close the working copy, its buffer and remove it from the shared working copy table.
+        * Ignore if no per-working copy info existed.
+        * NOTE: it must be synchronized as it may interact with the element info cache (if useCount is decremented to 0), see bug 50667.
+        * Returns the new use count (or -1 if it didn't exist).
+        */
+       public synchronized int discardPerWorkingCopyInfo(CompilationUnit workingCopy) throws JavaModelException {
+               synchronized(perWorkingCopyInfos) {
+                       WorkingCopyOwner owner = workingCopy.owner;
+                       Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
+                       if (workingCopyToInfos == null) return -1;
+                       
+                       PerWorkingCopyInfo info = (PerWorkingCopyInfo)workingCopyToInfos.get(workingCopy);
+                       if (info == null) return -1;
+                       
+                       if (--info.useCount == 0) {
+                               // create the delta builder (this remembers the current content of the working copy)
+                               JavaElementDeltaBuilder deltaBuilder = null;
+                               if (workingCopy.isPrimary()) {
+                                       deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
+                               }
+
+                               // remove per working copy info
+                               workingCopyToInfos.remove(workingCopy);
+                               if (workingCopyToInfos.isEmpty()) {
+                                       this.perWorkingCopyInfos.remove(owner);
+                               }
+
+                               // remove infos + close buffer (since no longer working copy)
+                               removeInfoAndChildren(workingCopy);
+                               workingCopy.closeBuffer();
+
+                               // compute the delta if needed and register it if there are changes
+                               if (deltaBuilder != null) {
+                                       deltaBuilder.buildDeltas();
+                                       if ((deltaBuilder.delta != null) && (deltaBuilder.delta.getAffectedChildren().length > 0)) {
+                                               getDeltaProcessor().registerJavaModelDelta(deltaBuilder.delta);
+                                       }
+                               }
+                               
+                       }
+                       return info.useCount;
+               }
+       }
        
        /**
         * @see ISaveParticipant
@@ -727,7 +840,7 @@ public class JavaModelManager implements ISaveParticipant {
                        
                // Refresh internal scopes
                if (deltaToNotify != null) {
-//             TODO khartlage temp-del
+//             TODO  temp-del
 //                     Iterator scopes = this.scopes.keySet().iterator();
 //                     while (scopes.hasNext()) {
 //                             AbstractSearchScope scope = (AbstractSearchScope)scopes.next();
@@ -868,7 +981,9 @@ public class JavaModelManager implements ISaveParticipant {
        }
        
 
-       
+       public DeltaProcessor getDeltaProcessor() {
+               return this.deltaState.getDeltaProcessor();
+       }
        /** 
         * Returns the set of elements which are out of synch with their buffers.
         */
@@ -904,7 +1019,7 @@ public class JavaModelManager implements ISaveParticipant {
                        return proj;
                }
                int rootEnd= memento.indexOf(JavaElement.JEM_PACKAGEFRAGMENT, projectEnd + 1);
-//     TODO khartlage temp-del
+//     TODO  temp-del
 //             if (rootEnd == -1) {
 //                     return model.getHandleFromMementoForRoot(memento, proj, projectEnd, memento.length());
 //             }
@@ -1000,19 +1115,42 @@ public class JavaModelManager implements ISaveParticipant {
                JavaModelManager.PerProjectInfo info = getPerProjectInfo(project, false /* don't create info */);
                if (info == null) {
                        if (!JavaProject.hasJavaNature(project)) {
-                               throw ((JavaProject)PHPCore.create(project)).newNotPresentException();
+                               throw ((JavaProject)JavaCore.create(project)).newNotPresentException();
                        }
                        info = getPerProjectInfo(project, true /* create info */);
                }
                return info;
        }
+       /*
+        * Returns the per-working copy info for the given working copy at the given path.
+        * If it doesn't exist and if create, add a new per-working copy info with the given problem requestor.
+        * If recordUsage, increment the per-working copy info's use count.
+        * Returns null if it doesn't exist and not create.
+        */
+       public PerWorkingCopyInfo getPerWorkingCopyInfo(CompilationUnit workingCopy,boolean create, boolean recordUsage, IProblemRequestor problemRequestor) {
+               synchronized(perWorkingCopyInfos) { // use the perWorkingCopyInfo collection as its own lock
+                       WorkingCopyOwner owner = workingCopy.owner;
+                       Map workingCopyToInfos = (Map)this.perWorkingCopyInfos.get(owner);
+                       if (workingCopyToInfos == null && create) {
+                               workingCopyToInfos = new HashMap();
+                               this.perWorkingCopyInfos.put(owner, workingCopyToInfos);
+                       }
 
+                       PerWorkingCopyInfo info = workingCopyToInfos == null ? null : (PerWorkingCopyInfo) workingCopyToInfos.get(workingCopy);
+                       if (info == null && create) {
+                               info= new PerWorkingCopyInfo(workingCopy, problemRequestor);
+                               workingCopyToInfos.put(workingCopy, info);
+                       }
+                       if (info != null && recordUsage) info.useCount++;
+                       return info;
+               }
+       }       
        /**
         * Returns the name of the variables for which an CP variable initializer is registered through an extension point
         */
        public static String[] getRegisteredVariableNames(){
                
-               Plugin jdtCorePlugin = PHPCore.getPlugin();
+               Plugin jdtCorePlugin = JavaCore.getPlugin();
                if (jdtCorePlugin == null) return null;
 
                ArrayList variableList = new ArrayList(5);
@@ -1062,11 +1200,21 @@ public class JavaModelManager implements ISaveParticipant {
         */
        private File getSerializationFile(IProject project) {
                if (!project.exists()) return null;
-               IPluginDescriptor descr= PHPCore.getJavaCore().getDescriptor();
-               IPath workingLocation= project.getPluginWorkingLocation(descr);
+               IPath workingLocation = project.getWorkingLocation(JavaCore.PLUGIN_ID);
                return workingLocation.append("state.dat").toFile(); //$NON-NLS-1$
        }
-
+       /*
+        * Returns the temporary cache for newly opened elements for the current thread.
+        * Creates it if not already created.
+        */
+       public HashMap getTemporaryCache() {
+               HashMap result = (HashMap)this.temporaryCache.get();
+               if (result == null) {
+                       result = new HashMap();
+                       this.temporaryCache.set(result);
+               }
+               return result;
+       }
        /**
         * Returns the open ZipFile at the given location. If the ZipFile
         * does not yet exist, it is created, opened, and added to the cache
@@ -1094,18 +1242,18 @@ public class JavaModelManager implements ISaveParticipant {
                                } else { // internal resource (not an IFile or not existing)
                                        IPath location;
                                        if (file.getType() != IResource.FILE || (location = file.getLocation()) == null) {
-                                               throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
+                                               throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
                                        }
                                        fileSystemPath= location.toOSString();
                                }
                        } else if (!path.isAbsolute()) {
                                file= root.getFile(path);
                                if (file == null || file.getType() != IResource.FILE) {
-                                       throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
+                                       throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
                                }
                                IPath location = file.getLocation();
                                if (location == null) {
-                                       throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
+                                       throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("file.notFound", path.toString()), null)); //$NON-NLS-1$
                                }
                                fileSystemPath= location.toOSString();
                        } else {
@@ -1122,11 +1270,16 @@ public class JavaModelManager implements ISaveParticipant {
                                }
                                return zipFile;
                        } catch (IOException e) {
-                               throw new CoreException(new Status(Status.ERROR, PHPCore.PLUGIN_ID, -1, Util.bind("status.IOException"), e)); //$NON-NLS-1$
+                               throw new CoreException(new Status(Status.ERROR, JavaCore.PLUGIN_ID, -1, Util.bind("status.IOException"), e)); //$NON-NLS-1$
                        }
                }
        }
-
+       /*
+        * Returns whether there is a temporary cache for the current thread.
+        */
+       public boolean hasTemporaryCache() {
+               return this.temporaryCache.get() != null;
+       }
 //     public void loadVariablesAndContainers() throws CoreException {
 //
 //             // backward compatibility, consider persistent property 
@@ -1286,7 +1439,35 @@ public class JavaModelManager implements ISaveParticipant {
        protected void putInfo(IJavaElement element, Object info) {
                this.cache.putInfo(element, info);
        }
-
+       /*
+        * Puts the infos in the given map (keys are IJavaElements and values are JavaElementInfos)
+        * in the Java model cache in an atomic way.
+        * First checks that the info for the opened element (or one of its ancestors) has not been 
+        * added to the cache. If it is the case, another thread has opened the element (or one of
+        * its ancestors). So returns without updating the cache.
+        */
+       protected synchronized void putInfos(IJavaElement openedElement, Map newElements) {
+               // remove children
+               Object existingInfo = this.cache.peekAtInfo(openedElement);
+               if (openedElement instanceof IParent && existingInfo instanceof JavaElementInfo) {
+                       IJavaElement[] children = ((JavaElementInfo)existingInfo).getChildren();
+                       for (int i = 0, size = children.length; i < size; ++i) {
+                               JavaElement child = (JavaElement) children[i];
+                               try {
+                                       child.close();
+                               } catch (JavaModelException e) {
+                                       // ignore
+                               }
+                       }
+               }
+       
+               Iterator iterator = newElements.keySet().iterator();
+               while (iterator.hasNext()) {
+                       IJavaElement element = (IJavaElement)iterator.next();
+                       Object info = newElements.get(element);
+                       this.cache.putInfo(element, info);
+               }
+       }
        /**
         * Reads the build state for the relevant project.
         */
@@ -1297,7 +1478,7 @@ public class JavaModelManager implements ISaveParticipant {
                                DataInputStream in= new DataInputStream(new BufferedInputStream(new FileInputStream(file)));
                                try {
                                        String pluginID= in.readUTF();
-                                       if (!pluginID.equals(PHPCore.PLUGIN_ID))
+                                       if (!pluginID.equals(JavaCore.PLUGIN_ID))
                                                throw new IOException(Util.bind("build.wrongFileFormat")); //$NON-NLS-1$
                                        String kind= in.readUTF();
                                        if (!kind.equals("STATE")) //$NON-NLS-1$
@@ -1311,7 +1492,7 @@ public class JavaModelManager implements ISaveParticipant {
                                }
                        } catch (Exception e) {
                                e.printStackTrace();
-                               throw new CoreException(new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, Platform.PLUGIN_ERROR, "Error reading last build state for project "+ project.getName(), e)); //$NON-NLS-1$
+                               throw new CoreException(new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR, "Error reading last build state for project "+ project.getName(), e)); //$NON-NLS-1$
                        }
                }
                return null;
@@ -1412,10 +1593,44 @@ public class JavaModelManager implements ISaveParticipant {
                }
        }
        
-       protected void removeInfo(IJavaElement element) {
-               this.cache.removeInfo(element);
-       }
-
+//     PROTECTED VOID REMOVEINFO(IJAVAELEMENT ELEMENT) {
+//             THIS.CACHE.REMOVEINFO(ELEMENT);
+//     }
+       /*
+        * Removes all cached info for the given element (including all children)
+        * from the cache.
+        * Returns the info for the given element, or null if it was closed.
+        */
+       public synchronized Object removeInfoAndChildren(JavaElement element) throws JavaModelException {
+               Object info = this.cache.peekAtInfo(element);
+               if (info != null) {
+                       boolean wasVerbose = false;
+                       try {
+                               if (VERBOSE) {
+                                       System.out.println("CLOSING Element ("+ Thread.currentThread()+"): " + element.toStringWithAncestors());  //$NON-NLS-1$//$NON-NLS-2$
+                                       wasVerbose = true;
+                                       VERBOSE = false;
+                               }
+                               element.closing(info);
+                               if (element instanceof IParent && info instanceof JavaElementInfo) {
+                                       IJavaElement[] children = ((JavaElementInfo)info).getChildren();
+                                       for (int i = 0, size = children.length; i < size; ++i) {
+                                               JavaElement child = (JavaElement) children[i];
+                                               child.close();
+                                       }
+                               }
+                               this.cache.removeInfo(element);
+                               if (wasVerbose) {
+                                       System.out.println("-> Package cache size = " + this.cache.pkgSize()); //$NON-NLS-1$
+                                       System.out.println("-> Openable cache filling ratio = " + NumberFormat.getInstance().format(this.cache.openableFillingRatio()) + "%"); //$NON-NLS-1$//$NON-NLS-2$
+                               }
+                       } finally {
+                               JavaModelManager.VERBOSE = wasVerbose;
+                       }
+                       return info;
+               }
+               return null;
+       }       
        public void removePerProjectInfo(JavaProject javaProject) {
                synchronized(perProjectInfo) { // use the perProjectInfo collection as its own lock
                        IProject project = javaProject.getProject();
@@ -1425,7 +1640,12 @@ public class JavaModelManager implements ISaveParticipant {
                        }
                }
        }
-
+       /*
+        * Resets the temporary cache for newly created elements to null.
+        */
+       public void resetTemporaryCache() {
+               this.temporaryCache.set(null);
+       }
        /**
         * @see ISaveParticipant
         */
@@ -1453,7 +1673,7 @@ public class JavaModelManager implements ISaveParticipant {
                try {
                        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(file)));
                        try {
-                               out.writeUTF(PHPCore.PLUGIN_ID);
+                               out.writeUTF(JavaCore.PLUGIN_ID);
                                out.writeUTF("STATE"); //$NON-NLS-1$
                                if (info.savedState == null) {
                                        out.writeBoolean(false);
@@ -1467,12 +1687,12 @@ public class JavaModelManager implements ISaveParticipant {
                } catch (RuntimeException e) {
                        try {file.delete();} catch(SecurityException se) {}
                        throw new CoreException(
-                               new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
+                               new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
                                        Util.bind("build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$
                } catch (IOException e) {
                        try {file.delete();} catch(SecurityException se) {}
                        throw new CoreException(
-                               new Status(IStatus.ERROR, PHPCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
+                               new Status(IStatus.ERROR, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR,
                                        Util.bind("build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$
                }
                if (PHPBuilder.DEBUG) {
@@ -1508,7 +1728,7 @@ public class JavaModelManager implements ISaveParticipant {
                if (vStats != null) {
                        IStatus[] stats= new IStatus[vStats.size()];
                        vStats.toArray(stats);
-                       throw new CoreException(new MultiStatus(PHPCore.PLUGIN_ID, IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null)); //$NON-NLS-1$
+                       throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID, IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null)); //$NON-NLS-1$
                }
        }
 
@@ -1520,7 +1740,7 @@ public class JavaModelManager implements ISaveParticipant {
 
                // optional behaviour
                // possible value of index 0 is Compute
-               if (!PHPCore.COMPUTE.equals(PHPCore.getOption(PHPCore.CORE_JAVA_BUILD_ORDER))) return; // cannot be customized at project level
+               if (!JavaCore.COMPUTE.equals(JavaCore.getOption(JavaCore.CORE_JAVA_BUILD_ORDER))) return; // cannot be customized at project level
                
                if (javaBuildOrder == null || javaBuildOrder.length <= 1) return;
                
@@ -1585,7 +1805,7 @@ public class JavaModelManager implements ISaveParticipant {
        }
 
        public void shutdown () {
-//     TODO khartlage temp-del
+//     TODO  temp-del
 //             if (this.deltaProcessor.indexManager != null){ // no more indexing
 //                     this.deltaProcessor.indexManager.shutdown();
 //             }
@@ -1661,11 +1881,37 @@ public class JavaModelManager implements ISaveParticipant {
                if (variablePath == JavaModelManager.VariableInitializationInProgress){
                        return;
                } 
-               Preferences preferences = PHPCore.getPlugin().getPluginPreferences();
+               Preferences preferences = JavaCore.getPlugin().getPluginPreferences();
                String variableKey = CP_VARIABLE_PREFERENCES_PREFIX+variableName;
                String variableString = variablePath == null ? CP_ENTRY_IGNORE : variablePath.toString();
                preferences.setDefault(variableKey, CP_ENTRY_IGNORE); // use this default to get rid of removed ones
                preferences.setValue(variableKey, variableString);
-               PHPCore.getPlugin().savePluginPreferences();
+               JavaCore.getPlugin().savePluginPreferences();
+       }
+       /*
+        * Returns all the working copies which have the given owner.
+        * Adds the working copies of the primary owner if specified.
+        * Returns null if it has none.
+        */
+       public ICompilationUnit[] getWorkingCopies(WorkingCopyOwner owner, boolean addPrimary) {
+               synchronized(perWorkingCopyInfos) {
+                       ICompilationUnit[] primaryWCs = addPrimary && owner != DefaultWorkingCopyOwner.PRIMARY 
+                               ? getWorkingCopies(DefaultWorkingCopyOwner.PRIMARY, false) 
+                               : null;
+                       Map workingCopyToInfos = (Map)perWorkingCopyInfos.get(owner);
+                       if (workingCopyToInfos == null) return primaryWCs;
+                       int primaryLength = primaryWCs == null ? 0 : primaryWCs.length;
+                       int size = workingCopyToInfos.size(); // note size is > 0 otherwise pathToPerWorkingCopyInfos would be null
+                       ICompilationUnit[] result = new ICompilationUnit[primaryLength + size];
+                       if (primaryWCs != null) {
+                               System.arraycopy(primaryWCs, 0, result, 0, primaryLength);
+                       }
+                       Iterator iterator = workingCopyToInfos.values().iterator();
+                       int index = primaryLength;
+                       while(iterator.hasNext()) {
+                               result[index++] = ((JavaModelManager.PerWorkingCopyInfo)iterator.next()).getWorkingCopy();
+                       }
+                       return result;
+               }               
        }
 }