##### Coverage Report - org.melati.servlet.ConfigServlet

Classes in this File | Line Coverage | Branch Coverage | Complexity
ConfigServlet |
94% | 80/85
85% | 12/14
| 1.9333333333333333;1.933

1 |  |
     /*
2 |  |
      * $Source: /usr/cvsroot/melati/melati/src/site/resources/withWebmacro/org.melati.servlet.ConfigServlet.html,v $
3 |  |
      * $Revision: 1.1 $
4 |  |
      *
5 |  |
      * Copyright (C) 2000 Tim Joyce
6 |  |
      *
7 |  |
      * Part of Melati (http://melati.org), a framework for the rapid
8 |  |
      * development of clean, maintainable web applications.
9 |  |
      *
10 |  |
      * Melati is free software; Permission is granted to copy, distribute
11 |  |
      * and/or modify this software under the terms either:
12 |  |
      *
13 |  |
      * a) the GNU General Public License as published by the Free Software
14 |  |
      *    Foundation; either version 2 of the License, or (at your option)
15 |  |
      *    any later version,
16 |  |
      *
17 |  |
      *    or
18 |  |
      *
19 |  |
      * b) any version of the Melati Software License, as published
20 |  |
      *    at http://melati.org
21 |  |
      *
22 |  |
      * You should have received a copy of the GNU General Public License and
23 |  |
      * the Melati Software License along with this program;
24 |  |
      * if not, write to the Free Software Foundation, Inc.,
25 |  |
      * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA to obtain the
26 |  |
      * GNU General Public License and visit http://melati.org to obtain the
27 |  |
      * Melati Software License.
28 |  |
      *
29 |  |
      * Feel free to contact the Developers of Melati (http://melati.org),
30 |  |
      * if you would like to work out a different arrangement than the options
31 |  |
      * outlined here.  It is our intention to allow Melati to be used by as
32 |  |
      * wide an audience as possible.
33 |  |
      *
34 |  |
      * This program is distributed in the hope that it will be useful,
35 |  |
      * but WITHOUT ANY WARRANTY; without even the implied warranty of
36 |  |
      * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
37 |  |
      * GNU General Public License for more details.
38 |  |
      *
39 |  |
      * Contact details for copyright holder:
40 |  |
      *
41 |  |
      *     Tim Joyce <timj At paneris.org>
42 |  |
      *     http://paneris.org/
43 |  |
      *     68 Sandbanks Rd, Poole, Dorset. BH14 8BY. UK
44 |  |
      */
45 |  |
46 |  |
     package org.melati.servlet;
47 |  |
48 |  |
     import java.io.PrintWriter;
49 |  |
     import java.io.IOException;
50 |  |
51 |  |
     import javax.servlet.ServletConfig;
52 |  |
     import javax.servlet.ServletException;
53 |  |
     import javax.servlet.http.HttpServlet;
54 |  |
     import javax.servlet.http.HttpServletRequest;
55 |  |
     import javax.servlet.http.HttpServletResponse;
56 |  |
57 |  |
     import org.melati.Melati;
58 |  |
     import org.melati.PoemContext;
59 |  |
     import org.melati.MelatiConfig;
60 |  |
     import org.melati.poem.AccessPoemException;
61 |  |
     import org.melati.poem.NoSuchRowPoemException;
62 |  |
     import org.melati.util.ConnectionPendingException;
63 |  |
     import org.melati.util.MelatiWriter;
64 |  |
65 |  |
     /**
66 |  |
      * Config Servlet is the simplest way to use Melati.
67 |  |
      *
68 |  |
      * All a ConfigServlet does is to configure a melati and combine the
69 |  |
      * doGet and doPost methods.  Importantly it does not establish a poem session
70 |  |
      * leaving you to do this for yourself.
71 |  |
      *
72 |  |
      * If you want a poem session established, please extend PoemServlet.
73 |  |
      *
74 |  |
      * ConfigServlet does set up a basic PoemContext with the Method set,
75 |  |
      * but not the POEM logicaldatabase, table or troid.
76 |  |
      *
77 |  |
      * The URL is expected to take one of the following form:
78 |  |
      *
79 |  |
      * <BLOCKQUOTE><TT>
80 |  |
      * http://<I>h</I>/<I>s</I>/<I>meth</I>
81 |  |
      * </TT></BLOCKQUOTE>
82 |  |
      *
83 |  |
      * the method is broken out of the path info and passed to
84 |  |
      * your application code in the <TT>Melati</TT> and
85 |  |
      * <TT>PoemContext</TT> parameter
86 |  |
      *
87 |  |
      * <TABLE>
88 |  |
      *   <TR>
89 |  |
      *     <TD><TT><I>h</I></TT></TD>
90 |  |
      *     <TD>host name, such as <TT>www.melati.org</TT></TD>
91 |  |
      *   </TR>
92 |  |
      *   <TR>
93 |  |
      *     <TD><TT><I>s</I></TT></TD>
94 |  |
      *     <TD>
95 |  |
      *       servlet-determining part, such as
96 |  |
      *       <TT>melati/org.melati.admin.Admin</TT>
97 |  |
      *     </TD>
98 |  |
      *   </TR>
99 |  |
      *   <TR>
100 |  |
      *     <TD><TT><I>meth</I></TT></TD>
101 |  |
      *     <TD>
102 |  |
      *       A freeform string telling your servlet what it is meant to do.  This
103 |  |
      *       is automatically made available in templates as
104 |  |
      *       <TT>$melati.Method</TT>.
105 |  |
      *     </TD>
106 |  |
      *   </TR>
107 |  |
      * </TABLE>
108 |  |
      *
109 |  |
      * You can change the way these things are determined by overriding
110 |  |
      * <TT>poemContext(Melati)</TT>.
111 |  |
      */
112 |  |
113 | 156 |
     public abstract class ConfigServlet extends HttpServlet {
114 |  |
115 |  |
       /**
116 |  |
        * Eclipse generated.
117 |  |
        */
118 |  |
       private static final long serialVersionUID = 8995954958766276122L;
119 |  |
120 |  |
       protected MelatiConfig melatiConfig;
121 | 78 |
       protected String sysAdminName = "nobody";
122 | 78 |
       protected String sysAdminEmail = "nobody@nobody.com";;
123 |  |
124 |  |
       /**
125 |  |
        * Inititialise Melati.
126 |  |
        *
127 |  |
        * @param config a <code>ServletConfig</code>
128 |  |
        * @throws ServletException is anything goes wrong
129 |  |
        */
130 |  |
       public void init(ServletConfig config) throws ServletException {
131 | 78 |
         super.init(config);
132 | 78 |
         melatiConfig = melatiConfig();
133 | 76 |
       }
134 |  |
135 |  |
       /**
136 |  |
        * Handles GET.
137 |  |
        *
138 |  |
        * @param request the incoming <code>HttpServletRequest</code>
139 |  |
        * @param response the outgoing <code>HttpServletResponse</code>
140 |  |
        */
141 |  |
       public void doGet(HttpServletRequest request,
142 |  |
                         HttpServletResponse response) {
143 | 1041 |
         doGetPostRequest(request, response);
144 | 1039 |
       }
145 |  |
146 |  |
       /**
147 |  |
        * Handle a POST.
148 |  |
        *
149 |  |
        * @param request the incoming <code>HttpServletRequest</code>
150 |  |
        * @param response the outgoing <code>HttpServletResponse</code>
151 |  |
        */
152 |  |
       public void doPost(HttpServletRequest request,
153 |  |
                          HttpServletResponse response) {
154 | 132 |
         doGetPostRequest(request, response);
155 | 132 |
       }
156 |  |
157 |  |
       /**
158 |  |
        * Process the request.
159 |  |
        *
160 |  |
        * Exceptions are presented to the user if practicable, or written to the log.
161 |  |
        *
162 |  |
        * @param request the incoming <code>HttpServletRequest</code>
163 |  |
        * @param response the outgoing <code>HttpServletResponse</code>
164 |  |
        */
165 |  |
       private void doGetPostRequest(final HttpServletRequest request,
166 |  |
                                     final HttpServletResponse response) {
167 | 1173 |
         Melati melati = new Melati(melatiConfig, request, response);
168 |  |
         try {
169 | 1173 |
           melati.establishCharsets();
170 | 1173 |
           melati.setPoemContext(poemContext(melati));
171 | 1173 |
           doConfiguredRequest(melati);
172 |  |
           // send the output to the client
173 | 1147 |
           melati.write();
174 |  |
         }
175 | 28 |
         catch (Exception e) {
176 | 28 |
           error(melati,e);
177 | 1145 |
         }
178 | 1171 |
       }
179 |  |
180 |  |
       /**
181 |  |
        * Send an error message.
182 |  |
        *
183 |  |
        * @param melati the {@link Melati}
184 |  |
        * @param e      the {@link Exception} to report
185 |  |
        */
186 |  |
       public void error(Melati melati, Exception e) {
187 | 20 |
         melati.getResponse().setStatus(httpStatusCode(e));
188 |  |
189 |  |
         // has it been trapped already, if so, we don't need to relog it here
190 | 20 |
         if (! (e instanceof TrappedException)) {
191 |  |
           try {
192 |  |
             // log it
193 | 16 |
             e.printStackTrace(System.err);
194 |  |
             // and put it on the page
195 | 16 |
             melati.setResponseContentType ("text/html");
196 | 16 |
             MelatiWriter mw =  melati.getWriter();
197 |  |
             // get rid of anything that has been written so far
198 | 16 |
             mw.reset();
199 | 16 |
             PrintWriter out = new PrintWriter(mw.getWriter());
200 | 16 |
             if (e instanceof ConnectionPendingException) {
201 | 2 |
               writeConnectionPendingException(out,e);
202 |  |
             } else {
203 | 14 |
               writeError(out,e);
204 |  |
             }
205 | 16 |
             melati.write();
206 | 0 |
           } catch (IOException f) {
207 | 0 |
             e.printStackTrace(System.err);
208 | 0 |
             throw new TrappedException("Problem logging error", f);
209 | 14 |
           }
210 |  |
         }
211 | 18 |
       }
212 |  |
213 |  |
       protected int httpStatusCode(Exception e) {
214 | 50 |
         if (e instanceof AccessPoemException)
215 | 2 |
           return 401; // Not Authorized
216 | 48 |
         if (e instanceof InvalidUsageException)
217 | 2 |
           return 400; // Client error
218 | 46 |
         if (e instanceof NoSuchRowPoemException)
219 | 0 |
           return 404; // Not found
220 | 46 |
         return 500; // Server error
221 |  |
       }
222 |  |
223 |  |
       /**
224 |  |
        * Print an error directly to the client.
225 |  |
        *
226 |  |
        * This is rarely called, eg when the template engine
227 |  |
        * fails to render the default error template.
228 |  |
        *
229 |  |
        * @param out the <code>PrintWriter</code> to print to
230 |  |
        * @param e   the {@link Exception} to report
231 |  |
        */
232 |  |
       public void writeError(PrintWriter out, Exception e) {
233 | 14 |
         out.println("<html><head><title>Melati Error</title></head>");
234 | 14 |
         out.println("<!-- HTML generated in " +
235 |  |
                     "org.melati.servlet.ConfigServlet.java -->");
236 | 14 |
         out.println("<body><h2>Melati Error</h2>");
237 | 14 |
         out.println("<h3>Reported from ConfigServlet</h3>");
238 | 14 |
         out.println("<p>An error has occured in the application");
239 | 14 |
         out.println("that runs this website, please contact <a href='mailto:");
240 | 14 |
         out.println(getSysAdminEmail() + "'>" + getSysAdminName() + "</a>");
241 | 14 |
         out.println(", with the information given below.</p>");
242 | 14 |
         out.println("<h4><font color='red'><pre>");
243 | 14 |
         e.printStackTrace(out);
244 | 14 |
         out.println("</pre></font></h4></body></html>");
245 | 14 |
       }
246 |  |
247 |  |
       /**
248 |  |
        * Print the <code>ConnectionPendingException</code>  directly to the client.
249 |  |
        *
250 |  |
        * This is called if a request is made whilst the system is
251 |  |
        * still being initialised.
252 |  |
        *
253 |  |
        * @param out the <code>PrintWriter</code> to print to
254 |  |
        * @param e   the {@link Exception} to report
255 |  |
        */
256 |  |
       public void writeConnectionPendingException(PrintWriter out, Exception e) {
257 | 2 |
         out.println("<html><head><title>Database Initialising</title>\n");
258 | 2 |
         out.println("<META HTTP-EQUIV='Refresh' CONTENT='30'>\n</head>\n");
259 | 2 |
         out.println("<!-- Generated in org.melati.servlet.ConfigServlet.java -->");
260 | 2 |
         out.println("<body><center><h2>Database Initialising</h2><p>&nbsp;</p>");
261 | 2 |
         out.println("<p><b>Sorry</b>, ");
262 | 2 |
         out.println("the database that runs this website is just starting up.");
263 | 2 |
         out.println("This takes a few seconds, ");
264 | 2 |
         out.println("so you should be able to use the site in a moment.");
265 | 2 |
         out.println("<p>This page will refresh in 30 seconds, ");
266 | 2 |
         out.println("and you will be able to continue.</p>");
267 | 2 |
         out.println("<!--");
268 | 2 |
         e.printStackTrace(out);
269 | 2 |
         out.println("--></center></body></html>");
270 | 2 |
       }
271 |  |
272 |  |
       /**
273 |  |
        * This method <b>SHOULD</b> be overidden.
274 |  |
        * @return the System Administrators name.
275 |  |
        */
276 |  |
       public String getSysAdminName () {
277 | 8 |
         return sysAdminName;
278 |  |
       }
279 |  |
280 |  |
       /**
281 |  |
        * This method <b>SHOULD</b> be overidden.
282 |  |
        * @return the System Administrators email address.
283 |  |
        */
284 |  |
       public String getSysAdminEmail () {
285 | 8 |
         return sysAdminEmail;
286 |  |
       }
287 |  |
288 |  |
       /**
289 |  |
        * @param sysAdminEmail The sysAdminEmail to set.
290 |  |
        */
291 |  |
       protected void setSysAdminEmail(String sysAdminEmail) {
292 | 1121 |
         this.sysAdminEmail = sysAdminEmail;
293 | 1121 |
       }
294 |  |
295 |  |
296 |  |
       /**
297 |  |
        * @param sysAdminName The sysAdminName to set.
298 |  |
        */
299 |  |
       protected void setSysAdminName(String sysAdminName) {
300 | 1121 |
         this.sysAdminName = sysAdminName;
301 | 1121 |
       }
302 |  |
303 |  |
       protected PoemContext poemContext(Melati melati)
304 |  |
           throws PathInfoException {
305 | 52 |
         PoemContext it = new PoemContext();
306 | 52 |
         String[] parts = melati.getPathInfoParts();
307 | 52 |
         if (parts.length > 0)
308 | 32 |
          it.setMethod(parts[parts.length - 1]);
309 | 52 |
        return it;
310 |  |
      }
311 |  |
312 |  |
       /**
313 |  |
        * To override any setting from org.melati.MelatiConfig.properties,
314 |  |
        * simply override this method and return a valid MelatiConfig.
315 |  |
        *
316 |  |
        * eg to use a different AccessHandler from the default:
317 |  |
        *
318 |  |
        * <PRE>
319 |  |
        *   protected MelatiConfig melatiConfig() throws MelatiException {
320 |  |
        *     MelatiConfig config = super.melatiConfig();
321 |  |
        *     config.setAccessHandler(new YourAccessHandler());
322 |  |
        *     return config;
323 |  |
        *   }
324 |  |
        * </PRE>
325 |  |
        *
326 |  |
        * @return a new {@link MelatiConfig}
327 |  |
        */
328 |  |
       protected MelatiConfig melatiConfig() {
329 | 74 |
         MelatiConfig m = new MelatiConfig();
330 | 74 |
         String realPath = getServletConfig().getServletContext().getRealPath("/");
331 | 74 |
         if (realPath == null)
332 | 0 |
           throw new NullPointerException();
333 | 74 |
         m.setRealPath(realPath);
334 | 74 |
         return m;
335 |  |
       }
336 |  |
337 |  |
       /**
338 |  |
        * Instantiate this method to build up your own output.
339 |  |
        * @param melati
340 |  |
        * @throws Exception if anything goes wrong
341 |  |
        */
342 |  |
       protected abstract void doConfiguredRequest(Melati melati)
343 |  |
           throws Exception;
344 |  |
345 |  |
346 |  |
     }