001// Copyright 2005 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
015package org.apache.tapestry.portlet;
016
017import java.io.IOException;
018import java.io.PrintWriter;
019import java.util.ArrayList;
020import java.util.Date;
021import java.util.List;
022
023import org.apache.hivemind.ApplicationRuntimeException;
024import org.apache.tapestry.IMarkupWriter;
025import org.apache.tapestry.IPage;
026import org.apache.tapestry.IRequestCycle;
027import org.apache.tapestry.PageRedirectException;
028import org.apache.tapestry.Tapestry;
029import org.apache.tapestry.TapestryUtils;
030import org.apache.tapestry.asset.AssetFactory;
031import org.apache.tapestry.engine.EngineMessages;
032import org.apache.tapestry.markup.MarkupWriterSource;
033import org.apache.tapestry.util.ContentType;
034import org.apache.tapestry.util.PageRenderSupportImpl;
035import org.apache.tapestry.web.WebResponse;
036
037/**
038 * The guts of rendering a page as a portlet response; used by
039 * {@link org.apache.tapestry.portlet.RenderService} and
040 * {@link org.apache.tapestry.portlet.PortletHomeService}.
041 * 
042 * @author Howard M. Lewis Ship
043 * @since 4.0
044 */
045public class PortletRendererImpl implements PortletRenderer
046{
047    private WebResponse _response;
048
049    private MarkupWriterSource _markupWriterSource;
050
051    private AssetFactory _assetFactory;
052
053    private String _applicationId;
054
055    public void renderPage(IRequestCycle cycle, String pageName) throws IOException
056    {
057        try {
058                cycle.activate(pageName);
059        
060                IPage page = cycle.getPage();
061        
062                ContentType contentType = page.getResponseContentType();
063        
064                PrintWriter printWriter = _response.getPrintWriter(contentType);
065        
066                IMarkupWriter writer = _markupWriterSource.newMarkupWriter(printWriter, contentType);
067        
068                String namespace = _response.getNamespace();
069        
070                PageRenderSupportImpl support = new PageRenderSupportImpl(_assetFactory, namespace, null);
071        
072                TapestryUtils.storePageRenderSupport(cycle, support);
073        
074                IMarkupWriter nested = writer.getNestedWriter();
075        
076                cycle.renderPage(nested);
077        
078                String id = "Tapestry Portlet " + _applicationId + " " + namespace;
079        
080                writer.comment("BEGIN " + id);
081                writer.comment("Page: " + page.getPageName());
082                writer.comment("Generated: " + new Date());
083                writer.comment("Framework version: " + Tapestry.VERSION);
084        
085                support.writeBodyScript(writer, cycle);
086        
087                nested.close();
088        
089                support.writeInitializationScript(writer);
090        
091                writer.comment("END " + id);
092
093                writer.close();
094                
095                // TODO: Trap errors and do some error reporting here?
096        }
097        catch (PageRedirectException e) {
098                handlePageRedirectException(cycle, e);
099        }
100    }
101
102    protected void handlePageRedirectException(IRequestCycle cycle, PageRedirectException exception)
103                throws IOException
104        {
105                List pageNames = new ArrayList();
106                
107                String pageName = exception.getTargetPageName();
108                
109                while (true)
110                {
111                    if (pageNames.contains(pageName))
112                    {
113                        pageNames.add(pageName);
114                
115                        throw new ApplicationRuntimeException(EngineMessages.validateCycle(pageNames));
116                    }
117                
118                    // Record that this page has been a target.
119                
120                    pageNames.add(pageName);
121                
122                    try
123                    {
124                        // Attempt to activate the new page.
125                
126                        cycle.activate(pageName);
127                
128                        break;
129                    }
130                    catch (PageRedirectException secondRedirectException)
131                    {
132                        pageName = secondRedirectException.getTargetPageName();
133                    }
134                }
135                
136                renderPage(cycle, pageName);
137        }
138    
139    public void setMarkupWriterSource(MarkupWriterSource markupWriterSource)
140    {
141        _markupWriterSource = markupWriterSource;
142    }
143
144    public void setResponse(WebResponse response)
145    {
146        _response = response;
147    }
148
149    public void setAssetFactory(AssetFactory assetFactory)
150    {
151        _assetFactory = assetFactory;
152    }
153
154    public void setApplicationId(String applicationId)
155    {
156        _applicationId = applicationId;
157    }
158}