243747 [hotbug] "Cannot find the tag library descriptor" after removing a taglib file with duplicate URI
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/ArrayMap.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/ArrayMap.java
new file mode 100644
index 0000000..507ec77
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/ArrayMap.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2008 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ *
+ *******************************************************************************/
+package org.eclipse.jst.jsp.core.internal.java;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+/**
+ * This implementation of a hashtable maps keys to arrays
+ * to support multiple values being associated with a single
+ * key. To remove a specific entry, a key and inserted value must
+ * be provided. Removing just based on the key name will remove all
+ * values stored under that key
+ *
+ */
+public class ArrayMap extends Hashtable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public ArrayMap(int size) {
+ super(size);
+ }
+
+ public synchronized Object put(Object key, Object value) {
+ Object[] values = (Object[]) super.get(key);
+ Object[] newValues = null;
+
+ if (values == null || values.length == 0)
+ newValues = new Object[1];
+ else {
+ newValues = new Object[values.length + 1];
+ System.arraycopy(values, 0, newValues, 0, values.length);
+ }
+
+ newValues[newValues.length - 1] = value;
+ return super.put(key, newValues);
+ }
+
+ /**
+ * Removes the first occurrence of <code>value</code> from the list
+ * of values associated with <code>key</code>
+ *
+ * @param key the key that has <code>value</code>
+ * @param value the specific value to remove from the key
+ * @return The item removed from the list of values
+ */
+ public synchronized Object remove(Object key, Object value) {
+ Object[] values = (Object[]) super.get(key);
+ Object removed = null;
+ Object[] result = null;
+ if (values != null && value != null) {
+ for (int i = 0; i < values.length; i++) {
+ if (value.equals(values[i])) {
+ removed = values[i];
+ result = new Object[values.length - 1];
+
+ if (result.length > 0) {
+ // Copy left of value
+ System.arraycopy(values, 0, result, 0, i);
+ // Copy right of value
+ if (i < (values.length - 1))
+ System.arraycopy(values, i+1, result, i, result.length - i);
+ }
+ else
+ super.remove(key);
+
+ break;
+ }
+ }
+ }
+
+ if(result != null && result.length > 0)
+ super.put(key, result);
+
+ return removed;
+ }
+
+ public Collection values() {
+ Collection valuemaps = super.values();
+ Collection values = new ArrayList();
+
+ for(Iterator i = valuemaps.iterator(); i.hasNext();)
+ values.addAll(Arrays.asList((Object[]) i.next()));
+
+ return values;
+ }
+
+}
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 6c24aca..306829a 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
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2005, 2007 IBM Corporation and others.
+ * Copyright (c) 2005, 2008 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
@@ -73,10 +73,12 @@
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP11TLDNames;
import org.eclipse.jst.jsp.core.internal.contentmodel.tld.provisional.JSP12TLDNames;
import org.eclipse.jst.jsp.core.internal.contenttype.DeploymentDescriptorPropertyCache;
+import org.eclipse.jst.jsp.core.internal.java.ArrayMap;
import org.eclipse.jst.jsp.core.internal.util.DocumentProvider;
import org.eclipse.jst.jsp.core.internal.util.FacetModuleCoreSupport;
import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
import org.eclipse.wst.sse.core.internal.util.JarUtilities;
+import org.eclipse.wst.sse.core.internal.util.Sorter;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
@@ -87,6 +89,7 @@
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import com.ibm.icu.text.Collator;
import com.ibm.icu.util.StringTokenizer;
class ProjectDescription {
@@ -475,6 +478,36 @@
return s.toString();
}
}
+
+ private class TaglibSorter extends Sorter {
+ Collator collator = Collator.getInstance();
+
+ public boolean compare(Object elementOne, Object elementTwo) {
+ /**
+ * Returns true if elementTwo is 'greater than' elementOne This is
+ * the 'ordering' method of the sort operation. Each subclass
+ * overides this method with the particular implementation of the
+ * 'greater than' concept for the objects being sorted.
+ */
+
+ return (collator.compare(getTaglibPath((ITaglibRecord) elementOne), getTaglibPath((ITaglibRecord) elementTwo))) < 0;
+ }
+
+ private String getTaglibPath(ITaglibRecord record) {
+ switch(record.getRecordType()) {
+ case ITaglibRecord.JAR:
+ return ((JarRecord) record).getLocation().toString();
+ case ITaglibRecord.TAGDIR:
+ return ((TagDirRecord) record).getPath().toString();
+ case ITaglibRecord.TLD:
+ return ((TLDRecord) record).getPath().toString();
+ case ITaglibRecord.URL:
+ return ((URLRecord) record).getBaseLocation();
+ default:
+ return ""; //$NON-NLS-1$
+ }
+ }
+ }
static boolean _debugIndexCreation = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indexcreation")); //$NON-NLS-1$ //$NON-NLS-2$
static boolean _debugIndexTime = "true".equalsIgnoreCase(Platform.getDebugOption("org.eclipse.jst.jsp.core/taglib/indextime")); //$NON-NLS-1$ //$NON-NLS-2$
@@ -543,6 +576,8 @@
ILock LOCK = Job.getJobManager().newLock();
private long time0;
+
+ private TaglibSorter fTaglibSorter = new TaglibSorter();
ProjectDescription(IProject project, String saveStateFile) {
super();
@@ -1097,7 +1132,7 @@
String localRoot = getLocalRoot(path);
Hashtable implicitReferences = (Hashtable) fImplicitReferences.get(localRoot);
if (implicitReferences == null) {
- implicitReferences = new Hashtable(1);
+ implicitReferences = new ArrayMap(1);
fImplicitReferences.put(localRoot, implicitReferences);
}
return implicitReferences;
@@ -1427,7 +1462,7 @@
URLRecord[] records = (URLRecord[]) record.getURLRecords().toArray(new URLRecord[0]);
for (int i = 0; i < records.length; i++) {
TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, records[i], ITaglibIndexDelta.REMOVED));
- getImplicitReferences(jar.getFullPath().toString()).remove(records[i].getURI());
+ ((ArrayMap) getImplicitReferences(jar.getFullPath().toString())).remove(records[i].getURI(), records[i]);
}
if (record.has11TLD) {
TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
@@ -1459,7 +1494,7 @@
TLDRecord record = (TLDRecord) fTLDReferences.remove(tld.getFullPath().toString());
if (record != null) {
if (record.getURI() != null) {
- getImplicitReferences(tld.getFullPath().toString()).remove(record.getURI());
+ ((ArrayMap) getImplicitReferences(tld.getFullPath().toString())).remove(record.getURI(), record);
}
TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, record, ITaglibIndexDelta.REMOVED));
}
@@ -1474,7 +1509,7 @@
for (int i = 0; i < records.length; i++) {
if (_debugIndexCreation)
Logger.log(Logger.INFO, "removed record for " + records[i].getURI() + "@" + records[i].path); //$NON-NLS-1$ //$NON-NLS-2$
- getImplicitReferences(webxml.getFullPath().toString()).remove(records[i].getURI());
+ ((ArrayMap) getImplicitReferences(webxml.getFullPath().toString())).remove(records[i].getURI(), records[i]);
TaglibIndex.getInstance().addDelta(new TaglibIndexDelta(fProject, records[i], ITaglibIndexDelta.REMOVED));
}
}
@@ -1539,7 +1574,12 @@
record = (ITaglibRecord) fTLDReferences.get(path);
}
if (record == null && jspVersion >= 1.2) {
- record = (ITaglibRecord) getImplicitReferences(basePath).get(reference);
+ Object[] records = (Object[]) getImplicitReferences(basePath).get(reference);
+ if (records != null && records.length > 0) {
+ if (records.length > 1)
+ records = fTaglibSorter.sort(records);
+ record = (ITaglibRecord) records[records.length - 1];
+ }
}
@@ -1593,7 +1633,12 @@
for (int i = 0; i < webxmls.length; i++) {
if (record != null)
continue;
- record = (ITaglibRecord) getImplicitReferences(webxmls[i].path.toString()).get(reference);
+ Object[] records = (Object[]) getImplicitReferences(webxmls[i].path.toString()).get(reference);
+ if (records != null && records.length > 0) {
+ if (records.length > 1)
+ records = fTaglibSorter.sort(records);
+ record = (ITaglibRecord) records[records.length - 1];
+ }
}
}
}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Sorter.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Sorter.java
new file mode 100644
index 0000000..e3ff42b
--- /dev/null
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/util/Sorter.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * IBM Corporation - initial API and implementation
+ * Jens Lukowski/Innoopract - initial renaming/restructuring
+ *
+ *******************************************************************************/
+package org.eclipse.wst.sse.core.internal.util;
+
+
+
+/**
+ * The SortOperation takes a collection of objects and returns a sorted
+ * collection of these objects. Concrete instances of this class provide the
+ * criteria for the sorting of the objects based on the type of the objects.
+ */
+public abstract class Sorter {
+
+ /**
+ * Returns true if elementTwo is 'greater than' elementOne This is the
+ * 'ordering' method of the sort operation. Each subclass overides this
+ * method with the particular implementation of the 'greater than' concept
+ * for the objects being sorted.
+ */
+ public abstract boolean compare(Object elementOne, Object elementTwo);
+
+ /**
+ * Sort the objects in sorted collection and return that collection.
+ */
+ private Object[] quickSort(Object[] sortedCollection, int left, int right) {
+ int originalLeft = left;
+ int originalRight = right;
+ Object mid = sortedCollection[(left + right) / 2];
+
+ do {
+ while (compare(sortedCollection[left], mid))
+ left++;
+ while (compare(mid, sortedCollection[right]))
+ right--;
+ if (left <= right) {
+ Object tmp = sortedCollection[left];
+ sortedCollection[left] = sortedCollection[right];
+ sortedCollection[right] = tmp;
+ left++;
+ right--;
+ }
+ } while (left <= right);
+
+ if (originalLeft < right)
+ sortedCollection = quickSort(sortedCollection, originalLeft, right);
+ if (left < originalRight)
+ sortedCollection = quickSort(sortedCollection, left, originalRight);
+
+ return sortedCollection;
+ }
+
+ /**
+ * Return a new sorted collection from this unsorted collection. Sort
+ * using quick sort.
+ */
+ public Object[] sort(Object[] unSortedCollection) {
+ int size = unSortedCollection.length;
+ Object[] sortedCollection = new Object[size];
+
+ //copy the array so can return a new sorted collection
+ System.arraycopy(unSortedCollection, 0, sortedCollection, 0, size);
+ if (size > 1)
+ quickSort(sortedCollection, 0, size - 1);
+
+ return sortedCollection;
+ }
+}
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/feature.xml b/features/org.eclipse.wst.xml_core.feature.patch/feature.xml
index 6de62d2..c41d440 100644
--- a/features/org.eclipse.wst.xml_core.feature.patch/feature.xml
+++ b/features/org.eclipse.wst.xml_core.feature.patch/feature.xml
@@ -22,7 +22,7 @@
</url>
<requires>
- <import feature="org.eclipse.wst.xml_core.feature" version="1.5.5.v200708020450--3YIAAbAWGEFQHU" patch="true"/>
+ <import feature="org.eclipse.wst.xml_core.feature" version="3.0.1.v200807220139-7A7NEGuE7QYGHNH_NuKhUl" patch="true"/>
</requires>
<plugin
@@ -31,11 +31,5 @@
install-size="0"
version="0.0.0"
unpack="false"/>
- <plugin
- id="org.eclipse.wst.xml.core"
- download-size="0"
- install-size="0"
- version="0.0.0"
- unpack="false"/>
</feature>