You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jspwiki.apache.org by aj...@apache.org on 2008/09/15 16:21:35 UTC
svn commit: r695481 [2/2] - in
/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH: doc/
tests/com/ecyrd/jspwiki/ui/stripes/ tests/com/ecyrd/jspwiki/util/
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParser.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParser.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParser.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParser.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,726 @@
+package com.ecyrd.jspwiki.ui.stripes;
+
+import java.util.*;
+
+/**
+ * Parser that reads JSP document and constructs a {@link JspDocument} with the
+ * results.
+ */
+class JspParser
+{
+ private static final class Counter
+ {
+ private int m_pos;
+
+ Counter()
+ {
+ m_pos = 0;
+ }
+
+ public void increment()
+ {
+ m_pos++;
+ }
+
+ public int position()
+ {
+ return m_pos;
+ }
+ }
+
+ private enum NodeLifecycle
+ {
+ TAG_RESOLUTION,
+ /**
+ * Characters after the directive tag start (<) and whitespace, but
+ * before whitespace that delimit the attributes.
+ */
+ /**
+ * Characters after the opening left bracket (<), but before
+ * whitespace that delimit the attributes.
+ */
+ TAG_NAME,
+ /**
+ * After <@ that determines that it's a JSP element, but before we
+ * know for sure what it is.
+ */
+ JSP_DIRECTIVE_NAME,
+ /**
+ * Whitespace between the node name and the first attribute, and between
+ * attributes.
+ */
+ BETWEEN_ATTRIBUTES,
+ /**
+ * Characters that name an attribute, after whitespace but before the
+ * equals (=) character.
+ */
+ ATTRIBUTE_NAME,
+ /**
+ * When the current character is the equals (=) character that separates
+ * the attribute name and value.
+ */
+ ATTRIBUTE_EQUALS,
+ /**
+ * The opening quote, closing quote, and all characters in between, that
+ * denote an attribute's value.
+ */
+ ATTRIBUTE_VALUE,
+ /** Any outside of a tag or element (i.e., part of a text node). */
+ TEXT_NODE,
+ /** Any text inside of a scriptlet, JSP comment, or JSP declaration. */
+ CODE_OR_COMMENT,
+ }
+
+ /**
+ * Encapsulates the current state of document parsing.
+ */
+ private static class ParseContext
+ {
+ private Node m_node = null;
+
+ private Attribute m_attribute = null;
+
+ private Counter m_counter = null;;
+
+ private NodeLifecycle m_stage = NodeLifecycle.TEXT_NODE;
+
+ public ParseContext( Counter counter )
+ {
+ m_counter = counter;
+ }
+
+ private Map<NodeLifecycle,Integer> m_markers = new HashMap<NodeLifecycle,Integer>();
+
+ /**
+ * Sets a "marker" for the current stage (as reported by
+ * {@link #getStage()} at the current position (as reported by
+ * {@link #position()}. The marker can be retrieved later via
+ * {@link #getMarker(com.ecyrd.jspwiki.ui.stripes.JspParser.NodeLifecycle)}.
+ * Callers may place only one marker per lifecycle stage. Generally,
+ * markers are used to set character positions that are important to
+ * retrieve later, for example the position of the left angle-bracket
+ * during the {@link NodeLifecycle#TAG_RESOLUTION} stage.
+ */
+ public void mark()
+ {
+ m_markers.put( getStage(), position() );
+ }
+
+ /**
+ * Retrieves the position of the marker set for the current stage (as set by {@link #mark()}).
+ * If no marker was set, this method returns {@link Node#POSITION_NOT_SET}.
+ * @param stage the stage for which the marker position is desired
+ * @return the position of the marker.
+ */
+ public int getMarker( NodeLifecycle stage )
+ {
+ Integer mark = m_markers.get( stage );
+ return mark == null ? Node.POSITION_NOT_SET : mark.intValue();
+ }
+
+ public Attribute getAttribute()
+ {
+ return m_attribute;
+ }
+
+ public Counter getCounter()
+ {
+ return m_counter;
+ }
+
+ public Node getNode()
+ {
+ return m_node;
+ }
+
+ public NodeLifecycle getStage()
+ {
+ return m_stage;
+ }
+
+ public void incrementPosition()
+ {
+ m_counter.increment();
+ }
+
+ public int position()
+ {
+ return m_counter.position();
+ }
+
+ public void setAttribute( Attribute attribute )
+ {
+ m_attribute = attribute;
+ }
+
+ public void setNode( Node node )
+ {
+ m_node = node;
+ }
+
+ public void setStage( NodeLifecycle stage )
+ {
+ m_stage = stage;
+ }
+ }
+
+ private final List<Integer> lineBreaks = new ArrayList<Integer>();
+
+ private JspDocument doc = null;
+
+ protected Stack<ParseContext> contextStack = new Stack<ParseContext>();
+
+ private Stack<Node> nodeStack = new Stack<Node>();
+
+ private String m_source;
+
+ /** The current parsing context. */
+ private ParseContext context;
+
+ /**
+ * Constructs a new JspDocument.
+ */
+ public JspParser()
+ {
+ super();
+ }
+
+ /**
+ * Parses a JSP file, supplied as a String, into Nodes.
+ *
+ * @param m_source the JSP file contents
+ */
+ public JspDocument parse( String source )
+ {
+ // Initialize the cached document, m_source, and stack variables
+ this.doc = new JspDocument();
+ m_source = source;
+ contextStack.clear();
+ nodeStack.clear();
+ nodeStack.push( doc.getRoot() );
+
+ // Create new parse context and put it on the stack
+ context = new ParseContext( new Counter() );
+ initText( context.position() );
+
+ // Initialize parser delegates
+ ParserDelegate textParser = new TextParser();
+
+ // Parse the file, character by character
+ for( char currentChar : source.toCharArray() )
+ {
+ // Is the current character whitespace?
+ boolean isWhitespace = Character.isWhitespace( currentChar );
+ char ch = isWhitespace ? ' ' : currentChar; // For case statements
+ int pos = context.position();
+
+ switch( context.getStage() )
+ {
+ // Part of a text node.
+ case TEXT_NODE: {
+ textParser.handle( ch, context );
+ switch( ch )
+ {
+ // If we see a quote, check to see if it's a part of a
+ // parent attribute
+ case ('\''):
+ case ('"'): {
+ if( contextStack.size() > 0 )
+ {
+ Attribute parentAttribute = contextStack.peek().getAttribute();
+ if( parentAttribute != null && ch == parentAttribute.getAttributeDelimiter() )
+ {
+ // Finish the current text node and attach
+ // it to the parent attribute
+ finalizeText();
+
+ // Restore the parent ParseContext and Node
+ context = contextStack.pop();
+ nodeStack.pop();
+
+ // Finish the parent attribute
+ finalizeAttribute();
+ }
+ }
+ break;
+ }
+ case ('<'): {
+ // Finalize current node and start a new
+ // (unresolved) one
+ finalizeText();
+ initTag( NodeType.UNRESOLVED, context.position() );
+ context.setStage( NodeLifecycle.TAG_RESOLUTION );
+ break;
+ }
+ }
+ break;
+ }
+
+ case TAG_RESOLUTION: {
+ Node node = context.getNode();
+ switch( node.getType() )
+ {
+
+ case UNRESOLVED: {
+ switch( ch )
+ {
+ // If <%, it's a JSP element
+ case ('%'): {
+ // Re-initialize the node as a JSPMarkup
+ // node
+ initJspMarkup();
+ break;
+ }
+
+ // If </, it's an HTML end tag
+ case ('/'): {
+ // Re-initialize the node as an end tag
+ initTag( NodeType.HTML_END_TAG, node.getStart() );
+ context.setStage( NodeLifecycle.TAG_NAME );
+ break;
+ }
+
+ // If < plus space, it's just ordinary
+ // (albeit sloppy) markup
+ case (' '): {
+ // Re-initialize the node as a text node
+ initText( node.getStart() );
+ context.setStage( NodeLifecycle.TEXT_NODE );
+ break;
+ }
+
+ // Any other char means its HTML start tag
+ // or combined tag
+ default: {
+ node.setType( NodeType.UNRESOLVED_HTML_TAG );
+ context.setStage( NodeLifecycle.TAG_NAME );
+ }
+ }
+ break;
+ }
+
+ // If JSP element, next character narrows it down
+ case UNRESOLVED_JSP_TAG: {
+ switch( ch )
+ {
+ // Dash after <% means hidden JSP
+ // comment
+ case ('-'): {
+ node.setType( NodeType.JSP_COMMENT );
+ context.setStage( NodeLifecycle.CODE_OR_COMMENT );
+ break;
+ }
+
+ // Bang after <% means JSP
+ // declaration
+ case ('!'): {
+ node.setType( NodeType.JSP_DECLARATION );
+ context.setStage( NodeLifecycle.CODE_OR_COMMENT );
+ break;
+ }
+
+ // Equals after <% means JSP
+ // expression
+ case ('='): {
+ node.setType( NodeType.JSP_EXPRESSION );
+ context.setStage( NodeLifecycle.CODE_OR_COMMENT );
+ break;
+ }
+
+ // At-sign after <% means JSP
+ // directive
+ case ('@'): {
+ // Re-initialize the node as a JspDirective
+ initJspDirective();
+ context.setStage( NodeLifecycle.BETWEEN_ATTRIBUTES );
+ break;
+ }
+
+ // Whitespace after <% means
+ // scriptlet
+ case (' '): {
+ node.setType( NodeType.SCRIPTLET );
+ context.setStage( NodeLifecycle.CODE_OR_COMMENT );
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ case CODE_OR_COMMENT: {
+ switch( ch )
+ {
+ // Terminating %> means the end of the scriptlet
+ case ('>'): {
+ if( source.charAt( pos - 1 ) == '%' )
+ {
+ finalizeJspMarkup();
+ initText( pos + 1 );
+ }
+ break;
+ }
+ }
+ break;
+ }
+
+ // Characters that supply the JSP directive name.
+ case JSP_DIRECTIVE_NAME: {
+ if( isWhitespace )
+ {
+ Node node = context.getNode();
+ Attribute directive = context.getAttribute();
+ node.setName( m_source.substring( directive.getStart(), context.position() ) );
+ context.setAttribute( null );
+ context.setStage( NodeLifecycle.BETWEEN_ATTRIBUTES );
+ }
+ break;
+ }
+
+ // After < but before whitespace that delimit attributes.
+ case TAG_NAME: {
+ switch( ch )
+ {
+ // If current character is whitespace, set the name and
+ // move
+ // to attributes stage
+ case (' '): {
+ finalizeTagName();
+ context.setStage( NodeLifecycle.BETWEEN_ATTRIBUTES );
+ break;
+ }
+
+ // Right angle bracket == end of the node
+ case ('>'): {
+ finalizeTagName();
+ finalizeNode( pos + 1 );
+ initText( pos + 1 );
+ break;
+ }
+ }
+ break;
+ }
+
+ // Whitespace between node name and first attribute, or
+ // between attributes.
+ case BETWEEN_ATTRIBUTES: {
+ switch( ch )
+ {
+ case (' '): {
+ break;
+ }
+ case ('/'): {
+ // Ignore the / because we might be in HTML
+ // combined tag
+ break;
+ }
+ case ('%'): {
+ // Ignore the % because we might be in a JSP
+ // directive/element
+ break;
+ }
+ case ('>'): {
+ finalizeNode( pos + 1 );
+ initText( pos + 1 );
+ break;
+ }
+ default:
+ initAttribute();
+ }
+ break;
+ }
+
+ // Characters that name an attribute, after whitespace but
+ // before equals (=).
+ case ATTRIBUTE_NAME: {
+ if( ch == '=' )
+ {
+ Attribute attribute = context.getAttribute();
+ attribute.setName( m_source.substring( attribute.getStart(), pos ) );
+ context.setStage( NodeLifecycle.ATTRIBUTE_EQUALS );
+ }
+ break;
+ }
+
+ // The equals (=) that separates the attribute name and
+ // value.
+ case ATTRIBUTE_EQUALS: {
+ if( ch == '\'' || ch == '\"' )
+ {
+ // Save the quote delimiter for later
+ Attribute attribute = context.getAttribute();
+ attribute.setAttributeDelimiter( ch );
+
+ // Push current ParseContext and Node onto stack
+ contextStack.push( context );
+ nodeStack.push( attribute );
+
+ // Create new context, with text node as child of
+ // attribute
+ context = new ParseContext( context.getCounter() );
+ initText( context.position() + 1 );
+ context.getNode().setParent( attribute );
+ }
+ break;
+ }
+
+ }
+
+ // Reset the line/column counters if we encounter linebreaks
+ if( currentChar == '\r' || currentChar == '\n' )
+ {
+ lineBreaks.add( pos );
+ }
+
+ // Increment the character position
+ context.incrementPosition();
+ }
+
+ // Finalize the last node and return the parsed JSP
+ finalizeNode( context.position() );
+ return doc;
+ }
+
+ private void finalizeJspMarkup()
+ {
+ Node node = context.getNode();
+ NodeType type = node.getType();
+
+ // Set the end position
+ node.setEnd( context.position() + 1 );
+
+ node.setValue( m_source
+ .substring( node.getStart() + type.getTagStart().length(), node.getEnd() - type.getTagEnd().length() ) );
+
+ // If node length is > 0, add it to the parent
+ if( node.getEnd() > node.getStart() )
+ {
+ node.getParent().addChild( node );
+ }
+ }
+
+ private void finalizeAttribute()
+ {
+ Attribute attribute = context.getAttribute();
+ Node node = attribute.getParent();
+ attribute.setEnd( context.position() + 1 );
+ if( node.isHtmlNode() )
+ {
+ ((Tag) node).addAttribute( attribute );
+ }
+ else if( node.getType() == NodeType.JSP_DIRECTIVE )
+ {
+ ((JspDirective) node).addAttribute( attribute );
+ }
+ context.setAttribute( null );
+ context.setStage( NodeLifecycle.BETWEEN_ATTRIBUTES );
+ }
+
+ private void finalizeText()
+ {
+ Node node = context.getNode();
+
+ // Set the end position
+ node.setEnd( context.position() );
+
+ node.setValue( m_source.substring( node.getStart(), node.getEnd() ) );
+
+ // If node length is > 0, add it to the parent
+ if( node.getEnd() > node.getStart() )
+ {
+ node.getParent().addChild( node );
+ }
+ }
+
+ /**
+ * Finalizes the current Tag (returned by {@link ParseContext#getNode()}),
+ * adds it as a child to the parent node, and initializes a new {@link Text}
+ * node that will begin at a specified character position. The parent node
+ * is determined by taking the Node currently at the top of the internal
+ * node stack.
+ *
+ * @param pos the desired start position for the new text node
+ */
+ private void finalizeNode( int pos )
+ {
+ Node node = context.getNode();
+ NodeType type = node.getType();
+
+ // Set the end position
+ node.setEnd( pos );
+
+ // Finalize the node type if it is still undefined
+ if( type == NodeType.UNRESOLVED_HTML_TAG )
+ {
+ char lastCh = m_source.charAt( pos - 2 );
+ if( lastCh == '/' )
+ {
+ node.setType( NodeType.HTML_COMBINED_TAG );
+ }
+ else
+ {
+ // If no /, it's an HTML start tag, and new nodes should be
+ // children of it
+ node.setType( NodeType.HTML_START_TAG );
+ nodeStack.push( node );
+ }
+ }
+ else if( type == NodeType.TEXT )
+ {
+ node.setValue( m_source.substring( node.getStart(), node.getEnd() ) );
+ }
+ else if( node.isJspNode() )
+ {
+ node.setValue( m_source.substring( node.getStart() + type.getTagStart().length(), node.getEnd()
+ - type.getTagEnd().length() ) );
+ }
+
+ // If node length is > 0, add it to the parent
+ if( node.getEnd() > node.getStart() )
+ {
+ node.getParent().addChild( node );
+ }
+ }
+
+ private void finalizeTagName()
+ {
+ Node node = context.getNode();
+ int nameStart = node.getStart() + node.getType().getTagStart().length();
+ int pos = context.position();
+ if( pos - nameStart > 0 )
+ {
+ node.setName( m_source.substring( nameStart, pos ) );
+ }
+ }
+
+ private void initAttribute()
+ {
+ Attribute attribute = new Attribute( doc );
+ attribute.setParent( context.getNode() );
+ context.setAttribute( attribute );
+
+ // Set the start, end, linebreak
+ updatePosition( attribute, context.position() );
+
+ // Set the correct lifecycle stage
+ Node node = context.getNode();
+ if( node.getType() == NodeType.JSP_DIRECTIVE && node.getName() == null )
+ {
+ context.setStage( NodeLifecycle.JSP_DIRECTIVE_NAME );
+ }
+ else
+ {
+ context.setStage( NodeLifecycle.ATTRIBUTE_NAME );
+ }
+ }
+
+ /**
+ * Sets the start, end and line/column positions for a supplied node, based
+ * on the position in the ParseContext.
+ *
+ * @param node the node to set
+ */
+ private void updatePosition( Node node, int pos )
+ {
+ // Set the start, end, linebreak
+ node.setStart( pos );
+ int lastLineBreakPos = lineBreaks.size() == 0 ? Node.POSITION_NOT_SET : lineBreaks.get( lineBreaks.size() - 1 );
+ node.setLine( lineBreaks.size() + 1 );
+ node.setColumn( pos - lastLineBreakPos );
+ }
+
+ /**
+ * Factory method that returns a new JspDirective node.
+ */
+ private void initJspDirective()
+ {
+ // Create new JspDirective
+ JspDirective node = new JspDirective( doc );
+
+ // Set parent relationship
+ node.setParent( nodeStack.peek() );
+ context.setNode( node );
+ context.setAttribute( null );
+
+ // Set the start, end, linebreak
+ updatePosition( node, context.position() - 2 );
+ }
+
+ /**
+ * Factory method that returns a new JspMarkup node.
+ */
+ private void initJspMarkup()
+ {
+ // Create new JspMarkup
+ JspMarkup node = new JspMarkup( doc, NodeType.UNRESOLVED_JSP_TAG );
+
+ // Set parent relationship
+ node.setParent( nodeStack.peek() );
+ context.setNode( node );
+ context.setAttribute( null );
+
+ // Set the start, end, linebreak
+ updatePosition( node, context.position() - 1 );
+ }
+
+ /**
+ * Factory method that constructs and returns a new Tag. When constructed,
+ * the node's start position, line number, column number and level are set
+ * automatically based on JspDocument's internal cache of line-breaks and
+ * nodes. Note that the new node is not actually added to the internal node
+ * tree until the method {@link #finalizeNode(Node, int)} is called.
+ *
+ * @param type the node type
+ * @param pos the start position for the tag
+ */
+ private void initTag( NodeType type, int pos )
+ {
+ // Create new Tag
+ Tag tag = new Tag( doc, type );
+
+ // If HTML end tag, pop the node stack first
+ if( tag.getType() == NodeType.HTML_END_TAG )
+ {
+ nodeStack.pop();
+ }
+
+ // Set parent relationship
+ tag.setParent( nodeStack.peek() );
+ context.setNode( tag );
+ context.setAttribute( null );
+
+ // Set the start, end, linebreak
+ updatePosition( tag, pos );
+ }
+
+ private void initText( int pos )
+ {
+ // Create new Text
+ Text text = new Text( doc );
+
+ // Set parent relationship
+ text.setParent( nodeStack.peek() );
+ context.setNode( text );
+ context.setAttribute( null );
+
+ // Set the start, end, linebreak
+ updatePosition( text, pos );
+ context.setStage( NodeLifecycle.TEXT_NODE );
+ }
+
+ public static abstract class ParserDelegate
+ {
+ public abstract void handle( char ch, ParseContext context );
+ }
+
+ public static class TextParser extends ParserDelegate
+ {
+ public void handle( char ch, ParseContext context )
+ {
+ }
+
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParserTest.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParserTest.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParserTest.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspParserTest.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,499 @@
+package com.ecyrd.jspwiki.ui.stripes;
+
+import java.io.File;
+import java.util.List;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+
+public class JspParserTest extends TestCase
+{
+ public JspParserTest( String s )
+ {
+ super( s );
+ }
+
+ public void testParse() throws Exception
+ {
+ JspMigrator m = new JspMigrator();
+ File src = new File( "src/webdocs/LoginForm.jsp" );
+ String s = m.readSource( src );
+
+ // Parse the contents of the file
+ JspParser parser = new JspParser();
+ JspDocument doc = parser.parse( s );
+
+ // Should result in 18 nodes parsed (10 tags/directives + 8 text/whitespace nodes
+ Node node;
+ Node attribute;
+ List<Node> nodes = doc.getNodes();
+ assertEquals( 18, nodes.size() );
+ int i = 0;
+
+ // Test line 1 aka nodes 0+1
+ node = nodes.get( i );
+ assertEquals( 1, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 0, node.getStart() );
+ assertEquals( 39, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.JSP_DIRECTIVE, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "page", node.getName() );
+ assertEquals( 1, ((JspDirective)node).getAttributes().size() );
+ attribute = ((JspDirective)node).getAttributes().get( 0 );
+ assertEquals( "import", attribute.getName() );
+ assertEquals( "org.apache.log4j.*", attribute.getValue() );
+ i++;
+ node = nodes.get( i );
+ assertEquals( 1, node.getLine() );
+ assertEquals( 40, node.getColumn() );
+ assertEquals( 39, node.getStart() );
+ assertEquals( 40, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test line 2 aka nodes 2+3
+ node = nodes.get( i );
+ assertEquals( 2, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 40, node.getStart() );
+ assertEquals( 80, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.JSP_DIRECTIVE, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "page", node.getName() );
+ assertEquals( 1, ((JspDirective)node).getAttributes().size() );
+ attribute = ((JspDirective)node).getAttributes().get( 0 );
+ assertEquals( "import", attribute.getName() );
+ assertEquals( "com.ecyrd.jspwiki.*", attribute.getValue() );
+ i++;
+ node = nodes.get( i );
+ assertEquals( 2, node.getLine() );
+ assertEquals( 41, node.getColumn() );
+ assertEquals( 80, node.getStart() );
+ assertEquals( 81, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test line 3 aka nodes 4+5
+ node = nodes.get( i );
+ assertEquals( 3, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 81, node.getStart() );
+ assertEquals( 128, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.JSP_DIRECTIVE, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "page", node.getName() );
+ assertEquals( 1, ((JspDirective)node).getAttributes().size() );
+ attribute = ((JspDirective)node).getAttributes().get( 0 );
+ assertEquals( "import", attribute.getName() );
+ assertEquals( "com.ecyrd.jspwiki.action.*", attribute.getValue() );
+ i++;
+ node = nodes.get( i );
+ assertEquals( 3, node.getLine() );
+ assertEquals( 48, node.getColumn() );
+ assertEquals( 128, node.getStart() );
+ assertEquals( 129, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test line 4 aka nodes 6+7
+ node = nodes.get( i );
+ assertEquals( 4, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 129, node.getStart() );
+ assertEquals( 163, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.JSP_DIRECTIVE, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "page", node.getName() );
+ assertEquals( 1, ((JspDirective)node).getAttributes().size() );
+ attribute = ((JspDirective)node).getAttributes().get( 0 );
+ assertEquals( "errorPage", attribute.getName() );
+ assertEquals( "/Error.jsp", attribute.getValue() );
+ i++;
+ node = nodes.get( i );
+ assertEquals( 4, node.getLine() );
+ assertEquals( 35, node.getColumn() );
+ assertEquals( 163, node.getStart() );
+ assertEquals( 164, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test line 5 aka nodes 8+9
+ node = nodes.get( i );
+ assertEquals( 5, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 164, node.getStart() );
+ assertEquals( 218, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.JSP_DIRECTIVE, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "taglib", node.getName() );
+ assertEquals( 2, ((JspDirective)node).getAttributes().size() );
+ attribute = ((JspDirective)node).getAttributes().get( 0 );
+ assertEquals( "uri", attribute.getName() );
+ assertEquals( "/WEB-INF/jspwiki.tld", attribute.getValue() );
+ attribute = ((JspDirective)node).getAttributes().get( 1 );
+ assertEquals( "prefix", attribute.getName() );
+ assertEquals( "wiki", attribute.getValue() );
+ i++;
+ node = nodes.get( i );
+ assertEquals( 5, node.getLine() );
+ assertEquals( 55, node.getColumn() );
+ assertEquals( 218, node.getStart() );
+ assertEquals( 219, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test line 6 aka nodes 10+11
+ node = nodes.get( i );
+ assertEquals( 6, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 219, node.getStart() );
+ assertEquals( 276, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.JSP_DIRECTIVE, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "taglib", node.getName() );
+ assertEquals( 2, ((JspDirective)node).getAttributes().size() );
+ attribute = ((JspDirective)node).getAttributes().get( 0 );
+ assertEquals( "uri", attribute.getName() );
+ assertEquals( "/WEB-INF/stripes.tld", attribute.getValue() );
+ attribute = ((JspDirective)node).getAttributes().get( 1 );
+ assertEquals( "prefix", attribute.getName() );
+ assertEquals( "stripes", attribute.getValue() );
+ i++;
+ node = nodes.get( i );
+ assertEquals( 6, node.getLine() );
+ assertEquals( 58, node.getColumn() );
+ assertEquals( 276, node.getStart() );
+ assertEquals( 277, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test line 7 aka nodes 12+13
+ node = nodes.get( i );
+ assertEquals( 7, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 277, node.getStart() );
+ assertEquals( 354, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.HTML_COMBINED_TAG, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "stripes:useActionBean", node.getName() );
+
+ // AbstractNode 12 should have 1 attribute: beanclass="com.ecyrd.jspwiki.action.LoginActionBean"
+ assertEquals( 1, ((Tag)node).getAttributes().size() );
+ attribute = ((Tag)node).getAttributes().get( 0 );
+ assertEquals( "beanclass", attribute.getName() );
+ assertEquals ( NodeType.ATTRIBUTE, attribute.getType());
+ assertEquals( "com.ecyrd.jspwiki.action.LoginActionBean", attribute.getValue() );
+ assertEquals( 'c', ((Tag)node).getAttributes().get( 0 ).getValue().charAt( 0 ) );
+ i++;
+
+ // Test line 7, node 13 (line break)
+ node = nodes.get( i );
+ assertEquals( 7, node.getLine() );
+ assertEquals( 78, node.getColumn() );
+ assertEquals( 354, node.getStart() );
+ assertEquals( 355, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test lines 8-19 aka nodes 14+15
+ node = nodes.get( i );
+ assertEquals( 8, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 355, node.getStart() );
+ assertEquals( 767, node.getEnd() );
+ assertEquals( NodeType.JSP_DECLARATION, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( null, node.getName() );
+ i++;
+ node = nodes.get( i );
+ assertEquals( 19, node.getLine() );
+ assertEquals( 3, node.getColumn() );
+ assertEquals( 767, node.getStart() );
+ assertEquals( 768, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "(TEXT)", node.getName() );
+ i++;
+
+ // Test line 20-33 aka node 16
+ node = nodes.get( i );
+ assertEquals( 20, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 768, node.getStart() );
+ assertEquals( 1513, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.SCRIPTLET, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( null, node.getName() );
+ i++;
+
+ // Test second tag on line 33 aka node 17
+ node = nodes.get( i );
+ assertEquals( 33, node.getLine() );
+ assertEquals( 3, node.getColumn() );
+ assertEquals( 1513, node.getStart() );
+ assertEquals( 1553, node.getEnd() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( NodeType.HTML_COMBINED_TAG, node.getType() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 17, node.getSiblings().size() );
+ assertEquals( "wiki:Include", node.getName() );
+
+ // AbstractNode 17 should have 1 attribute: page="<%=contentPage%>"
+ assertEquals( 1, ((Tag)node).getAttributes().size() );
+ attribute = ((Tag)node).getAttributes().get( 0 );
+ assertEquals( "page", attribute.getName() );
+ assertEquals ( NodeType.ATTRIBUTE, attribute.getType());
+ assertEquals( "<%=contentPage%>", attribute.getValue() );
+ assertEquals( 1, attribute.getChildren().size() );
+ assertEquals ( NodeType.JSP_EXPRESSION, attribute.getChildren().get( 0 ).getType() );
+ assertEquals ( "contentPage", attribute.getChildren().get( 0 ).getValue() );
+ i++;
+ }
+
+ public void testParseNestedTags() {
+ String s= " <foo attribute1=\"1\"> <bar attribute2=\"2\" attribute3=\"3\"/> </foo> ";
+ JspDocument doc = new JspParser().parse( s );
+
+ // Total number of nodes (depth-first search) is 7
+ List<Node> nodes = doc.getNodes();
+ Node node;
+ Node attribute;
+ assertEquals( 7, nodes.size());
+
+ // First, check the root node. Should have 4 children (2 text nodes + 2 html nodes)
+ node = doc.getRoot();
+ assertEquals( 4, node.getChildren().size() );
+
+ // AbstractNode 0 is whitespace
+ node = nodes.get( 0 );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( "(TEXT)", node.getName() );
+ assertEquals( " ", node.getValue() );
+ assertEquals( doc.getRoot(), node.getParent() );
+ assertEquals( 0, node.getStart() );
+ assertEquals( 2, node.getEnd() );
+
+ // AbstractNode 1 is <foo> with 1 attribute
+ node = nodes.get( 1 );
+ assertEquals( NodeType.HTML_START_TAG, node.getType() );
+ assertEquals( "<foo attribute1=\"1\">", node.toString() );
+ assertEquals( "foo", node.getName() );
+ assertEquals( " <bar attribute2=\"2\" attribute3=\"3\"/> ", node.getValue() );
+ assertEquals( 2, node.getStart() );
+ assertEquals( 22, node.getEnd() );
+
+ // AbstractNode 1: attributes test
+ assertEquals( 1, ((Tag)node).getAttributes().size() );
+ attribute = ((Tag)node).getAttributes().get( 0 );
+ assertEquals( "attribute1", attribute.getName() );
+ assertEquals( "1", attribute.getValue() );
+ assertEquals( 7, attribute.getStart() );
+ assertEquals( 21, attribute.getEnd() );
+
+ // AbstractNode 1 also has 3 child elements: <bar> plus two whitespace nodes
+ assertEquals( 3, node.getChildren().size() );
+
+ // Check AbstractNode 1, child 0 -- should be whitespace
+ node = nodes.get( 1 ).getChildren().get( 0 );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( "(TEXT)", node.getName() );
+ assertEquals( " ", node.getValue() );
+ assertEquals( nodes.get( 1 ), node.getParent() );
+ assertEquals( 22, node.getStart() );
+ assertEquals( 24, node.getEnd() );
+
+ // Check AbstractNode 1, child 1 -- should be <bar>
+ node = nodes.get( 1 ).getChildren().get( 1 );
+ assertEquals( NodeType.HTML_COMBINED_TAG, node.getType() );
+ assertEquals( "<bar attribute2=\"2\" attribute3=\"3\"/>", node.toString() );
+ assertEquals( "bar", node.getName() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( 24, node.getStart() );
+ assertEquals( 60, node.getEnd() );
+ assertEquals( 2, ((Tag)node).getAttributes().size() );
+ assertEquals( "attribute2", ((Tag)node).getAttributes().get( 0 ).getName() );
+ assertEquals( "2", ((Tag)node).getAttributes().get( 0 ).getValue() );
+ assertEquals( "attribute3", ((Tag)node).getAttributes().get( 1 ).getName() );
+ assertEquals( "3", ((Tag)node).getAttributes().get( 1 ).getValue() );
+
+ // Check AbstractNode 1, child 2 -- should be whitespace
+ node = nodes.get( 1 ).getChildren().get( 2 );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( "(TEXT)", node.getName() );
+ assertEquals( " ", node.getValue() );
+ assertEquals( nodes.get( 1 ), node.getParent() );
+ assertEquals( 60, node.getStart() );
+ assertEquals( 62, node.getEnd() );
+
+ // AbstractNode 5 (</foo) has no attributes
+ node = nodes.get( 5 );
+ assertEquals( NodeType.HTML_END_TAG, node.getType() );
+ assertEquals( null, node.getValue() );
+ assertEquals( "foo", node.getName() );
+ assertEquals( 0, ((Tag)node).getAttributes().size() );
+ assertEquals( 0, node.getChildren().size() );
+ assertEquals( 62, node.getStart() );
+ assertEquals( 68, node.getEnd() );
+
+ // AbstractNode 6 is whitespace
+ node = nodes.get( 6 );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( "(TEXT)", node.getName() );
+ assertEquals( " ", node.getValue() );
+ assertEquals( doc.getRoot(), node.getParent() );
+ assertEquals( 68, node.getStart() );
+ assertEquals( 70, node.getEnd() );
+
+ // The children of AbstractNode 1 == Nodes 2, 3 and 4 from doc.getNodes()
+ node = nodes.get( 1 );
+ assertEquals( nodes.get( 2 ), node.getChildren().get( 0 ) );
+ assertEquals( nodes.get( 3 ), node.getChildren().get( 1 ) );
+ assertEquals( nodes.get( 4 ), node.getChildren().get( 2 ) );
+
+ }
+
+ public void testParseNestedExpression()
+ {
+ String s = " <wiki:Include page=\"<%=contentPage%>\" var=\'Foo\' /> ";
+ JspDocument doc = new JspParser().parse( s );
+
+ List<Node> nodes = doc.getNodes();
+ Node node;
+ assertEquals( 3, nodes.size());
+
+ // AbstractNode 1: text node
+ node = nodes.get( 0 );
+ assertEquals( 1, node.getLine() );
+ assertEquals( 1, node.getColumn() );
+ assertEquals( 0, node.getStart() );
+ assertEquals( 2, node.getEnd() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( " ", node.getValue() );
+ assertEquals( "(TEXT)", node.getName() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 2, node.getSiblings().size() );
+ assertEquals( 0, node.getChildren().size() );
+
+ // AbstractNode 2: HTML tag with attribute containing JSP expression
+ node = nodes.get( 1 );
+ assertEquals( 1, node.getLine() );
+ assertEquals( 3, node.getColumn() );
+ assertEquals( 2, node.getStart() );
+ assertEquals( 52, node.getEnd() );
+ assertEquals( NodeType.HTML_COMBINED_TAG, node.getType() );
+ assertEquals( "<wiki:Include page=\"<%=contentPage%>\" var=\'Foo\'/>", node.toString() );
+ assertEquals( "wiki:Include", node.getName() );
+ assertEquals( null, node.getValue() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 2, node.getSiblings().size() );
+ assertEquals( 0, node.getChildren().size() );
+
+ // AbstractNode 2: test attributes
+ assertEquals( 2, ((Tag)node).getAttributes().size() );
+ Node attribute;
+ attribute = ((Tag)node).getAttributes().get( 0 );
+ assertEquals( NodeType.ATTRIBUTE, attribute.getType() );
+ assertEquals( "page", attribute.getName() );
+ assertEquals( "<%=contentPage%>", attribute.getValue() );
+ assertEquals( 1, attribute.getChildren().size() );
+ assertEquals( NodeType.JSP_EXPRESSION, attribute.getChildren().get( 0 ).getType() );
+ assertEquals( "contentPage", attribute.getChildren().get( 0 ).getValue() );
+
+ attribute = ((Tag)node).getAttributes().get( 1 );
+ assertEquals( NodeType.ATTRIBUTE, attribute.getType() );
+ assertEquals( "var", attribute.getName() );
+ assertEquals( "Foo", attribute.getValue() );
+ assertEquals( 1, attribute.getChildren().size() );
+ assertEquals( NodeType.TEXT, attribute.getChildren().get( 0 ).getType() );
+ assertEquals( "Foo", attribute.getChildren().get( 0 ).getValue() );
+
+ // AbstractNode 3: text
+ node = nodes.get( 2 );
+ assertEquals( 1, node.getLine() );
+ assertEquals( 53, node.getColumn() );
+ assertEquals( 52, node.getStart() );
+ assertEquals( 54, node.getEnd() );
+ assertEquals( NodeType.TEXT, node.getType() );
+ assertEquals( " ", node.getValue() );
+ assertEquals( "(TEXT)", node.getName() );
+ assertEquals( NodeType.ROOT, node.getParent().getType() );
+ assertEquals( 1, node.getLevel() );
+ assertEquals( 2, node.getSiblings().size() );
+ assertEquals( 0, node.getChildren().size() );
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite( JspParserTest.class );
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspTransformer.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspTransformer.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspTransformer.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/JspTransformer.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,19 @@
+package com.ecyrd.jspwiki.ui.stripes;
+
+import java.util.Map;
+
+/**
+ * Strategy interface for transforming JSPs.
+ */
+public interface JspTransformer
+{
+ /**
+ * Executes the transformation on the JSP and returns the result.
+ *
+ * @param sharedState a map containing key/value pairs that represent any
+ * shared-state information that this method might need during
+ * transformation.
+ * @param doc the JSP to transform.
+ */
+ public void transform( Map<String, Object> sharedState, JspDocument doc );
+}
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Node.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Node.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Node.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Node.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,150 @@
+package com.ecyrd.jspwiki.ui.stripes;
+
+import java.util.List;
+
+public interface Node
+{
+
+ public static final int POSITION_NOT_SET = -1;
+
+ /**
+ * Returns the JspDocument the Node belongs to.
+ * @return the document
+ */
+ public abstract JspDocument getJspDocument();
+
+ /**
+ * Adds a child to the current AbstractNode. If the AbstractNode is of type
+ * {@link NodeType#HTML_COMBINED_TAG}, the tag will be split into two nodes
+ * (start tag and end tag), with the child AbstractNode inserted between the two.
+ *
+ * @param node the node to insert
+ * @param value the node to insert in between the split nodes
+ * @throws IllegalArgumentException if the supplied node to split is not of
+ * type {@link NodeType#HTML_START_TAG},
+ * {@link NodeType#HTML_START_TAG} or
+ * {@link NodeType#HTML_COMBINED_TAG}
+ * @throws IllegalStateException if the current AbstractNode must be split, and does
+ * not have a parent.
+ */
+ public abstract void addChild( Node node );
+
+ /**
+ * Returns the child nodes of this node, as a defensive copy of the
+ * internally-cached list.
+ *
+ * @return the children
+ */
+ public abstract List<Node> getChildren();
+
+ /**
+ * Returns the column the node starts on, relative to the beginning of the
+ * line in the source text.
+ *
+ * @return the column
+ */
+ public abstract int getColumn();
+
+ /**
+ * Returns the exnding character position of the node, exclusive, relative
+ * to the beginning of the source text.
+ *
+ * @return the end position
+ */
+ public abstract int getEnd();
+
+ /**
+ * Returns the "level" of the tag; that is, how far from the top-level nodes
+ * (which are level 1). If the parent of this node is not set, this method
+ * returns -1.
+ *
+ * @return
+ */
+ public abstract int getLevel();
+
+ /**
+ * Returns the line of the source text the node starts on.
+ *
+ * @return the line
+ */
+ public abstract int getLine();
+
+ /**
+ * Returns the m_name of the tag, if the node is an HTML start, end, or
+ * combined tag, or the directive m_name if a JSP directive;
+ * <code>null</code> otherwise.
+ *
+ * @return the tag m_name
+ */
+ public abstract String getName();
+
+ /**
+ * Returns the parent of this node, which may be null if a top-level node.
+ *
+ * @return the parent
+ */
+ public abstract Node getParent();
+
+ /**
+ * Returns the siblings of this node.
+ *
+ * @return the siblings
+ */
+ public abstract List<Node> getSiblings();
+
+ /**
+ * Returns the starting character position of the node, inclusive, relative
+ * to the beginning of the source text.
+ *
+ * @return the start position
+ */
+ public abstract int getStart();
+
+ /**
+ * Returns the type of the node.
+ *
+ * @return the type
+ */
+ public abstract NodeType getType();
+
+ /**
+ * Returns the value of the node, which will be all characters between
+ * a matched pair of start and end tags (for Tags), all characters between
+ * matching quotes (for Attributes), or text characters (for Texts).
+ *
+ * @return the value
+ */
+ public abstract String getValue();
+
+ public abstract boolean isHtmlNode();
+
+ public abstract boolean isJspNode();
+
+ public abstract void removeChild( Node node );
+
+ public abstract void setColumn( int i );
+
+ public abstract void setEnd( int pos );
+
+ public abstract void setLine( int i );
+
+ /**
+ * For Node types that support it, sets the logical name of the Node.
+ * @param name a String representing the name.
+ */
+ public abstract void setName( String name );
+
+ public abstract void setParent( Node parent );
+
+ public abstract void setStart( int pos );
+
+ public abstract void setType( NodeType type );
+
+ /**
+ * Convenience method that replaces all child Nodes with a single text node
+ * whose value is supplied by the caller.
+ * @param value the value to replace
+ */
+ public abstract void setValue( String value );
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/NodeType.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/NodeType.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/NodeType.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/NodeType.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,69 @@
+/**
+ *
+ */
+package com.ecyrd.jspwiki.ui.stripes;
+
+public enum NodeType
+{
+ /** Root node */
+ ROOT(null, null),
+ /** Attribute node */
+ ATTRIBUTE(null,null),
+ /** Text node */
+ TEXT("", ""),
+ /** HTML start tag */
+ HTML_START_TAG("<", ">"),
+ /** HTML end tag */
+ HTML_END_TAG("</", ">"),
+ /** HTML end tag */
+ HTML_COMBINED_TAG("<", "/>"),
+ /** HTML tag, but not sure whether it's a start, end or combined tag. */
+ UNRESOLVED_HTML_TAG("<", null),
+ /** JSP comments, e.g., <%-- comment --%> */
+ JSP_COMMENT("<%--", "--%>"),
+ /**
+ * JSP declaration, e.g., <%! declaration; [ declaration; ]+ ...
+ * %>
+ */
+ JSP_DECLARATION("<%!", "%>"),
+ /** JSP expression, e.g., <%= expression %> */
+ JSP_EXPRESSION("<%=", "%>"),
+ /**
+ * JSP scriptlet, e.g., <% code fragment %>. Note the whitespace
+ * after the %.
+ */
+ SCRIPTLET("<%", "%>"),
+ /**
+ * JSP page, import or taglib directive, e.g., <%@ include... %>
+ * <%@ page... %> <%@ taglib... %>
+ */
+ JSP_DIRECTIVE("<%@", "%>"),
+ /** JSP tag, but not sure what kind.. */
+ UNRESOLVED_JSP_TAG(null, null),
+ /** Parser has seen <, but hasn't figured out what it is yet. */
+ UNRESOLVED(null, null);
+ private final String m_tagStart;
+
+ private final String m_tagEnd;
+
+ NodeType(String tagStart, String tagEnd )
+ {
+ m_tagStart = tagStart;
+ m_tagEnd = tagEnd;
+ }
+
+ public String getTagEnd()
+ {
+ return m_tagEnd;
+ }
+
+ public String getTagStart()
+ {
+ return m_tagStart;
+ }
+
+ public String toString() {
+ return name();
+ }
+
+}
\ No newline at end of file
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformer.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformer.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformer.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformer.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,186 @@
+package com.ecyrd.jspwiki.ui.stripes;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Transforms a JspDocument from standard JSP markup to Stripes markup.
+ */
+public class StripesJspTransformer extends AbstractJspTransformer
+{
+
+ public void transform( Map<String, Object> sharedState, JspDocument doc )
+ {
+
+ // Add the Stripes taglib declaration if it's not there already
+ List<Node> nodes = doc.getNodes( NodeType.JSP_DIRECTIVE );
+ boolean declaresStripesTaglib = false;
+ for ( Node node : nodes )
+ {
+ Tag tag = (Tag)node;
+ if ( "taglib".equals( node.getName() ) )
+ {
+ Attribute attribute = tag.getAttribute( "prefix" );
+ if ( attribute != null )
+ {
+ declaresStripesTaglib = true;
+ break;
+ }
+ }
+ }
+ if ( !declaresStripesTaglib )
+ {
+ Tag tag = new Tag( doc, NodeType.JSP_DIRECTIVE );
+ tag.setName( "taglib" );
+ Attribute attribute = new Attribute( doc );
+ attribute.setName( "uri" );
+ attribute.setValue( "/WEB-INF/stripes.tld" );
+ tag.addAttribute( attribute );
+ attribute = new Attribute( doc );
+ attribute.setName( "prefix" );
+ attribute.setValue( "stripes" );
+ tag.addAttribute( attribute );
+ doc.getRoot().addChild( tag );
+ message( doc.getRoot(), "Added Stripes taglib directive." );
+ }
+
+ // Process HTML nodes
+ nodes = doc.getNodes();
+ for( Node node : nodes )
+ {
+ // For all HTML tags...
+ if( node.isHtmlNode() )
+ {
+ Tag tag = (Tag)node;
+
+ // Change <form> to <stripes:form>
+ if( "form".equals( tag.getName() ) )
+ {
+ migrateFormTag( tag );
+ }
+
+ // Change <input type="*"> tags to <stripes:*>
+ else if( "input".equals( tag.getName() ) )
+ {
+ migrateInputTag( tag );
+ }
+ }
+ }
+ }
+
+ /**
+ * Migrates the <input> tag.
+ * @param tag the AbstractNode that represents the form tag being processed.
+ */
+ private void migrateInputTag( Tag tag )
+ {
+
+ // Move 'type' attribute value to the localname
+ Attribute attribute = tag.getAttribute( "type" );
+ if( attribute != null )
+ {
+ // If a submit input, tell user to change the "name"
+ // value to something useful for Stripes
+ if( "submit".equals( attribute.getValue() ) )
+ {
+ Node nameAttribute = tag.getAttribute( "name" );
+ String nameValue = nameAttribute == null ? "(not set)" : nameAttribute.getName();
+ message( nameAttribute, "NOTE: the \"name\" attribute of <input type=\"submit\" is \"" + nameValue
+ + "\"" );
+ }
+
+ // Move type attribute to qname
+ String type = attribute.getValue();
+ message( attribute, "Changed <input type=\"" + type + "\"> to <stripes:" + type + ">." );
+ tag.setName( "stripes:" + type );
+ tag.removeAttribute( attribute );
+ }
+
+ // If embedded markup in "value" attribute, move to child
+ // nodes
+ attribute = tag.getAttribute( "value" );
+ if( attribute != null )
+ {
+ List<Node> children = attribute.getChildren();
+ if( children.size() > 1 || (children.size() == 1 && children.get( 0 ).getType() != NodeType.TEXT) )
+ {
+ // Remove the attribute
+ tag.removeAttribute( attribute );
+ // Move all of the attribute's nodes to the
+ // children nodes
+ for( Node valueNode : attribute.getChildren() )
+ {
+ tag.addChild( valueNode );
+ }
+ message( attribute,
+ "Moved embedded tag(s) in <input> \"value\" attribute to the tag body. These are now child element(s) of <input>." );
+ }
+ }
+ }
+
+ /**
+ * Migrates the <form> tag.
+ * @param tag the AbstractNode that represents the form tag being processed.
+ */
+ private void migrateFormTag( Tag tag )
+ {
+ message( tag, "Changed name to <stripes:form>." );
+ tag.setName( "stripes:form" );
+
+ // Change "accept-charset" attribute to acceptcharset
+ Node attribute = tag.getAttribute( "accept-charset" );
+ if( attribute != null )
+ {
+ message( attribute, "Changed name to \"acceptcharset\"." );
+ attribute.setName( "acceptcharset" );
+ }
+
+ // If URL has parameters, add them as child <stripes:param>
+ // elements
+ // e.g., param in <form action="Login.jsp?tab=profile>
+ // becomes <stripes:param name="tab" value="profile">
+ attribute = tag.getAttribute( "action" );
+ if( attribute != null )
+ {
+ String actionUrl = attribute.getValue();
+ if( actionUrl != null )
+ {
+ int qmark = actionUrl.indexOf( '?' );
+ if( qmark < actionUrl.length() - 1 )
+ {
+ // Change "action" attribute"
+ String trimmedPath = actionUrl.substring( 0, qmark );
+ message( attribute, "Trimmed value to \"" + trimmedPath + "\"");
+ attribute.setValue( trimmedPath );
+
+ // Split the parameters and add a new
+ // <stripes:param> child element for each
+ String[] params = actionUrl.substring( qmark + 1 ).split( "&" );
+ for( String param : params )
+ {
+ if( param.length() > 1 )
+ {
+ JspDocument doc = tag.getJspDocument();
+ String name = param.substring( 0, param.indexOf( '=' ) );
+ String value = param.substring( name.length() +1 );
+ Tag stripesParam = new Tag( doc, NodeType.HTML_COMBINED_TAG );
+ stripesParam.setName( "stripes:param" );
+ Attribute nameAttribute = new Attribute( doc );
+ nameAttribute.setName( "name" );
+ nameAttribute.setValue( name );
+ stripesParam.addAttribute( nameAttribute );
+ Attribute valueAttribute = new Attribute( doc );
+ valueAttribute.setName( "value" );
+ valueAttribute.setValue( value );
+ stripesParam.addAttribute( valueAttribute );
+ tag.addChild( stripesParam );
+ message( tag, "Created <stripes:form> child element <stripes:param name=\"" + name + "\""
+ + " value=\"" + value + "\"/>." );
+ }
+ }
+ }
+ }
+ }
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformerTest.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformerTest.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformerTest.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/StripesJspTransformerTest.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,97 @@
+package com.ecyrd.jspwiki.ui.stripes;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+
+public class StripesJspTransformerTest extends TestCase
+{
+ protected Map<String,Object> m_sharedState = new HashMap<String,Object>();
+ protected JspTransformer m_transformer = new StripesJspTransformer();
+ protected JspDocument m_doc = new JspDocument();
+
+ public StripesJspTransformerTest( String s )
+ {
+ super( s );
+ }
+
+ public void testFormWithParams() throws Exception
+ {
+ String s = "<form action=\"Login.jsp?tab=profile\"/>";
+ JspDocument doc = new JspParser().parse( s );
+ m_transformer.transform( m_sharedState, doc );
+
+ assertEquals( 3, doc.getNodes().size() );
+ Node node = doc.getNodes().get( 0 );
+ assertEquals( "stripes:form", node.getName() );
+ assertEquals( 1, ((Tag)node).getAttributes().size() );
+ Node attribute = ((Tag)node).getAttributes().get( 0 );
+ assertEquals( "Login.jsp", attribute.getValue() );
+ }
+
+ public void testFormCombinedTag() throws Exception
+ {
+ String s = "<form accept-charset=\"UTF-8\" method=\"POST\" />";
+ JspDocument doc = new JspParser().parse( s );
+ m_transformer.transform( m_sharedState, doc );
+
+ assertEquals( 1, doc.getNodes().size() );
+ Node node = doc.getNodes().get( 0 );
+ assertEquals( "stripes:form", node.getName() );
+
+ assertEquals( 2, ((Tag)node).getAttributes().size() );
+ Node attribute = ((Tag)node).getAttributes().get( 0 );
+ assertEquals( "acceptcharset", attribute.getName() );
+ }
+
+ public void testPasswordTag() throws Exception
+ {
+ String s = "<input type=\"password\" size=\"24\" value=\"\" name=\"j_username\" id=\"j_username\" />";
+ JspDocument doc = new JspParser().parse( s );
+ Node node;
+
+ // Before transformation, 1 node, with 5 attributes
+ node = doc.getNodes().get( 0 );
+ assertEquals( 1, doc.getNodes().size() );
+ assertEquals( 5, ((Tag)node).getAttributes().size() );
+ m_transformer.transform( m_sharedState, doc );
+
+ // After transformation, the "type" attribute is deleted
+ assertEquals( 1, doc.getNodes().size() );
+ node = doc.getNodes().get( 0 );
+ assertEquals( NodeType.HTML_COMBINED_TAG, node.getType() );
+ assertEquals( "stripes:password", node.getName() );
+ assertEquals( 4, ((Tag)node).getAttributes().size() );
+ assertEquals( 0, node.getChildren().size() );
+ }
+
+ public void testPasswordTagComplex() throws Exception
+ {
+ String s = "<input type=\"password\" size=\"24\" value=\"<wiki:Variable var='uid' default='' />\" name=\"j_username\" id=\"j_username\" />";
+ JspDocument doc = new JspParser().parse( s );
+ assertEquals( 1, doc.getNodes().size() );
+ m_transformer.transform( m_sharedState, doc );
+
+ // After transformation, the "type" and "value" attributes are deleted; value becomes child node
+ assertEquals( 3, doc.getNodes().size() );
+ Node node = doc.getNodes().get( 0 );
+ assertEquals( NodeType.HTML_START_TAG, node.getType() );
+ assertEquals( "stripes:password", node.getName() );
+ assertEquals( 3, ((Tag)node).getAttributes().size() );
+
+ // The value attribute should show up as a child node
+ assertEquals( 1, node.getChildren().size() );
+ node = node.getChildren().get( 0 );
+ assertEquals( NodeType.HTML_COMBINED_TAG, node.getType() );
+ assertEquals( "wiki:Variable", node.getName() );
+ }
+
+ public static Test suite()
+ {
+ return new TestSuite( StripesJspTransformerTest.class );
+ }
+}
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Tag.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Tag.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Tag.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Tag.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,156 @@
+/**
+ *
+ */
+package com.ecyrd.jspwiki.ui.stripes;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Node implementation representing an HTML or XML tag.
+ */
+public class Tag extends AbstractNode
+{
+ private List<Attribute> m_attributes = new ArrayList<Attribute>();
+
+ /**
+ *
+ * @param doc the parent JspDocument
+ * @param type
+ */
+ public Tag ( JspDocument doc, NodeType type )
+ {
+ super( doc, type );
+ }
+
+ public void addAttribute( Attribute attribute )
+ {
+ m_attributes.add( attribute );
+ }
+
+ /**
+ * Returns the attribute whose name matches a supplied string, or
+ * <code>null</code> if not found.
+ *
+ * @param name the named attribute to search for
+ * @return the attribute if found, or <code>null</code>
+ */
+ public Attribute getAttribute( String name )
+ {
+ if( name == null )
+ {
+ throw new IllegalArgumentException( "Name cannot be null. " );
+ }
+ for( Attribute attribute : m_attributes )
+ {
+ if( name.equals( attribute.getName() ) )
+ {
+ return attribute;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the attributes of this node, as a defensive copy of the
+ * internally-cached list.
+ *
+ * @return
+ */
+ public List<Attribute> getAttributes()
+ {
+ List<Attribute> attributesCopy = new ArrayList<Attribute>();
+ attributesCopy.addAll( m_attributes );
+ return Collections.unmodifiableList( attributesCopy );
+ }
+
+ public void removeAttribute( Attribute attribute )
+ {
+ m_attributes.remove( attribute );
+ }
+
+ private String diagnostic()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append( "[" );
+ sb.append( m_type.toString() );
+ sb.append( "(pos=" );
+ sb.append( m_line );
+ sb.append( ":" );
+ sb.append( m_col );
+ sb.append( ",chars=" );
+ sb.append( m_start );
+ sb.append( ":" );
+ sb.append( m_end );
+ sb.append( ",L" );
+ sb.append( getLevel() );
+ sb.append( ")," );
+ sb.append( "name=\"" );
+ sb.append( m_name );
+ sb.append( "\"," );
+ if( m_attributes.size() > 0 )
+ {
+ sb.append( "attributes=" );
+ for( Attribute attr : m_attributes )
+ {
+ sb.append( "[" );
+ sb.append( attr.toString() );
+ sb.append( "\"]" );
+ }
+ sb.append( "," );
+ }
+ sb.append( "value=\"" );
+ sb.append( getValue() );
+ sb.append( "\"]" );
+
+ return sb.toString(); }
+
+ public String getValue()
+ {
+ if ( m_type != NodeType.HTML_START_TAG )
+ {
+ return null;
+ }
+ return super.getValue();
+ }
+
+ /**
+ * Returns the string that represents the Tag, including the name and attributes, but not any child nodes.
+ */
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append( m_type.getTagStart() );
+
+ // HTML nodes and JSP directives are formatted in mostly the same way.
+ if ( isHtmlNode() || m_type == NodeType.JSP_DIRECTIVE )
+ {
+ if ( m_type == NodeType.JSP_DIRECTIVE )
+ {
+ sb.append( ' ' );
+ }
+ sb.append( m_name );
+ if( m_attributes.size() > 0 )
+ {
+ for( Attribute attr : m_attributes )
+ {
+ sb.append( ' ' );
+ sb.append( attr.toString() );
+ }
+ }
+ }
+
+ // Everything else is just the start/end tags plus the children nodes
+ else {
+ for ( Node child : m_children )
+ {
+ sb.append( child.toString() );
+ }
+ }
+
+ sb.append( m_type.getTagEnd() );
+ return sb.toString();
+ }
+
+}
Added: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Text.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Text.java?rev=695481&view=auto
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Text.java (added)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/ui/stripes/Text.java Mon Sep 15 07:21:34 2008
@@ -0,0 +1,44 @@
+package com.ecyrd.jspwiki.ui.stripes;
+
+public class Text extends AbstractNode
+{
+
+ private String m_value = null;
+
+ public Text( JspDocument doc )
+ {
+ super( doc, NodeType.TEXT );
+ }
+
+ /**
+ * Always returns \"(TEXT)\".
+ */
+ @Override
+ public String getName()
+ {
+ return "(TEXT)";
+ }
+
+ public String getValue()
+ {
+ return m_value;
+ }
+
+ public void setName( String name )
+ {
+ throw new UnsupportedOperationException( "Text nodes cannot have names.");
+ }
+
+ public void setValue( String value )
+ {
+ m_value = value;
+ }
+
+ /**
+ * Returns the string that represents the Tag, including the name and attributes, but not any child nodes.
+ */
+ public String toString()
+ {
+ return m_value;
+ }
+}
Modified: incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/util/AllTests.java
URL: http://svn.apache.org/viewvc/incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/util/AllTests.java?rev=695481&r1=695480&r2=695481&view=diff
==============================================================================
--- incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/util/AllTests.java (original)
+++ incubator/jspwiki/branches/JSPWIKI_2_9_STRIPES_BRANCH/tests/com/ecyrd/jspwiki/util/AllTests.java Mon Sep 15 07:21:34 2008
@@ -2,6 +2,8 @@
package com.ecyrd.jspwiki.util;
+import com.ecyrd.jspwiki.ui.stripes.JspParserTest;
+
import junit.framework.*;
public class AllTests extends TestCase
@@ -23,6 +25,7 @@
suite.addTest( SerializerTest.suite() );
suite.addTest( TextUtilTest.suite() );
suite.addTest( TimedCounterListTest.suite() );
+ suite.addTest( JspParserTest.suite() );
return suite;
}