Source Code Cross Referenced for Template.java in  » Content-Management-System » contelligent » de » finix » contelligent » render » 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 » Content Management System » contelligent » de.finix.contelligent.render 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2001-2006 C:1 Financial Services GmbH
003:         *
004:         * This software is free software; you can redistribute it and/or
005:         * modify it under the terms of the GNU Lesser General Public
006:         * License Version 2.1, as published by the Free Software Foundation.
007:         *
008:         * This software is distributed in the hope that it will be useful,
009:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
010:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
011:         * Lesser General Public License for more details.
012:         *
013:         * You should have received a copy of the GNU Lesser General Public
014:         * License along with this library; if not, write to the Free Software
015:         * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
016:         */
017:
018:        package de.finix.contelligent.render;
019:
020:        import java.io.CharArrayWriter;
021:        import java.io.IOException;
022:        import java.io.Writer;
023:        import java.text.ParseException;
024:        import java.util.ArrayList;
025:        import java.util.Collection;
026:        import java.util.Collections;
027:        import java.util.HashMap;
028:        import java.util.HashSet;
029:        import java.util.Iterator;
030:        import java.util.List;
031:        import java.util.Map;
032:        import java.util.Set;
033:
034:        import javax.servlet.http.HttpServletRequest;
035:        import javax.servlet.http.HttpUtils;
036:
037:        import de.finix.contelligent.CallData;
038:        import de.finix.contelligent.Component;
039:        import de.finix.contelligent.ComponentManager;
040:        import de.finix.contelligent.ComponentNotFoundException;
041:        import de.finix.contelligent.ComponentPath;
042:        import de.finix.contelligent.Container;
043:        import de.finix.contelligent.HTTPCallData;
044:        import de.finix.contelligent.core.AbstractCallDataImpl;
045:        import de.finix.contelligent.exception.CircularRenderException;
046:        import de.finix.contelligent.exception.ComponentPersistenceException;
047:        import de.finix.contelligent.exception.ContelligentException;
048:        import de.finix.contelligent.exception.ContelligentExceptionID;
049:        import de.finix.contelligent.logging.LoggingService;
050:
051:        public class Template {
052:            final static org.apache.log4j.Logger log = LoggingService
053:                    .getLogger(Template.class);
054:
055:            final static public String FINIX_TAG_PREFIX = "<finix:";
056:
057:            final static private int FINIX_TAG_PREFIX_LENGTH = FINIX_TAG_PREFIX
058:                    .length();
059:
060:            final static public String RENDER_IDENTIFIER = "render "; // XXX: should
061:
062:            // we match any
063:            // whitespace?
064:
065:            final static private int RENDER_LENGTH = RENDER_IDENTIFIER.length();
066:
067:            final static public String THIS_PATH = ".";
068:
069:            final static public String PATH_ATTRIBUTE = "path";
070:
071:            final static public String SUBSTITUTION_PREFIX = "{{";
072:
073:            final static public String SUBSTITUTION_POSTFIX = "}}";
074:
075:            final static public int EVAL_FINAL = 1;
076:
077:            final static public int EVAL_STATIC = 2;
078:
079:            final static public int EVAL_DYNAMIC = 4;
080:
081:            private String text;
082:
083:            private List precompiledTemplate, optimizedTemplate;
084:
085:            public Template(String text) throws ContelligentException {
086:                setText(text);
087:            }
088:
089:            public void setText(String text) throws ContelligentException {
090:                this .text = text;
091:                precompiledTemplate = precompileTemplate(text);
092:            }
093:
094:            public String getText() {
095:                return text;
096:            }
097:
098:            public void setPrecompiledTemplate(List precompiledTemplate) {
099:                this .precompiledTemplate = precompiledTemplate;
100:            }
101:
102:            public List getPrecompiledTemplate() throws ContelligentException {
103:                return precompiledTemplate;
104:            }
105:
106:            public List precompileTemplate(String template)
107:                    throws ContelligentException {
108:                final boolean debugEnabled = log.isDebugEnabled();
109:                // replace internal links with finix tags...
110:                int lastPosition = 0, currentPosition = 0;
111:                int close = -1;
112:                List precompiledTemplate = new ArrayList();
113:                while ((currentPosition = template.indexOf(FINIX_TAG_PREFIX,
114:                        lastPosition)) >= 0) {
115:                    if (debugEnabled)
116:                        log
117:                                .debug("precompileTemplate() - ... found tag-prefix '"
118:                                        + FINIX_TAG_PREFIX
119:                                        + "' at position "
120:                                        + currentPosition + " ...");
121:                    precompiledTemplate.add(new PrecompiledTemplateFragment(
122:                            template.substring(lastPosition, currentPosition)));
123:                    lastPosition = currentPosition;
124:                    currentPosition += FINIX_TAG_PREFIX_LENGTH;
125:                    if (template.startsWith(RENDER_IDENTIFIER, currentPosition)) {
126:                        if (debugEnabled)
127:                            log
128:                                    .debug("precompileTemplate() - ... identified tag '"
129:                                            + RENDER_IDENTIFIER
130:                                            + "' at position "
131:                                            + currentPosition + " ...");
132:                        currentPosition += RENDER_LENGTH;
133:                        close = template.indexOf(">", currentPosition);
134:                        if (close != -1) {
135:                            if (template.charAt(close - 1) == '/') {
136:                                precompileRenderTag(precompiledTemplate,
137:                                        template, currentPosition, close - 1);
138:                            } else {
139:                                // normally we would have to check for a closing
140:                                // </finix:..> tag in this case // TODO: warn or debug?
141:                                log
142:                                        .debug("precompileTemplate() - normally a 'finix:render' tag MUST end with '/>' ...");
143:                                precompileRenderTag(precompiledTemplate,
144:                                        template, currentPosition, close);
145:                            }
146:                        }
147:                    } else {
148:                        // rat: Removed. This used to report the wrong string on errors.
149:                        // currentPosition += RENDER_LENGTH;
150:                        close = template.indexOf(">", currentPosition);
151:                        if (template.length() >= currentPosition + 10) {
152:                            log
153:                                    .warn("precompileTemplate() - ignoring unknown tag at position "
154:                                            + currentPosition
155:                                            + ", starts with ["
156:                                            + template.substring(
157:                                                    currentPosition,
158:                                                    currentPosition + 10)
159:                                            + "]!");
160:                        } else {
161:                            log
162:                                    .warn("precompileTemplate() - ignoring unknown tag at position "
163:                                            + currentPosition
164:                                            + ", near end of content!");
165:                        }
166:                    }
167:                    if (close == -1) {
168:                        log
169:                                .error("precompileTemplate() - parse-error at position "
170:                                        + currentPosition
171:                                        + ", tag has to end with either > or /> ");
172:                        throw new ComponentPersistenceException(
173:                                ContelligentExceptionID.component_unclosedRenderTag);
174:                    }
175:                    currentPosition = (close + 1);
176:                    lastPosition = currentPosition;
177:                }
178:
179:                if (lastPosition > template.length()) {
180:                    log
181:                            .error("precompileTemplate() - last position is greater than lenght!");
182:                } else {
183:                    precompiledTemplate
184:                            .add(new PrecompiledTemplateFragment(template
185:                                    .substring(lastPosition, template.length())));
186:                }
187:                return precompiledTemplate;
188:            }
189:
190:            private void precompileRenderTag(List precompiledTemplate,
191:                    String template, int start, int end)
192:                    throws ContelligentException {
193:                try {
194:                    String path = getAttribute(template.substring(start, end),
195:                            PATH_ATTRIBUTE);
196:                    if (path.trim().length() == 0) {
197:                        throw new ContelligentException(
198:                                "Parse-error: tag contains empty path");
199:                    }
200:                    ComponentPath componentPath;
201:                    Map parameterMap = null;
202:                    int questionMark = path.indexOf('?');
203:                    String pathString = path;
204:
205:                    if (questionMark != -1) {
206:                        pathString = path.substring(0, questionMark);
207:                        String parameterString = path
208:                                .substring(questionMark + 1);
209:                        parameterMap = HttpUtils
210:                                .parseQueryString(parameterString);
211:                    }
212:                    precompiledTemplate.add(createFragment(new ComponentPath(
213:                            pathString), parameterMap));
214:                } catch (ParseException exception) {
215:                    throw new ComponentPersistenceException(
216:                            ContelligentExceptionID.component_invalidRenderTag,
217:                            new Object[] { template.substring(start, end) });
218:                }
219:            }
220:
221:            /**
222:             * Overwrite to create specific precompiled template fragment for render
223:             * tag.
224:             * 
225:             * @param componentPath
226:             * @param parameterMap
227:             * @return
228:             */
229:            protected PrecompiledTemplateFragment createFragment(
230:                    ComponentPath componentPath, Map parameterMap) {
231:                return new PrecompiledTemplateFragment(componentPath,
232:                        parameterMap);
233:            }
234:
235:            /**
236:             * Overwrite to create specific precompiled template fragment for text.
237:             */
238:            protected PrecompiledTemplateFragment createFragment(String text) {
239:                return new PrecompiledTemplateFragment(text);
240:            }
241:
242:            public List getOptimizedTemplate(int options, Component component,
243:                    CallData callData) throws IOException {
244:                if (optimizedTemplate == null) {
245:                    optimizedTemplate = new ArrayList();
246:                    for (Iterator i = precompiledTemplate.iterator(); i
247:                            .hasNext();) {
248:                        optimizedTemplate.add(((PrecompiledTemplateFragment) i
249:                                .next()).getOptimizedTemplateFragment(options,
250:                                component, callData));
251:                    }
252:                    // concat all text fragments that are not separated by render-tags
253:                    for (Iterator i = precompiledTemplate.iterator(); i
254:                            .hasNext();) {
255:                        PrecompiledTemplateFragment fragment = (PrecompiledTemplateFragment) i
256:                                .next();
257:                    }
258:                }
259:                return optimizedTemplate;
260:            }
261:
262:            static String getAttribute(String tagTorso, String attributeName)
263:                    throws ParseException {
264:                int current = 0;
265:                int separatorIndex = -1;
266:
267:                while ((separatorIndex = tagTorso.indexOf('=', current)) > -1) {
268:                    String attrName = tagTorso.substring(current,
269:                            separatorIndex).trim();
270:                    current = separatorIndex;
271:
272:                    // skip whitespaces:
273:                    while (tagTorso.length() > current
274:                            && Character.isWhitespace(tagTorso
275:                                    .charAt(current++)))
276:                        ;
277:
278:                    if (tagTorso.charAt(current) != '\"'
279:                            && tagTorso.charAt(current) != '\'') {
280:                        log
281:                                .error("getAttributeMap() - tag evaluation error: attribute values have to be included in quotes [\" or \'] for attribute "
282:                                        + attrName);
283:                        throw new ParseException(
284:                                "tag evaluation error: attribute values have to be included in quotes [\" or \'] for attribute "
285:                                        + attrName, current);
286:                    }
287:                    current++;
288:                    separatorIndex = tagTorso.indexOf("\"", current);
289:                    if (separatorIndex == -1) {
290:                        separatorIndex = tagTorso.indexOf("\'", current);
291:                    }
292:                    if (separatorIndex < 0) {
293:                        log
294:                                .error("tag evaluation error: attribute has to be quoted at the end [\" or \']");
295:                        throw new ParseException(
296:                                "tag evaluation error: attribute has to be quoted at the end [\" or \']",
297:                                current);
298:                    }
299:                    String attrValue = tagTorso.substring(current,
300:                            separatorIndex).trim();
301:
302:                    if (log.isDebugEnabled()) {
303:                        log.debug("getAttributeMap() - found attribute '"
304:                                + attrName + "=\"" + attrValue + "\"' ...");
305:                    }
306:                    if (attrName.equals(attributeName)) {
307:                        return attrValue;
308:                    }
309:                    current = separatorIndex + 1;
310:                }
311:                log.error("tag evaluation error: attribute '" + attributeName
312:                        + "' is missing");
313:                throw new ParseException("tag evaluation error: attribute '"
314:                        + attributeName + "' is missing in " + tagTorso,
315:                        current);
316:            }
317:
318:            static Map getAttributeMap(String tagTorso) throws ParseException {
319:                Map attributes = new HashMap();
320:                int current = 0;
321:                int separatorIndex = -1;
322:
323:                while ((separatorIndex = tagTorso.indexOf('=', current)) > -1) {
324:                    String attrName = tagTorso.substring(current,
325:                            separatorIndex).trim();
326:                    current = separatorIndex;
327:
328:                    // skip whitespaces:
329:                    while (tagTorso.length() > current
330:                            && Character.isWhitespace(tagTorso
331:                                    .charAt(current++)))
332:                        ;
333:
334:                    if (tagTorso.charAt(current) != '\"'
335:                            && tagTorso.charAt(current) != '\'') {
336:                        log
337:                                .error("getAttributeMap() - tag evaluation error: attribute values have to be included in quotes [\" or \'] for attribute "
338:                                        + attrName);
339:                        throw new ParseException(
340:                                "tag evaluation error: attribute values have to be included in quotes [\" or \'] for attribute "
341:                                        + attrName, current);
342:                    }
343:                    current++;
344:                    separatorIndex = tagTorso.indexOf("\"", current);
345:                    if (separatorIndex == -1) {
346:                        separatorIndex = tagTorso.indexOf("\'", current);
347:                    }
348:                    if (separatorIndex < 0) {
349:                        log
350:                                .error("tag evaluation error: attribute has to be quoted at the end [\" or \']");
351:                        throw new ParseException(
352:                                "tag evaluation error: attribute has to be quoted at the end [\" or \']",
353:                                current);
354:                    }
355:                    String attrValue = tagTorso.substring(current,
356:                            separatorIndex).trim();
357:
358:                    if (log.isDebugEnabled()) {
359:                        log.debug("getAttributeMap() - found attribute '"
360:                                + attrName + "=\"" + attrValue + "\"' ...");
361:                    }
362:                    attributes.put(attrName, attrValue);
363:                    current = separatorIndex;
364:                }
365:                return attributes;
366:            }
367:
368:            public void write(Writer writer, Component component,
369:                    CallData callData) throws ContelligentException,
370:                    IOException {
371:                List templateToWrite = precompiledTemplate;
372:                if (optimizedTemplate != null) {
373:                    templateToWrite = optimizedTemplate;
374:                }
375:                for (Iterator i = templateToWrite.iterator(); i.hasNext();) {
376:                    ((PrecompiledTemplateFragment) i.next()).write(writer,
377:                            component, callData);
378:                }
379:            }
380:
381:            private static Component resolveComponent(Component component,
382:                    ComponentPath componentPath, CallData callData)
383:                    throws ComponentNotFoundException {
384:                // loadType component and check if it should be inlined...
385:                ComponentManager manager = callData.getActualManager();
386:                Component resolvedComponent = null;
387:
388:                if (componentPath.isAbsolute()) {
389:                    resolvedComponent = manager.getComponent(componentPath,
390:                            callData);
391:                } else if (componentPath.toString().equals(THIS_PATH)) {
392:                    return component;
393:                } else {
394:                    if (component != null && component instanceof  Container) {
395:                        resolvedComponent = manager.getSubcomponent(
396:                                (Container) component, componentPath, callData);
397:                    } else {
398:                        log
399:                                .error("resolveComponent() - evaluation of relative path '"
400:                                        + componentPath
401:                                        + "' impossible without a component!");
402:                        throw new ComponentNotFoundException(
403:                                ContelligentExceptionID.component_notFound_relativePathWithoutParent,
404:                                componentPath);
405:                    }
406:                }
407:                return resolvedComponent;
408:            }
409:
410:            /**
411:             * Returns a collection of ComponentPath instances which may be relative or
412:             * absolute where each path represents the path attribute of a
413:             * {@link #RENDER_IDENTIFIER render tag}. <BR>
414:             * Note that the paths may still contain category tokens!
415:             */
416:            public Collection getPathsOfRelationTargets() {
417:                Collection relationSources = new HashSet();
418:                Iterator templates = precompiledTemplate.iterator();
419:                while (templates.hasNext()) {
420:                    PrecompiledTemplateFragment fragment = (PrecompiledTemplateFragment) templates
421:                            .next();
422:                    if (fragment.getType() == PrecompiledTemplateFragment.RENDER_TAG) {
423:                        ComponentPath componentPath = fragment
424:                                .getComponentPath();
425:                        if (!componentPath.toString().equals(THIS_PATH)) { // skip
426:                            // THIS_PATH
427:                            // (='.') !
428:                            relationSources.add(componentPath);
429:                        }
430:                    } // else nothing to do: the fragment does not contain any
431:                    // relation.
432:                }
433:                return relationSources;
434:            }
435:
436:            public static class PrecompiledTemplateFragment implements 
437:                    Cloneable {
438:                public final static int TEXT_FRAGMENT = 0;
439:
440:                public final static int TEXT_FRAGMENT_SUBSTITUTE = 2;
441:
442:                public final static int RENDER_TAG = 1;
443:
444:                private int type;
445:
446:                private String textFragment;
447:
448:                private Map parameterMap;
449:
450:                private ComponentPath componentPath;
451:
452:                public PrecompiledTemplateFragment(String textFragment) {
453:                    boolean substitute = false;
454:                    if (textFragment != null) {
455:                        int pospre = textFragment.indexOf(SUBSTITUTION_PREFIX);
456:                        int pospost = textFragment
457:                                .indexOf(SUBSTITUTION_POSTFIX);
458:                        if ((pospre >= 0) && (pospost >= 0)) {
459:                            substitute = true;
460:                            log.debug("Fragment will be posprocessed.");
461:                        }
462:                    }
463:                    // wenn im text Zeichen auftachen, die anzeigen, dass unter
464:                    // Umständen Textbaustein wie z.b.
465:                    // {{request.scheme}} auftauchen, dann wird dieses Fragment als
466:                    // SUBSTITUTE gekennzeichnet.
467:                    // Beim rendern wird der Text vor der Ausgabe dann nochmal
468:                    // zusätzlich geparsed.
469:                    this .type = substitute ? TEXT_FRAGMENT_SUBSTITUTE
470:                            : TEXT_FRAGMENT;
471:                    this .textFragment = textFragment;
472:                }
473:
474:                public PrecompiledTemplateFragment(ComponentPath componentPath) {
475:                    this .type = RENDER_TAG;
476:                    this .componentPath = componentPath;
477:                    this .parameterMap = null;
478:                }
479:
480:                public PrecompiledTemplateFragment(ComponentPath componentPath,
481:                        Map parameterMap) {
482:                    this .type = RENDER_TAG;
483:                    this .componentPath = componentPath;
484:                    if (parameterMap != null) {
485:                        this .parameterMap = Collections
486:                                .unmodifiableMap(parameterMap);
487:                    }
488:                }
489:
490:                public String getTextFragment() {
491:                    return textFragment;
492:                }
493:
494:                /**
495:                 * Get the type of the fragment.
496:                 * 
497:                 * @return the type of the fragment.
498:                 */
499:                public int getType() {
500:                    return type;
501:                }
502:
503:                /**
504:                 * Get the component path of a relation target specified by a render tag
505:                 * type fragment.
506:                 * 
507:                 * @return the component path of a relation target.
508:                 */
509:                public ComponentPath getComponentPath() {
510:                    return componentPath;
511:                }
512:
513:                /**
514:                 * /** Set the component path of a relation target specified by a render
515:                 * tag type fragment.
516:                 * 
517:                 * @param componentPath
518:                 *            the component path of a relation target.
519:                 */
520:                public void setComponentPath(ComponentPath componentPath) {
521:                    this .componentPath = componentPath;
522:                }
523:
524:                public PrecompiledTemplateFragment getOptimizedTemplateFragment(
525:                        int options, Component component, CallData callData)
526:                        throws IOException {
527:                    PrecompiledTemplateFragment fragment = (PrecompiledTemplateFragment) this 
528:                            .clone();
529:                    if (type == RENDER_TAG) {
530:                        try {
531:                            Component resolvedComponent = resolveComponent(
532:                                    component, componentPath, callData);
533:                            if (resolvedComponent instanceof  Renderable) {
534:                                if ((resolvedComponent.getComponentContext()
535:                                        .isFinal() && ((options & EVAL_FINAL) != 0))
536:                                        || (!resolvedComponent.isDynamic() && ((options & EVAL_STATIC) != 0))) {
537:                                    Renderer renderer = ((Renderable) resolvedComponent)
538:                                            .getRenderer();
539:                                    CharArrayWriter writer = new CharArrayWriter(
540:                                            16384);
541:                                    renderer.render(writer, parameterMap,
542:                                            callData);
543:                                    fragment = new PrecompiledTemplateFragment(
544:                                            writer.toString());
545:                                }
546:                            } else {
547:                                log
548:                                        .error("optimize() - try to optimize non renderable component '"
549:                                                + componentPath + "'!");
550:                            }
551:                        } catch (ComponentNotFoundException exception) {
552:                            log.error("optimize() - component '"
553:                                    + componentPath + "' not found!");
554:                        } catch (ContelligentException exception) {
555:                            log
556:                                    .error("optimize() - could not optimize fragment!");
557:                        }
558:                    }
559:                    return fragment;
560:                }
561:
562:                public void write(Writer writer, Component component,
563:                        CallData callData) throws ContelligentException,
564:                        IOException {
565:                    if (type == TEXT_FRAGMENT) {
566:                        if (log.isDebugEnabled()) {
567:                            log.debug("write() - rendering text fragment: '"
568:                                    + textFragment + "' ...");
569:                        }
570:                        renderText(writer);
571:                    } else if (type == TEXT_FRAGMENT_SUBSTITUTE) {
572:                        if (log.isDebugEnabled()) {
573:                            log
574:                                    .debug("write() - rendering text fragment (postprocess): '"
575:                                            + textFragment + "' ...");
576:                        }
577:                        renderTextSubstitute(writer, callData);
578:                    } else if (type == RENDER_TAG) {
579:                        if (log.isDebugEnabled()) {
580:                            log.debug("write() - rendering component: '"
581:                                    + componentPath + "' ...");
582:                        }
583:                        renderTag(component, componentPath, parameterMap,
584:                                callData, writer);
585:                    }
586:                }
587:
588:                public Object clone() {
589:                    PrecompiledTemplateFragment fragment = null;
590:                    if (type == TEXT_FRAGMENT) {
591:                        fragment = new PrecompiledTemplateFragment(new String(
592:                                textFragment));
593:                    } else if (type == RENDER_TAG) {
594:                        fragment = new PrecompiledTemplateFragment(
595:                                componentPath);
596:                        if (parameterMap != null) {
597:                            fragment.parameterMap = new HashMap(parameterMap);
598:                        }
599:                    }
600:                    return fragment;
601:                }
602:
603:                /**
604:                 * Resolve component with absolute path or path relative to given
605:                 * component.
606:                 * 
607:                 * @param component
608:                 * @param componentPath
609:                 * @param callData
610:                 * @return
611:                 * @throws ComponentNotFoundException
612:                 */
613:                protected Component resolveComponent(Component component,
614:                        ComponentPath componentPath, CallData callData)
615:                        throws ComponentNotFoundException {
616:                    return Template.resolveComponent(component, componentPath,
617:                            callData);
618:                }
619:
620:                /**
621:                 * Render render tag. Overwrite to change rendering behaviour.
622:                 * 
623:                 * @param component
624:                 * @param componentPath
625:                 * @param parameterMap
626:                 * @param callData
627:                 * @param writer
628:                 * @throws ContelligentException
629:                 * @throws IOException
630:                 */
631:                protected void renderTag(Component component,
632:                        ComponentPath componentPath, Map parameterMap,
633:                        CallData callData, Writer writer)
634:                        throws ContelligentException, IOException {
635:
636:                    boolean pushed = false;
637:                    Map oldCategoryMap = callData.getCategoryMap();
638:                    Map oldParameterMap = callData.getParameters();
639:                    HashMap newCategoryMap = null;
640:                    HashMap newParameterMap = null;
641:                    AbstractCallDataImpl cImpl = (AbstractCallDataImpl) callData;
642:
643:                    try {
644:                        // switch categories, if applicable and copy parameters
645:                        // to callData parameterMap
646:                        // (Moved ahead before the resolve in 9.1 to allow
647:                        // CurrentPage to respond to the new parameters)
648:                        if (parameterMap != null) {
649:                            Iterator it = parameterMap.keySet().iterator();
650:                            while (it.hasNext()) {
651:                                String paramName = (String) it.next();
652:                                Object o = parameterMap.get(paramName);
653:                                if (oldCategoryMap.containsKey(paramName)) {
654:                                    if (newCategoryMap == null) {
655:                                        newCategoryMap = new HashMap(
656:                                                oldCategoryMap);
657:                                    }
658:                                    if (o instanceof  String[]) {
659:                                        newCategoryMap.put(paramName,
660:                                                ((String[]) o)[0]);
661:                                    } else if (o instanceof  String) {
662:                                        newCategoryMap.put(paramName,
663:                                                (String) o);
664:                                    }
665:                                }
666:                                if (newParameterMap == null) {
667:                                    newParameterMap = new HashMap(
668:                                            oldParameterMap);
669:                                }
670:                                newParameterMap.put(paramName, o);
671:                            }
672:                            if (newCategoryMap != null) {
673:                                cImpl.setCategoryMap(newCategoryMap);
674:                            }
675:                            if (newParameterMap != null) {
676:                                cImpl.setParameters(newParameterMap);
677:                            }
678:                        }
679:
680:                        // Extremely verbose logging of parameter maps for each
681:                        // render call. Might be useful later on...
682:                        if (log.isDebugEnabled()) {
683:                            StringBuffer sb = new StringBuffer();
684:                            sb
685:                                    .append("\n--------------------------\nRendering: "
686:                                            + component.getComponentContext()
687:                                                    .getPath()
688:                                            + "\nLocal parameterMap:\n");
689:                            if (parameterMap != null) {
690:                                Set keySet = parameterMap.keySet();
691:                                if (keySet != null) {
692:                                    Iterator keys = keySet.iterator();
693:                                    while (keys.hasNext()) {
694:                                        String key = (String) keys.next();
695:                                        String value = "";
696:                                        Object o = parameterMap.get(key);
697:                                        if (o instanceof  String[]) {
698:                                            value = ((String[]) o)[0];
699:                                        } else if (o instanceof  String) {
700:                                            value = (String) o;
701:                                        }
702:                                        sb.append(key + " / " + value + "\n");
703:                                    }
704:                                }
705:                            }
706:                            sb.append("\nInherited parameterMap:\n");
707:                            Map params = callData.getParameters();
708:                            if (params != null) {
709:                                Set keySet = params.keySet();
710:                                if (keySet != null) {
711:                                    Iterator keys = keySet.iterator();
712:                                    while (keys.hasNext()) {
713:                                        String key = (String) keys.next();
714:                                        String value = "";
715:                                        Object o = params.get(key);
716:                                        if (o instanceof  String[]) {
717:                                            value = ((String[]) o)[0];
718:                                        } else if (o instanceof  String) {
719:                                            value = (String) o;
720:                                        }
721:                                        sb.append(key + " / " + value + "\n");
722:                                    }
723:                                }
724:                            }
725:                            log.debug(sb.toString());
726:                        }
727:                        // End of parameter/category setup
728:
729:                        Component resolvedComponent = resolveComponent(
730:                                component, componentPath, callData);
731:                        if (resolvedComponent instanceof  Renderable) {
732:                            ComponentPath realPath = resolvedComponent
733:                                    .getComponentContext().getPath();
734:                            boolean alreadyRendered = callData
735:                                    .checkRenderStack(realPath);
736:                            if (alreadyRendered) {
737:                                throw new CircularRenderException();
738:                            }
739:                            Renderer renderer = ((Renderable) resolvedComponent)
740:                                    .getRenderer();
741:                            callData.pushRenderStack(realPath);
742:                            pushed = true;
743:
744:                            // Actual passing of control happens here
745:                            renderer.render(writer, parameterMap, callData);
746:
747:                        } else {
748:                            log
749:                                    .error("write() - can not render non-renderable component '"
750:                                            + resolvedComponent + "'!");
751:                            throw new ContelligentException("Component '"
752:                                    + resolvedComponent
753:                                    + "' is not renderable!");
754:                        }
755:                    } catch (ComponentNotFoundException exception) {
756:                        Component blueprint;
757:                        ComponentPath blueprintPath = component
758:                                .getComponentContext().getType()
759:                                .getBlueprintPath();
760:                        if (blueprintPath == null
761:                                || component.getComponentContext().getPath()
762:                                        .equals(blueprintPath)) {
763:                            blueprint = component;
764:                        } else {
765:                            ComponentManager manager = callData
766:                                    .getActualManager();
767:                            blueprint = manager.getComponent(blueprintPath,
768:                                    callData);
769:                        }
770:                        log.warn("render() - component '" + componentPath
771:                                + "' not found, checking if blueprint has it!");
772:                        // check if component exists at blueprint definition
773:                        try {
774:                            Component resolvedComponent = resolveComponent(
775:                                    blueprint, componentPath, callData);
776:                            if (resolvedComponent instanceof  Renderable) {
777:                                Renderer renderer = ((Renderable) resolvedComponent)
778:                                        .getRenderer();
779:                                renderer.render(writer, parameterMap, callData);
780:                            } else {
781:                                log
782:                                        .error("write() - can not render non-renderable component '"
783:                                                + resolvedComponent + "'!");
784:                                throw new ContelligentException("Component '"
785:                                        + resolvedComponent
786:                                        + "' is not renderable!");
787:                            }
788:                        } catch (ComponentNotFoundException e) {
789:                            log.error("render() - component '" + componentPath
790:                                    + "' not found (even not at blueprint)!");
791:                        }
792:                    } finally {
793:                        // always restore the old category map
794:                        if (newCategoryMap != null) {
795:                            cImpl.setCategoryMap(oldCategoryMap);
796:                        }
797:                        if (newParameterMap != null) {
798:                            cImpl.setParameters(oldParameterMap);
799:                        }
800:                    }
801:
802:                    // The pop call is intentionally not in the finally block,
803:                    // because the decision what to do with the stack
804:                    // is the responsibility of whoever catches the
805:                    // exception.
806:                    if (pushed) {
807:                        callData.popRenderStack();
808:                    }
809:
810:                }
811:
812:                /**
813:                 * Render constant text.
814:                 * 
815:                 * @param writer
816:                 * @throws IOException
817:                 */
818:                protected void renderText(Writer writer) throws IOException {
819:                    writer.write(textFragment);
820:                }
821:
822:                /**
823:                 * Dieser Sonderfall von renderText parsed den Text vor der Ausgabe
824:                 * nochmal. Dadurch können spezielle Platzhalter im Text wie z.B.
825:                 * {{request.scheme}} ersetzt werden. Derzeit wird nur dieser
826:                 * Platzhalter ersetzt. Geplant ist über diesen Mechanismus auch andere
827:                 * Platzhalter zu ermöglichen-
828:                 */
829:                protected void renderTextSubstitute(Writer writer,
830:                        CallData callData) throws IOException {
831:                    String substituted = substitute(textFragment, callData);
832:                    writer.write(substituted);
833:                }
834:
835:                final static String SCHEME_PARAMETER = "request.scheme";
836:
837:                final static String SCHEME_PATTERN = SUBSTITUTION_PREFIX
838:                        + SCHEME_PARAMETER + SUBSTITUTION_POSTFIX;
839:
840:                /**
841:                 * Ersetzungsfunktion für Platzhalter. Derzeit wird nur
842:                 * {{request.scheme}} ersetzt.
843:                 */
844:                private String substitute(String content, CallData callData) {
845:                    StringBuffer ret = new StringBuffer();
846:                    int to = 0;
847:                    int from = 0;
848:                    try {
849:                        if (callData instanceof  HTTPCallData) {
850:
851:                            HTTPCallData hc = (HTTPCallData) callData;
852:
853:                            HttpServletRequest request = hc
854:                                    .getHttpServletRequest();
855:                            String scheme_req = request.getScheme();
856:                            String scheme_hdr = request
857:                                    .getHeader(SCHEME_PARAMETER);
858:                            String scheme_prm = callData
859:                                    .getParameter(SCHEME_PARAMETER);
860:                            String scheme = null;
861:                            if (scheme_prm != null) {
862:                                scheme = scheme_prm;
863:                            } else if (scheme_hdr != null) {
864:                                scheme = scheme_hdr;
865:                            } else {
866:                                scheme = scheme_req;
867:                            }
868:
869:                            to = content.indexOf(SCHEME_PATTERN);
870:                            while (to >= 0) {
871:                                ret.append(content.substring(from, to));
872:                                ret.append(scheme);
873:
874:                                String test = ret.toString();
875:                                from = to + SCHEME_PATTERN.length();
876:                                to = content.indexOf(SCHEME_PATTERN, to + 1);
877:                            }
878:                            ret.append(content.substring(from));
879:                            return ret.toString();
880:                        }
881:                    } catch (Exception e) {
882:                        log.error("EXC: " + e);
883:                        log.debug("TRACE: ", e);
884:                    }
885:                    // wenn irgendwas schiefgeht, wird der content 1:1 geliefert
886:                    return content;
887:                }
888:
889:            } // class PrecompiledTemplateFragment
890:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.