Commits

Anonymous committed c6e726b

- resolved an issue where a tag's parent wasn't being set in velocity
- expanded the displaytags example

git-svn-id: http://svn.opensymphony.com/svn/webwork/trunk@168573baa09-0c28-0410-bef9-dab3c582ae83

Comments (0)

Files changed (7)

lib/example/commons-beanutils-1.6.jar

Binary file added.

lib/example/commons-lang-2.0.jar

Binary file added.

src/java/com/opensymphony/webwork/views/jsp/ActionTag.java

             if (actionContext != null) {
                 OgnlValueStack stack = actionContext.getValueStack();
 
-                if (stack != null) {
+                if ((stack != null) && (stack.size() > 1)) {
                     Object newTop = stack.peek();
 
                     while (!(newTop == null) && !newTop.equals(top)) {

src/java/com/opensymphony/webwork/views/velocity/AbstractTagDirective.java

 
 /**
  * Custom user Directive that enables the WebWork2 UI tags to be easily accessed from Velocity pages
- * 
+ *
  * @author $author$
  * @version $id$
  */
     //~ Static fields/initializers /////////////////////////////////////////////
 
     /**
- * a params of tagname to tagclass that provides faster lookup that searching through the tagpath.  for example,
- * <pre>#tag( TextField )</pre>
- * would result in "TextField" and com.opensymphony.webwork.views.jsp.ui.TextFieldTag.class being stored in the
- * tagclassMap
- * todo enable this params to be reloaded or reset
- */
+     * a params of tagname to tagclass that provides faster lookup that searching through the tagpath.  for example,
+     * <pre>#tag( TextField )</pre>
+     * would result in "TextField" and com.opensymphony.webwork.views.jsp.ui.TextFieldTag.class being stored in the
+     * tagclassMap
+     * todo enable this params to be reloaded or reset
+     */
     protected static Map tagclassMap = new HashMap();
 
     //~ Methods ////////////////////////////////////////////////////////////////
 
     /**
- * the guts of this directive that indicates how this directive should be rendered.  Conceptually, this method is
- * a controller that delegates the work to other methods.  by convention, i'm using process* for the delegated
- * methods.  processRenderer and processTag respectively.
- */
+     * the guts of this directive that indicates how this directive should be rendered.  Conceptually, this method is
+     * a controller that delegates the work to other methods.  by convention, i'm using process* for the delegated
+     * methods.  processRenderer and processTag respectively.
+     */
     public boolean render(InternalContextAdapter contextAdapter, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
         if (node.jjtGetNumChildren() < 1) {
             throw new ParseErrorException("no tag specified!  to use the #tag directive, you must specify at least the name of the tag to use");
         OgnlUtil.setProperties(propertyMap, object);
 
         /**
- * if this directive allows for a body, the last child Node will be the body.  we'll want to grab a handle to
- * this Node to allow the processTag method to use it
- */
+         * if this directive allows for a body, the last child Node will be the body.  we'll want to grab a handle to
+         * this Node to allow the processTag method to use it
+         */
         Node bodyNode = null;
 
         /**
- * if this Directive is a BLOCK directive, then we <b>know</b> we must have a body.  store the reference to
- * the directive's body in bodyNode
- */
+         * if this Directive is a BLOCK directive, then we <b>know</b> we must have a body.  store the reference to
+         * the directive's body in bodyNode
+         */
         if (this.getType() == BLOCK) {
             bodyNode = node.jjtGetChild(node.jjtGetNumChildren() - 1);
         }
 
         /**
- * save the previous parent and tag if there are any
- */
+         * save the previous parent and tag if there are any
+         */
         Object currentParent = contextAdapter.get(VelocityManager.PARENT);
         Object currentTag = contextAdapter.get(VelocityManager.TAG);
 
         try {
             // if we're already inside a tag, then make this tag the new parent
-            if (currentTag != null) {
-                contextAdapter.put(VelocityManager.PARENT, currentTag);
-            }
-
+            contextAdapter.put(VelocityManager.PARENT, currentTag);
             contextAdapter.put(VelocityManager.TAG, object);
-
             InternalContextAdapter subContextAdapter = new WrappedInternalContextAdapter(contextAdapter);
 
             if (object instanceof Tag) {
                 PageContext pageContext = ServletActionContext.getPageContext();
+                ((Tag) object).setParent((Tag) currentTag);
 
                 return this.processTag(pageContext, (Tag) object, subContextAdapter, writer, bodyNode);
             } else {
             }
         } finally {
             /**
- * replace the parent and/or child if there were any
- */
+             * replace the parent and/or child if there were any
+             */
             if (currentParent != null) {
                 contextAdapter.put(VelocityManager.PARENT, currentParent);
             } else {
     }
 
     /**
- * todo it would be nice for the Configuration object to allow listeners to be registered so that they can be
- * notified of changes to the Configuration files
- * 
- * @return an array of paths to search for our tag library
- */
+     * todo it would be nice for the Configuration object to allow listeners to be registered so that they can be
+     * notified of changes to the Configuration files
+     *
+     * @return an array of paths to search for our tag library
+     */
     protected String[] getTagPath() throws ResourceNotFoundException {
         List pathList = new ArrayList();
 
     }
 
     /**
- * create a new instance of our rendering object.  this will usually be a Tag, but I've left it as an Object just
- * in case we want to define more abitrary rendering mechanisms that are not JSP tags
- * 
- * @param node the node that contains the label for our rendering object.  this will usually be something like
- *             TextField, Password, or Component
- * @return a new instance of the object specified by the Node
- * @throws org.apache.velocity.exception.ResourceNotFoundException
- *          
- */
+     * create a new instance of our rendering object.  this will usually be a Tag, but I've left it as an Object just
+     * in case we want to define more abitrary rendering mechanisms that are not JSP tags
+     *
+     * @param node the node that contains the label for our rendering object.  this will usually be something like
+     *             TextField, Password, or Component
+     * @return a new instance of the object specified by the Node
+     * @throws org.apache.velocity.exception.ResourceNotFoundException
+     *
+     */
     protected Object createObject(Node node) throws ResourceNotFoundException {
         String tagname = node.getFirstToken().toString();
         Class clazz = (Class) tagclassMap.get(tagname);
     }
 
     /**
- * create a Map of properties that the user has passed in.  for example,
- * <pre>
- * #tag( TextField "name=hello" "value=world" "template=foo" )
- * </pre>
- * would yield a params that contains {["name", "hello"], ["value", "world"], ["template", "foo"]}
- * 
- * @param node the Node passed in to the render method
- * @return a Map of the user specified properties
- * @throws org.apache.velocity.exception.ParseErrorException
- *          if the was an error in the format of the property
- * @see #render
- */
+     * create a Map of properties that the user has passed in.  for example,
+     * <pre>
+     * #tag( TextField "name=hello" "value=world" "template=foo" )
+     * </pre>
+     * would yield a params that contains {["name", "hello"], ["value", "world"], ["template", "foo"]}
+     *
+     * @param node the Node passed in to the render method
+     * @return a Map of the user specified properties
+     * @throws org.apache.velocity.exception.ParseErrorException
+     *          if the was an error in the format of the property
+     * @see #render
+     */
     protected Map createPropertyMap(InternalContextAdapter contextAdapter, Node node) throws ParseErrorException, MethodInvocationException {
         Map propertyMap = new HashMap();
 
         for (int index = 1, length = node.jjtGetNumChildren(); index < length;
-                index++) {
+             index++) {
             this.putProperty(propertyMap, contextAdapter, node.jjtGetChild(index));
         }
 
     }
 
     /**
- * Searches for tags (class that are instances of Renderers or Tags) in the webwork.velocity.tag.path using the
- * following rules:
- * <ul>
- * <li>append the tagname + 'Tag' to the path and see if a class exists and is a Renderer or Tag</li>
- * <li>append the tagname to the path and see if a class exists and is a Renderer or Tag</li>
- * </ul>
- * For example, let us say that we're search for a custom tag, Foobar.  Assuming our webwork.velocity.tag.path is
- * the default ("com.opensymphony.webwork.views.jsp.ui", "com.opensymphony.webwork.views.jsp", ""), then we will search
- * for our tag in the following locations:
- * <ul>
- * <li>com.opensymphony.webwork.views.jsp.ui.FoobarTag</li>
- * <li>com.opensymphony.webwork.views.jsp.ui.Foobar</li>
- * <li>com.opensymphony.webwork.views.jsp.FoobarTag</li>
- * <li>com.opensymphony.webwork.views.jsp.Foobar</li>
- * <li>FoobarTag</li>
- * <li>Foobar</li>
- * </ul>
- * 
- * @param tagname 
- * @return 
- * @see #getTagPath
- */
+     * Searches for tags (class that are instances of Renderers or Tags) in the webwork.velocity.tag.path using the
+     * following rules:
+     * <ul>
+     * <li>append the tagname + 'Tag' to the path and see if a class exists and is a Renderer or Tag</li>
+     * <li>append the tagname to the path and see if a class exists and is a Renderer or Tag</li>
+     * </ul>
+     * For example, let us say that we're search for a custom tag, Foobar.  Assuming our webwork.velocity.tag.path is
+     * the default ("com.opensymphony.webwork.views.jsp.ui", "com.opensymphony.webwork.views.jsp", ""), then we will search
+     * for our tag in the following locations:
+     * <ul>
+     * <li>com.opensymphony.webwork.views.jsp.ui.FoobarTag</li>
+     * <li>com.opensymphony.webwork.views.jsp.ui.Foobar</li>
+     * <li>com.opensymphony.webwork.views.jsp.FoobarTag</li>
+     * <li>com.opensymphony.webwork.views.jsp.Foobar</li>
+     * <li>FoobarTag</li>
+     * <li>Foobar</li>
+     * </ul>
+     *
+     * @param tagname
+     * @return
+     * @see #getTagPath
+     */
     protected Class findTagInPath(String tagname) throws ResourceNotFoundException {
         String[] tagpath = this.getTagPath();
 
         Class clazz = null;
 
         for (int index = 0; (clazz == null) && (index < tagpath.length);
-                index++) {
+             index++) {
             try {
                 clazz = Class.forName(tagpath[index] + "." + tagname + "Tag");
             } catch (ClassNotFoundException e) {
     }
 
     /**
- *
- */
+     *
+     */
     protected boolean processTag(PageContext pageContext, Tag tag, InternalContextAdapter context, Writer writer, Node bodyNode) throws ParseErrorException, IOException, MethodInvocationException, ResourceNotFoundException {
         tag.setPageContext(pageContext);
         writer = pageContext.getOut();
     }
 
     /**
- * adds a given Node's key/value pair to the propertyMap.  For example, if this Node contained the value "rows=20",
- * then the key, rows, would be added to the propertyMap with the String value, 20.
- * 
- * @param propertyMap a params containing all the properties that we wish to set
- * @param node        the parameter to set expressed in "name=value" format
- */
+     * adds a given Node's key/value pair to the propertyMap.  For example, if this Node contained the value "rows=20",
+     * then the key, rows, would be added to the propertyMap with the String value, 20.
+     *
+     * @param propertyMap a params containing all the properties that we wish to set
+     * @param node        the parameter to set expressed in "name=value" format
+     */
     protected void putProperty(Map propertyMap, InternalContextAdapter contextAdapter, Node node) throws ParseErrorException, MethodInvocationException {
         // node.value uses the WebWorkValueStack to evaluate the directive's value parameter
         String param = node.value(contextAdapter).toString();
     //~ Inner Classes //////////////////////////////////////////////////////////
 
     /**
- * the WrappedInternalContextAdapter is a simple wrapper around the InternalContextAdapter that allows us to
- * effectively create local variables within each custom directive that don't bleed into the main context.
- */
+     * the WrappedInternalContextAdapter is a simple wrapper around the InternalContextAdapter that allows us to
+     * effectively create local variables within each custom directive that don't bleed into the main context.
+     */
     class WrappedInternalContextAdapter implements InternalContextAdapter {
         private HashMap params = new HashMap();
         private InternalContextAdapter contextAdapter;

src/test/webwork.properties

 webwork.custom.properties=test,com/opensymphony/webwork/othertest
 
 # added the MockTag to the path of Tags that the TagDirective will search through
-webwork.velocity.tag.path = com.opensymphony.webwork.views.velocity.ui
+webwork.velocity.tag.path = com.opensymphony.webwork.views.velocity.ui, org.displaytag.tags

src/webapp/displaytag.vm

 }</style>
 </head>
 <body>
-#set( $list = ["a", "b", "c"] )
-$req.setAttribute("list", $list)
+#set( $action = $stack.findValue("new com.opensymphony.webwork.example.ui.SimpleAction()") )
+$req.setAttribute("list", $action.list)
 
 #tag( Table "name=list" )
+
+#bodytag( Table "name=list" )
+  #tag( Column "property=key" )
+  #tag( Column "property=value" )
+  #tag( Column "title=static value" "value=static" )
+#end
+
 </body>
 </html>
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="3" relativePaths="false">
+  <component name="ProjectRootManager" version="2">
+    <jdk name="java version &quot;1.4.2_01&quot;" />
+    <projectPath>
+      <root type="composite">
+        <root type="simple" url="file://$PROJECT_DIR$" />
+      </root>
+    </projectPath>
+    <sourcePath>
+      <root type="composite">
+        <root type="simple" url="file://$PROJECT_DIR$/config-browser/src" />
+        <root type="simple" url="file://$PROJECT_DIR$/misc/weblogic6.1/src/java" />
+        <root type="simple" url="file://$PROJECT_DIR$/src/example" />
+        <root type="simple" url="file://$PROJECT_DIR$/src/java" />
+        <root type="simple" url="file://$PROJECT_DIR$/src/migration" />
+        <root type="simple" url="file://$PROJECT_DIR$/src/test" />
+        <root type="jdk" rootType="sourcePath" name="java version &quot;1.4.2_01&quot;" />
+      </root>
+    </sourcePath>
+    <classPath>
+      <root type="composite">
+        <root type="output" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/commons-logging.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/mail.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/mockobjects-alt-jdk1.3-0.09dev.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/example/standard.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/example/displaytag-1.0-b1.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/commons-beanutils-1.5.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/mockobjects-core-0.09dev.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/pell-multipart.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/bsh-1.2b6.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/mockobjects-jdk1.3-j2ee1.3-0.09dev.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/ognl-2.6.3.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/velocity-dep-1.3.1.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/mockobjects-jdk1.3-0.09dev.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/example/jstl.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/servlet.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/oscore-2.2.1.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/cos-multipart.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/core/xwork-1.0-beta.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/commons-digester-1.3.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/junit-3.8.1.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/mockobjects-alt-jdk1.3-j2ee1.3-0.09dev.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/example/taglibs-benchmark.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/commons-collections-2.1.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/example/commons-collections-2.1.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/build/clover-1.2.2.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/itext-0.96.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/freemarker-2.3pre13.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/jakarta-poi-1.5.1-final-20020615.jar!/" />
+        <root type="simple" url="jar://$PROJECT_DIR$/lib/optional/jasperreports-0.5.0.jar!/" />
+        <root type="jdk" rootType="classPath" name="java version &quot;1.4.2_01&quot;" />
+        <root type="simple" url="jar://D:/opensource/jakarta-velocity-tools/dist/velocity-tools-1.1-dev.jar!/" />
+        <root type="simple" url="jar://D:/opensource/jakarta-velocity-tools/dist/velocity-tools-view-1.1-dev.jar!/" />
+      </root>
+    </classPath>
+    <excludePath>
+      <root type="composite">
+        <root type="excludedOutput" />
+      </root>
+    </excludePath>
+    <javadocPath>
+      <root type="composite">
+        <root type="jdk" rootType="javadocPath" name="java version &quot;1.4.2_01&quot;" />
+      </root>
+    </javadocPath>
+    <assert_keyword enabled="no" />
+    <exclude_output enabled="yes" />
+  </component>
+  <component name="CompilerConfiguration">
+    <option name="DEFAULT_COMPILER" value="Javac" />
+    <option name="SYNCHRONIZE_OUTPUT_DIRECTORY" value="false" />
+    <option name="DEFAULT_OUTPUT_PATH" value="$PROJECT_DIR$/src/webapp/WEB-INF/classes" />
+    <option name="OUTPUT_MODE" value="single" />
+    <resourceExtensions>
+      <entry name=".+\.(properties|xml|html)" />
+      <entry name=".+\.(gif|png|jpeg|jpg)" />
+    </resourceExtensions>
+  </component>
+  <component name="JavacSettings">
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="false" />
+    <option name="DEPRECATION" value="true" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+    <option name="MAXIMUM_HEAP_SIZE" value="128" />
+  </component>
+  <component name="JikesSettings">
+    <option name="JIKES_PATH" value="" />
+    <option name="DEBUGGING_INFO" value="true" />
+    <option name="DEPRECATION" value="true" />
+    <option name="GENERATE_NO_WARNINGS" value="false" />
+    <option name="GENERATE_MAKE_FILE_DEPENDENCIES" value="false" />
+    <option name="DO_FULL_DEPENDENCE_CHECK" value="false" />
+    <option name="IS_EMACS_ERRORS_MODE" value="true" />
+    <option name="ADDITIONAL_OPTIONS_STRING" value="" />
+  </component>
+  <component name="AntConfiguration">
+    <option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
+    <option name="FILTER_TARGETS" value="false" />
+  </component>
+  <component name="JavadocGenerationManager">
+    <option name="OUTPUT_DIRECTORY" />
+    <option name="OPTION_SCOPE" value="protected" />
+    <option name="OPTION_HIERARCHY" value="true" />
+    <option name="OPTION_NAVIGATOR" value="true" />
+    <option name="OPTION_INDEX" value="true" />
+    <option name="OPTION_SEPARATE_INDEX" value="true" />
+    <option name="OPTION_DOCUMENT_TAG_USE" value="false" />
+    <option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
+    <option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
+    <option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
+    <option name="OPTION_DEPRECATED_LIST" value="true" />
+    <option name="OTHER_OPTIONS" value="" />
+    <option name="HEAP_SIZE" />
+    <option name="OPEN_IN_BROWSER" value="true" />
+  </component>
+  <component name="WebManager">
+    <option enabled="false" />
+  </component>
+  <component name="WebRootContainer" />
+  <component name="EjbManager" enabled="false" />
+  <component name="JUnitProjectSettings">
+    <option name="TEST_RUNNER" value="UI" />
+  </component>
+  <component name="EntryPointsManager">
+    <entry_points />
+  </component>
+  <component name="EjbActionsConfiguration">
+    <option name="NEW_MESSAGE_BEAN_LAST_PACKAGE" value="" />
+    <option name="NEW_ENTITY_BEAN_LAST_PACKAGE" value="" />
+    <option name="NEW_SESSION_BEAN_LAST_PACKAGE" value="" />
+  </component>
+  <component name="CodeStyleManager">
+    <option name="USE_DEFAULT_CODE_STYLE_SCHEME" value="true" />
+    <option name="CODE_STYLE_SCHEME" value="" />
+  </component>
+  <component name="ExportToHTMLSettings">
+    <option name="PRINT_LINE_NUMBERS" value="false" />
+    <option name="OPEN_IN_BROWSER" value="false" />
+    <option name="OUTPUT_DIRECTORY" />
+  </component>
+</project>
+