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 * <head> portions of the page. [ <a
036 * href="../../../../../ComponentReference/Shell.html">Component Reference </a>]
037 * <p>
038 * Specifically does <em>not</em> provide a <body> tag, that is usually accomplished using a
039 * {@link Body} 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 }