[154971] TaglibIndexer causing performance problems during project migration
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ProjectDescription.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ProjectDescription.java
index 7c3edbb..a58ad95 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ProjectDescription.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/ProjectDescription.java
@@ -242,12 +242,9 @@
 	 * A brief representation of the information in a TLD.
 	 */
 	static class TaglibInfo {
-		public TaglibInfo() {
-			super();
-		}
-
 		// extract only when asked?
 		String description;
+
 		float jspVersion;
 		String largeIcon;
 		String shortName;
@@ -255,6 +252,10 @@
 		String tlibVersion;
 		String uri;
 
+		public TaglibInfo() {
+			super();
+		}
+
 		public String toString() {
 			return "TaglibInfo|" + shortName + "|" + tlibVersion + "|" + smallIcon + "|" + largeIcon + "|" + jspVersion + "|" + uri + "|" + description;
 		}
@@ -433,7 +434,8 @@
 	private static final String WEB_INF = "WEB-INF"; //$NON-NLS-1$
 	private static final IPath WEB_INF_PATH = new Path(WEB_INF);
 	private static final String WEB_XML = "web.xml"; //$NON-NLS-1$
-	private static final String SAVE_FORMAT_VERSION = "1.0";
+	private static final String SAVE_FORMAT_VERSION = "1.0.1";
+	private static final String BUILDPATH_DIRTY = "BUILDPATH_DIRTY"; //$NON-NLS-1$
 
 	/*
 	 * Records active JARs on the classpath. Taglib descriptors should be
@@ -441,6 +443,12 @@
 	 */
 	Hashtable fClasspathJars;
 
+	/**
+	 * Notes that the build path information is stale. Some operations can now
+	 * be skipped until a resolve/getAvailable call is made.
+	 */
+	boolean fBuildPathIsDirty = false;
+
 	Stack fClasspathProjects = null;
 
 	// holds references by URI to JARs
@@ -675,6 +683,13 @@
 		return record;
 	}
 
+	private void ensureUpTodate() {
+		if (fBuildPathIsDirty) {
+			indexClasspath();
+			fBuildPathIsDirty = false;
+		}
+	}
+
 	private TaglibInfo extractInfo(String basePath, InputStream tldContents) {
 		TaglibInfo info = new TaglibInfo();
 		if (tldContents != null) {
@@ -724,6 +739,8 @@
 	}
 
 	synchronized List getAvailableTaglibRecords(IPath path) {
+		ensureUpTodate();
+
 		Collection implicitReferences = getImplicitReferences(path.toString()).values();
 		List records = new ArrayList(fTLDReferences.size() + fTagDirReferences.size() + fJARReferences.size() + fWebXMLReferences.size());
 		records.addAll(fTLDReferences.values());
@@ -861,6 +878,10 @@
 	}
 
 	void handleElementChanged(IJavaElementDelta delta) {
+		if (fBuildPathIsDirty) {
+			return;
+		}
+
 		// Logger.log(Logger.INFO_DEBUG, "IJavaElementDelta: " + delta);
 		IJavaElement element = delta.getElement();
 		if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT && ((IPackageFragmentRoot) element).isArchive()) {
@@ -927,6 +948,7 @@
 
 		IJavaProject javaProject = JavaCore.create(fProject);
 		indexClasspath(javaProject);
+
 		if (_debugIndexTime)
 			Logger.log(Logger.INFO, "indexed " + fProject.getName() + " classpath in " + (System.currentTimeMillis() - time0) + "ms"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 	}
@@ -990,6 +1012,17 @@
 		}
 	}
 
+	/*
+	 * private void removeClasspathLibrary(String libraryLocation) { JarRecord
+	 * record = (JarRecord) fClasspathJars.remove(libraryLocation); if (record !=
+	 * null) { URLRecord[] records = (URLRecord[])
+	 * record.getURLRecords().toArray(new URLRecord[0]); for (int i = 0; i <
+	 * records.length; i++) {
+	 * fClasspathReferences.remove(records[i].getURI()); }
+	 * TaglibIndex.fireTaglibRecordEvent(new TaglibRecordEvent(record,
+	 * ITaglibRecordEvent.REMOVED)); } }
+	 */
+
 	/**
 	 * @param javaProject
 	 */
@@ -1009,17 +1042,6 @@
 		}
 	}
 
-	/*
-	 * private void removeClasspathLibrary(String libraryLocation) { JarRecord
-	 * record = (JarRecord) fClasspathJars.remove(libraryLocation); if (record !=
-	 * null) { URLRecord[] records = (URLRecord[])
-	 * record.getURLRecords().toArray(new URLRecord[0]); for (int i = 0; i <
-	 * records.length; i++) {
-	 * fClasspathReferences.remove(records[i].getURI()); }
-	 * TaglibIndex.fireTaglibRecordEvent(new TaglibRecordEvent(record,
-	 * ITaglibRecordEvent.REMOVED)); } }
-	 */
-
 	private String readTextofChild(Node node, String childName) {
 		NodeList children = node.getChildNodes();
 		for (int i = 0; i < children.getLength(); i++) {
@@ -1086,6 +1108,8 @@
 	 * @return
 	 */
 	ITaglibRecord resolve(String basePath, String reference) {
+		ensureUpTodate();
+
 		ITaglibRecord record = null;
 		String path = null;
 
@@ -1172,8 +1196,10 @@
 	 */
 	private void restoreReferences() {
 		if (TaglibIndex.ENABLED) {
+			// resources first
 			index();
-
+			// now build path
+			
 			// ================ test reload time ========================
 			boolean restored = false;
 			File savedState = new File(fSaveStateFilename);
@@ -1196,8 +1222,8 @@
 								lineText = doc.get(line.getOffset(), line.getLength());
 								StringTokenizer toker = new StringTokenizer(lineText, "|");
 								if (toker.hasMoreTokens()) {
-									String referenceType = toker.nextToken();
-									if ("JAR".equalsIgnoreCase(referenceType)) {
+									String tokenType = toker.nextToken();
+									if ("JAR".equalsIgnoreCase(tokenType)) {
 										boolean has11TLD = Boolean.valueOf(toker.nextToken()).booleanValue();
 										// make the rest the libraryLocation
 										String libraryLocation = toker.nextToken();
@@ -1245,7 +1271,7 @@
 
 										fClasspathJars.put(libraryLocation, libraryRecord);
 									}
-									else if ("URL".equalsIgnoreCase(referenceType)) {
+									else if ("URL".equalsIgnoreCase(tokenType)) {
 										// make the rest the URL
 										String urlString = toker.nextToken();
 										while (toker.hasMoreTokens()) {
@@ -1301,6 +1327,10 @@
 										}
 										fClasspathReferences.put(urlRecord.getURI(), urlRecord);
 									}
+									// last since only occurs once
+									else if (BUILDPATH_DIRTY.equalsIgnoreCase(tokenType)) {
+										fBuildPathIsDirty = Boolean.valueOf(toker.nextToken()).booleanValue();
+									}
 								}
 							}
 							if (libraryRecord != null) {
@@ -1331,7 +1361,7 @@
 
 
 			if (!restored) {
-				indexClasspath();
+				setBuildPathIsDirty();
 			}
 		}
 	}
@@ -1341,21 +1371,24 @@
 	 * description is being cleared and not after every update.
 	 */
 	void saveReferences() {
+		// the build path information is out of date, remember that
 		time0 = System.currentTimeMillis();
 		Writer writer = null;
 
 		/**
 		 * <pre>
-		 *                                 1.0
-		 *                                 Save classpath information (! is field delimiter)
-		 *                                 Jars are saved as &quot;JAR:&quot;+ has11TLD + jar path 
-		 *                                 URLRecords as &quot;URL:&quot;+URL
+		 *                                        1.0
+		 *                                        Save classpath information (| is field delimiter)
+		 *                                        Jars are saved as &quot;JAR:&quot;+ has11TLD + jar path 
+		 *                                        URLRecords as &quot;URL:&quot;+URL
 		 * </pre>
 		 */
 		try {
 			writer = new OutputStreamWriter(new FileOutputStream(fSaveStateFilename), "utf8");
 			writer.write(SAVE_FORMAT_VERSION);
 			writer.write('\n');
+			writer.write(BUILDPATH_DIRTY + "|" + fBuildPathIsDirty);
+			writer.write('\n');
 
 			Enumeration jars = fClasspathJars.keys();
 			while (jars.hasMoreElements()) {
@@ -1390,6 +1423,10 @@
 		if (_debugIndexTime)
 			Logger.log(Logger.INFO, "time spent saving index for " + fProject.getName() + ": " + (System.currentTimeMillis() - time0));
 	}
+	
+	void setBuildPathIsDirty() {
+		fBuildPathIsDirty = true;
+	}
 
 	void updateClasspathLibrary(String libraryLocation, int deltaKind) {
 		JarRecord libraryRecord = null;
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndex.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndex.java
index 8779879..f7b257e 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndex.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/taglib/TaglibIndex.java
@@ -143,13 +143,13 @@
 
 			classpathStack.push(project.getElementName());
 			try {
-				/* Handle changes to this project's build path */
+				/* Handle large changes to this project's build path */
 				IResource resource = project.getCorrespondingResource();
 				if (resource.getType() == IResource.PROJECT && !projectsIndexed.contains(resource)) {
 					ProjectDescription description = getDescription((IProject) resource);
 					if (description != null && !frameworkIsShuttingDown()) {
 						projectsIndexed.add(resource);
-						description.indexClasspath();
+						description.setBuildPathIsDirty();
 					}
 				}
 				/*