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 java.io.IOException;
017    import java.io.PrintWriter;
018    
019    import org.apache.tapestry.IComponent;
020    import org.apache.tapestry.IMarkupWriter;
021    import org.apache.tapestry.IPage;
022    import org.apache.tapestry.IRender;
023    import org.apache.tapestry.IRequestCycle;
024    import org.apache.tapestry.engine.NullWriter;
025    import org.apache.tapestry.markup.MarkupWriterSource;
026    import org.apache.tapestry.services.RequestLocaleManager;
027    import org.apache.tapestry.services.ResponseBuilder;
028    import org.apache.tapestry.util.ContentType;
029    import org.apache.tapestry.web.WebResponse;
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 RequestLocaleManager _localeManager;
040        
041        private MarkupWriterSource _markupWriterSource;
042    
043        private WebResponse _webResponse;
044        
045        /** Default writer for rendering html output. */
046        private IMarkupWriter _writer;
047        
048        /**
049         * Used in testing only.
050         * @param writer
051         */
052        public DefaultResponseBuilder(IMarkupWriter writer)
053        {
054            _writer = writer;
055        }
056        
057        /**
058         * Creates a new response builder with the required services it needs
059         * to render the response when {@link #renderResponse(IRequestCycle)} is called.
060         * 
061         * @param localeManager 
062         *          Used to set the locale on the response.
063         * @param markupWriterSource
064         *          Creates IMarkupWriter instance to be used.
065         * @param webResponse
066         *          Web response for output stream.
067         */
068        public DefaultResponseBuilder(RequestLocaleManager localeManager, 
069                MarkupWriterSource markupWriterSource, WebResponse webResponse)
070        {
071            _localeManager = localeManager;
072            _markupWriterSource = markupWriterSource;
073            _webResponse = webResponse;
074        }
075        
076        /**
077         * 
078         * {@inheritDoc}
079         */
080        public boolean isDynamic()
081        {
082            return Boolean.FALSE;
083        }
084        
085        /**
086         * 
087         * {@inheritDoc}
088         */
089        public void renderResponse(IRequestCycle cycle)
090        throws IOException
091        {
092            if (_writer == null) {
093                
094                _localeManager.persistLocale();
095                
096                IPage page = cycle.getPage();
097    
098                ContentType contentType = page.getResponseContentType();
099    
100                String encoding = contentType.getParameter(ENCODING_KEY);
101    
102                if (encoding == null)
103                {
104                    encoding = cycle.getEngine().getOutputEncoding();
105    
106                    contentType.setParameter(ENCODING_KEY, encoding);
107                }
108                
109                PrintWriter printWriter = _webResponse.getPrintWriter(contentType);
110                
111                _writer = _markupWriterSource.newMarkupWriter(printWriter, contentType);
112            
113            }
114            
115            // render response
116            
117            cycle.renderPage(this);
118            
119            _writer.close();
120        }
121        
122        /**
123         * 
124         * {@inheritDoc}
125         */
126        public void render(IMarkupWriter writer, IRender render, IRequestCycle cycle)
127        {
128            if (writer == null)
129                render.render(_writer, cycle);
130            else
131                render.render(writer, cycle);
132        }
133        
134        /** 
135         * {@inheritDoc}
136         */
137        public void updateComponent(String id)
138        {
139        }
140        
141        /** 
142         * {@inheritDoc}
143         */
144        public boolean contains(IComponent target)
145        {
146            return false;
147        }
148    
149        /** 
150         * {@inheritDoc}
151         */
152        public IMarkupWriter getWriter()
153        {
154            if (_writer == null)
155                return NullWriter.getSharedInstance();
156            
157            return _writer;
158        }
159        
160        /** 
161         * {@inheritDoc}
162         */
163        public IMarkupWriter getWriter(String id, String type)
164        {
165            if (_writer == null)
166                return NullWriter.getSharedInstance();
167            
168            return _writer;
169        }
170        
171        /** 
172         * {@inheritDoc}
173         */
174        public boolean isBodyScriptAllowed(IComponent target)
175        {
176            return true;
177        }
178    
179        /** 
180         * {@inheritDoc}
181         */
182        public boolean isExternalScriptAllowed(IComponent target)
183        {
184            return true;
185        }
186    
187        /** 
188         * {@inheritDoc}
189         */
190        public boolean isInitializationScriptAllowed(IComponent target)
191        {
192            return true;
193        }
194        
195        /**
196         * {@inheritDoc}
197         */
198        public boolean isImageInitializationAllowed(IComponent target)
199        {
200            return true;
201        }
202        
203        /** 
204         * {@inheritDoc}
205         */
206        public void beginBodyScript(IMarkupWriter writer, IRequestCycle cycle)
207        {
208            writer.begin("script");
209            writer.attribute("type", "text/javascript");
210            writer.printRaw("<!--");
211        }
212        
213        /** 
214         * {@inheritDoc}
215         */
216        public void endBodyScript(IMarkupWriter writer, IRequestCycle cycle)
217        {
218            writer.printRaw("\n\n// -->");
219            writer.end();
220        }
221    
222        /** 
223         * {@inheritDoc}
224         */
225        public void writeBodyScript(IMarkupWriter writer, String script, IRequestCycle cycle)
226        {
227            writer.printRaw("\n\n");
228            writer.printRaw(script);
229        }
230    
231        /** 
232         * {@inheritDoc}
233         */
234        public void writeExternalScript(IMarkupWriter writer, String url, IRequestCycle cycle)
235        {        
236            writer.begin("script");
237            writer.attribute("type", "text/javascript");
238            writer.attribute("src", url);
239            writer.end();
240            writer.println();
241        }
242        
243        /** 
244         * {@inheritDoc}
245         */
246        public void writeImageInitializations(IMarkupWriter writer, String script, String preloadName, IRequestCycle cycle)
247        {
248            
249            writer.println();
250            writer.printRaw("dojo.addOnLoad(function(e) {\n");
251            
252            writer.printRaw("\n\n" + preloadName + " = [];\n");
253            writer.printRaw("if (document.images)\n");
254            writer.printRaw("{\n");
255            writer.printRaw(script);
256            writer.printRaw("}\n");
257            
258            writer.printRaw("});");
259        }
260        
261        /** 
262         * {@inheritDoc}
263         */
264        public void writeInitializationScript(IMarkupWriter writer, String script)
265        {
266            writer.begin("script");
267            writer.attribute("type", "text/javascript");
268            writer.printRaw("<!--\n");
269            
270            writer.printRaw("dojo.addOnLoad(function(e) {\n");
271            
272            writer.printRaw(script);
273            
274            writer.printRaw("});");
275            
276            writer.printRaw("\n// -->");
277            writer.end();
278        }
279    }