001// Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 
002// The Molly framework is freely distributable under the terms of an
003// MIT-style license. For details, see the molly pages web site at:
004// http://www.mollypages.org/. Use, modify, have fun !
005
006package fc.web.page;
007
008import java.io.*;
009import java.util.*;
010
011import javax.servlet.*;
012import javax.servlet.http.*;
013
014/** 
015A page is a cool and sane replacement for JSP's with much better syntax.
016<p>
017Server side pages implement this interface via the concrete {@link PageImpl}
018class. This class has some additional utility methods as well that page
019authors may find useful.
020
021@author hursh jain
022*/
023public interface Page
024{
025//all pages result in java files with this package name;
026public static String  PACKAGE_NAME = "molly.pages";
027
028//not used: public static String  DEFAULT_ERROR_PAGE  = "/molly/error.mp";
029public static int     DEFAULT_BUFFER_SIZE   = 8048;
030
031/** 
032The default mime-type for each page. Usually, there should be no reason
033to change this. However, if need be, this can be changed via a page
034compiler directive or turned off entirely. If it's turned off, then the
035mime-type should be manually specified via the {@link
036javax.servlet.ServletResponse.setContentType} method.
037*/
038public static String  DEFAULT_MIME_TYPE     = "text/html";
039
040/** 
041The default encoding of the page, specified in the header sent back to the client. This
042can be changed to utf-8, utf-16 or any other coding by a page directive. Alternately, this
043can be set to an empty string and a different encoding can also be specified in the
044&lt;head&gt; section of the html document, for example:
045<pre>
046&lt;head&gt;&lt;meta http-equiv=content-type content='text/html; charset=UTF-8'&gt;&lt;/head&gt;
047</pre>
048<font color=red>Encodings can be tricky. We are first compiling a page into a java source
049file, then running the source file and sending it's output to the browser. <b>Read the
050page <a href="http://www.mollypages.org/page/charset.mp">encoding and charsets</a> if you
051are using any non-us-ascii or non-ISO-8859-1</b> characters in your molly source
052page.</font>
053*/
054public static String  DEFAULT_ENCODING    = "UTF-8";
055
056
057/**
058Used when compiling a page using javac. 
059<p> 
060If no src_encoding directive is present in the page, we use UTF-8 is the best modern way
061of doing this (ISO-8859-1 is obsolete and ISO-8859-1 documents can run into issues with
062javac (which may default to UTF-8 on modern platforms if not specified and
063umlauts/diacritics/accents are in UTF-8 and ISO-8859-1).
064*/
065public static String  DEFAULT_SRC_ENCODING  = "UTF-8";
066
067
068public void render(HttpServletRequest req, HttpServletResponse res) throws Exception;
069
070/**
071This method is invoked whenever a page is created and before it
072is run.
073<p>
074Pages should override this method to instantiate/set-up page
075variables as needed. (pages have no-arg constructors so like
076most of the servlet API, setup and initialization of variables
077is done in a init method instead).
078<p>
079When overriding this class, you must remember to 
080call: <tt>super.init</tt>
081<p>
082The page class is reloaded if the page is modified. Variables
083should therefore be cleaned up in the {@link destory} method 
084as needed.
085*/
086public void init(PageServlet servlet, String contextRelativePagePath) throws ServletException;
087
088/**
089This method is invoked whenever a page is destoryed/unloaded
090*/
091public void destroy();
092
093/**
094Returns the path to this page from the web servers <i>document root</i>. 
095<p>So for example, if the page is at <code>foo/bar.mp</code> and is running
096under the webapp context of <code>context1</code>, then the page path
097will be: <code>/context1/foo/bar.mp</code>. If there is no specific
098web app (i.e., the most common case of a default "" webapp), then the page
099path will be <code>/foo/bar.mp</code>
100<p>
101This page path is essentially what needs to be typed in the browsers
102URL window to invoke the page. It's also useful as form action parameters.
103For example, in a molly page:
104<blockquote>
105<pre>
106..
107&lt;form action="[=getPagePath(req)]" method="post"&gt;
108..
109&lt;/form&gt;
110</pre>
111</blockquote>
112This will submit the form to the same page where the form is defined. This
113can be hard coded of course but by using <code>getPagePath</code>, the html
114does not have to be changed if the name of the page changes on disk.
115*/
116public String getPagePath(HttpServletRequest req);
117
118/**
119Returns the real absolute directory path for the {@link #getPagePath PagePath}.
120<p>
121So, for example, for a webserver document root at
122<code>/web/sites/default/</code> and a page located in
123<code>foo/bar.mp</code>, the real path will be:
124<code>/web/sites/default/foo/bar.mp</code>
125*/
126public String getRealPath(HttpServletRequest req);
127
128/**
129Redirects the client to the new page location. This is a thin (possibly
130easier to remember) wrapper around the {@link HttpServletResponse.sendRedirect} method.
131<p>
132The location parameter can be relative to the specified request's URI or
133relative to the context root if it contains a leading '/'. The webapp name
134(if any) does <b>not</b> have to be specified, the redirect will creates a
135full URL <u>(including the webapp context path)</u> suitable for this
136purpose. 
137<p>
138For example:
139<style>
140#redirects {background: #cccccc; }
141#redirects tr {background: white; }
142#redirects .head {font-weight: bold; }
143</style>
144<table id=redirects border=0 cellspacing=1 cellpadding=7>
145<tr class=head>
146  <td width="25%">webapp context</td>
147  <td width="25%">current page</td>
148  <td width="25%">location parameter</td>
149  <td width="25%">resulting page</td>
150</tr>
151<tr>
152  <td>default web app ("/")</td>
153  <td>foo/bar.mp</td>
154  <td>baz.mp</td>
155  <td>foo/baz.mp</td>
156</tr>
157<tr>
158  <td>default web app ("/")</td>
159  <td>foo/bar.mp</td>
160  <td>/baz.mp</td>
161  <td>baz.mp</td>
162</tr>
163<tr>
164  <td>/myapp</td>
165  <td>foo/bar.mp</td>
166  <td>baz.mp</td>
167  <td>/myapp/foo/baz.mp</td>
168</tr>
169<tr>
170  <td>/myapp</td>
171  <td>foo/bar.mp</td>
172  <td>/baz.mp</td>
173  <td>/myapp/baz.mp</td>
174</tr>
175</table>
176
177@param  req     the current request
178@param  res     the current response
179@param  location  location to redirect to.
180*/
181public void clientRedirect(HttpServletRequest req, HttpServletResponse res, String newLocation) throws IOException;
182
183/**
184Returns a thread specific CharArrayWriter that can be passed to this method
185as various points in the page. The contents of this writer can then be
186printed on the page when desired. 
187<p>
188Note: The writer is <b>not</b> reset or flushed when it is retrieved. It
189must be <font color=blue>reset manually</font> via calling the {@link
190java.io.CharArrayWriter#reset} method. This design-decision allows request
191threads to collect debugging data across multiple pages.
192<p>
193The suggested usage idiom is:
194<blockquote>
195<pre>
196  dbg(true);
197  CharArrayWriter <font color=blue>cw</font> = getThreadLocalWriter():
198  bug(<font color=blue>cw</font>, "some message");
199  ...
200  bug(<font color=blue>cw</font>, "other message");
201  ...
202  <font color=blue>
203  cw.writeTo(out);
204  cw.reset();
205  </font>
206</pre>
207</blockquote>
208*/
209public CharArrayWriter getThreadLocalWriter();
210
211/* 
212These are in PageImpl but do they need to be in the Page interface as well ?
213Subject to change so prolly not, thus commented out. hj
214
215public void startTimer();
216public long getTime();
217public void dbg(boolean val);
218public void dbgPrefix(String dbg_prefix);
219public void dbgSuffix(String dbg_suffix);
220public void bug(final Writer writer, final Object str1) throws IOException;
221public void bug(final Writer writer, final Object str1, final Object str2) throws IOException;
222public void bug(final Writer writer, final Object str1, final Object str2, final Object str3) throws IOException;
223public void bug(final Writer writer, final Object str1, final Object str2, final Object str3, final Object... args) throws IOException;
224*/
225}