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