Author: hlship
Date: Tue Oct 25 19:18:47 2011
New Revision: 1188867

URL: http://svn.apache.org/viewvc?rev=1188867&view=rev
Log:
TAP5-1720: Supply a "<!DOCTYPE html>" for any component template that doesn't 
have a specific <!DOCTYPE>

Added:
    
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/html_entities.tml
Modified:
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateParserImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateSaxParser.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParser.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java
    
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java
    
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateParserImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateParserImpl.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateParserImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateParserImpl.java
 Tue Oct 25 19:18:47 2011
@@ -14,9 +14,8 @@
 
 package org.apache.tapestry5.internal.dynamic;
 
-import java.util.Map;
-
 import org.apache.tapestry5.internal.services.PageSource;
+import org.apache.tapestry5.internal.services.TemplateParser;
 import org.apache.tapestry5.ioc.Resource;
 import org.apache.tapestry5.ioc.annotations.PostInjection;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
@@ -28,6 +27,8 @@ import org.apache.tapestry5.services.Upd
 import org.apache.tapestry5.services.dynamic.DynamicTemplate;
 import org.apache.tapestry5.services.dynamic.DynamicTemplateParser;
 
+import java.util.Map;
+
 public class DynamicTemplateParserImpl implements DynamicTemplateParser, 
UpdateListener
 {
     private final Map<Resource, DynamicTemplate> cache = 
CollectionFactory.newConcurrentMap();
@@ -38,10 +39,13 @@ public class DynamicTemplateParserImpl i
 
     private final URLChangeTracker tracker;
 
-    public DynamicTemplateParserImpl(ClasspathURLConverter converter, 
BindingSource bindingSource, PageSource pageSource)
+    private final TemplateParser componentTemplateParser;
+
+    public DynamicTemplateParserImpl(ClasspathURLConverter converter, 
BindingSource bindingSource, PageSource pageSource, TemplateParser 
componentTemplateParser)
     {
         this.bindingSource = bindingSource;
         this.pageSource = pageSource;
+        this.componentTemplateParser = componentTemplateParser;
 
         tracker = new URLChangeTracker(converter);
     }
@@ -69,7 +73,7 @@ public class DynamicTemplateParserImpl i
 
     private DynamicTemplate doParse(Resource resource)
     {
-        return new DynamicTemplateSaxParser(resource, bindingSource).parse();
+        return new DynamicTemplateSaxParser(resource, bindingSource, 
componentTemplateParser.getDTDURLMappings()).parse();
     }
 
     public void checkForUpdates()

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateSaxParser.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateSaxParser.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateSaxParser.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/dynamic/DynamicTemplateSaxParser.java
 Tue Oct 25 19:18:47 2011
@@ -14,15 +14,6 @@
 
 package org.apache.tapestry5.internal.dynamic;
 
-import java.net.URL;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.namespace.QName;
-
 import org.apache.tapestry5.Binding;
 import org.apache.tapestry5.BindingConstants;
 import org.apache.tapestry5.Block;
@@ -44,7 +35,16 @@ import org.apache.tapestry5.services.Bin
 import org.apache.tapestry5.services.dynamic.DynamicDelegate;
 import org.apache.tapestry5.services.dynamic.DynamicTemplate;
 
-/** Does the heavy lifting for {@link DynamicTemplateParserImpl}. */
+import javax.xml.namespace.QName;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Does the heavy lifting for {@link DynamicTemplateParserImpl}.
+ */
 public class DynamicTemplateSaxParser
 {
     private final Resource resource;
@@ -53,8 +53,6 @@ public class DynamicTemplateSaxParser
 
     private final XMLTokenStream tokenStream;
 
-    private final Map<String, URL> publicIdToURL = Collections.emptyMap();
-
     private static final Pattern PARAM_ID_PATTERN = 
Pattern.compile("^param:(\\p{Alpha}\\w*)$",
             Pattern.CASE_INSENSITIVE);
 
@@ -69,7 +67,7 @@ public class DynamicTemplateSaxParser
         }
     };
 
-    public DynamicTemplateSaxParser(Resource resource, BindingSource 
bindingSource)
+    public DynamicTemplateSaxParser(Resource resource, BindingSource 
bindingSource, Map<String, URL> publicIdToURL)
     {
         this.resource = resource;
         this.bindingSource = bindingSource;
@@ -84,8 +82,7 @@ public class DynamicTemplateSaxParser
             tokenStream.parse();
 
             return toDynamicTemplate(root());
-        }
-        catch (Exception ex)
+        } catch (Exception ex)
         {
             throw new TapestryException(String.format("Failure parsing dynamic 
template %s: %s", resource,
                     InternalUtils.toMessage(ex)), tokenStream.getLocation(), 
ex);
@@ -219,7 +216,7 @@ public class DynamicTemplateSaxParser
     }
 
     private static DynamicTemplateElement createElementWriterElement(final 
String elementURI, final String elementName,
-            final List<DynamicTemplateAttribute> attributes, 
List<DynamicTemplateElement> body)
+                                                                     final 
List<DynamicTemplateAttribute> attributes, List<DynamicTemplateElement> body)
     {
         final Flow<DynamicTemplateElement> bodyFlow = F.flow(body).reverse();
 
@@ -269,8 +266,7 @@ public class DynamicTemplateSaxParser
                     Block block = delegate.getBlock(blockId);
 
                     queue.push((RenderCommand) block);
-                }
-                catch (Exception ex)
+                } catch (Exception ex)
                 {
                     throw new TapestryException(String.format(
                             "Exception rendering block '%s' as part of dynamic 
template: %s", blockId,
@@ -443,7 +439,7 @@ public class DynamicTemplateSaxParser
     }
 
     private static Mapper<DynamicDelegate, String> 
createExpansionExtractor(final String expression,
-            final Location location, final BindingSource bindingSource)
+                                                                            
final Location location, final BindingSource bindingSource)
     {
         return new Mapper<DynamicDelegate, String>()
         {
@@ -458,8 +454,7 @@ public class DynamicTemplateSaxParser
                     Object boundValue = binding.get();
 
                     return boundValue == null ? null : boundValue.toString();
-                }
-                catch (Throwable t)
+                } catch (Throwable t)
                 {
                     throw new TapestryException(InternalUtils.toMessage(t), 
location, t);
                 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/DTDData.java
 Tue Oct 25 19:18:47 2011
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2011 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.
@@ -19,14 +19,17 @@ import org.xml.sax.ext.LexicalHandler;
 /**
  * A capturing of the data from
  * {@link LexicalHandler#startDTD(String, String, String)}.
- * 
+ *
  * @since 5.2.0
  */
-public interface DTDData
+public class DTDData
 {
-    String getRootName();
+    public final String rootName, publicId, systemId;
 
-    String getPublicId();
-
-    String getSystemId();
+    public DTDData(String rootName, String publicId, String systemId)
+    {
+        this.rootName = rootName;
+        this.publicId = publicId;
+        this.systemId = systemId;
+    }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/SaxTemplateParser.java
 Tue Oct 25 19:18:47 2011
@@ -1,4 +1,4 @@
-// Copyright 2009 The Apache Software Foundation
+// Copyright 2009, 2011 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.
@@ -293,8 +293,8 @@ public class SaxTemplateParser
     {
         DTDData dtdInfo = tokenStream.getDTDInfo();
 
-        tokenAccumulator.add(new DTDToken(dtdInfo.getRootName(), 
dtdInfo.getPublicId(), dtdInfo
-                .getSystemId(), getLocation()));
+        tokenAccumulator.add(new DTDToken(dtdInfo.rootName, dtdInfo.publicId, 
dtdInfo
+                .systemId, getLocation()));
     }
 
     private Location getLocation()

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParser.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParser.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParser.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParser.java
 Tue Oct 25 19:18:47 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2008 The Apache Software Foundation
+// Copyright 2006, 2008, 2011 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.
@@ -19,6 +19,7 @@ import org.apache.tapestry5.ioc.Resource
 import org.apache.tapestry5.ioc.annotations.UsesMappedConfiguration;
 
 import java.net.URL;
+import java.util.Map;
 
 /**
  * Parses a resource into a {@link 
org.apache.tapestry5.internal.parser.ComponentTemplate}. The service's 
configuration
@@ -37,4 +38,13 @@ public interface TemplateParser
      * @throws RuntimeException if the resource does not exist, or if there is 
any kind of parse error
      */
     ComponentTemplate parseTemplate(Resource templateResource);
+
+    /**
+     * Returns a mapping from URL string to a local equivalent URL, used to 
avoid attempting to pull
+     * well-known DTDs down over the wire while parsing XML.
+     *
+     * @since 5.3
+     */
+    Map<String, URL> getDTDURLMappings();
 }
+

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/TemplateParserImpl.java
 Tue Oct 25 19:18:47 2011
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007, 2008, 2009, 2010 The Apache Software Foundation
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 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.
@@ -14,9 +14,6 @@
 
 package org.apache.tapestry5.internal.services;
 
-import java.net.URL;
-import java.util.Map;
-
 import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.internal.parser.ComponentTemplate;
 import org.apache.tapestry5.ioc.Invokable;
@@ -24,11 +21,14 @@ import org.apache.tapestry5.ioc.Operatio
 import org.apache.tapestry5.ioc.Resource;
 import org.apache.tapestry5.ioc.annotations.Symbol;
 
+import java.net.URL;
+import java.util.Map;
+
 /**
  * Parses Tapestry XML template files into {@link ComponentTemplate} instances.
  * A new instance of {@link SaxTemplateParser} is created for each document
  * parsed.
- * 
+ *
  * @since 5.1.0.0
  */
 public class TemplateParserImpl implements TemplateParser
@@ -41,8 +41,8 @@ public class TemplateParserImpl implemen
 
     public TemplateParserImpl(Map<String, URL> configuration,
 
-    @Symbol(SymbolConstants.COMPRESS_WHITESPACE)
-    boolean defaultCompressWhitespace, OperationTracker tracker)
+                              @Symbol(SymbolConstants.COMPRESS_WHITESPACE)
+                              boolean defaultCompressWhitespace, 
OperationTracker tracker)
     {
         this.configuration = configuration;
         this.defaultCompressWhitespace = defaultCompressWhitespace;
@@ -62,4 +62,9 @@ public class TemplateParserImpl implemen
             }
         });
     }
+
+    public Map<String, URL> getDTDURLMappings()
+    {
+        return configuration;
+    }
 }

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry5/internal/services/XMLTokenStream.java
 Tue Oct 25 19:18:47 2011
@@ -37,6 +37,11 @@ import java.util.Map;
  */
 public class XMLTokenStream
 {
+
+    public static final String TRANSITIONAL_DOCTYPE = "<!DOCTYPE html PUBLIC 
\"-//W3C//DTD XHTML 1.0 Transitional//EN\" 
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\";>";
+
+    private static final DTDData HTML5_DTD_DATA = new DTDData("html", null, 
null);
+
     private final class SaxHandler implements LexicalHandler, EntityResolver, 
ContentHandler
     {
         private Locator locator;
@@ -62,7 +67,10 @@ public class XMLTokenStream
 
             if (cachedLocation == null)
             {
-                cachedLocation = new LocationImpl(resource, line);
+                // lineOffset accounts for the extra line when a doctype is 
injected. The line number reported
+                // from the XML parser inlcudes the phantom doctype line, the 
lineOffset is used to subtract one
+                // to get the real line number.
+                cachedLocation = new LocationImpl(resource, line + lineOffset);
             }
 
             return cachedLocation;
@@ -138,6 +146,7 @@ public class XMLTokenStream
 
         public void ignorableWhitespace(char[] ch, int start, int length) 
throws SAXException
         {
+            characters(ch, start, length);
         }
 
         public void startDTD(final String name, final String publicId, final 
String systemId)
@@ -145,26 +154,12 @@ public class XMLTokenStream
         {
             insideDTD = true;
 
-            DTDData data = new DTDData()
+            if (!ignoreDTD)
             {
+                DTDData data = html5DTD ? HTML5_DTD_DATA : new DTDData(name, 
publicId, systemId);
 
-                public String getSystemId()
-                {
-                    return html5DTD ? null : systemId;
-                }
-
-                public String getRootName()
-                {
-                    return name;
-                }
-
-                public String getPublicId()
-                {
-                    return html5DTD ? null : publicId;
-                }
-            };
-
-            add(XMLTokenType.DTD).dtdData = data;
+                add(XMLTokenType.DTD).dtdData = data;
+            }
         }
 
         public void endDocument() throws SAXException
@@ -182,12 +177,21 @@ public class XMLTokenStream
             this.locator = locator;
         }
 
+        /**
+         * Checks for the extra namespace injected when the transitional 
doctype is injected (which
+         * occurs when the template contains no doctype).
+         */
+        private boolean ignoreURI(String uri)
+        {
+            return ignoreDTD && uri.equals("http://www.w3.org/1999/xhtml";);
+        }
+
         public void startElement(String uri, String localName, String qName, 
Attributes attributes)
                 throws SAXException
         {
             XMLToken token = add(XMLTokenType.START_ELEMENT);
 
-            token.uri = uri;
+            token.uri = ignoreURI(uri) ? "" : uri;
             token.localName = localName;
             token.qName = qName;
 
@@ -227,6 +231,11 @@ public class XMLTokenStream
 
         public void startPrefixMapping(String prefix, String uri) throws 
SAXException
         {
+            if (ignoreDTD && prefix.equals("") && 
uri.equals("http://www.w3.org/1999/xhtml";))
+            {
+                return;
+            }
+
             namespaceMappings.add(new NamespaceMapping(prefix, uri));
         }
 
@@ -270,7 +279,9 @@ public class XMLTokenStream
 
     private Location exceptionLocation;
 
-    private boolean html5DTD;
+    private boolean html5DTD, ignoreDTD;
+
+    private int lineOffset;
 
     public XMLTokenStream(Resource resource, Map<String, URL> publicIdToURL)
     {
@@ -314,60 +325,95 @@ public class XMLTokenStream
         }
     }
 
-    private InputStream openStream() throws IOException
+    enum State
     {
+        MAYBE_XML, MAYBE_DOCTYPE, JUST_COPY
+    }
 
+    private InputStream openStream() throws IOException
+    {
         InputStream rawStream = resource.openStream();
 
         InputStreamReader rawReader = new InputStreamReader(rawStream);
         LineNumberReader reader = new LineNumberReader(rawReader);
 
+        ByteArrayOutputStream bos = new ByteArrayOutputStream(5000);
+        PrintWriter writer = new PrintWriter(bos);
+
+        State state = State.MAYBE_XML;
+
         try
         {
-            String firstLine = reader.readLine();
-
-            if ("<!DOCTYPE html>".equalsIgnoreCase(firstLine))
+            while (true)
             {
-                // When we hit the doctype later, ignore the transitional 
PUBLIC and SYSTEM ids and
-                // treat it like a proper HTML5 doctype.
-                html5DTD = true;
-                return substituteTransitionalDoctype(reader);
-            }
+                String line = reader.readLine();
 
-            // Open a fresh stream for the parser to operate on.
+                if (line == null)
+                {
+                    break;
+                }
 
-            return resource.openStream();
+                switch (state)
+                {
 
-        } finally
-        {
-            reader.close();
-        }
-    }
+                    case MAYBE_XML:
 
-    private InputStream substituteTransitionalDoctype(LineNumberReader reader) 
throws IOException
-    {
-        ByteArrayOutputStream bos = new ByteArrayOutputStream(5000);
-        PrintWriter writer = new PrintWriter(bos);
+                        if (line.toLowerCase().startsWith("<?xml"))
+                        {
+                            writer.println(line);
+                            state = State.MAYBE_DOCTYPE;
+                            continue;
+                        }
 
-        writer.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 
Transitional//EN\" 
\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\";>");
+                    case MAYBE_DOCTYPE:
 
-        while (true)
-        {
-            String line = reader.readLine();
-            if (line == null)
-            {
-                break;
-            }
+                        if (line.trim().length() == 0)
+                        {
+                            writer.println(line);
+                            continue;
+                        }
 
-            writer.println(line);
-        }
+                        String lineLower = line.toLowerCase();
+
+                        if (lineLower.equals("<!doctype html>"))
+                        {
+                            html5DTD = true;
+                            writer.println(TRANSITIONAL_DOCTYPE);
+                            state = State.JUST_COPY;
+                            continue;
+                        }
+
+
+                        if (lineLower.startsWith("<!doctype"))
+                        {
+                            writer.println(line);
+                            state = State.JUST_COPY;
+                            continue;
+                        }
 
-        writer.close();
+                        // No doctype, let's provide one.
+
+                        ignoreDTD = true;
+                        lineOffset = -1;
+                        writer.println(TRANSITIONAL_DOCTYPE);
+
+                        state = State.JUST_COPY;
+
+                        // And drop down to writing out the actual line, and 
all following lines.
+
+                    case JUST_COPY:
+                        writer.println(line);
+                }
+            }
+        } finally
+        {
+            writer.close();
+            reader.close();
+        }
 
         return new ByteArrayInputStream(bos.toByteArray());
     }
 
-
     private XMLToken token()
     {
         return tokens.get(cursor);

Modified: 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java?rev=1188867&r1=1188866&r2=1188867&view=diff
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java
 (original)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry5/internal/services/TemplateParserImplTest.java
 Tue Oct 25 19:18:47 2011
@@ -985,4 +985,22 @@ public class TemplateParserImplTest exte
             assertMessageContains(ex, "Extension point 'batman' is already 
defined for this template.");
         }
     }
+
+    @Test
+    public void html_entities_inside_template_without_doctype_are_allowed() 
throws Exception
+    {
+
+        List<TemplateToken> tokens = tokens("html_entities.tml");
+
+        assertEquals(tokens.size(), 3);
+
+        StartElementToken token0 = get(tokens, 0);
+
+        assertEquals(token0.name, "html");
+
+        TextToken token1 = get(tokens, 1);
+
+        assertEquals(token1.text, "\n[\u00A0]\n");
+
+    }
 }

Added: 
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/html_entities.tml
URL: 
http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/html_entities.tml?rev=1188867&view=auto
==============================================================================
--- 
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/html_entities.tml
 (added)
+++ 
tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry5/internal/services/html_entities.tml
 Tue Oct 25 19:18:47 2011
@@ -0,0 +1,3 @@
+<html>
+    [&nbsp;]
+</html>
\ No newline at end of file


Reply via email to