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 generatorContent = "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", generatorContent);
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());
084                writer.end(); // title
085                writer.println();
086    
087                IRender delegate = getDelegate();
088    
089                if (delegate != null)
090                    delegate.render(writer, cycle);
091    
092                IAsset stylesheet = getStylesheet();
093    
094                if (stylesheet != null)
095                    writeStylesheetLink(writer, cycle, stylesheet);
096    
097                Iterator i = (Iterator) getValueConverter().coerceValue(
098                        getStylesheets(),
099                        Iterator.class);
100    
101                while (i.hasNext())
102                {
103                    stylesheet = (IAsset) i.next();
104    
105                    writeStylesheetLink(writer, cycle, stylesheet);
106                }
107    
108                writeRefresh(writer, cycle);
109    
110                writer.end(); // head
111            }
112    
113            // Render the body, the actual page content
114    
115            renderBody(writer, cycle);
116    
117            if (!rewinding)
118            {
119                writer.end(); // html
120                writer.println();
121    
122                long endTime = System.currentTimeMillis();
123    
124                writer.comment("Render time: ~ " + (endTime - startTime) + " ms");
125            }
126    
127        }
128    
129        private void writeDocType(IMarkupWriter writer, IRequestCycle cycle)
130        {
131            // This is the real code
132            String doctype = getDoctype();
133            if (HiveMind.isNonBlank(doctype))
134            {
135                writer.printRaw("<!DOCTYPE " + doctype + ">");
136                writer.println();
137            }
138        }
139    
140        private void writeStylesheetLink(IMarkupWriter writer, IRequestCycle cycle, IAsset stylesheet)
141        {
142            writer.beginEmpty("link");
143            writer.attribute("rel", "stylesheet");
144            writer.attribute("type", "text/css");
145            writer.attribute("href", stylesheet.buildURL());
146            writer.println();
147        }
148    
149        private void writeRefresh(IMarkupWriter writer, IRequestCycle cycle)
150        {
151            int refresh = getRefresh();
152    
153            if (refresh <= 0)
154                return;
155    
156            // Here comes the tricky part ... have to assemble a complete URL
157            // for the current page.
158    
159            IEngineService pageService = getPageService();
160            String pageName = getPage().getPageName();
161    
162            ILink link = pageService.getLink(false, pageName);
163    
164            StringBuffer buffer = new StringBuffer();
165            buffer.append(refresh);
166            buffer.append("; URL=");
167            buffer.append(link.getAbsoluteURL());
168    
169            writeMetaTag(writer, "http-equiv", "Refresh", buffer.toString());
170        }
171    
172        private void writeMetaTag(IMarkupWriter writer, String key, String value, String content)
173        {
174            writer.beginEmpty("meta");
175            writer.attribute(key, value);
176            writer.attribute("content", content);
177            writer.println();
178        }
179    
180        public abstract IRender getDelegate();
181    
182        public abstract int getRefresh();
183    
184        public abstract IAsset getStylesheet();
185    
186        public abstract Object getStylesheets();
187    
188        public abstract String getTitle();
189    
190        public abstract String getDoctype();
191    
192        public abstract boolean getRenderContentType();
193    
194        /** @since 4.0 */
195        public abstract ValueConverter getValueConverter();
196    
197        /** @since 4.0 */
198    
199        public abstract IEngineService getPageService();
200    
201        /** @since 4.0 */
202    
203        public abstract IApplicationSpecification getApplicationSpecification();
204    
205        /** @since 4.0 */
206    
207        public abstract IRender getBaseTagWriter();
208        
209        /** @since 4.0.1 */
210        
211        public abstract boolean getRenderBaseTag();
212    }