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 String encoding = contentType.getParameter(ENCODING_KEY); 132 133 if (encoding == null) 134 { 135 encoding = cycle.getEngine().getOutputEncoding(); 136 137 contentType.setParameter(ENCODING_KEY, encoding); 138 } 139 140 PrintWriter printWriter = _webResponse.getPrintWriter(contentType); 141 142 _writer = _markupWriterSource.newMarkupWriter(printWriter, contentType); 143 } 144 145 // render response 146 147 _prs = new PageRenderSupportImpl(_assetFactory, _namespace, cycle.getPage().getLocation(), this); 148 149 TapestryUtils.storePageRenderSupport(cycle, _prs); 150 151 cycle.renderPage(this); 152 153 TapestryUtils.removePageRenderSupport(cycle); 154 155 flush(); 156 157 if (_closeWriter) 158 _writer.close(); 159 } 160 161 public void flush() 162 throws IOException 163 { 164 // Important - causes any cookies stored to properly be written out before the 165 // rest of the response starts being written - see TAPESTRY-825 166 167 _writer.flush(); 168 } 169 170 /** 171 * 172 * {@inheritDoc} 173 */ 174 public void render(IMarkupWriter writer, IRender render, IRequestCycle cycle) 175 { 176 if (writer == null) 177 render.render(_writer, cycle); 178 else 179 render.render(writer, cycle); 180 } 181 182 /** 183 * {@inheritDoc} 184 */ 185 public void updateComponent(String id) 186 { 187 } 188 189 /** 190 * {@inheritDoc} 191 */ 192 public boolean contains(IComponent target) 193 { 194 return false; 195 } 196 197 /** 198 * {@inheritDoc} 199 */ 200 public boolean explicitlyContains(IComponent target) 201 { 202 return false; 203 } 204 205 /** 206 * {@inheritDoc} 207 */ 208 public IMarkupWriter getWriter() 209 { 210 if (_writer == null) 211 return NullWriter.getSharedInstance(); 212 213 return _writer; 214 } 215 216 /** 217 * {@inheritDoc} 218 */ 219 public IMarkupWriter getWriter(String id, String type) 220 { 221 if (_writer == null) 222 return NullWriter.getSharedInstance(); 223 224 return _writer; 225 } 226 227 /** 228 * {@inheritDoc} 229 */ 230 public boolean isBodyScriptAllowed(IComponent target) 231 { 232 return true; 233 } 234 235 /** 236 * {@inheritDoc} 237 */ 238 public boolean isExternalScriptAllowed(IComponent target) 239 { 240 return true; 241 } 242 243 /** 244 * {@inheritDoc} 245 */ 246 public boolean isInitializationScriptAllowed(IComponent target) 247 { 248 return true; 249 } 250 251 /** 252 * {@inheritDoc} 253 */ 254 public boolean isImageInitializationAllowed(IComponent target) 255 { 256 return true; 257 } 258 259 /** 260 * {@inheritDoc} 261 */ 262 public String getPreloadedImageReference(IComponent target, IAsset source) 263 { 264 return _prs.getPreloadedImageReference(target, source); 265 } 266 267 /** 268 * {@inheritDoc} 269 */ 270 public String getPreloadedImageReference(IComponent target, String url) 271 { 272 return _prs.getPreloadedImageReference(target, url); 273 } 274 275 /** 276 * {@inheritDoc} 277 */ 278 public String getPreloadedImageReference(String url) 279 { 280 return _prs.getPreloadedImageReference(url); 281 } 282 283 /** 284 * {@inheritDoc} 285 */ 286 public void addBodyScript(IComponent target, String script) 287 { 288 _prs.addBodyScript(target, script); 289 } 290 291 /** 292 * {@inheritDoc} 293 */ 294 public void addBodyScript(String script) 295 { 296 _prs.addBodyScript(script); 297 } 298 299 /** 300 * {@inheritDoc} 301 */ 302 public void addExternalScript(IComponent target, Resource resource) 303 { 304 _prs.addExternalScript(target, resource); 305 } 306 307 /** 308 * {@inheritDoc} 309 */ 310 public void addExternalScript(Resource resource) 311 { 312 _prs.addExternalScript(resource); 313 } 314 315 /** 316 * {@inheritDoc} 317 */ 318 public void addInitializationScript(IComponent target, String script) 319 { 320 _prs.addInitializationScript(target, script); 321 } 322 323 /** 324 * {@inheritDoc} 325 */ 326 public void addInitializationScript(String script) 327 { 328 _prs.addInitializationScript(script); 329 } 330 331 public void addScriptAfterInitialization(IComponent target, String script) 332 { 333 _prs.addScriptAfterInitialization(target, script); 334 } 335 336 /** 337 * {@inheritDoc} 338 */ 339 public String getUniqueString(String baseValue) 340 { 341 return _prs.getUniqueString(baseValue); 342 } 343 344 /** 345 * {@inheritDoc} 346 */ 347 public void writeBodyScript(IMarkupWriter writer, IRequestCycle cycle) 348 { 349 _prs.writeBodyScript(writer, cycle); 350 } 351 352 /** 353 * {@inheritDoc} 354 */ 355 public void writeInitializationScript(IMarkupWriter writer) 356 { 357 _prs.writeInitializationScript(writer); 358 } 359 360 /** 361 * {@inheritDoc} 362 */ 363 public void beginBodyScript(IMarkupWriter writer, IRequestCycle cycle) 364 { 365 writer.begin("script"); 366 writer.attribute("type", "text/javascript"); 367 writer.printRaw("<!--"); 368 writer.println(); 369 } 370 371 /** 372 * {@inheritDoc} 373 */ 374 public void endBodyScript(IMarkupWriter writer, IRequestCycle cycle) 375 { 376 writer.println(); 377 writer.printRaw("// -->"); 378 writer.end(); 379 } 380 381 /** 382 * {@inheritDoc} 383 */ 384 public void writeBodyScript(IMarkupWriter writer, String script, IRequestCycle cycle) 385 { 386 writer.printRaw(script); 387 } 388 389 /** 390 * {@inheritDoc} 391 */ 392 public void writeExternalScript(IMarkupWriter writer, String url, IRequestCycle cycle) 393 { 394 writer.begin("script"); 395 writer.attribute("type", "text/javascript"); 396 writer.attribute("src", url); 397 writer.end(); 398 writer.println(); 399 } 400 401 /** 402 * {@inheritDoc} 403 */ 404 public void writeImageInitializations(IMarkupWriter writer, String script, String preloadName, IRequestCycle cycle) 405 { 406 407 writer.println(); 408 writer.printRaw("dojo.addOnLoad(function(e) {\n"); 409 410 writer.printRaw(preloadName + " = [];\n"); 411 writer.printRaw("if (document.images)\n"); 412 writer.printRaw("{\n"); 413 writer.printRaw(script); 414 writer.printRaw("}\n"); 415 416 writer.printRaw("});"); 417 } 418 419 /** 420 * {@inheritDoc} 421 */ 422 public void writeInitializationScript(IMarkupWriter writer, String script) 423 { 424 writer.begin("script"); 425 writer.attribute("type", "text/javascript"); 426 writer.printRaw("<!--\n"); 427 428 writer.printRaw("dojo.addOnLoad(function(e) {\n"); 429 430 writer.printRaw(script); 431 432 writer.printRaw("});"); 433 434 writer.printRaw("\n// -->"); 435 writer.end(); 436 } 437 438 /** 439 * This implementation does nothing. 440 * {@inheritDoc} 441 */ 442 public void addStatusMessage(IMarkupWriter normalWriter, String category, String text) 443 { 444 } 445 }