1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.tobago.renderkit;
21
22 import org.apache.myfaces.tobago.ajax.AjaxUtils;
23 import org.apache.myfaces.tobago.application.ProjectStage;
24 import org.apache.myfaces.tobago.config.TobagoConfig;
25 import org.apache.myfaces.tobago.context.Capability;
26 import org.apache.myfaces.tobago.internal.webapp.DebugResponseWriterWrapper;
27 import org.apache.myfaces.tobago.internal.webapp.HtmlResponseWriter;
28 import org.apache.myfaces.tobago.internal.webapp.JsonResponseWriter;
29 import org.apache.myfaces.tobago.internal.webapp.XmlResponseWriter;
30 import org.apache.myfaces.tobago.util.FacesVersion;
31 import org.apache.myfaces.tobago.util.VariableResolverUtils;
32 import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import javax.faces.FactoryFinder;
37 import javax.faces.context.FacesContext;
38 import javax.faces.context.ResponseStream;
39 import javax.faces.context.ResponseWriter;
40 import javax.faces.render.RenderKit;
41 import javax.faces.render.RenderKitFactory;
42 import javax.faces.render.Renderer;
43 import javax.faces.render.ResponseStateManager;
44 import java.io.OutputStream;
45 import java.io.Writer;
46 import java.util.HashMap;
47 import java.util.Map;
48
49 public class TobagoRenderKit extends RenderKit {
50
51 private static final Logger LOG = LoggerFactory.getLogger(TobagoRenderKit.class);
52
53 public static final String RENDER_KIT_ID = "tobago";
54
55 private ResponseStateManager responseStateManager = new TobagoResponseStateManager();
56
57 private RenderKit htmlBasicRenderKit;
58
59 private Map<Key, Renderer> renderers = new HashMap<Key, Renderer>();
60
61 public TobagoRenderKit() {
62 if (LOG.isDebugEnabled()) {
63 LOG.debug("Creating TobagoRenderKit");
64 }
65 }
66
67 @Override
68 public Renderer getRenderer(String family, String rendererType) {
69 Renderer renderer = renderers.get(new Key(family, rendererType));
70 if (renderer == null) {
71 RenderKit renderKit = getHtmlBasicRenderKit();
72 renderer = renderKit.getRenderer(family, rendererType);
73 if (renderer != null) {
74 renderer = new RendererBaseWrapper(renderer);
75 }
76 }
77
78 if (renderer == null) {
79 LOG.error("The class which was found by the ResourceManager cannot be "
80 + "found or instantiated: classname='" + rendererType + "'");
81 }
82
83 return renderer;
84 }
85
86 private RenderKit getHtmlBasicRenderKit() {
87 if (htmlBasicRenderKit == null) {
88 RenderKitFactory rkFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
89 htmlBasicRenderKit =
90 rkFactory.getRenderKit(FacesContext.getCurrentInstance(), RenderKitFactory.HTML_BASIC_RENDER_KIT);
91 }
92 return htmlBasicRenderKit;
93 }
94
95 @Override
96 public ResponseWriter createResponseWriter(
97 Writer writer, String contentTypeList, String characterEncoding) {
98 String contentType;
99 FacesContext facesContext = FacesContext.getCurrentInstance();
100 if (AjaxUtils.isAjaxRequest(facesContext)) {
101 return new JsonResponseWriter(writer, "application/json", characterEncoding);
102 }
103 if (contentTypeList == null) {
104 contentType = "text/html";
105 } else if (contentTypeList.indexOf("text/html") > -1) {
106 contentType = "text/html";
107 LOG.warn("patching content type from " + contentTypeList + " to " + contentType + "'");
108 } else if (contentTypeList.indexOf("text/fo") > -1) {
109 contentType = "text/fo";
110 LOG.warn("patching content type from " + contentTypeList + " to " + contentType + "'");
111 } else if (contentTypeList.indexOf("application/json") > -1) {
112 return new JsonResponseWriter(writer, "application/json", characterEncoding);
113 } else {
114 contentType = "text/html";
115 LOG.warn("Content-Type '" + contentTypeList + "' not supported! Using text/html");
116 }
117
118
119
120
121 boolean xml = false;
122 if ("application/xhtml+xml".equals(contentType)
123 || "application/xhtml".equals(contentType)
124 || "application/xml".equals(contentType)
125 || "text/xml".equals(contentType)) {
126 xml = true;
127 }
128
129
130 if (!VariableResolverUtils.resolveClientProperties(FacesContext.getCurrentInstance())
131 .getUserAgent().hasCapability(Capability.CONTENT_TYPE_XHTML)) {
132 contentType = "text/html";
133 }
134
135 TobagoResponseWriter responseWriter;
136 if (xml) {
137 responseWriter = new XmlResponseWriter(writer, contentType, characterEncoding);
138 } else {
139 responseWriter = new HtmlResponseWriter(writer, contentType, characterEncoding);
140 }
141 if (TobagoConfig.getInstance(facesContext).getProjectStage() == ProjectStage.Development) {
142 responseWriter = new DebugResponseWriterWrapper(responseWriter);
143 }
144 return responseWriter;
145 }
146
147 @Override
148 public void addRenderer(String family, String rendererType, Renderer renderer) {
149 renderers.put(new Key(family, rendererType), renderer);
150 }
151
152 @Override
153 public ResponseStateManager getResponseStateManager() {
154 if (FacesVersion.supports12() && FacesVersion.isMyfaces()
155 || FacesVersion.supports20() && FacesVersion.isMojarra()) {
156 return getHtmlBasicRenderKit().getResponseStateManager();
157 } else {
158 return responseStateManager;
159 }
160 }
161
162 @Override
163 public ResponseStream createResponseStream(OutputStream outputStream) {
164 return getHtmlBasicRenderKit().createResponseStream(outputStream);
165 }
166
167 private static final class Key {
168 private final String family;
169 private final String rendererType;
170
171 private Key(String family, String rendererType) {
172 this.family = family;
173 this.rendererType = rendererType;
174 }
175
176 public boolean equals(Object o) {
177 if (this == o) {
178 return true;
179 }
180 if (o == null || getClass() != o.getClass()) {
181 return false;
182 }
183
184 Key key = (Key) o;
185
186 if (!family.equals(key.family)) {
187 return false;
188 }
189 if (!rendererType.equals(key.rendererType)) {
190 return false;
191 }
192
193 return true;
194 }
195
196 public int hashCode() {
197 int result;
198 result = family.hashCode();
199 result = 31 * result + rendererType.hashCode();
200 return result;
201 }
202 }
203 }