1 // ========================================================================
2 // $Id: Page.java,v 1.5 2004/09/23 02:15:15 gregwilkins Exp $
3 // Copyright 1996-2004 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 // ========================================================================
15
16 package org.mortbay.html;
17 import java.io.IOException;
18 import java.io.Writer;
19 import java.util.Dictionary;
20 import java.util.Hashtable;
21
22 /* --------------------------------------------------------------------- */
23 /** HTML Page.
24 * A HTML Page extends composite with the addition of the HTML Header
25 * tags, fields and elements.
26 * Furthermore, individual parts of the page may be written or the
27 * progressive page be output with flush.
28 * <p>
29 * Pages contain parameters and named sections. These are used by
30 * derived Page classes that implement a Look and Feel. Page users
31 * may add to name sections such as "Margin" or "Footer" and set
32 * parameters such as "HelpUrl" without knowledge of how the look and feel
33 * will arrange these. To assist with standard look and feel creation
34 * Page defines a set of standard names for many common parameters
35 * and sections.
36 * <p>
37 * If named sections are used, the page constructor or completeSections
38 * must add the named section to the page in the appropriate places.
39 * If named sections are not added to the page, then they can only be
40 * written with an explicit call to write(out,"section",end);
41 * Changes in behaviour to section creation and adding, should be controlled
42 * via page properties.
43 * <p>
44 * @deprecated Unless somebody steps forward to update and maintain this package
45 * @see Composite
46 * @version $Id: Page.java,v 1.5 2004/09/23 02:15:15 gregwilkins Exp $
47 * @author Greg Wilkins
48 */
49 public class Page extends Composite
50 {
51 /* ----------------------------------------------------------------- */
52 public static final String
53 Request="Request",
54 Response="Response",
55 Header="Header",
56 Title="Title",
57 Section="Section",
58 HeaderSize="HdrSize", // HeaderSize string suitable for FRAMESET
59 Footer="Footer",
60 FooterSize="FtrSize", // FooterSize string suitable for FRAMESET
61 Content="Content",
62 ContentSize="CntSize",
63 Margin="Margin",
64 MarginSize="MrgSize",
65 LeftMargin="Left",
66 LeftMarginSize="LMSize",
67 RightMargin="Right",
68 RightMarginSize="RMSize",
69 Help="Help",
70 Home="Home",
71 Heading="Heading",
72 Up="Up",
73 Prev="Prev",
74 Next="Next",
75 Back="Back",
76 Target="Target",
77 BaseUrl="BaseUrl",
78 FgColour="FgColour",
79 BgColour="BgColour",
80 HighlightColour="HlColour",
81 PageType="PageType",
82 NoTitle="No Title"
83 ;
84
85 /* ----------------------------------------------------------------- */
86 protected Hashtable properties = new Hashtable(10);
87
88 /* ----------------------------------------------------------------- */
89 Hashtable sections = new Hashtable(10);
90 private Composite head= new Composite();
91 private String base="";
92 private boolean writtenHtmlHead = false;
93 private boolean writtenBodyTag = false;
94
95 /* ----------------------------------------------------------------- */
96 public Page()
97 {
98 this(NoTitle);
99 }
100
101 /* ----------------------------------------------------------------- */
102 public Page(String title)
103 {
104 title(title);
105 }
106
107 /* ----------------------------------------------------------------- */
108 public Page(String title, String attributes)
109 {
110 title(title);
111 attribute(attributes);
112 }
113
114 /* ----------------------------------------------------------------- */
115 /** Set page title.
116 * @return This Page (for chained commands)
117 */
118 public Page title(String title)
119 {
120 properties.put(Title,title);
121 String heading = (String)properties.get(Heading);
122 if (heading==null||heading.equals(NoTitle))
123 properties.put(Heading,title);
124 return this;
125 }
126
127 /* ----------------------------------------------------------------- */
128 /** Add element or object to the page header.
129 * @param o The Object to add. If it is a String or Element, it is
130 * added directly, otherwise toString() is called.
131 * @return This Page (for chained commands)
132 */
133 public Page addHeader(Object o)
134 {
135 head.add("\n");
136 head.add(o);
137 return this;
138 }
139
140 /* ----------------------------------------------------------------- */
141 /** Set page background image.
142 * @return This Page (for chained commands)
143 */
144 public final Page setBackGroundImage(String bg)
145 {
146 attribute("background",bg);
147 return this;
148 }
149
150 /* ----------------------------------------------------------------- */
151 /** Set page background color.
152 * @return This Page (for chained commands)
153 */
154 public final Page setBackGroundColor(String color)
155 {
156 properties.put(BgColour,color);
157 attribute("bgcolor",color);
158 return this;
159 }
160
161 /* ----------------------------------------------------------------- */
162 /** Set the URL Base for the Page.
163 * @param target Default link target, null if none.
164 * @param href Default absolute href, null if none.
165 * @return This Page (for chained commands)
166 */
167 public final Page setBase(String target, String href)
168 {
169 base="<base " +
170 ((target!=null)?("TARGET=\""+target+"\""):"") +
171 ((href!=null)?("HREF=\""+href+"\""):"") +
172 ">";
173 return this;
174 }
175
176 /* ----------------------------------------------------------------- */
177 /** Write the entire page by calling:<br>
178 * writeHtmlHead(out)<br>
179 * writeBodyTag(out)<br>
180 * writeElements(out)<br>
181 * writeHtmlEnd(out)
182 */
183 public void write(Writer out)
184 throws IOException
185 {
186 writeHtmlHead(out);
187 writeBodyTag(out);
188 writeElements(out);
189 writeHtmlEnd(out);
190 }
191
192 /* ------------------------------------------------------------ */
193 /** Write HTML page head tags.
194 * Write tags <HTML><head> .... </head>
195 */
196 public void writeHtmlHead(Writer out)
197 throws IOException
198 {
199 if (!writtenHtmlHead)
200 {
201 writtenHtmlHead=true;
202 completeSections();
203 out.write("<html><head>");
204 String title=(String)properties.get(Title);
205 if (title!=null && title.length()>0 && !title.equals(NoTitle))
206 out.write("<title>"+title+"</title>");
207 head.write(out);
208 out.write(base);
209 out.write("\n</head>\n");
210 }
211 }
212
213 /* ------------------------------------------------------------ */
214 /** Write HTML page body tag.
215 * Write tags <BODY page attributes>.
216 */
217 public void writeBodyTag(Writer out)
218 throws IOException
219 {
220 if (!writtenBodyTag)
221 {
222 writtenBodyTag = true;
223 out.write("<body "+attributes()+">\n");
224 }
225 }
226
227 /* ------------------------------------------------------------ */
228 /** Write end BODY and end HTML tags.
229 */
230 public void writeHtmlEnd(Writer out)
231 throws IOException
232 {
233 out.write("\n</body>\n");
234 out.write("</html>\n");
235 }
236
237 /* ------------------------------------------------------------ */
238 /** Write any body elements of the page.
239 */
240 public void writeElements(Writer out)
241 throws IOException
242 {
243 super.write(out);
244 }
245
246 /* ------------------------------------------------------------ */
247 /** Write page section.
248 * The page is written containing only the named section.
249 * If a head and bodyTag have not been written, then they
250 * are written before the section. If endHtml is true, the
251 * end HTML tag is also written.
252 * If the named section is Content and it cannot be found,
253 * then the normal page contents are written.
254 */
255 public void write(Writer out,
256 String section,
257 boolean endHtml)
258 throws IOException
259 {
260 writeHtmlHead(out);
261 writeBodyTag(out);
262 Composite s = getSection(section);
263 if (s==null)
264 {
265 if (section.equals(Content))
266 writeElements(out);
267 }
268 else
269 s.write(out);
270 if (endHtml)
271 writeHtmlEnd(out);
272 out.flush();
273 }
274
275 /* ------------------------------------------------------------ */
276 /* Flush the current contents of the page.
277 * writeHtmlEnd() is not called and should either be
278 * explicitly called or called via an eventual call to write()
279 */
280 public void flush(Writer out)
281 throws IOException
282 {
283 writeHtmlHead(out);
284 writeBodyTag(out);
285 super.flush(out);
286 }
287
288 /* ------------------------------------------------------------ */
289 /* Reset the page status to not written.
290 * This is useful if you want to send a page more than once.
291 */
292 public void rewind()
293 {
294 writtenHtmlHead = false;
295 writtenBodyTag = false;
296 }
297
298 /* ------------------------------------------------------------ */
299 /** Access the page properties. It is up to a derived Page class
300 * to interpret these properties.
301 */
302 public Dictionary properties()
303 {
304 return properties;
305 }
306
307 /* ------------------------------------------------------------ */
308 /** Return the preferred FrameSet to be used with a specialized Page.
309 * The Frames will be named after the sections they are to
310 * contain.
311 * The default implementation returns null
312 */
313 public FrameSet frameSet()
314 {
315 return null;
316 }
317
318 /* ------------------------------------------------------------ */
319 /** Set a composite as a named section. Other Page users may.
320 * add to the section by calling addTo(). It is up to the section
321 * creator to add the section to the page in it appropriate position.
322 */
323 public void setSection(String section, Composite composite)
324 {
325 sections.put(section,composite);
326 }
327
328 /* ------------------------------------------------------------ */
329 /** Set a composite as a named section and add it to the.
330 * contents of the page
331 */
332 public void addSection(String section, Composite composite)
333 {
334 sections.put(section,composite);
335 add(composite);
336 }
337
338 /* ------------------------------------------------------------ */
339 /** Get a composite as a named section.
340 */
341 public Composite getSection(String section)
342 {
343 return (Composite)sections.get(section);
344 }
345
346 /* ------------------------------------------------------------ */
347 /** Add content to a named sections. If the named section cannot.
348 * be found, the content is added to the page.
349 */
350 public void addTo(String section, Object element)
351 {
352 Composite s = (Composite)sections.get(section);
353 if (s==null)
354 add(element);
355 else
356 s.add(element);
357 }
358
359 /* ------------------------------------------------------------ */
360 /** This call back is called just before writeHeaders() actually
361 * writes the HTML page headers. It can be implemented by a derived
362 * Page class to complete a named section after the rest of the Page
363 * has been created and appropriate properties set.
364 */
365 protected void completeSections()
366 {
367 }
368 }