The jsp.core changes are
[284932] TaglibIndex optimization ignores important resource change events
[285087] JSP Translator does not support IterationTag constructs
The other jst.web_core.feature changes are
[284302] Memory leaks in IArchive classes
[284327] Memory leaks because of final static constants
The wst.sse.core change is
[285067] BasicStructuredDocument should only acquireLock in a try/finally
The wst.xml.core change is
[285075] Remove automatic promotion of invalid child tags in XMLModelParser
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslator.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslator.java
index 9cd41c0..5dba25c 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslator.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/JSPTranslator.java
@@ -61,6 +61,7 @@
import org.eclipse.jst.jsp.core.internal.provisional.JSP11Namespace;
import org.eclipse.jst.jsp.core.internal.provisional.JSP12Namespace;
import org.eclipse.jst.jsp.core.internal.regions.DOMJSPRegionContexts;
+import org.eclipse.jst.jsp.core.internal.taglib.CustomTag;
import org.eclipse.jst.jsp.core.internal.taglib.TaglibHelper;
import org.eclipse.jst.jsp.core.internal.taglib.TaglibHelperManager;
import org.eclipse.jst.jsp.core.internal.taglib.TaglibVariable;
@@ -245,6 +246,21 @@
*/
private String fELTranslatorID;
+ /**
+ * A structure for holding a region collection marker and list of variable
+ * information. The region can be used later for positioning validation
+ * messages.
+ */
+ static class RegionTag {
+ ITextRegionCollection region;
+ CustomTag tag;
+
+ RegionTag(ITextRegionCollection region, CustomTag tag) {
+ this.region = region;
+ this.tag = tag;
+ }
+ }
+
public JSPTranslator() {
super();
init();
@@ -801,8 +817,13 @@
*/
String decl = ""; //$NON-NLS-1$
if (customTag.getFirstRegion().getType().equals(DOMRegionContext.XML_TAG_OPEN)) {
- TaglibVariable[] taglibVars = helper.getTaglibVariables(tagToAdd, getStructuredDocument(), customTag);
-
+ /*
+ * Start tag
+ */
+ List problems = new ArrayList();
+ CustomTag tag = helper.getCustomTag(tagToAdd, getStructuredDocument(), customTag, problems);
+ TaglibVariable[] taglibVars = tag.getTagVariables();
+ fTranslationProblems.addAll(problems);
// Bug 199047
/*
* Add AT_BEGIN variables
@@ -814,14 +835,21 @@
}
}
+ boolean isEmptyTag = customTag.getLastRegion().getType().equals(DOMRegionContext.XML_EMPTY_TAG_CLOSE);
+
/**
* Add opening curly brace
*/
-
StringBuffer text = new StringBuffer();
+ if (!isEmptyTag && tag.isIterationTag() && tag.getTagClassName() != null)
+ text.append("\nwhile (true) "); //$NON-NLS-1$
text.append("{ // <"); //$NON-NLS-1$
text.append(tagToAdd);
- text.append(">\n"); //$NON-NLS-1$
+ if (isEmptyTag)
+ text.append("/>\n"); //$NON-NLS-1$
+ else
+ text.append(">\n"); //$NON-NLS-1$
+
appendToBuffer(text.toString(), fUserCode, false, customTag); //$NON-NLS-1$
/**
@@ -838,9 +866,9 @@
* If empty, pop from stack, add ending curly brace and AT_END
* variables
*/
- if (customTag.getLastRegion().getType().equals(DOMRegionContext.XML_EMPTY_TAG_CLOSE)) {
+ if (isEmptyTag) {
text = new StringBuffer();
- text.append("} // </"); //$NON-NLS-1$
+ text.append("} // <"); //$NON-NLS-1$
text.append(tagToAdd);
text.append("/>\n"); //$NON-NLS-1$
appendToBuffer(text.toString(), fUserCode, false, customTag); //$NON-NLS-1$
@@ -856,7 +884,7 @@
* Store for use at end tag and for accurate pairing even with
* extra end tags (with empty non-null array)
*/
- fTagToVariableMap.push(tagToAdd, taglibVars);
+ fTagToVariableMap.push(tagToAdd, new RegionTag(customTag, tag));
}
}
/**
@@ -864,14 +892,23 @@
*/
else if (customTag.getFirstRegion().getType().equals(DOMRegionContext.XML_END_TAG_OPEN)) {
// pop the variables
- TaglibVariable[] taglibVars = (TaglibVariable[]) fTagToVariableMap.pop(tagToAdd);
- if (taglibVars != null) {
+ RegionTag regionTag = (RegionTag) fTagToVariableMap.pop(tagToAdd);
+ if (regionTag != null) {
+ TaglibVariable[] taglibVars = regionTag.tag.getTagVariables();
// even an empty array will indicate a need for a closing
// brace
StringBuffer text = new StringBuffer();
- text.append("} // </"); //$NON-NLS-1$
+ if (regionTag.tag.isIterationTag())
+ doAfterBody(text, regionTag);
+ text.append("} "); //$NON-NLS-1$
+ text.append("// </"); //$NON-NLS-1$
text.append(tagToAdd);
- text.append(">\n"); //$NON-NLS-1$
+ if (customTag.getLastRegion().getType().equals(DOMRegionContext.XML_EMPTY_TAG_CLOSE)) {
+ text.append("/>\n"); //$NON-NLS-1$
+ }
+ else {
+ text.append(">\n"); //$NON-NLS-1$
+ }
appendToBuffer(text.toString(), fUserCode, false, customTag); //$NON-NLS-1$
/*
@@ -890,6 +927,12 @@
}
}
+ private void doAfterBody(StringBuffer buffer, RegionTag regionTag) {
+ buffer.append("\tif ( (new "); //$NON-NLS-1$
+ buffer.append(regionTag.tag.getTagClassName());
+ buffer.append("()).doAfterBody() != javax.servlet.jsp.tagext.BodyTag.EVAL_BODY_AGAIN)\n\t\tbreak;\n"); //$NON-NLS-1$
+ }
+
private IFile getFile() {
IFile f = null;
IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(getStructuredDocument());
@@ -955,6 +998,30 @@
translateCodas();
/*
+ * Any contents left in the map indicate start tags that never had end
+ * tags. While the '{' that is present without the matching '}' should
+ * cause a Java translation fault, that's not particularly helpful to
+ * a user who may only know how to use custom tags as tags. Ultimately
+ * unbalanced custom tags should just be reported as unbalanced tags,
+ * and unbalanced '{'/'}' only reported when the user actually
+ * unbalanced them with scriptlets.
+ */
+ Iterator regionAndTaglibVariables = fTagToVariableMap.values().iterator();
+ while (regionAndTaglibVariables.hasNext()) {
+ RegionTag regionTag = (RegionTag) regionAndTaglibVariables.next();
+
+ StringBuffer text = new StringBuffer();
+ // Account for iteration tags that have a missing end tag
+ if (regionTag.tag.isIterationTag())
+ doAfterBody(text, regionTag);
+ text.append("} "); //$NON-NLS-1$
+ text.append("// [</"); //$NON-NLS-1$
+ text.append(regionTag.tag.getTagName());
+ text.append(">]"); //$NON-NLS-1$
+ appendToBuffer(text.toString(), fUserCode, false, fStructuredDocument.getLastStructuredDocumentRegion());
+ }
+ fTagToVariableMap.clear();
+ /*
* Make sure any extra custom tag start tags won't cause compiler
* problems, they should instead be reported as unbalanced tags
*/
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/StackMap.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/StackMap.java
index 3ec0b34..2412687 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/StackMap.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/java/StackMap.java
@@ -14,6 +14,7 @@
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.Map;
import java.util.Stack;
@@ -139,4 +140,19 @@
}
return size;
}
+
+ /**
+ * Returns all of the values of this StackMap.
+ *
+ * @return the values of every Stack within this StackMap.
+ */
+ Collection values() {
+ Collection values = new LinkedList();
+ Iterator i = fInternalMap.values().iterator();
+ while (i.hasNext()) {
+ Collection c = (Collection) i.next();
+ values.addAll(c);
+ }
+ return values;
+ }
}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/CustomTag.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/CustomTag.java
new file mode 100644
index 0000000..0186713
--- /dev/null
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/CustomTag.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * Copyright (c) 2009 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.taglib;
+
+/**
+ * Contains information about a custom tag including the tag name (with prefix),
+ * the class that defines the functionality of the tag, TEI class, any scripting variables associated with the
+ * TEI class, and if the class is an iteration tag
+ *
+ */
+public class CustomTag {
+
+ private final String fTagName;
+ private final String fClassName;
+ private final String fTeiClassName;
+ private final boolean fIsIterationTag;
+ private final TaglibVariable[] fVariables;
+
+ public CustomTag(String tagName, String className, String teiClassName, TaglibVariable[] tagVariables, boolean isIterationTag) {
+ fTagName = tagName;
+ fClassName = className;
+ fTeiClassName = teiClassName;
+ fVariables = tagVariables;
+ fIsIterationTag = isIterationTag;
+ }
+
+ /**
+ * Returns the name of the tag with its prefix
+ * @return the tag name including prefix
+ */
+ public String getTagName() {
+ return fTagName;
+ }
+
+ /**
+ * Returns the name of the implementation class for the tag
+ * @return the name of the implementation class for the tag
+ */
+ public String getTagClassName() {
+ return fClassName;
+ }
+
+ /**
+ * Returns the name of the TagExtraInfo class for the tag
+ * @return the name of the TagExtraInfo class for the tag
+ */
+ public String getTeiClassName() {
+ return fTeiClassName;
+ }
+
+ /**
+ * Returns an array of scripting variables associated with the TagExtraInfo class
+ * @return an array of scripting variables associated with the TagExtraInfo class
+ */
+ public TaglibVariable[] getTagVariables() {
+ return fVariables;
+ }
+
+ /**
+ * Identifies if the tag implements the IterationTag interface
+ * @return true if the tag implements the IterationTag interface; false otherwise
+ */
+ public boolean isIterationTag() {
+ return fIsIterationTag;
+ }
+}
diff --git a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
index 8064e08..063c796 100644
--- a/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
+++ b/bundles/org.eclipse.jst.jsp.core/src/org/eclipse/jst/jsp/core/internal/taglib/TaglibHelper.java
@@ -23,6 +23,7 @@
import java.util.Map;
import java.util.Set;
+import javax.servlet.jsp.tagext.IterationTag;
import javax.servlet.jsp.tagext.TagAttributeInfo;
import javax.servlet.jsp.tagext.TagData;
import javax.servlet.jsp.tagext.TagExtraInfo;
@@ -101,6 +102,89 @@
fTranslationProblems = new HashMap();
}
+ private boolean isIterationTag(TLDElementDeclaration elementDecl, IStructuredDocument document, ITextRegionCollection customTag, List problems) {
+ Class tagClass;
+ try {
+ tagClass = Class.forName(elementDecl.getTagclass(), true, getClassloader());
+ if (tagClass != null) {
+ return IterationTag.class.isInstance(tagClass.newInstance());
+ }
+ } catch (ClassNotFoundException e) {
+ Object createdProblem = createJSPProblem(document, customTag, IJSPProblem.TagClassNotFound, JSPCoreMessages.TaglibHelper_3, elementDecl.getTagclass(), true);
+ if (createdProblem != null)
+ problems.add(createdProblem);
+ if (DEBUG)
+ Logger.logException(elementDecl.getTagclass(), e);
+ } catch (IllegalAccessException e) {
+ if (DEBUG)
+ Logger.logException(elementDecl.getTagclass(), e);
+ } catch (InstantiationException e) {
+ if (DEBUG)
+ Logger.logException(elementDecl.getTagclass(), e);
+ } catch (NoClassDefFoundError e) {
+ if (DEBUG)
+ Logger.logException(elementDecl.getTagclass(), e);
+ }
+ return false;
+ }
+
+ public CustomTag getCustomTag(String tagToAdd, IStructuredDocument structuredDoc, ITextRegionCollection customTag, List problems) {
+ List results = new ArrayList();
+ boolean isIterationTag = false;
+ String tagClass = null;
+ String teiClass = null;
+ if (problems == null)
+ problems = new ArrayList();
+ ModelQuery mq = getModelQuery(structuredDoc);
+ if (mq != null) {
+ TLDCMDocumentManager mgr = TaglibController.getTLDCMDocumentManager(structuredDoc);
+
+ if (mgr != null) {
+
+ List trackers = mgr.getCMDocumentTrackers(-1);
+ Iterator taglibs = trackers.iterator();
+
+ CMDocument doc = null;
+ CMNamedNodeMap elements = null;
+ while (taglibs.hasNext()) {
+ doc = (CMDocument) taglibs.next();
+ CMNode node = null;
+ if ((elements = doc.getElements()) != null && (node = elements.getNamedItem(tagToAdd)) != null && node.getNodeType() == CMNode.ELEMENT_DECLARATION) {
+
+ if (node instanceof CMNodeWrapper) {
+ node = ((CMNodeWrapper) node).getOriginNode();
+ }
+ TLDElementDeclaration tldElementDecl = (TLDElementDeclaration) node;
+
+ tagClass = tldElementDecl.getTagclass();
+ teiClass = tldElementDecl.getTeiclass();
+ isIterationTag = isIterationTag(tldElementDecl, structuredDoc, customTag, problems);
+ /*
+ * Although clearly not the right place to add validation
+ * design-wise, this is the first time we have the
+ * necessary information to validate the tag class.
+ */
+ validateTagClass(structuredDoc, customTag, tldElementDecl, problems);
+
+ // 1.2+ taglib style
+ addVariables(results, node, customTag);
+
+ // for 1.1 need more info from taglib tracker
+ if (doc instanceof TaglibTracker) {
+ String uri = ((TaglibTracker) doc).getURI();
+ String prefix = ((TaglibTracker) doc).getPrefix();
+ // only for 1.1 taglibs
+ addTEIVariables(structuredDoc, customTag, results, tldElementDecl, prefix, uri, problems);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ return new CustomTag(tagToAdd, tagClass, teiClass, (TaglibVariable[]) results.toArray(new TaglibVariable[results.size()]), isIterationTag);
+ }
+
/**
* @param tagToAdd
* is the name of the tag whose variables we want
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 7785fc0..01bae41 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
@@ -290,8 +290,6 @@
}
}
for (int i = 0; i < projects.length; i++) {
- if (deltas[i].getKind() == IResourceDelta.CHANGED && (deltas[i].getFlags() == IResourceDelta.ENCODING || deltas[i].getFlags() == IResourceDelta.MARKERS))
- continue;
try {
if (deltas[i] != null && deltas[i].getKind() != IResourceDelta.REMOVED && projects[i].isAccessible()) {
ProjectDescription description = getDescription(projects[i]);
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
index ede7786..bd3191f 100644
--- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
@@ -2336,8 +2336,9 @@
stopPostNotificationProcessing();
clearReadOnly();
- acquireLock();
try {
+ acquireLock();
+
CharSequenceReader subSetTextStoreReader = new CharSequenceReader((CharSequence) getStore(), 0, getStore().getLength());
resetParser(subSetTextStoreReader, 0);
//
diff --git a/bundles/org.eclipse.wst.xml.core/META-INF/MANIFEST.MF b/bundles/org.eclipse.wst.xml.core/META-INF/MANIFEST.MF
index c4bd59b..671395d 100644
--- a/bundles/org.eclipse.wst.xml.core/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.wst.xml.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@
Bundle-ManifestVersion: 2
Bundle-Name: %pluginName
Bundle-SymbolicName: org.eclipse.wst.xml.core; singleton:=true
-Bundle-Version: 1.1.308.qualifier
+Bundle-Version: 1.1.309.qualifier
Bundle-Activator: org.eclipse.wst.xml.core.internal.XMLCorePlugin
Bundle-Vendor: %providerName
Bundle-Localization: plugin
diff --git a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java
index 06d25f8..5585428 100644
--- a/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java
+++ b/bundles/org.eclipse.wst.xml.core/src/org/eclipse/wst/xml/core/internal/document/XMLModelParser.java
@@ -1279,75 +1279,20 @@
* org.w3c.dom.Node
*/
private void insertNode(Node node) {
- if (node == null)
- return;
- if (this.context == null)
- return;
-
- Node parent = this.context.getParentNode();
- if (parent == null)
- return;
- Node next = this.context.getNextNode();
- while (parent.getNodeType() == Node.ELEMENT_NODE) {
- ElementImpl element = (ElementImpl) parent;
- if (canContain(element, node)) {
- if (!element.hasStartTag() && next == element.getFirstChild()) {
- // first child of implicit tag
- // deletege to the parent
- parent = element.getParentNode();
- if (parent == null)
- return;
- next = element;
+ if(node != null && this.context != null) {
+ Node parent = this.context.getParentNode();
+ if(parent != null) {
+ Node next = this.context.getNextNode();
+
+ insertNode(parent, node, next);
+ next = node.getNextSibling();
+ if (next != null) {
this.context.setNextNode(next);
- continue;
- }
- break;
- }
- parent = element.getParentNode();
- if (parent == null)
- return;
-
- // promote siblings
- Node newNext = element.getNextSibling();
- Node child = next;
- while (child != null) {
- Node nextChild = child.getNextSibling();
- element.removeChild(child);
- parent.insertBefore(child, newNext);
- child = nextChild;
- }
-
- // leave the old end tag where it is
- if (element.hasEndTag()) {
- Element end = element.removeEndTag();
- if (end != null) {
- parent.insertBefore(end, newNext);
- if (next == null)
- next = end;
+ } else {
+ this.context.setParentNode(node.getParentNode());
}
}
- if (!element.hasStartTag()) {
- // implicit element
- if (!element.hasChildNodes()) {
- parent.removeChild(element);
- }
- }
-
- // update context
- if (next == null)
- next = newNext;
- if (next != null)
- this.context.setNextNode(next);
- else
- this.context.setParentNode(parent);
}
-
- insertNode(parent, node, next);
- next = node.getNextSibling();
- if (next != null)
- this.context.setNextNode(next);
- else
- this.context.setParentNode(node.getParentNode());
}
/**
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/buildnotes_org.eclipse.wst.xml_core.feature.patch.html b/features/org.eclipse.wst.xml_core.feature.patch/buildnotes_org.eclipse.wst.xml_core.feature.patch.html
index e775190..5836167 100644
--- a/features/org.eclipse.wst.xml_core.feature.patch/buildnotes_org.eclipse.wst.xml_core.feature.patch.html
+++ b/features/org.eclipse.wst.xml_core.feature.patch/buildnotes_org.eclipse.wst.xml_core.feature.patch.html
@@ -11,5 +11,7 @@
<p>Bug <a href='https://bugs.eclipse.org/272389'>272389</a>. tokenizers stuck in loop when input not matched</p>
<p>Bug <a href="https://bugs.eclipse.org/282205">282205</a>. HTMLHeadTokenizer can get stuck in an infinite loop</p>
+<p>Bug <a href="https://bugs.eclipse.org/285067">285067</a>. BasicStructuredDocument should only acquireLock in a try/finally</p>
+<p>Bug <a href="https://bugs.eclipse.org/285075">285075</a>. Remove automatic promotion of invalid child tags in XMLModelParser</p>
</body>
</head>
\ No newline at end of file
diff --git a/features/org.eclipse.wst.xml_core.feature.patch/feature.properties b/features/org.eclipse.wst.xml_core.feature.patch/feature.properties
index 6341949..aac3a28 100644
--- a/features/org.eclipse.wst.xml_core.feature.patch/feature.properties
+++ b/features/org.eclipse.wst.xml_core.feature.patch/feature.properties
@@ -29,6 +29,8 @@
\n\
Bug https://bugs.eclipse.org/272389 tokenizers stuck in loop when input not matched\n\
Bug https://bugs.eclipse.org/282205 HTMLHeadTokenizer can get stuck in an infinite loop\n\
+Bug https://bugs.eclipse.org/285067 BasicStructuredDocument should only acquireLock in a try/finally\n\
+Bug https://bugs.eclipse.org/285075 Remove automatic promotion of invalid child tags in XMLModelParser\n\
\n\
# "copyright" property - text of the "Feature Update Copyright"
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 fb68732..b1b085c 100644
--- a/features/org.eclipse.wst.xml_core.feature.patch/feature.xml
+++ b/features/org.eclipse.wst.xml_core.feature.patch/feature.xml
@@ -26,6 +26,13 @@
</requires>
<plugin
+ id="org.eclipse.wst.xml.core"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
id="org.eclipse.wst.sse.core"
download-size="0"
install-size="0"