You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2014/03/11 17:18:14 UTC

git commit: WICKET-5531 Create new placeholder tag to indicate where header contributions should appear

Repository: wicket
Updated Branches:
  refs/heads/5531-wicket-header-items [created] 0123767f7


WICKET-5531 Create new placeholder tag to indicate where header contributions should appear


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/0123767f
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/0123767f
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/0123767f

Branch: refs/heads/5531-wicket-header-items
Commit: 0123767f798e7715ae0da81188c0e6e2e5f4a236
Parents: 6f2d651
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Tue Mar 11 18:17:24 2014 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Tue Mar 11 18:17:24 2014 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/wicket/Component.java  |  5 +-
 .../java/org/apache/wicket/MarkupContainer.java |  2 +-
 .../org/apache/wicket/markup/MergedMarkup.java  |  2 +-
 .../java/org/apache/wicket/markup/TagUtils.java | 22 ++++++++-
 .../org/apache/wicket/markup/WicketTag.java     |  8 ++++
 .../html/internal/HtmlHeaderContainer.java      | 12 +++--
 .../html/internal/HtmlHeaderItemsContainer.java | 41 +++++++++++++++++
 .../parser/filter/HtmlHeaderSectionHandler.java | 48 ++++++++++++++++++--
 .../parser/filter/OpenCloseTagExpander.java     | 11 +++--
 .../parser/filter/WicketTagIdentifier.java      |  7 +--
 .../markup/resolver/HtmlHeaderResolver.java     | 43 ++++++++++++++----
 11 files changed, 168 insertions(+), 33 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/Component.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/Component.java b/wicket-core/src/main/java/org/apache/wicket/Component.java
index 4c43f52..6e6c7da 100644
--- a/wicket-core/src/main/java/org/apache/wicket/Component.java
+++ b/wicket-core/src/main/java/org/apache/wicket/Component.java
@@ -2549,11 +2549,8 @@ public abstract class Component
 				// Render the body. The default strategy will simply call the component's
 				// onComponentTagBody() implementation.
 				getMarkupSourcingStrategy().onComponentTagBody(this, markupStream, tag);
-			}
 
-			// Render close tag
-			if (tag.isOpen())
-			{
+				// Render close tag
 				if (openTag.isOpen())
 				{
 					renderClosingComponentTag(markupStream, tag, getRenderBodyOnly());

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
index 75ff938..85eb11c 100644
--- a/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/MarkupContainer.java
@@ -1521,7 +1521,7 @@ public abstract class MarkupContainer extends Component implements Iterable<Comp
 			render = !openTag.hasNoCloseTag();
 		}
 
-		if (render == true)
+		if (render)
 		{
 			renderAll(markupStream, openTag);
 		}

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/MergedMarkup.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/MergedMarkup.java b/wicket-core/src/main/java/org/apache/wicket/markup/MergedMarkup.java
index cb173a1..eb1a6b9 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/MergedMarkup.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/MergedMarkup.java
@@ -421,7 +421,7 @@ public class MergedMarkup extends Markup
 				}
 			}
 
-			if (copy == true)
+			if (copy)
 			{
 				addMarkupElement(elem);
 			}

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/TagUtils.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/TagUtils.java b/wicket-core/src/main/java/org/apache/wicket/markup/TagUtils.java
index 7fd4e4d..09aa73a 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/TagUtils.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/TagUtils.java
@@ -106,7 +106,7 @@ public class TagUtils
 	}
 
 	/**
-	 * 
+	 *
 	 * @param elem
 	 * @return True if the current markup element is a &lt;wicket:head&gt; tag
 	 */
@@ -124,6 +124,24 @@ public class TagUtils
 	}
 
 	/**
+	 *
+	 * @param elem
+	 * @return True if the current markup element is a &lt;wicket:head&gt; tag
+	 */
+	public static final boolean isWicketHeaderItemsTag(final MarkupElement elem)
+	{
+		if (elem instanceof WicketTag)
+		{
+			WicketTag wtag = (WicketTag)elem;
+			if (wtag.isHeaderItemsTag())
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
 	 * 
 	 * @param elem
 	 * @return True if the current markup element is a &lt;wicket:body&gt; tag
@@ -195,4 +213,4 @@ public class TagUtils
 				"Expected a Tag but found raw markup: " + elem.toString());
 		}
 	}
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/WicketTag.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/WicketTag.java b/wicket-core/src/main/java/org/apache/wicket/markup/WicketTag.java
index b609f7b..120d2af 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/WicketTag.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/WicketTag.java
@@ -133,6 +133,14 @@ public class WicketTag extends ComponentTag
 	}
 
 	/**
+	 * @return True, if tag name equals 'wicket:header-items'
+	 */
+	public final boolean isHeaderItemsTag()
+	{
+		return HtmlHeaderResolver.HEADER_ITEMS.equalsIgnoreCase(getName());
+	}
+
+	/**
 	 * @return True, if tag name equals 'wicket:message'
 	 */
 	public final boolean isMessageTag()

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
index 42e63b6..51962f7 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderContainer.java
@@ -48,8 +48,8 @@ import org.apache.wicket.response.StringResponse;
  * &lt;head&gt; regions may contain additional wicket components, which can be added by means of
  * add(Component) as usual.
  * <p>
- * &lt;wicket:head&gt; tags are handled by simple WebMarkupContainers also created by a
- * HtmlHeaderResolver.
+ * &lt;wicket:head&gt; tags are handled by simple {@link TransparentWebMarkupContainer}s also created by
+ * {@link org.apache.wicket.markup.resolver.HtmlHeaderResolver}.
  * <p>
  * <ul>
  * <li>&lt;head&gt; will be inserted in output automatically if required</li>
@@ -63,7 +63,7 @@ import org.apache.wicket.response.StringResponse;
  * <li>components within &lt;wicket:head&gt; must be added by means of add(), like always with
  * Wicket. No difference.</li>
  * <li>&lt;wicket:head&gt; and it's content is copied to the output. Components contained in
- * &lt;org.apache.wicket.head&gt; are rendered as usual</li>
+ * &lt;wicket:head&gt; are rendered as usual</li>
  * </ul>
  * 
  * @author Juergen Donnerstag
@@ -379,17 +379,19 @@ public class HtmlHeaderContainer extends TransparentWebMarkupContainer
 				if (tag instanceof WicketTag)
 				{
 					WicketTag wtag = (WicketTag)tag;
-					if (wtag.isHeadTag())
+					if (wtag.isHeadTag() || wtag.isHeaderItemsTag())
 					{
 						if (tag.getMarkupClass() == null)
 						{
 							headerMarkup = stream.getMarkupFragment();
+							break;
 						}
 					}
 				}
-				else if (tag.getName().equalsIgnoreCase("head"))
+				else if (tag.getName().equalsIgnoreCase("head") && tag.isAutoComponentTag())
 				{
 					headerMarkup = stream.getMarkupFragment();
+					break;
 				}
 			}
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderItemsContainer.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderItemsContainer.java b/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderItemsContainer.java
new file mode 100644
index 0000000..55490eb
--- /dev/null
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/html/internal/HtmlHeaderItemsContainer.java
@@ -0,0 +1,41 @@
+/*
+ * 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.html.internal;
+
+/**
+ */
+public class HtmlHeaderItemsContainer extends HtmlHeaderContainer
+{
+	private static final long serialVersionUID = 1L;
+
+	/**
+	 * Constructor
+	 *
+	 * @param id
+	 *          The component id
+	 */
+	public HtmlHeaderItemsContainer(String id)
+	{
+		super(id);
+	}
+
+	@Override
+	protected boolean renderOpenAndCloseTags()
+	{
+		return false;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHeaderSectionHandler.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHeaderSectionHandler.java b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHeaderSectionHandler.java
index 4edafac..7042da2 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHeaderSectionHandler.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/HtmlHeaderSectionHandler.java
@@ -25,11 +25,12 @@ import org.apache.wicket.markup.MarkupException;
 import org.apache.wicket.markup.MarkupStream;
 import org.apache.wicket.markup.parser.AbstractMarkupFilter;
 import org.apache.wicket.markup.parser.XmlTag.TagType;
+import org.apache.wicket.markup.resolver.HtmlHeaderResolver;
 
 
 /**
- * This is a markup inline filter. It assumes that WicketTagIdentifier has been called first and
- * search for a &lt;head&gt; tag (note: not wicket:head). Provided the markup contains a
+ * This is a markup inline filter. It assumes that {@link org.apache.wicket.markup.parser.filter.WicketTagIdentifier}
+ * has been called first and search for a &lt;head&gt; tag (note: not wicket:head). Provided the markup contains a
  * &lt;body&gt; tag it will automatically prepend a &lt;head&gt; tag if missing.
  * <p>
  * Note: This handler is only relevant for Pages (see MarkupParser.newFilterChain())
@@ -45,12 +46,14 @@ public final class HtmlHeaderSectionHandler extends AbstractMarkupFilter
 	/** The automatically assigned wicket:id to &gt;head&lt; tag */
 	public static final String HEADER_ID = "_header_";
 
-	/** True if <head> has been found already */
+	/** True if &lt;head&gt; has been found already */
 	private boolean foundHead = false;
 
-	/** True if </head> has been found already */
+	/** True if &lt;/head&gt; has been found already */
 	private boolean foundClosingHead = false;
 
+	private boolean foundHeaderItemsTag = false;
+
 	/** True if all the rest of the markup file can be ignored */
 	private boolean ignoreTheRest = false;
 
@@ -97,6 +100,16 @@ public final class HtmlHeaderSectionHandler extends AbstractMarkupFilter
 				}
 				else if (tag.isClose())
 				{
+					if (foundHeaderItemsTag)
+					{
+						// revert the settings from above
+						ComponentTag headOpenTag = tag.getOpenTag();
+						headOpenTag.setId(HEADER_ID + "-Ignored");
+						headOpenTag.setAutoComponentTag(false);
+						headOpenTag.setModified(false);
+						headOpenTag.setFlag(ComponentTag.RENDER_RAW, true);
+					}
+
 					foundClosingHead = true;
 				}
 
@@ -109,6 +122,16 @@ public final class HtmlHeaderSectionHandler extends AbstractMarkupFilter
 				foundClosingHead = true;
 			}
 		}
+		else if (HtmlHeaderResolver.HEADER_ITEMS.equalsIgnoreCase(tag.getName()) &&
+				tag.getNamespace().equalsIgnoreCase(getWicketNamespace()))
+		{
+			foundHeaderItemsTag = true;
+			tag.setId(HEADER_ID);
+			tag.setAutoComponentTag(true);
+			tag.setModified(true);
+
+			return tag;
+		}
 		else if (BODY.equalsIgnoreCase(tag.getName()) && (tag.getNamespace() == null))
 		{
 			// WICKET-4511: We found <body> inside <head> tag. Markup is not valid!
@@ -132,6 +155,23 @@ public final class HtmlHeaderSectionHandler extends AbstractMarkupFilter
 		return tag;
 	}
 
+	// temporary storage. Introduce into flow on next request
+	private ComponentTag next = null;
+
+	@Override
+	public MarkupElement nextElement() throws ParseException
+	{
+		// Did we hold back an elem? Than return that first
+		if (next != null)
+		{
+			MarkupElement rtn = next;
+			next = null;
+			return rtn;
+		}
+
+		return super.nextElement();
+	}
+
 	/**
 	 * Insert <head> open and close tag (with empty body) to the current position.
 	 */

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java
index 390c1f4..c8d8581 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/OpenCloseTagExpander.java
@@ -24,6 +24,7 @@ import org.apache.wicket.markup.ComponentTag;
 import org.apache.wicket.markup.MarkupElement;
 import org.apache.wicket.markup.parser.AbstractMarkupFilter;
 import org.apache.wicket.markup.parser.XmlTag.TagType;
+import org.apache.wicket.markup.resolver.HtmlHeaderResolver;
 
 /**
  * MarkupFilter that expands certain open-close tag as separate open and close tags. Firefox, unless
@@ -60,7 +61,7 @@ public class OpenCloseTagExpander extends AbstractMarkupFilter
 		// @TODO by now an exclude list is probably shorter
 		"article", "aside", "details", "summary", "figure", "figcaption", "footer",
 		"header", "hgroup", "mark", "meter", "nav", "progress", "ruby", "rt", "rp", "section",
-		"audio", "video", "canvas", "datalist", "output");
+		"audio", "video", "canvas", "datalist", "output", HtmlHeaderResolver.HEADER_ITEMS);
 
 	// temporary storage. Introduce into flow on next request
 	private ComponentTag next = null;
@@ -88,10 +89,10 @@ public class OpenCloseTagExpander extends AbstractMarkupFilter
 		if (tag.isOpenClose())
 		{
 			String name = tag.getName();
-			if (tag.getNamespace() != null)
-			{
-				name = tag.getNamespace() + ":" + tag.getName();
-			}
+//			if (tag.getNamespace() != null)
+//			{
+//				name = tag.getNamespace() + ":" + tag.getName();
+//			}
 
 			if (contains(name))
 			{

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/WicketTagIdentifier.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/WicketTagIdentifier.java b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/WicketTagIdentifier.java
index 2906f69..1eac945 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/WicketTagIdentifier.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/parser/filter/WicketTagIdentifier.java
@@ -64,6 +64,7 @@ public final class WicketTagIdentifier extends AbstractMarkupFilter
 		WELL_KNOWN_TAG_NAMES.add(WicketRemoveTagHandler.REMOVE);
 		WELL_KNOWN_TAG_NAMES.add(FragmentResolver.FRAGMENT);
 		WELL_KNOWN_TAG_NAMES.add(HtmlHeaderResolver.HEAD);
+		WELL_KNOWN_TAG_NAMES.add(HtmlHeaderResolver.HEADER_ITEMS);
 		WELL_KNOWN_TAG_NAMES.add(MarkupInheritanceResolver.CHILD);
 		WELL_KNOWN_TAG_NAMES.add(MarkupInheritanceResolver.EXTEND);
 		WELL_KNOWN_TAG_NAMES.add(WicketContainerResolver.CONTAINER);
@@ -85,12 +86,12 @@ public final class WicketTagIdentifier extends AbstractMarkupFilter
 	 * Get the next tag from the next MarkupFilter in the chain and search for Wicket specific tags.
 	 * <p>
 	 * Note: The xml parser - the next MarkupFilter in the chain - returns XmlTags which are a
-	 * subclass of MarkupElement. The implementation of this filter will return either ComponentTags
-	 * or ComponentWicketTags. Both are subclasses of MarkupElement as well and both maintain a
+	 * subclass of MarkupElement. The implementation of this filter will return either ComponentTag
+	 * or WicketTag. Both are subclasses of MarkupElement and both maintain a
 	 * reference to the XmlTag. But no XmlTag is returned.
 	 * 
 	 * @see org.apache.wicket.markup.parser.IMarkupFilter#nextElement()
-	 * @return The next tag from markup to be processed. If null, no more tags are available
+	 * @return The next tag from markup to be processed. If {@code null} then no more tags are available
 	 */
 	@Override
 	protected MarkupElement onComponentTag(ComponentTag tag) throws ParseException

http://git-wip-us.apache.org/repos/asf/wicket/blob/0123767f/wicket-core/src/main/java/org/apache/wicket/markup/resolver/HtmlHeaderResolver.java
----------------------------------------------------------------------
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/resolver/HtmlHeaderResolver.java b/wicket-core/src/main/java/org/apache/wicket/markup/resolver/HtmlHeaderResolver.java
index 4688b12..8ebe0ce 100644
--- a/wicket-core/src/main/java/org/apache/wicket/markup/resolver/HtmlHeaderResolver.java
+++ b/wicket-core/src/main/java/org/apache/wicket/markup/resolver/HtmlHeaderResolver.java
@@ -27,6 +27,7 @@ import org.apache.wicket.markup.html.TransparentWebMarkupContainer;
 import org.apache.wicket.markup.html.WebMarkupContainer;
 import org.apache.wicket.markup.html.WebPage;
 import org.apache.wicket.markup.html.internal.HtmlHeaderContainer;
+import org.apache.wicket.markup.html.internal.HtmlHeaderItemsContainer;
 import org.apache.wicket.markup.parser.filter.HtmlHeaderSectionHandler;
 import org.apache.wicket.markup.parser.filter.WicketTagIdentifier;
 import org.apache.wicket.util.resource.IResourceStream;
@@ -40,7 +41,7 @@ import org.apache.wicket.util.resource.IResourceStream;
  * (auto) added to the component hierarchy and immediately rendered. Please see the javadoc for
  * {@link HtmlHeaderContainer} on how it treats the tag.
  * <p>
- * In case of &lt;wicket:head&gt; a simple {@link WebMarkupContainer} handles the tag.
+ * In case of &lt;wicket:head&gt; a simple {@link TransparentWebMarkupContainer} handles the tag.
  * 
  * @author Juergen Donnerstag
  */
@@ -50,30 +51,33 @@ public class HtmlHeaderResolver implements IComponentResolver
 
 	/** */
 	public static final String HEAD = "head";
+	public static final String HEADER_ITEMS = "header-items";
 
 	@Override
 	public Component resolve(final MarkupContainer container, final MarkupStream markupStream,
 		final ComponentTag tag)
 	{
+		final Page page = container.getPage();
+
 		// Only <head> component tags have the id == "_header"
 		if (tag.getId().equals(HtmlHeaderSectionHandler.HEADER_ID))
 		{
 			// Create a special header component which will gather additional
 			// input the <head> from 'contributors'.
 			return newHtmlHeaderContainer(HtmlHeaderSectionHandler.HEADER_ID +
-				container.getPage().getAutoIndex());
+				page.getAutoIndex(), tag);
 		}
 		else if ((tag instanceof WicketTag) && ((WicketTag)tag).isHeadTag())
 		{
 			// If we found <wicket:head> without surrounding <head> on a Page,
-			// than we have to add wicket:head into a automatically generated
+			// then we have to add wicket:head into a automatically generated
 			// head first.
 			if (container instanceof WebPage)
 			{
 				// Create a special header component which will gather
 				// additional input the <head> from 'contributors'.
 				MarkupContainer header = newHtmlHeaderContainer(HtmlHeaderSectionHandler.HEADER_ID +
-					container.getPage().getAutoIndex());
+					page.getAutoIndex(), tag);
 
 				// It is <wicket:head>. Because they do not provide any
 				// additional functionality they are merely a means of surrounding relevant
@@ -99,13 +103,14 @@ public class HtmlHeaderResolver implements IComponentResolver
 
 				return header;
 			}
-			final Page page = container.getPage();
+
 			final String pageClassName = (page != null) ? page.getClass().getName() : "unknown";
 			final IResourceStream stream = markupStream.getResource();
 			final String streamName = (stream != null) ? stream.toString() : "unknown";
 
 			throw new MarkupException(
-				"Mis-placed <wicket:head>. <wicket:head> must be outside of <wicket:panel>, <wicket:border>, and <wicket:extend>. Error occured while rendering page: " +
+				"Mis-placed <wicket:head>. <wicket:head> must be outside of <wicket:panel>, <wicket:border>, " +
+						"and <wicket:extend>. Error occurred while rendering page: " +
 					pageClassName + " using markup stream: " + streamName);
 		}
 
@@ -115,12 +120,34 @@ public class HtmlHeaderResolver implements IComponentResolver
 
 	/**
 	 * Return a new HtmlHeaderContainer
-	 * 
+	 *
 	 * @param id
 	 * @return HtmlHeaderContainer
+	 * @deprecated Use #newHtmlHeaderContainer(String, ComponentTag) instead
 	 */
+	@Deprecated
 	protected HtmlHeaderContainer newHtmlHeaderContainer(String id)
 	{
 		return new HtmlHeaderContainer(id);
 	}
-}
\ No newline at end of file
+
+	/**
+	 * Return a new HtmlHeaderContainer
+	 *
+	 * @param id
+	 * @return HtmlHeaderContainer
+	 */
+	protected HtmlHeaderContainer newHtmlHeaderContainer(String id, ComponentTag tag)
+	{
+		HtmlHeaderContainer htmlHeaderContainer;
+		if (HtmlHeaderResolver.HEADER_ITEMS.equalsIgnoreCase(tag.getName()))
+		{
+			htmlHeaderContainer = new HtmlHeaderItemsContainer(id);
+		}
+		else
+		{
+			htmlHeaderContainer = newHtmlHeaderContainer(id);
+		}
+		return htmlHeaderContainer;
+	}
+}