001// Copyright 2007, 2008, 2009, 2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.internal.services; 016 017import java.util.List; 018 019import org.apache.tapestry5.ContentType; 020import org.apache.tapestry5.MarkupWriter; 021import org.apache.tapestry5.dom.DefaultMarkupModel; 022import org.apache.tapestry5.dom.Html5MarkupModel; 023import org.apache.tapestry5.dom.MarkupModel; 024import org.apache.tapestry5.dom.XMLMarkupModel; 025import org.apache.tapestry5.internal.parser.DTDToken; 026import org.apache.tapestry5.internal.parser.TemplateToken; 027import org.apache.tapestry5.internal.parser.TokenType; 028import org.apache.tapestry5.internal.structure.Page; 029import org.apache.tapestry5.model.ComponentModel; 030import org.apache.tapestry5.services.MarkupWriterFactory; 031import org.apache.tapestry5.services.pageload.ComponentRequestSelectorAnalyzer; 032import org.apache.tapestry5.services.pageload.ComponentResourceSelector; 033 034public class MarkupWriterFactoryImpl implements MarkupWriterFactory 035{ 036 private final PageContentTypeAnalyzer pageContentTypeAnalyzer; 037 038 private final RequestPageCache cache; 039 040 private final ComponentTemplateSource templateSource; 041 042 private final ComponentRequestSelectorAnalyzer componentRequestSelectorAnalyzer; 043 044 private final MarkupModel htmlModel = new DefaultMarkupModel(); 045 046 private final MarkupModel xmlModel = new XMLMarkupModel(); 047 048 private final MarkupModel htmlPartialModel = new DefaultMarkupModel(true); 049 050 private final MarkupModel xmlPartialModel = new XMLMarkupModel(true); 051 052 private final MarkupModel html5Model = new Html5MarkupModel(); 053 054 private final MarkupModel html5PartialModel = new Html5MarkupModel(true); 055 056 public MarkupWriterFactoryImpl(PageContentTypeAnalyzer pageContentTypeAnalyzer, 057 RequestPageCache cache, ComponentTemplateSource templateSource, 058 ComponentRequestSelectorAnalyzer componentRequestSelectorAnalyzer) 059 { 060 this.pageContentTypeAnalyzer = pageContentTypeAnalyzer; 061 this.cache = cache; 062 this.templateSource = templateSource; 063 this.componentRequestSelectorAnalyzer = componentRequestSelectorAnalyzer; 064 } 065 066 public MarkupWriter newMarkupWriter(ContentType contentType) 067 { 068 return constructMarkupWriter(contentType, false, false); 069 } 070 071 public MarkupWriter newPartialMarkupWriter(ContentType contentType) 072 { 073 return constructMarkupWriter(contentType, true, false); 074 } 075 076 private MarkupWriter constructMarkupWriter(ContentType contentType, boolean partial, boolean HTML5) 077 { 078 boolean isHTML = contentType.getMimeType().equalsIgnoreCase("text/html"); 079 080 MarkupModel model; 081 082 if(isHTML) 083 model = HTML5 ? (partial ? html5PartialModel : html5Model) : (partial ? htmlPartialModel : htmlModel); 084 else 085 model = partial ? xmlPartialModel : xmlModel; 086 // The charset parameter sets the encoding attribute of the XML declaration, if 087 // not null and if using the XML model. 088 089 return new MarkupWriterImpl(model, contentType.getCharset()); 090 } 091 092 public MarkupWriter newMarkupWriter(String pageName) 093 { 094 Page page = cache.get(pageName); 095 096 return newMarkupWriter(page); 097 } 098 099 private boolean hasHTML5Doctype(Page page) 100 { 101 ComponentModel componentModel = page.getRootComponent().getComponentResources().getComponentModel(); 102 103 ComponentResourceSelector selector = componentRequestSelectorAnalyzer.buildSelectorForRequest(); 104 105 List<TemplateToken> tokens = templateSource.getTemplate(componentModel, selector).getTokens(); 106 107 DTDToken dtd = null; 108 109 for(TemplateToken token : tokens) 110 { 111 if(token.getTokenType() == TokenType.DTD) 112 { 113 dtd = (DTDToken) token; 114 break; 115 } 116 } 117 118 return dtd != null && dtd.name.equalsIgnoreCase("html") && dtd.publicId == null && dtd.systemId == null; 119 } 120 121 public MarkupWriter newMarkupWriter(Page page) 122 { 123 boolean isHTML5 = hasHTML5Doctype(page); 124 125 ContentType contentType = pageContentTypeAnalyzer.findContentType(page); 126 127 return constructMarkupWriter(contentType, false, isHTML5); 128 } 129 130 public MarkupWriter newPartialMarkupWriter(Page page) 131 { 132 boolean isHTML5 = hasHTML5Doctype(page); 133 134 ContentType contentType = pageContentTypeAnalyzer.findContentType(page); 135 136 return constructMarkupWriter(contentType, true, isHTML5); 137 } 138 139 public MarkupWriter newPartialMarkupWriter(String pageName) 140 { 141 Page page = cache.get(pageName); 142 143 return newPartialMarkupWriter(page); 144 } 145}