You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2021/04/06 09:36:52 UTC

[myfaces] branch master updated: MYFACES-4393 - Faces 4.0: Add docType

This is an automated email from the ASF dual-hosted git repository.

tandraschko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/myfaces.git


The following commit(s) were added to refs/heads/master by this push:
     new ac5ebd1  MYFACES-4393 - Faces 4.0: Add docType
ac5ebd1 is described below

commit ac5ebd1be15e30c10ac449de58a46fa8fb4a393d
Author: Thomas Andraschko <ta...@apache.org>
AuthorDate: Tue Apr 6 11:36:44 2021 +0200

    MYFACES-4393 - Faces 4.0: Add docType
---
 .../main/java/jakarta/faces/component/Doctype.java | 50 +++++++++++
 .../java/jakarta/faces/component/UIViewRoot.java   | 30 ++++++-
 .../jakarta/faces/component/html/_HtmlDoctype.java | 40 ++++-----
 .../myfaces/view/facelets/AbstractFacelet.java     |  3 +
 .../apache/myfaces/view/facelets/DoctypeImpl.java  | 58 +++++++++++++
 .../view/facelets/compiler/CompilationManager.java | 10 +++
 .../view/facelets/compiler/CompilationUnit.java    |  2 +-
 .../myfaces/view/facelets/compiler/Compiler.java   | 49 +++++++++--
 .../view/facelets/compiler/SAXCompiler.java        | 36 +++-----
 .../myfaces/view/facelets/impl/DefaultFacelet.java | 25 ++++--
 .../view/facelets/impl/DefaultFaceletFactory.java  | 21 +++--
 .../facelets/compiler/doctype/DoctypeTestCase.java | 98 ++++++++++++++++++++++
 .../view/facelets/compiler/doctype/html5.xhtml     | 25 ++++++
 .../view/facelets/compiler/doctype/xhtml.xhtml     | 25 ++++++
 14 files changed, 395 insertions(+), 77 deletions(-)

diff --git a/api/src/main/java/jakarta/faces/component/Doctype.java b/api/src/main/java/jakarta/faces/component/Doctype.java
new file mode 100644
index 0000000..8494185
--- /dev/null
+++ b/api/src/main/java/jakarta/faces/component/Doctype.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 jakarta.faces.component;
+
+/**
+ * <p class="changed_added_4_0">
+ * <strong>Doctype</strong> is an interface that must be implemented by any {@link UIComponent} that represents a document type declaration.
+ * </p>
+ *
+ * @since 4.0
+ */
+public interface Doctype {
+
+    /**
+     * Returns the name of the first element in the document, never <code>null</code>.
+     * For example, <code>"html"</code>.
+     * @return The name of the first element in the document, never <code>null</code>.
+     */
+    String getRootElement();
+
+    /**
+     * Returns the public identifier of the document, or <code>null</code> if there is none.
+     * For example, <code>"-//W3C//DTD XHTML 1.1//EN"</code>.
+     * @return The public identifier of the document, or <code>null</code> if there is none.
+     */
+    String getPublic();
+
+    /**
+     * Returns the system identifier of the document, or <code>null</code> if there is none.
+     * For example, <code>"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"</code>.
+     * @return The system identifier of the document, or <code>null</code> if there is none.
+     */
+    String getSystem();
+}
diff --git a/api/src/main/java/jakarta/faces/component/UIViewRoot.java b/api/src/main/java/jakarta/faces/component/UIViewRoot.java
index 576d67c..e28d459 100644
--- a/api/src/main/java/jakarta/faces/component/UIViewRoot.java
+++ b/api/src/main/java/jakarta/faces/component/UIViewRoot.java
@@ -171,6 +171,8 @@ public class UIViewRoot extends UIComponentBase implements UniqueIdVendor
     private transient boolean _resourceDependencyUniqueId;
     private transient Map<String,Object> _attributesMap;
     
+    private Doctype doctype;
+    
     /**
      * Construct an instance of the UIViewRoot.
      */
@@ -470,7 +472,7 @@ public class UIViewRoot extends UIComponentBase implements UniqueIdVendor
 
         // Generate an identifier for a component. The identifier will be prefixed with
         // UNIQUE_ID_PREFIX, and will be unique within this UIViewRoot.
-        if(seed==null)
+        if(seed == null)
         {
             if (isResourceDependencyUniqueId())
             {
@@ -972,7 +974,7 @@ public class UIViewRoot extends UIComponentBase implements UniqueIdVendor
 
     public void setLocale(Locale locale)
     {
-        getStateHelper().put(PropertyKeys.locale, locale );
+        getStateHelper().put(PropertyKeys.locale, locale);
     }
 
     /**
@@ -1986,4 +1988,28 @@ public class UIViewRoot extends UIComponentBase implements UniqueIdVendor
 
         return alwaysPerformValidationWhenRequiredTrue;
     }    
+
+    /**
+     * <p>
+     * Return the doctype of this view.
+     * </p>
+     *
+     * @return the doctype of this view.
+     * @since 4.0
+     */
+    public Doctype getDoctype() {
+        return doctype;
+    }
+
+    /**
+     * <p>
+     * Set the doctype of this view.
+     * </p>
+     *
+     * @param doctype The doctype.
+     * @since 4.0
+     */
+    public void setDoctype(Doctype doctype) {
+        this.doctype = doctype;
+    }
 }
diff --git a/api/src/main/java/jakarta/faces/component/html/_HtmlDoctype.java b/api/src/main/java/jakarta/faces/component/html/_HtmlDoctype.java
index 6d2af2c..554c807 100644
--- a/api/src/main/java/jakarta/faces/component/html/_HtmlDoctype.java
+++ b/api/src/main/java/jakarta/faces/component/html/_HtmlDoctype.java
@@ -18,6 +18,7 @@
  */
 package jakarta.faces.component.html;
 
+import jakarta.faces.component.Doctype;
 import jakarta.faces.component.UIOutput;
 
 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
@@ -28,31 +29,22 @@ import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFPropert
  */
 @JSFComponent(name="h:doctype", clazz = "jakarta.faces.component.html.HtmlDoctype",
         defaultRendererType="jakarta.faces.Doctype",template=true)
-abstract class _HtmlDoctype extends UIOutput
+abstract class _HtmlDoctype extends UIOutput implements Doctype
 {
 
-  static public final String COMPONENT_FAMILY = "jakarta.faces.Output";
-  static public final String COMPONENT_TYPE = "jakarta.faces.OutputDoctype";
-
-  /**
-   * 
-   * @return
-   */
-  @JSFProperty
-  public abstract String getPublic();
-  
-  /**
-   * 
-   * @return
-   */
-  @JSFProperty
-  public abstract String getRootElement(); 
-  
-  /**
-   * 
-   * @return
-   */
-  @JSFProperty
-  public abstract String getSystem(); 
+    static public final String COMPONENT_FAMILY = "jakarta.faces.Output";
+    static public final String COMPONENT_TYPE = "jakarta.faces.OutputDoctype";
+
+    @JSFProperty
+    @Override
+    public abstract String getPublic();
+
+    @JSFProperty
+    @Override
+    public abstract String getRootElement(); 
+
+    @JSFProperty
+    @Override
+    public abstract String getSystem(); 
 
 }
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFacelet.java b/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFacelet.java
index a8a8803..53c348c 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFacelet.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFacelet.java
@@ -25,6 +25,7 @@ import jakarta.el.ELException;
 import jakarta.el.ExpressionFactory;
 import jakarta.faces.FacesException;
 import jakarta.faces.application.Resource;
+import jakarta.faces.component.Doctype;
 import jakarta.faces.component.UIComponent;
 import jakarta.faces.context.FacesContext;
 import jakarta.faces.view.facelets.Facelet;
@@ -107,4 +108,6 @@ public abstract class AbstractFacelet extends Facelet
     {
         return getAlias(); 
     }
+    
+    public abstract Doctype getDoctype();
 }
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/DoctypeImpl.java b/impl/src/main/java/org/apache/myfaces/view/facelets/DoctypeImpl.java
new file mode 100644
index 0000000..db4357b
--- /dev/null
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/DoctypeImpl.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.view.facelets;
+
+import jakarta.faces.component.Doctype;
+import java.io.Serializable;
+
+public class DoctypeImpl implements Serializable, Doctype
+{
+    private String rootElement;
+    private String publicId;
+    private String system;
+
+    public DoctypeImpl()
+    {
+    }
+
+    public DoctypeImpl(String rootElement, String publicId, String system)
+    {
+        this.rootElement = rootElement;
+        this.publicId = publicId;
+        this.system = system;
+    }
+
+    @Override
+    public String getRootElement()
+    {
+        return rootElement;
+    }
+
+    @Override
+    public String getPublic()
+    {
+        return publicId;
+    }
+
+    @Override
+    public String getSystem()
+    {
+        return system;
+    }
+}
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationManager.java b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationManager.java
index c34e90e..2dde7fa 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationManager.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationManager.java
@@ -25,6 +25,7 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 
 import jakarta.faces.application.FacesMessage;
+import jakarta.faces.component.Doctype;
 import jakarta.faces.view.Location;
 import jakarta.faces.view.facelets.FaceletHandler;
 import jakarta.faces.view.facelets.Tag;
@@ -32,6 +33,7 @@ import jakarta.faces.view.facelets.TagAttribute;
 import jakarta.faces.view.facelets.TagAttributeException;
 import jakarta.faces.view.facelets.TagDecorator;
 import jakarta.faces.view.facelets.TagException;
+import org.apache.myfaces.view.facelets.DoctypeImpl;
 
 import org.apache.myfaces.view.facelets.tag.TagAttributesImpl;
 import org.apache.myfaces.view.facelets.tag.TagLibrary;
@@ -74,6 +76,8 @@ final class CompilationManager
     private CompilationUnit interfaceCompilationUnit;
     
     private final FaceletsProcessingInstructions faceletsProcessingInstructions;
+    
+    private Doctype doctype;
 
     public CompilationManager(String alias, Compiler compiler, FaceletsProcessingInstructions instructions)
     {
@@ -141,6 +145,7 @@ final class CompilationManager
 
         DoctypeUnit unit = new DoctypeUnit(this.alias, this.nextTagId(),
             name, publicId, systemId, faceletsProcessingInstructions.isHtml5Doctype());
+        this.doctype = new DoctypeImpl(name, publicId, systemId);
         this.startUnit(unit);
     }
 
@@ -598,5 +603,10 @@ final class CompilationManager
     {
         return faceletsProcessingInstructions;
     }
+
+    public Doctype getDoctype()
+    {
+        return doctype;
+    }
 }
 
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationUnit.java b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationUnit.java
index 5e82efe..3fa282f 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationUnit.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/CompilationUnit.java
@@ -62,7 +62,7 @@ class CompilationUnit
     {
         if (this.children == null)
         {
-            this.children = new ArrayList<CompilationUnit>();
+            this.children = new ArrayList<>();
         }
         this.children.add(unit);
     }
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/Compiler.java b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/Compiler.java
index 8e609e2..bccc2fa 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/Compiler.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/Compiler.java
@@ -30,6 +30,7 @@ import java.util.logging.Logger;
 import jakarta.el.ELException;
 import jakarta.el.ExpressionFactory;
 import jakarta.faces.FacesException;
+import jakarta.faces.component.Doctype;
 import jakarta.faces.context.FacesContext;
 import jakarta.faces.view.facelets.FaceletException;
 import jakarta.faces.view.facelets.FaceletHandler;
@@ -74,40 +75,40 @@ public abstract class Compiler
 
     }
 
-    public final FaceletHandler compile(URL src, String alias) throws IOException, FaceletException, ELException,
+    public final CompilerResult compile(URL src, String alias) throws IOException, FaceletException, ELException,
             FacesException
     {
         return this.doCompile(src, alias);
     }
     
-    public final FaceletHandler compileViewMetadata(URL src, String alias)
+    public final CompilerResult compileViewMetadata(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException
     {
         return this.doCompileViewMetadata(src, alias);
     }
     
-    public final FaceletHandler compileCompositeComponentMetadata(URL src, String alias)
+    public final CompilerResult compileCompositeComponentMetadata(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException
     {
         return this.doCompileCompositeComponentMetadata(src, alias);
     }
     
-    public final FaceletHandler compileComponent(
+    public final CompilerResult compileComponent(
         String taglibURI, String tagName, Map<String,Object> attributes)
     {
         return this.doCompileComponent(taglibURI, tagName, attributes);
     }
 
-    protected abstract FaceletHandler doCompile(URL src, String alias)
+    protected abstract CompilerResult doCompile(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException;
 
-    protected abstract FaceletHandler doCompileViewMetadata(URL src, String alias)
+    protected abstract CompilerResult doCompileViewMetadata(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException;
     
-    protected abstract FaceletHandler doCompileCompositeComponentMetadata(URL src, String alias)
+    protected abstract CompilerResult doCompileCompositeComponentMetadata(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException;
     
-    protected abstract FaceletHandler doCompileComponent(
+    protected abstract CompilerResult doCompileComponent(
         String taglibURI, String tagName, Map<String,Object> attributes);
 
     public final TagDecorator createTagDecorator()
@@ -261,5 +262,37 @@ public abstract class Compiler
     {
         this.faceletsProcessingConfigurations = faceletsProcessingConfigurations;
     }
+    
+    public static class CompilerResult
+    {
+        private FaceletHandler faceletHandler;
+        private Doctype doctype;
+
+        CompilerResult(FaceletHandler faceletHandler, Doctype doctype)
+        {
+            this.faceletHandler = faceletHandler;
+            this.doctype = doctype;
+        }
+
+        public FaceletHandler getFaceletHandler()
+        {
+            return faceletHandler;
+        }
+
+        public void setFaceletHandler(FaceletHandler faceletHandler)
+        {
+            this.faceletHandler = faceletHandler;
+        }
+
+        public Doctype getDoctype()
+        {
+            return doctype;
+        }
+
+        public void setDoctypeUnit(Doctype doctype)
+        {
+            this.doctype = doctype;
+        }
+    }
 }
 
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/SAXCompiler.java b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/SAXCompiler.java
index c65c6bc..26c9004 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/SAXCompiler.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/compiler/SAXCompiler.java
@@ -247,24 +247,6 @@ public final class SAXCompiler extends Compiler
             if (this.inDocument && !unit.getFaceletsProcessingInstructions().isConsumeXmlDocType())
             {
                 this.unit.writeDoctype(name, publicId, systemId);
-                /*
-                StringBuffer sb = new StringBuffer(64);
-                sb.append("<!DOCTYPE ").append(name);
-                if (publicId != null)
-                {
-                    sb.append(" PUBLIC \"").append(publicId).append("\"");
-                    if (systemId != null)
-                    {
-                        sb.append(" \"").append(systemId).append("\"");
-                    }
-                }
-                else if (systemId != null)
-                {
-                    sb.append(" SYSTEM \"").append(systemId).append("\"");
-                }
-                sb.append(" >\n");
-                this.unit.writeInstruction(sb.toString());
-                */
             }
             this.inDocument = false;
         }
@@ -813,7 +795,7 @@ public final class SAXCompiler extends Compiler
     }
 
     @Override
-    public FaceletHandler doCompile(URL src, String alias)
+    public CompilerResult doCompile(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException
     {
         CompilationManager mngr = null;
@@ -843,14 +825,14 @@ public final class SAXCompiler extends Compiler
                 is.close();
             }
         }
-        return new EncodingHandler(mngr.createFaceletHandler(), encoding);
+        return new CompilerResult(new EncodingHandler(mngr.createFaceletHandler(), encoding), mngr.getDoctype());
     }
 
     /**
      * @since 2.0
      */
     @Override
-    protected FaceletHandler doCompileViewMetadata(URL src, String alias)
+    protected CompilerResult doCompileViewMetadata(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException
     {
         CompilationManager mngr = null;
@@ -907,14 +889,14 @@ public final class SAXCompiler extends Compiler
                 is.close();
             }
         }
-        return new EncodingHandler(mngr.createFaceletHandler(), encoding);
+        return new CompilerResult(new EncodingHandler(mngr.createFaceletHandler(), encoding), mngr.getDoctype());
     }
 
     /**
      * @since 2.0.1
      */
     @Override
-    protected FaceletHandler doCompileCompositeComponentMetadata(URL src, String alias)
+    protected CompilerResult doCompileCompositeComponentMetadata(URL src, String alias)
             throws IOException, FaceletException, ELException, FacesException
     {
         CompilationManager mngr = null;
@@ -928,6 +910,8 @@ public final class SAXCompiler extends Compiler
             CompositeComponentMetadataHandler handler = new CompositeComponentMetadataHandler(mngr, alias);
             SAXParser parser = this.createSAXParser(handler);
             parser.parse(is, handler);
+            
+            
         }
         catch (SAXException e)
         {
@@ -944,11 +928,11 @@ public final class SAXCompiler extends Compiler
                 is.close();
             }
         }
-        return new EncodingHandler(mngr.createFaceletHandler(), encoding);
+        return new CompilerResult(new EncodingHandler(mngr.createFaceletHandler(), encoding), mngr.getDoctype());
     }
     
     @Override
-    protected FaceletHandler doCompileComponent(
+    protected CompilerResult doCompileComponent(
         String taglibURI, String tagName, Map<String, Object> attributes)
     {
         String alias = tagName;
@@ -1026,7 +1010,7 @@ public final class SAXCompiler extends Compiler
         mngr.popNamespace(prefix);
         
         FaceletHandler handler = new DynamicComponentFacelet((NamespaceHandler) mngr.createFaceletHandler());
-        return handler;
+        return new CompilerResult(handler, mngr.getDoctype());
     }
     
     protected FaceletsProcessingInstructions getDefaultFaceletsProcessingInstructions()
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFacelet.java b/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFacelet.java
index 584a2a9..cdca8b6 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFacelet.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFacelet.java
@@ -40,6 +40,7 @@ import jakarta.el.ExpressionFactory;
 import jakarta.faces.FacesException;
 import jakarta.faces.application.Resource;
 import jakarta.faces.application.ViewResource;
+import jakarta.faces.component.Doctype;
 import jakarta.faces.component.UIComponent;
 import jakarta.faces.component.UIViewRoot;
 import jakarta.faces.component.UniqueIdVendor;
@@ -80,9 +81,10 @@ final class DefaultFacelet extends AbstractFacelet
     private final boolean _isBuildingCompositeComponentMetadata; 
     private final boolean _encodingHandler;
     private final boolean viewUniqueIdsCacheEnabled;
+    private final Doctype doctype;
 
     public DefaultFacelet(DefaultFaceletFactory factory, ExpressionFactory el, URL src, String alias,
-                          String faceletId, FaceletHandler root, boolean viewUniqueIdsCacheEnabled)
+                          String faceletId, FaceletHandler root, boolean viewUniqueIdsCacheEnabled, Doctype doctype)
     {
         _factory = factory;
         _elFactory = el;
@@ -97,11 +99,12 @@ final class DefaultFacelet extends AbstractFacelet
         _isBuildingCompositeComponentMetadata = false;
         _encodingHandler = (root instanceof EncodingHandler);
         this.viewUniqueIdsCacheEnabled = viewUniqueIdsCacheEnabled;
+        this.doctype = doctype;
     }
 
     public DefaultFacelet(DefaultFaceletFactory factory, ExpressionFactory el, URL src, String alias,
             String faceletId, FaceletHandler root, boolean isBuildingCompositeComponentMetadata,
-            boolean viewUniqueIdsCacheEnabled)
+            boolean viewUniqueIdsCacheEnabled, Doctype doctype)
     {
         _factory = factory;
         _elFactory = el;
@@ -116,6 +119,7 @@ final class DefaultFacelet extends AbstractFacelet
         _isBuildingCompositeComponentMetadata = isBuildingCompositeComponentMetadata;
         _encodingHandler = (root instanceof EncodingHandler);
         this.viewUniqueIdsCacheEnabled = viewUniqueIdsCacheEnabled;
+        this.doctype = doctype;
     }    
 
     /**
@@ -152,8 +156,8 @@ final class DefaultFacelet extends AbstractFacelet
             }
             if (parent instanceof UIViewRoot)
             {
-                myFaceletContext.setViewRoot((UIViewRoot)parent);
-                ComponentSupport.setCachedFacesContext((UIViewRoot)parent, facesContext);
+                myFaceletContext.setViewRoot((UIViewRoot) parent);
+                ComponentSupport.setCachedFacesContext((UIViewRoot) parent, facesContext);
             }
         }
         DefaultFaceletContext ctx = new DefaultFaceletContext(facesContext, this, myFaceletContext);
@@ -177,6 +181,11 @@ final class DefaultFacelet extends AbstractFacelet
                 pushedUniqueIdVendor = true;
             }
             
+            if (parent instanceof UIViewRoot)
+            {
+                ((UIViewRoot) parent).setDoctype(getDoctype());
+            }
+
             this.refresh(parent);
             myFaceletContext.markForDeletion(parent);
             _root.apply(ctx, parent);
@@ -214,7 +223,7 @@ final class DefaultFacelet extends AbstractFacelet
             {
                 if (parent instanceof UIViewRoot)
                 {
-                    ComponentSupport.setCachedFacesContext((UIViewRoot)parent, null);
+                    ComponentSupport.setCachedFacesContext((UIViewRoot) parent, null);
                 }
                 myFaceletContext.release(facesContext);
                 List<String> uniqueIdList = ((EncodingHandler)_root).getUniqueIdList();
@@ -656,4 +665,10 @@ final class DefaultFacelet extends AbstractFacelet
     {
         return _isBuildingCompositeComponentMetadata;
     }
+
+    @Override
+    public Doctype getDoctype()
+    {
+        return doctype;
+    }
 }
diff --git a/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletFactory.java b/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletFactory.java
index fe0e321..eeec952 100644
--- a/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletFactory.java
+++ b/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletFactory.java
@@ -38,7 +38,6 @@ import jakarta.faces.view.facelets.FaceletCache;
 import jakarta.faces.view.facelets.FaceletCacheFactory;
 import jakarta.faces.view.facelets.FaceletContext;
 import jakarta.faces.view.facelets.FaceletException;
-import jakarta.faces.view.facelets.FaceletHandler;
 import jakarta.faces.view.facelets.ResourceResolver;
 import org.apache.myfaces.config.MyfacesConfig;
 
@@ -337,9 +336,9 @@ public final class DefaultFaceletFactory extends FaceletFactory
         String alias = '/' + _removeFirst(url.getFile(), baseUrl == null ? "" : baseUrl.getFile());
         try
         {
-            FaceletHandler h = _compiler.compile(url, alias);
-            DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias, alias, h,
-                viewUniqueIdsCacheEnabled);
+            Compiler.CompilerResult result = _compiler.compile(url, alias);
+            DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias, alias,
+                    result.getFaceletHandler(), viewUniqueIdsCacheEnabled, result.getDoctype());
             return f;
         }
         catch (FileNotFoundException fnfe)
@@ -372,9 +371,9 @@ public final class DefaultFaceletFactory extends FaceletFactory
         String alias = "/viewMetadata" + faceletId;
         try
         {
-            FaceletHandler h = _compiler.compileViewMetadata(url, alias);
+            Compiler.CompilerResult result = _compiler.compileViewMetadata(url, alias);
             DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias, 
-                    faceletId, h, viewUniqueIdsCacheEnabled);
+                    faceletId, result.getFaceletHandler(), viewUniqueIdsCacheEnabled, result.getDoctype());
             return f;
         }
         catch (FileNotFoundException fnfe)
@@ -407,9 +406,9 @@ public final class DefaultFaceletFactory extends FaceletFactory
                 baseUrl == null ? "" : baseUrl.getFile());
         try
         {
-            FaceletHandler h = _compiler.compileCompositeComponentMetadata(url, alias);
+            Compiler.CompilerResult result = _compiler.compileCompositeComponentMetadata(url, alias);
             DefaultFacelet f = new DefaultFacelet(this, _compiler.createExpressionFactory(), url, alias,
-                    alias, h, true, viewUniqueIdsCacheEnabled);
+                    alias, result.getFaceletHandler(), true, viewUniqueIdsCacheEnabled, result.getDoctype());
             return f;
         }
         catch (FileNotFoundException fnfe)
@@ -558,10 +557,10 @@ public final class DefaultFaceletFactory extends FaceletFactory
     @Override
     public Facelet compileComponentFacelet(String taglibURI, String tagName, Map<String,Object> attributes)
     {
-        FaceletHandler handler = _compiler.compileComponent(taglibURI, tagName, attributes);
+        Compiler.CompilerResult result = _compiler.compileComponent(taglibURI, tagName, attributes);
         String alias = "/component/oamf:"+tagName;
-        return new DefaultFacelet(this, _compiler.createExpressionFactory(), getBaseUrl(), alias, alias, handler,
-                viewUniqueIdsCacheEnabled);
+        return new DefaultFacelet(this, _compiler.createExpressionFactory(), getBaseUrl(), alias, alias,
+                result.getFaceletHandler(), viewUniqueIdsCacheEnabled, result.getDoctype());
     }
     
     /**
diff --git a/impl/src/test/java/org/apache/myfaces/view/facelets/compiler/doctype/DoctypeTestCase.java b/impl/src/test/java/org/apache/myfaces/view/facelets/compiler/doctype/DoctypeTestCase.java
new file mode 100644
index 0000000..862b867
--- /dev/null
+++ b/impl/src/test/java/org/apache/myfaces/view/facelets/compiler/doctype/DoctypeTestCase.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.myfaces.view.facelets.compiler.doctype;
+import org.apache.myfaces.view.facelets.tag.ui.*;
+
+import jakarta.faces.component.UIViewRoot;
+import jakarta.faces.view.facelets.Facelet;
+
+import org.apache.myfaces.view.facelets.AbstractFacelet;
+import org.apache.myfaces.view.facelets.FaceletFactory;
+import org.apache.myfaces.view.facelets.FaceletTestCase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class DoctypeTestCase extends FaceletTestCase
+{
+
+    @Override
+    protected void setupComponents() throws Exception
+    {
+        application.addComponent(UIViewRoot.COMPONENT_TYPE, UIViewRoot.class
+                .getName());
+        application.addComponent(ComponentRef.COMPONENT_TYPE,
+                ComponentRef.class.getName());
+    }
+
+    @Override
+    protected void setupConvertersAndValidators() throws Exception
+    {
+    }
+
+    @Override
+    protected void setupRenderers() throws Exception
+    {
+    }
+
+    @Test
+    public void testCompilerHtml5() throws Exception {
+        FaceletFactory ff = vdl.getFaceletFactory();
+        Facelet f = ff.getFacelet(this.getClass().getResource("/org/apache/myfaces/view/facelets/compiler/doctype/html5.xhtml"));
+        
+        Assert.assertNotNull(((AbstractFacelet) f).getDoctype());
+        Assert.assertEquals("html", ((AbstractFacelet) f).getDoctype().getRootElement());
+        Assert.assertEquals(null, ((AbstractFacelet) f).getDoctype().getPublic());
+        Assert.assertEquals(null, ((AbstractFacelet) f).getDoctype().getSystem());
+    }
+    
+    @Test
+    public void testCompilerXhtml() throws Exception {
+        FaceletFactory ff = vdl.getFaceletFactory();
+        Facelet f = ff.getFacelet(this.getClass().getResource("/org/apache/myfaces/view/facelets/compiler/doctype/xhtml.xhtml"));
+        
+        Assert.assertNotNull(((AbstractFacelet) f).getDoctype());
+        Assert.assertEquals("html", ((AbstractFacelet) f).getDoctype().getRootElement());
+        Assert.assertEquals("-//W3C//DTD XHTML 1.0 Transitional//EN", ((AbstractFacelet) f).getDoctype().getPublic());
+        Assert.assertEquals("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd", ((AbstractFacelet) f).getDoctype().getSystem());
+    }
+    
+    @Test
+    public void testHtml5() throws Exception
+    {
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "html5.xhtml");
+
+        Assert.assertNotNull(root.getDoctype());
+        Assert.assertEquals("html", root.getDoctype().getRootElement());
+        Assert.assertEquals(null, root.getDoctype().getPublic());
+        Assert.assertEquals(null, root.getDoctype().getSystem());
+    }
+    
+    @Test
+    public void testXhtml() throws Exception
+    {
+        UIViewRoot root = facesContext.getViewRoot();
+        vdl.buildView(facesContext, root, "xhtml.xhtml");
+
+        Assert.assertNotNull(root.getDoctype());
+        Assert.assertEquals("html", root.getDoctype().getRootElement());
+        Assert.assertEquals("-//W3C//DTD XHTML 1.0 Transitional//EN", root.getDoctype().getPublic());
+        Assert.assertEquals("http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd", root.getDoctype().getSystem());
+    }
+}
diff --git a/impl/src/test/resources/org/apache/myfaces/view/facelets/compiler/doctype/html5.xhtml b/impl/src/test/resources/org/apache/myfaces/view/facelets/compiler/doctype/html5.xhtml
new file mode 100644
index 0000000..1ace4ef
--- /dev/null
+++ b/impl/src/test/resources/org/apache/myfaces/view/facelets/compiler/doctype/html5.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+ 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.
+
+ $Id: include.xhtml,v 1.2 2008/07/13 19:01:37 rlubke Exp $
+-->
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+
+    </head>
+    <body>
+
+    </body>
+</html>
diff --git a/impl/src/test/resources/org/apache/myfaces/view/facelets/compiler/doctype/xhtml.xhtml b/impl/src/test/resources/org/apache/myfaces/view/facelets/compiler/doctype/xhtml.xhtml
new file mode 100644
index 0000000..c1d3a81
--- /dev/null
+++ b/impl/src/test/resources/org/apache/myfaces/view/facelets/compiler/doctype/xhtml.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!--
+ 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.
+
+ $Id: include.xhtml,v 1.2 2008/07/13 19:01:37 rlubke Exp $
+-->
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+    <head>
+
+    </head>
+    <body>
+
+    </body>
+</html>
\ No newline at end of file