tapestry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jkuhn...@apache.org
Subject svn commit: r405492 - in /tapestry/tapestry4/trunk/framework/src: java/org/apache/tapestry/script/ java/org/apache/tapestry/services/ java/org/apache/tapestry/services/impl/ java/org/apache/tapestry/util/ test/org/apache/tapestry/services/impl/ test/or...
Date Tue, 09 May 2006 18:06:05 GMT
Author: jkuhnert
Date: Tue May  9 11:06:02 2006
New Revision: 405492

URL: http://svn.apache.org/viewcvs?rev=405492&view=rev
Log:
Refactored javascript writing of PageRenderSupport to delegate to ResponseBuilder.

Added:
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/Script_4_0.dtd
    tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/DefaultResponseBuilderTest.java
    tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/ScriptUtilsTest.java
Modified:
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/ScriptParser.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/ResponseBuilder.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java
    tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/PageRenderSupportImpl.java

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/ScriptParser.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/ScriptParser.java?rev=405492&r1=405491&r2=405492&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/ScriptParser.java
(original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/ScriptParser.java
Tue May  9 11:06:02 2006
@@ -64,13 +64,16 @@
     /** @since 3.0 */
     public static final String SCRIPT_DTD_3_0_PUBLIC_ID = "-//Apache Software Foundation//Tapestry
Script Specification 3.0//EN";
 
+    /** @since 4.1 */
+    public static final String SCRIPT_DTD_4_0_PUBLIC_ID = "-//Apache Software Foundation//Tapestry
Script Specification 4.0//EN";
+    
     private RuleDirectedParser _parser;
     
     public ScriptParser(ClassResolver resolver, ExpressionEvaluator evaluator,
             ValueConverter valueConverter)
     {
         _parser = new RuleDirectedParser();
-
+        
         _parser.registerEntity(SCRIPT_DTD_1_0_PUBLIC_ID,
                 "/org/apache/tapestry/script/Script_1_0.dtd");
         _parser.registerEntity(SCRIPT_DTD_1_1_PUBLIC_ID,
@@ -79,7 +82,9 @@
                 "/org/apache/tapestry/script/Script_1_2.dtd");
         _parser.registerEntity(SCRIPT_DTD_3_0_PUBLIC_ID,
                 "/org/apache/tapestry/script/Script_3_0.dtd");
-
+        _parser.registerEntity(SCRIPT_DTD_4_0_PUBLIC_ID,
+        "/org/apache/tapestry/script/Script_4_0.dtd");
+        
         _parser.addRule("script", new ScriptRule(evaluator, valueConverter));
         _parser.addRule("let", new LetRule());
         _parser.addRule("set", new SetRule());
@@ -91,7 +96,7 @@
         _parser.addRule("if-not", new IfRule(false));
         _parser.addRule("foreach", new ForeachRule());
         _parser.addRule("unique", new UniqueRule());
-
+        
         // This will go away when the 1.1 and earler DTDs are retired.
         _parser.addRule("insert", new InsertRule());
 

Added: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/Script_4_0.dtd
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/Script_4_0.dtd?rev=405492&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/Script_4_0.dtd
(added)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/script/Script_4_0.dtd
Tue May  9 11:06:02 2006
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+DTD for the files used with the ScriptParser class and Script component.  
+This is recognized with the public identifier:
+
+	-//Apache Software Foundation//Tapestry Script Specification 4.0//EN
+
+The canonical location for the DTD is:
+
+	http://tapestry.apache.org/dtd/Script_4_0.dtd
+
+The root element is always script.
+	
+This DTD is backwards compatible with the 1.2 DTD, with the following exceptions:
+- Addition of <unique> element
+- Addition of unique attribute to <let> element
+- Addition of index attribute to <foreach> element
+-->
+<!-- =======================================================
+
+Entity: full-content
+
+Identifies the contents of most of the other elements.
+
+-->
+<!ENTITY % full-content "(#PCDATA | foreach | if | if-not | unique)*">
+<!-- =======================================================
+
+Element: body
+Contained by: script
+
+Allows a mix of text and control elements.  This text is added to
+the large scripting block just inside the <body> tag.
+-->
+<!ELEMENT body %full-content;>
+<!-- =======================================================
+
+Element: foreach
+Appears in: %full-content;
+
+Iterates over a list of items; this is modeled after the
+For component.  No iteration occurs if the value
+from the expression is null.
+
+Attributes:
+  key: Defines the symbol into which each succesive value is stored.
+  index: Defines the symbol into which the index of the value of the current iteration is
stored.
+  expression: The source of values, as an OGNL expression rooted in the symbols Map.
+-->
+<!ELEMENT foreach %full-content;>
+<!ATTLIST foreach
+  key CDATA #IMPLIED
+  index CDATA #IMPLIED
+  expression CDATA #REQUIRED
+>
+
+<!-- =======================================================
+Element: include-script
+Contained by: script
+
+Inserts a reference to an external, static, JavaScript file.
+
+Attributes:
+  resource-path: The path to the script within the classpath.
+-->
+<!ELEMENT include-script EMPTY>
+<!ATTLIST include-script
+  resource-path CDATA #REQUIRED
+>
+
+<!-- =======================================================
+
+Element: if
+Appears in: %full-content;
+
+Creates a conditional portion of the script; The body of the element 
+is only included if the expression evaulates to true.
+
+Attributes:
+  expression: The trigger expression, as an OGNL expression rooted in 
+    the symbols Map.
+
+-->
+<!ELEMENT if %full-content;>
+<!ATTLIST if
+  expression CDATA #REQUIRED
+>
+<!-- =======================================================
+
+Element: if-not
+Appears in: %full-content;
+
+Creates a conditional portion of the script; The body of the element 
+is only included if the property-path evaulates to false.
+
+Attributes:
+  expression: The trigger expression, as an OGNL expression rooted in 
+    the symbols Map.
+
+-->
+<!ELEMENT if-not %full-content;>
+<!ATTLIST if-not
+  expression CDATA #REQUIRED
+>
+<!-- =======================================================
+Element: initialization
+Contained by: script
+
+Text in this block is added to the event handler for the <body>
+tag's onLoad event.
+-->
+<!ELEMENT initialization %full-content;>
+
+
+
+<!-- =======================================================
+Element: input-symbol
+Contained by: script
+
+Defines an input symbol used by the script.
+Attributes:
+  key: The name of the symbol.
+  class:  If specified, the exected class or interface for the symbol.
+  required: If yes, then the symbol must be non-null.
+-->
+
+<!ELEMENT input-symbol EMPTY>
+<!ATTLIST input-symbol
+  key CDATA #REQUIRED
+  class CDATA #IMPLIED
+  required (yes|no) "no"
+>
+
+<!-- =======================================================
+
+Element: let
+Contained by: script
+
+Used to create a new symbol. The content of the tag
+is used to create a string that is the name.  If the
+unique flag is enabled, the name is ensured to be unique
+(a suffix may be appended to ensure it is unique
+among all names so generated).
+
+Attributes:
+  key: The name of the symbol to create.
+  unique: If yes, the name is ensured to be unique.
+  The default is no.
+
+-->
+<!ELEMENT let %full-content;>
+<!ATTLIST let
+  key CDATA #REQUIRED
+  unique (yes|no) "no"
+>
+<!-- =======================================================
+
+Element: script
+
+Root element.
+
+Allows zero or more let elements (to establish new symbols),
+followed by a body and/or initialization element.
+
+-->
+<!ELEMENT script (include-script*, input-symbol*, 
+	(let | set)*, body?, initialization?)>
+
+
+<!-- =======================================================
+
+Element: set
+Contained by: script
+
+Creates a new symbol as the result of evaluating an OGNL expression.
+
+-->
+<!ELEMENT set EMPTY>
+<!ATTLIST set
+  key CDATA #REQUIRED
+  expression CDATA #REQUIRED
+>
+
+<!-- =======================================================
+
+Element: unique
+Appears in: %full-content;
+
+Defines a block that only is rendered once per page.
+This is appropriate to certain kinds of initialization code
+that should not be duplicated, even if the script is
+executed multiple times.
+
+-->
+<!ELEMENT unique %full-content;>

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/ResponseBuilder.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/ResponseBuilder.java?rev=405492&r1=405491&r2=405492&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/ResponseBuilder.java
(original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/ResponseBuilder.java
Tue May  9 11:06:02 2006
@@ -29,7 +29,15 @@
  * @since 4.1
  */
 public interface ResponseBuilder {
-
+    
+    String SCRIPT_TYPE = "script";
+    
+    String BODY_SCRIPT = "bodyscript";
+    
+    String INCLUDE_SCRIPT = "includescript";
+    
+    String INITIALIZATION_SCRIPT = "initializationscript";
+    
     /**
      * Renders the response to a client. Handles transitioning logic
      * for setting up page and associated components for response.
@@ -56,6 +64,83 @@
     void render(IMarkupWriter writer, IRender render, IRequestCycle cycle);
     
     /**
+     * Invoked by {@link PageRenderSupport} to write external js package
+     * includes. This method will be invoked for each external script requesting
+     * inclusion in the response.
+     * 
+     * These will typically be written out as 
+     * <code>
+     * <script type="text/javascript" src="url"></script>
+     * </code>.
+     * 
+     * @param url
+     *          The absolute url to the .js package to be included.
+     * @param cycle
+     *          The associated request.
+     */    
+    void writeExternalScript(String url, IRequestCycle cycle);
+    
+    /**
+     * Marks the beginning of the core body script.
+     * 
+     * @param cycle
+     *          The associated request.
+     */
+    void beginBodyScript(IRequestCycle cycle);
+    
+    /**
+     * Intended to be written within the confines of the body script, should
+     * be invoked once just after {@link #beginBodyScript(IRequestCycle)} is called
+     * to include any image initializations. This method should only be called if
+     * there are actually images that need pre-initialization. Ie in many instances 
+     * it will not be called at all.
+     * 
+     * @param script
+     *          The non null value of the script images to include. 
+     * @param preloadName 
+     *          The global variable name to give to the preloaded images array.
+     * @param cycle
+     *          The associated request.
+     */
+    void writeImageInitializations(String script, String preloadName, IRequestCycle cycle);
+    
+    /**
+     * Called after {@link #beginBodyScript(IRequestCycle)} to write the containing
+     * body script. This method may not be called at all if there is no js body 
+     * to write into the response.
+     * 
+     * @param script
+     *          The script to write into the body response.
+     * @param cycle
+     *          The associated request.
+     */
+    void writeBodyScript(String script, IRequestCycle cycle);
+    
+    /**
+     * Marks the end of the body block being called. This method will 
+     * always be called if {@link #beginBodyScript(IRequestCycle)} was previously
+     * called. 
+     * 
+     * @param cycle
+     *          The associated request.
+     */
+    void endBodyScript(IRequestCycle cycle);
+    
+    /**
+     * Writes any javascript that should only execute after all other items
+     * on a page have completed rendering. This is typically implemented via
+     * wrapping the executing of the code to some sort of <code>window.onload</code>

+     * event, but will vary depending on the implementation of the builder being used.
+     * 
+     * This method will ~only~ be called if there is any queued intialization script 
+     * to write.
+     * 
+     * @param script
+     *          The initialzation script to write.
+     */
+    void writeInitializationScript(String script);
+    
+    /**
      * Returns the IMarkupWriter associated with this response, it may or may
      * not be a NullWriter instance depending on the response type or stage 
      * of the render cycle. (specifically during rewind)
@@ -65,6 +150,19 @@
      */
     
     IMarkupWriter getWriter();
+    
+    /**
+     * Gets a write that will output its content in a <code>response</code>
+     * element with the given id and type. 
+     * 
+     * @param id 
+     *          The response element id to give writer.
+     * @param type
+     *          Optional - If specified will give the response element a type
+     *          attribute.
+     * @return A valid {@link IMarkupWriter} instance to write content to.
+     */
+    IMarkupWriter getWriter(String id, String type);
     
     /**
      * Determines if the specified component should have its javascript 

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java?rev=405492&r1=405491&r2=405492&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
(original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DefaultResponseBuilder.java
Tue May  9 11:06:02 2006
@@ -105,9 +105,9 @@
 
                 contentType.setParameter(ENCODING_KEY, encoding);
             }
-
+            
             PrintWriter printWriter = _webResponse.getPrintWriter(contentType);
-
+            
             _writer = _markupWriterSource.newMarkupWriter(printWriter, contentType);
         
         }
@@ -141,7 +141,18 @@
         
         return _writer;
     }
-
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public IMarkupWriter getWriter(String id, String type)
+    {
+        if (_writer == null)
+            return NullWriter.getSharedInstance();
+        
+        return _writer;
+    }
+    
     /** 
      * {@inheritDoc}
      */
@@ -164,5 +175,88 @@
     public boolean isInitializationScriptAllowed(IComponent target)
     {
         return true;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void beginBodyScript(IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter();
+        
+        writer.begin("script");
+        writer.attribute("type", "text/javascript");
+        writer.printRaw("<!--");
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void endBodyScript(IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter();
+        
+        writer.printRaw("\n\n// -->");
+        writer.end();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeBodyScript(String script, IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter();
+        
+        writer.printRaw("\n\n");
+        writer.printRaw(script);
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeExternalScript(String url, IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter();
+        
+        writer.begin("script");
+        writer.attribute("type", "text/javascript");
+        writer.attribute("src", url);
+        writer.end();
+        writer.println();
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeImageInitializations(String script, String preloadName, IRequestCycle
cycle)
+    {
+        IMarkupWriter writer = getWriter();
+        
+        writer.printRaw("\n\nvar " + preloadName + " = new Array();\n");
+        writer.printRaw("if (document.images)\n");
+        writer.printRaw("{\n");
+        writer.printRaw(script);
+        writer.printRaw("}\n");
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeInitializationScript(String script)
+    {
+        IMarkupWriter writer = getWriter();
+        
+        writer.begin("script");
+        writer.attribute("type", "text/javascript");
+        writer.printRaw("<!--\n");
+        
+        writer.printRaw("dojo.event.connect(window, 'onload', function(e) {\n");
+        
+        writer.printRaw(script);
+        
+        writer.printRaw("});");
+        
+        writer.printRaw("\n// -->");
+        writer.end();
     }
 }

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java?rev=405492&r1=405491&r2=405492&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
(original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/DojoAjaxResponseBuilder.java
Tue May  9 11:06:02 2006
@@ -162,6 +162,82 @@
     /** 
      * {@inheritDoc}
      */
+    public void beginBodyScript(IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter(ResponseBuilder.BODY_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
+        
+        writer.begin("script");
+        writer.printRaw("\n//<![CDATA[\n");
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void endBodyScript(IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter(ResponseBuilder.BODY_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
+        
+        writer.printRaw("\n//]]>\n");
+        writer.end();
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeBodyScript(String script, IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter(ResponseBuilder.BODY_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
+        
+        writer.printRaw(script);
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeExternalScript(String url, IRequestCycle cycle)
+    {
+        IMarkupWriter writer = getWriter(ResponseBuilder.INCLUDE_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
+        
+        writer.begin("script");
+        writer.attribute("type", "text/javascript");
+        writer.attribute("src", url);
+        writer.end();
+        writer.println();
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeImageInitializations(String script, String preloadName, IRequestCycle
cycle)
+    {
+        IMarkupWriter writer = getWriter(ResponseBuilder.BODY_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
+        
+        writer.printRaw("\n\nvar " + preloadName + " = new Array();\n");
+        writer.printRaw("if (document.images)\n");
+        writer.printRaw("{\n");
+        writer.printRaw(script);
+        writer.printRaw("}\n");
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeInitializationScript(String script)
+    {
+        IMarkupWriter writer = getWriter(ResponseBuilder.INITIALIZATION_SCRIPT, ResponseBuilder.SCRIPT_TYPE);
+        
+        writer.begin("script");
+        writer.printRaw("\n//<![CDATA[\n");
+        
+        writer.printRaw(script);
+        
+        writer.printRaw("\n//]]>\n");
+        writer.end();
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
     public void render(IMarkupWriter writer, IRender render, IRequestCycle cycle)
     {
         if (IComponent.class.isInstance(render)
@@ -189,17 +265,10 @@
     }
     
     /**
-     * Gets a write that will output its content in a <code>response</code>
-     * element with the given id and type. 
      * 
-     * @param id 
-     *          The response element id to give writer.
-     * @param type
-     *          Optional - If specified will give the response element a type
-     *          attribute.
-     * @return A valid {@link IMarkupWriter} instance to write content to.
+     * {@inheritDoc}
      */
-    IMarkupWriter getWriter(String id, String type)
+    public IMarkupWriter getWriter(String id, String type)
     {
         Defense.notNull(id, "id can't be null");
         
@@ -299,7 +368,7 @@
         //form components have id's generated to ensure uniqueness
         if (comp instanceof IFormComponent)
             id = ((IFormComponent)comp).getClientId();
-        if (id != null) 
+        if (id != null)
             return id;
         
         id = comp.getId();

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java?rev=405492&r1=405491&r2=405492&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java
(original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/services/impl/JSONResponseBuilder.java
Tue May  9 11:06:02 2006
@@ -165,6 +165,14 @@
     /** 
      * {@inheritDoc}
      */
+    public IMarkupWriter getWriter(String id, String type)
+    {
+        return _nullWriter;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
     public boolean isBodyScriptAllowed(IComponent target)
     {
         return false;
@@ -184,5 +192,53 @@
     public boolean isInitializationScriptAllowed(IComponent target)
     {
         return false;
+    }
+    
+    /** 
+     * {@inheritDoc}
+     */
+    public void beginBodyScript(IRequestCycle cycle)
+    {
+        // does nothing
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void endBodyScript(IRequestCycle cycle)
+    {
+        // does nothing
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeBodyScript(String script, IRequestCycle cycle)
+    {
+        // does nothing
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeExternalScript(String url, IRequestCycle cycle)
+    {
+        // does nothing
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeImageInitializations(String script, String preloadName, IRequestCycle
cycle)
+    {
+        // does nothing
+    }
+
+    /** 
+     * {@inheritDoc}
+     */
+    public void writeInitializationScript(String script)
+    {
+        // does nothing
     }
 }

Modified: tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/PageRenderSupportImpl.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/PageRenderSupportImpl.java?rev=405492&r1=405491&r2=405492&view=diff
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/PageRenderSupportImpl.java
(original)
+++ tapestry/tapestry4/trunk/framework/src/java/org/apache/tapestry/util/PageRenderSupportImpl.java
Tue May  9 11:06:02 2006
@@ -114,7 +114,7 @@
 
             if (_imageInitializations == null)
                 _imageInitializations = new StringBuffer();
-
+            
             _imageInitializations.append("  ");
             _imageInitializations.append(varName);
             _imageInitializations.append(" = new Image();\n");
@@ -123,7 +123,7 @@
             _imageInitializations.append(" = \"");
             _imageInitializations.append(URL);
             _imageInitializations.append("\";\n");
-
+            
             _imageMap.put(URL, reference);
         }
 
@@ -134,7 +134,7 @@
     {
         addBodyScript(null, script);
     }
-
+    
     public void addBodyScript(IComponent target, String script)
     {
         if (!_builder.isBodyScriptAllowed(target)) return;
@@ -164,7 +164,6 @@
     public void addExternalScript(Resource scriptLocation)
     {
         addExternalScript(null, scriptLocation);
-
     }
     
     public void addExternalScript(IComponent target, Resource scriptLocation)
@@ -173,43 +172,38 @@
         
         if (_externalScripts == null)
             _externalScripts = new ArrayList();
-
+        
         if (_externalScripts.contains(scriptLocation))
             return;
 
         // Record the Resource so we don't include it twice.
 
         _externalScripts.add(scriptLocation);
-
     }
 
     public String getUniqueString(String baseValue)
     {
         return _idAllocator.allocateId(baseValue);
     }
-
+    
     private void writeExternalScripts(IMarkupWriter writer, IRequestCycle cycle)
     {
         int count = Tapestry.size(_externalScripts);
         for (int i = 0; i < count; i++)
         {
             Resource scriptLocation = (Resource) _externalScripts.get(i);
-
+            
             IAsset asset = _assetFactory.createAsset(scriptLocation, null);
-
+            
             String url = asset.buildURL();
-
+            
             // Note: important to use begin(), not beginEmpty(), because browser don't
             // interpret <script .../> properly.
-
-            writer.begin("script");
-            writer.attribute("type", "text/javascript");
-            writer.attribute("src", url);
-            writer.end();
-            writer.println();
+            
+            _builder.writeExternalScript(url, cycle);
         }
     }
-
+    
     /**
      * Writes a single large JavaScript block containing:
      * <ul>
@@ -228,30 +222,22 @@
 
         if (!(any(_bodyScript) || any(_imageInitializations)))
             return;
-
-        writer.begin("script");
-        writer.attribute("type", "text/javascript");
-        writer.printRaw("<!--");
-
+        
+        _builder.beginBodyScript(cycle);
+        
         if (any(_imageInitializations))
         {
-            writer.printRaw("\n\nvar " + _preloadName + " = new Array();\n");
-            writer.printRaw("if (document.images)\n");
-            writer.printRaw("{\n");
-            writer.printRaw(_imageInitializations.toString());
-            writer.printRaw("}\n");
+            _builder.writeImageInitializations(_imageInitializations.toString(), _preloadName,
cycle);
         }
 
         if (any(_bodyScript))
         {
-            writer.printRaw("\n\n");
-            writer.printRaw(_bodyScript.toString());
+            _builder.writeBodyScript(_bodyScript.toString(), cycle);
         }
-
-        writer.printRaw("\n\n// -->");
-        writer.end();
+        
+        _builder.endBodyScript(cycle);
     }
-
+    
     /**
      * Writes any image initializations; this should be invoked at the end of the render,
after all
      * the related HTML will have already been streamed to the client and parsed by the web
browser.
@@ -262,20 +248,8 @@
     {
         if (!any(_initializationScript))
             return;
-
-        writer.begin("script");
-        writer.attribute("language", "JavaScript");
-        writer.attribute("type", "text/javascript");
-        writer.printRaw("<!--\n");
-        
-        writer.printRaw("dojo.event.connect(window, 'onload', function(e) {\n");
-        
-        writer.printRaw(_initializationScript.toString());
-        
-        writer.printRaw("});");
         
-        writer.printRaw("\n// -->");
-        writer.end();
+        _builder.writeInitializationScript(_initializationScript.toString());
     }
 
     private boolean any(StringBuffer buffer)

Added: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/DefaultResponseBuilderTest.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/DefaultResponseBuilderTest.java?rev=405492&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/DefaultResponseBuilderTest.java
(added)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/services/impl/DefaultResponseBuilderTest.java
Tue May  9 11:06:02 2006
@@ -0,0 +1,212 @@
+// Copyright May 9, 2006 The Apache Software Foundation
+//
+// 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 org.apache.tapestry.services.impl;
+
+import java.io.CharArrayWriter;
+import java.io.PrintWriter;
+
+import org.apache.hivemind.test.HiveMindTestCase;
+import org.apache.tapestry.IComponent;
+import org.apache.tapestry.IMarkupWriter;
+import org.apache.tapestry.IRender;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.engine.NullWriter;
+import org.apache.tapestry.markup.MarkupFilter;
+import org.apache.tapestry.markup.MarkupWriterImpl;
+import org.apache.tapestry.markup.UTFMarkupFilter;
+import org.apache.tapestry.services.ResponseBuilder;
+
+
+/**
+ * Tests functionality of {@link DefaultResponseBuilder}.
+ * 
+ * @author jkuhnert
+ */
+public class DefaultResponseBuilderTest extends HiveMindTestCase
+{
+
+    private static CharArrayWriter _writer;
+
+    private PrintWriter newPrintWriter()
+    {
+        _writer = new CharArrayWriter();
+
+        return new PrintWriter(_writer);
+    }
+
+    protected void tearDown() throws Exception
+    {
+        _writer = null;
+
+        super.tearDown();
+    }
+
+    private void assertOutput(String expected)
+    {
+        assertEquals(expected, _writer.toString());
+
+        _writer.reset();
+    }
+    
+    public void testNullRender() 
+    {
+        IRender render = (IRender)newMock(IRender.class);
+        IRequestCycle cycle = (IRequestCycle)newMock(IRequestCycle.class);
+        
+        ResponseBuilder builder = new DefaultResponseBuilder(null);
+        
+        render.render(null, cycle);
+        
+        replayControls();
+        
+        builder.render(null, render, cycle);
+        
+        verifyControls();
+        
+        assertSame(builder.getWriter(), NullWriter.getSharedInstance());
+    }
+    
+    public void testNormalRender()
+    {
+        IRender render = (IRender)newMock(IRender.class);
+        IRequestCycle cycle = (IRequestCycle)newMock(IRequestCycle.class);
+        IMarkupWriter writer = (IMarkupWriter)newMock(IMarkupWriter.class);
+        
+        ResponseBuilder builder = new DefaultResponseBuilder(writer);
+        
+        render.render(writer, cycle);
+        
+        replayControls();
+        
+        builder.render(null, render, cycle);
+        
+        verifyControls();
+        
+        assertSame(builder.getWriter(), writer);
+    }
+    
+    public void testGetWriterType()
+    {
+        IMarkupWriter writer = (IMarkupWriter)newMock(IMarkupWriter.class);
+        ResponseBuilder builder = new DefaultResponseBuilder(writer);
+        
+        assertSame(builder.getWriter("test", "type"), writer);
+    }
+    
+    public void testAllowedScripts()
+    {
+        IComponent component = (IComponent)newMock(IComponent.class);
+        ResponseBuilder builder = new DefaultResponseBuilder(null);
+        
+        assertTrue(builder.isBodyScriptAllowed(component));
+        assertTrue(builder.isExternalScriptAllowed(component));
+        assertTrue(builder.isInitializationScriptAllowed(component));
+    }
+    
+    public void testWriteBodyScript()
+    {
+        MarkupFilter filter = new UTFMarkupFilter();
+        PrintWriter writer = newPrintWriter();
+        IRequestCycle cycle = (IRequestCycle)newMock(IRequestCycle.class);
+        
+        replayControls();
+        
+        IMarkupWriter mw = new MarkupWriterImpl("text/html", writer, filter);
+        ResponseBuilder builder = new DefaultResponseBuilder(mw);
+        
+        String bscript = "var e=4;";
+        String imageInit = "image initializations";
+        String preload = "preloadedvarname";
+        
+        verifyControls();
+        replayControls();
+        
+        builder.beginBodyScript(cycle);
+        
+        assertOutput("<script type=\"text/javascript\"><!--");
+        
+        builder.writeImageInitializations(imageInit, preload, cycle);
+        
+        assertOutput("\n\nvar " + preload + " = new Array();\n"
+                + "if (document.images)\n"
+                + "{\n" + imageInit + "}\n");
+        
+        builder.writeBodyScript(bscript, cycle);
+        
+        assertOutput("\n\n" + bscript);
+        
+        builder.endBodyScript(cycle);
+        
+        assertOutput("\n\n// --></script>");
+        
+        verifyControls();
+    }
+    
+    public void testWriteExternalScripts()
+    {
+        MarkupFilter filter = new UTFMarkupFilter();
+        PrintWriter writer = newPrintWriter();
+        IRequestCycle cycle = (IRequestCycle)newMock(IRequestCycle.class);
+        
+        replayControls();
+        
+        IMarkupWriter mw = new MarkupWriterImpl("text/html", writer, filter);
+        ResponseBuilder builder = new DefaultResponseBuilder(mw);
+        
+        String script1 = "http://noname/js/package.js";
+        String script2 = "http://noname/js/package.js";
+        
+        verifyControls();
+        replayControls();
+        
+        builder.writeExternalScript(script1, cycle);
+        
+        assertOutput("<script type=\"text/javascript\" src=\""
+                + script1 + "\"></script>\n");
+        
+        builder.writeExternalScript(script2, cycle);
+        
+        assertOutput("<script type=\"text/javascript\" src=\""
+                + script2 + "\"></script>\n");
+        
+        verifyControls();
+    }
+    
+    public void testWriteInitializationScript()
+    {
+        MarkupFilter filter = new UTFMarkupFilter();
+        PrintWriter writer = newPrintWriter();
+        
+        replayControls();
+        
+        IMarkupWriter mw = new MarkupWriterImpl("text/html", writer, filter);
+        ResponseBuilder builder = new DefaultResponseBuilder(mw);
+        
+        String script = "doThisInInit();";
+        
+        verifyControls();
+        replayControls();
+        
+        builder.writeInitializationScript(script);
+        
+        assertOutput("<script type=\"text/javascript\"><!--\n"
+                + "dojo.event.connect(window, 'onload', function(e) {\n"
+                + script 
+                + "});"
+                + "\n// -->"
+                + "</script>");
+        
+        verifyControls();
+    }
+}

Added: tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/ScriptUtilsTest.java
URL: http://svn.apache.org/viewcvs/tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/ScriptUtilsTest.java?rev=405492&view=auto
==============================================================================
--- tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/ScriptUtilsTest.java
(added)
+++ tapestry/tapestry4/trunk/framework/src/test/org/apache/tapestry/util/ScriptUtilsTest.java
Tue May  9 11:06:02 2006
@@ -0,0 +1,210 @@
+// Copyright May 9, 2006 The Apache Software Foundation
+//
+// 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 org.apache.tapestry.util;
+
+import org.apache.hivemind.test.HiveMindTestCase;
+import org.apache.oro.text.perl.Perl5Util;
+import org.apache.oro.text.regex.MatchResult;
+
+
+/**
+ * Tests functionality of {@link ScriptUtils}.
+ * 
+ * @author jkuhnert
+ */
+public class ScriptUtilsTest extends HiveMindTestCase
+{
+    protected static final String JAVASCRIPT_NOCOMMENT = 
+        "<script type=\"text/javascript\">"
+        + "if (document.updateObject) {"
+        + " document.updateObject.progressFinished('updateId');"
+        + "}"
+        + "</script>";
+    
+    protected static final String MULTI_JAVASCRIPT_NOCOMMENT = 
+        "<script type=\"text/javascript\">"
+        + "if (document.updateObject) {"
+        + " document.updateObject.progressFinished('updateId');"
+        + "}"
+        + "if (document.updateObject) {"
+        + " document.updateObject.progressFinished('updateId');"
+        + "}"
+        + "</script>"
+        + JAVASCRIPT_NOCOMMENT
+        + JAVASCRIPT_NOCOMMENT;
+    
+    protected static final String TEST_INPUT1 =
+        JAVASCRIPT_NOCOMMENT 
+        + "some text is here";
+    
+    protected static final String TEST_INPUT2 =
+        "beginning text"
+        + JAVASCRIPT_NOCOMMENT 
+        + "some text is here";
+    
+    protected static final String TEST_INPUT3 =
+        JAVASCRIPT_NOCOMMENT 
+        + "Here yee"
+        + JAVASCRIPT_NOCOMMENT
+        + "some text is here";
+    
+    protected static final String TEST_INPUT4 =
+        TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3
+        + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3 + TEST_INPUT3;
+    
+    protected static final String TEST_INPUT_INCLUDE =
+        JAVASCRIPT_NOCOMMENT 
+        + "some text is here"
+        + "<script type=\"text/javascript\" src=\"http://yourmom.js\"></script>";
+    
+    public static final String BEGIN_COMMENT = "//<![CDATA[";
+    public static final String END_COMMENT = "//]]>";
+    
+    /**
+     * Tests finding {@link #JAVASCRIPT_NOCOMMENT} with 
+     * regular expressions.
+     * @testng.test groups = "functest", "util"
+     */
+    public void testFindScript()
+    {
+        Perl5Util util = new Perl5Util();
+        String expr = "/(?:<script.*?>)((\\n|.)*?)(?:<\\/script>)/";
+        
+        assertTrue(util.match(expr, JAVASCRIPT_NOCOMMENT));
+        
+        MatchResult result = util.getMatch();
+        assertNotNull(result);
+        assertEquals(3, result.groups());
+        assertEquals("if (document.updateObject) { document.updateObject.progressFinished('updateId');}",
+                result.group(1));
+    }
+    
+    /**
+     * Tests finding {@link #JAVASCRIPT_NOCOMMENT} with 
+     * regular expressions.
+     * @testng.test groups = "functest", "util"
+     */
+    public void testFindMultipleScripts()
+    {
+        Perl5Util util = new Perl5Util();
+        String expr = "/(?:<script.*?>)((\\n|.)*?)(?:<\\/script>)/";
+        
+        assertTrue(util.match(expr, MULTI_JAVASCRIPT_NOCOMMENT));
+        
+        MatchResult result = util.getMatch();
+        assertNotNull(result);
+        assertEquals(3, result.groups());
+        assertEquals("if (document.updateObject) { document.updateObject.progressFinished('updateId');}"
+                + "if (document.updateObject) { document.updateObject.progressFinished('updateId');}",
+                result.group(1));
+    }
+    
+    /**
+     * Calls {@link ScriptUtils#ensureValidScriptTags(String)} with 
+     * {@link #JAVASCRIPT_NOCOMMENT} and tests that it returns a validly
+     * marked up content block capable of being embedded in an xml document.
+     * @testng.test groups = "functest" , "util"
+     */
+    public void testEnsureValidScriptTags()
+    {
+        assertEquals(ScriptUtils.ensureValidScriptTags(JAVASCRIPT_NOCOMMENT),
+                ScriptUtils.BEGIN_COMMENT
+                + "if (document.updateObject) { document.updateObject.progressFinished('updateId');}"
+                + ScriptUtils.END_COMMENT);
+        
+        //Test other various non jscript text
+        assertNull(null, ScriptUtils.ensureValidScriptTags(null));
+        assertEquals("", ScriptUtils.ensureValidScriptTags(""));
+        assertEquals(ScriptUtils.ensureValidScriptTags("<html>This is html</html>"),
+                "<html>This is html</html>");
+    }
+    
+    /**
+     * @testng.test groups = "functest" , "util"
+     */
+    public void testEnsureValidScriptTagsWithHtmlComments()
+    {  
+        String data = "<!-- some comments1 -->" + TEST_INPUT1 + "<b>test</b><!--
some comments2 -->";
+        data += " <!-- some comments3 -->" + TEST_INPUT1 + "<b>test</b><!--
some comments4 -->";
+        String result = ScriptUtils.ensureValidScriptTags(data);
+        
+        assertTrue(result.indexOf("<!-- some comments1 -->") >= 0);
+        assertTrue(result.indexOf("<!-- some comments2 -->") >= 0);
+        assertTrue(result.indexOf("<!-- some comments3 -->") >= 0);
+        assertTrue(result.indexOf("<!-- some comments4 -->") >= 0);
+    }
+    
+    /**
+     * Tests that the complete string is returned, with 
+     * any js in it "fixed".
+     * @testng.test groups = "functest", "util"
+     */
+    public void testCompleteReturn()
+    {
+        assertEquals(ScriptUtils.ensureValidScriptTags(TEST_INPUT1),
+                ScriptUtils.BEGIN_COMMENT
+                + "if (document.updateObject) { document.updateObject.progressFinished('updateId');}"
+                + ScriptUtils.END_COMMENT + "some text is here");
+
+        assertEquals(ScriptUtils.ensureValidScriptTags(TEST_INPUT2),
+                "beginning text" 
+                + ScriptUtils.BEGIN_COMMENT
+                + "if (document.updateObject) { document.updateObject.progressFinished('updateId');}"
+                + ScriptUtils.END_COMMENT + "some text is here");
+        
+        assertEquals(ScriptUtils.ensureValidScriptTags(TEST_INPUT3),
+                ScriptUtils.BEGIN_COMMENT
+                + "if (document.updateObject) { document.updateObject.progressFinished('updateId');}"
+                + ScriptUtils.END_COMMENT
+                + "Here yee" 
+                +  ScriptUtils.BEGIN_COMMENT
+                + "if (document.updateObject) { document.updateObject.progressFinished('updateId');}"
+                + ScriptUtils.END_COMMENT
+                + "some text is here");
+    }
+}



Mime
View raw message