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