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 }