001 package org.apache.myfaces.tobago.renderkit; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.slf4j.Logger; 021 import org.slf4j.LoggerFactory; 022 import org.apache.myfaces.tobago.application.ProjectStage; 023 import org.apache.myfaces.tobago.config.TobagoConfig; 024 import org.apache.myfaces.tobago.internal.webapp.DebugTobagoResponseWriterWrapper; 025 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseJsonWriterImpl; 026 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterImpl; 027 import org.apache.myfaces.tobago.internal.webapp.TobagoResponseXmlWriterImpl; 028 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter; 029 030 import javax.faces.FactoryFinder; 031 import javax.faces.context.FacesContext; 032 import javax.faces.context.ResponseStream; 033 import javax.faces.context.ResponseWriter; 034 import javax.faces.render.RenderKit; 035 import javax.faces.render.RenderKitFactory; 036 import javax.faces.render.Renderer; 037 import javax.faces.render.ResponseStateManager; 038 import java.io.OutputStream; 039 import java.io.Writer; 040 import java.util.HashMap; 041 import java.util.Map; 042 043 public class TobagoRenderKit extends RenderKit { 044 045 private static final Logger LOG = LoggerFactory.getLogger(TobagoRenderKit.class); 046 047 public static final String RENDER_KIT_ID = "tobago"; 048 049 private ResponseStateManager responseStateManager = new TobagoResponseStateManager(); 050 051 private RenderKit htmlBasicRenderKit; 052 053 private Map<Key, Renderer> renderers = new HashMap<Key, Renderer>(); 054 055 @Override 056 public Renderer getRenderer(String family, String rendererType) { 057 if (LOG.isDebugEnabled()) { 058 LOG.debug("family = '" + family + "'"); 059 } 060 Renderer renderer = renderers.get(new Key(family, rendererType)); 061 if (renderer == null) { 062 RenderKit renderKit = getHtmlBasicRenderKit(); 063 renderer = renderKit.getRenderer(family, rendererType); 064 if (renderer != null) { 065 renderer = new RendererBaseWrapper(renderer); 066 } 067 } 068 069 if (renderer == null) { 070 LOG.error("The class which was found by the ResourceManager cannot be " 071 + "found or instantiated: classname='" + rendererType + "'"); 072 } 073 074 return renderer; 075 } 076 077 private RenderKit getHtmlBasicRenderKit() { 078 if (htmlBasicRenderKit == null) { 079 RenderKitFactory rkFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY); 080 htmlBasicRenderKit = 081 rkFactory.getRenderKit(FacesContext.getCurrentInstance(), RenderKitFactory.HTML_BASIC_RENDER_KIT); 082 } 083 return htmlBasicRenderKit; 084 } 085 086 @Override 087 public ResponseWriter createResponseWriter( 088 Writer writer, String contentTypeList, String characterEncoding) { 089 String contentType; 090 if (contentTypeList == null) { 091 contentType = "text/html"; 092 } else if (contentTypeList.indexOf("text/html") > -1) { 093 contentType = "text/html"; 094 LOG.warn("patching content type from " + contentTypeList + " to " + contentType + "'"); 095 } else if (contentTypeList.indexOf("text/fo") > -1) { 096 contentType = "text/fo"; 097 LOG.warn("patching content type from " + contentTypeList + " to " + contentType + "'"); 098 } else if (contentTypeList.indexOf("application/json") > -1) { 099 return new TobagoResponseJsonWriterImpl(writer, "application/json", characterEncoding); 100 } else { 101 contentType = "text/html"; 102 LOG.warn("Content-Type '" + contentTypeList + "' not supported! Using text/html"); 103 } 104 105 boolean xml = false; 106 if ("application/xhtml".equals(contentType) 107 || "application/xml".equals(contentType) 108 || "text/xml".equals(contentType)) { 109 xml = true; 110 } 111 // XXX for XHTML 1.0 the content type must be set to "text/html" for IE6 112 // XXX so at this time we can't differ ... 113 // xml = true; 114 TobagoResponseWriter responseWriter; 115 if (xml) { 116 responseWriter = new TobagoResponseXmlWriterImpl(writer, contentType, characterEncoding); 117 } else { 118 responseWriter = new TobagoResponseWriterImpl(writer, contentType, characterEncoding); 119 } 120 if (TobagoConfig.getInstance(FacesContext.getCurrentInstance()).getProjectStage() == ProjectStage.Development) { 121 return new DebugTobagoResponseWriterWrapper(responseWriter); 122 } 123 return responseWriter; 124 } 125 126 @Override 127 public void addRenderer(String family, String rendererType, Renderer renderer) { 128 renderers.put(new Key(family, rendererType), renderer); 129 } 130 131 @Override 132 public ResponseStateManager getResponseStateManager() { 133 //return getHtmlBasicRenderKit().getResponseStateManager(); 134 return responseStateManager; 135 } 136 137 @Override 138 public ResponseStream createResponseStream(OutputStream outputStream) { 139 return getHtmlBasicRenderKit().createResponseStream(outputStream); 140 } 141 142 private static final class Key { 143 private final String family; 144 private final String rendererType; 145 146 private Key(String family, String rendererType) { 147 this.family = family; 148 this.rendererType = rendererType; 149 } 150 151 public boolean equals(Object o) { 152 if (this == o) { 153 return true; 154 } 155 if (o == null || getClass() != o.getClass()) { 156 return false; 157 } 158 159 Key key = (Key) o; 160 161 if (!family.equals(key.family)) { 162 return false; 163 } 164 if (!rendererType.equals(key.rendererType)) { 165 return false; 166 } 167 168 return true; 169 } 170 171 public int hashCode() { 172 int result; 173 result = family.hashCode(); 174 result = 31 * result + rendererType.hashCode(); 175 return result; 176 } 177 } 178 }