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    
015    package org.apache.tapestry.portlet;
016    
017    import java.io.IOException;
018    import java.io.PrintWriter;
019    import java.util.ArrayList;
020    import java.util.Date;
021    import java.util.List;
022    
023    import org.apache.hivemind.ApplicationRuntimeException;
024    import org.apache.tapestry.IMarkupWriter;
025    import org.apache.tapestry.IPage;
026    import org.apache.tapestry.IRequestCycle;
027    import org.apache.tapestry.PageRedirectException;
028    import org.apache.tapestry.Tapestry;
029    import org.apache.tapestry.TapestryUtils;
030    import org.apache.tapestry.asset.AssetFactory;
031    import org.apache.tapestry.engine.EngineMessages;
032    import org.apache.tapestry.markup.MarkupWriterSource;
033    import org.apache.tapestry.util.ContentType;
034    import org.apache.tapestry.util.PageRenderSupportImpl;
035    import 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     */
045    public 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    }