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.MarkupWriter; 016import org.apache.tapestry5.SymbolConstants; 017import org.apache.tapestry5.TapestryConstants; 018import org.apache.tapestry5.http.ContentType; 019import org.apache.tapestry5.http.TapestryHttpSymbolConstants; 020import org.apache.tapestry5.http.services.Request; 021import org.apache.tapestry5.http.services.Response; 022import org.apache.tapestry5.internal.InternalConstants; 023import org.apache.tapestry5.ioc.IOOperation; 024import org.apache.tapestry5.ioc.annotations.Inject; 025import org.apache.tapestry5.ioc.annotations.Symbol; 026import org.apache.tapestry5.json.JSONObject; 027import org.apache.tapestry5.services.MarkupWriterFactory; 028import org.apache.tapestry5.services.PartialMarkupRenderer; 029 030import java.io.IOException; 031import java.io.PrintWriter; 032 033public class AjaxPartialResponseRendererImpl implements AjaxPartialResponseRenderer 034{ 035 private final MarkupWriterFactory factory; 036 037 private final Request request; 038 039 private final Response response; 040 041 private final PartialMarkupRenderer partialMarkupRenderer; 042 043 private final boolean compactJSON; 044 045 private final ContentType contentType; 046 047 public AjaxPartialResponseRendererImpl(MarkupWriterFactory factory, 048 049 Request request, 050 051 Response response, 052 053 PartialMarkupRenderer partialMarkupRenderer, 054 055 @Inject 056 @Symbol(TapestryHttpSymbolConstants.CHARSET) 057 String outputEncoding, 058 059 @Symbol(SymbolConstants.COMPACT_JSON) 060 boolean compactJSON) 061 { 062 this.factory = factory; 063 this.request = request; 064 this.response = response; 065 this.partialMarkupRenderer = partialMarkupRenderer; 066 this.compactJSON = compactJSON; 067 068 contentType = new ContentType(InternalConstants.JSON_MIME_TYPE).withCharset(outputEncoding); 069 } 070 071 public void renderPartialPageMarkup(final JSONObject reply) throws IOException 072 { 073 assert reply != null; 074 075 request.setAttribute(TapestryConstants.RESPONSE_RENDERER, new IOOperation<Void>() 076 { 077 public Void perform() throws IOException 078 { 079 // This is a complex area as we are trying to keep public and private services properly 080 // separated, and trying to keep stateless and stateful (i.e., perthread scope) services 081 // separated. So we inform the stateful queue service what it needs to do here ... 082 083 String pageName = (String) request.getAttribute(InternalConstants.PAGE_NAME_ATTRIBUTE_NAME); 084 085 if (pageName == null) 086 { 087 throw new IllegalStateException("The active page name has not been specified."); 088 } 089 090 MarkupWriter writer = factory.newPartialMarkupWriter(pageName); 091 092 // ... and here, the pipeline eventually reaches the PRQ to let it render the root render command. 093 094 partialMarkupRenderer.renderMarkup(writer, reply); 095 096 PrintWriter pw = response.getPrintWriter(contentType.toString()); 097 098 reply.print(pw, compactJSON); 099 100 pw.close(); 101 102 return null; 103 } 104 }); 105 } 106 107 public void renderPartialPageMarkup() throws IOException 108 { 109 renderPartialPageMarkup(new JSONObject()); 110 } 111}