001    // Copyright 2007, 2008, 2009, 2010, 2011 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    
015    package org.apache.tapestry5.internal.services;
016    
017    import org.apache.tapestry5.ContentType;
018    import org.apache.tapestry5.MarkupWriter;
019    import org.apache.tapestry5.SymbolConstants;
020    import org.apache.tapestry5.internal.InternalConstants;
021    import org.apache.tapestry5.ioc.annotations.Inject;
022    import org.apache.tapestry5.ioc.annotations.Symbol;
023    import org.apache.tapestry5.json.JSONObject;
024    import org.apache.tapestry5.services.*;
025    
026    import java.io.IOException;
027    import java.io.PrintWriter;
028    
029    public class AjaxPartialResponseRendererImpl implements AjaxPartialResponseRenderer
030    {
031        private final MarkupWriterFactory factory;
032    
033        private final Request request;
034    
035        private final Response response;
036    
037        private final PartialMarkupRenderer partialMarkupRenderer;
038    
039        private final String outputEncoding;
040    
041        private final boolean compactJSON;
042    
043        private final Environment environment;
044    
045        public AjaxPartialResponseRendererImpl(MarkupWriterFactory factory,
046    
047                                               Request request,
048    
049                                               Response response,
050    
051                                               PartialMarkupRenderer partialMarkupRenderer,
052    
053                                               @Inject
054                                               @Symbol(SymbolConstants.CHARSET)
055                                               String outputEncoding,
056    
057                                               @Symbol(SymbolConstants.COMPACT_JSON)
058                                               boolean compactJSON, Environment environment)
059        {
060            this.factory = factory;
061            this.request = request;
062            this.response = response;
063            this.partialMarkupRenderer = partialMarkupRenderer;
064            this.outputEncoding = outputEncoding;
065            this.compactJSON = compactJSON;
066            this.environment = environment;
067        }
068    
069        public void renderPartialPageMarkup() throws IOException
070        {
071            environment.cloak();
072    
073            try
074            {
075                // This is a complex area as we are trying to keep public and private services properly
076                // separated, and trying to keep stateless and stateful (i.e., perthread scope) services
077                // separated. So we inform the stateful queue service what it needs to do here ...
078    
079                ContentType pageContentType = (ContentType) request.getAttribute(InternalConstants.CONTENT_TYPE_ATTRIBUTE_NAME);
080    
081                ContentType contentType = new ContentType(InternalConstants.JSON_MIME_TYPE, outputEncoding);
082    
083                MarkupWriter writer = factory.newPartialMarkupWriter(pageContentType);
084    
085                JSONObject reply = new JSONObject();
086    
087                // ... and here, the pipeline eventually reaches the PRQ to let it render the root render command.
088    
089                partialMarkupRenderer.renderMarkup(writer, reply);
090    
091                PrintWriter pw = response.getPrintWriter(contentType.toString());
092    
093                reply.print(pw, compactJSON);
094    
095                pw.close();
096            } finally
097            {
098                environment.decloak();
099            }
100        }
101    }