Source Code Cross Referenced for TemplateServlet.java in  » Scripting » groovy-1.0 » groovy » servlet » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Scripting » groovy 1.0 » groovy.servlet 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * $Id: TemplateServlet.java 4032 2006-08-30 07:18:49Z mguillem $
003:         * 
004:         * Copyright 2003 (C) James Strachan and Bob Mcwhirter. All Rights Reserved.
005:         * 
006:         * Redistribution and use of this software and associated documentation
007:         * ("Software"), with or without modification, are permitted provided that the
008:         * following conditions are met:
009:         * 
010:         * 1. Redistributions of source code must retain copyright statements and
011:         * notices. Redistributions must also contain a copy of this document.
012:         * 
013:         * 2. Redistributions in binary form must reproduce the above copyright notice,
014:         * this list of conditions and the following disclaimer in the documentation
015:         * and/or other materials provided with the distribution.
016:         * 
017:         * 3. The name "groovy" must not be used to endorse or promote products derived
018:         * from this Software without prior written permission of The Codehaus. For
019:         * written permission, please contact info@codehaus.org.
020:         * 
021:         * 4. Products derived from this Software may not be called "groovy" nor may
022:         * "groovy" appear in their names without prior written permission of The
023:         * Codehaus. "groovy" is a registered trademark of The Codehaus.
024:         * 
025:         * 5. Due credit should be given to The Codehaus - http://groovy.codehaus.org/
026:         * 
027:         * THIS SOFTWARE IS PROVIDED BY THE CODEHAUS AND CONTRIBUTORS ``AS IS'' AND ANY
028:         * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
029:         * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
030:         * DISCLAIMED. IN NO EVENT SHALL THE CODEHAUS OR ITS CONTRIBUTORS BE LIABLE FOR
031:         * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
032:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
033:         * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
034:         * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
035:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
036:         * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
037:         *  
038:         */
039:        package groovy.servlet;
040:
041:        import groovy.text.SimpleTemplateEngine;
042:        import groovy.text.Template;
043:        import groovy.text.TemplateEngine;
044:
045:        import java.io.File;
046:        import java.io.FileReader;
047:        import java.io.IOException;
048:        import java.io.Writer;
049:        import java.util.Date;
050:        import java.util.Map;
051:        import java.util.WeakHashMap;
052:
053:        import javax.servlet.ServletConfig;
054:        import javax.servlet.ServletException;
055:        import javax.servlet.http.HttpServletRequest;
056:        import javax.servlet.http.HttpServletResponse;
057:
058:        /**
059:         * A generic servlet for serving (mostly HTML) templates.
060:         * 
061:         * <p>
062:         * It delegates work to a <code>groovy.text.TemplateEngine</code> implementation 
063:         * processing HTTP requests.
064:         *
065:         * <h4>Usage</h4>
066:         * 
067:         * <code>helloworld.html</code> is a headless HTML-like template
068:         * <pre><code>
069:         *  &lt;html&gt;
070:         *    &lt;body&gt;
071:         *      &lt;% 3.times { %&gt;
072:         *        Hello World!
073:         *      &lt;% } %&gt;
074:         *      &lt;br&gt;
075:         *    &lt;/body&gt;
076:         *  &lt;/html&gt; 
077:         * </code></pre>
078:         * 
079:         * Minimal <code>web.xml</code> example serving HTML-like templates
080:         * <pre><code>
081:         * &lt;web-app&gt;
082:         *   &lt;servlet&gt;
083:         *     &lt;servlet-name&gt;template&lt;/servlet-name&gt;
084:         *     &lt;servlet-class&gt;groovy.servlet.TemplateServlet&lt;/servlet-class&gt;
085:         *   &lt;/servlet&gt;
086:         *   &lt;servlet-mapping&gt;
087:         *     &lt;servlet-name&gt;template&lt;/servlet-name&gt;
088:         *     &lt;url-pattern&gt;*.html&lt;/url-pattern&gt;
089:         *   &lt;/servlet-mapping&gt;
090:         * &lt;/web-app&gt;
091:         * </code></pre>
092:         * 
093:         * <h4>Template engine configuration</h4>
094:         * 
095:         * <p>
096:         * By default, the TemplateServer uses the {@link groovy.text.SimpleTemplateEngine}
097:         * which interprets JSP-like templates. The init parameter <code>template.engine</code>
098:         * defines the fully qualified class name of the template to use:
099:         * <pre>
100:         *   template.engine = [empty] - equals groovy.text.SimpleTemplateEngine
101:         *   template.engine = groovy.text.SimpleTemplateEngine
102:         *   template.engine = groovy.text.GStringTemplateEngine
103:         *   template.engine = groovy.text.XmlTemplateEngine
104:         * </pre>
105:         * 
106:         * <h4>Logging and extra-output options</h4>
107:         *
108:         * <p>
109:         * This implementation provides a verbosity flag switching log statements.
110:         * The servlet init parameter name is:
111:         * <pre>
112:         *   generate.by = true(default) | false
113:         * </pre>
114:         * 
115:         * @see TemplateServlet#setVariables(ServletBinding)
116:         * 
117:         * @author Christian Stein
118:         * @author Guillaume Laforge
119:         * @version 2.0
120:         */
121:        public class TemplateServlet extends AbstractHttpServlet {
122:
123:            /**
124:             * Simple cache entry that validates against last modified and length
125:             * attributes of the specified file. 
126:             *
127:             * @author Christian Stein
128:             */
129:            private static class TemplateCacheEntry {
130:
131:                Date date;
132:                long hit;
133:                long lastModified;
134:                long length;
135:                Template template;
136:
137:                public TemplateCacheEntry(File file, Template template) {
138:                    this (file, template, false); // don't get time millis for sake of speed
139:                }
140:
141:                public TemplateCacheEntry(File file, Template template,
142:                        boolean timestamp) {
143:                    if (file == null) {
144:                        throw new NullPointerException("file");
145:                    }
146:                    if (template == null) {
147:                        throw new NullPointerException("template");
148:                    }
149:                    if (timestamp) {
150:                        this .date = new Date(System.currentTimeMillis());
151:                    } else {
152:                        this .date = null;
153:                    }
154:                    this .hit = 0;
155:                    this .lastModified = file.lastModified();
156:                    this .length = file.length();
157:                    this .template = template;
158:                }
159:
160:                /**
161:                 * Checks the passed file attributes against those cached ones. 
162:                 *
163:                 * @param file
164:                 *  Other file handle to compare to the cached values.
165:                 * @return <code>true</code> if all measured values match, else <code>false</code>
166:                 */
167:                public boolean validate(File file) {
168:                    if (file == null) {
169:                        throw new NullPointerException("file");
170:                    }
171:                    if (file.lastModified() != this .lastModified) {
172:                        return false;
173:                    }
174:                    if (file.length() != this .length) {
175:                        return false;
176:                    }
177:                    hit++;
178:                    return true;
179:                }
180:
181:                public String toString() {
182:                    if (date == null) {
183:                        return "Hit #" + hit;
184:                    }
185:                    return "Hit #" + hit + " since " + date;
186:                }
187:
188:            }
189:
190:            /**
191:             * Simple file name to template cache map.
192:             */
193:            private final Map cache;
194:
195:            /**
196:             * Underlying template engine used to evaluate template source files.
197:             */
198:            private TemplateEngine engine;
199:
200:            /**
201:             * Flag that controls the appending of the "Generated by ..." comment.
202:             */
203:            private boolean generateBy;
204:
205:            /**
206:             * Create new TemplateSerlvet.
207:             */
208:            public TemplateServlet() {
209:                this .cache = new WeakHashMap();
210:                this .engine = null; // assigned later by init()
211:                this .generateBy = true; // may be changed by init()
212:            }
213:
214:            /**
215:             * Gets the template created by the underlying engine parsing the request.
216:             * 
217:             * <p>
218:             * This method looks up a simple (weak) hash map for an existing template
219:             * object that matches the source file. If the source file didn't change in
220:             * length and its last modified stamp hasn't changed compared to a precompiled
221:             * template object, this template is used. Otherwise, there is no or an
222:             * invalid template object cache entry, a new one is created by the underlying
223:             * template engine. This new instance is put to the cache for consecutive
224:             * calls.
225:             * </p>
226:             * 
227:             * @return The template that will produce the response text.
228:             * @param file
229:             *            The HttpServletRequest.
230:             * @throws ServletException
231:             *            If the request specified an invalid template source file 
232:             */
233:            protected Template getTemplate(File file) throws ServletException {
234:
235:                String key = file.getAbsolutePath();
236:                Template template = null;
237:
238:                /*
239:                 * Test cache for a valid template bound to the key.
240:                 */
241:                if (verbose) {
242:                    log("Looking for cached template by key \"" + key + "\"");
243:                }
244:                TemplateCacheEntry entry = (TemplateCacheEntry) cache.get(key);
245:                if (entry != null) {
246:                    if (entry.validate(file)) {
247:                        if (verbose) {
248:                            log("Cache hit! " + entry);
249:                        }
250:                        template = entry.template;
251:                    } else {
252:                        if (verbose) {
253:                            log("Cached template needs recompiliation!");
254:                        }
255:                    }
256:                } else {
257:                    if (verbose) {
258:                        log("Cache miss.");
259:                    }
260:                }
261:
262:                //
263:                // Template not cached or the source file changed - compile new template!
264:                //
265:                if (template == null) {
266:                    if (verbose) {
267:                        log("Creating new template from file " + file + "...");
268:                    }
269:                    FileReader reader = null;
270:                    try {
271:                        reader = new FileReader(file);
272:                        template = engine.createTemplate(reader);
273:                    } catch (Exception e) {
274:                        throw new ServletException(
275:                                "Creation of template failed: " + e, e);
276:                    } finally {
277:                        if (reader != null) {
278:                            try {
279:                                reader.close();
280:                            } catch (IOException ignore) {
281:                                // e.printStackTrace();
282:                            }
283:                        }
284:                    }
285:                    cache.put(key, new TemplateCacheEntry(file, template,
286:                            verbose));
287:                    if (verbose) {
288:                        log("Created and added template to cache. [key=" + key
289:                                + "]");
290:                    }
291:                }
292:
293:                //
294:                // Last sanity check.
295:                //
296:                if (template == null) {
297:                    throw new ServletException(
298:                            "Template is null? Should not happen here!");
299:                }
300:
301:                return template;
302:
303:            }
304:
305:            /**
306:             * Initializes the servlet from hints the container passes.
307:             * <p>
308:             * Delegates to sub-init methods and parses the following parameters:
309:             * <ul>
310:             * <li> <tt>"generatedBy"</tt> : boolean, appends "Generated by ..." to the
311:             *     HTML response text generated by this servlet.
312:             *     </li>
313:             * </ul>
314:             * @param config
315:             *  Passed by the servlet container.
316:             * @throws ServletException
317:             *  if this method encountered difficulties 
318:             *  
319:             * @see TemplateServlet#initTemplateEngine(ServletConfig)
320:             */
321:            public void init(ServletConfig config) throws ServletException {
322:                super .init(config);
323:                this .engine = initTemplateEngine(config);
324:                if (engine == null) {
325:                    throw new ServletException(
326:                            "Template engine not instantiated.");
327:                }
328:                String value = config.getInitParameter("generated.by");
329:                if (value != null) {
330:                    this .generateBy = Boolean.valueOf(value).booleanValue();
331:                }
332:                log("Servlet " + getClass().getName() + " initialized on "
333:                        + engine.getClass());
334:            }
335:
336:            /**
337:             * Creates the template engine.
338:             * 
339:             * Called by {@link TemplateServlet#init(ServletConfig)} and returns just 
340:             * <code>new groovy.text.SimpleTemplateEngine()</code> if the init parameter
341:             * <code>template.engine</code> is not set by the container configuration.
342:             * 
343:             * @param config 
344:             *  Current serlvet configuration passed by the container.
345:             * 
346:             * @return The underlying template engine or <code>null</code> on error.
347:             */
348:            protected TemplateEngine initTemplateEngine(ServletConfig config) {
349:                String name = config.getInitParameter("template.engine");
350:                if (name == null) {
351:                    return new SimpleTemplateEngine();
352:                }
353:                try {
354:                    return (TemplateEngine) Class.forName(name).newInstance();
355:                } catch (InstantiationException e) {
356:                    log("Could not instantiate template engine: " + name, e);
357:                } catch (IllegalAccessException e) {
358:                    log("Could not access template engine class: " + name, e);
359:                } catch (ClassNotFoundException e) {
360:                    log("Could not find template engine class: " + name, e);
361:                }
362:                return null;
363:            }
364:
365:            /**
366:             * Services the request with a response.
367:             * <p>
368:             * First the request is parsed for the source file uri. If the specified file
369:             * could not be found or can not be read an error message is sent as response.
370:             * 
371:             * </p>
372:             * @param request
373:             *            The http request.
374:             * @param response
375:             *            The http response.
376:             * @throws IOException 
377:             *            if an input or output error occurs while the servlet is
378:             *            handling the HTTP request
379:             * @throws ServletException
380:             *            if the HTTP request cannot be handled
381:             */
382:            public void service(HttpServletRequest request,
383:                    HttpServletResponse response) throws ServletException,
384:                    IOException {
385:
386:                if (verbose) {
387:                    log("Creating/getting cached template...");
388:                }
389:
390:                //
391:                // Get the template source file handle.
392:                //
393:                File file = super .getScriptUriAsFile(request);
394:                String name = file.getName();
395:                if (!file.exists()) {
396:                    response.sendError(HttpServletResponse.SC_NOT_FOUND);
397:                    return; // throw new IOException(file.getAbsolutePath());
398:                }
399:                if (!file.canRead()) {
400:                    response.sendError(HttpServletResponse.SC_FORBIDDEN,
401:                            "Can not read \"" + name + "\"!");
402:                    return; // throw new IOException(file.getAbsolutePath());
403:                }
404:
405:                //
406:                // Get the requested template.
407:                //
408:                long getMillis = System.currentTimeMillis();
409:                Template template = getTemplate(file);
410:                getMillis = System.currentTimeMillis() - getMillis;
411:
412:                //
413:                // Create new binding for the current request.
414:                //
415:                ServletBinding binding = new ServletBinding(request, response,
416:                        servletContext);
417:                setVariables(binding);
418:
419:                //
420:                // Prepare the response buffer content type _before_ getting the writer.
421:                // and set status code to ok
422:                //
423:                response.setContentType(CONTENT_TYPE_TEXT_HTML);
424:                response.setStatus(HttpServletResponse.SC_OK);
425:
426:                //
427:                // Get the output stream writer from the binding.
428:                //
429:                Writer out = (Writer) binding.getVariable("out");
430:                if (out == null) {
431:                    out = response.getWriter();
432:                }
433:
434:                //
435:                // Evaluate the template.
436:                //
437:                if (verbose) {
438:                    log("Making template \"" + name + "\"...");
439:                }
440:                // String made = template.make(binding.getVariables()).toString();
441:                // log(" = " + made);
442:                long makeMillis = System.currentTimeMillis();
443:                template.make(binding.getVariables()).writeTo(out);
444:                makeMillis = System.currentTimeMillis() - makeMillis;
445:
446:                if (generateBy) {
447:                    StringBuffer sb = new StringBuffer(100);
448:                    sb
449:                            .append("\n<!-- Generated by Groovy TemplateServlet [create/get=");
450:                    sb.append(Long.toString(getMillis));
451:                    sb.append(" ms, make=");
452:                    sb.append(Long.toString(makeMillis));
453:                    sb.append(" ms] -->\n");
454:                    out.write(sb.toString());
455:                }
456:
457:                //
458:                // flush the response buffer.
459:                //
460:                response.flushBuffer();
461:
462:                if (verbose) {
463:                    log("Template \"" + name
464:                            + "\" request responded. [create/get=" + getMillis
465:                            + " ms, make=" + makeMillis + " ms]");
466:                }
467:
468:            }
469:
470:            /**
471:             * Override this method to set your variables to the Groovy binding.
472:             * <p>
473:             * All variables bound the binding are passed to the template source text, 
474:             * e.g. the HTML file, when the template is merged.
475:             * </p>
476:             * <p>
477:             * The binding provided by TemplateServlet does already include some default
478:             * variables. As of this writing, they are (copied from 
479:             * {@link groovy.servlet.ServletBinding}):
480:             * <ul>
481:             * <li><tt>"request"</tt> : HttpServletRequest </li>
482:             * <li><tt>"response"</tt> : HttpServletResponse </li>
483:             * <li><tt>"context"</tt> : ServletContext </li>
484:             * <li><tt>"application"</tt> : ServletContext </li>
485:             * <li><tt>"session"</tt> : request.getSession(<b>false</b>) </li>
486:             * </ul>
487:             * </p>
488:             * <p>
489:             * And via implicite hard-coded keywords:
490:             * <ul>
491:             * <li><tt>"out"</tt> : response.getWriter() </li>
492:             * <li><tt>"sout"</tt> : response.getOutputStream() </li>
493:             * <li><tt>"html"</tt> : new MarkupBuilder(response.getWriter()) </li>
494:             * </ul>
495:             * </p>
496:             *
497:             * <p>Example binding all servlet context variables:
498:             * <pre><code>
499:             * class Mytlet extends TemplateServlet {
500:             * 
501:             *   protected void setVariables(ServletBinding binding) {
502:             *     // Bind a simple variable
503:             *     binding.setVariable("answer", new Long(42));
504:             *   
505:             *     // Bind all servlet context attributes...
506:             *     ServletContext context = (ServletContext) binding.getVariable("context");
507:             *     Enumeration enumeration = context.getAttributeNames();
508:             *     while (enumeration.hasMoreElements()) {
509:             *       String name = (String) enumeration.nextElement();
510:             *       binding.setVariable(name, context.getAttribute(name));
511:             *     }
512:             *   }
513:             * 
514:             * }
515:             * <code></pre>
516:             * </p>
517:             * 
518:             * @param binding
519:             *  to be modified
520:             */
521:            protected void setVariables(ServletBinding binding) {
522:                // empty
523:            }
524:
525:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.