Source Code Cross Referenced for TurbineVelocityService.java in  » Web-Framework » TURBINE » org » apache » turbine » services » velocity » 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 » Web Framework » TURBINE » org.apache.turbine.services.velocity 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package org.apache.turbine.services.velocity;
002:
003:        /*
004:         * Licensed to the Apache Software Foundation (ASF) under one
005:         * or more contributor license agreements.  See the NOTICE file
006:         * distributed with this work for additional information
007:         * regarding copyright ownership.  The ASF licenses this file
008:         * to you under the Apache License, Version 2.0 (the
009:         * "License"); you may not use this file except in compliance
010:         * with the License.  You may obtain a copy of the License at
011:         *
012:         *   http://www.apache.org/licenses/LICENSE-2.0
013:         *
014:         * Unless required by applicable law or agreed to in writing,
015:         * software distributed under the License is distributed on an
016:         * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017:         * KIND, either express or implied.  See the License for the
018:         * specific language governing permissions and limitations
019:         * under the License.
020:         */
021:
022:        import java.io.ByteArrayOutputStream;
023:        import java.io.IOException;
024:        import java.io.OutputStream;
025:        import java.io.OutputStreamWriter;
026:        import java.io.Writer;
027:        import java.util.Iterator;
028:        import java.util.List;
029:        import java.util.Vector;
030:
031:        import javax.servlet.ServletConfig;
032:
033:        import org.apache.commons.collections.ExtendedProperties;
034:        import org.apache.commons.configuration.Configuration;
035:        import org.apache.commons.lang.StringUtils;
036:        import org.apache.commons.logging.Log;
037:        import org.apache.commons.logging.LogFactory;
038:        import org.apache.turbine.Turbine;
039:        import org.apache.turbine.services.InitializationException;
040:        import org.apache.turbine.services.pull.PullService;
041:        import org.apache.turbine.services.pull.TurbinePull;
042:        import org.apache.turbine.services.template.BaseTemplateEngineService;
043:        import org.apache.turbine.util.RunData;
044:        import org.apache.turbine.util.TurbineException;
045:        import org.apache.velocity.VelocityContext;
046:        import org.apache.velocity.app.Velocity;
047:        import org.apache.velocity.app.event.EventCartridge;
048:        import org.apache.velocity.app.event.MethodExceptionEventHandler;
049:        import org.apache.velocity.context.Context;
050:        import org.apache.velocity.runtime.log.Log4JLogChute;
051:
052:        /**
053:         * This is a Service that can process Velocity templates from within a
054:         * Turbine Screen. It is used in conjunction with the templating service
055:         * as a Templating Engine for templates ending in "vm". It registers
056:         * itself as translation engine with the template service and gets
057:         * accessed from there. After configuring it in your properties, it
058:         * should never be necessary to call methods from this service directly.
059:         *
060:         * Here's an example of how you might use it from a
061:         * screen:<br>
062:         *
063:         * <code>
064:         * Context context = TurbineVelocity.getContext(data);<br>
065:         * context.put("message", "Hello from Turbine!");<br>
066:         * String results = TurbineVelocity.handleRequest(context,"helloWorld.vm");<br>
067:         * data.getPage().getBody().addElement(results);<br>
068:         * </code>
069:         *
070:         * @author <a href="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
071:         * @author <a href="mailto:krzewski@e-point.pl">Rafal Krzewski</a>
072:         * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
073:         * @author <a href="mailto:sean@informage.ent">Sean Legassick</a>
074:         * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
075:         * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
076:         * @version $Id: TurbineVelocityService.java 552336 2007-07-01 16:33:47Z tv $
077:         */
078:        public class TurbineVelocityService extends BaseTemplateEngineService
079:                implements  VelocityService, MethodExceptionEventHandler {
080:            /** The generic resource loader path property in velocity.*/
081:            private static final String RESOURCE_LOADER_PATH = ".resource.loader.path";
082:
083:            /** Default character set to use if not specified in the RunData object. */
084:            private static final String DEFAULT_CHAR_SET = "ISO-8859-1";
085:
086:            /** The prefix used for URIs which are of type <code>jar</code>. */
087:            private static final String JAR_PREFIX = "jar:";
088:
089:            /** The prefix used for URIs which are of type <code>absolute</code>. */
090:            private static final String ABSOLUTE_PREFIX = "file://";
091:
092:            /** Logging */
093:            private static Log log = LogFactory
094:                    .getLog(TurbineVelocityService.class);
095:
096:            /** Is the pullModelActive? */
097:            private boolean pullModelActive = false;
098:
099:            /** Shall we catch Velocity Errors and report them in the log file? */
100:            private boolean catchErrors = true;
101:
102:            /** Default encoding to use if not specified in the RunData object. */
103:            private String defaultEncoding = DEFAULT_CHAR_SET;
104:
105:            /** Internal Reference to the pull Service */
106:            private PullService pullService = null;
107:
108:            /**
109:             * Load all configured components and initialize them. This is
110:             * a zero parameter variant which queries the Turbine Servlet
111:             * for its config.
112:             *
113:             * @throws InitializationException Something went wrong in the init
114:             *         stage
115:             */
116:            public void init() throws InitializationException {
117:                try {
118:                    initVelocity();
119:
120:                    // We can only load the Pull Model ToolBox
121:                    // if the Pull service has been listed in the TR.props
122:                    // and the service has successfully been initialized.
123:                    if (TurbinePull.isRegistered()) {
124:                        pullModelActive = true;
125:
126:                        pullService = TurbinePull.getService();
127:
128:                        log.debug("Activated Pull Tools");
129:                    }
130:
131:                    // Register with the template service.
132:                    registerConfiguration(VelocityService.VELOCITY_EXTENSION);
133:
134:                    setInit(true);
135:                } catch (Exception e) {
136:                    throw new InitializationException(
137:                            "Failed to initialize TurbineVelocityService", e);
138:                }
139:            }
140:
141:            /**
142:             * Inits the service using servlet parameters to obtain path to the
143:             * configuration file.
144:             *
145:             * @param config The ServletConfiguration from Turbine
146:             *
147:             * @throws InitializationException Something went wrong when starting up.
148:             * @deprecated use init() instead.
149:             */
150:            public void init(ServletConfig config)
151:                    throws InitializationException {
152:                init();
153:            }
154:
155:            /**
156:             * Create a Context object that also contains the globalContext.
157:             *
158:             * @return A Context object.
159:             */
160:            public Context getContext() {
161:                Context globalContext = pullModelActive ? pullService
162:                        .getGlobalContext() : null;
163:
164:                Context ctx = new VelocityContext(globalContext);
165:                return ctx;
166:            }
167:
168:            /**
169:             * This method returns a new, empty Context object.
170:             *
171:             * @return A Context Object.
172:             */
173:            public Context getNewContext() {
174:                Context ctx = new VelocityContext();
175:
176:                // Attach an Event Cartridge to it, so we get exceptions
177:                // while invoking methods from the Velocity Screens
178:                EventCartridge ec = new EventCartridge();
179:                ec.addEventHandler(this );
180:                ec.attachToContext(ctx);
181:                return ctx;
182:            }
183:
184:            /**
185:             * MethodException Event Cartridge handler
186:             * for Velocity.
187:             *
188:             * It logs an execption thrown by the velocity processing
189:             * on error level into the log file
190:             *
191:             * @param clazz The class that threw the exception
192:             * @param method The Method name that threw the exception
193:             * @param e The exception that would've been thrown
194:             * @return A valid value to be used as Return value
195:             * @throws Exception We threw the exception further up
196:             */
197:            public Object methodException(Class clazz, String method,
198:                    Exception e) throws Exception {
199:                log.error("Class " + clazz.getName() + "." + method
200:                        + " threw Exception", e);
201:
202:                if (!catchErrors) {
203:                    throw e;
204:                }
205:
206:                return "[Turbine caught an Error here. Look into the turbine.log for further information]";
207:            }
208:
209:            /**
210:             * Create a Context from the RunData object.  Adds a pointer to
211:             * the RunData object to the VelocityContext so that RunData
212:             * is available in the templates.
213:             *
214:             * @param data The Turbine RunData object.
215:             * @return A clone of the WebContext needed by Velocity.
216:             */
217:            public Context getContext(RunData data) {
218:                // Attempt to get it from the data first.  If it doesn't
219:                // exist, create it and then stuff it into the data.
220:                Context context = (Context) data.getTemplateInfo()
221:                        .getTemplateContext(VelocityService.CONTEXT);
222:
223:                if (context == null) {
224:                    context = getContext();
225:                    context.put(VelocityService.RUNDATA_KEY, data);
226:
227:                    if (pullModelActive) {
228:                        // Populate the toolbox with request scope, session scope
229:                        // and persistent scope tools (global tools are already in
230:                        // the toolBoxContent which has been wrapped to construct
231:                        // this request-specific context).
232:                        pullService.populateContext(context, data);
233:                    }
234:
235:                    data.getTemplateInfo().setTemplateContext(
236:                            VelocityService.CONTEXT, context);
237:                }
238:                return context;
239:            }
240:
241:            /**
242:             * Process the request and fill in the template with the values
243:             * you set in the Context.
244:             *
245:             * @param context  The populated context.
246:             * @param filename The file name of the template.
247:             * @return The process template as a String.
248:             *
249:             * @throws TurbineException Any exception trown while processing will be
250:             *         wrapped into a TurbineException and rethrown.
251:             */
252:            public String handleRequest(Context context, String filename)
253:                    throws TurbineException {
254:                String results = null;
255:                ByteArrayOutputStream bytes = null;
256:                OutputStreamWriter writer = null;
257:                String charset = getCharSet(context);
258:
259:                try {
260:                    bytes = new ByteArrayOutputStream();
261:
262:                    writer = new OutputStreamWriter(bytes, charset);
263:
264:                    executeRequest(context, filename, writer);
265:                    writer.flush();
266:                    results = bytes.toString(charset);
267:                } catch (Exception e) {
268:                    renderingError(filename, e);
269:                } finally {
270:                    try {
271:                        if (bytes != null) {
272:                            bytes.close();
273:                        }
274:                    } catch (IOException ignored) {
275:                        // do nothing.
276:                    }
277:                }
278:                return results;
279:            }
280:
281:            /**
282:             * Process the request and fill in the template with the values
283:             * you set in the Context.
284:             *
285:             * @param context A Context.
286:             * @param filename A String with the filename of the template.
287:             * @param output A OutputStream where we will write the process template as
288:             * a String.
289:             *
290:             * @throws TurbineException Any exception trown while processing will be
291:             *         wrapped into a TurbineException and rethrown.
292:             */
293:            public void handleRequest(Context context, String filename,
294:                    OutputStream output) throws TurbineException {
295:                String charset = getCharSet(context);
296:                OutputStreamWriter writer = null;
297:
298:                try {
299:                    writer = new OutputStreamWriter(output, charset);
300:                    executeRequest(context, filename, writer);
301:                } catch (Exception e) {
302:                    renderingError(filename, e);
303:                } finally {
304:                    try {
305:                        if (writer != null) {
306:                            writer.flush();
307:                        }
308:                    } catch (Exception ignored) {
309:                        // do nothing.
310:                    }
311:                }
312:            }
313:
314:            /**
315:             * Process the request and fill in the template with the values
316:             * you set in the Context.
317:             *
318:             * @param context A Context.
319:             * @param filename A String with the filename of the template.
320:             * @param writer A Writer where we will write the process template as
321:             * a String.
322:             *
323:             * @throws TurbineException Any exception trown while processing will be
324:             *         wrapped into a TurbineException and rethrown.
325:             */
326:            public void handleRequest(Context context, String filename,
327:                    Writer writer) throws TurbineException {
328:                try {
329:                    executeRequest(context, filename, writer);
330:                } catch (Exception e) {
331:                    renderingError(filename, e);
332:                } finally {
333:                    try {
334:                        if (writer != null) {
335:                            writer.flush();
336:                        }
337:                    } catch (Exception ignored) {
338:                        // do nothing.
339:                    }
340:                }
341:            }
342:
343:            /**
344:             * Process the request and fill in the template with the values
345:             * you set in the Context. Apply the character and template
346:             * encodings from RunData to the result.
347:             *
348:             * @param context A Context.
349:             * @param filename A String with the filename of the template.
350:             * @param writer A OutputStream where we will write the process template as
351:             * a String.
352:             *
353:             * @throws Exception A problem occured.
354:             */
355:            private void executeRequest(Context context, String filename,
356:                    Writer writer) throws Exception {
357:                String encoding = getEncoding(context);
358:
359:                Velocity.mergeTemplate(filename, encoding, context, writer);
360:            }
361:
362:            /**
363:             * Retrieve the required charset from the Turbine RunData in the context
364:             *
365:             * @param context A Context.
366:             * @return The character set applied to the resulting String.
367:             */
368:            private String getCharSet(Context context) {
369:                String charset = null;
370:
371:                Object data = context.get(VelocityService.RUNDATA_KEY);
372:                if ((data != null) && (data instanceof  RunData)) {
373:                    charset = ((RunData) data).getCharSet();
374:                }
375:
376:                return (StringUtils.isEmpty(charset)) ? DEFAULT_CHAR_SET
377:                        : charset;
378:            }
379:
380:            /**
381:             * Retrieve the required encoding from the Turbine RunData in the context
382:             *
383:             * @param context A Context.
384:             * @return The encoding applied to the resulting String.
385:             */
386:            private String getEncoding(Context context) {
387:                String encoding = null;
388:
389:                Object data = context.get(VelocityService.RUNDATA_KEY);
390:                if ((data != null) && (data instanceof  RunData)) {
391:                    encoding = ((RunData) data).getTemplateEncoding();
392:                }
393:
394:                return (StringUtils.isEmpty(encoding)) ? defaultEncoding
395:                        : encoding;
396:            }
397:
398:            /**
399:             * Macro to handle rendering errors.
400:             *
401:             * @param filename The file name of the unrenderable template.
402:             * @param e        The error.
403:             *
404:             * @exception TurbineException Thrown every time.  Adds additional
405:             *                             information to <code>e</code>.
406:             */
407:            private static void renderingError(String filename, Exception e)
408:                    throws TurbineException {
409:                String err = "Error rendering Velocity template: " + filename;
410:                log.error(err, e);
411:                throw new TurbineException(err, e);
412:            }
413:
414:            /**
415:             * Setup the velocity runtime by using a subset of the
416:             * Turbine configuration which relates to velocity.
417:             *
418:             * @exception Exception An Error occured.
419:             */
420:            private synchronized void initVelocity() throws Exception {
421:                // Get the configuration for this service.
422:                Configuration conf = getConfiguration();
423:
424:                catchErrors = conf.getBoolean(CATCH_ERRORS_KEY,
425:                        CATCH_ERRORS_DEFAULT);
426:
427:                if (conf.containsKey(Velocity.INPUT_ENCODING)) {
428:                    defaultEncoding = conf.getString(Velocity.INPUT_ENCODING);
429:                }
430:
431:                conf.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM_CLASS,
432:                        Log4JLogChute.class.getName());
433:                conf.setProperty(Velocity.RUNTIME_LOG_LOGSYSTEM
434:                        + ".log4j.category", "velocity");
435:
436:                Velocity.setExtendedProperties(createVelocityProperties(conf));
437:                Velocity.init();
438:            }
439:
440:            /**
441:             * This method generates the Extended Properties object necessary
442:             * for the initialization of Velocity. It also converts the various
443:             * resource loader pathes into webapp relative pathes. It also
444:             *
445:             * @param conf The Velocity Service configuration
446:             *
447:             * @return An ExtendedProperties Object for Velocity
448:             *
449:             * @throws Exception If a problem occured while converting the properties.
450:             */
451:
452:            public ExtendedProperties createVelocityProperties(
453:                    Configuration conf) throws Exception {
454:                // This bugger is public, because we want to run some Unit tests
455:                // on it.
456:
457:                ExtendedProperties veloConfig = new ExtendedProperties();
458:
459:                // Fix up all the template resource loader pathes to be
460:                // webapp relative. Copy all other keys verbatim into the
461:                // veloConfiguration.
462:
463:                for (Iterator i = conf.getKeys(); i.hasNext();) {
464:                    String key = (String) i.next();
465:                    if (!key.endsWith(RESOURCE_LOADER_PATH)) {
466:                        Object value = conf.getProperty(key);
467:
468:                        // Since 1.0-pre-something, Commons Collections suddently
469:                        // no longer returns a vector for multiple value-keys but a
470:                        // List object. Velocity will choke if we add this object because
471:                        // org.apache.commons.collections.ExtendedProperties expect a
472:                        // Vector object. Ah, the joys of incompatible class changes,
473:                        // unwritten assumptions and general Java JAR Hell... =8-O
474:                        if (value instanceof  List) {
475:                            List srcValue = (List) value;
476:                            Vector targetValue = new Vector(srcValue.size());
477:
478:                            for (Iterator it = srcValue.iterator(); it
479:                                    .hasNext();) {
480:                                targetValue.add(it.next());
481:                            }
482:
483:                            veloConfig.addProperty(key, targetValue);
484:                        } else {
485:                            veloConfig.addProperty(key, value);
486:                        }
487:
488:                        continue; // for()
489:                    }
490:
491:                    List paths = conf.getList(key, null);
492:                    if (paths == null) {
493:                        // We don't copy this into VeloProperties, because
494:                        // null value is unhealthy for the ExtendedProperties object...
495:                        continue; // for()
496:                    }
497:
498:                    Velocity.clearProperty(key);
499:
500:                    // Translate the supplied pathes given here.
501:                    // the following three different kinds of
502:                    // pathes must be translated to be webapp-relative
503:                    //
504:                    // jar:file://path-component!/entry-component
505:                    // file://path-component
506:                    // path/component
507:
508:                    for (Iterator j = paths.iterator(); j.hasNext();) {
509:                        String path = (String) j.next();
510:
511:                        log.debug("Translating " + path);
512:
513:                        if (path.startsWith(JAR_PREFIX)) {
514:                            // skip jar: -> 4 chars
515:                            if (path.substring(4).startsWith(ABSOLUTE_PREFIX)) {
516:                                // We must convert up to the jar path separator
517:                                int jarSepIndex = path.indexOf("!/");
518:
519:                                // jar:file:// -> skip 11 chars
520:                                path = (jarSepIndex < 0) ? Turbine
521:                                        .getRealPath(path.substring(11))
522:                                // Add the path after the jar path separator again to the new url.
523:                                        : (Turbine.getRealPath(path.substring(
524:                                                11, jarSepIndex)) + path
525:                                                .substring(jarSepIndex));
526:
527:                                log
528:                                        .debug("Result (absolute jar path): "
529:                                                + path);
530:                            }
531:                        } else if (path.startsWith(ABSOLUTE_PREFIX)) {
532:                            // skip file:// -> 7 chars
533:                            path = Turbine.getRealPath(path.substring(7));
534:
535:                            log.debug("Result (absolute URL Path): " + path);
536:                        }
537:                        // Test if this might be some sort of URL that we haven't encountered yet.
538:                        else if (path.indexOf("://") < 0) {
539:                            path = Turbine.getRealPath(path);
540:
541:                            log.debug("Result (normal fs reference): " + path);
542:                        }
543:
544:                        log.debug("Adding " + key + " -> " + path);
545:                        // Re-Add this property to the configuration object
546:                        veloConfig.addProperty(key, path);
547:                    }
548:                }
549:                return veloConfig;
550:            }
551:
552:            /**
553:             * Find out if a given template exists. Velocity
554:             * will do its own searching to determine whether
555:             * a template exists or not.
556:             *
557:             * @param template String template to search for
558:             * @return True if the template can be loaded by Velocity
559:             */
560:            public boolean templateExists(String template) {
561:                return Velocity.resourceExists(template);
562:            }
563:
564:            /**
565:             * Performs post-request actions (releases context
566:             * tools back to the object pool).
567:             *
568:             * @param context a Velocity Context
569:             */
570:            public void requestFinished(Context context) {
571:                if (pullModelActive) {
572:                    pullService.releaseTools(context);
573:                }
574:            }
575:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.