/******************************************************************************* * Copyright (c) 2000, 2003 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package net.sourceforge.phpdt.internal.core; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; 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; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.WeakHashMap; //import java.util.zip.ZipFile; import net.sourceforge.phpdt.core.ElementChangedEvent; import net.sourceforge.phpdt.core.IClasspathEntry; import net.sourceforge.phpdt.core.ICompilationUnit; import net.sourceforge.phpdt.core.IElementChangedListener; import net.sourceforge.phpdt.core.IJavaElement; import net.sourceforge.phpdt.core.IJavaElementDelta; import net.sourceforge.phpdt.core.IJavaModel; import net.sourceforge.phpdt.core.IJavaProject; import net.sourceforge.phpdt.core.IPackageFragment; import net.sourceforge.phpdt.core.IPackageFragmentRoot; import net.sourceforge.phpdt.core.IParent; import net.sourceforge.phpdt.core.IProblemRequestor; import net.sourceforge.phpdt.core.IWorkingCopy; import net.sourceforge.phpdt.core.JavaCore; import net.sourceforge.phpdt.core.JavaModelException; import net.sourceforge.phpdt.core.WorkingCopyOwner; import net.sourceforge.phpdt.core.compiler.IProblem; import net.sourceforge.phpdt.internal.core.builder.PHPBuilder; import net.sourceforge.phpdt.internal.core.util.Util; import net.sourceforge.phpdt.internal.core.util.PHPFileUtil; import net.sourceforge.phpeclipse.PHPeclipsePlugin; 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.IResourceDelta; import org.eclipse.core.resources.ISaveContext; import org.eclipse.core.resources.ISaveParticipant; //import org.eclipse.core.resources.IWorkspace; //import org.eclipse.core.resources.IWorkspaceDescription; 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.IProgressMonitor; import org.eclipse.core.runtime.ISafeRunnable; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.MultiStatus; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.Platform; //import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.Preferences; import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.Preferences.PropertyChangeEvent; /** * The JavaModelManager manages instances of * IJavaModel. IElementChangedListeners register * with the JavaModelManager, and receive * ElementChangedEvents for all IJavaModels. *

* The single instance of JavaModelManager is available from the * static method JavaModelManager.getJavaModelManager(). */ public class JavaModelManager implements ISaveParticipant { /** * Unique handle onto the JavaModel */ final JavaModel javaModel = new JavaModel(); // public IndexManager indexManager = new IndexManager(); /** * Classpath variables pool */ public static HashMap Variables = new HashMap(5); public static HashMap PreviousSessionVariables = new HashMap(5); public static HashSet OptionNames = new HashSet(20); public final static String CP_VARIABLE_PREFERENCES_PREFIX = PHPeclipsePlugin.PLUGIN_ID + ".classpathVariable."; //$NON-NLS-1$ public final static String CP_CONTAINER_PREFERENCES_PREFIX = PHPeclipsePlugin.PLUGIN_ID + ".classpathContainer."; //$NON-NLS-1$ public final static String CP_ENTRY_IGNORE = "####"; //$NON-NLS-1$ /** * Classpath containers pool */ public static HashMap containers = new HashMap(5); public static HashMap PreviousSessionContainers = new HashMap(5); /** * Name of the extension point for contributing classpath variable * initializers */ // public static final String CPVARIABLE_INITIALIZER_EXTPOINT_ID = // "classpathVariableInitializer" ; //$NON-NLS-1$ /** * Name of the extension point for contributing classpath container * initializers */ // public static final String CPCONTAINER_INITIALIZER_EXTPOINT_ID = // "classpathContainerInitializer" ; //$NON-NLS-1$ /** * Name of the extension point for contributing a source code formatter */ public static final String FORMATTER_EXTPOINT_ID = "codeFormatter"; // $/** /** * Value of the content-type for Java source files */ public static final String JAVA_SOURCE_CONTENT_TYPE = PHPeclipsePlugin.PLUGIN_ID + ".phpSource"; //$NON-NLS-1$NON-NLS-1$ /** * Special value used for recognizing ongoing initialization and breaking * initialization cycles */ public final static IPath VariableInitializationInProgress = new Path( "Variable Initialization In Progress"); //$NON-NLS-1$ // public final static IClasspathContainer ContainerInitializationInProgress // = new IClasspathContainer() { // public IClasspathEntry[] getClasspathEntries() { return null; } // public String getDescription() { return "Container Initialization In // Progress"; } //$NON-NLS-1$ // public int getKind() { return 0; } // public IPath getPath() { return null; } // public String toString() { return getDescription(); } // }; // private static final String INDEX_MANAGER_DEBUG = PHPeclipsePlugin.PLUGIN_ID // + "/debug/indexmanager"; //$NON-NLS-1$ // private static final String COMPILER_DEBUG = PHPeclipsePlugin.PLUGIN_ID // + "/debug/compiler"; //$NON-NLS-1$ private static final String JAVAMODEL_DEBUG = PHPeclipsePlugin.PLUGIN_ID + "/debug/javamodel"; //$NON-NLS-1$ private static final String CP_RESOLVE_DEBUG = PHPeclipsePlugin.PLUGIN_ID + "/debug/cpresolution"; //$NON-NLS-1$ private static final String ZIP_ACCESS_DEBUG = PHPeclipsePlugin.PLUGIN_ID + "/debug/zipaccess"; //$NON-NLS-1$ private static final String DELTA_DEBUG = PHPeclipsePlugin.PLUGIN_ID + "/debug/javadelta"; //$NON-NLS-1$ // private static final String HIERARCHY_DEBUG = PHPeclipsePlugin.PLUGIN_ID // + "/debug/hierarchy"; //$NON-NLS-1$ private static final String POST_ACTION_DEBUG = PHPeclipsePlugin.PLUGIN_ID + "/debug/postaction"; //$NON-NLS-1$ private static final String BUILDER_DEBUG = PHPeclipsePlugin.PLUGIN_ID + "/debug/builder"; //$NON-NLS-1$ // private static final String COMPLETION_DEBUG = PHPeclipsePlugin.PLUGIN_ID // + "/debug/completion"; //$NON-NLS-1$ // private static final String SELECTION_DEBUG = PHPeclipsePlugin.PLUGIN_ID // + "/debug/selection"; //$NON-NLS-1$ // // private static final String SHARED_WC_DEBUG = PHPeclipsePlugin.PLUGIN_ID // + "/debug/sharedworkingcopy"; //$NON-NLS-1$ // // private static final String SEARCH_DEBUG = PHPeclipsePlugin.PLUGIN_ID // + "/debug/search"; //$NON-NLS-1$ 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. */ public static boolean conflictsWithOutputLocation(IPath folderPath, JavaProject project) { try { IPath outputLocation = project.getOutputLocation(); if (outputLocation == null) { // in doubt, there is a conflict return true; } if (outputLocation.isPrefixOf(folderPath)) { // only allow nesting in project's output if there is a // corresponding source folder // or if the project's output is not used (in other words, if // all source folders have their custom output) IClasspathEntry[] classpath = project .getResolvedClasspath(true); boolean isOutputUsed = false; for (int i = 0, length = classpath.length; i < length; i++) { IClasspathEntry entry = classpath[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_SOURCE) { if (entry.getPath().equals(outputLocation)) { return false; } if (entry.getOutputLocation() == null) { isOutputUsed = true; } } } return isOutputUsed; } return false; } catch (JavaModelException e) { // in doubt, there is a conflict return true; } } // public static IClasspathContainer containerGet(IJavaProject project, // IPath containerPath) { // Map projectContainers = (Map)Containers.get(project); // if (projectContainers == null){ // return null; // } // IClasspathContainer container = // (IClasspathContainer)projectContainers.get(containerPath); // return container; // } // public static void containerPut(IJavaProject project, IPath // containerPath, IClasspathContainer container){ // // Map projectContainers = (Map)Containers.get(project); // if (projectContainers == null){ // projectContainers = new HashMap(1); // Containers.put(project, projectContainers); // } // // if (container == null) { // projectContainers.remove(containerPath); // Map previousContainers = (Map)PreviousSessionContainers.get(project); // if (previousContainers != null){ // previousContainers.remove(containerPath); // } // } else { // projectContainers.put(containerPath, container); // } // // // do not write out intermediate initialization value // if (container == JavaModelManager.ContainerInitializationInProgress) { // return; // } // Preferences preferences = // PHPeclipsePlugin.getPlugin().getPluginPreferences(); // String containerKey = // CP_CONTAINER_PREFERENCES_PREFIX+project.getElementName() // +"|"+containerPath;//$NON-NLS-1$ // String containerString = CP_ENTRY_IGNORE; // try { // if (container != null) { // containerString = // ((JavaProject)project).encodeClasspath(container.getClasspathEntries(), // null, false); // } // } catch(JavaModelException e){ // } // preferences.setDefault(containerKey, CP_ENTRY_IGNORE); // use this // default to get rid of removed ones // preferences.setValue(containerKey, containerString); // PHPeclipsePlugin.getPlugin().savePluginPreferences(); // } /** * Returns the Java element corresponding to the given resource, or * null if unable to associate the given resource with a Java * element. *

* The resource must be one of: *

*

* Creating a Java element has the side effect of creating and opening all * of the element's parents if they are not yet open. */ public static IJavaElement create(IResource resource, IJavaProject project) { if (resource == null) { return null; } int type = resource.getType(); switch (type) { case IResource.PROJECT: 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 JavaCore.create((IWorkspaceRoot) resource); default: return null; } } /** * Returns the Java element corresponding to the given file, its project * being the given project. Returns null if unable to * associate the given file with a Java element. * *

* The file must be one of: *

*

* Creating a Java element has the side effect of creating and opening all * of the element's parents if they are not yet open. */ public static IJavaElement create(IFile file, IJavaProject project) { if (file == null) { return null; } if (project == null) { project = JavaCore.create(file.getProject()); } if (file.getFileExtension() != null) { String name = file.getName(); if (PHPFileUtil.isValidPHPUnitName(name)) // if (PHPFileUtil.isPHPFile(file)) return createCompilationUnitFrom(file, project); // if (ProjectPrefUtil.isValidClassFileName(name)) // return createClassFileFrom(file, project); // if (ProjectPrefUtil.isArchiveFileName(name)) // return createJarPackageFragmentRootFrom(file, project); } return null; } /** * Returns the package fragment or package fragment root corresponding to * the given folder, its parent or great parent being the given project. or * null if unable to associate the given folder with a Java * element. *

* Note that a package fragment root is returned rather than a default * package. *

* Creating a Java element has the side effect of creating and opening all * of the element's parents if they are not yet open. */ public static IJavaElement create(IFolder folder, IJavaProject project) { if (folder == null) { return null; } if (project == null) { project = JavaCore.create(folder.getProject()); } IJavaElement element = determineIfOnClasspath(folder, project); if (conflictsWithOutputLocation(folder.getFullPath(), (JavaProject) project) || (folder.getName().indexOf('.') >= 0 && !(element instanceof IPackageFragmentRoot))) { return null; // only package fragment roots are allowed with dot // names } else { return element; } } /** * Creates and returns a class file element for the given * .class file, its project being the given project. Returns * null if unable to recognize the class file. */ // public static IClassFile createClassFileFrom(IFile file, IJavaProject // project ) { // if (file == null) { // return null; // } // if (project == null) { // project = PHPCore.create(file.getProject()); // } // IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file, // project); // if (pkg == null) { // // fix for 1FVS7WE // // not on classpath - make the root its folder, and a default package // IPackageFragmentRoot root = // project.getPackageFragmentRoot(file.getParent()); // pkg = root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME); // } // return pkg.getClassFile(file.getName()); // } /** * Creates and returns a compilation unit element for the given * .java file, its project being the given project. Returns * null if unable to recognize the compilation unit. */ public static ICompilationUnit createCompilationUnitFrom(IFile file, IJavaProject project) { if (file == null) return null; if (project == null) { project = JavaCore.create(file.getProject()); } IPackageFragment pkg = (IPackageFragment) determineIfOnClasspath(file, project); if (pkg == null) { // not on classpath - make the root its folder, and a default // package IPackageFragmentRoot root = project.getPackageFragmentRoot(file .getParent()); pkg = root .getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME); if (VERBOSE) { System.out .println("WARNING : creating unit element outside classpath (" + Thread.currentThread() + "): " + file.getFullPath()); //$NON-NLS-1$//$NON-NLS-2$ } } return pkg.getCompilationUnit(file.getName()); } /** * Creates and returns a handle for the given JAR file, its project being * the given project. The Java model associated with the JAR's project may * be created as a side effect. Returns null if unable to * create a JAR package fragment root. (for example, if the JAR file * represents a non-Java resource) */ // public static IPackageFragmentRoot createJarPackageFragmentRootFrom(IFile // file, IJavaProject project) { // if (file == null) { // return null; // } // if (project == null) { // project = PHPCore.create(file.getProject()); // } // // // Create a jar package fragment root only if on the classpath // IPath resourcePath = file.getFullPath(); // try { // IClasspathEntry[] entries = // ((JavaProject)project).getResolvedClasspath(true); // for (int i = 0, length = entries.length; i < length; i++) { // IClasspathEntry entry = entries[i]; // IPath rootPath = entry.getPath(); // if (rootPath.equals(resourcePath)) { // return project.getPackageFragmentRoot(file); // } // } // } catch (JavaModelException e) { // } // return null; // } /** * Returns the package fragment root represented by the resource, or 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) { IPath resourcePath = resource.getFullPath(); try { IClasspathEntry[] entries = 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); for (int i = 0; i < entries.length; i++) { IClasspathEntry entry = entries[i]; if (entry.getEntryKind() == IClasspathEntry.CPE_PROJECT) continue; IPath rootPath = entry.getPath(); if (rootPath.equals(resourcePath)) { return project.getPackageFragmentRoot(resource); } else if (rootPath.isPrefixOf(resourcePath) && !Util.isExcluded(resource, null, ((ClasspathEntry) entry) .fullExclusionPatternChars())) { // given we have a resource child of the root, it cannot be // a JAR pkg root IPackageFragmentRoot root = ((JavaProject) project) .getFolderPackageFragmentRoot(rootPath); if (root == null) return null; IPath pkgPath = resourcePath.removeFirstSegments(rootPath .segmentCount()); if (resource.getType() == IResource.FILE) { // if the resource is a file, then remove the last // segment which // is the file name in the package 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(); return root.getPackageFragment(pkgName); } else { String pkgName = Util.packageName(pkgPath); if (pkgName == null) {// || // JavaConventions.validatePackageName(pkgName).getSeverity() // == IStatus.ERROR) { return null; } return root.getPackageFragment(pkgName); } } } } catch (JavaModelException npe) { return null; } return null; } /** * The singleton manager */ private final static JavaModelManager Manager = new JavaModelManager(); /** * Infos cache. */ 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. */ private boolean isFiring = true; /** * Queue of deltas created explicily by the Java Model that have yet to be * fired. */ ArrayList javaModelDeltas = new ArrayList(); /** * Queue of reconcile deltas on working copies that have yet to be fired. * This is a table form IWorkingCopy to IJavaElementDelta */ HashMap reconcileDeltas = new HashMap(); /** * Collection of listeners for Java element deltas */ private IElementChangedListener[] elementChangedListeners = new IElementChangedListener[5]; private int[] elementChangedListenerMasks = new int[5]; private int elementChangedListenerCount = 0; public int currentChangeEventType = ElementChangedEvent.PRE_AUTO_BUILD; public static final int DEFAULT_CHANGE_EVENT = 0; // must not collide with // ElementChangedEvent // event masks /** * Used to convert IResourceDeltas into * IJavaElementDeltas. */ // public final DeltaProcessor deltaProcessor = new DeltaProcessor(this); /** * Used to update the JavaModel for IJavaElementDeltas. */ private final ModelUpdater modelUpdater = new ModelUpdater(); /** * Workaround for bug 15168 circular errors not reported This is a cache of * the projects before any project addition/deletion has started. */ public IJavaProject[] javaProjectsCache; /** * Table from IProject to PerProjectInfo. NOTE: this object itself is used * as a lock to synchronize creation/removal of per project infos */ protected Map perProjectInfo = new HashMap(5); /** * A map from ICompilationUnit to IWorkingCopy of the shared working copies. */ public Map sharedWorkingCopies = new HashMap(); /** * A weak set of the known scopes. */ protected WeakHashMap searchScopes = new WeakHashMap(); // public static class PerProjectInfo { // public IProject project; // public Object savedState; // public boolean triedRead; // public IClasspathEntry[] classpath; // public IClasspathEntry[] lastResolvedClasspath; // public Map resolvedPathToRawEntries; // reverse map from resolved path to // raw entries // public IPath outputLocation; // public Preferences preferences; // public PerProjectInfo(IProject project) { // // this.triedRead = false; // this.savedState = null; // this.project = project; // } // } public static class PerProjectInfo { public IProject project; public Object savedState; public boolean triedRead; public IClasspathEntry[] rawClasspath; public IClasspathEntry[] resolvedClasspath; public Map resolvedPathToRawEntries; // reverse map from resolved // path to raw entries public IPath outputLocation; public Preferences preferences; public PerProjectInfo(IProject project) { this.triedRead = false; this.savedState = null; this.project = project; } // updating raw classpath need to flush obsoleted cached information // about resolved entries public synchronized void updateClasspathInformation( IClasspathEntry[] newRawClasspath) { this.rawClasspath = newRawClasspath; this.resolvedClasspath = null; this.resolvedPathToRawEntries = null; } public String toString() { StringBuffer buffer = new StringBuffer(); buffer.append("Info for "); //$NON-NLS-1$ buffer.append(this.project.getFullPath()); buffer.append("\nRaw classpath:\n"); //$NON-NLS-1$ if (this.rawClasspath == null) { buffer.append(" \n"); //$NON-NLS-1$ } else { for (int i = 0, length = this.rawClasspath.length; i < length; i++) { buffer.append(" "); //$NON-NLS-1$ buffer.append(this.rawClasspath[i]); buffer.append('\n'); } } buffer.append("Resolved classpath:\n"); //$NON-NLS-1$ IClasspathEntry[] resolvedCP = this.resolvedClasspath; if (resolvedCP == null) { buffer.append(" \n"); //$NON-NLS-1$ } else { for (int i = 0, length = resolvedCP.length; i < length; i++) { buffer.append(" "); //$NON-NLS-1$ buffer.append(resolvedCP[i]); buffer.append('\n'); } } buffer.append("Output location:\n "); //$NON-NLS-1$ if (this.outputLocation == null) { buffer.append(""); //$NON-NLS-1$ } else { buffer.append(this.outputLocation); } return buffer.toString(); } } 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; /** * A cache of opened zip files per thread. (map from Thread to map of IPath * to java.io.ZipFile) NOTE: this object itself is used as a lock to * synchronize creation/removal of entries */ //private HashMap zipFiles = new HashMap(); /** * Update the classpath variable cache */ public static class PluginPreferencesListener implements Preferences.IPropertyChangeListener { /** * @see org.eclipse.core.runtime.Preferences.IPropertyChangeListener#propertyChange(PropertyChangeEvent) */ public void propertyChange(Preferences.PropertyChangeEvent event) { // 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); // } } } /** * Line separator to use throughout the JavaModel for any source edit * operation */ public static String LINE_SEPARATOR = System.getProperty("line.separator"); //$NON-NLS-1$ /** * Constructs a new JavaModelManager */ private JavaModelManager() { } /** * @deprecated - discard once debug has converted to not using it */ // public void addElementChangedListener(IElementChangedListener listener) { // this.addElementChangedListener(listener, // ElementChangedEvent.POST_CHANGE // | ElementChangedEvent.POST_RECONCILE); // } /** * addElementChangedListener method comment. Need to clone defensively the * listener information, in case some listener is reacting to some * notification iteration by adding/changing/removing any of the other (for * example, if it deregisters itself). */ public void addElementChangedListener(IElementChangedListener listener, int eventMask) { for (int i = 0; i < this.elementChangedListenerCount; i++) { if (this.elementChangedListeners[i].equals(listener)) { // only clone the masks, since we could be in the middle of // notifications and one listener decide to change // any event mask of another listeners (yet not notified). int cloneLength = this.elementChangedListenerMasks.length; System .arraycopy( this.elementChangedListenerMasks, 0, this.elementChangedListenerMasks = new int[cloneLength], 0, cloneLength); this.elementChangedListenerMasks[i] = eventMask; // could be // different return; } } // may need to grow, no need to clone, since iterators will have cached // original arrays and max boundary and we only add to the end. int length; if ((length = this.elementChangedListeners.length) == this.elementChangedListenerCount) { System .arraycopy( this.elementChangedListeners, 0, this.elementChangedListeners = new IElementChangedListener[length * 2], 0, length); System.arraycopy(this.elementChangedListenerMasks, 0, this.elementChangedListenerMasks = new int[length * 2], 0, length); } this.elementChangedListeners[this.elementChangedListenerCount] = listener; this.elementChangedListenerMasks[this.elementChangedListenerCount] = eventMask; this.elementChangedListenerCount++; } /** * Starts caching ZipFiles. Ignores if there are already clients. */ // public void cacheZipFiles() { // synchronized (this.zipFiles) { // Thread currentThread = Thread.currentThread(); // if (this.zipFiles.get(currentThread) != null) // return; // this.zipFiles.put(currentThread, new HashMap()); // } // } // public void closeZipFile(ZipFile zipFile) { // if (zipFile == null) // return; // synchronized (this.zipFiles) { // if (this.zipFiles.get(Thread.currentThread()) != null) { // return; // zip file will be closed by call to flushZipFiles // } // try { // if (JavaModelManager.ZIP_ACCESS_VERBOSE) { // System.out // .println("(" + Thread.currentThread() + ") [JavaModelManager.closeZipFile(ZipFile)] Closing ZipFile on " + zipFile.getName()); //$NON-NLS-1$ //$NON-NLS-2$ // } // zipFile.close(); // } catch (IOException e) { // } // } // } /** * Configure the plugin with respect to option settings defined in * ".options" file */ public void configurePluginDebugOptions() { 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$ // // option = Platform.getDebugOption(COMPILER_DEBUG); // if(option != null) Compiler.DEBUG = // option.equalsIgnoreCase("true") ; //$NON-NLS-1$ // // option = Platform.getDebugOption(COMPLETION_DEBUG); // if(option != null) CompletionEngine.DEBUG = // option.equalsIgnoreCase("true") ; //$NON-NLS-1$ // option = Platform.getDebugOption(CP_RESOLVE_DEBUG); if (option != null) JavaModelManager.CP_RESOLVE_VERBOSE = option .equalsIgnoreCase("true"); //$NON-NLS-1$ option = Platform.getDebugOption(DELTA_DEBUG); if (option != null) DeltaProcessor.VERBOSE = option.equalsIgnoreCase("true"); //$NON-NLS-1$ // option = Platform.getDebugOption(HIERARCHY_DEBUG); // if(option != null) TypeHierarchy.DEBUG = // option.equalsIgnoreCase("true") ; //$NON-NLS-1$ // // option = Platform.getDebugOption(INDEX_MANAGER_DEBUG); // if(option != null) IndexManager.VERBOSE = // option.equalsIgnoreCase("true") ; //$NON-NLS-1$ option = Platform.getDebugOption(JAVAMODEL_DEBUG); if (option != null) JavaModelManager.VERBOSE = option.equalsIgnoreCase("true"); //$NON-NLS-1$ option = Platform.getDebugOption(POST_ACTION_DEBUG); if (option != null) JavaModelOperation.POST_ACTION_VERBOSE = option .equalsIgnoreCase("true"); //$NON-NLS-1$ // option = Platform.getDebugOption(SEARCH_DEBUG); // if(option != null) SearchEngine.VERBOSE = // option.equalsIgnoreCase("true") ; //$NON-NLS-1$ // // option = Platform.getDebugOption(SELECTION_DEBUG); // if(option != null) SelectionEngine.DEBUG = // 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 */ public void doneSaving(ISaveContext context) { } /** * 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. */ public void fire(IJavaElementDelta customDelta, int eventType) { if (!this.isFiring) return; if (DeltaProcessor.VERBOSE && (eventType == DEFAULT_CHANGE_EVENT || eventType == ElementChangedEvent.PRE_AUTO_BUILD)) { System.out .println("-----------------------------------------------------------------------------------------------------------------------");//$NON-NLS-1$ } IJavaElementDelta deltaToNotify; if (customDelta == null) { deltaToNotify = this.mergeDeltas(this.javaModelDeltas); } else { deltaToNotify = customDelta; } // Refresh internal scopes if (deltaToNotify != null) { // TODO temp-del // Iterator scopes = this.scopes.keySet().iterator(); // while (scopes.hasNext()) { // AbstractSearchScope scope = (AbstractSearchScope)scopes.next(); // scope.processDelta(deltaToNotify); // } } // Notification // Important: if any listener reacts to notification by updating the // listeners list or mask, these lists will // be duplicated, so it is necessary to remember original lists in a // variable (since field values may change under us) IElementChangedListener[] listeners = this.elementChangedListeners; int[] listenerMask = this.elementChangedListenerMasks; int listenerCount = this.elementChangedListenerCount; switch (eventType) { case DEFAULT_CHANGE_EVENT: firePreAutoBuildDelta(deltaToNotify, listeners, listenerMask, listenerCount); firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount); fireReconcileDelta(listeners, listenerMask, listenerCount); break; case ElementChangedEvent.PRE_AUTO_BUILD: firePreAutoBuildDelta(deltaToNotify, listeners, listenerMask, listenerCount); break; case ElementChangedEvent.POST_CHANGE: firePostChangeDelta(deltaToNotify, listeners, listenerMask, listenerCount); fireReconcileDelta(listeners, listenerMask, listenerCount); break; } } private void firePreAutoBuildDelta(IJavaElementDelta deltaToNotify, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { if (DeltaProcessor.VERBOSE) { System.out .println("FIRING PRE_AUTO_BUILD Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$ System.out .println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$ } if (deltaToNotify != null) { notifyListeners(deltaToNotify, ElementChangedEvent.PRE_AUTO_BUILD, listeners, listenerMask, listenerCount); } } private void firePostChangeDelta(IJavaElementDelta deltaToNotify, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { // post change deltas if (DeltaProcessor.VERBOSE) { System.out .println("FIRING POST_CHANGE Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$ System.out .println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$ } if (deltaToNotify != null) { // flush now so as to keep listener reactions to post their own // deltas for subsequent iteration this.flush(); notifyListeners(deltaToNotify, ElementChangedEvent.POST_CHANGE, listeners, listenerMask, listenerCount); } } private void fireReconcileDelta(IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { IJavaElementDelta deltaToNotify = mergeDeltas(this.reconcileDeltas .values()); if (DeltaProcessor.VERBOSE) { System.out .println("FIRING POST_RECONCILE Delta [" + Thread.currentThread() + "]:"); //$NON-NLS-1$//$NON-NLS-2$ System.out .println(deltaToNotify == null ? "" : deltaToNotify.toString()); //$NON-NLS-1$ } if (deltaToNotify != null) { // flush now so as to keep listener reactions to post their own // deltas for subsequent iteration this.reconcileDeltas = new HashMap(); notifyListeners(deltaToNotify, ElementChangedEvent.POST_RECONCILE, listeners, listenerMask, listenerCount); } } public void notifyListeners(IJavaElementDelta deltaToNotify, int eventType, IElementChangedListener[] listeners, int[] listenerMask, int listenerCount) { final ElementChangedEvent extraEvent = new ElementChangedEvent( deltaToNotify, eventType); for (int i = 0; i < listenerCount; i++) { if ((listenerMask[i] & eventType) != 0) { final IElementChangedListener listener = listeners[i]; long start = -1; if (DeltaProcessor.VERBOSE) { System.out .print("Listener #" + (i + 1) + "=" + listener.toString());//$NON-NLS-1$//$NON-NLS-2$ start = System.currentTimeMillis(); } // wrap callbacks with Safe runnable for subsequent listeners to // be called when some are causing grief SafeRunner.run(new ISafeRunnable() { public void handleException(Throwable exception) { Util .log(exception, "Exception occurred in listener of Java element change notification"); //$NON-NLS-1$ } public void run() throws Exception { listener.elementChanged(extraEvent); } }); if (DeltaProcessor.VERBOSE) { System.out .println(" -> " + (System.currentTimeMillis() - start) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ } } } } /** * Flushes all deltas without firing them. */ protected void flush() { this.javaModelDeltas = new ArrayList(); } /** * Flushes ZipFiles cache if there are no more clients. */ // public void flushZipFiles() { // synchronized (this.zipFiles) { // Thread currentThread = Thread.currentThread(); // HashMap map = (HashMap) this.zipFiles.remove(currentThread); // if (map == null) // return; // Iterator iterator = map.values().iterator(); // while (iterator.hasNext()) { // try { // ZipFile zipFile = (ZipFile) iterator.next(); // if (JavaModelManager.ZIP_ACCESS_VERBOSE) { // System.out // .println("(" + currentThread + ") [JavaModelManager.flushZipFiles()] Closing ZipFile on " + zipFile.getName()); //$NON-NLS-1$//$NON-NLS-2$ // } // zipFile.close(); // } catch (IOException e) { // } // } // } // } public DeltaProcessor getDeltaProcessor() { return this.deltaState.getDeltaProcessor(); } /** * Returns the set of elements which are out of synch with their buffers. */ protected Map getElementsOutOfSynchWithBuffers() { return this.elementsOutOfSynchWithBuffers; } // public IndexManager getIndexManager() { // return this.indexManager; // } /** * Returns the IJavaElement represented by the * String memento. */ public IJavaElement getHandleFromMemento(String memento) throws JavaModelException { if (memento == null) { return null; } JavaModel model = (JavaModel) getJavaModel(); if (memento.equals("")) { // workspace memento //$NON-NLS-1$ return model; } int modelEnd = memento.indexOf(JavaElement.JEM_JAVAPROJECT); if (modelEnd == -1) { return null; } boolean returnProject = false; int projectEnd = memento.indexOf(JavaElement.JEM_PACKAGEFRAGMENTROOT, modelEnd); if (projectEnd == -1) { projectEnd = memento.length(); returnProject = true; } String projectName = memento.substring(modelEnd + 1, projectEnd); JavaProject proj = (JavaProject) model.getJavaProject(projectName); if (returnProject) { return proj; } // int rootEnd = memento.indexOf(JavaElement.JEM_PACKAGEFRAGMENT, // projectEnd + 1); // TODO temp-del // if (rootEnd == -1) { // return model.getHandleFromMementoForRoot(memento, proj, projectEnd, // memento.length()); // } // IPackageFragmentRoot root = // model.getHandleFromMementoForRoot(memento, proj, projectEnd, // rootEnd); // if (root == null) // return null; // // int end= memento.indexOf(JavaElement.JEM_COMPILATIONUNIT, rootEnd); // if (end == -1) { // end= memento.indexOf(JavaElement.JEM_CLASSFILE, rootEnd); // if (end == -1) { // if (rootEnd + 1 == memento.length()) { // return // root.getPackageFragment(IPackageFragment.DEFAULT_PACKAGE_NAME); // } else { // return root.getPackageFragment(memento.substring(rootEnd + 1)); // } // } // //deal with class file and binary members // return model.getHandleFromMementoForBinaryMembers(memento, root, // rootEnd, end); // } // // //deal with compilation units and source members // return model.getHandleFromMementoForSourceMembers(memento, root, // rootEnd, end); return null; } // public IndexManager getIndexManager() { // return this.deltaProcessor.indexManager; // } /** * Returns the info for the element. */ public Object getInfo(IJavaElement element) { return this.cache.getInfo(element); } /** * Returns the handle to the active Java Model. */ public final JavaModel getJavaModel() { return javaModel; } /** * Returns the singleton JavaModelManager */ public final static JavaModelManager getJavaModelManager() { return Manager; } /** * Returns the last built state for the given project, or null if there is * none. Deserializes the state if necessary. * * For use by image builder and evaluation support only */ public Object getLastBuiltState(IProject project, IProgressMonitor monitor) { if (!JavaProject.hasJavaNature(project)) return null; // should never be requested on non-Java projects PerProjectInfo info = getPerProjectInfo(project, true/* * create if * missing */); if (!info.triedRead) { info.triedRead = true; try { if (monitor != null) monitor.subTask(Util.bind( "build.readStateProgress", project.getName())); //$NON-NLS-1$ info.savedState = readState(project); } catch (CoreException e) { e.printStackTrace(); } } return info.savedState; } /* * Returns the per-project info for the given project. If specified, create * the info if the info doesn't exist. */ public PerProjectInfo getPerProjectInfo(IProject project, boolean create) { synchronized (perProjectInfo) { // use the perProjectInfo collection as // its own lock PerProjectInfo info = (PerProjectInfo) perProjectInfo.get(project); if (info == null && create) { info = new PerProjectInfo(project); perProjectInfo.put(project, info); } return info; } } /* * Returns the per-project info for the given project. If the info doesn't * exist, check for the project existence and create the info. @throws * JavaModelException if the project doesn't exist. */ public PerProjectInfo getPerProjectInfoCheckExistence(IProject project) throws JavaModelException { JavaModelManager.PerProjectInfo info = getPerProjectInfo(project, false /* * don't * create * info */); if (info == null) { if (!JavaProject.hasJavaNature(project)) { 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 = JavaCore.getPlugin(); // if (jdtCorePlugin == null) // return null; // // ArrayList variableList = new ArrayList(5); // // IExtensionPoint extension = // // jdtCorePlugin.getDescriptor().getExtensionPoint(JavaModelManager.CPVARIABLE_INITIALIZER_EXTPOINT_ID); // // if (extension != null) { // // IExtension[] extensions = extension.getExtensions(); // // for(int i = 0; i < extensions.length; i++){ // // IConfigurationElement [] configElements = // // extensions[i].getConfigurationElements(); // // for(int j = 0; j < configElements.length; j++){ // // String varAttribute = configElements[j].getAttribute("variable"); // // //$NON-NLS-1$ // // if (varAttribute != null) variableList.add(varAttribute); // // } // // } // // } // String[] variableNames = new String[variableList.size()]; // variableList.toArray(variableNames); // return variableNames; // } /** * Returns the name of the container IDs for which an CP container * initializer is registered through an extension point */ // public static String[] getRegisteredContainerIDs(){ // // Plugin jdtCorePlugin = PHPCore.getPlugin(); // if (jdtCorePlugin == null) return null; // // ArrayList containerIDList = new ArrayList(5); // IExtensionPoint extension = // jdtCorePlugin.getDescriptor().getExtensionPoint(JavaModelManager.CPCONTAINER_INITIALIZER_EXTPOINT_ID); // if (extension != null) { // IExtension[] extensions = extension.getExtensions(); // for(int i = 0; i < extensions.length; i++){ // IConfigurationElement [] configElements = // extensions[i].getConfigurationElements(); // for(int j = 0; j < configElements.length; j++){ // String idAttribute = configElements[j].getAttribute("id"); //$NON-NLS-1$ // if (idAttribute != null) containerIDList.add(idAttribute); // } // } // } // String[] containerIDs = new String[containerIDList.size()]; // containerIDList.toArray(containerIDs); // return containerIDs; // } /** * Returns the File to use for saving and restoring the last built state for * the given project. */ private File getSerializationFile(IProject project) { if (!project.exists()) return null; 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 of open * ZipFiles. The location must be a absolute path. * * @exception CoreException * If unable to create/open the ZipFile */ // public ZipFile getZipFile(IPath path) throws CoreException { // // synchronized (this.zipFiles) { // TODO: use PeThreadObject which does // // synchronization // Thread currentThread = Thread.currentThread(); // HashMap map = null; // ZipFile zipFile; // if ((map = (HashMap) this.zipFiles.get(currentThread)) != null // && (zipFile = (ZipFile) map.get(path)) != null) { // // return zipFile; // } // String fileSystemPath = null; // IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot(); // IResource file = root.findMember(path); // if (path.isAbsolute() && file != null) { // if (file == null) { // external file // fileSystemPath = path.toOSString(); // } else { // internal resource (not an IFile or not existing) // IPath location; // if (file.getType() != IResource.FILE // || (location = file.getFullPath()) == null) { // 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, // JavaCore.PLUGIN_ID, -1, Util.bind( // "file.notFound", path.toString()), null)); //$NON-NLS-1$ // } // IPath location = file.getFullPath(); // if (location == null) { // 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 { // fileSystemPath = path.toOSString(); // } // // try { // if (ZIP_ACCESS_VERBOSE) { // System.out // .println("(" + currentThread + ") [JavaModelManager.getZipFile(IPath)] Creating ZipFile on " + fileSystemPath); //$NON-NLS-1$ //$NON-NLS-2$ // } // zipFile = new ZipFile(fileSystemPath); // if (map != null) { // map.put(path, zipFile); // } // return zipFile; // } catch (IOException e) { // 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 // QualifiedName qName = new QualifiedName(PHPCore.PLUGIN_ID, "variables"); // //$NON-NLS-1$ // String xmlString = // ResourcesPlugin.getWorkspace().getRoot().getPersistentProperty(qName); // // try { // if (xmlString != null){ // StringReader reader = new StringReader(xmlString); // Element cpElement; // try { // DocumentBuilder parser = // DocumentBuilderFactory.newInstance().newDocumentBuilder(); // cpElement = parser.parse(new InputSource(reader)).getDocumentElement(); // } catch(SAXException e) { // return; // } catch(ParserConfigurationException e){ // return; // } finally { // reader.close(); // } // if (cpElement == null) return; // if (!cpElement.getNodeName().equalsIgnoreCase("variables")) { // //$NON-NLS-1$ // return; // } // // NodeList list= cpElement.getChildNodes(); // int length= list.getLength(); // for (int i= 0; i < length; ++i) { // Node node= list.item(i); // short type= node.getNodeType(); // if (type == Node.ELEMENT_NODE) { // Element element= (Element) node; // if (element.getNodeName().equalsIgnoreCase("variable")) { //$NON-NLS-1$ // variablePut( // element.getAttribute("name"), //$NON-NLS-1$ // new Path(element.getAttribute("path"))); //$NON-NLS-1$ // } // } // } // } // } catch(IOException e){ // } finally { // if (xmlString != null){ // ResourcesPlugin.getWorkspace().getRoot().setPersistentProperty(qName, // null); // flush old one // } // // } // // // load variables and containers from preferences into cache // Preferences preferences = // PHPeclipsePlugin.getDefault().getPluginPreferences(); // // only get variable from preferences not set to their default // String[] propertyNames = preferences.propertyNames(); // int variablePrefixLength = CP_VARIABLE_PREFERENCES_PREFIX.length(); // for (int i = 0; i < propertyNames.length; i++){ // String propertyName = propertyNames[i]; // if (propertyName.startsWith(CP_VARIABLE_PREFERENCES_PREFIX)){ // String varName = propertyName.substring(variablePrefixLength); // IPath varPath = new Path(preferences.getString(propertyName).trim()); // // Variables.put(varName, varPath); // PreviousSessionVariables.put(varName, varPath); // } // if (propertyName.startsWith(CP_CONTAINER_PREFERENCES_PREFIX)){ // recreatePersistedContainer(propertyName, // preferences.getString(propertyName), true/*add to container values*/); // } // } // // override persisted values for variables which have a registered // initializer // String[] registeredVariables = getRegisteredVariableNames(); // for (int i = 0; i < registeredVariables.length; i++) { // String varName = registeredVariables[i]; // Variables.put(varName, null); // reset variable, but leave its entry in // the Map, so it will be part of variable names. // } // // override persisted values for containers which have a registered // initializer // String[] registeredContainerIDs = getRegisteredContainerIDs(); // for (int i = 0; i < registeredContainerIDs.length; i++) { // String containerID = registeredContainerIDs[i]; // Iterator projectIterator = Containers.keySet().iterator(); // while (projectIterator.hasNext()){ // IJavaProject project = (IJavaProject)projectIterator.next(); // Map projectContainers = (Map)Containers.get(project); // if (projectContainers != null){ // Iterator containerIterator = projectContainers.keySet().iterator(); // while (containerIterator.hasNext()){ // IPath containerPath = (IPath)containerIterator.next(); // if (containerPath.segment(0).equals(containerID)) { // registered // container // projectContainers.put(containerPath, null); // reset container value, but // leave entry in Map // } // } // } // } // } // } /** * Merged all awaiting deltas. */ public IJavaElementDelta mergeDeltas(Collection deltas) { if (deltas.size() == 0) return null; if (deltas.size() == 1) return (IJavaElementDelta) deltas.iterator().next(); if (DeltaProcessor.VERBOSE) { System.out .println("MERGING " + deltas.size() + " DELTAS [" + Thread.currentThread() + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } Iterator iterator = deltas.iterator(); IJavaElement javaModel = this.getJavaModel(); JavaElementDelta rootDelta = new JavaElementDelta(javaModel); boolean insertedTree = false; while (iterator.hasNext()) { JavaElementDelta delta = (JavaElementDelta) iterator.next(); if (DeltaProcessor.VERBOSE) { System.out.println(delta.toString()); } IJavaElement element = delta.getElement(); if (javaModel.equals(element)) { IJavaElementDelta[] children = delta.getAffectedChildren(); for (int j = 0; j < children.length; j++) { JavaElementDelta projectDelta = (JavaElementDelta) children[j]; rootDelta.insertDeltaTree(projectDelta.getElement(), projectDelta); insertedTree = true; } IResourceDelta[] resourceDeltas = delta.getResourceDeltas(); if (resourceDeltas != null) { for (int i = 0, length = resourceDeltas.length; i < length; i++) { rootDelta.addResourceDelta(resourceDeltas[i]); insertedTree = true; } } } else { rootDelta.insertDeltaTree(element, delta); insertedTree = true; } } if (insertedTree) { return rootDelta; } else { return null; } } /** * Returns the info for this element without disturbing the cache ordering. */ // TODO: should be synchronized, could answer unitialized info or if cache // is in middle of rehash, could even answer distinct element info protected Object peekAtInfo(IJavaElement element) { return this.cache.peekAtInfo(element); } /** * @see ISaveParticipant */ public void prepareToSave(ISaveContext context) throws CoreException { } // 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. */ protected Object readState(IProject project) throws CoreException { File file = getSerializationFile(project); if (file != null && file.exists()) { try { DataInputStream in = new DataInputStream( new BufferedInputStream(new FileInputStream(file))); try { String pluginID = in.readUTF(); 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$ throw new IOException(Util .bind("build.wrongFileFormat")); //$NON-NLS-1$ if (in.readBoolean()) return PHPBuilder.readState(project, in); if (PHPBuilder.DEBUG) System.out .println("Saved state thinks last build failed for " + project.getName()); //$NON-NLS-1$ } finally { in.close(); } } catch (Exception e) { e.printStackTrace(); 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; } // public static void recreatePersistedContainer(String propertyName, String // containerString, boolean addToContainerValues) { // int containerPrefixLength = CP_CONTAINER_PREFERENCES_PREFIX.length(); // int index = propertyName.indexOf('|', containerPrefixLength); // if (containerString != null) containerString = containerString.trim(); // if (index > 0) { // final String projectName = propertyName.substring(containerPrefixLength, // index).trim(); // JavaProject project = // (JavaProject)getJavaModelManager().getJavaModel().getJavaProject(projectName); // final IPath containerPath = new // Path(propertyName.substring(index+1).trim()); // // if (containerString == null || containerString.equals(CP_ENTRY_IGNORE)) { // containerPut(project, containerPath, null); // } else { // final IClasspathEntry[] containerEntries = // project.decodeClasspath(containerString, false, false); // if (containerEntries != null && containerEntries != // JavaProject.INVALID_CLASSPATH) { // IClasspathContainer container = new IClasspathContainer() { // public IClasspathEntry[] getClasspathEntries() { // return containerEntries; // } // public String getDescription() { // return "Persisted container ["+containerPath+" for project ["+ // projectName+"]"; //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ // } // public int getKind() { // return 0; // } // public IPath getPath() { // return containerPath; // } // public String toString() { // return getDescription(); // } // // }; // if (addToContainerValues) { // containerPut(project, containerPath, container); // } // Map projectContainers = (Map)PreviousSessionContainers.get(project); // if (projectContainers == null){ // projectContainers = new HashMap(1); // PreviousSessionContainers.put(project, projectContainers); // } // projectContainers.put(containerPath, container); // } // } // } // } /** * Registers the given delta with this manager. */ protected void registerJavaModelDelta(IJavaElementDelta delta) { this.javaModelDeltas.add(delta); } /** * Remembers the given scope in a weak set (so no need to remove it: it will * be removed by the garbage collector) */ // public void rememberScope(AbstractSearchScope scope) { // // NB: The value has to be null so as to not create a strong reference on // the scope // this.scopes.put(scope, null); // } /** * removeElementChangedListener method comment. */ public void removeElementChangedListener(IElementChangedListener listener) { for (int i = 0; i < this.elementChangedListenerCount; i++) { if (this.elementChangedListeners[i].equals(listener)) { // need to clone defensively since we might be in the middle of // listener notifications (#fire) int length = this.elementChangedListeners.length; IElementChangedListener[] newListeners = new IElementChangedListener[length]; System.arraycopy(this.elementChangedListeners, 0, newListeners, 0, i); int[] newMasks = new int[length]; System.arraycopy(this.elementChangedListenerMasks, 0, newMasks, 0, i); // copy trailing listeners int trailingLength = this.elementChangedListenerCount - i - 1; if (trailingLength > 0) { System.arraycopy(this.elementChangedListeners, i + 1, newListeners, i, trailingLength); System.arraycopy(this.elementChangedListenerMasks, i + 1, newMasks, i, trailingLength); } // update manager listener state (#fire need to iterate over // original listeners through a local variable to hold onto // the original ones) this.elementChangedListeners = newListeners; this.elementChangedListenerMasks = newMasks; this.elementChangedListenerCount--; return; } } } /** * Remembers the given scope in a weak set (so no need to remove it: it will * be removed by the garbage collector) */ // public void rememberScope(AbstractSearchScope scope) { // // NB: The value has to be null so as to not create a strong reference on // the scope // this.searchScopes.put(scope, null); // } /* * 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(); PerProjectInfo info = (PerProjectInfo) perProjectInfo.get(project); if (info != null) { perProjectInfo.remove(project); } } } /* * Resets the temporary cache for newly created elements to null. */ public void resetTemporaryCache() { this.temporaryCache.set(null); } /** * @see ISaveParticipant */ public void rollback(ISaveContext context) { } private void saveState(PerProjectInfo info, ISaveContext context) throws CoreException { // passed this point, save actions are non trivial if (context.getKind() == ISaveContext.SNAPSHOT) return; // save built state if (info.triedRead) saveBuiltState(info); } /** * Saves the built state for the project. */ private void saveBuiltState(PerProjectInfo info) throws CoreException { if (PHPBuilder.DEBUG) System.out.println(Util.bind( "build.saveStateProgress", info.project.getName())); //$NON-NLS-1$ File file = getSerializationFile(info.project); if (file == null) return; long t = System.currentTimeMillis(); try { DataOutputStream out = new DataOutputStream( new BufferedOutputStream(new FileOutputStream(file))); try { out.writeUTF(JavaCore.PLUGIN_ID); out.writeUTF("STATE"); //$NON-NLS-1$ if (info.savedState == null) { out.writeBoolean(false); } else { out.writeBoolean(true); PHPBuilder.writeState(info.savedState, out); } } finally { out.close(); } } catch (RuntimeException e) { try { file.delete(); } catch (SecurityException se) { } throw new CoreException( 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, JavaCore.PLUGIN_ID, Platform.PLUGIN_ERROR, Util .bind( "build.cannotSaveState", info.project.getName()), e)); //$NON-NLS-1$ } if (PHPBuilder.DEBUG) { t = System.currentTimeMillis() - t; System.out.println(Util.bind( "build.saveStateComplete", String.valueOf(t))); //$NON-NLS-1$ } } private synchronized Map containerClone(IJavaProject project) { Map originalProjectContainers = (Map) JavaModelManager.containers.get(project); if (originalProjectContainers == null) return null; Map projectContainers = new HashMap(originalProjectContainers.size()); projectContainers.putAll(originalProjectContainers); return projectContainers; } /** * @see ISaveParticipant */ public void saving(ISaveContext context) throws CoreException { // save container values on snapshot/full save Preferences preferences = JavaCore.getPlugin().getPluginPreferences(); IJavaProject[] projects = getJavaModel().getJavaProjects(); for (int i = 0, length = projects.length; i < length; i++) { IJavaProject project = projects[i]; // clone while iterating (see // https://bugs.eclipse.org/bugs/show_bug.cgi?id=59638) Map projectContainers = containerClone(project); if (projectContainers == null) continue; for (Iterator keys = projectContainers.keySet().iterator(); keys .hasNext();) { IPath containerPath = (IPath) keys.next(); // IClasspathContainer container = (IClasspathContainer) // projectContainers.get(containerPath); String containerKey = CP_CONTAINER_PREFERENCES_PREFIX + project.getElementName() + "|" + containerPath;//$NON-NLS-1$ String containerString = CP_ENTRY_IGNORE; // try { // if (container != null) { // containerString = // ((JavaProject)project).encodeClasspath(container.getClasspathEntries(), // null, false); // } // } catch(JavaModelException e){ // // could not encode entry: leave it as CP_ENTRY_IGNORE // } preferences.setDefault(containerKey, CP_ENTRY_IGNORE); // use // this // default // to // get // rid // of // removed // ones preferences.setValue(containerKey, containerString); } } JavaCore.getPlugin().savePluginPreferences(); // if (context.getKind() == ISaveContext.FULL_SAVE) { // // will need delta since this save (see // https://bugs.eclipse.org/bugs/show_bug.cgi?id=38658) // context.needDelta(); // // // clean up indexes on workspace full save // // (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=52347) // IndexManager manager = this.indexManager; // if (manager != null) { // manager.cleanUpIndexes(); // } // } IProject savedProject = context.getProject(); if (savedProject != null) { if (!JavaProject.hasJavaNature(savedProject)) return; // ignore PerProjectInfo info = getPerProjectInfo(savedProject, true /* * create * info */); saveState(info, context); return; } ArrayList vStats = null; // lazy initialized for (Iterator iter = perProjectInfo.values().iterator(); iter.hasNext();) { try { PerProjectInfo info = (PerProjectInfo) iter.next(); saveState(info, context); } catch (CoreException e) { if (vStats == null) vStats = new ArrayList(); vStats.add(e.getStatus()); } } if (vStats != null) { IStatus[] stats = new IStatus[vStats.size()]; vStats.toArray(stats); throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID, IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null)); //$NON-NLS-1$ } } /** * @see ISaveParticipant */ // public void saving(ISaveContext context) throws CoreException { // // IProject savedProject = context.getProject(); // if (savedProject != null) { // if (!JavaProject.hasJavaNature(savedProject)) return; // ignore // PerProjectInfo info = getPerProjectInfo(savedProject, true /* create info // */); // saveState(info, context); // return; // } // // ArrayList vStats= null; // lazy initialized // for (Iterator iter = perProjectInfo.values().iterator(); iter.hasNext();) // { // try { // PerProjectInfo info = (PerProjectInfo) iter.next(); // saveState(info, context); // } catch (CoreException e) { // if (vStats == null) // vStats= new ArrayList(); // vStats.add(e.getStatus()); // } // } // if (vStats != null) { // IStatus[] stats= new IStatus[vStats.size()]; // vStats.toArray(stats); // throw new CoreException(new MultiStatus(JavaCore.PLUGIN_ID, // IStatus.ERROR, stats, Util.bind("build.cannotSaveStates"), null)); // //$NON-NLS-1$ // } // } /** * Record the order in which to build the java projects (batch build). This * order is based on the projects classpath settings. */ // protected void setBuildOrder(String[] javaBuildOrder) // throws JavaModelException { // // // optional behaviour // // possible value of index 0 is Compute // 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; // // IWorkspace workspace = ResourcesPlugin.getWorkspace(); // IWorkspaceDescription description = workspace.getDescription(); // String[] wksBuildOrder = description.getBuildOrder(); // // String[] newOrder; // if (wksBuildOrder == null) { // newOrder = javaBuildOrder; // } else { // // remove projects which are already mentionned in java builder // // order // int javaCount = javaBuildOrder.length; // HashMap newSet = new HashMap(javaCount); // create a set for fast // // check // for (int i = 0; i < javaCount; i++) { // newSet.put(javaBuildOrder[i], javaBuildOrder[i]); // } // int removed = 0; // int oldCount = wksBuildOrder.length; // for (int i = 0; i < oldCount; i++) { // if (newSet.containsKey(wksBuildOrder[i])) { // wksBuildOrder[i] = null; // removed++; // } // } // // add Java ones first // newOrder = new String[oldCount - removed + javaCount]; // System.arraycopy(javaBuildOrder, 0, newOrder, 0, javaCount); // java // // projects // // are // // built // // first // // // copy previous items in their respective order // int index = javaCount; // for (int i = 0; i < oldCount; i++) { // if (wksBuildOrder[i] != null) { // newOrder[index++] = wksBuildOrder[i]; // } // } // } // // commit the new build order out // description.setBuildOrder(newOrder); // try { // workspace.setDescription(description); // } catch (CoreException e) { // throw new JavaModelException(e); // } // } /** * Sets the last built state for the given project, or null to reset it. */ public void setLastBuiltState(IProject project, Object state) { if (!JavaProject.hasJavaNature(project)) return; // should never be requested on non-Java projects PerProjectInfo info = getPerProjectInfo(project, true /* * create if * missing */); info.triedRead = true; // no point trying to re-read once using setter info.savedState = state; if (state == null) { // delete state file to ensure a full build // happens if the workspace crashes try { File file = getSerializationFile(project); if (file != null && file.exists()) file.delete(); } catch (SecurityException se) { } } } public void shutdown() { // TODO temp-del // if (this.deltaProcessor.indexManager != null){ // no more indexing // this.deltaProcessor.indexManager.shutdown(); // } try { IJavaModel model = this.getJavaModel(); if (model != null) { model.close(); } } catch (JavaModelException e) { } } /** * Turns the firing mode to on. That is, deltas that are/have been * registered will be fired. */ // public void startDeltas() { // this.isFiring = true; // } /** * Turns the firing mode to off. That is, deltas that are/have been * registered will not be fired until deltas are started again. */ // public void stopDeltas() { // this.isFiring = false; // } /** * Update Java Model given some delta */ public void updateJavaModel(IJavaElementDelta customDelta) { if (customDelta == null) { for (int i = 0, length = this.javaModelDeltas.size(); i < length; i++) { IJavaElementDelta delta = (IJavaElementDelta) this.javaModelDeltas .get(i); this.modelUpdater.processJavaDelta(delta); } } else { this.modelUpdater.processJavaDelta(customDelta); } } public static IPath variableGet(String variableName) { return (IPath) Variables.get(variableName); } // public static String[] variableNames() { // int length = Variables.size(); // String[] result = new String[length]; // Iterator vars = Variables.keySet().iterator(); // int index = 0; // while (vars.hasNext()) { // result[index++] = (String) vars.next(); // } // return result; // } // public static void variablePut(String variableName, IPath variablePath) { // // // update cache - do not only rely on listener refresh // if (variablePath == null) { // Variables.remove(variableName); // PreviousSessionVariables.remove(variableName); // } else { // Variables.put(variableName, variablePath); // } // // // do not write out intermediate initialization value // if (variablePath == JavaModelManager.VariableInitializationInProgress) { // return; // } // 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); // 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; } } /* * A HashSet that contains the IJavaProject whose classpath is being * resolved. */ private ThreadLocal classpathsBeingResolved = new ThreadLocal(); private HashSet getClasspathBeingResolved() { HashSet result = (HashSet) this.classpathsBeingResolved.get(); if (result == null) { result = new HashSet(); this.classpathsBeingResolved.set(result); } return result; } public boolean isClasspathBeingResolved(IJavaProject project) { return getClasspathBeingResolved().contains(project); } public void setClasspathBeingResolved(IJavaProject project, boolean classpathIsResolved) { if (classpathIsResolved) { getClasspathBeingResolved().add(project); } else { getClasspathBeingResolved().remove(project); } } }