Source Code Cross Referenced for TemplateEngine.java in  » J2EE » Dinamica » dinamica » 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 » J2EE » Dinamica » dinamica 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        package dinamica;
0002:
0003:        import java.text.MessageFormat;
0004:        import java.util.ArrayList;
0005:        import java.util.HashMap;
0006:        import java.util.Iterator;
0007:        import java.io.PrintWriter;
0008:        import java.net.URLEncoder;
0009:        import java.sql.Types;
0010:        import javax.servlet.RequestDispatcher;
0011:        import javax.servlet.ServletContext;
0012:        import javax.servlet.http.*;
0013:        import java.util.Locale;
0014:        import electric.xml.*;
0015:
0016:        /**
0017:         * Core-level framework class: Text Generator.
0018:         * <br><br>
0019:         * Generates text output (html, xml, sql, etc) given
0020:         * a template with some special markers that will be replaced
0021:         * by data (supplied from recordsets). This class is used by the MVC mechanism of this framework
0022:         * and for general purpose text management.
0023:         * <br><br>
0024:         * This is a very powerfull class, it can generate html forms
0025:         * with its values ready to be edited, whole tables with one line
0026:         * of code, complete well written, portable SQL statements with one line of code,
0027:         * no matter how many fields or the type of each field, the statement will
0028:         * be formatted appropiately, without programmer effort.
0029:         * <br><br>
0030:         * It helps to COMPLETELY separate content from presentation, the
0031:         * templates are dynamically loaded and some labels are replaced with
0032:         * data provided by recordsets using very simple and effective logic. 
0033:         * <br><br>
0034:         * Markers are represented by:
0035:         * <li> Field Markers: ${fld:FieldName}
0036:         * <li> Default Values Markers: ${def:DefaultValueName}
0037:         * <li> Sequence Markers: ${seq:nextval@SequenceName} - ${seq:currval@SequenceName}. This markers allows cross-database sequence expressions, the generation
0038:         * of the actual SEQUENCE SQL expression is determined by context parameters in WEB.XML (sequence-nextval and sequence-currval). 
0039:         * 
0040:         * <br><br>
0041:         * As you can see, the markers distingish themselves by a prefix which
0042:         * denotes its type of marker (fld, def or seq).
0043:         * <br><br>
0044:         * Field Markers can have an additional attribute (not valid for SQL generation)
0045:         * representing the output format, using any valid Java mask for dates and numbers. 
0046:         * Example: {fld:FieldName@mask} - where "mask" would be the output format mask.<br>
0047:         * <br><br>
0048:         * Repeating blocks can also be generated and are conmmonly used for
0049:         * printing tables or filling HTML SELECT controls (ComboBox/ListBox). Example:
0050:         * <pre>
0051:         * &ltrepeat&gt
0052:         * &lttr&gt
0053:         * 		&lttd&gt${fld:col_1}&lt/td&gt
0054:         * 		&lttd>${fld:col_2}&lt/td&gt
0055:         * &lt/tr&gt
0056:         * &lt/repeat&gt
0057:         * </pre>
0058:         * 
0059:         * This can be replaced using one line of code with the data
0060:         * values of each record in a recordset, default formats are applied
0061:         * unless you specify an output format for a specific field. Default formats
0062:         * are configured in WEB.XML, as context parameters (def-format-date and def-format-double).
0063:         * <br><br>
0064:         * This class also supports two advanced features: Special markers for <b>dynamic labes</b> ${lbl:KeyName} which are replaced
0065:         * according to a pre-selected language (ES, EN, IT, etc), this allows multi-language templates, and
0066:         * also supports <b>includes</b>, the ability to dynamically include the output of another MVC transaction, which allows
0067:         * composition of pages from smaller parts, using a special marker: ${inc:ModuleName}
0068:         * <br><br>
0069:         * Please consult the How-to documentation to learn all about this class and its
0070:         * role inside the framework. 
0071:         * <br><br>
0072:         * Context parameters in WEB.XML used by this class:
0073:         * <xmp>
0074:         *	<context-param>
0075:         *		<param-name>def-format-date</param-name>
0076:         *		<param-value>dd-MM-yyyy</param-value>
0077:         *		<description>default format for dates</description>
0078:         *	</context-param>
0079:         *
0080:         *	<context-param>
0081:         *		<param-name>sequence-nextval</param-name>
0082:         *		<param-value>${seq}.NEXTVAL</param-value>
0083:         *		<description>SQL expression to obtain the next sequence value - sequence name will be ${seq}</description>
0084:         *	</context-param>
0085:         *	
0086:         *	<context-param>
0087:         *		<param-name>sequence-currval</param-name>
0088:         *		<param-value>${seq}.CURRVAL</param-value>
0089:         *		<description>SQL expression to obtain the current sequence value - sequence name will be ${seq}</description>
0090:         *	</context-param>
0091:         * </xmp>
0092:         * 
0093:         * Creation date: 18/09/2003<br>
0094:         * Last Update: 18/09/2003<br>
0095:         * (c) 2003 Martin Cordova<br>
0096:         * This code is released under the LGPL license<br>
0097:         * @author Martin Cordova
0098:         */
0099:        public class TemplateEngine {
0100:
0101:            /** template text */
0102:            private String _template = "";
0103:
0104:            /** servlet request - used to generate many default values related to the request */
0105:            private HttpServletRequest _req = null;
0106:
0107:            /** servlet context - used to read configuration from the context */
0108:            private ServletContext _ctx = null;
0109:
0110:            /** custom defined Locale used for format masks in dates and numbers */
0111:            private Locale _locale = null;
0112:
0113:            /** callback object that implements the interface IRowEvent */
0114:            private IRowEvent _rowEvent = null;
0115:
0116:            /** template encoding -if available- */
0117:            private String _encoding = null;
0118:
0119:            /**
0120:             * Set template encoding - for information purporses only
0121:             * @param encoding Canonical name of character encoding (ISO-8859-1, etc)
0122:             */
0123:            public void setEncoding(String encoding) {
0124:                _encoding = encoding;
0125:            }
0126:
0127:            /**
0128:             * Set reference to callback object that
0129:             * implements the IRowEvent interface
0130:             * @param obj Object that implements the IRowEvent interface
0131:             */
0132:            public void setRowEventObject(IRowEvent obj) {
0133:                _rowEvent = obj;
0134:            }
0135:
0136:            /**
0137:             * Set custom LOCALE for formatting
0138:             * @param l Locale object
0139:             */
0140:            public void setLocale(Locale l) throws Throwable {
0141:                _locale = l;
0142:                replaceLabels();
0143:            }
0144:
0145:            /**
0146:             * Set servlet request reference
0147:             * @param req HTTP Servlet Request object
0148:             */
0149:            public void setRequest(HttpServletRequest req) {
0150:                _req = req;
0151:            }
0152:
0153:            /**
0154:             * Servlet oriented constructor
0155:             * @param ctx Servlet Context - will be used to read context parameters.
0156:             * @param req Servlet Request - will be used to produce default values, like userid or remote_addr.
0157:             * @param template Text template with markers
0158:             * @throws Throwable
0159:             */
0160:            public TemplateEngine(ServletContext ctx, HttpServletRequest req,
0161:                    String template) {
0162:                _template = template;
0163:                _ctx = ctx;
0164:                _req = req;
0165:
0166:                //patch june-28-2004 -avoid unnecessary replace calls for repeat sections
0167:                try {
0168:                    replaceDefaultValues();
0169:                    if (_req != null && _ctx != null) {
0170:                        replaceSessionAttributes();
0171:                        replaceRequestAttributes();
0172:                    }
0173:                } catch (Throwable e) {
0174:                }
0175:
0176:            }
0177:
0178:            /**
0179:             * Generates SQL using the recordset values from the current record,
0180:             * substitutes the field markers with properly formatted values. Saves a lot
0181:             * of work with only one line of code. This method is smart enough as to generate
0182:             * well formatted values for Strings and portable formats for dates and timestamps,
0183:             * using the date/timestamp canonical syntax. Also special characters like single quote (') in
0184:             * Strings will be correctly escaped to avoid SQL syntax errors or SQL injection attacks.
0185:             * <br><br>
0186:             * This object must be created using a SQL template containing markers like ${fld:FieldName}, ${def:date} or ${seq:nextval@SeqName}
0187:             * @param rs Recordset containing at least one record, the record position must be valid
0188:             * @return Well formatted SQL with all the markers replaced by the corresponding values (only fld, def and seq markers are considered, no format masks allowed) 
0189:             * @throws Throwable
0190:             */
0191:            @SuppressWarnings("unchecked")
0192:            public String getSql(Recordset rs) throws Throwable {
0193:
0194:                try {
0195:
0196:                    //patch 2007-07-17 replace special marker for security schema ${schema}
0197:                    //in any SQL template that may contain it
0198:                    if (_ctx != null) {
0199:                        if (_template.indexOf("${schema}") > 0) {
0200:                            String schema = _ctx
0201:                                    .getInitParameter("security-schema");
0202:                            if (schema == null)
0203:                                schema = "";
0204:                            else if (!schema.endsWith(".")
0205:                                    && !schema.equals(""))
0206:                                schema = schema + ".";
0207:                            _template = StringUtil.replace(_template,
0208:                                    "${schema}", schema);
0209:                        }
0210:                    }
0211:                    //end patch
0212:
0213:                    if (rs != null) {
0214:                        /* get recordset metadata */
0215:                        HashMap<String, RecordsetField> flds = rs.getFields();
0216:
0217:                        /* for each field try to replace value */
0218:                        Iterator i = flds.values().iterator();
0219:                        while (i.hasNext()) {
0220:
0221:                            RecordsetField f = (RecordsetField) i.next();
0222:                            String fname = f.getName();
0223:                            Object value = rs.getValue(fname);
0224:                            String marker = "${fld:" + fname + "}";
0225:
0226:                            if (value == null) {
0227:                                _template = StringUtil.replace(_template,
0228:                                        marker, "NULL");
0229:                            } else {
0230:                                switch (f.getType()) {
0231:                                case Types.VARCHAR:
0232:                                case Types.CHAR:
0233:                                case Types.LONGVARCHAR:
0234:                                    String v = (String) value;
0235:                                    v = StringUtil.replace(v, "'", "''");
0236:                                    _template = StringUtil.replace(_template,
0237:                                            marker, "'" + v + "'");
0238:                                    break;
0239:
0240:                                case Types.DATE:
0241:                                    java.util.Date d = (java.util.Date) value;
0242:                                    _template = StringUtil.replace(_template,
0243:                                            marker, "{d '"
0244:                                                    + StringUtil.formatDate(d,
0245:                                                            "yyyy-MM-dd")
0246:                                                    + "'}");
0247:                                    break;
0248:
0249:                                case Types.TIMESTAMP:
0250:                                    java.util.Date d1 = (java.util.Date) value;
0251:                                    _template = StringUtil
0252:                                            .replace(
0253:                                                    _template,
0254:                                                    marker,
0255:                                                    "{ts '"
0256:                                                            + StringUtil
0257:                                                                    .formatDate(
0258:                                                                            d1,
0259:                                                                            "yyyy-MM-dd HH:mm:ss:SSS")
0260:                                                            + "'}");
0261:                                    break;
0262:
0263:                                default:
0264:                                    String n = dinamica.StringUtil
0265:                                            .formatNumber(value, "#.######");
0266:                                    n = dinamica.StringUtil
0267:                                            .replace(n, ",", ".");
0268:                                    _template = StringUtil.replace(_template,
0269:                                            marker, n);
0270:                                    break;
0271:
0272:                                }
0273:                            }
0274:
0275:                        }
0276:                    }
0277:
0278:                    /* replace default values */
0279:                    if (_req != null)
0280:                        replaceDefaultValues();
0281:
0282:                    /* replace SEQUENCE and request/session markers */
0283:                    if (_ctx != null && _req != null) {
0284:                        replaceRequestAttributes();
0285:                        replaceSessionAttributes();
0286:                        replaceLabels();
0287:
0288:                        ArrayList<Marker> seqs = getMarkers("seq");
0289:
0290:                        /* for each field marker set value */
0291:                        Iterator<Marker> is = seqs.iterator();
0292:                        while (is.hasNext()) {
0293:                            /* get next marker */
0294:                            Marker m = (Marker) is.next();
0295:                            String seqType = m.getName(); //sequence mode (nextval|currval)
0296:                            String seqName = m.getExtraInfo(); //sequence object name
0297:                            String marker = "${seq:" + seqType + "@" + seqName
0298:                                    + "}";
0299:
0300:                            /* get sequence configuration from context */
0301:                            String seqConfigParam = "sequence-" + seqType;
0302:                            String seqExpr = _ctx
0303:                                    .getInitParameter(seqConfigParam);
0304:
0305:                            /* throw error if config not found */
0306:                            if (seqExpr == null || seqExpr.equals("")) {
0307:                                String args[] = { marker };
0308:                                String msg = Errors.SEQUENCE_BAD_CONFIGURATION;
0309:                                msg = MessageFormat
0310:                                        .format(msg, (Object[]) args);
0311:                                throw new Throwable(msg);
0312:                            }
0313:
0314:                            /* replace sequence expression */
0315:                            String value = "";
0316:
0317:                            //patch for Resin 3.0.6 - Feb26-2004
0318:                            if (seqExpr.indexOf("${seq}") < 0)
0319:                                value = StringUtil.replace(seqExpr, "$[seq]",
0320:                                        seqName);
0321:                            else
0322:                                value = StringUtil.replace(seqExpr, "${seq}",
0323:                                        seqName);
0324:                            //end patch
0325:
0326:                            _template = StringUtil.replace(_template, marker,
0327:                                    value);
0328:
0329:                        }
0330:                    }
0331:
0332:                    return _template;
0333:                } catch (Throwable e) {
0334:                    String msg = "[TemplateEngine].\n Template:" + _template
0335:                            + "\n";
0336:                    String data = "";
0337:                    if (rs != null) {
0338:                        data = rs.toString();
0339:                        System.err.println(msg + data);
0340:                    }
0341:                    throw e;
0342:                }
0343:
0344:            }
0345:
0346:            /**
0347:             * Replace default values present in the template, default values
0348:             * are special markers expressed in the form: ${def:valueName}<br>
0349:             * Implemented defaults are:<br>
0350:             * <li>${def:user} - HttpServletRequest.getPrincipal().getUserName(). If the user is not authenticated then returns an empty string ""
0351:             * <li>${def:date} - yyyy-MM-dd
0352:             * <li>${def:time} - HH:mm:ss
0353:             * <li>${def:timestamp} - yyyy-MM-dd HH:mm:ss:SSS
0354:             * <li>${def:host} - HttpServletRequest.getServerName()
0355:             * <li>${def:context} - HttpServletRequest.getContextPath()
0356:             * <li>${def:remoteaddr} - HttpServletRequest.getRemoteAddr()
0357:             * <li>${def:uri} - HttpServletRequest.getRequestURI()
0358:             * <li>${def:dateDMY} - dd-MM-yyyy
0359:             * <li>${def:dateMDY} - MM-dd-yyyy
0360:             * <li>${def:actionroot} - action parent path
0361:             * <li>${def:httpserver} - protocol://hostname:port
0362:             * <br>
0363:             * All values extracted from HttpServletRequest will be replaced
0364:             * by an empty string "" if the request object is null. Use the method
0365:             * setRequest() to set the request object or the special constructor
0366:             * TemplateEngine(ServletContext ctx, HttpServletRequest req, String t) if you want to set
0367:             * the request object.
0368:             * <br>
0369:             * Default values can be used in every kind of template, SQL, HTML, XML, etc.
0370:             */
0371:            public void replaceDefaultValues() throws Throwable {
0372:
0373:                //patch june-22-2004 don't waste time
0374:                if (_template.indexOf("${def:") < 0)
0375:                    return;
0376:
0377:                String markers[] = { "${def:user}", "${def:date}",
0378:                        "${def:time}", "${def:timestamp}", "${def:host}",
0379:                        "${def:context}", "${def:remoteaddr}", "${def:uri}",
0380:                        "${def:dateDMY}", "${def:dateMDY}",
0381:                        "${def:actionroot}", "${def:httpserver}",
0382:                        "${def:session}" };
0383:
0384:                String values[] = new String[markers.length];
0385:
0386:                String userid = null;
0387:                if (_req != null)
0388:                    userid = _req.getRemoteUser();
0389:                if (userid == null)
0390:                    userid = "";
0391:
0392:                java.util.Date d = new java.util.Date();
0393:                values[0] = userid;
0394:                values[1] = StringUtil.formatDate(d, "yyyy-MM-dd");
0395:                values[2] = StringUtil.formatDate(d, "HH:mm:ss");
0396:                values[3] = StringUtil.formatDate(d, "yyyy-MM-dd HH:mm:ss:SSS");
0397:
0398:                if (_req != null)
0399:                    values[4] = _req.getServerName();
0400:                else
0401:                    values[4] = "";
0402:
0403:                if (_req != null)
0404:                    values[5] = _req.getContextPath();
0405:                else
0406:                    values[5] = "";
0407:
0408:                if (_req != null)
0409:                    values[6] = _req.getRemoteAddr();
0410:                else
0411:                    values[6] = "";
0412:
0413:                if (_req != null)
0414:                    values[7] = _req.getRequestURI();
0415:                else
0416:                    values[7] = "";
0417:
0418:                values[8] = StringUtil.formatDate(d, "dd-MM-yyyy");
0419:                values[9] = StringUtil.formatDate(d, "MM-dd-yyyy");
0420:
0421:                if (_req != null) {
0422:                    String path = (String) _req
0423:                            .getAttribute("dinamica.action.path");
0424:                    path = path.substring(0, path.lastIndexOf("/"));
0425:                    values[10] = path;
0426:                } else
0427:                    values[10] = "";
0428:
0429:                if (_req != null) {
0430:                    String http = "http://";
0431:                    if (_req.isSecure())
0432:                        http = "https://";
0433:                    http = http + _req.getServerName() + ":"
0434:                            + _req.getServerPort();
0435:                    values[11] = http;
0436:                } else
0437:                    values[11] = "";
0438:
0439:                if (_req != null) {
0440:                    values[12] = _req.getSession(true).getId();
0441:                } else
0442:                    values[12] = "";
0443:
0444:                for (int i = 0; i < markers.length; i++) {
0445:                    _template = StringUtil.replace(_template, markers[i],
0446:                            values[i]);
0447:                }
0448:
0449:            }
0450:
0451:            /**
0452:             * Return current state of the internal template
0453:             */
0454:            public String toString() {
0455:                return _template;
0456:            }
0457:
0458:            /**
0459:             * Returns a list of markers of a given type
0460:             * @param prefix The type of marker (fld, lbl, inc, seq)
0461:             * @return ArrayList containing Marker objects
0462:             * @throws Throwable
0463:             */
0464:            public ArrayList<Marker> getMarkers(String prefix) throws Throwable {
0465:
0466:                /* test precondition */
0467:                if (prefix.length() != 3) {
0468:                    String args[] = { prefix };
0469:                    String msg = Errors.INVALID_PREFIX;
0470:                    msg = MessageFormat.format(msg, (Object[]) args);
0471:                    throw new Throwable(msg);
0472:                }
0473:
0474:                int pos = 0;
0475:                ArrayList<Marker> l = new ArrayList<Marker>();
0476:
0477:                /* search markers */
0478:                while (pos >= 0) {
0479:                    int pos1 = 0;
0480:                    int pos2 = 0;
0481:                    int newPos = 0;
0482:
0483:                    /* find start of marker */
0484:                    pos1 = _template.indexOf("${" + prefix + ":", pos);
0485:                    if (pos1 >= 0) {
0486:
0487:                        /* find end of marker */
0488:                        newPos = pos1 + 6;
0489:                        pos2 = _template.indexOf("}", newPos);
0490:
0491:                        if (pos2 > 0) {
0492:
0493:                            /* get marker string */
0494:                            String fld = _template.substring(newPos, pos2);
0495:                            Marker m = new Marker(fld, null, pos1, pos2);
0496:
0497:                            /* search for etra attribute (format or sequence name) */
0498:                            int pos3 = fld.indexOf("@");
0499:                            if (pos3 > 0) {
0500:
0501:                                String name = fld.substring(0, pos3);
0502:                                String extraInfo = fld.substring(pos3 + 1, fld
0503:                                        .length());
0504:
0505:                                if ((name.indexOf(" ") >= 0)
0506:                                        || (name.indexOf("\r") >= 0)
0507:                                        || (name.indexOf("\n") >= 0)
0508:                                        || (name.indexOf('\t') >= 0)) {
0509:                                    String args[] = { name };
0510:                                    String msg = Errors.INVALID_MARKER;
0511:                                    msg = MessageFormat.format(msg,
0512:                                            (Object[]) args);
0513:                                    throw new Throwable(msg);
0514:                                }
0515:
0516:                                m.setName(name);
0517:                                m.setExtraInfo(extraInfo);
0518:                            }
0519:
0520:                            l.add(m);
0521:                        } else {
0522:                            throw new Throwable(Errors.MARKER_UNCLOSED);
0523:                        }
0524:                        pos = pos2 + 1;
0525:                    } else {
0526:                        pos = -1;
0527:                    }
0528:                }
0529:
0530:                return l;
0531:
0532:            }
0533:
0534:            /**
0535:             * Replace all possible field markers with corresponding
0536:             * recordset field values from current record. This method
0537:             * is mainly used to populate forms
0538:             * @param rs Recordset with a valid record position
0539:             * @param nullValueExpr The string to represent null values ("" or &ampnbsp;)
0540:             * @throws Throwable
0541:             */
0542:            public void replace(Recordset rs, String nullValueExpr)
0543:                    throws Throwable {
0544:
0545:                /* parse the template and create list of field markers */
0546:                ArrayList<Marker> flds = getMarkers("fld");
0547:
0548:                /* call internal replace method */
0549:                replace(rs, nullValueExpr, flds);
0550:
0551:            }
0552:
0553:            /**
0554:             * Navigate all the recordset and replace the
0555:             * values of each record. This method is used to produce
0556:             * tables or fill controls like ComboBoxes or ListBoxes. It is
0557:             * suitable for any section of the template that must be repeated
0558:             * as many times as records are in the recordset 
0559:             *
0560:             * @param rs Recordset
0561:             * @param nullValueExpr The string to represent null values ("" or &ampnbsp;) - when generating html tables it should be &ampnbsp;
0562:             * @param RepeatSectionTag A custom tag that encloses the repeatable section
0563:             * @throws Throwable
0564:             */
0565:            @SuppressWarnings("unchecked")
0566:            public void replace(Recordset rs, String nullValueExpr,
0567:                    String repeatSectionTag) throws Throwable {
0568:
0569:                dinamica.parser.FastTemplateEngine fte = new dinamica.parser.FastTemplateEngine();
0570:
0571:                String section = null;
0572:                String repeatTemplate = null;
0573:                int pos1 = 0;
0574:                int pos2 = 0;
0575:
0576:                String tagStart = "<" + repeatSectionTag + ">";
0577:                String tagEnd = "</" + repeatSectionTag + ">";
0578:
0579:                /* find start of repeat section */
0580:                pos1 = _template.indexOf(tagStart);
0581:                if (pos1 >= 0) {
0582:
0583:                    /* find end of repeat section */
0584:                    int newPos = pos1 + tagStart.length();
0585:                    pos2 = _template.indexOf(tagEnd, newPos);
0586:
0587:                    if (pos2 > 0) {
0588:                        /* get section string */
0589:                        section = _template.substring(pos1, pos2
0590:                                + tagEnd.length());
0591:                        repeatTemplate = _template.substring(newPos, pos2);
0592:
0593:                        /* buffer to contain generated text */
0594:                        StringBuilder buf = new StringBuilder();
0595:
0596:                        /* navigate all recordset */
0597:                        if (rs.getRecordCount() > 0) {
0598:
0599:                            // fast template engine
0600:                            fte.setTemplate(repeatTemplate);
0601:                            ArrayList<dinamica.parser.Marker> markers = fte
0602:                                    .getMarkers();
0603:
0604:                            // rewind recordset
0605:                            rs.top();
0606:
0607:                            /* for each record */
0608:                            while (rs.next()) {
0609:
0610:                                setValues(fte, markers, rs, nullValueExpr);
0611:
0612:                                // get row
0613:                                String row = fte.toString();
0614:
0615:                                /* row event available? */
0616:                                if (_rowEvent != null) {
0617:                                    row = _rowEvent.onNewRow(rs, row);
0618:                                }
0619:
0620:                                // append text
0621:                                buf.append(row);
0622:
0623:                            }
0624:                            _template = StringUtil.replace(_template, section,
0625:                                    buf.toString());
0626:                        } else {
0627:                            _template = StringUtil.replace(_template, section,
0628:                                    "");
0629:                        }
0630:
0631:                    } else {
0632:                        String args[] = { repeatSectionTag };
0633:                        String msg = Errors.REPEAT_TAG_NOT_CLOSED;
0634:                        msg = MessageFormat.format(msg, (Object[]) args);
0635:                        throw new Throwable(msg);
0636:                    }
0637:
0638:                } else {
0639:                    String args[] = { repeatSectionTag };
0640:                    String msg = Errors.REPEAT_TAG_NOT_FOUND;
0641:                    msg = MessageFormat.format(msg, (Object[]) args);
0642:                    throw new Throwable(msg);
0643:                }
0644:
0645:            }
0646:
0647:            /**
0648:             * Internal method that factorizes most of the code
0649:             * that is common to all the overloaders
0650:             * @param rs Recordset
0651:             * @param nullValueExpr The string to represent null values ("" or &ampnbsp;) - when generating html tables it should be &ampnbsp;
0652:             * @param markers ArrayList containing the field markers
0653:             * @throws Throwable
0654:             */
0655:            @SuppressWarnings("unchecked")
0656:            void replace(Recordset rs, String nullValueExpr, ArrayList markers)
0657:                    throws Throwable {
0658:
0659:                String strValue = null;
0660:                Object value = null;
0661:                String toReplace = null;
0662:
0663:                /* get recordset fields */
0664:                HashMap rsFlds = rs.getFields();
0665:
0666:                /* parse the template and create list of field markers */
0667:                ArrayList flds = markers;
0668:
0669:                /* for each field marker set value */
0670:                Iterator i = flds.iterator();
0671:                while (i.hasNext()) {
0672:
0673:                    String formatPluginName = null;
0674:                    IFormatPlugin fmtObj = null;
0675:                    FormatPluginParser fpp = null;
0676:
0677:                    /* get next marker */
0678:                    Marker m = (Marker) i.next();
0679:                    String fName = m.getName();
0680:                    String fFormat = m.getExtraInfo();
0681:
0682:                    /* determine if it is an special field (rowNumber/rowIndex) otherwise if the field exists */
0683:                    boolean found = true;
0684:                    boolean fakeField = false;
0685:                    if (!fName.equals("_rowNumber")
0686:                            && !fName.equals("_rowIndex")) {
0687:                        if (!rsFlds.containsKey(fName))
0688:                            found = false;
0689:                    } else {
0690:                        fakeField = true;
0691:                    }
0692:
0693:                    /* recordset contains this field? */
0694:                    if (found) {
0695:
0696:                        String defDateFmt = null;
0697:
0698:                        /* read default date format */
0699:                        if (_ctx != null)
0700:                            defDateFmt = _ctx
0701:                                    .getInitParameter("def-format-date");
0702:
0703:                        if (defDateFmt == null || defDateFmt.equals(""))
0704:                            defDateFmt = "dd-MM-yyyy";
0705:
0706:                        /* rebuild marker to replace by searched and replaced by corresponding value */
0707:                        if (fFormat != null) {
0708:                            toReplace = "${fld:" + fName + "@" + fFormat + "}";
0709:
0710:                            //PATCH 2005-05-23 - get plugin name if available
0711:                            if (fFormat.startsWith("class:")) {
0712:                                formatPluginName = fFormat.substring(6);
0713:                                fpp = new FormatPluginParser(formatPluginName);
0714:                                fmtObj = (IFormatPlugin) Thread.currentThread()
0715:                                        .getContextClassLoader().loadClass(
0716:                                                fpp.getName()).newInstance();
0717:                            }
0718:                        } else
0719:                            toReplace = "${fld:" + fName + "}";
0720:
0721:                        /* get field value */
0722:                        value = rs.getValue(fName);
0723:
0724:                        //custom format??
0725:                        if (fmtObj != null) {
0726:                            strValue = fmtObj.format(fName, rs, _locale, fpp
0727:                                    .getArgs());
0728:                        } else {
0729:
0730:                            /* apply appropiate null representation */
0731:                            if (value == null) {
0732:                                strValue = nullValueExpr;
0733:                            } else {
0734:
0735:                                /* get field info */
0736:                                RecordsetField f = null;
0737:                                if (!fakeField)
0738:                                    f = (RecordsetField) rsFlds.get(fName);
0739:                                else
0740:                                    f = new RecordsetField(fName, "INTEGER",
0741:                                            Types.INTEGER);
0742:
0743:                                /* format value according to data type*/
0744:                                if (f.getType() != Types.DATE
0745:                                        && f.getType() != Types.TIMESTAMP) {
0746:                                    /* format defined? */
0747:                                    if (fFormat == null) {
0748:                                        strValue = String.valueOf(value);
0749:                                    } else {
0750:                                        //is a string data type?
0751:                                        if (f.getType() == Types.VARCHAR
0752:                                                || f.getType() == Types.CHAR
0753:                                                || f.getType() == Types.CLOB
0754:                                                || f.getType() == Types.LONGVARCHAR) {
0755:                                            if (fFormat.equals("xml")) {
0756:                                                //encode special characters for xml/html output
0757:                                                strValue = encodeXML((String) value);
0758:                                            } else if (fFormat.equals("html")) {
0759:                                                //encode special characters for xml/html output
0760:                                                strValue = encodeHTML((String) value);
0761:                                            } else if (fFormat.equals("url")) {
0762:                                                //encode special characters for xml/html output
0763:                                                strValue = URLEncoder
0764:                                                        .encode((String) value,
0765:                                                                "UTF-8");
0766:                                            } else if (fFormat.equals("js")) {
0767:                                                //encode special characters for xml/html output
0768:                                                strValue = encodeJS((String) value);
0769:                                            } else {
0770:                                                throw new Throwable(
0771:                                                        "Invalid format mask for the field:"
0772:                                                                + fName);
0773:                                            }
0774:
0775:                                        }
0776:                                        // it is a numeric data type
0777:                                        else {
0778:
0779:                                            if (_locale == null)
0780:                                                strValue = StringUtil
0781:                                                        .formatNumber(value,
0782:                                                                fFormat);
0783:                                            else
0784:                                                strValue = StringUtil
0785:                                                        .formatNumber(value,
0786:                                                                fFormat,
0787:                                                                _locale);
0788:
0789:                                        }
0790:                                    }
0791:                                } else {
0792:                                    /* apply default or custom date format? */
0793:                                    if (fFormat == null)
0794:                                        fFormat = defDateFmt;
0795:                                    if (_locale == null)
0796:                                        strValue = StringUtil
0797:                                                .formatDate(
0798:                                                        (java.util.Date) value,
0799:                                                        fFormat);
0800:                                    else
0801:                                        strValue = StringUtil.formatDate(
0802:                                                (java.util.Date) value,
0803:                                                fFormat, _locale);
0804:                                }
0805:
0806:                            }
0807:
0808:                        }
0809:
0810:                        /* replace marker with value */
0811:                        _template = StringUtil.replace(_template, toReplace,
0812:                                strValue);
0813:
0814:                    }
0815:
0816:                }
0817:
0818:            }
0819:
0820:            /**
0821:             * Replace dynamic labels ${lbl:Name} using the
0822:             * session locale, which must be indicated using the method
0823:             * setLocale, otherwise the language code
0824:             * specified in the context-attribute <b>def-language</b> in WEB.XML will be used
0825:             * to select the default locale. If none has been properly configured
0826:             * or the label does not exist for the selected Locale, then
0827:             * an exception will be triggered. This mechanism uses the label
0828:             * configuration file stored in /WEB-INF/labels.xml. Please check
0829:             * the documentation to learn the structure of this file.
0830:             * Place the appropiate markers and make sure the labels.xml file is properly configured.
0831:             * In order to use this method, the TemplateEngine must have access to
0832:             * the ServletContext, so use the appropiate constructor. If there is no
0833:             * valid reference to the ServletContext, then this method will trigger
0834:             * an error
0835:             * @throws Throwable
0836:             */
0837:            public void replaceLabels() throws Throwable {
0838:
0839:                if (_ctx == null)
0840:                    throw new Throwable(
0841:                            "Servlet Context is null - this method can't work without a ServletContext.");
0842:
0843:                //patch june-22-2004 don't waste time
0844:                if (_template.indexOf("${lbl:") < 0)
0845:                    return;
0846:
0847:                /* parse the template and create list of label markers */
0848:                ArrayList<Marker> flds = getMarkers("lbl");
0849:
0850:                /* load labels.xml file */
0851:                String xmlData = StringUtil.getResource(_ctx,
0852:                        "/WEB-INF/labels.xml");
0853:
0854:                /* parse document */
0855:                Document doc = new Document(xmlData);
0856:                Element root = doc.getRoot();
0857:
0858:                /* identify locale to be used */
0859:                String language = null;
0860:                if (_locale == null)
0861:                    language = _ctx.getInitParameter("def-language");
0862:                else
0863:                    language = _locale.getLanguage();
0864:
0865:                if (language == null || language.equals(""))
0866:                    throw new Throwable(
0867:                            "Language not defined (Locale or default language may be null)");
0868:
0869:                for (int i = 0; i < flds.size(); i++) {
0870:                    Marker m = (Marker) flds.get(i);
0871:                    String name = m.getName();
0872:                    String label = "${" + "lbl:" + name + "}";
0873:                    _template = StringUtil.replace(_template, label, getLabel(
0874:                            name, root, language));
0875:                }
0876:
0877:            }
0878:
0879:            /**
0880:             * Lookup a dynamic label value given the language code and the label ID
0881:             * @param labelName Label ID
0882:             * @param root The root element of the labels.xml tree
0883:             * @param language The ISO language code (es, en, it, etc.)
0884:             * @return The label translation
0885:             * @throws Throwable if the label ID or the language code are not valid 
0886:             */
0887:            String getLabel(String labelName, Element root, String language)
0888:                    throws Throwable {
0889:
0890:                /* find label */
0891:                Element label = root.getElement(new XPath("label[@id='"
0892:                        + labelName + "']"));
0893:                if (label == null)
0894:                    throw new Throwable("Label not found: " + labelName);
0895:
0896:                /* find translation for language code */
0897:                Element translation = label.getElement(new XPath(
0898:                        "value[@language='" + language + "']"));
0899:                if (translation == null)
0900:                    throw new Throwable(
0901:                            "Label translation not found for this language code: "
0902:                                    + language);
0903:
0904:                return translation.getString();
0905:
0906:            }
0907:
0908:            /**
0909:             * Split template into segments stored into an array.
0910:             * A segment may be a printable text or an INCLUDE directive
0911:             * to include the content of another resource from the same context
0912:             * @return ArrayList containing TemplateSegment objects
0913:             * @throws Throwable
0914:             */
0915:            ArrayList<TemplateSegment> getSegments() throws Throwable {
0916:
0917:                ArrayList<TemplateSegment> s = new ArrayList<TemplateSegment>();
0918:
0919:                /* get include markers */
0920:                ArrayList<Marker> l = getMarkers("inc");
0921:
0922:                if (l.size() > 0) {
0923:                    int lastPos = 0;
0924:                    for (int i = 0; i < l.size(); i++) {
0925:                        /* create segment */
0926:                        Marker m = (Marker) l.get(i);
0927:                        TemplateSegment seg1 = new TemplateSegment();
0928:                        seg1.segmentType = "data";
0929:                        seg1.segmentData = _template.substring(lastPos, m
0930:                                .getPos1());
0931:
0932:                        TemplateSegment seg2 = new TemplateSegment();
0933:                        seg2.segmentType = "inc";
0934:                        seg2.segmentData = m.getName();
0935:
0936:                        lastPos = m.getPos2() + 1;
0937:
0938:                        s.add(seg1);
0939:                        s.add(seg2);
0940:
0941:                    }
0942:                    TemplateSegment seg1 = new TemplateSegment();
0943:                    seg1.segmentType = "data";
0944:                    seg1.segmentData = _template.substring(lastPos);
0945:                    s.add(seg1);
0946:
0947:                } else {
0948:
0949:                    TemplateSegment seg = new TemplateSegment();
0950:                    seg.segmentType = "data";
0951:                    seg.segmentData = _template;
0952:                    s.add(seg);
0953:                }
0954:
0955:                return s;
0956:            }
0957:
0958:            /**
0959:             * Print template and process any INCLUDE directive
0960:             * present into the template; in order to do this the
0961:             * class required a reference to the ServletContext, Request
0962:             * and Response, otherwise it can't dispatch to include another servlets.
0963:             * No writer must be obtained from the Servlet response object
0964:             * prior to calling this method, because this method will call getWriter() from
0965:             * the passed Response object.<br>
0966:             * <br>
0967:             * <b>NOTE:</b> default values and dynamic labels will be automatically
0968:             * replaced by this method. This is the preferred way to print a template
0969:             * to make sure everything is being replaced, the caller is only responsable
0970:             * for setting the appropiate response headers.
0971:             * @param res HttpServletResponse
0972:             * @throws Throwable if the ServletContext reference is null
0973:             */
0974:            public void print(HttpServletResponse res) throws Throwable {
0975:
0976:                if (_ctx == null)
0977:                    throw new Throwable(
0978:                            "ServletContext is null - can't print template because the request dispatcher must be obtained from the ServletContext.");
0979:
0980:                replaceDefaultValues();
0981:                replaceLabels();
0982:                replaceRequestAttributes();
0983:                replaceSessionAttributes();
0984:
0985:                PrintWriter pw = res.getWriter();
0986:
0987:                // patch 28-june-2004 - set content length if no includes are used in this template
0988:                if (_template.indexOf("${inc:") >= 0) {
0989:                    ArrayList<TemplateSegment> s = getSegments();
0990:                    for (int i = 0; i < s.size(); i++) {
0991:                        TemplateSegment t = (TemplateSegment) s.get(i);
0992:                        if (t.segmentType.equals("inc")) {
0993:                            try {
0994:                                RequestDispatcher rd = _ctx
0995:                                        .getRequestDispatcher(t.segmentData);
0996:                                rd.include(_req, res);
0997:                            } catch (Throwable e) {
0998:                                String msg = "INCLUDE Error (" + t.segmentData
0999:                                        + ") - " + e.getMessage();
1000:                                throw new Throwable(msg);
1001:                            }
1002:                        } else {
1003:                            pw.print(t.segmentData);
1004:                        }
1005:                    }
1006:                } else {
1007:                    //PATCH 2005-02-23 - encoding support
1008:                    byte body[] = null;
1009:                    if (_encoding != null)
1010:                        body = _template.getBytes(_encoding);
1011:                    else
1012:                        body = _template.getBytes();
1013:
1014:                    res.setContentLength(body.length);
1015:                    pw.print(_template);
1016:                }
1017:
1018:            }
1019:
1020:            /**
1021:             * HTML Control utility method.<br>
1022:             * Select combobox item for single select combobox. This method
1023:             * will insert the word "selected" in the appropiate option element
1024:             * from the corresponding select html control.<br>
1025:             * <b>NOTE:</b> All html keywords related to the control must be
1026:             * in lower case, including attributes and tag names. Name and Value lookup
1027:             * is case sensitive!
1028:             * @param controlName HTML control name attribute
1029:             * @param value Option value to search for
1030:             * @throws Throwable if can't find control or its closing tag
1031:             */
1032:            public void setComboValue(String controlName, String value)
1033:                    throws Throwable {
1034:                int pos1 = 0;
1035:                int pos2 = 0;
1036:                String combo = "";
1037:
1038:                /* define control to find */
1039:                String find = "<select name=\"" + controlName + "\"";
1040:
1041:                /* find it */
1042:                pos1 = _template.indexOf(find);
1043:
1044:                /* found? */
1045:                if (pos1 >= 0) {
1046:                    /* extract segment  from template */
1047:                    pos2 = _template.indexOf("</select>", pos1);
1048:                    if (pos2 > 0) {
1049:
1050:                        /* extract */
1051:                        int newpos2 = pos2 + "</select>".length();
1052:                        combo = _template.substring(pos1, newpos2);
1053:
1054:                        /* set item=selected if found */
1055:                        find = "<option value=\"" + value + "\"";
1056:                        String newItem = find + " selected ";
1057:                        String temp = StringUtil.replace(combo, find, newItem);
1058:
1059:                        /* replace into template */
1060:                        _template = StringUtil.replace(_template, combo, temp);
1061:
1062:                    } else {
1063:                        throw new Throwable(
1064:                                "Can't find closing tag for this HTML control: "
1065:                                        + controlName);
1066:                    }
1067:                } else {
1068:                    throw new Throwable("HTML control not found: "
1069:                            + controlName);
1070:                }
1071:
1072:            }
1073:
1074:            /**
1075:             * HTML Control utility method.<br>
1076:             * Set combobox values for multiple items using a recordset
1077:             * to lookup the values from a field and set the corresponding option items
1078:             * in the select control. All records from the recordset are used.
1079:             * @param controlName Name of the html select control which is also the name
1080:             * of the field name to use from the Recordset 
1081:             * @param rs
1082:             * @throws Throwable
1083:             */
1084:            public void setComboValue(String controlName, Recordset rs)
1085:                    throws Throwable {
1086:                if (rs.getRecordCount() == 0)
1087:                    return;
1088:
1089:                rs.top();
1090:                while (rs.next()) {
1091:                    /* reuse setComboValue method */
1092:                    String value = String.valueOf(rs.getValue(controlName));
1093:                    setComboValue(controlName, value);
1094:                }
1095:            }
1096:
1097:            /**
1098:             * HTML Control utility method.<br>
1099:             * Select RadioButton control from a group of controls
1100:             * using a value to match the appropiate control
1101:             * <b>NOTE:</b> All html keywords related to the control must be
1102:             * in lower case, including attributes and tag names. Name and Value lookup
1103:             * is case sensitive!
1104:             * @param controlName HTML control name attribute
1105:             * @param value Value to search for
1106:             * @throws Throwable if can't find control
1107:             */
1108:            public void setRadioButton(String controlName, String value)
1109:                    throws Throwable {
1110:
1111:                int pos1 = 0;
1112:                int pos2 = 0;
1113:                String ctrl = "";
1114:                int flag = 0;
1115:                int pos = 0;
1116:
1117:                while (flag >= 0) {
1118:
1119:                    /* define control to find */
1120:                    String find = "<input";
1121:
1122:                    /* find it */
1123:                    pos1 = _template.indexOf(find, pos);
1124:
1125:                    /* found? */
1126:                    if (pos1 >= 0) {
1127:                        flag = 1;
1128:
1129:                        /* extract segment  from template */
1130:                        pos2 = _template.indexOf(">", pos1);
1131:                        if (pos2 > 0) {
1132:
1133:                            /* extract */
1134:                            int newpos2 = pos2 + ">".length();
1135:                            ctrl = _template.substring(pos1, newpos2);
1136:
1137:                            /* check to see if this is the requested control */
1138:                            find = "name=\"" + controlName + "\"";
1139:                            int newpos1 = ctrl.indexOf(find);
1140:
1141:                            /* found? this is one of the requested controls! */
1142:                            if (newpos1 >= 0) {
1143:
1144:                                /* mark this control as "selected" if its value match */
1145:                                find = "value=\"" + value + "\"";
1146:                                String newItem = find + " checked ";
1147:                                String temp = StringUtil.replace(ctrl, find,
1148:                                        newItem);
1149:
1150:                                /* replace into template */
1151:                                if (!temp.equals(ctrl)) {
1152:                                    _template = StringUtil.replace(_template,
1153:                                            ctrl, temp);
1154:                                    return;
1155:                                } else {
1156:                                    ctrl = temp;
1157:                                }
1158:
1159:                            }
1160:                            pos = pos1 + ctrl.length();
1161:                        } else {
1162:                            throw new Throwable(
1163:                                    "'input' Tag is not properly closed for this HTML control: "
1164:                                            + controlName);
1165:                        }
1166:                    } else {
1167:                        flag = -1;
1168:                    }
1169:
1170:                }
1171:
1172:            }
1173:
1174:            /**
1175:             * HTML Control utility method.<br>
1176:             * Set checkbox values for multiple items using a recordset
1177:             * to lookup the values from a field and set the corresponding checkbox items
1178:             * in the checkbox control group. All records from the recordset are used.
1179:             * @param controlName Name of the html select control which is also the name
1180:             * of the field name to use from the Recordset 
1181:             * @param rs
1182:             * @throws Throwable
1183:             */
1184:            public void setCheckbox(String controlName, Recordset rs)
1185:                    throws Throwable {
1186:                if (rs.getRecordCount() == 0)
1187:                    return;
1188:
1189:                rs.top();
1190:                while (rs.next()) {
1191:                    /* reuse setRadioButton method */
1192:                    String value = String.valueOf(rs.getValue(controlName));
1193:                    setRadioButton(controlName, value);
1194:                }
1195:            }
1196:
1197:            /**
1198:             * Change template body - if necessary, should be called before replacing any data
1199:             * because all previous changes will be lost
1200:             * @param string New template body
1201:             */
1202:            public void setTemplate(String string) {
1203:                _template = string;
1204:            }
1205:
1206:            /**
1207:             * Returns a Tag body, including the tag markers.
1208:             * This is a utility method that may be used by special
1209:             * Output modules, like Master/Detail reports that need
1210:             * to extract and later replace subsections of a template.
1211:             * @param tagName
1212:             * @return
1213:             * @throws Throwable if tagName is not present in the template
1214:             */
1215:            public String getTagBody(String tagName) throws Throwable {
1216:
1217:                int pos1 = 0;
1218:                int pos2 = 0;
1219:
1220:                String tagStart = "<" + tagName + ">";
1221:                String tagEnd = "</" + tagName + ">";
1222:
1223:                /* find start of repeat section */
1224:                pos1 = _template.indexOf(tagStart);
1225:                if (pos1 >= 0) {
1226:
1227:                    /* find end of repeat section */
1228:                    int newPos = pos1 + tagStart.length();
1229:                    pos2 = _template.indexOf(tagEnd, newPos);
1230:
1231:                    if (pos2 > 0) {
1232:                        /* extract tag body */
1233:                        return _template
1234:                                .substring(pos1, pos2 + tagEnd.length());
1235:                    } else {
1236:                        String args[] = { tagName };
1237:                        String msg = Errors.REPEAT_TAG_NOT_CLOSED;
1238:                        msg = MessageFormat.format(msg, (Object[]) args);
1239:                        throw new Throwable(msg);
1240:                    }
1241:
1242:                } else {
1243:                    String args[] = { tagName };
1244:                    String msg = Errors.REPEAT_TAG_NOT_FOUND;
1245:                    msg = MessageFormat.format(msg, (Object[]) args);
1246:                    throw new Throwable(msg);
1247:                }
1248:
1249:            }
1250:
1251:            /**
1252:             * Replace field markers representing request attribute values
1253:             * like ${req:attributeID}
1254:             * @throws Throwable
1255:             */
1256:            public void replaceRequestAttributes() throws Throwable {
1257:                if (_ctx == null)
1258:                    throw new Throwable(
1259:                            "Servlet Context is null - this method can't work without a ServletContext.");
1260:
1261:                //patch june-22-2004 don't waste time
1262:                if (_template.indexOf("${req:") < 0)
1263:                    return;
1264:
1265:                /* parse the template and create list of label markers */
1266:                ArrayList<Marker> flds = getMarkers("req");
1267:
1268:                for (int i = 0; i < flds.size(); i++) {
1269:                    Marker m = (Marker) flds.get(i);
1270:
1271:                    String name = m.getName();
1272:
1273:                    //PATCH 2005-04-15  - support for XML/URL encoding
1274:                    String fmt = m.getExtraInfo();
1275:                    if (fmt == null)
1276:                        fmt = "";
1277:                    else
1278:                        fmt = "@" + fmt;
1279:                    String label = "${" + "req:" + name + fmt + "}";
1280:
1281:                    /* PATCH 2004-12-06 - request markers were
1282:                     * being eliminated if request attribute was null, creating
1283:                     * problems for custom output modules that set request attributes
1284:                     */
1285:                    String value = (String) _req.getAttribute(name);
1286:                    if (value != null) {
1287:                        if (!fmt.equals("")) {
1288:                            if (fmt.equals("@xml"))
1289:                                value = encodeXML(value);
1290:                            else if (fmt.equals("@html"))
1291:                                value = encodeHTML(value);
1292:                            else if (fmt.equals("@js"))
1293:                                value = encodeJS(value);
1294:                            else if (fmt.equals("@url"))
1295:                                value = URLEncoder.encode(value, "UTF-8");
1296:                            else
1297:                                throw new Throwable(
1298:                                        "Invalid encoding directive for request attribute: "
1299:                                                + name);
1300:                        }
1301:                        _template = StringUtil.replace(_template, label, value);
1302:                    }
1303:                }
1304:            }
1305:
1306:            /**
1307:             * Replace field markers representing session attribute values
1308:             * like ${ses:attributeID}
1309:             * @throws Throwable
1310:             */
1311:            public void replaceSessionAttributes() throws Throwable {
1312:
1313:                if (_req == null)
1314:                    throw new Throwable(
1315:                            "Request is null - this method can't work without a Request object.");
1316:
1317:                //patch june-22-2004 don't waste time
1318:                if (_template.indexOf("${ses:") < 0)
1319:                    return;
1320:
1321:                //get session object
1322:                HttpSession session = _req.getSession(true);
1323:
1324:                /* parse the template and create list of label markers */
1325:                ArrayList<Marker> flds = getMarkers("ses");
1326:
1327:                for (int i = 0; i < flds.size(); i++) {
1328:                    Marker m = (Marker) flds.get(i);
1329:                    String name = m.getName();
1330:
1331:                    // PATCH 2005-05-25 - test existence of session attribute
1332:                    Object obj = session.getAttribute(name);
1333:
1334:                    if (obj == null)
1335:                        throw new Throwable("Cannot find Session attribute ["
1336:                                + name + "]; UserID: " + _req.getRemoteUser()
1337:                                + "; Session isNew: " + session.isNew() + "; ");
1338:
1339:                    //patch 2005-06-09 - avoid errors if attribute type is not String
1340:                    String value = String.valueOf(obj);
1341:                    String label = "${" + "ses:" + name + "}";
1342:                    _template = StringUtil.replace(_template, label, value);
1343:
1344:                }
1345:
1346:            }
1347:
1348:            /**
1349:             * Encode reserved xml characters (&amp;,&lt;,&gt;,',").<br>
1350:             * This characters will be replaced by the pre-defined entities.
1351:             * @param input String that will be processed
1352:             * @return String with all reserved characters replaced
1353:             */
1354:            public String encodeXML(String input) {
1355:                input = StringUtil.replace(input, "&", "&amp;");
1356:                input = StringUtil.replace(input, "<", "&lt;");
1357:                input = StringUtil.replace(input, ">", "&gt;");
1358:                input = StringUtil.replace(input, "'", "&apos;");
1359:                input = StringUtil.replace(input, "\"", "&quot;");
1360:
1361:                return input;
1362:            }
1363:
1364:            /**
1365:             * Encode reserved html characters (&amp;,&lt;,&gt;,',").<br>
1366:             * This characters will be replaced by the pre-defined entities.
1367:             * @param input String that will be processed
1368:             * @return String with all reserved characters replaced
1369:             */
1370:            public String encodeHTML(String input) {
1371:                input = StringUtil.replace(input, "&", "&amp;");
1372:                input = StringUtil.replace(input, "<", "&lt;");
1373:                input = StringUtil.replace(input, ">", "&gt;");
1374:                input = StringUtil.replace(input, "\"", "&quot;");
1375:
1376:                return input;
1377:            }
1378:
1379:            /**
1380:             * Encode reserved javascript characters (\,").<br>
1381:             * This characters will be replaced by the pre-defined entities.
1382:             * @param input String that will be processed
1383:             * @return String with all reserved characters replaced
1384:             */
1385:            public String encodeJS(String input) {
1386:                input = StringUtil.replace(input, "\\", "\\\\");
1387:                input = StringUtil.replace(input, "\"", "\\\"");
1388:                input = StringUtil.replace(input, "\r\n", "\\r\\n");
1389:
1390:                return input;
1391:            }
1392:
1393:            /**
1394:             * Replace any text into the template
1395:             * @param toReplace Text to be replaced
1396:             * @param newValue New value
1397:             */
1398:            public void replace(String toReplace, String newValue) {
1399:                _template = StringUtil.replace(_template, toReplace, newValue);
1400:            }
1401:
1402:            /**
1403:             * Set corresponding column values for template markers<br>
1404:             * Patch june-28-2004 - Fast parser technique
1405:             * @param fte Fast template parser (new fck package)
1406:             * @param rs Recordset positioned on a valid record
1407:             * @param nullExpression String used to represent a null value
1408:             * @throws Throwable
1409:             */
1410:            @SuppressWarnings("unchecked")
1411:            public void setValues(dinamica.parser.FastTemplateEngine fte,
1412:                    ArrayList<dinamica.parser.Marker> markers, Recordset rs,
1413:                    String nullExpression) throws Throwable {
1414:
1415:                String strValue = null;
1416:                Object value = null;
1417:
1418:                /* read default date format */
1419:                String defDateFmt = null;
1420:                if (_ctx != null)
1421:                    defDateFmt = _ctx.getInitParameter("def-format-date");
1422:                if (defDateFmt == null || defDateFmt.equals(""))
1423:                    defDateFmt = "dd-MM-yyyy";
1424:
1425:                /* get recordset fields */
1426:                HashMap<String, RecordsetField> rsFlds = rs.getFields();
1427:
1428:                /* parse the template and create list of field markers */
1429:                ArrayList<dinamica.parser.Marker> flds = markers;
1430:
1431:                /* for each field marker set value */
1432:                Iterator<dinamica.parser.Marker> i = flds.iterator();
1433:                while (i.hasNext()) {
1434:
1435:                    String formatPluginName = null;
1436:                    IFormatPlugin fmtObj = null;
1437:                    FormatPluginParser fpp = null;
1438:
1439:                    /* get next marker */
1440:                    dinamica.parser.Marker m = (dinamica.parser.Marker) i
1441:                            .next();
1442:                    String fName = m.getColumnName();
1443:                    String fFormat = m.getFormat();
1444:
1445:                    /* determine if it is an special field (rowNumber/rowIndex) otherwise if the field exists */
1446:                    boolean found = true;
1447:                    boolean fakeField = false;
1448:                    if (!fName.equals("_rowNumber")
1449:                            && !fName.equals("_rowIndex")) {
1450:                        if (!rsFlds.containsKey(fName))
1451:                            found = false;
1452:                    } else {
1453:                        fakeField = true;
1454:                    }
1455:
1456:                    /* recordset contains this field? */
1457:                    if (found) {
1458:
1459:                        if (fFormat != null) {
1460:                            //PATCH 2005-05-23 - get plugin name if available
1461:                            if (fFormat.startsWith("class:")) {
1462:                                formatPluginName = fFormat.substring(6);
1463:                                fpp = new FormatPluginParser(formatPluginName);
1464:                                fmtObj = (IFormatPlugin) Thread.currentThread()
1465:                                        .getContextClassLoader().loadClass(
1466:                                                fpp.getName()).newInstance();
1467:                            }
1468:                        }
1469:
1470:                        /* get field value */
1471:                        value = rs.getValue(fName);
1472:
1473:                        if (fmtObj != null) {
1474:                            strValue = fmtObj.format(fName, rs, _locale, fpp
1475:                                    .getArgs());
1476:                        } else {
1477:                            /* apply appropiate null representation */
1478:                            if (value == null) {
1479:                                strValue = nullExpression;
1480:                            } else {
1481:
1482:                                /* get field info */
1483:                                RecordsetField f = null;
1484:                                if (!fakeField)
1485:                                    f = (RecordsetField) rsFlds.get(fName);
1486:                                else
1487:                                    f = new RecordsetField(fName, "INTEGER",
1488:                                            Types.INTEGER);
1489:
1490:                                /* format value according to data type*/
1491:                                if (f.getType() != Types.DATE
1492:                                        && f.getType() != Types.TIMESTAMP) {
1493:                                    /* format defined? */
1494:                                    if (fFormat == null) {
1495:                                        strValue = String.valueOf(value);
1496:                                    } else {
1497:                                        //is a string data type?
1498:                                        if (f.getType() == Types.VARCHAR
1499:                                                || f.getType() == Types.CHAR
1500:                                                || f.getType() == Types.CLOB) {
1501:                                            if (fFormat.equals("xml")) {
1502:                                                //encode special characters for xml/html output
1503:                                                strValue = encodeXML((String) value);
1504:                                            } else if (fFormat.equals("html")) {
1505:                                                //encode special characters for xml/html output
1506:                                                strValue = encodeHTML((String) value);
1507:                                            } else if (fFormat.equals("url")) {
1508:                                                //encode special characters for xml/html output
1509:                                                strValue = URLEncoder
1510:                                                        .encode((String) value,
1511:                                                                "UTF-8");
1512:                                            } else {
1513:                                                throw new Throwable(
1514:                                                        "Invalid format mask for the field:"
1515:                                                                + fName);
1516:                                            }
1517:
1518:                                        }
1519:                                        // it is a numeric data type
1520:                                        else {
1521:
1522:                                            if (_locale == null)
1523:                                                strValue = StringUtil
1524:                                                        .formatNumber(value,
1525:                                                                fFormat);
1526:                                            else
1527:                                                strValue = StringUtil
1528:                                                        .formatNumber(value,
1529:                                                                fFormat,
1530:                                                                _locale);
1531:
1532:                                        }
1533:                                    }
1534:                                } else {
1535:                                    /* apply default or custom date format? */
1536:                                    if (fFormat == null)
1537:                                        fFormat = defDateFmt;
1538:                                    if (_locale == null)
1539:                                        strValue = StringUtil
1540:                                                .formatDate(
1541:                                                        (java.util.Date) value,
1542:                                                        fFormat);
1543:                                    else
1544:                                        strValue = StringUtil.formatDate(
1545:                                                (java.util.Date) value,
1546:                                                fFormat, _locale);
1547:                                }
1548:
1549:                            }
1550:
1551:                        }
1552:
1553:                        // set value
1554:                        fte.setValue(m.getKey(), strValue);
1555:
1556:                    }
1557:
1558:                }
1559:
1560:            }
1561:
1562:            /**
1563:             * Replace all markers of type ${fld:xxx} with an empty string "".<br>
1564:             * Added on Aug-30-2005 to support a new print mode="clear" in config.xml.
1565:             * @throws Throwable
1566:             */
1567:            public void clearFieldMarkers() throws Throwable {
1568:
1569:                String toReplace = null;
1570:
1571:                /* parse the template and create list of field markers */
1572:                ArrayList<Marker> flds = getMarkers("fld");
1573:
1574:                /* for each field marker set value */
1575:                Iterator<Marker> i = flds.iterator();
1576:                while (i.hasNext()) {
1577:
1578:                    /* get next marker */
1579:                    Marker m = (Marker) i.next();
1580:                    String fName = m.getName();
1581:                    String fFormat = m.getExtraInfo();
1582:
1583:                    if (fFormat != null)
1584:                        toReplace = "${fld:" + fName + "@" + fFormat + "}";
1585:                    else
1586:                        toReplace = "${fld:" + fName + "}";
1587:
1588:                    /* replace marker with value */
1589:                    _template = StringUtil.replace(_template, toReplace, "");
1590:
1591:                }
1592:
1593:            }
1594:
1595:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.