001// Licensed under the Apache License, Version 2.0 (the "License"); 002// you may not use this file except in compliance with the License. 003// You may obtain a copy of the License at 004// 005// http://www.apache.org/licenses/LICENSE-2.0 006// 007// Unless required by applicable law or agreed to in writing, software 008// distributed under the License is distributed on an "AS IS" BASIS, 009// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 010// See the License for the specific language governing permissions and 011// limitations under the License. 012 013package org.apache.tapestry5.internal.services; 014 015import org.apache.tapestry5.ContentType; 016import org.apache.tapestry5.MarkupWriter; 017import org.apache.tapestry5.SymbolConstants; 018import org.apache.tapestry5.TapestryConstants; 019import org.apache.tapestry5.internal.InternalConstants; 020import org.apache.tapestry5.ioc.IOOperation; 021import org.apache.tapestry5.ioc.annotations.Inject; 022import org.apache.tapestry5.ioc.annotations.Symbol; 023import org.apache.tapestry5.json.JSONObject; 024import org.apache.tapestry5.services.MarkupWriterFactory; 025import org.apache.tapestry5.services.PartialMarkupRenderer; 026import org.apache.tapestry5.services.Request; 027import org.apache.tapestry5.services.Response; 028 029import java.io.IOException; 030import java.io.PrintWriter; 031 032public class AjaxPartialResponseRendererImpl implements AjaxPartialResponseRenderer 033{ 034 private final MarkupWriterFactory factory; 035 036 private final Request request; 037 038 private final Response response; 039 040 private final PartialMarkupRenderer partialMarkupRenderer; 041 042 private final boolean compactJSON; 043 044 private final ContentType contentType; 045 046 public AjaxPartialResponseRendererImpl(MarkupWriterFactory factory, 047 048 Request request, 049 050 Response response, 051 052 PartialMarkupRenderer partialMarkupRenderer, 053 054 @Inject 055 @Symbol(SymbolConstants.CHARSET) 056 String outputEncoding, 057 058 @Symbol(SymbolConstants.COMPACT_JSON) 059 boolean compactJSON) 060 { 061 this.factory = factory; 062 this.request = request; 063 this.response = response; 064 this.partialMarkupRenderer = partialMarkupRenderer; 065 this.compactJSON = compactJSON; 066 067 contentType = new ContentType(InternalConstants.JSON_MIME_TYPE).withCharset(outputEncoding); 068 } 069 070 public void renderPartialPageMarkup(final JSONObject reply) throws IOException 071 { 072 assert reply != null; 073 074 request.setAttribute(TapestryConstants.RESPONSE_RENDERER, new IOOperation<Void>() 075 { 076 public Void perform() throws IOException 077 { 078 // This is a complex area as we are trying to keep public and private services properly 079 // separated, and trying to keep stateless and stateful (i.e., perthread scope) services 080 // separated. So we inform the stateful queue service what it needs to do here ... 081 082 String pageName = (String) request.getAttribute(InternalConstants.PAGE_NAME_ATTRIBUTE_NAME); 083 084 if (pageName == null) 085 { 086 throw new IllegalStateException("The active page name has not been specified."); 087 } 088 089 MarkupWriter writer = factory.newPartialMarkupWriter(pageName); 090 091 // ... and here, the pipeline eventually reaches the PRQ to let it render the root render command. 092 093 partialMarkupRenderer.renderMarkup(writer, reply); 094 095 PrintWriter pw = response.getPrintWriter(contentType.toString()); 096 097 reply.print(pw, compactJSON); 098 099 pw.close(); 100 101 return null; 102 } 103 }); 104 } 105 106 public void renderPartialPageMarkup() throws IOException 107 { 108 renderPartialPageMarkup(new JSONObject()); 109 } 110}