Revision: 1479
http://stripes.svn.sourceforge.net/stripes/?rev=1479&view=rev
Author: bengunter
Date: 2012-03-05 16:19:23 +0000 (Mon, 05 Mar 2012)
Log Message:
-----------
Rolled up fix for STS-871 from 1.5.x branch.
Modified Paths:
--------------
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutDefinitionTag.java
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java
Added Paths:
-----------
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTagPath.java
Property Changed:
----------------
trunk/
Property changes on: trunk
___________________________________________________________________
Modified: svn:mergeinfo
- /branches/1.5.x:1463-1464,1466,1468-1469,1471,1473,1475
+ /branches/1.5.x:1463-1464,1466,1468-1469,1471,1473,1475,1477-1478
Modified:
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
2012-03-05 16:16:15 UTC (rev 1478)
+++
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutComponentTag.java
2012-03-05 16:19:23 UTC (rev 1479)
@@ -15,13 +15,13 @@
package net.sourceforge.stripes.tag.layout;
import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
import java.util.regex.Pattern;
import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.PageContext;
import net.sourceforge.stripes.exception.StripesJspException;
+import net.sourceforge.stripes.exception.StripesRuntimeException;
import net.sourceforge.stripes.util.Log;
/**
@@ -49,88 +49,42 @@
/** Sets the name of the component. */
public void setName(String name) { this.name = name; }
- /**
- * Get the current layout context.
- *
- * @throws StripesJspException If a {@link LayoutContext} is not found.
- */
- public LayoutContext getContext() throws StripesJspException {
- if (context == null) {
- context = LayoutContext.lookup(pageContext);
+ @Override
+ public void setPageContext(PageContext pageContext) {
+ // Call super method
+ super.setPageContext(pageContext);
- if (context == null) {
- throw new StripesJspException("A component tag named \"" +
getName() + "\" in "
- + getCurrentPagePath() + " was unable to find a layout
context.");
- }
+ // Initialize the layout context and related fields
+ context = LayoutContext.lookup(pageContext);
- log.trace("Component ", getName() + " has context ",
context.getRenderPage(), " -> ",
- context.getDefinitionPage());
+ if (context == null) {
+ throw new StripesRuntimeException("A component tag named \"" +
getName() + "\" in "
+ + getCurrentPagePath() + " was unable to find a layout
context.");
}
- return context;
- }
+ log.trace("Component ", getName() + " has context ",
context.getRenderPage(), " -> ",
+ context.getDefinitionPage());
- /**
- * True if this tag is a component that must execute so that the current
component tag can
- * execute. That is, this tag is a parent of the current component.
- *
- * @throws StripesJspException if thrown by {@link #getContext()}.
- */
- protected boolean isPathComponent() throws StripesJspException {
- List<String> path = getContext().getComponentPath();
- return path == null ? false : isPathComponent(this, path.iterator());
+ silent = context.getOut().isSilent();
}
/**
- * Recursive method called from {@link #isPathComponent()} that returns
true if the specified
- * tag's name is present in the component path iterator at the same
position where this tag
- * occurs in the render/component tag tree. For example, if the path
iterator contains the
- * component names {@code ["foo", "bar"]} then this method will return
true if the tag's name is
- * {@code "bar"} and it is a child of a render tag that is a child of a
component tag whose name
- * is {@code "foo"}.
- *
- * @param tag The tag to check
- * @param path The path to the check the tag against
- * @return
- */
- protected boolean isPathComponent(LayoutComponentTag tag, Iterator<String>
path) {
- LayoutTag parent = tag.getLayoutParent();
- if (parent instanceof LayoutRenderTag) {
- parent = parent.getLayoutParent();
- if (!(parent instanceof LayoutComponentTag) || parent instanceof
LayoutComponentTag
- && isPathComponent((LayoutComponentTag) parent, path) &&
path.hasNext()) {
- return tag.getName().equals(path.next());
- }
- }
-
- return false;
- }
-
- /**
* True if this tag is the component to be rendered on this pass from
* {@link LayoutDefinitionTag}.
*
* @throws StripesJspException If a {@link LayoutContext} is not found.
*/
public boolean isCurrentComponent() throws StripesJspException {
- final LayoutContext context = getContext();
String name = context.getComponent();
if (name == null || !name.equals(getName()))
return false;
- final List<String> want = context.getComponentPath();
- if (want == null)
- return true;
-
final LayoutTag parent = getLayoutParent();
if (!(parent instanceof LayoutRenderTag))
- return false;
+ return context.getComponentPath().getComponentPath() == null;
- final List<String> got = context.getPathToRenderTag((LayoutRenderTag)
parent);
- if (got == null)
- return false;
-
- return want.equals(got);
+ final LayoutRenderTagPath got = ((LayoutRenderTag) parent).getPath();
+ return got != null && got.equals(context.getComponentPath());
}
/**
@@ -154,9 +108,6 @@
@Override
public int doStartTag() throws JspException {
try {
- LayoutContext context = getContext();
- silent = context.getOut().isSilent();
-
if (context.isComponentRenderPhase()) {
if (isChildOfRender()) {
if (isCurrentComponent()) {
@@ -164,7 +115,7 @@
context.getOut().setSilent(false, pageContext);
return EVAL_BODY_INCLUDE;
}
- else if (isPathComponent()) {
+ else if (context.getComponentPath().isPathComponent(this))
{
log.debug("Silently execute '", getName(), "' in ",
context.getRenderPage());
context.getOut().setSilent(true, pageContext);
return EVAL_BODY_INCLUDE;
@@ -280,7 +231,6 @@
// Set current component name back to null as a signal to the
component tag within the
// definition tag that the component did, indeed, render and it
should not output the
// default contents.
- LayoutContext context = getContext();
if (isCurrentComponent())
context.setComponent(null);
Modified:
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
2012-03-05 16:16:15 UTC (rev 1478)
+++ trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutContext.java
2012-03-05 16:19:23 UTC (rev 1479)
@@ -21,10 +21,7 @@
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
-import java.util.Collections;
import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -143,7 +140,7 @@
private Map<String,LayoutComponentRenderer> components = new
HashMap<String,LayoutComponentRenderer>();
private Map<String,Object> parameters = new HashMap<String,Object>();
private String renderPage, component;
- private List<String> componentPath;
+ private LayoutRenderTagPath componentPath;
private boolean componentRenderPhase, rendered;
/**
@@ -155,37 +152,10 @@
public LayoutContext(LayoutRenderTag renderTag) {
this.renderTag = renderTag;
this.renderPage = renderTag.getCurrentPagePath();
-
- List<String> path = getPathToRenderTag(renderTag);
- if (path != null) {
- this.componentPath = Collections.unmodifiableList(path);
- log.debug("Path is ", this.componentPath);
- }
+ this.componentPath = new LayoutRenderTagPath(renderTag);
+ log.debug("Path is ", this.componentPath);
}
- /**
- * Calculate the path to a render tag. The path is a list of names of
components that must
- * execute, in order, so that the specified render tag can execute.
- *
- * @param tag The render tag.
- * @return A list of component names or null if the render tag is not a
child of a component.
- */
- public List<String> getPathToRenderTag(LayoutRenderTag tag) {
- LinkedList<String> path = null;
-
- for (LayoutTag parent = tag.getLayoutParent(); parent instanceof
LayoutComponentTag;) {
- if (path == null)
- path = new LinkedList<String>();
-
- path.addFirst(((LayoutComponentTag) parent).getName());
-
- parent = parent.getLayoutParent();
- parent = parent instanceof LayoutRenderTag ?
parent.getLayoutParent() : null;
- }
-
- return path;
- }
-
/** Get the previous layout context from the stack. */
public LayoutContext getPrevious() { return previous; }
@@ -447,7 +417,7 @@
* Get the list of components in the render page that must execute so that
the render tag that
* created this context can execute.
*/
- public List<String> getComponentPath() { return componentPath; }
+ public LayoutRenderTagPath getComponentPath() { return componentPath; }
/** Get the layout writer to which the layout is rendered. */
public LayoutWriter getOut() { return out; }
Modified:
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutDefinitionTag.java
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutDefinitionTag.java
2012-03-05 16:16:15 UTC (rev 1478)
+++
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutDefinitionTag.java
2012-03-05 16:19:23 UTC (rev 1479)
@@ -20,7 +20,7 @@
import javax.servlet.jsp.JspException;
import javax.servlet.jsp.PageContext;
-import net.sourceforge.stripes.exception.StripesJspException;
+import net.sourceforge.stripes.exception.StripesRuntimeException;
/**
* On the surface, allows a developer to define a layout using a custom tag -
but is actually
@@ -34,25 +34,23 @@
private LayoutContext context;
private boolean renderPhase, silent;
- /**
- * Get the current layout context.
- *
- * @throws StripesJspException If there is no {@link LayoutContext} for
this layout in the
- * current {@link PageContext}.
- */
- public LayoutContext getContext() throws StripesJspException {
- if (context == null) {
- context = LayoutContext.lookup(pageContext);
+ @Override
+ public void setPageContext(PageContext pageContext) {
+ // Call super method
+ super.setPageContext(pageContext);
+
+ // Initialize layout context and related fields
+ context = LayoutContext.lookup(pageContext);
- if (context == null || getLayoutParent() != null) {
- throw new StripesJspException("The JSP page " +
getCurrentPagePath()
- + " contains a layout-definition tag and was invoked
directly. "
- + "A layout-definition can only be invoked by a page
that contains "
- + "a layout-render tag.");
- }
+ if (context == null || getLayoutParent() != null) {
+ throw new StripesRuntimeException("The JSP page " +
getCurrentPagePath()
+ + " contains a layout-definition tag and was invoked
directly. "
+ + "A layout-definition can only be invoked by a page that
contains "
+ + "a layout-render tag.");
}
- return context;
+ renderPhase = context.isComponentRenderPhase();
+ silent = context.getOut().isSilent();
}
/**
@@ -65,10 +63,6 @@
@Override
public int doStartTag() throws JspException {
try {
- LayoutContext context = getContext(); // Initialize context
- renderPhase = context.isComponentRenderPhase(); // Initialize
phase flag
- silent = context.getOut().isSilent();
-
// Flag this definition has rendered, even though it's not really
done yet.
context.setRendered(true);
@@ -100,7 +94,7 @@
public int doEndTag() throws JspException {
try {
cleanUpComponentRenderers();
- getContext().getOut().setSilent(silent, pageContext);
+ context.getOut().setSilent(silent, pageContext);
return SKIP_PAGE;
}
catch (IOException e) {
Modified:
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java
===================================================================
--- trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java
2012-03-05 16:16:15 UTC (rev 1478)
+++ trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTag.java
2012-03-05 16:19:23 UTC (rev 1479)
@@ -40,30 +40,47 @@
private String name;
private LayoutContext context;
private boolean contextIsNew, silent;
+ private LayoutRenderTagPath path;
private BodyContent bodyContent;
/** Gets the name of the layout to be used. */
public String getName() { return name; }
- /** Sets the name of the layout to be used. */
- public void setName(String name) { this.name = name; }
+ /** Sets the name of the layout to be used and then calls {@link
#initialize()}. */
+ public void setName(String name) {
+ this.name = name;
+ initialize();
+ }
- /** Look up an existing layout context or create a new one if none is
found. */
- public LayoutContext getContext() {
- if (context == null) {
- LayoutContext context = LayoutContext.lookup(pageContext);
+ /** Get the {@link LayoutRenderTagPath} that identifies this tag within
the current page. */
+ public LayoutRenderTagPath getPath( ) { return path; }
- boolean create = context == null ||
!context.isComponentRenderPhase()
- || isChildOfCurrentComponent();
+ /**
+ * Initialize fields before execution begins. Typically, this would be
done by overriding
+ * {@link #setPageContext(javax.servlet.jsp.PageContext)}, but that isn't
possible in this case
+ * because some of the logic depends on {@link #setName(String)} having
been called, which does
+ * not happen until after {@link
#setPageContext(javax.servlet.jsp.PageContext)} has been
+ * called.
+ */
+ protected void initialize() {
+ LayoutContext context = LayoutContext.lookup(pageContext);
- if (create)
- context = LayoutContext.push(this);
+ boolean create = context == null || !context.isComponentRenderPhase()
+ || isChildOfCurrentComponent();
- this.context = context;
- this.contextIsNew = create;
+ LayoutRenderTagPath path;
+ if (create) {
+ context = LayoutContext.push(this);
+ path = context.getComponentPath();
}
+ else {
+ path = new LayoutRenderTagPath(this);
+ }
- return context;
+ this.context = context;
+ this.contextIsNew = create;
+ this.path = path;
+ this.silent = context.getOut().isSilent();
}
/** Returns true if this tag is a child of the current component tag. */
@@ -81,7 +98,7 @@
/** Used by the JSP container to provide the tag with dynamic attributes.
*/
public void setDynamicAttribute(String uri, String localName, Object
value) throws JspException {
- getContext().getParameters().put(localName, value);
+ context.getParameters().put(localName, value);
}
/**
@@ -98,9 +115,6 @@
@Override
public int doStartTag() throws JspException {
try {
- LayoutContext context = getContext();
- silent = context.getOut().isSilent();
-
if (contextIsNew) {
log.debug("Start layout init in ", context.getRenderPage());
pushPageContextAttributes(context.getParameters());
@@ -152,7 +166,6 @@
@Override
public int doEndTag() throws JspException {
try {
- LayoutContext context = getContext();
if (contextIsNew) {
log.debug("End layout init in ", context.getRenderPage());
@@ -201,6 +214,7 @@
finally {
this.context = null;
this.contextIsNew = false;
+ this.path = null;
this.silent = false;
if (this.bodyContent != null) {
Copied:
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTagPath.java
(from rev 1478,
branches/1.5.x/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTagPath.java)
===================================================================
---
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTagPath.java
(rev 0)
+++
trunk/stripes/src/net/sourceforge/stripes/tag/layout/LayoutRenderTagPath.java
2012-03-05 16:19:23 UTC (rev 1479)
@@ -0,0 +1,161 @@
+/* Copyright 2012 Ben Gunter
+ *
+ * Licensed 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 net.sourceforge.stripes.tag.layout;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.servlet.jsp.PageContext;
+
+import net.sourceforge.stripes.exception.StripesJspException;
+
+/**
+ * Uniquely identifies a {@link LayoutRenderTag} within a page. Within a
single page, any number of
+ * render tags can be accessible via the same "path," where a path consists of
zero or more
+ * component tags that are parents of the render tag. This class helps to
distinguish between
+ * multiple render tags with the same component path by assigning sequential
indexes to them.
+ *
+ * @author Ben Gunter
+ * @since Stripes 1.5.7
+ */
+public class LayoutRenderTagPath {
+ private List<String> componentPath;
+ private int index;
+
+ /** Construct a new instance to identify the specified tag. */
+ public LayoutRenderTagPath(LayoutRenderTag tag) {
+ this.componentPath = calculateComponentPath(tag);
+ this.index = incrementIndex(tag.getPageContext());
+ }
+
+ /**
+ * Calculate the path to a render tag. The path is a list of names of
components that must
+ * execute, in order, so that the specified render tag can execute.
+ *
+ * @param tag The render tag.
+ * @return A list of component names or null if the render tag is not a
child of a component.
+ */
+ protected List<String> calculateComponentPath(LayoutRenderTag tag) {
+ LinkedList<String> path = null;
+
+ for (LayoutTag parent = tag.getLayoutParent(); parent instanceof
LayoutComponentTag;) {
+ if (path == null)
+ path = new LinkedList<String>();
+
+ path.addFirst(((LayoutComponentTag) parent).getName());
+
+ parent = parent.getLayoutParent();
+ parent = parent instanceof LayoutRenderTag ?
parent.getLayoutParent() : null;
+ }
+
+ return path;
+ }
+
+ /** Get the next index for this path from the specified page context. */
+ protected int incrementIndex(PageContext pageContext) {
+ String key = getClass().getName() + "#" + toStringWithoutIndex();
+ Integer index = (Integer) pageContext.getAttribute(key);
+ if (index == null)
+ index = 0;
+ else
+ ++index;
+ pageContext.setAttribute(key, index);
+ return index;
+ }
+
+ /** Get the names of the {@link LayoutComponentTag}s that are parent tags
of the render tag. */
+ public List<String> getComponentPath() {
+ return componentPath;
+ }
+
+ /** Get the index (zero-based) of the combined render page and component
path within the page. */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * True if the specified tag is a component that must execute so that the
current component tag
+ * can execute. That is, this tag is a parent of the current component.
+ *
+ * @param tag The tag to check to see if it is part of this path.
+ * @throws StripesJspException if thrown by {@link #getContext()}.
+ */
+ public boolean isPathComponent(LayoutComponentTag tag) throws
StripesJspException {
+ List<String> path = getComponentPath();
+ return path == null ? false : isPathComponent(tag, path.iterator());
+ }
+
+ /**
+ * Recursive method called from {@link #isPathComponent()} that returns
true if the specified
+ * tag's name is present in the component path iterator at the same
position where this tag
+ * occurs in the render/component tag tree. For example, if the path
iterator contains the
+ * component names {@code ["foo", "bar"]} then this method will return
true if the tag's name is
+ * {@code "bar"} and it is a child of a render tag that is a child of a
component tag whose name
+ * is {@code "foo"}.
+ *
+ * @param tag The tag to check
+ * @param path The path to the check the tag against
+ * @return
+ */
+ protected boolean isPathComponent(LayoutComponentTag tag, Iterator<String>
path) {
+ LayoutTag parent = tag.getLayoutParent();
+ if (parent instanceof LayoutRenderTag) {
+ parent = parent.getLayoutParent();
+ if (!(parent instanceof LayoutComponentTag) || parent instanceof
LayoutComponentTag
+ && isPathComponent((LayoutComponentTag) parent, path) &&
path.hasNext()) {
+ return tag.getName().equals(path.next());
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ LayoutRenderTagPath that = (LayoutRenderTagPath) obj;
+ if (index != that.index)
+ return false;
+ if (componentPath == that.componentPath)
+ return true;
+ if (componentPath == null || that.componentPath == null)
+ return false;
+ return componentPath.equals(that.componentPath);
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ @Override
+ public String toString() {
+ return toStringWithoutIndex() + '[' + index + ']';
+ }
+
+ /** Get a string representation of this instance without including the
index. */
+ public String toStringWithoutIndex() {
+ if (componentPath == null)
+ return "";
+
+ StringBuilder s = new StringBuilder();
+ for (Iterator<String> it = componentPath.iterator(); it.hasNext();) {
+ s.append(it.next());
+ if (it.hasNext())
+ s.append('>');
+ }
+ return s.toString();
+ }
+}
This was sent by the SourceForge.net collaborative development platform, the
world's largest Open Source development site.
------------------------------------------------------------------------------
Try before you buy = See our experts in action!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-dev2
_______________________________________________
Stripes-development mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/stripes-development