001 // Copyright Mar 18, 2006 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 package org.apache.tapestry.services.impl; 015 016 import org.apache.hivemind.Resource; 017 import org.apache.hivemind.util.Defense; 018 import org.apache.tapestry.*; 019 import org.apache.tapestry.asset.AssetFactory; 020 import org.apache.tapestry.engine.NullWriter; 021 import org.apache.tapestry.markup.MarkupWriterSource; 022 import org.apache.tapestry.services.RequestLocaleManager; 023 import org.apache.tapestry.services.ResponseBuilder; 024 import org.apache.tapestry.util.ContentType; 025 import org.apache.tapestry.util.PageRenderSupportImpl; 026 import org.apache.tapestry.web.WebResponse; 027 028 import java.io.IOException; 029 import java.io.PrintWriter; 030 031 032 /** 033 * Manages normal html responses for tapestry request/response cycles. 034 * 035 * @author jkuhnert 036 */ 037 public class DefaultResponseBuilder implements ResponseBuilder 038 { 039 private final AssetFactory _assetFactory; 040 041 private final String _namespace; 042 043 private PageRenderSupportImpl _prs; 044 045 private RequestLocaleManager _localeManager; 046 047 private MarkupWriterSource _markupWriterSource; 048 049 private WebResponse _webResponse; 050 051 /** Default writer for rendering html output. */ 052 private IMarkupWriter _writer; 053 054 private boolean _closeWriter = true; 055 056 /** 057 * Portlet constructor. 058 * 059 * @param writer 060 */ 061 public DefaultResponseBuilder(IMarkupWriter writer, 062 AssetFactory assetFactory, String namespace, boolean closeWriter) 063 { 064 _writer = writer; 065 _assetFactory = assetFactory; 066 _namespace = namespace; 067 _closeWriter = closeWriter; 068 } 069 070 /** 071 * Used in testing only. 072 * @param writer 073 */ 074 public DefaultResponseBuilder(IMarkupWriter writer) 075 { 076 _writer = writer; 077 _assetFactory = null; 078 _namespace = null; 079 } 080 081 /** 082 * Creates a new response builder with the required services it needs 083 * to render the response when {@link #renderResponse(IRequestCycle)} is called. 084 * 085 * @param localeManager 086 * Used to set the locale on the response. 087 * @param markupWriterSource 088 * Creates IMarkupWriter instance to be used. 089 * @param webResponse 090 * Web response for output stream. 091 */ 092 public DefaultResponseBuilder(RequestLocaleManager localeManager, 093 MarkupWriterSource markupWriterSource, WebResponse webResponse, 094 AssetFactory assetFactory, String namespace) 095 { 096 Defense.notNull(assetFactory, "assetService"); 097 098 _localeManager = localeManager; 099 _markupWriterSource = markupWriterSource; 100 _webResponse = webResponse; 101 102 // Used by PageRenderSupport 103 104 _assetFactory = assetFactory; 105 _namespace = namespace; 106 } 107 108 /** 109 * 110 * {@inheritDoc} 111 */ 112 public boolean isDynamic() 113 { 114 return false; 115 } 116 117 /** 118 * 119 * {@inheritDoc} 120 */ 121 public void renderResponse(IRequestCycle cycle) 122 throws IOException 123 { 124 if (_writer == null) { 125 126 _localeManager.persistLocale(); 127 128 IPage page = cycle.getPage(); 129 130 ContentType contentType = page.getResponseContentType(); 131 132 String encoding = contentType.getParameter(ENCODING_KEY); 133 134 if (encoding == null) 135 { 136 encoding = cycle.getEngine().getOutputEncoding(); 137 138 contentType.setParameter(ENCODING_KEY, encoding); 139 } 140 141 PrintWriter printWriter = _webResponse.getPrintWriter(contentType); 142 143 _writer = _markupWriterSource.newMarkupWriter(printWriter, contentType); 144 } 145 146 // render response 147 148 _prs = new PageRenderSupportImpl(_assetFactory, _namespace, cycle.getPage().getLocation(), this); 149 150 TapestryUtils.storePageRenderSupport(cycle, _prs); 151 152 cycle.renderPage(this); 153 154 TapestryUtils.removePageRenderSupport(cycle); 155 156 flush(); 157 158 if (_closeWriter) 159 _writer.close(); 160 } 161 162 public void flush() 163 throws IOException 164 { 165 // Important - causes any cookies stored to properly be written out before the 166 // rest of the response starts being written - see TAPESTRY-825 167 168 _writer.flush(); 169 } 170 171 /** 172 * 173 * {@inheritDoc} 174 */ 175 public void render(IMarkupWriter writer, IRender render, IRequestCycle cycle) 176 { 177 if (writer == null) 178 render.render(_writer, cycle); 179 else 180 render.render(writer, cycle); 181 } 182 183 /** 184 * {@inheritDoc} 185 */ 186 public void updateComponent(String id) 187 { 188 } 189 190 /** 191 * {@inheritDoc} 192 */ 193 public boolean contains(IComponent target) 194 { 195 return false; 196 } 197 198 /** 199 * {@inheritDoc} 200 */ 201 public boolean explicitlyContains(IComponent target) 202 { 203 return false; 204 } 205 206 /** 207 * {@inheritDoc} 208 */ 209 public IMarkupWriter getWriter() 210 { 211 if (_writer == null) 212 return NullWriter.getSharedInstance(); 213 214 return _writer; 215 } 216 217 /** 218 * {@inheritDoc} 219 */ 220 public IMarkupWriter getWriter(String id, String type) 221 { 222 if (_writer == null) 223 return NullWriter.getSharedInstance(); 224 225 return _writer; 226 } 227 228 /** 229 * {@inheritDoc} 230 */ 231 public boolean isBodyScriptAllowed(IComponent target) 232 { 233 return true; 234 } 235 236 /** 237 * {@inheritDoc} 238 */ 239 public boolean isExternalScriptAllowed(IComponent target) 240 { 241 return true; 242 } 243 244 /** 245 * {@inheritDoc} 246 */ 247 public boolean isInitializationScriptAllowed(IComponent target) 248 { 249 return true; 250 } 251 252 /** 253 * {@inheritDoc} 254 */ 255 public boolean isImageInitializationAllowed(IComponent target) 256 { 257 return true; 258 } 259 260 /** 261 * {@inheritDoc} 262 */ 263 public String getPreloadedImageReference(IComponent target, IAsset source) 264 { 265 return _prs.getPreloadedImageReference(target, source); 266 } 267 268 /** 269 * {@inheritDoc} 270 */ 271 public String getPreloadedImageReference(IComponent target, String url) 272 { 273 return _prs.getPreloadedImageReference(target, url); 274 } 275 276 /** 277 * {@inheritDoc} 278 */ 279 public String getPreloadedImageReference(String url) 280 { 281 return _prs.getPreloadedImageReference(url); 282 } 283 284 /** 285 * {@inheritDoc} 286 */ 287 public void addBodyScript(IComponent target, String script) 288 { 289 _prs.addBodyScript(target, script); 290 } 291 292 /** 293 * {@inheritDoc} 294 */ 295 public void addBodyScript(String script) 296 { 297 _prs.addBodyScript(script); 298 } 299 300 /** 301 * {@inheritDoc} 302 */ 303 public void addExternalScript(IComponent target, Resource resource) 304 { 305 _prs.addExternalScript(target, resource); 306 } 307 308 /** 309 * {@inheritDoc} 310 */ 311 public void addExternalScript(Resource resource) 312 { 313 _prs.addExternalScript(resource); 314 } 315 316 /** 317 * {@inheritDoc} 318 */ 319 public void addInitializationScript(IComponent target, String script) 320 { 321 _prs.addInitializationScript(target, script); 322 } 323 324 /** 325 * {@inheritDoc} 326 */ 327 public void addInitializationScript(String script) 328 { 329 _prs.addInitializationScript(script); 330 } 331 332 /** 333 * {@inheritDoc} 334 */ 335 public String getUniqueString(String baseValue) 336 { 337 return _prs.getUniqueString(baseValue); 338 } 339 340 /** 341 * {@inheritDoc} 342 */ 343 public void writeBodyScript(IMarkupWriter writer, IRequestCycle cycle) 344 { 345 _prs.writeBodyScript(writer, cycle); 346 } 347 348 /** 349 * {@inheritDoc} 350 */ 351 public void writeInitializationScript(IMarkupWriter writer) 352 { 353 _prs.writeInitializationScript(writer); 354 } 355 356 /** 357 * {@inheritDoc} 358 */ 359 public void beginBodyScript(IMarkupWriter writer, IRequestCycle cycle) 360 { 361 writer.begin("script"); 362 writer.attribute("type", "text/javascript"); 363 writer.printRaw("<!--"); 364 writer.println(); 365 } 366 367 /** 368 * {@inheritDoc} 369 */ 370 public void endBodyScript(IMarkupWriter writer, IRequestCycle cycle) 371 { 372 writer.println(); 373 writer.printRaw("// -->"); 374 writer.end(); 375 } 376 377 /** 378 * {@inheritDoc} 379 */ 380 public void writeBodyScript(IMarkupWriter writer, String script, IRequestCycle cycle) 381 { 382 writer.printRaw(script); 383 } 384 385 /** 386 * {@inheritDoc} 387 */ 388 public void writeExternalScript(IMarkupWriter writer, String url, IRequestCycle cycle) 389 { 390 writer.begin("script"); 391 writer.attribute("type", "text/javascript"); 392 writer.attribute("src", url); 393 writer.end(); 394 writer.println(); 395 } 396 397 /** 398 * {@inheritDoc} 399 */ 400 public void writeImageInitializations(IMarkupWriter writer, String script, String preloadName, IRequestCycle cycle) 401 { 402 403 writer.println(); 404 writer.printRaw("dojo.addOnLoad(function(e) {\n"); 405 406 writer.printRaw(preloadName + " = [];\n"); 407 writer.printRaw("if (document.images)\n"); 408 writer.printRaw("{\n"); 409 writer.printRaw(script); 410 writer.printRaw("}\n"); 411 412 writer.printRaw("});"); 413 } 414 415 /** 416 * {@inheritDoc} 417 */ 418 public void writeInitializationScript(IMarkupWriter writer, String script) 419 { 420 writer.begin("script"); 421 writer.attribute("type", "text/javascript"); 422 writer.printRaw("<!--\n"); 423 424 writer.printRaw("dojo.addOnLoad(function(e) {\n"); 425 426 writer.printRaw(script); 427 428 writer.printRaw("});"); 429 430 writer.printRaw("\n// -->"); 431 writer.end(); 432 } 433 434 /** 435 * This implementation does nothing. 436 * {@inheritDoc} 437 */ 438 public void addStatusMessage(IMarkupWriter normalWriter, String category, String text) 439 { 440 } 441 }