You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by jd...@apache.org on 2011/03/21 22:54:41 UTC
svn commit: r1083980 - in /wicket/trunk/wicket-core/src:
main/java/org/apache/wicket/markup/
main/java/org/apache/wicket/markup/parser/
main/java/org/apache/wicket/markup/parser/filter/
test/java/org/apache/wicket/ajax/ test/java/org/apache/wicket/mark...
Author: jdonnerstag
Date: Mon Mar 21 21:54:40 2011
New Revision: 1083980
URL: http://svn.apache.org/viewvc?rev=1083980&view=rev
Log:
- fixed test case
- some more changes to the "framework"
Will adjust and apply Pedro's patch next
Issue: WICKET-3433
Added:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/HtmlSpecialTag.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/TagStack.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/ConditionalCommentFilter.java
Modified:
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/AbstractMarkupParser.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupException.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupParser.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupStream.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/AbstractMarkupFilter.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/IXmlPullParser.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlPullParser.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlTag.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java
wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RootMarkupFilter.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ajax/MockComponent1-expected.html
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/MarkupParserTest.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/panel/PanelTest.java
wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/parser/XmlPullParserTest.java
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/AbstractMarkupParser.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/AbstractMarkupParser.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/AbstractMarkupParser.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/AbstractMarkupParser.java Mon Mar 21 21:54:40 2011
@@ -209,9 +209,9 @@ public abstract class AbstractMarkupPars
* @return The next tag
* @throws ParseException
*/
- private ComponentTag getNextTag() throws ParseException
+ private MarkupElement getNextTag() throws ParseException
{
- return (ComponentTag)markupFilterChain.nextElement();
+ return markupFilterChain.nextElement();
}
/**
@@ -225,52 +225,62 @@ public abstract class AbstractMarkupPars
int size = markup.size();
// Loop through tags
- ComponentTag tag;
- while (null != (tag = getNextTag()))
+ MarkupElement elem;
+ while (null != (elem = getNextTag()))
{
- boolean add = (tag.getId() != null);
- if (!add && tag.isClose())
+ if (elem instanceof HtmlSpecialTag)
{
- add = ((tag.getOpenTag() != null) && (tag.getOpenTag().getId() != null));
+ elem = new ComponentTag(((HtmlSpecialTag)elem).getXmlTag());
}
- // Add tag to list?
- if (add || tag.isModified() || (markup.size() != size))
+ if (elem instanceof ComponentTag)
{
- // Add text from last position to the current tag position
- CharSequence text = xmlParser.getInputFromPositionMarker(tag.getPos());
- if (text.length() > 0)
- {
- text = handleRawText(text.toString());
+ ComponentTag tag = (ComponentTag)elem;
- // Make sure you add it at the correct location.
- // IMarkupFilters might have added elements as well.
- markup.addMarkupElement(size, new RawMarkup(text));
+ boolean add = (tag.getId() != null);
+ if (!add && tag.isClose())
+ {
+ add = ((tag.getOpenTag() != null) && (tag.getOpenTag().getId() != null));
}
- xmlParser.setPositionMarker();
-
- if (add)
+ // Add tag to list?
+ if (add || tag.isModified() || (markup.size() != size))
{
- // Add to the markup unless the tag has been flagged as
- // to be removed from the markup. (e.g. <wicket:remove>
- if (tag.isIgnore() == false)
+ // Add text from last position to the current tag position
+ CharSequence text = xmlParser.getInputFromPositionMarker(tag.getPos());
+ if (text.length() > 0)
{
- markup.addMarkupElement(tag);
+ text = handleRawText(text.toString());
+
+ // Make sure you add it at the correct location.
+ // IMarkupFilters might have added elements as well.
+ markup.addMarkupElement(size, new RawMarkup(text));
+ }
+
+ xmlParser.setPositionMarker();
+
+ if (add)
+ {
+ // Add to the markup unless the tag has been flagged as
+ // to be removed from the markup. (e.g. <wicket:remove>
+ if (tag.isIgnore() == false)
+ {
+ markup.addMarkupElement(tag);
+ }
+ }
+ else if (tag.isModified())
+ {
+ markup.addMarkupElement(new RawMarkup(tag.toCharSequence()));
+ }
+ else
+ {
+ xmlParser.setPositionMarker(tag.getPos());
}
}
- else if (tag.isModified())
- {
- markup.addMarkupElement(new RawMarkup(tag.toCharSequence()));
- }
- else
- {
- xmlParser.setPositionMarker(tag.getPos());
- }
- }
- // always remember the latest index (size)
- size = markup.size();
+ // always remember the latest index (size)
+ size = markup.size();
+ }
}
}
catch (final ParseException ex)
@@ -314,7 +324,12 @@ public abstract class AbstractMarkupPars
*/
protected void postProcess(final Markup markup)
{
- markupFilterChain.postProcess(markup);
+ IMarkupFilter filter = markupFilterChain;
+ while (filter != null)
+ {
+ filter.postProcess(markup);
+ filter = filter.getNextFilter();
+ }
}
/**
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/ComponentTag.java Mon Mar 21 21:54:40 2011
@@ -65,11 +65,8 @@ public class ComponentTag extends Markup
/** Render the tag as RawMarkup even if no Component can be found */
public final static int RENDER_RAW = 0x0020;
- /**
- * Assuming this is a open (or open-close) tag, 'closes' refers to the ComponentTag which closes
- * it.
- */
- private ComponentTag closes;
+ /** If close tag, than reference to the corresponding close tag */
+ private ComponentTag openTag;
/** The underlying xml tag */
protected final XmlTag xmlTag;
@@ -223,7 +220,7 @@ public class ComponentTag extends Markup
{
if (open instanceof ComponentTag)
{
- return (closes == open) || getXmlTag().closes(((ComponentTag)open).getXmlTag());
+ return (openTag == open) || getXmlTag().closes(((ComponentTag)open).getXmlTag());
}
return false;
@@ -317,7 +314,7 @@ public class ComponentTag extends Markup
*/
public final ComponentTag getOpenTag()
{
- return closes;
+ return openTag;
}
/**
@@ -604,7 +601,7 @@ public class ComponentTag extends Markup
*/
public final void setOpenTag(final ComponentTag tag)
{
- closes = tag;
+ openTag = tag;
getXmlTag().setOpenTag(tag.getXmlTag());
}
Added: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/HtmlSpecialTag.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/HtmlSpecialTag.java?rev=1083980&view=auto
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/HtmlSpecialTag.java (added)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/HtmlSpecialTag.java Mon Mar 21 21:54:40 2011
@@ -0,0 +1,237 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.markup.parser.IXmlPullParser.HttpTagType;
+import org.apache.wicket.markup.parser.XmlTag;
+import org.apache.wicket.markup.parser.XmlTag.TagType;
+import org.apache.wicket.request.Response;
+
+
+/**
+ *
+ * @author Juergen Donnerstag
+ */
+public class HtmlSpecialTag extends MarkupElement
+{
+ /** The underlying xml tag */
+ protected final XmlTag xmlTag;
+
+ /** Boolean flags. See above */
+ private int flags = 0;
+
+ private final HttpTagType httpTagType;
+
+ /**
+ * Construct.
+ *
+ * @param tag
+ * The underlying xml tag
+ * @param httpTagType
+ */
+ public HtmlSpecialTag(final XmlTag tag, final HttpTagType httpTagType)
+ {
+ xmlTag = tag.makeImmutable();
+ this.httpTagType = httpTagType;
+ }
+
+ /**
+ * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
+ *
+ * @param flag
+ * The flag to set
+ * @param set
+ * True to turn the flag on, false to turn it off
+ */
+ public final void setFlag(final int flag, final boolean set)
+ {
+ if (set)
+ {
+ flags |= flag;
+ }
+ else
+ {
+ flags &= ~flag;
+ }
+ }
+
+ /**
+ * THIS METHOD IS NOT PART OF THE WICKET PUBLIC API. DO NOT USE IT!
+ *
+ * @param flag
+ * The flag to test
+ * @return True if the flag is set
+ */
+ public final boolean getFlag(final int flag)
+ {
+ return (flags & flag) != 0;
+ }
+
+ /**
+ * Gets the length of the tag in characters.
+ *
+ * @return The tag's length
+ */
+ public final int getLength()
+ {
+ return xmlTag.getLength();
+ }
+
+ /**
+ * @see org.apache.wicket.markup.parser.XmlTag#getPos()
+ * @return Tag location (index in input string)
+ */
+ public final int getPos()
+ {
+ return xmlTag.getPos();
+ }
+
+ /**
+ * @return the tag type (OPEN, CLOSE or OPEN_CLOSE).
+ */
+ public final TagType getType()
+ {
+ return xmlTag.getType();
+ }
+
+ /**
+ * @see org.apache.wicket.markup.parser.XmlTag#isClose()
+ * @return True if this tag is a close tag
+ */
+ public final boolean isClose()
+ {
+ return xmlTag.isClose();
+ }
+
+ /**
+ * @see org.apache.wicket.markup.parser.XmlTag#isOpen()
+ * @return True if this tag is an open tag
+ */
+ public final boolean isOpen()
+ {
+ return xmlTag.isOpen();
+ }
+
+ /**
+ * @see org.apache.wicket.markup.parser.XmlTag#isOpenClose()
+ * @return True if this tag is an open and a close tag
+ */
+ public final boolean isOpenClose()
+ {
+ return xmlTag.isOpenClose();
+ }
+
+ /**
+ * Copies all internal properties from this tag to <code>dest</code>. This is basically cloning
+ * without instance creation.
+ *
+ * @param dest
+ * tag whose properties will be set
+ */
+ void copyPropertiesTo(final HtmlSpecialTag dest)
+ {
+ dest.flags = flags;
+ }
+
+ @Override
+ public CharSequence toCharSequence()
+ {
+ return xmlTag.toCharSequence();
+ }
+
+ /**
+ * Converts this object to a string representation.
+ *
+ * @return String version of this object
+ */
+ @Override
+ public final String toString()
+ {
+ return "" + httpTagType + ": '" + xmlTag.toString() + "'";
+ }
+
+ /**
+ * Write the tag to the response
+ *
+ * @param response
+ * The response to write to
+ * @param stripWicketAttributes
+ * if true, wicket:id are removed from output
+ * @param namespace
+ * Wicket's namespace to use
+ */
+ public final void writeOutput(final Response response, final boolean stripWicketAttributes,
+ final String namespace)
+ {
+ response.write(toString());
+ }
+
+ /**
+ * Converts this object to a string representation including useful information for debugging
+ *
+ * @return String version of this object
+ */
+ @Override
+ public final String toUserDebugString()
+ {
+ return xmlTag.toUserDebugString();
+ }
+
+ /**
+ * @return Returns the underlying xml tag.
+ */
+ public final XmlTag getXmlTag()
+ {
+ return xmlTag;
+ }
+
+ @Override
+ public boolean equalTo(final MarkupElement element)
+ {
+ if (element instanceof HtmlSpecialTag)
+ {
+ final HtmlSpecialTag that = (HtmlSpecialTag)element;
+ return getXmlTag().equalTo(that.getXmlTag());
+ }
+ return false;
+ }
+
+ /**
+ * For subclasses to override. Gets called just before a Component gets rendered. It is
+ * guaranteed that the markupStream is set on the Component and determineVisibility is not yet
+ * called.
+ *
+ * @param component
+ * The component that is about to be rendered
+ * @param markupStream
+ * The current amrkup stream
+ */
+ public void onBeforeRender(final Component component, final MarkupStream markupStream)
+ {
+ }
+
+ /**
+ * Gets httpTagType.
+ *
+ * @return httpTagType
+ */
+ public final HttpTagType getHttpTagType()
+ {
+ return httpTagType;
+ }
+}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupException.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupException.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupException.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupException.java Mon Mar 21 21:54:40 2011
@@ -98,6 +98,18 @@ public final class MarkupException exten
}
/**
+ * Construct.
+ *
+ * @param markup
+ * @param message
+ * @param cause
+ */
+ public MarkupException(final Markup markup, final String message, final Throwable cause)
+ {
+ this(new MarkupStream(markup).setCurrentIndex(markup.size() - 1), message, cause);
+ }
+
+ /**
* @return Returns the MarkupStream.
*/
public MarkupStream getMarkupStream()
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupParser.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupParser.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupParser.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupParser.java Mon Mar 21 21:54:40 2011
@@ -21,6 +21,7 @@ import java.util.ArrayList;
import org.apache.wicket.Page;
import org.apache.wicket.markup.parser.IMarkupFilter;
import org.apache.wicket.markup.parser.IXmlPullParser;
+import org.apache.wicket.markup.parser.filter.ConditionalCommentFilter;
import org.apache.wicket.markup.parser.filter.EnclosureHandler;
import org.apache.wicket.markup.parser.filter.HeadForceTagIdHandler;
import org.apache.wicket.markup.parser.filter.HtmlHandler;
@@ -182,6 +183,7 @@ public class MarkupParser extends Abstra
filters.add(new RelativePathPrefixHandler());
filters.add(new EnclosureHandler());
filters.add(new StyleAndScriptIdentifier(markup));
+ filters.add(new ConditionalCommentFilter());
return filters;
}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupStream.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupStream.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupStream.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/MarkupStream.java Mon Mar 21 21:54:40 2011
@@ -340,11 +340,13 @@ public class MarkupStream
/**
* @param currentIndex
* New current index in the stream
+ * @return this
*/
- public void setCurrentIndex(final int currentIndex)
+ public MarkupStream setCurrentIndex(final int currentIndex)
{
current = get(currentIndex);
this.currentIndex = currentIndex;
+ return this;
}
/**
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/AbstractMarkupFilter.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/AbstractMarkupFilter.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/AbstractMarkupFilter.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/AbstractMarkupFilter.java Mon Mar 21 21:54:40 2011
@@ -19,8 +19,11 @@ package org.apache.wicket.markup.parser;
import java.text.ParseException;
import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.HtmlSpecialTag;
import org.apache.wicket.markup.Markup;
import org.apache.wicket.markup.MarkupElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
@@ -31,6 +34,9 @@ import org.apache.wicket.markup.MarkupEl
*/
public abstract class AbstractMarkupFilter implements IMarkupFilter
{
+ /** Log. */
+ private static final Logger log = LoggerFactory.getLogger(AbstractMarkupFilter.class);
+
/** The next MarkupFilter in the chain */
private IMarkupFilter parent;
@@ -70,9 +76,16 @@ public abstract class AbstractMarkupFilt
public MarkupElement nextElement() throws ParseException
{
MarkupElement elem = getNextFilter().nextElement();
- if ((elem != null) && (elem instanceof ComponentTag))
+ if (elem != null)
{
- elem = onComponentTag((ComponentTag)elem);
+ if (elem instanceof ComponentTag)
+ {
+ elem = onComponentTag((ComponentTag)elem);
+ }
+ else if (elem instanceof HtmlSpecialTag)
+ {
+ elem = onSpecialTag((HtmlSpecialTag)elem);
+ }
}
return elem;
}
@@ -109,11 +122,11 @@ public abstract class AbstractMarkupFilt
* @return Usually the same as the tag attribute
* @throws ParseException
*/
-// Not yet used
-// protected MarkupElement onSpecialTag(final ComponentTag tag) throws ParseException
-// {
-// return tag;
-// }
+ protected MarkupElement onSpecialTag(final HtmlSpecialTag tag) throws ParseException
+ {
+ log.error(tag.toString());
+ return tag;
+ }
/**
* Invoked if current element is raw markup
@@ -136,9 +149,6 @@ public abstract class AbstractMarkupFilt
return count++;
}
- /**
- * Noop by default
- */
public void postProcess(final Markup markup)
{
}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/IXmlPullParser.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/IXmlPullParser.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/IXmlPullParser.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/IXmlPullParser.java Mon Mar 21 21:54:40 2011
@@ -32,7 +32,7 @@ import org.apache.wicket.util.resource.R
public interface IXmlPullParser
{
/** The last element found */
- public enum ELEMENT_TYPE {
+ public enum HttpTagType {
/** next() must be called at least once for the Type to be valid */
NOT_INITIALIZED,
@@ -48,6 +48,9 @@ public interface IXmlPullParser
/** <!--[if ] ... --> */
CONDITIONAL_COMMENT,
+ /** <![endif]--> */
+ CONDITIONAL_COMMENT_ENDIF,
+
/** <![CDATA[ .. ]]> */
CDATA,
@@ -155,7 +158,7 @@ public interface IXmlPullParser
* @return o, if end of file. Else a TAG, COMMENT etc.
* @throws ParseException
*/
- ELEMENT_TYPE next() throws ParseException;
+ HttpTagType next() throws ParseException;
/**
*
Added: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/TagStack.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/TagStack.java?rev=1083980&view=auto
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/TagStack.java (added)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/TagStack.java Mon Mar 21 21:54:40 2011
@@ -0,0 +1,231 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.parser;
+
+import java.text.ParseException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.WicketParseException;
+import org.apache.wicket.markup.parser.filter.HtmlHandler;
+import org.apache.wicket.util.collections.ArrayListStack;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Stack to push and pop HTML elements asserting its structure.
+ */
+public class TagStack
+{
+ private static final Logger log = LoggerFactory.getLogger(HtmlHandler.class);
+
+ /** Map of simple tags. */
+ private static final Map<String, Boolean> doesNotRequireCloseTag = new HashMap<String, Boolean>();
+
+ static
+ {
+ // Tags which are allowed not be closed in HTML
+ doesNotRequireCloseTag.put("p", Boolean.TRUE);
+ doesNotRequireCloseTag.put("br", Boolean.TRUE);
+ doesNotRequireCloseTag.put("img", Boolean.TRUE);
+ doesNotRequireCloseTag.put("input", Boolean.TRUE);
+ doesNotRequireCloseTag.put("hr", Boolean.TRUE);
+ doesNotRequireCloseTag.put("link", Boolean.TRUE);
+ doesNotRequireCloseTag.put("meta", Boolean.TRUE);
+ }
+
+ /** Tag stack to find balancing tags */
+ final private ArrayListStack<ComponentTag> stack = new ArrayListStack<ComponentTag>();
+ private boolean debug;
+
+ /**
+ * Assert that tag has no mismatch error. If the parameter is an open tag, just push it on stack
+ * to be tested latter.
+ *
+ * @param tag
+ * @throws ParseException
+ */
+ public void assertValidInStack(ComponentTag tag) throws ParseException
+ {
+ // Get the next tag. If null, no more tags are available
+ if (tag == null)
+ {
+ validate();
+ return;
+ }
+
+ if (log.isDebugEnabled() && debug)
+ {
+ log.debug("tag: " + tag.toUserDebugString() + ", stack: " + stack);
+ }
+
+ // Check tag type
+ if (tag.isOpen())
+ {
+ // Push onto stack
+ stack.push(tag);
+ }
+ else if (tag.isClose())
+ {
+ assertOpenTagFor(tag);
+ }
+ else if (tag.isOpenClose())
+ {
+ // Tag closes itself
+ tag.setOpenTag(tag);
+ }
+ }
+
+ /**
+ * Bind close tag with its open tag and pop it from the stack.
+ *
+ * @param closeTag
+ * @throws ParseException
+ */
+ private void assertOpenTagFor(ComponentTag closeTag) throws ParseException
+ {
+ // Check that there is something on the stack
+ if (stack.size() > 0)
+ {
+ // Pop the top tag off the stack
+ ComponentTag top = stack.pop();
+
+ // If the name of the current close tag does not match the
+ // tag on the stack then we may have a mismatched close tag
+ boolean mismatch = !hasEqualTagName(top, closeTag);
+
+ if (mismatch)
+ {
+ top.setHasNoCloseTag(true);
+
+ // Pop any simple tags off the top of the stack
+ while (mismatch && !requiresCloseTag(top.getName()))
+ {
+ top.setHasNoCloseTag(true);
+
+ // Pop simple tag
+ if (stack.isEmpty())
+ {
+ break;
+ }
+ top = stack.pop();
+
+ // Does new top of stack mismatch too?
+ mismatch = !hasEqualTagName(top, closeTag);
+ }
+
+ // If adjusting for simple tags did not fix the problem,
+ // it must be a real mismatch.
+ if (mismatch)
+ {
+ throw new ParseException("Tag " + top.toUserDebugString() +
+ " has a mismatched close tag at " + closeTag.toUserDebugString(),
+ top.getPos());
+ }
+ }
+
+ // Tag matches, so add pointer to matching tag
+ closeTag.setOpenTag(top);
+ }
+ else
+ {
+ throw new WicketParseException("Tag does not have a matching open tag:", closeTag);
+ }
+ }
+
+ private void validate() throws WicketParseException
+ {
+ ComponentTag top = getNotClosedTag();
+ if (top != null)
+ {
+ throw new WicketParseException("Tag does not have a close tag:", top);
+ }
+ }
+
+ /**
+ * @return not closed tag
+ */
+ public ComponentTag getNotClosedTag()
+ {
+ // No more tags from the markup.
+ // If there's still a non-simple tag left, it's an error
+ if (stack.size() > 0)
+ {
+ for (int i = 0; i < stack.size(); i++)
+ {
+ ComponentTag tag = stack.get(i);
+ if (!requiresCloseTag(tag.getName()))
+ {
+ stack.pop();
+ }
+ else
+ {
+ return tag;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Configure this stack to call log.debug at operations
+ */
+ public void debug()
+ {
+ debug = true;
+ }
+
+ /**
+ * Gets whether this tag does not require a closing tag.
+ *
+ * @param name
+ * The tag's name, e.g. a, br, div, etc.
+ * @return True if this tag does not require a closing tag
+ */
+ public static boolean requiresCloseTag(final String name)
+ {
+ return doesNotRequireCloseTag.get(name.toLowerCase()) == null;
+ }
+
+ /**
+ * Compare tag name including namespace
+ *
+ * @param tag1
+ * @param tag2
+ * @return true if name and namespace are equal
+ */
+ public static boolean hasEqualTagName(final ComponentTag tag1, final ComponentTag tag2)
+ {
+ if (!tag1.getName().equalsIgnoreCase(tag2.getName()))
+ {
+ return false;
+ }
+
+ if ((tag1.getNamespace() == null) && (tag2.getNamespace() == null))
+ {
+ return true;
+ }
+
+ if ((tag1.getNamespace() != null) && (tag2.getNamespace() != null))
+ {
+ return tag1.getNamespace().equalsIgnoreCase(tag2.getNamespace());
+ }
+
+ return false;
+ }
+}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlPullParser.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlPullParser.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlPullParser.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlPullParser.java Mon Mar 21 21:54:40 2011
@@ -68,9 +68,9 @@ public final class XmlPullParser impleme
private CharSequence doctype;
/** The type of what is in lastText */
- private ELEMENT_TYPE lastType = ELEMENT_TYPE.NOT_INITIALIZED;
+ private HttpTagType lastType = HttpTagType.NOT_INITIALIZED;
- /** If lastType == TAG, than ... */
+ /** The last tag found */
private XmlTag lastTag;
/**
@@ -136,7 +136,7 @@ public final class XmlPullParser impleme
input.setPosition(pos);
lastText = input.getSubstring(startIndex, pos);
- lastType = ELEMENT_TYPE.BODY;
+ lastType = HttpTagType.BODY;
// Check that the tag is properly closed
lastPos = input.find('>', lastPos + tagNameLen);
@@ -163,12 +163,12 @@ public final class XmlPullParser impleme
* @return XXX
* @throws ParseException
*/
- public final ELEMENT_TYPE next() throws ParseException
+ public final HttpTagType next() throws ParseException
{
// Reached end of markup file?
if (input.getPosition() >= input.size())
{
- return ELEMENT_TYPE.NOT_INITIALIZED;
+ return HttpTagType.NOT_INITIALIZED;
}
if (skipUntilText != null)
@@ -183,18 +183,19 @@ public final class XmlPullParser impleme
// Tag or Body?
if (input.charAt(input.getPosition()) != '<')
{
+ // It's a BODY
if (openBracketIndex == -1)
{
// There is no next matching tag.
lastText = input.getSubstring(-1);
input.setPosition(input.size());
- lastType = ELEMENT_TYPE.BODY;
+ lastType = HttpTagType.BODY;
return lastType;
}
lastText = input.getSubstring(openBracketIndex);
input.setPosition(openBracketIndex);
- lastType = ELEMENT_TYPE.BODY;
+ lastType = HttpTagType.BODY;
return lastType;
}
@@ -220,14 +221,6 @@ public final class XmlPullParser impleme
input.getPosition());
}
- // Handle special tags like <!-- and <![CDATA ...
- final char firstChar = tagText.charAt(0);
- if ((firstChar == '!') || (firstChar == '?'))
- {
- specialTagHandling(tagText, openBracketIndex, closeBracketIndex);
- return lastType;
- }
-
// Type of the tag, to be determined next
final TagType type;
@@ -266,19 +259,31 @@ public final class XmlPullParser impleme
}
}
- // Parse remaining tag text, obtaining a tag object or null
- // if it's invalid
- lastTag = parseTagText(tagText);
- if (lastTag != null)
- {
- // Populate tag fields
- lastTag.type = type;
- lastTag.text = new TextSegment(lastText, openBracketIndex, input.getLineNumber(),
+ // Handle special tags like <!-- and <![CDATA ...
+ final char firstChar = tagText.charAt(0);
+ if ((firstChar == '!') || (firstChar == '?'))
+ {
+ specialTagHandling(tagText, openBracketIndex, closeBracketIndex);
+
+ input.countLinesTo(openBracketIndex);
+ TextSegment text = new TextSegment(lastText, openBracketIndex, input.getLineNumber(),
input.getColumnNumber());
+ lastTag = new XmlTag(text, type);
+
+ return lastType;
+ }
+ TextSegment text = new TextSegment(lastText, openBracketIndex, input.getLineNumber(),
+ input.getColumnNumber());
+ XmlTag tag = new XmlTag(text, type);
+ lastTag = tag;
+
+ // Parse the tag text and populate tag attributes
+ if (parseTagText(tag, tagText))
+ {
// Move to position after the tag
input.setPosition(closeBracketIndex + 1);
- lastType = ELEMENT_TYPE.TAG;
+ lastType = HttpTagType.TAG;
return lastType;
}
else
@@ -301,43 +306,62 @@ public final class XmlPullParser impleme
// Handle comments
if (tagText.startsWith("!--"))
{
- // Normal comment section.
- // Skip ahead to "-->". Note that you can not simply test for
- // tagText.endsWith("--") as the comment might contain a '>'
- // inside.
- int pos = input.find("-->", openBracketIndex + 1);
- if (pos == -1)
- {
- throw new ParseException("Unclosed comment beginning at" + getLineAndColumnText(),
- openBracketIndex);
- }
-
- pos += 3;
- lastText = input.getSubstring(openBracketIndex, pos);
- lastType = ELEMENT_TYPE.COMMENT;
-
- // Conditional comment? E.g. "<!--[if IE]><a href='test.html'>my link</a><![endif]-->"
- if (tagText.startsWith("!--[if ") && tagText.endsWith("]") &&
- lastText.toString().endsWith("<![endif]-->"))
+ // downlevel-revealed conditional comments e.g.: <!--[if (gt IE9)|!(IE)]><!-->
+ if (tagText.contains("![endif]--"))
{
- lastType = ELEMENT_TYPE.CONDITIONAL_COMMENT;
+ lastType = HttpTagType.CONDITIONAL_COMMENT_ENDIF;
+
+ // Move to position after the tag
+ input.setPosition(closeBracketIndex + 1);
+ return;
+ }
+
+ // Conditional comment? E.g.
+ // "<!--[if IE]><a href='test.html'>my link</a><![endif]-->"
+ if (tagText.startsWith("!--[if ") && tagText.endsWith("]"))
+ {
+ int pos = input.find("]-->", openBracketIndex + 1);
+ if (pos == -1)
+ {
+ throw new ParseException("Unclosed conditional comment beginning at" +
+ getLineAndColumnText(), openBracketIndex);
+ }
+
+ pos += 4;
+ lastText = input.getSubstring(openBracketIndex, pos);
// Actually it is no longer a comment. It is now
// up to the browser to select the section appropriate.
input.setPosition(closeBracketIndex + 1);
+ lastType = HttpTagType.CONDITIONAL_COMMENT;
}
else
{
+ // Normal comment section.
+ // Skip ahead to "-->". Note that you can not simply test for
+ // tagText.endsWith("--") as the comment might contain a '>'
+ // inside.
+ int pos = input.find("-->", openBracketIndex + 1);
+ if (pos == -1)
+ {
+ throw new ParseException("Unclosed comment beginning at" +
+ getLineAndColumnText(), openBracketIndex);
+ }
+
+ pos += 3;
+ lastText = input.getSubstring(openBracketIndex, pos);
+ lastType = HttpTagType.COMMENT;
input.setPosition(pos);
}
return;
}
// The closing tag of a conditional comment, e.g.
- // "<!--[if IE]><a href='test.html'>my link</a><![endif]-->"
+ // "<!--[if IE]><a href='test.html'>my link</a><![endif]-->
+ // and also <!--<![endif]-->"
if (tagText.equals("![endif]--"))
{
- lastType = ELEMENT_TYPE.CONDITIONAL_COMMENT;
+ lastType = HttpTagType.CONDITIONAL_COMMENT;
input.setPosition(closeBracketIndex + 1);
return;
}
@@ -373,14 +397,14 @@ public final class XmlPullParser impleme
input.setPosition(closeBracketIndex + 1);
lastText = tagText;
- lastType = ELEMENT_TYPE.CDATA;
+ lastType = HttpTagType.CDATA;
return;
}
}
if (tagText.charAt(0) == '?')
{
- lastType = ELEMENT_TYPE.PROCESSING_INSTRUCTION;
+ lastType = HttpTagType.PROCESSING_INSTRUCTION;
// Move to position after the tag
input.setPosition(closeBracketIndex + 1);
@@ -389,7 +413,7 @@ public final class XmlPullParser impleme
if (tagText.startsWith("!DOCTYPE"))
{
- lastType = ELEMENT_TYPE.DOCTYPE;
+ lastType = HttpTagType.DOCTYPE;
// Get the tagtext between open and close brackets
doctype = input.getSubstring(openBracketIndex + 1, closeBracketIndex);
@@ -400,7 +424,7 @@ public final class XmlPullParser impleme
}
// Move to position after the tag
- lastType = ELEMENT_TYPE.SPECIAL_TAG;
+ lastType = HttpTagType.SPECIAL_TAG;
input.setPosition(closeBracketIndex + 1);
}
@@ -426,7 +450,7 @@ public final class XmlPullParser impleme
*/
public final XmlTag nextTag() throws ParseException
{
- while (next() != ELEMENT_TYPE.NOT_INITIALIZED)
+ while (next() != HttpTagType.NOT_INITIALIZED)
{
switch (lastType)
{
@@ -576,12 +600,13 @@ public final class XmlPullParser impleme
/**
* Parses the text between tags. For example, "a href=foo.html".
*
+ * @param tag
* @param tagText
* The text between tags
- * @return A new Tag object or null if the tag is invalid
+ * @return false in case of an error
* @throws ParseException
*/
- private XmlTag parseTagText(final String tagText) throws ParseException
+ private boolean parseTagText(final XmlTag tag, final String tagText) throws ParseException
{
// Get the length of the tagtext
final int tagTextLength = tagText.length();
@@ -590,8 +615,6 @@ public final class XmlPullParser impleme
final TagNameParser tagnameParser = new TagNameParser(tagText);
if (tagnameParser.matcher().lookingAt())
{
- final XmlTag tag = new XmlTag();
-
// Extract the tag from the pattern matcher
tag.name = tagnameParser.getName();
tag.namespace = tagnameParser.getNamespace();
@@ -601,7 +624,7 @@ public final class XmlPullParser impleme
int pos = tagnameParser.matcher().end(0);
if (pos == tagTextLength)
{
- return tag;
+ return true;
}
// Extract attributes
@@ -643,13 +666,13 @@ public final class XmlPullParser impleme
// attributes)
if (pos == tagTextLength)
{
- return tag;
+ return true;
}
}
- return tag;
+ return true;
}
- return null;
+ return false;
}
}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlTag.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlTag.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlTag.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/XmlTag.java Mon Mar 21 21:54:40 2011
@@ -19,6 +19,7 @@ package org.apache.wicket.markup.parser;
import java.util.Iterator;
import java.util.Map;
+import org.apache.wicket.markup.parser.IXmlPullParser.HttpTagType;
import org.apache.wicket.util.lang.Objects;
import org.apache.wicket.util.string.AppendingStringBuffer;
import org.apache.wicket.util.string.StringValue;
@@ -84,6 +85,8 @@ public class XmlTag
/** True if this tag is mutable, false otherwise. */
private boolean isMutable = true;
+ private HttpTagType httpTagType;
+
/**
* Construct.
*/
@@ -93,6 +96,18 @@ public class XmlTag
}
/**
+ * Construct.
+ *
+ * @param text
+ * @param type
+ */
+ public XmlTag(final TextSegment text, final TagType type)
+ {
+ this.text = text;
+ this.type = type;
+ }
+
+ /**
* Gets whether this tag closes the provided open tag.
*
* @param open
@@ -285,8 +300,10 @@ public class XmlTag
/**
* Makes this tag object immutable by making the attribute map unmodifiable. Immutable tags
* cannot be made mutable again. They can only be copied into new mutable tag objects.
+ *
+ * @return this
*/
- public void makeImmutable()
+ public XmlTag makeImmutable()
{
if (isMutable)
{
@@ -297,6 +314,7 @@ public class XmlTag
text = null;
}
}
+ return this;
}
/**
@@ -618,12 +636,30 @@ public class XmlTag
/** Full text of tag. */
final CharSequence text;
- TextSegment(CharSequence text, int pos, int line, int col)
+ TextSegment(final CharSequence text, final int pos, final int line, final int col)
{
this.text = text;
this.pos = pos;
lineNumber = line;
columnNumber = col;
}
+
+ /**
+ *
+ * @return The xml markup text
+ */
+ public final CharSequence getText()
+ {
+ return text;
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString()
+ {
+ return text.toString();
+ }
}
}
Added: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/ConditionalCommentFilter.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/ConditionalCommentFilter.java?rev=1083980&view=auto
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/ConditionalCommentFilter.java (added)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/ConditionalCommentFilter.java Mon Mar 21 21:54:40 2011
@@ -0,0 +1,264 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.markup.parser.filter;
+
+import java.text.ParseException;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Queue;
+import java.util.Set;
+
+import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.HtmlSpecialTag;
+import org.apache.wicket.markup.Markup;
+import org.apache.wicket.markup.MarkupElement;
+import org.apache.wicket.markup.parser.AbstractMarkupFilter;
+import org.apache.wicket.markup.parser.IXmlPullParser.HttpTagType;
+import org.apache.wicket.util.lang.Generics;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Skip duplicated mismatched markup inside conditional comments
+ *
+ * @author Pedro Santos
+ * @author Juergen Donnerstag
+ */
+public class ConditionalCommentFilter extends AbstractMarkupFilter
+{
+ private static final Logger log = LoggerFactory.getLogger(ConditionalCommentFilter.class);
+
+ private Queue<ComponentTag> queue = new LinkedList<ComponentTag>();
+ private Map<Integer, Set<String>> skipByLevelMap = Generics.newHashMap();
+ private int level;
+
+ @Override
+ protected MarkupElement onSpecialTag(final HtmlSpecialTag tag) throws ParseException
+ {
+ if (tag.getHttpTagType() == HttpTagType.CONDITIONAL_COMMENT)
+ {
+
+ }
+ return tag;
+ }
+
+// public MarkupElement nextTag() throws ParseException
+// {
+// MarkupElement next = null;
+// if (queue.size() > 0)
+// {
+// next = queue.poll();
+// }
+// else
+// {
+// next = getNextFilter().nextTag();
+// }
+// if (next == null)
+// {
+// return null;
+// }
+// else if (next instanceof ConditionalComment)
+// {
+// ConditionalComment conditionalComment = (ConditionalComment)next;
+// if (conditionalComment.isStartIf())
+// {
+// ConditionalTags conditionalTags = new ConditionalTags();
+// conditionalTags.iterate(getNextFilter());
+// ComponentTag mismatch = conditionalTags.getMismatch();
+// if (mismatch != null)
+// {
+//
+// if (mismatch.isOpen())
+// {
+// // start skipping it at this level
+// log.debug("Start to skip: " + mismatch.getName());
+// startSkip(mismatch.getName());
+// }
+// else
+// {
+// if (shouldSkip(mismatch.getName()))
+// {
+// log.debug("Skipping: " + mismatch.getName());
+// // just skipping the close tag
+// }
+// else
+// {
+// throw new ParseException("Not opened tag: " + mismatch,
+// conditionalTags.mismatchTag.getPos());
+// }
+// }
+// }
+// queue.addAll(conditionalTags.getValidTags());
+// // start the recursion
+// return nextTag();
+// }
+// else
+// {
+// // ConditionalTags should have iterated over the close tag already
+// throw new ParseException("Not opened conditional comment close tag",
+// conditionalComment.getPos());
+// }
+// }
+// else
+// {
+// ComponentTag componentTag = (ComponentTag)next;
+// if (componentTag.isOpen())
+// {
+// level++;
+// }
+// else if (componentTag.isClose())
+// {
+// if (shouldSkip(componentTag.getName()))
+// {
+// log.debug("Skipping close tag outside conditional comment: " +
+// componentTag.getName());
+// // tag outside conditional comment are skipped once
+// stopSkipping(componentTag.getName());
+// // skipping
+// return nextTag();
+// }
+// level--;
+// }
+// return next;
+// }
+// }
+//
+// private void startSkip(String tagName)
+// {
+// Set<String> toSkipSet = skipByLevelMap.get(level);
+// if (toSkipSet == null)
+// {
+// skipByLevelMap.put(level, toSkipSet = new HashSet<String>());
+//
+// }
+// toSkipSet.add(tagName);
+// }
+//
+// private void stopSkipping(String tagName)
+// {
+// skipByLevelMap.get(level).remove(tagName);
+// }
+//
+// private boolean shouldSkip(String tagName)
+// {
+// Set<String> skipList = skipByLevelMap.get(level);
+// return skipList != null && skipList.contains(tagName);
+// }
+//
+// /**
+// * Track the markup inside an conditional tag
+// *
+// * @author Pedro Santos
+// */
+// private static class ConditionalTags
+// {
+// private TagStack tagStack = new TagStack();
+// private ArrayList<ComponentTag> tagSequence = new ArrayList<ComponentTag>();
+// private ComponentTag mismatchTag;
+//
+// public void iterate(IMarkupFilter nextFilter) throws ParseException
+// {
+// MarkupElement markupElement = null;
+// do
+// {
+// markupElement = nextFilter.nextTag();
+// if (markupElement instanceof ConditionalComment)
+// {
+// ConditionalComment conditionalComment = (ConditionalComment)markupElement;
+// if (conditionalComment.isStartIf())
+// {
+// throw new ParseException("nested conditional comments are not suported",
+// conditionalComment.getPos());
+// }
+// }
+// else
+// {
+// ComponentTag componentTag = (ComponentTag)markupElement;
+// try
+// {
+// tagStack.assertValidInStack(componentTag);
+// tagSequence.add(componentTag);
+// }
+// catch (ParseException e)
+// {
+// mismatchTag = componentTag;
+// }
+// }
+// }
+// while (markupElement != null && !(markupElement instanceof ConditionalComment));
+// }
+//
+// private List<ComponentTag> getValidTags()
+// {
+// ComponentTag notClosed = tagStack.getNotClosedTag();
+// @SuppressWarnings("unchecked")
+// List<ComponentTag> validTags = (List<ComponentTag>)tagSequence.clone();
+// if (notClosed != null)
+// {
+// validTags.remove(notClosed);
+// }
+// return validTags;
+// }
+//
+// private boolean hasMismatch()
+// {
+// return mismatchTag != null || tagStack.getNotClosedTag() != null;
+// }
+//
+// private ComponentTag getMismatch()
+// {
+// return mismatchTag != null ? mismatchTag : tagStack.getNotClosedTag();
+// }
+//
+// private boolean equalsTo(ConditionalTags other)
+// {
+// if (tagSequence.size() != other.tagSequence.size())
+// {
+// return false;
+// }
+// else
+// {
+// for (int i = 0; i < tagSequence.size(); i++)
+// {
+// if (!tagSequence.get(i).getName().equals(other.tagSequence.get(i).getName()) ||
+// !tagSequence.get(i).getType().equals(other.tagSequence.get(i).getType()))
+// {
+// return false;
+// }
+// }
+// }
+// return true;
+// }
+// }
+
+ /**
+ * Post-process the markup if necessary
+ */
+ @Override
+ public void postProcess(final Markup markup)
+ {
+ }
+
+ /**
+ * Noop
+ */
+ @Override
+ protected MarkupElement onComponentTag(final ComponentTag tag) throws ParseException
+ {
+ return tag;
+ }
+}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHandler.java Mon Mar 21 21:54:40 2011
@@ -20,10 +20,10 @@ import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
-import org.apache.wicket.WicketRuntimeException;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.Markup;
import org.apache.wicket.markup.MarkupElement;
+import org.apache.wicket.markup.MarkupException;
import org.apache.wicket.markup.WicketParseException;
import org.apache.wicket.markup.parser.AbstractMarkupFilter;
import org.apache.wicket.util.collections.ArrayListStack;
@@ -81,8 +81,7 @@ public final class HtmlHandler extends A
}
else
{
- throw new WicketRuntimeException(new WicketParseException(
- "Tag does not have a close tag:", top));
+ throw new MarkupException(markup, "Tag does not have a close tag", null);
}
}
}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java Mon Mar 21 21:54:40 2011
@@ -22,7 +22,6 @@ import java.util.List;
import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.MarkupElement;
-import org.apache.wicket.markup.RawMarkup;
import org.apache.wicket.markup.parser.AbstractMarkupFilter;
import org.apache.wicket.markup.parser.XmlTag.TagType;
@@ -47,6 +46,7 @@ public class OpenCloseTagExpander extend
// compatible
, "span", "p", "strong", "b", "e", "select", "col");
+ // temporary storage. Introduce into flow on next request
private ComponentTag next = null;
@Override
@@ -60,19 +60,15 @@ public class OpenCloseTagExpander extend
return rtn;
}
- // Find the next tag
- MarkupElement elem;
- do
- {
- elem = getNextFilter().nextElement();
- if (elem == null)
- {
- return null;
- }
- }
- while (elem instanceof RawMarkup);
+ return super.nextElement();
+ }
- ComponentTag tag = (ComponentTag)elem;
+ /**
+ *
+ */
+ @Override
+ protected MarkupElement onComponentTag(final ComponentTag tag) throws ParseException
+ {
if (tag.isOpenClose())
{
String name = tag.getName();
@@ -92,6 +88,7 @@ public class OpenCloseTagExpander extend
}
}
}
+
return tag;
}
@@ -120,13 +117,4 @@ public class OpenCloseTagExpander extend
{
return replaceForTags.contains(name.toLowerCase());
}
-
- /**
- * Noop
- */
- @Override
- protected MarkupElement onComponentTag(ComponentTag tag) throws ParseException
- {
- return tag;
- }
}
Modified: wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RootMarkupFilter.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RootMarkupFilter.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RootMarkupFilter.java (original)
+++ wicket/trunk/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/RootMarkupFilter.java Mon Mar 21 21:54:40 2011
@@ -19,11 +19,13 @@ package org.apache.wicket.markup.parser.
import java.text.ParseException;
import org.apache.wicket.markup.ComponentTag;
+import org.apache.wicket.markup.HtmlSpecialTag;
+import org.apache.wicket.markup.Markup;
import org.apache.wicket.markup.MarkupElement;
import org.apache.wicket.markup.parser.AbstractMarkupFilter;
import org.apache.wicket.markup.parser.IMarkupFilter;
import org.apache.wicket.markup.parser.IXmlPullParser;
-import org.apache.wicket.markup.parser.IXmlPullParser.ELEMENT_TYPE;
+import org.apache.wicket.markup.parser.IXmlPullParser.HttpTagType;
/**
@@ -52,16 +54,24 @@ public final class RootMarkupFilter exte
@Override
public final MarkupElement nextElement() throws ParseException
{
- ELEMENT_TYPE type;
- while ((type = parser.next()) != ELEMENT_TYPE.TAG)
+ HttpTagType type;
+ while ((type = parser.next()) != HttpTagType.NOT_INITIALIZED)
{
- if (type == ELEMENT_TYPE.NOT_INITIALIZED)
+ if (type == HttpTagType.BODY)
{
- return null;
+ continue;
+ }
+ else if (type == HttpTagType.TAG)
+ {
+ return new ComponentTag(parser.getElement());
+ }
+ else
+ {
+ return new HtmlSpecialTag(parser.getElement(), type);
}
}
- return new ComponentTag(parser.getElement());
+ return null;
}
/**
@@ -90,4 +100,21 @@ public final class RootMarkupFilter exte
{
return tag;
}
+
+ /**
+ * Noop
+ */
+ @Override
+ public final void postProcess(Markup markup)
+ {
+ }
+
+ /**
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString()
+ {
+ return parser.toString();
+ }
}
Modified: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ajax/MockComponent1-expected.html
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ajax/MockComponent1-expected.html?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ajax/MockComponent1-expected.html (original)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/ajax/MockComponent1-expected.html Mon Mar 21 21:54:40 2011
@@ -1,9 +1,11 @@
<![CDATA[<head xmlns:wicket="http://wicket.apache.org">
-<style type="text/css" id="org-apache-wicket-ajax-MockComponent1-0"><![CDATA[
+<style type="text/css" id="org-apache-wicket-ajax-MockComponent1-0"><!--/*--><![CDATA[/*><!--*/
+
.onTheFlyClass {
background-color: red;
color: white;
width: 200px;
}
-]^]^></style>
+
+/*-->]^]^>*/</style>
</head>]]>
\ No newline at end of file
Modified: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/MarkupParserTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/MarkupParserTest.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/MarkupParserTest.java (original)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/MarkupParserTest.java Mon Mar 21 21:54:40 2011
@@ -23,6 +23,7 @@ import java.util.Locale;
import junit.framework.Assert;
import org.apache.wicket.WicketTestCase;
+import org.apache.wicket.markup.html.border.Border;
import org.apache.wicket.markup.html.pages.PageExpiredErrorPage;
import org.apache.wicket.markup.parser.XmlTag.TagType;
import org.apache.wicket.markup.parser.filter.WicketTagIdentifier;
@@ -388,7 +389,8 @@ public final class MarkupParserTest exte
assertEquals(5, markup.size());
assertEquals("html", ((ComponentTag)markup.get(0)).getName());
assertEquals("html", ((ComponentTag)markup.get(4)).getName());
- assertEquals("<![CDATA[... <x a> ...]]>", markup.get(2).toString());
+ assertEquals("<!--/*--><![CDATA[/*><!--*/\n... <x a> ...\n/*-->]]>*/", markup.get(2)
+ .toString());
}
/**
@@ -454,7 +456,7 @@ public final class MarkupParserTest exte
tag = markup.get(0);
assertEquals("<script>", tag.toString());
tag = markup.get(1);
- assertEquals("<![CDATA[ text ]]>", tag.toString());
+ assertEquals("<!--/*--><![CDATA[/*><!--*/\n text \n/*-->]]>*/", tag.toString());
tag = markup.get(2);
assertEquals("</script>", tag.toString());
@@ -490,7 +492,7 @@ public final class MarkupParserTest exte
tag = markup.get(1);
assertEquals("<script>", tag.toString());
tag = markup.get(2);
- assertEquals("<![CDATA[ text ]]>", tag.toString());
+ assertEquals("<!--/*--><![CDATA[/*><!--*/\n text \n/*-->]]>*/", tag.toString());
tag = markup.get(3);
assertEquals("</script>", tag.toString());
@@ -499,8 +501,74 @@ public final class MarkupParserTest exte
tag = markup.get(1);
assertEquals("<script>", tag.toString());
tag = markup.get(2);
- assertEquals("<![CDATA[ text ]]>", tag.toString());
+ assertEquals("<!--/*--><![CDATA[/*><!--*/\n text \n/*-->]]>*/", tag.toString());
tag = markup.get(3);
assertEquals("</script>", tag.toString());
}
+
+
+ /**
+ * @throws IOException
+ * @throws ResourceStreamNotFoundException
+ * @throws ParseException
+ */
+ public void testParseConditionalComment() throws IOException, ResourceStreamNotFoundException,
+ ParseException
+ {
+ String x = " <!--[if IE]>\r\n" + //
+ " <a href=\"SimplePage_3.html\">Link</a>\r\n" + //
+ " <![endif]-->";
+ MarkupParser parser = new MarkupParser(x);
+ Markup markup = parser.parse();
+ assertEquals(x, markup.toString(true));
+ }
+
+ /**
+ * @throws IOException
+ * @throws ResourceStreamNotFoundException
+ */
+ public void testParseTagToBeExpanded() throws IOException, ResourceStreamNotFoundException
+ {
+ String x = "<html xmlns:wicket>\r\n<body>\r\n <span wicket:id=\"myPanel\"/>\r\n</body>\r\n</html>\r\n";
+ MarkupParser parser = new MarkupParser(x);
+ Markup markup = parser.parse();
+ assertEquals(
+ "<html xmlns:wicket>\r\n<body>\r\n <span wicket:id=\"myPanel\"></span>\r\n</body>\r\n</html>\r\n",
+ markup.toString(true));
+ }
+
+ /**
+ * @throws IOException
+ * @throws ResourceStreamNotFoundException
+ */
+ public void testParseBorderSintax() throws IOException, ResourceStreamNotFoundException
+ {
+ tester.getApplication().getPageSettings().addComponentResolver(new Border("test_resolver")
+ {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ });
+ String x = "<wicket:border>before body - <wicket:body/> - after body</wicket:border>";
+ MarkupParser parser = new MarkupParser(x);
+ Markup markup = parser.parse();
+ assertEquals(x, markup.toString(true));
+ }
+
+ /**
+ * WICKET-3500
+ *
+ * @throws IOException
+ * @throws ResourceStreamNotFoundException
+ */
+ public void testRawMakupParsingWithStripCommentsSetTrue() throws IOException,
+ ResourceStreamNotFoundException
+ {
+ tester.getApplication().getMarkupSettings().setStripComments(true);
+ String conditionalComment = "\r\n <!--[if IE 6]>\r\n<![endif]-->";
+ MarkupParser parser = new MarkupParser(conditionalComment);
+ Markup markup = parser.parse();
+ assertEquals(conditionalComment, markup.get(0).toString());
+ }
}
Modified: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/panel/PanelTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/panel/PanelTest.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/panel/PanelTest.java (original)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/html/panel/PanelTest.java Mon Mar 21 21:54:40 2011
@@ -59,7 +59,7 @@ public class PanelTest extends WicketTes
hit = true;
assertNotNull(mex.getMarkupStream());
- assertTrue(mex.getMessage().contains("Expected close tag for "));
+ assertTrue(mex.getMessage().contains("Tag does not have a close tag"));
assertTrue(mex.getMessage().contains("SimplePanel_1.html"));
}
assertTrue("Did expect a MarkupException", hit);
Modified: wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/parser/XmlPullParserTest.java
URL: http://svn.apache.org/viewvc/wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/parser/XmlPullParserTest.java?rev=1083980&r1=1083979&r2=1083980&view=diff
==============================================================================
--- wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/parser/XmlPullParserTest.java (original)
+++ wicket/trunk/wicket-core/src/test/java/org/apache/wicket/markup/parser/XmlPullParserTest.java Mon Mar 21 21:54:40 2011
@@ -21,7 +21,7 @@ import java.text.ParseException;
import junit.framework.TestCase;
-import org.apache.wicket.markup.parser.IXmlPullParser.ELEMENT_TYPE;
+import org.apache.wicket.markup.parser.IXmlPullParser.HttpTagType;
import org.apache.wicket.util.resource.StringResourceStream;
/**
@@ -283,9 +283,9 @@ public class XmlPullParserTest extends T
// assertTrue(tag.isOpen("tag"));
tag = parser.nextTag();
// assertTrue(tag.isOpen("tag"));
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertTrue(tag.isClose());
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertNull(tag);
}
@@ -307,16 +307,16 @@ public class XmlPullParserTest extends T
{
final XmlPullParser parser = new XmlPullParser();
parser.parse("<html><script language=\"JavaScript\">... <x a> ...</script></html>");
- XmlTag tag = (XmlTag)parser.nextTag();
+ XmlTag tag = parser.nextTag();
assertTrue(tag.isOpen());
assertEquals("html", tag.getName());
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertTrue(tag.isOpen());
assertEquals("script", tag.getName());
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertTrue(tag.isClose());
assertEquals("script", tag.getName());
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertTrue(tag.isClose());
assertEquals("html", tag.getName());
}
@@ -329,13 +329,13 @@ public class XmlPullParserTest extends T
{
final XmlPullParser parser = new XmlPullParser();
parser.parse("<!--[if IE]><a href='test.html'>my link</a><![endif]-->");
- XmlTag tag = (XmlTag)parser.nextTag();
+ XmlTag tag = parser.nextTag();
assertTrue(tag.isOpen());
assertEquals("a", tag.getName());
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertTrue(tag.isClose());
assertEquals("a", tag.getName());
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertNull(tag);
}
@@ -347,21 +347,21 @@ public class XmlPullParserTest extends T
{
final XmlPullParser parser = new XmlPullParser();
parser.parse("<!--[if IE]><a href='test.html'>my link</a><![endif]-->");
- ELEMENT_TYPE type = parser.next();
- assertEquals(type, ELEMENT_TYPE.CONDITIONAL_COMMENT);
+ HttpTagType type = parser.next();
+ assertEquals(type, HttpTagType.CONDITIONAL_COMMENT);
type = parser.next();
- assertEquals(type, ELEMENT_TYPE.TAG);
- assertTrue(((XmlTag)parser.getElement()).isOpen());
+ assertEquals(type, HttpTagType.TAG);
+ assertTrue((parser.getElement()).isOpen());
type = parser.next();
- assertEquals(type, ELEMENT_TYPE.BODY);
+ assertEquals(type, HttpTagType.BODY);
type = parser.next();
- assertEquals(type, ELEMENT_TYPE.TAG);
- assertEquals("a", ((XmlTag)parser.getElement()).getName());
- assertTrue(((XmlTag)parser.getElement()).isClose());
+ assertEquals(type, HttpTagType.TAG);
+ assertEquals("a", (parser.getElement()).getName());
+ assertTrue((parser.getElement()).isClose());
type = parser.next();
- assertEquals(type, ELEMENT_TYPE.CONDITIONAL_COMMENT);
+ assertEquals(type, HttpTagType.CONDITIONAL_COMMENT);
type = parser.next();
- assertEquals(type, ELEMENT_TYPE.NOT_INITIALIZED);
+ assertEquals(type, HttpTagType.NOT_INITIALIZED);
}
/**
@@ -372,17 +372,17 @@ public class XmlPullParserTest extends T
{
final XmlPullParser parser = new XmlPullParser();
parser.parse("<filter-mapping>");
- XmlTag tag = (XmlTag)parser.nextTag();
+ XmlTag tag = parser.nextTag();
assertTrue(tag.isOpen());
assertEquals("filter-mapping", tag.getName());
parser.parse("<filter.mapping>");
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertTrue(tag.isOpen());
assertEquals("filter.mapping", tag.getName());
parser.parse("<filter_mapping>");
- tag = (XmlTag)parser.nextTag();
+ tag = parser.nextTag();
assertTrue(tag.isOpen());
assertEquals("filter_mapping", tag.getName());
}
@@ -395,8 +395,30 @@ public class XmlPullParserTest extends T
{
final XmlPullParser parser = new XmlPullParser();
parser.parse("<!DOCTYPE html>");
- ELEMENT_TYPE type = parser.next();
- assertEquals(ELEMENT_TYPE.DOCTYPE, type);
+ HttpTagType type = parser.next();
+ assertEquals(HttpTagType.DOCTYPE, type);
assertEquals("!DOCTYPE html", parser.getDoctype());
}
-}
+
+ /**
+ * @throws Exception
+ */
+ public final void testDownlevelRevealedConditionalComments() throws Exception
+ {
+ final XmlPullParser parser = new XmlPullParser();
+ parser.parse("<!--[if (gt IE 9)|!(IE)]><!--><html lang=\"en\" class=\"no-js\"><!--<![endif]--> <span>test</span>");
+ HttpTagType type = parser.next();
+ assertEquals(HttpTagType.CONDITIONAL_COMMENT, type);
+
+ type = parser.next();
+ assertEquals(HttpTagType.COMMENT, type);
+
+ type = parser.next();
+ assertEquals(HttpTagType.TAG, type);
+ XmlTag componentTag = parser.getElement();
+ assertEquals("html", componentTag.getName());
+
+ type = parser.next();
+ assertEquals(HttpTagType.CONDITIONAL_COMMENT_ENDIF, type);
+ }
+}
\ No newline at end of file