001    // Copyright 2004, 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.html;
016    
017    import java.util.Date;
018    import java.util.Iterator;
019    
020    import org.apache.hivemind.HiveMind;
021    import org.apache.tapestry.AbstractComponent;
022    import org.apache.tapestry.IAsset;
023    import org.apache.tapestry.IMarkupWriter;
024    import org.apache.tapestry.IPage;
025    import org.apache.tapestry.IRender;
026    import org.apache.tapestry.IRequestCycle;
027    import org.apache.tapestry.Tapestry;
028    import org.apache.tapestry.coerce.ValueConverter;
029    import org.apache.tapestry.engine.IEngineService;
030    import org.apache.tapestry.engine.ILink;
031    import org.apache.tapestry.spec.IApplicationSpecification;
032    
033    /**
034     * Component for creating a standard 'shell' for a page, which comprises the <html> and
035     * &lt;head&gt; portions of the page. [ <a
036     * href="../../../../../ComponentReference/Shell.html">Component Reference </a>]
037     * <p>
038     * Specifically does <em>not</em> provide a &lt;body&gt; tag, that is usually accomplished using a
039     * {@link Body}&nbsp; component.
040     * 
041     * @author Howard Lewis Ship
042     */
043    
044    public abstract class Shell extends AbstractComponent
045    {
046        private static final String GENERATOR_CONTENT = "Tapestry Application Framework, version "
047                + Tapestry.VERSION;
048    
049        protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
050        {
051            long startTime = 0;
052    
053            boolean rewinding = cycle.isRewinding();
054    
055            if (!rewinding)
056            {
057                startTime = System.currentTimeMillis();
058    
059                writeDocType(writer, cycle);
060    
061                IPage page = getPage();
062                
063                writer.comment("Application: " + getApplicationSpecification().getName());
064                
065                writer.comment("Page: " + page.getPageName());
066                writer.comment("Generated: " + new Date());
067                
068                writer.begin("html");
069                writer.println();
070                writer.begin("head");
071                writer.println();
072    
073                writeMetaTag(writer, "name", "generator", GENERATOR_CONTENT);
074                
075                if (getRenderContentType())
076                    writeMetaTag(writer, "http-equiv", "Content-Type", writer.getContentType());
077                
078                if (getRenderBaseTag())
079                    getBaseTagWriter().render(writer, cycle);
080                
081                writer.begin("title");
082                
083                writer.print(getTitle(), getRaw());               
084                writer.end(); // title
085                writer.println();
086                
087                IRender delegate = getDelegate();
088                
089                if (delegate != null)
090                    delegate.render(writer, cycle);
091                
092                IRender ajaxDelegate = getAjaxDelegate();
093                
094                if (isAjaxEnabled() && ajaxDelegate != null)
095                    ajaxDelegate.render(writer, cycle);
096                
097                IAsset stylesheet = getStylesheet();
098                
099                if (stylesheet != null)
100                    writeStylesheetLink(writer, cycle, stylesheet);
101                
102                Iterator i = (Iterator) getValueConverter().coerceValue(
103                        getStylesheets(),
104                        Iterator.class);
105                
106                while (i.hasNext())
107                {
108                    stylesheet = (IAsset) i.next();
109    
110                    writeStylesheetLink(writer, cycle, stylesheet);
111                }
112                
113                writeRefresh(writer, cycle);
114                
115                writer.end(); // head
116            }
117            
118            // Render the body, the actual page content
119            
120            renderBody(writer, cycle);
121            
122            if (!rewinding)
123            {
124                writer.end(); // html
125                writer.println();
126    
127                long endTime = System.currentTimeMillis();
128    
129                writer.comment("Render time: ~ " + (endTime - startTime) + " ms");
130            }
131    
132        }
133    
134        private void writeDocType(IMarkupWriter writer, IRequestCycle cycle)
135        {
136            // This is the real code
137            String doctype = getDoctype();
138            if (HiveMind.isNonBlank(doctype))
139            {
140                writer.printRaw("<!DOCTYPE " + doctype + ">");
141                writer.println();
142            }
143        }
144    
145        private void writeStylesheetLink(IMarkupWriter writer, IRequestCycle cycle, IAsset stylesheet)
146        {
147            writer.beginEmpty("link");
148            writer.attribute("rel", "stylesheet");
149            writer.attribute("type", "text/css");
150            writer.attribute("href", stylesheet.buildURL());
151            writer.println();
152        }
153    
154        private void writeRefresh(IMarkupWriter writer, IRequestCycle cycle)
155        {
156            int refresh = getRefresh();
157    
158            if (refresh <= 0)
159                return;
160    
161            // Here comes the tricky part ... have to assemble a complete URL
162            // for the current page.
163    
164            IEngineService pageService = getPageService();
165            String pageName = getPage().getPageName();
166    
167            ILink link = pageService.getLink(false, pageName);
168    
169            StringBuffer buffer = new StringBuffer();
170            buffer.append(refresh);
171            buffer.append("; URL=");
172            buffer.append(link.getAbsoluteURL());
173    
174            writeMetaTag(writer, "http-equiv", "Refresh", buffer.toString());
175        }
176        
177        private void writeMetaTag(IMarkupWriter writer, String key, String value, String content)
178        {
179            writer.beginEmpty("meta");
180            writer.attribute(key, value);
181            writer.attribute("content", content);
182            writer.println();
183        }
184        
185        public abstract boolean isAjaxEnabled();
186        
187        public abstract IRender getAjaxDelegate();
188        
189        public abstract IRender getDelegate();
190    
191        public abstract int getRefresh();
192    
193        public abstract IAsset getStylesheet();
194    
195        public abstract Object getStylesheets();
196    
197        public abstract String getTitle();
198    
199        public abstract String getDoctype();
200    
201        public abstract boolean getRenderContentType();
202    
203        /** @since 4.0 */
204        public abstract ValueConverter getValueConverter();
205    
206        /** @since 4.0 */
207    
208        public abstract IEngineService getPageService();
209    
210        /** @since 4.0 */
211    
212        public abstract IApplicationSpecification getApplicationSpecification();
213    
214        /** @since 4.0 */
215    
216        public abstract IRender getBaseTagWriter();
217        
218        /** @since 4.0.1 */
219        
220        public abstract boolean getRenderBaseTag();
221        
222        /** @since 4.0.3 */
223        
224        public abstract boolean getRaw();
225    
226    }