KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opencms > template > CmsXmlTemplate


1 /*
2  * File : $Source: /usr/local/cvs/opencms/src-modules/com/opencms/template/CmsXmlTemplate.java,v $
3  * Date : $Date: 2005/06/27 23:22:20 $
4  * Version: $Revision: 1.6 $
5  *
6  * This library is part of OpenCms -
7  * the Open Source Content Mananagement System
8  *
9  * Copyright (C) 2001 The OpenCms Group
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * Lesser General Public License for more details.
20  *
21  * For further information about OpenCms, please see the
22  * OpenCms Website: http://www.opencms.org
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27  */

28
29 package com.opencms.template;
30
31 import org.opencms.file.CmsObject;
32 import org.opencms.file.CmsPropertyDefinition;
33 import org.opencms.file.CmsRequestContext;
34 import org.opencms.i18n.CmsEncoder;
35 import org.opencms.importexport.CmsCompatibleCheck;
36 import org.opencms.main.CmsException;
37 import org.opencms.main.CmsLog;
38 import org.opencms.main.OpenCms;
39 import org.opencms.staticexport.CmsLinkManager;
40 import org.opencms.workplace.editors.CmsDefaultPageEditor;
41
42 import com.opencms.defaults.A_CmsContentDefinition;
43 import com.opencms.defaults.I_CmsTimedContentDefinition;
44 import com.opencms.legacy.CmsLegacyException;
45 import com.opencms.legacy.CmsXmlTemplateLoader;
46 import com.opencms.template.cache.A_CmsElement;
47 import com.opencms.template.cache.CmsElementCache;
48 import com.opencms.template.cache.CmsElementDefinition;
49 import com.opencms.template.cache.CmsElementDefinitionCollection;
50 import com.opencms.template.cache.CmsElementDescriptor;
51 import com.opencms.template.cache.CmsElementVariant;
52 import com.opencms.template.cache.CmsElementXml;
53
54 import java.util.Enumeration JavaDoc;
55 import java.util.Hashtable JavaDoc;
56 import java.util.Vector JavaDoc;
57
58 import javax.servlet.http.HttpServletRequest JavaDoc;
59
60 /**
61  * Template class for displaying the processed contents of hierachical XML template files
62  * that can include other subtemplates.
63  *
64  * @author Alexander Lucas
65  * @version $Revision: 1.6 $ $Date: 2005/06/27 23:22:20 $
66  *
67  * @deprecated Will not be supported past the OpenCms 6 release.
68  */

69 public class CmsXmlTemplate extends A_CmsTemplate implements I_CmsXmlTemplate {
70
71     /** Name of the special body element. */
72     public static final String JavaDoc C_BODY_ELEMENT = CmsDefaultPageEditor.XML_BODY_ELEMENT;
73
74     /** Boolean for additional debug output control. */
75     public static final boolean C_DEBUG = true;
76
77     /** Name of the frame selector parameter. */
78     public static final String JavaDoc C_FRAME_SELECTOR = "cmsframe";
79
80     /**
81      * Template cache for storing cacheable results of the subtemplates.
82      */

83     protected static com.opencms.template.I_CmsTemplateCache m_cache;
84
85     /** Element descriptor. */
86     private static final String JavaDoc C_ELEMENT = "_ELEMENT_";
87
88     /** Error string to be inserted for corrupt subtemplates for guest user requests. */
89     private static final String JavaDoc C_ERRORTEXT = "ERROR!";
90
91     /**
92      * For debugging purposes only.
93      * Counts the number of re-uses od the instance of this class.
94      */

95     private int m_counter;
96
97     /**
98      * Collect caching informations from the current template class.
99      * <P>
100      * Complex classes that are able to include other subtemplates
101      * have to check the streaming ability of their subclasses here!
102      *
103      * @param cms CmsObject Object for accessing system resources
104      * @param templateFile Filename of the template file
105      * @param elementName Element name of this template in our parent template.
106      * @param parameters Hashtable with all template class parameters.
107      * @param templateSelector template section that should be processed.
108      * @return <EM>true</EM> if this class may stream it's results, <EM>false</EM> otherwise.
109      */

110     public CmsCacheDirectives collectCacheDirectives(CmsObject cms, String JavaDoc templateFile,
111         String JavaDoc elementName, Hashtable JavaDoc parameters, String JavaDoc templateSelector) {
112
113         // Frist build our own cache directives.
114
boolean isCacheable = isCacheable(cms, templateFile, elementName, parameters, templateSelector);
115         boolean isProxyPrivateCacheable = isProxyPrivateCacheable(cms, templateFile, elementName, parameters, templateSelector);
116         boolean isProxyPublicCacheable = isProxyPublicCacheable(cms, templateFile, elementName, parameters, templateSelector);
117         boolean isExportable = isExportable(cms, templateFile, elementName, parameters, templateSelector);
118         boolean isStreamable = isStreamable(cms, templateFile, elementName, parameters, templateSelector);
119         CmsCacheDirectives result = new CmsCacheDirectives(isCacheable, isProxyPrivateCacheable,
120             isProxyPublicCacheable, isExportable, isStreamable);
121
122         // Collect all subelements of this page
123
CmsXmlTemplateFile doc = null;
124         Vector JavaDoc subtemplates = null;
125         try {
126             doc = this.getOwnTemplateFile(cms, templateFile, elementName, parameters, templateSelector);
127             doc.init(cms, templateFile);
128             subtemplates = doc.getAllSubElements();
129
130             // Loop through all subelements and get their cache directives
131
int numSubtemplates = subtemplates.size();
132             for (int i = 0; i < numSubtemplates; i++) {
133                 String JavaDoc elName = (String JavaDoc)subtemplates.elementAt(i);
134                 String JavaDoc className = null;
135                 String JavaDoc templateName = null;
136
137                 className = getTemplateClassName(elName, doc, parameters);
138                 templateName = getTemplateFileName(elName, doc, parameters);
139
140                 if (className != null) {
141                     I_CmsTemplate templClass = (I_CmsTemplate)CmsTemplateClassManager.getClassInstance(className);
142                     CmsCacheDirectives cd2 = templClass.collectCacheDirectives(cms, templateName, elName, parameters, null);
143                     /*System.err.println("* INT PUB PRV EXP STR");
144                      debugPrint(elementName, result.m_cd);
145                      System.err.println(" ");
146                      debugPrint(elName, cd2.m_cd);
147                      System.err.println(" " + templClass.getClass());
148                      System.err.println("* -------------------");*/

149
150                     //result.merge(templClass.collectCacheDirectives(cms, templateName, elName, parameters, null));
151
result.merge(cd2);
152                     /*debugPrint(elementName, result.m_cd);
153                      System.err.println(" ");
154                      System.err.println("* ");*/

155                 } else {
156                     // This template file includes a subelement not exactly defined.
157
// The name of it's template class is missing at the moment, so
158
// we cannot say anything about the cacheablility.
159
// Set it to false.
160
return new CmsCacheDirectives(false);
161                 }
162             }
163         } catch (CmsException e) {
164             if (CmsLog.getLog(this).isInfoEnabled()) {
165                 CmsLog.getLog(this).info("Can not determine cache directives for my template file "
166                     + templateFile, e);
167                 return new CmsCacheDirectives(false);
168             }
169         }
170         return result;
171
172     }
173
174     /**
175      * For debugging purposes only.
176      * Increments the class variable <code>counter</code> and
177      * prints out its new value..
178      * <P>
179      * May be called from the template file using
180      * <code>&lt;METHOD name="counter"&gt;</code>.
181      *
182      * @param cms CmsObject Object for accessing system resources.
183      * @param tagcontent Unused in this special case of a user method. Can be ignored.
184      * @param doc Reference to the A_CmsXmlContent object the initiating XLM document.
185      * @param userObject Hashtable with parameters.
186      * @return Actual value of <code>counter</code>.
187      */

188     public Integer JavaDoc counter(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc, Object JavaDoc userObject)
189     throws CmsException {
190
191         m_counter++;
192         return new Integer JavaDoc(m_counter);
193     }
194
195     /**
196      * Create a new element for the element cache consisting of the current template
197      * class and the given template file.
198      * <P>
199      * Complex template classes that are able to include other (sub-)templates
200      * must generate a collection of element definitions for their possible
201      * subtemplates. This collection is part of the new element.
202      * @param cms CmsObject for accessing system resources.
203      * @param templateFile Name of the template file for the new element
204      * @param parameters All parameters of the current request
205      * @return New element for the element cache
206      */

207     public A_CmsElement createElement(CmsObject cms, String JavaDoc templateFile, Hashtable JavaDoc parameters) {
208
209         CmsElementDefinitionCollection subtemplateDefinitions = new CmsElementDefinitionCollection();
210         int variantCachesize = 100;
211         // if the templateFile is null someone didnt set the Templatefile in the elementdefinition
212
// in this case we have to use the aktual body template when resolving the variant.
213
// In a body element there are no subelements and we dont care about access rights.
214
// So if if the Exception occurs becource of the template == null it is no error and
215
// we set the readAccessGroup = null (this will happen by getReadingpermittedGroup)
216
try {
217             CmsElementCache elementCache = CmsXmlTemplateLoader.getElementCache();
218             variantCachesize = elementCache.getVariantCachesize();
219
220             CmsXmlTemplateFile xmlTemplateDocument = getOwnTemplateFile(cms, templateFile, null, parameters, null);
221
222             Vector JavaDoc subtemplates = xmlTemplateDocument.getAllSubElementDefinitions();
223
224             int numSubtemplates = subtemplates.size();
225             for (int i = 0; i < numSubtemplates; i++) {
226                 String JavaDoc elName = (String JavaDoc)subtemplates.elementAt(i);
227                 String JavaDoc className = null;
228                 String JavaDoc templateName = null;
229                 String JavaDoc templateSelector = null;
230
231                 if (xmlTemplateDocument.hasSubtemplateClass(elName)) {
232                     className = xmlTemplateDocument.getSubtemplateClass(elName);
233                 }
234
235                 if (xmlTemplateDocument.hasSubtemplateFilename(elName)) {
236                     templateName = xmlTemplateDocument.getSubtemplateFilename(elName);
237                 }
238
239                 if (xmlTemplateDocument.hasSubtemplateSelector(elName)) {
240                     templateSelector = xmlTemplateDocument.getSubtemplateSelector(elName);
241                 }
242                 Hashtable JavaDoc templateParameters = xmlTemplateDocument.getParameters(elName);
243                 if (className != null || templateName != null || templateSelector != null
244                     || templateParameters.size() > 0) {
245                     if (className == null) {
246                         className = CmsCompatibleCheck.XML_CONTROL_DEFAULT_CLASS;
247                     }
248                     if (templateName != null) {
249                         templateName = CmsLinkManager.getAbsoluteUri(templateName, templateFile);
250                     }
251                     CmsElementDefinition elDef = new CmsElementDefinition(elName, className,
252                         templateName, templateSelector, templateParameters);
253                     subtemplateDefinitions.add(elDef);
254                 }
255             }
256         } catch (Exception JavaDoc e) {
257             if (templateFile != null) {
258                 if (CmsLog.getLog(this).isWarnEnabled()) {
259                     CmsLog.getLog(this).warn("Could not generate my template cache element", e);
260                 }
261             }
262         }
263         CmsElementXml result = new CmsElementXml(getClass().getName(), templateFile,
264             getCacheDirectives(cms, templateFile, null, parameters, null), subtemplateDefinitions,
265             variantCachesize);
266         return result;
267     }
268
269     /**
270      * gets the caching information from the current template class.
271      *
272      * @param cms CmsObject Object for accessing system resources
273      * @param templateFile Filename of the template file
274      * @param elementName Element name of this template in our parent template.
275      * @param parameters Hashtable with all template class parameters.
276      * @param templateSelector template section that should be processed.
277      * @return <EM>true</EM> if this class may stream it's results, <EM>false</EM> otherwise.
278      */

279     public CmsCacheDirectives getCacheDirectives(CmsObject cms, String JavaDoc templateFile,
280         String JavaDoc elementName, Hashtable JavaDoc parameters, String JavaDoc templateSelector) {
281
282         // First build our own cache directives.
283
CmsCacheDirectives result = new CmsCacheDirectives(true);
284         Vector JavaDoc para = new Vector JavaDoc();
285         para.add("cmsframe");
286         result.setCacheParameters(para);
287         return result;
288     }
289
290     /**
291      * Gets the content of a given template file and its subtemplates
292      * with the given parameters. The default section in the template file
293      * will be used.
294      * <P>
295      * Parameters are stored in a hashtable and can derive from
296      * <UL>
297      * <LI>Template file of the parent template</LI>
298      * <LI>Body file clicked by the user</LI>
299      * <LI>URL parameters</LI>
300      * </UL>
301      * Paramter names must be in "elementName.parameterName" format.
302      *
303      * @param cms CmsObject Object for accessing system resources
304      * @param templateFile Filename of the template file
305      * @param elementName Element name of this template in our parent template
306      * @param parameters Hashtable with all template class parameters.
307      * @return Content of the template and all subtemplates.
308      * @throws CmsException if something goes wrong
309      */

310     public byte[] getContent(CmsObject cms, String JavaDoc templateFile, String JavaDoc elementName,
311         Hashtable JavaDoc parameters) throws CmsException {
312
313         return getContent(cms, templateFile, elementName, parameters, null);
314     }
315
316     /**
317      * Gets the content of a defined section in a given template file and its subtemplates
318      * with the given parameters.
319      *
320      * @see #getContent(CmsObject, String, String, Hashtable, String)
321      * @param cms CmsObject Object for accessing system resources.
322      * @param templateFile Filename of the template file.
323      * @param elementName Element name of this template in our parent template.
324      * @param parameters Hashtable with all template class parameters.
325      * @param templateSelector template section that should be processed.
326      * @return Content of the template and all subtemplates.
327      * @throws CmsException if something goes wrong
328      */

329     public byte[] getContent(CmsObject cms, String JavaDoc templateFile, String JavaDoc elementName,
330         Hashtable JavaDoc parameters, String JavaDoc templateSelector) throws CmsException {
331
332         if (CmsLog.getLog(this).isDebugEnabled() && C_DEBUG) {
333             CmsLog.getLog(this).debug("[CmsXmlTemplate] getting content of element "
334                 + ((elementName == null) ? "<root>" : elementName));
335             CmsLog.getLog(this).debug("[CmsXmlTemplate] template file is: " + templateFile);
336             CmsLog.getLog(this).debug("[CmsXmlTemplate] selected template section is: "
337                 + ((templateSelector == null) ? "<default>" : templateSelector));
338         }
339         CmsXmlTemplateFile xmlTemplateDocument = getOwnTemplateFile(cms, templateFile, elementName, parameters, templateSelector);
340         if (templateSelector == null || "".equals(templateSelector)) {
341             templateSelector = (String JavaDoc)parameters.get(C_FRAME_SELECTOR);
342         }
343         return startProcessing(cms, xmlTemplateDocument, elementName, parameters, templateSelector);
344     }
345
346     /**
347      * Inserts the correct document description into the template.
348      * <P>
349      * This method can be called using <code>&lt;METHOD name="getDescription"&gt;</code>
350      * in the template file.
351      *
352      * @param cms CmsObject Object for accessing system resources.
353      * @param tagcontent Unused in this special case of a user method. Can be ignored.
354      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
355      * @param userObject Hashtable with parameters.
356      * @return String or byte[] with the content of this subelement.
357      * @throws CmsException if something goes wrong
358      */

359     public Object JavaDoc getDescription(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
360         Object JavaDoc userObject) throws CmsException {
361
362         String JavaDoc requestedUri = cms.getRequestContext().getUri();
363         String JavaDoc description = cms.readProperty(requestedUri, CmsPropertyDefinition.PROPERTY_DESCRIPTION);
364         if (description == null) {
365             description = "";
366         }
367         return description;
368     }
369
370     public Object JavaDoc getEncoding(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
371         Object JavaDoc userObject) throws CmsException {
372
373         return cms.getRequestContext().getEncoding();
374     }
375
376     /**
377      * @param cms CmsObject Object for accessing system resources.
378      * @param tagcontent Unused in this special case of a user method. Can be ignored.
379      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
380      * @param userObject Hashtable with parameters.
381      * @return String or byte[] with the content of this subelement.
382      * @throws CmsException if something goes wrong
383      */

384     public Object JavaDoc getFileUri(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
385         Object JavaDoc userObject) throws CmsException {
386
387         String JavaDoc uri = cms.getRequestContext().getUri();
388         return uri.substring(uri.lastIndexOf("/") + 1);
389     }
390
391     /**
392      * Gets the QueryString for CmsFrameTemplates.
393      * <P>
394      * This method can be called using <code>&lt;METHOD name="getCmsQueryString"&gt;</code>
395      * in the template file.
396      *
397      * @param cms CmsObject Object for accessing system resources.
398      * @param tagcontent Unused in this special case of a user method. Can be ignored.
399      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
400      * @param userObject Hashtable with parameters.
401      * @return String or byte[] with the content of this subelement.
402      * @throws CmsException if something goes wrong
403      */

404     public Object JavaDoc getFrameQueryString(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
405         Object JavaDoc userObject) throws CmsException {
406
407         String JavaDoc query = new String JavaDoc();
408         // get the parameternames of the original request and get the values from the userObject
409
try {
410             Enumeration JavaDoc parameters = (CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getOriginalRequest()).getParameterNames();
411             StringBuffer JavaDoc paramQuery = new StringBuffer JavaDoc();
412             while (parameters.hasMoreElements()) {
413                 String JavaDoc name = (String JavaDoc)parameters.nextElement();
414                 String JavaDoc value = (String JavaDoc)((Hashtable JavaDoc)userObject).get(name);
415                 if (value != null && !"".equals(value)) {
416                     paramQuery.append(name + "=" + value + "&");
417                 }
418             }
419             if (paramQuery.length() > 0) {
420                 // add the parameters to the query string
421
query = paramQuery.substring(0, paramQuery.length() - 1).toString();
422             }
423         } catch (Exception JavaDoc exc) {
424             exc.printStackTrace();
425         }
426
427         // get the name of the frame and parameters
428
String JavaDoc frame = "", param = "";
429         if (!tagcontent.equals("")) {
430             if (!tagcontent.startsWith("&")) {
431                 if (tagcontent.indexOf(",") != -1) {
432                     frame = tagcontent.substring(0, tagcontent.indexOf(","));
433                     param = tagcontent.substring(tagcontent.indexOf(",") + 1);
434                 } else {
435                     frame = tagcontent;
436                 }
437             } else {
438                 param = tagcontent;
439             }
440         }
441         query = (query == null ? "" : query);
442         if (!query.equals("")) {
443             if (query.indexOf("cmsframe=") != -1) {
444                 int start = query.indexOf("cmsframe=");
445                 int end = query.indexOf("&", start);
446                 String JavaDoc cmsframe = "";
447                 if (end != -1) {
448                     cmsframe = query.substring(start + 9, end);
449                 } else {
450                     cmsframe = query.substring(start + 9);
451                 }
452                 if (!cmsframe.equals("plain")) {
453                     if (!frame.equals("")) {
454                         if (end != -1) {
455                             query = query.substring(0, start + 9) + frame + query.substring(end);
456                         } else {
457                             query = query.substring(0, start + 9) + frame;
458                         }
459                     } else {
460                         if (end != -1) {
461                             query = query.substring(0, start) + query.substring(end + 1);
462                         } else {
463                             query = query.substring(0, start);
464                         }
465                     }
466                 }
467             } else {
468                 if (!tagcontent.equals("")) {
469                     query = query + "&cmsframe=" + frame;
470                 }
471             }
472             if (!query.equals("")) {
473                 query = "?" + query;
474             }
475         } else {
476             if (!frame.equals("")) {
477                 query = "?cmsframe=" + frame;
478             }
479         }
480         if (!query.equals("")) {
481             query = query + param;
482         } else {
483             query = "?" + param.substring(param.indexOf("&") + 1);
484         }
485         if (query.trim().equals("?") || query.trim().equals("&") || query.trim().equals("?&")
486             || query.trim().equals("??")) {
487             query = "";
488         }
489         return query;
490     }
491
492     /**
493      * Gets the target for a link.
494      * <P>
495      * This method can be called using <code>&lt;METHOD name="getCmsFrame"&gt;</code>
496      * in the template file.
497      *
498      * @param cms CmsObject Object for accessing system resources.
499      * @param tagcontent Unused in this special case of a user method. Can be ignored.
500      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
501      * @param userObject Hashtable with parameters.
502      * @return String or byte[] with the content of this subelement.
503      * @throws CmsException if something goes wrong
504      */

505     public Object JavaDoc getFrameTarget(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
506         Object JavaDoc userObject) throws CmsException {
507
508         String JavaDoc target = "";
509         String JavaDoc cmsframe = (String JavaDoc)((Hashtable JavaDoc)userObject).get("cmsframe");
510         cmsframe = (cmsframe == null ? "" : cmsframe);
511         if (cmsframe.equals("plain")) {
512             target = "";
513         } else {
514             if (tagcontent.equals("")) {
515                 target = "target=_top";
516             } else {
517                 target = "target=" + tagcontent;
518             }
519         }
520         return target;
521     }
522
523     /**
524      * Gets the key that should be used to cache the results of
525      * <EM>this</EM> template class.
526      * <P>
527      * Since our results may depend on the used template file,
528      * the parameters and the requested body document, we must
529      * build a complex key using this three arguments.
530      *
531      * @param cms CmsObject Object for accessing system resources
532      * @param templateFile Filename of the template file
533      * @param parameters Hashtable with all template class parameters.
534      * @param templateSelector template section that should be processed.
535      * @return key that can be used for caching
536      */

537     public Object JavaDoc getKey(CmsObject cms, String JavaDoc templateFile, Hashtable JavaDoc parameters,
538         String JavaDoc templateSelector) {
539
540         CmsRequestContext reqContext = cms.getRequestContext();
541         String JavaDoc result = "" + reqContext.currentProject().getId() + ":"
542             + reqContext.currentUser().getName() + reqContext.getUri()
543             + reqContext.addSiteRoot(templateFile);
544         Enumeration JavaDoc keys = parameters.keys();
545         while (keys.hasMoreElements()) {
546             String JavaDoc key = (String JavaDoc)keys.nextElement();
547             result = result + key + parameters.get(key);
548         }
549         result = result + templateSelector;
550         return result;
551     }
552
553     /**
554      * Inserts the correct document keyword into the template.
555      * <P>
556      * This method can be called using <code>&lt;METHOD name="getKeywords"&gt;</code>
557      * in the template file.
558      *
559      * @param cms CmsObject Object for accessing system resources.
560      * @param tagcontent Unused in this special case of a user method. Can be ignored.
561      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
562      * @param userObject Hashtable with parameters.
563      * @return String or byte[] with the content of this subelement.
564      * @throws CmsException
565      */

566     public Object JavaDoc getKeywords(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
567         Object JavaDoc userObject) throws CmsException {
568
569         String JavaDoc requestedUri = cms.getRequestContext().getUri();
570         String JavaDoc keywords = cms.readProperty(requestedUri, CmsPropertyDefinition.PROPERTY_KEYWORDS);
571         if (keywords == null) {
572             keywords = "";
573         }
574         return keywords;
575     }
576
577     /**
578      * gets the caching information for a specific methode.
579      * @param cms the cms object.
580      * @param methodName the name of the method for witch the MethodCacheDirectives are wanted.
581      */

582     public CmsMethodCacheDirectives getMethodCacheDirectives(CmsObject cms, String JavaDoc methodName) {
583
584         if ("getTitle".equals(methodName) || "getUri".equals(methodName)
585             || "getFileUri".equals(methodName) || "getDescription".equals(methodName)
586             || "getKeywords".equals(methodName) || "getProperty".equals(methodName)
587             || "getPathUri".equals(methodName)) {
588             CmsMethodCacheDirectives mcd = new CmsMethodCacheDirectives(true);
589             mcd.setCacheUri(true);
590             return mcd;
591         }
592         if ("getFrameQueryString".equals(methodName) || "getQueryString".equals(methodName)
593             || "getRequestIp".equals(methodName) || "getSessionId".equals(methodName)
594             || "getUriWithParameter".equals(methodName) || "parameters".equals(methodName)
595             || "getStylesheet".equals(methodName)) {
596             return new CmsMethodCacheDirectives(false);
597         }
598         return null;
599     }
600
601     /**
602      * Reads in the template file and starts the XML parser for the expected
603      * content type.
604      * <P>
605      * Every extending class using not CmsXmlTemplateFile as content type,
606      * but any derived type should override this method.
607      *
608      * @param cms CmsObject Object for accessing system resources.
609      * @param templateFile Filename of the template file.
610      * @param elementName Element name of this template in our parent template.
611      * @param parameters Hashtable with all template class parameters.
612      * @param templateSelector template section that should be processed.
613      * @return the template file
614      * @throws CmsException if something goes wrong
615      */

616     public CmsXmlTemplateFile getOwnTemplateFile(CmsObject cms, String JavaDoc templateFile,
617         String JavaDoc elementName, Hashtable JavaDoc parameters, String JavaDoc templateSelector) throws CmsException {
618
619         CmsXmlTemplateFile xmlTemplateDocument = new CmsXmlTemplateFile(cms, templateFile);
620         return xmlTemplateDocument;
621     }
622
623     /**
624      * Gets the path uri.<p>
625      *
626      * @param cms CmsObject Object for accessing system resources.
627      * @param tagcontent Unused in this special case of a user method. Can be ignored.
628      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
629      * @param userObject Hashtable with parameters.
630      * @return String or byte[] with the content of this subelement.
631      * @throws CmsException if something goes wrong
632      */

633     public Object JavaDoc getPathUri(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
634         Object JavaDoc userObject) throws CmsException {
635
636         String JavaDoc path = cms.getRequestContext().getUri();
637         path = path.substring(0, path.lastIndexOf("/") + 1);
638         path = CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getServletUrl() + path;
639         return path.getBytes();
640     }
641
642     /**
643      * Inserts the value of the given property in the template.
644      * <P>
645      * This method can be called using <code>&lt;METHOD name="getProperty"&gt;</code>
646      * in the template file.
647      *
648      * @param cms CmsObject Object for accessing system resources.
649      * @param tagcontent The name of the property.
650      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
651      * @param userObject Hashtable with parameters.
652      * @return String or byte[] with the content of this subelement.
653      * @throws CmsException if something goes wrong
654      */

655     public Object JavaDoc getProperty(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
656         Object JavaDoc userObject) throws CmsException {
657
658         String JavaDoc requestedUri = cms.getRequestContext().getUri();
659         String JavaDoc value = "";
660         try {
661             value = cms.readProperty(requestedUri, tagcontent);
662         } catch (Exception JavaDoc e) {
663             if (CmsLog.getLog(this).isWarnEnabled()) {
664                 CmsLog.getLog(this).warn("Usermethod getProperty throwed an Exception getting "
665                     + tagcontent, e);
666             }
667         }
668         if (value == null) {
669             value = "";
670         }
671         return value;
672     }
673
674     /**
675      * Inserts the correct servlet path title into the template.
676      * <P>
677      * This method can be called using <code>&lt;METHOD name="getTitle"&gt;</code>
678      * in the template file.
679      *
680      * @param cms CmsObject Object for accessing system resources.
681      * @param tagcontent Unused in this special case of a user method. Can be ignored.
682      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
683      * @param userObject Hashtable with parameters.
684      * @return String or byte[] with the content of this subelement.
685      * @throws CmsException if something goes wrong
686      */

687     public Object JavaDoc getQueryString(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
688         Object JavaDoc userObject) throws CmsException {
689
690         String JavaDoc query = (CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getOriginalRequest()).getQueryString();
691         if (query != null && !"".equals(query)) {
692             query = "?" + query;
693         }
694         return query;
695     }
696
697     /**
698      * Get the IP address of the current request.
699      * <P>
700      * This method can be called using <code>&lt;METHOD name="getRequestIp"&gt;</code>
701      * in the template file.
702      *
703      * @param cms CmsObject Object for accessing system resources.
704      * @param tagcontent Unused in this special case of a user method. Can be ignored.
705      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
706      * @param userObject Hashtable with parameters.
707      * @return String or byte[] with the content of this subelement.
708      * @throws CmsException if something goes wrong
709      */

710     public String JavaDoc getRequestIp(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
711         Object JavaDoc userObject) throws CmsException {
712
713         return (CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getOriginalRequest()).getRemoteAddr();
714     }
715
716     /**
717      * Inserts the correct servlet path title into the template.
718      * <P>
719      * This method can be called using <code>&lt;METHOD name="getTitle"&gt;</code>
720      * in the template file.
721      *
722      * @param cms CmsObject Object for accessing system resources.
723      * @param tagcontent Unused in this special case of a user method. Can be ignored.
724      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
725      * @param userObject Hashtable with parameters.
726      * @return String or byte[] with the content of this subelement.
727      * @throws CmsException if something goes wrong
728      * @deprecated instead of this method you should use the link tag.
729      */

730     public Object JavaDoc getServletPath(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
731         Object JavaDoc userObject) throws CmsException {
732
733         return CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getServletUrl() + "/";
734     }
735
736     /**
737      * Get the session id. If no session exists, a new one will be created.
738      * <P>
739      * This method can be called using <code>&lt;METHOD name="getSessionId"&gt;</code>
740      * in the template file.
741      *
742      * @param cms CmsObject Object for accessing system resources.
743      * @param tagcontent Unused in this special case of a user method. Can be ignored.
744      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
745      * @param userObject Hashtable with parameters.
746      * @return String or byte[] with the content of this subelement.
747      *@throws CmsException if something goes wrong
748      */

749     public String JavaDoc getSessionId(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
750         Object JavaDoc userObject) throws CmsException {
751
752         return (CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getOriginalRequest()).getSession(true).getId();
753     }
754
755     /**
756      * Inserts the correct stylesheet into the layout template.
757      * <P>
758      * This method can be called using <code>&lt;METHOD name="getStylesheet"&gt;</code>
759      * in the template file.
760      * <P>
761      * When using this method follwing parameters should be defined
762      * either in the page file or in the template file:
763      * <ul>
764      * <li><code>root.stylesheet-ie</code></li>
765      * <li><code>root.stylesheet-ns</code></li>
766      * </ul>
767      * These parameters should contain the correct OpenCms path
768      * for the Internet Explorer and Netscape Navigate
769      * specific stylesheets.
770      *
771      * @param cms CmsObject Object for accessing system resources.
772      * @param tagcontent Unused in this special case of a user method. Can be ignored.
773      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
774      * @param userObject Hashtable with parameters.
775      * @return String or byte[] with the content of this subelement.
776      * @throws CmsException In case no stylesheet was found (or there were errors accessing the CmsObject)
777      */

778     public String JavaDoc getStylesheet(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
779         Object JavaDoc userObject) throws CmsException {
780
781         String JavaDoc styleSheetUri = null;
782         try {
783             styleSheetUri = getStylesheet(cms, tagcontent, null, doc, userObject);
784         } catch (CmsException e) {
785             // Happens if no frametemplate is defined, can be ignored
786
}
787         if ((styleSheetUri == null) || ("".equals(styleSheetUri))) {
788             styleSheetUri = getStylesheet(cms, tagcontent, "frametemplate", doc, userObject);
789         } // The original behaviour is to throw an exception in case no stylesheed could be found
790
if (styleSheetUri == null) {
791             styleSheetUri = "";
792         }
793         return styleSheetUri;
794     }
795
796     /**
797      * Inserts the document title into the template.
798      * <P>
799      * This method can be called using <code>&lt;METHOD name="getTitle"&gt;</code>
800      * in the template file.
801      *
802      * @param cms CmsObject Object for accessing system resources.
803      * @param tagcontent Unused in this special case of a user method. Can be ignored.
804      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
805      * @param userObject Hashtable with parameters.
806      * @return String or byte[] with the content of this subelement.
807      * @throws CmsException if something goes wrong
808      */

809     public Object JavaDoc getTitle(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc, Object JavaDoc userObject)
810     throws CmsException {
811
812         String JavaDoc requestedUri = cms.getRequestContext().getUri();
813         String JavaDoc title = cms.readProperty(requestedUri, CmsPropertyDefinition.PROPERTY_TITLE);
814         if (title == null) {
815             return "";
816         }
817         return title;
818     }
819
820     /**
821      * Inserts the document title into the template, escaping special and non - ASCII characters
822      * with their HTML number representation (e.g. &amp; becomes &amp;#38;).<p>
823      *
824      * This method can be called using <code>&lt;METHOD name="getTitleEscaped"&gt;</code>
825      * in the template file.
826      *
827      * @param cms CmsObject Object for accessing system resources.
828      * @param tagcontent Unused in this special case of a user method. Can be ignored.
829      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
830      * @param userObject Hashtable with parameters.
831      * @return String or byte[] with the content of this subelement.
832      * @throws CmsException if something goes wrong
833      */

834     public Object JavaDoc getTitleEscaped(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
835         Object JavaDoc userObject) throws CmsException {
836
837         String JavaDoc requestedUri = cms.getRequestContext().getUri();
838         String JavaDoc title = cms.readProperty(requestedUri, CmsPropertyDefinition.PROPERTY_TITLE);
839         if (title == null) {
840             return "";
841         }
842         return CmsEncoder.escapeHtml(title);
843     }
844
845     /**
846      * @param cms CmsObject Object for accessing system resources.
847      * @param tagcontent May contain the parameter for framesets to work in the static export.
848      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
849      * @param userObj Hashtable with parameters.
850      * @return String or byte[] with the content of this subelement.
851      * @throws CmsException
852      */

853     public Object JavaDoc getUri(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc, Object JavaDoc userObject)
854     throws CmsException {
855
856         String JavaDoc res = cms.getRequestContext().getUri();
857         if (tagcontent == null || "".equals(tagcontent)) {
858             return OpenCms.getLinkManager().substituteLink(cms, res).getBytes();
859         } else {
860             return OpenCms.getLinkManager().substituteLink(cms, res + "?" + tagcontent).getBytes();
861         }
862     }
863
864     /**
865      * @param cms CmsObject Object for accessing system resources.
866      * @param tagcontent Contains the parameter for framesets.
867      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
868      * @param userObj Hashtable with parameters.
869      * @return String or byte[] with the content of this subelement.
870      * @throws CmsException
871      */

872     public Object JavaDoc getUriWithParameter(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
873         Object JavaDoc userObject) throws CmsException {
874
875         String JavaDoc query = new String JavaDoc();
876         // get the parameternames of the original request and get the values from the userObject
877
try {
878             Enumeration JavaDoc parameters = ((HttpServletRequest JavaDoc)CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getOriginalRequest()).getParameterNames();
879             StringBuffer JavaDoc paramQuery = new StringBuffer JavaDoc();
880             while (parameters.hasMoreElements()) {
881                 String JavaDoc name = (String JavaDoc)parameters.nextElement();
882                 String JavaDoc value = (String JavaDoc)((Hashtable JavaDoc)userObject).get(name);
883                 if (value != null && !"".equals(value)) {
884                     paramQuery.append(name + "=" + value + "&");
885                 }
886             }
887             if (paramQuery.length() > 0) {
888                 // add the parameters to the query string
889
query = paramQuery.substring(0, paramQuery.length() - 1).toString();
890             }
891         } catch (Exception JavaDoc exc) {
892             exc.printStackTrace();
893         }
894
895         // get the parameters in the tagcontent
896
if ((tagcontent != null) && (!"".equals(tagcontent))) {
897             if (tagcontent.startsWith("?")) {
898                 tagcontent = tagcontent.substring(1);
899             }
900             query = tagcontent + "&" + query;
901         }
902         return getUri(cms, query, doc, userObject);
903     }
904
905     /**
906      * Indicates if the current template class is able to stream it's results
907      * directly to the response oputput stream.
908      * <P>
909      * Classes must not set this feature, if they might throw special
910      * exception that cause HTTP errors (e.g. 404/Not Found), or if they
911      * might send HTTP redirects.
912      * <p>
913      * If a class sets this feature, it has to check the
914      * isStreaming() property of the RequestContext. If this is set
915      * to <code>true</code> the results must be streamed directly
916      * to the output stream. If it is <code>false</code> the results
917      * must not be streamed.
918      * <P>
919      * Complex classes that are able top include other subtemplates
920      * have to check the streaming ability of their subclasses here!
921      *
922      * @param cms CmsObject Object for accessing system resources
923      * @param templateFile Filename of the template file
924      * @param elementName Element name of this template in our parent template.
925      * @param parameters Hashtable with all template class parameters.
926      * @param templateSelector template section that should be processed.
927      * @return <EM>true</EM> if this class may stream it's results, <EM>false</EM> otherwise.
928      */

929     public boolean isStreamable(CmsObject cms, String JavaDoc templateFile, String JavaDoc elementName,
930         Hashtable JavaDoc parameters, String JavaDoc templateSelector) {
931
932         return true;
933     }
934
935     /**
936      * Tests, if the template cache is setted.
937      * @return <code>true</code> if setted, <code>false</code> otherwise.
938      */

939     public final boolean isTemplateCacheSet() {
940
941         return m_cache != null;
942     }
943
944     /**
945      * Returns the absolute path of a resource merged with the absolute path of the file and
946      * the relative path in the tagcontent. This path is a intern OpenCms path (i.e. it starts
947      * with a "/" ).
948      *
949      * @param cms CmsObject Object for accessing system resources.
950      * @param tagcontent The relative path of the resource incl. name of the resource.
951      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
952      * @param userObject Hashtable with parameters.
953      * @return String or byte[] with the content of this subelement.
954      * @throws CmsException if something goes wrong
955      */

956     public Object JavaDoc mergeAbsolutePath(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
957         Object JavaDoc userObject) throws CmsException {
958
959         return CmsLinkManager.getAbsoluteUri(tagcontent, doc.getAbsoluteFilename()).getBytes();
960     }
961
962     /**
963      * Returns the absolute path of a resource merged with the absolute path of the file and
964      * the relative path in the tagcontent. This method adds the servlet path at the beginning
965      * of the path.
966      *
967      * @param cms CmsObject Object for accessing system resources.
968      * @param tagcontent The relative path of the resource incl. name of the resource.
969      * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
970      * @param userObject Hashtable with parameters.
971      * @return String or byte[] with the content of this subelement.
972      * @throws CmsException if something goes wrong
973      */

974     public Object JavaDoc mergeAbsoluteUrl(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
975         Object JavaDoc userObject) throws CmsException {
976
977         String JavaDoc ocPath = new String JavaDoc((byte[])mergeAbsolutePath(cms, tagcontent, doc, userObject));
978         String JavaDoc servletPath = CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getServletUrl();
979         return (servletPath + ocPath).getBytes();
980     }
981
982     /**
983      * For debugging purposes only.
984      * Prints out all parameters.
985      * <P>
986      * May be called from the template file using
987      * <code>&lt;METHOD name="parameters"&gt;</code>.
988      *
989      * @param cms CmsObject Object for accessing system resources.
990      * @param tagcontent Unused in this special case of a user method. Can be ignored.
991      * @param doc Reference to the A_CmsXmlContent object the initiating XLM document.
992      * @param userObj Hashtable with parameters.
993      * @return Debugging information about all parameters.
994      */

995     public String JavaDoc parameters(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
996         Object JavaDoc userObject) {
997
998         Hashtable JavaDoc param = (Hashtable JavaDoc)userObject;
999         Enumeration JavaDoc keys = param.keys();
1000        String JavaDoc s = "";
1001        while (keys.hasMoreElements()) {
1002            String JavaDoc key = (String JavaDoc)keys.nextElement();
1003            s = s + "<B>" + key + "</B>: " + param.get(key) + "<BR>";
1004        }
1005        s = s + "<B>" + tagcontent + "</B><BR>";
1006        return s;
1007    }
1008
1009    public Object JavaDoc setEncoding(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
1010        Object JavaDoc userObject) throws CmsException {
1011
1012        if ((tagcontent != null) && !"".equals(tagcontent)) {
1013            cms.getRequestContext().setEncoding(tagcontent.trim());
1014        }
1015        return "";
1016    }
1017
1018    /**
1019     * Set the instance of template cache that should be used to store
1020     * cacheable results of the subtemplates.
1021     * If the template cache is not set, caching will be disabled.
1022     * @param c Template cache to be used.
1023     */

1024    public final void setTemplateCache(I_CmsTemplateCache c) {
1025
1026        m_cache = c;
1027    }
1028
1029    /**
1030     * Indicates if a previous cached result should be reloaded.
1031     * <P>
1032     * <em>not implemented.</em> Returns always <code>false</code>.
1033     *
1034     * @param cms CmsObject Object for accessing system resources
1035     * @param templateFile Filename of the template file
1036     * @param elementName Element name of this template in our parent template.
1037     * @param parameters Hashtable with all template class parameters.
1038     * @param templateSelector template section that should be processed.
1039     * @return <code>false</code>
1040     */

1041    public boolean shouldReload(CmsObject cms, String JavaDoc templateFile, String JavaDoc elementName,
1042        Hashtable JavaDoc parameters, String JavaDoc templateSelector) {
1043
1044        return false;
1045    }
1046
1047    /**
1048     * Handles any occurence of an <code>&lt;ELEMENT&gt;</code> tag.
1049     * <P>
1050     * Every XML template class should use CmsXmlTemplateFile as
1051     * the interface to the XML file. Since CmsXmlTemplateFile is
1052     * an extension of A_CmsXmlContent by the additional tag
1053     * <code>&lt;ELEMENT&gt;</code> this user method ist mandatory.
1054     *
1055     * @param cms CmsObject Object for accessing system resources.
1056     * @param tagcontent Unused in this special case of a user method. Can be ignored.
1057     * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
1058     * @param userObj Hashtable with parameters.
1059     * @return String or byte[] with the content of this subelement.
1060     * @throws CmsException
1061     */

1062    public Object JavaDoc templateElement(CmsObject cms, String JavaDoc tagcontent, A_CmsXmlContent doc,
1063        Object JavaDoc userObject) throws CmsException {
1064
1065        // Our own template file that wants to include a subelement
1066
CmsXmlTemplateFile templateFile = (CmsXmlTemplateFile)doc;
1067
1068        // Indicates, if this is a request of a guest user. Needed for error outputs.
1069
boolean isAnonymousUser = cms.getRequestContext().currentUser().isGuestUser();
1070
1071        // First create a copy of the parameter hashtable
1072
Hashtable JavaDoc parameterHashtable = (Hashtable JavaDoc)((Hashtable JavaDoc)userObject).clone();
1073
1074        // Name of the template class that should be used to handle the subtemplate
1075
String JavaDoc templateClass = getTemplateClassName(tagcontent, templateFile, parameterHashtable);
1076
1077        // Name of the subtemplate file.
1078
String JavaDoc templateFilename = CmsLinkManager.getAbsoluteUri(getTemplateFileName(tagcontent, templateFile, parameterHashtable), doc.getAbsoluteFilename());
1079
1080        // Name of the subtemplate template selector
1081
String JavaDoc templateSelector = getTemplateSelector(tagcontent, templateFile, parameterHashtable);
1082
1083        // Results returned by the subtemplate class
1084
byte[] result = null;
1085
1086        // Temporary object for loading the subtemplate class
1087
Object JavaDoc loadedObject = null;
1088
1089        // subtemplate class to be used for the include
1090
I_CmsTemplate subTemplate = null;
1091
1092        // Key for the cache
1093
Object JavaDoc subTemplateKey = null;
1094
1095        // try to load the subtemplate class
1096
try {
1097            loadedObject = CmsTemplateClassManager.getClassInstance(templateClass);
1098        } catch (CmsException e) {
1099
1100            // There was an error. First remove the template file from the file cache
1101
templateFile.removeFromFileCache();
1102            if (isAnonymousUser) {
1103
1104                // The current user is the anonymous user
1105
return C_ERRORTEXT;
1106            } else {
1107                // The current user is a system user, so we throw the exception again.
1108
throw e;
1109            }
1110        }
1111
1112        // Check if the loaded object is really an instance of an OpenCms template class
1113
if (!(loadedObject instanceof I_CmsTemplate)) {
1114            String JavaDoc errorMessage = "Class " + templateClass + " is no OpenCms template class.";
1115            if (CmsLog.getLog(this).isErrorEnabled()) {
1116                CmsLog.getLog(this).error(errorMessage);
1117            }
1118            throw new CmsLegacyException(errorMessage, CmsLegacyException.C_XML_NO_TEMPLATE_CLASS);
1119        }
1120        subTemplate = (I_CmsTemplate)loadedObject;
1121
1122        // Template class is now loaded. Next try to read the parameters
1123
Vector JavaDoc parameterTags = null;
1124        parameterTags = templateFile.getParameterNames(tagcontent);
1125        if (parameterTags != null) {
1126            int numParameterTags = parameterTags.size();
1127            for (int i = 0; i < numParameterTags; i++) {
1128                String JavaDoc paramName = (String JavaDoc)parameterTags.elementAt(i);
1129                String JavaDoc paramValue = templateFile.getParameter(tagcontent, paramName);
1130                if (!parameterHashtable.containsKey(paramName)) {
1131                    parameterHashtable.put(tagcontent + "." + paramName, paramValue);
1132                }
1133            }
1134        }
1135
1136        // all parameters are now parsed. Finally give the own subelement name
1137
// as parameter
1138
parameterHashtable.put(C_ELEMENT, tagcontent);
1139
1140        // Try to get the result from the cache
1141
//if(subTemplate.isCacheable(cms, templateFilename, tagcontent, parameterHashtable, null)) {
1142
if (subTemplate.collectCacheDirectives(cms, templateFilename, tagcontent, parameterHashtable, null).isInternalCacheable()) {
1143            subTemplateKey = subTemplate.getKey(cms, templateFilename, parameterHashtable, null);
1144            if (m_cache != null
1145                && m_cache.has(subTemplateKey)
1146                && (!subTemplate.shouldReload(cms, templateFilename, tagcontent, parameterHashtable, null))) {
1147                result = m_cache.get(subTemplateKey);
1148            }
1149        }
1150
1151        // OK. let's call the subtemplate
1152
if (result == null) {
1153            try {
1154                result = subTemplate.getContent(cms, templateFilename, tagcontent, parameterHashtable, templateSelector);
1155            } catch (Exception JavaDoc e) {
1156
1157                // Oh, oh..
1158

1159                // There were errors while getting the content of the subtemplate
1160
if (CmsLog.getLog(this).isErrorEnabled()) {
1161                    CmsLog.getLog(this).error("Could not generate output for template file \""
1162                        + templateFilename + "\" included as element \"" + tagcontent + "\"", e);
1163                }
1164
1165                // The anonymous user gets an error String instead of an exception
1166
if (isAnonymousUser) {
1167                    return C_ERRORTEXT;
1168                } else {
1169                    if (e instanceof CmsException) {
1170                        throw (CmsException)e;
1171                    } else {
1172                        throw new CmsLegacyException(
1173                            "Error while executing getContent for subtemplate \"" + tagcontent
1174                                + "\". " + e);
1175                    }
1176                }
1177            }
1178
1179            // Store the results in the template cache, if cacheable
1180
//if(subTemplate.isCacheable(cms, templateFilename, tagcontent, parameterHashtable, null)) {
1181
if (subTemplate.collectCacheDirectives(cms, templateFilename, tagcontent, parameterHashtable, null).isInternalCacheable()
1182                && m_cache != null) {
1183
1184                // we don't need to re-get the caching-key here since it already exists
1185
m_cache.put(subTemplateKey, result);
1186            }
1187        }
1188        return new CmsProcessedString(result, cms.getRequestContext().getEncoding());
1189    }
1190
1191    /**
1192     * Find the corresponding template class to be loaded.
1193     * this should be defined in the template file of the parent
1194     * template and can be overwritten in the body file.
1195     *
1196     * @param elementName Element name of this template in our parent template.
1197     * @param doc CmsXmlTemplateFile object of our template file including a subtemplate.
1198     * @param parameters Hashtable with all template class parameters.
1199     * @return Name of the class that should generate the output for the included template file.
1200     * @throws CmsException if something goes wrong
1201     */

1202    protected String JavaDoc getTemplateClassName(String JavaDoc elementName, CmsXmlTemplateFile doc,
1203        Hashtable JavaDoc parameters) throws CmsException {
1204
1205        String JavaDoc result = null;
1206        if (parameters.containsKey(elementName + "._CLASS_")) {
1207            result = (String JavaDoc)parameters.get(elementName + "._CLASS_");
1208        } else {
1209            if (doc.hasSubtemplateClass(elementName)) {
1210                result = doc.getSubtemplateClass(elementName);
1211            } else {
1212
1213                // Fallback to "body" element
1214
if (parameters.containsKey("body._CLASS_")) {
1215                    result = (String JavaDoc)parameters.get("body._CLASS_");
1216                }
1217            }
1218        }
1219        if (result == null) {
1220            CmsElementDefinitionCollection elDefs = (CmsElementDefinitionCollection)parameters.get("_ELDEFS_");
1221            if (elDefs != null) {
1222                CmsElementDefinition elDef = elDefs.get(elementName);
1223                if (elDef != null) {
1224                    result = elDef.getClassName();
1225                }
1226            }
1227        }
1228        return result;
1229    }
1230
1231    /**
1232     * Find the corresponding template file to be loaded by the template class.
1233     * this should be defined in the template file of the parent
1234     * template and can be overwritten in the body file.
1235     *
1236     * @param elementName Element name of this template in our parent template.
1237     * @param doc CmsXmlTemplateFile object of our template file including a subtemplate.
1238     * @param parameters Hashtable with all template class parameters.
1239     * @return Name of the template file that should be included.
1240     * @throws CmsException if something goes wrong
1241     */

1242    protected String JavaDoc getTemplateFileName(String JavaDoc elementName, CmsXmlTemplateFile doc,
1243        Hashtable JavaDoc parameters) throws CmsException {
1244
1245        String JavaDoc result = null;
1246        if (parameters.containsKey(elementName + "._TEMPLATE_")) {
1247            result = (String JavaDoc)parameters.get(elementName + "._TEMPLATE_");
1248        } else {
1249            if (doc.hasSubtemplateFilename(elementName)) {
1250                result = doc.getSubtemplateFilename(elementName);
1251            } else {
1252                // Fallback to "body" element
1253
if (parameters.containsKey("body._TEMPLATE_")) {
1254                    result = (String JavaDoc)parameters.get("body._TEMPLATE_");
1255                }
1256            }
1257        }
1258        if (result == null) {
1259            CmsElementDefinitionCollection elDefs = (CmsElementDefinitionCollection)parameters.get("_ELDEFS_");
1260            if (elDefs != null) {
1261                CmsElementDefinition elDef = elDefs.get(elementName);
1262                if (elDef != null) {
1263                    result = elDef.getTemplateName();
1264                }
1265            }
1266        }
1267        return result;
1268    }
1269
1270    /**
1271     * Find the corresponding template selector to be activated.
1272     * This may be defined in the template file of the parent
1273     * template and can be overwritten in the body file.
1274     *
1275     * @param elementName Element name of this template in our parent template.
1276     * @param doc CmsXmlTemplateFile object of our template file including a subtemplate.
1277     * @param parameters Hashtable with all template class parameters.
1278     * @return Name of the class that should generate the output for the included template file.
1279     * @throws CmsException if something goes wrong
1280     */

1281    protected String JavaDoc getTemplateSelector(String JavaDoc elementName, CmsXmlTemplateFile doc,
1282        Hashtable JavaDoc parameters) throws CmsException {
1283
1284        if (parameters.containsKey(elementName + "._TEMPLATESELECTOR_")) {
1285            return (String JavaDoc)parameters.get(elementName + "._TEMPLATESELECTOR_");
1286        } else {
1287            if (doc.hasSubtemplateSelector(elementName)) {
1288                return doc.getSubtemplateSelector(elementName);
1289            } else {
1290                CmsElementDefinitionCollection elDefs = (CmsElementDefinitionCollection)parameters.get("_ELDEFS_");
1291                if (elDefs != null) {
1292                    CmsElementDefinition elDef = elDefs.get(elementName);
1293                    if (elDef != null) {
1294                        return elDef.getTemplateSelector();
1295                    }
1296                }
1297                return null;
1298            }
1299        }
1300    }
1301
1302    /**
1303     * Saves the dependencies for this elementvariante.
1304     * We save the deps two ways.
1305     * First we have an so called extern Hashtable where we use as key a resource
1306     * (represented by a String) and as values an Vector with all ElementVariants
1307     * that depend on this resource (again represented by a String in which we save
1308     * the variant and the element it is in)
1309     * The second saveplace is the elementvariant itselv. The intern way to save.
1310     * There we store which resoucess affect this variant.
1311     *
1312     * @param cms The cms object.
1313     * @param templateName.
1314     * @param elementName only needed for getCachDirectives, if it is not used there it may be null
1315     * @param templateSelector only needed for getCachDirectives, if it is not used there it may be null
1316     * @param parameters.
1317     * @param vfsDeps A vector (of CmsResource objects) with the resources that variant depends on.
1318     * @param cosDeps A vector (of CmsContentDefinitions) with the cd-resources that variant depends on.
1319     * @param cosClassDeps A vector (of Class objects) with the contentdefinitions that variant depends on.
1320     */

1321    protected void registerVariantDeps(CmsObject cms, String JavaDoc templateName, String JavaDoc elementName,
1322        String JavaDoc templateSelector, Hashtable JavaDoc parameters, Vector JavaDoc vfsDeps, Vector JavaDoc cosDeps,
1323        Vector JavaDoc cosClassDeps) throws CmsException {
1324
1325        String JavaDoc cacheKey = getCacheDirectives(cms, templateName, elementName, parameters, templateSelector).getCacheKey(cms, parameters);
1326        if (CmsXmlTemplateLoader.isElementCacheEnabled() && (cacheKey != null)
1327            && (cms.getRequestContext().currentProject().isOnlineProject())) {
1328            boolean exportmode = false;
1329            Hashtable JavaDoc externVarDeps = CmsXmlTemplateLoader.getVariantDependencies();
1330            long exTimeForVariant = Long.MAX_VALUE;
1331            long now = System.currentTimeMillis();
1332            // this will be the entry for the extern hashtable
1333
String JavaDoc variantEntry = getClass().getName() + "|" + templateName + "|" + cacheKey;
1334
1335            // the vector for the intern variant store. it contains the keys for the extern Hashtable
1336
Vector JavaDoc allDeps = new Vector JavaDoc();
1337            // first the dependencies for the cos system
1338
if (cosDeps != null) {
1339                for (int i = 0; i < cosDeps.size(); i++) {
1340                    A_CmsContentDefinition contentDef = (A_CmsContentDefinition)cosDeps.elementAt(i);
1341                    String JavaDoc key = cms.getRequestContext().addSiteRoot(contentDef.getClass().getName()
1342                        + "/" + contentDef.getUniqueId(cms));
1343                    // if(exportmode){
1344
// cms.getRequestContext().addDependency(key);
1345
// }
1346
allDeps.add(key);
1347                    if (contentDef.isTimedContent()) {
1348                        long time = ((I_CmsTimedContentDefinition)cosDeps.elementAt(i)).getPublicationDate();
1349                        if (time > now && time < exTimeForVariant) {
1350                            exTimeForVariant = time;
1351                        }
1352                        time = ((I_CmsTimedContentDefinition)cosDeps.elementAt(i)).getPurgeDate();
1353                        if (time > now && time < exTimeForVariant) {
1354                            exTimeForVariant = time;
1355                        }
1356                        time = ((I_CmsTimedContentDefinition)cosDeps.elementAt(i)).getAdditionalChangeDate();
1357                        if (time > now && time < exTimeForVariant) {
1358                            exTimeForVariant = time;
1359                        }
1360                    }
1361                }
1362            }
1363            // // now for the Classes
1364
// if(cosClassDeps != null){
1365
// for(int i=0; i<cosClassDeps.size(); i++){
1366
// String key = cms.getRequestContext().addSiteRoot(((Class)cosClassDeps.elementAt(i)).getName() + "/");
1367
// allDeps.add(key);
1368
// if(exportmode){
1369
// cms.getRequestContext().addDependency(key);
1370
// }
1371
// }
1372
// }
1373
// now for the vfs
1374
// if(vfsDeps != null){
1375
// for(int i = 0; i < vfsDeps.size(); i++){
1376
// allDeps.add(((CmsResource)vfsDeps.elementAt(i)).getName());
1377
// if(exportmode){
1378
// cms.getRequestContext().addDependency(((CmsResource)vfsDeps.elementAt(i)).getName());
1379
// }
1380
// }
1381
// }
1382
// now put them all in the extern store
1383
for (int i = 0; i < allDeps.size(); i++) {
1384                String JavaDoc key = (String JavaDoc)allDeps.elementAt(i);
1385                Vector JavaDoc variantsForDep = (Vector JavaDoc)externVarDeps.get(key);
1386                if (variantsForDep == null) {
1387                    variantsForDep = new Vector JavaDoc();
1388                }
1389                if (!variantsForDep.contains(variantEntry)) {
1390                    variantsForDep.add(variantEntry);
1391                }
1392                externVarDeps.put(key, variantsForDep);
1393            }
1394            // at last we have to fill the intern store. that means we have to
1395
// put the alldeps vector in our variant that will be created later
1396
// in the startproccessing method.
1397
// Get current element.
1398
CmsElementCache elementCache = CmsXmlTemplateLoader.getElementCache();
1399            CmsElementDescriptor elKey = new CmsElementDescriptor(getClass().getName(),
1400                templateName);
1401            A_CmsElement currElem = elementCache.getElementLocator().get(cms, elKey, parameters);
1402            // add an empty variant with the vector to the element
1403
CmsElementVariant emptyVar = new CmsElementVariant();
1404            emptyVar.addDependencies(allDeps);
1405            if (exTimeForVariant < Long.MAX_VALUE) {
1406                emptyVar.mergeNextTimeout(exTimeForVariant);
1407            }
1408            Vector JavaDoc removedVar = currElem.addVariant(cacheKey, emptyVar);
1409            if ((removedVar != null)) {
1410                // adding a new variant deleted this variant so we have to update the extern store
1411
String JavaDoc key = (String JavaDoc)removedVar.firstElement();
1412                CmsElementVariant oldVar = (CmsElementVariant)removedVar.lastElement();
1413                Vector JavaDoc oldVarDeps = oldVar.getDependencies();
1414                if (oldVarDeps != null) {
1415                    String JavaDoc oldVariantEntry = getClass().getName() + "|" + templateName + "|" + key;
1416                    for (int i = 0; i < oldVarDeps.size(); i++) {
1417                        Vector JavaDoc externEntrys = (Vector JavaDoc)externVarDeps.get(oldVarDeps.elementAt(i));
1418                        if (externEntrys != null) {
1419                            externEntrys.removeElement(oldVariantEntry);
1420                        }
1421                    }
1422                }
1423            }
1424            // mark this element so it wont be deleted without updating the extern store
1425
currElem.thisElementHasDepVariants();
1426
1427        }
1428    }
1429
1430    /**
1431     * Starts the processing of the given template file by calling the
1432     * <code>getProcessedTemplateContent()</code> method of the content defintition
1433     * of the corresponding content type.
1434     * <P>
1435     * Any exceptions thrown while processing the template will be caught,
1436     * printed and and thrown again.
1437     * <P>
1438     * If element cache is enabled, <code>generateElementCacheVariant()</code>
1439     * will be called instead of <code>getProcessedTemplateContent()</code> for
1440     * generating a new element cache variant instead of the completely
1441     * processed output data.
1442     * This new variant will be stored in the current element using the cache key
1443     * given by the cache directives.
1444     *
1445     * @param cms CmsObject Object for accessing system resources.
1446     * @param xmlTemplateDocument XML parsed document of the content type "XML template file" or
1447     * any derived content type.
1448     * @param elementName Element name of this template in our parent template.
1449     * @param parameters Hashtable with all template class parameters.
1450     * @param templateSelector template section that should be processed.
1451     * @return Content of the template and all subtemplates.
1452     * @throws CmsException
1453     */

1454    protected byte[] startProcessing(CmsObject cms, CmsXmlTemplateFile xmlTemplateDocument,
1455        String JavaDoc elementName, Hashtable JavaDoc parameters, String JavaDoc templateSelector) throws CmsException {
1456
1457        byte[] result = null;
1458
1459        if (CmsXmlTemplateLoader.isElementCacheEnabled()) {
1460            CmsElementDefinitionCollection mergedElDefs = (CmsElementDefinitionCollection)parameters.get("_ELDEFS_");
1461            // We are in element cache mode. Create a new variant instead of a completely processed subtemplate
1462
CmsElementVariant variant = xmlTemplateDocument.generateElementCacheVariant(this, parameters, elementName, templateSelector);
1463            // Get current element.
1464
CmsElementCache elementCache = CmsXmlTemplateLoader.getElementCache();
1465            CmsElementDescriptor elKey = new CmsElementDescriptor(getClass().getName(),
1466                xmlTemplateDocument.getAbsoluteFilename());
1467            A_CmsElement currElem = elementCache.getElementLocator().get(cms, elKey, parameters);
1468
1469            // If this elemement is cacheable, store the new variant
1470
if (currElem.getCacheDirectives().isInternalCacheable()) {
1471                //currElem.addVariant(getKey(cms, xmlTemplateDocument.getAbsoluteFilename(), parameters, templateSelector), variant);
1472
Vector JavaDoc removedVar = currElem.addVariant(currElem.getCacheDirectives().getCacheKey(cms, parameters), variant);
1473                if ((removedVar != null) && currElem.hasDependenciesVariants()) {
1474                    // adding a new variant deleted this variant so we have to update the extern dependencies store
1475
String JavaDoc key = (String JavaDoc)removedVar.firstElement();
1476                    CmsElementVariant oldVar = (CmsElementVariant)removedVar.lastElement();
1477                    Vector JavaDoc oldVarDeps = oldVar.getDependencies();
1478                    if (oldVarDeps != null) {
1479                        String JavaDoc oldVariantEntry = getClass().getName() + "|"
1480                            + xmlTemplateDocument.getAbsoluteFilename() + "|" + key;
1481                        for (int i = 0; i < oldVarDeps.size(); i++) {
1482                            Vector JavaDoc externEntrys = (Vector JavaDoc)CmsXmlTemplateLoader.getVariantDependencies().get(oldVarDeps.elementAt(i));
1483                            if (externEntrys != null) {
1484                                externEntrys.removeElement(oldVariantEntry);
1485                            }
1486                        }
1487                    }
1488                }
1489            }
1490            result = ((CmsElementXml)currElem).resolveVariant(cms, variant, elementCache, mergedElDefs, parameters);
1491        } else {
1492            // Classic way. Element cache is not activated, so let's genereate the template as usual
1493
// Try to process the template file
1494
try {
1495                result = xmlTemplateDocument.getProcessedTemplateContent(this, parameters, templateSelector).getBytes(cms.getRequestContext().getEncoding());
1496            } catch (Throwable JavaDoc e) {
1497                // There were errors while generating output for this template.
1498
// Clear HTML cache and then throw exception again
1499
xmlTemplateDocument.removeFromFileCache();
1500                if (isCacheable(cms, xmlTemplateDocument.getAbsoluteFilename(), elementName, parameters, templateSelector)) {
1501                    m_cache.clearCache(getKey(cms, xmlTemplateDocument.getAbsoluteFilename(), parameters, templateSelector));
1502                }
1503                if (e instanceof CmsException) {
1504                    throw (CmsException)e;
1505                } else {
1506                    // under normal cirumstances, this should not happen.
1507
// any exception should be caught earlier and replaced by
1508
// corresponding CmsExceptions.
1509
String JavaDoc errorMessage = "Exception while getting content for (sub)template "
1510                        + elementName + ". " + e;
1511                    if (CmsLog.getLog(this).isErrorEnabled()) {
1512                        CmsLog.getLog(this).error(errorMessage, e);
1513                    }
1514                    throw new CmsLegacyException(errorMessage);
1515                }
1516            }
1517        }
1518        // update the template selector if nescessary
1519
if (templateSelector != null) {
1520            parameters.put(elementName + "._TEMPLATESELECTOR_", templateSelector);
1521        }
1522
1523        return result;
1524    }
1525
1526    /**
1527     * Help method that handles any occuring error by writing
1528     * an error message to the OpenCms logfile and throwing a
1529     * CmsException of the type "unknown".
1530     * @param errorMessage String with the error message to be printed.
1531     * @throws CmsException
1532     */

1533    protected void throwException(String JavaDoc errorMessage) throws CmsException {
1534
1535        throwException(errorMessage, CmsLegacyException.C_UNKNOWN_EXCEPTION);
1536    }
1537
1538    /**
1539     * Help method that handles any occuring error by writing
1540     * an error message to the OpenCms logfile and re-throwing a
1541     * caught exception.
1542     * @param errorMessage String with the error message to be printed.
1543     * @param e Exception to be re-thrown.
1544     * @throws CmsException
1545     */

1546    protected void throwException(String JavaDoc errorMessage, Exception JavaDoc e) throws CmsException {
1547
1548        if (CmsLog.getLog(this).isErrorEnabled()) {
1549            CmsLog.getLog(this).error(errorMessage, e);
1550        }
1551        if (e instanceof CmsException) {
1552            throw (CmsException)e;
1553        } else {
1554            throw new CmsLegacyException(errorMessage, CmsLegacyException.C_UNKNOWN_EXCEPTION, e);
1555        }
1556    }
1557
1558    /**
1559     * Help method that handles any occuring error by writing
1560     * an error message to the OpenCms logfile and throwing a
1561     * CmsException of the given type.
1562     * @param errorMessage String with the error message to be printed.
1563     * @param type Type of the exception to be thrown.
1564     * @throws CmsLegacyException
1565     */

1566    protected void throwException(String JavaDoc errorMessage, int type) throws CmsLegacyException {
1567
1568        if (CmsLog.getLog(this).isErrorEnabled()) {
1569            CmsLog.getLog(this).error(errorMessage);
1570        }
1571        throw new CmsLegacyException(errorMessage, type);
1572    }
1573
1574    /**
1575     * Internal method to do the actual lookup of the "stylesheet" tag
1576     * on the subtemplate / element specified.
1577     *
1578     * @param cms CmsObject Object for accessing system resources.
1579     * @param tagcontent Unused in this special case of a user method. Can be ignored.
1580     * @param templatename The subtemplate / element to look up the "stylesheet" tag
1581     * in, if null the mastertemplate is used.
1582     * @param doc Reference to the A_CmsXmlContent object of the initiating XLM document.
1583     * @param userObj Hashtable with parameters.
1584     * @return String or byte[] with the content of this subelement.
1585     * @throws CmsException In case no stylesheet was found (or there were errors accessing the CmsObject)
1586     */

1587    private String JavaDoc getStylesheet(CmsObject cms, String JavaDoc tagcontent, String JavaDoc templatename,
1588        A_CmsXmlContent doc, Object JavaDoc userObject) throws CmsException {
1589
1590        CmsXmlTemplateFile tempTemplateFile = (CmsXmlTemplateFile)doc;
1591
1592        // If templatename==null look in the master template
1593
CmsXmlTemplateFile templateFile = tempTemplateFile;
1594
1595        if (templatename != null) {
1596            // Get the XML parsed content of the selected template file.
1597
// This can be done by calling the getOwnTemplateFile() method of the
1598
// mastertemplate class.
1599
// The content is needed to determine the HTML style of the body element.
1600
Object JavaDoc tempObj = CmsTemplateClassManager.getClassInstance(tempTemplateFile.getSubtemplateClass(templatename));
1601            CmsXmlTemplate frameTemplateClassObject = (CmsXmlTemplate)tempObj;
1602            templateFile = frameTemplateClassObject.getOwnTemplateFile(cms, tempTemplateFile.getSubtemplateFilename(templatename), null, null, null);
1603        }
1604
1605        // Get the styles from the parameter hashtable
1606
String JavaDoc styleIE = null;
1607        String JavaDoc styleNS = null;
1608        if (templateFile.hasData("stylesheet-ie")) {
1609            styleIE = templateFile.getDataValue("stylesheet-ie");
1610        } else {
1611            if (templateFile.hasData("stylesheet")) {
1612                styleIE = templateFile.getDataValue("stylesheet");
1613            } else {
1614                styleIE = "";
1615            }
1616        }
1617        if (templateFile.hasData("stylesheet-ns")) {
1618            styleNS = templateFile.getDataValue("stylesheet-ns");
1619        } else {
1620            if (templateFile.hasData("stylesheet")) {
1621                styleNS = templateFile.getDataValue("stylesheet");
1622            } else {
1623                styleNS = "";
1624            }
1625        }
1626
1627        HttpServletRequest JavaDoc orgReq = CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getOriginalRequest();
1628        String JavaDoc servletPath = CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getServletUrl();
1629        if (!servletPath.endsWith("/")) {
1630            // Make sure servletPath always end's with a "/"
1631
servletPath = CmsXmlTemplateLoader.getRequest(cms.getRequestContext()).getServletUrl()
1632                + "/";
1633        }
1634
1635        // Make sure we don't have a double "/" in the style sheet path
1636
if (styleIE.startsWith("/")) {
1637            styleIE = styleIE.substring(1);
1638        }
1639        if (styleNS.startsWith("/")) {
1640            styleNS = styleNS.substring(1);
1641        }
1642
1643        // Get the user's browser
1644
String JavaDoc browser = orgReq.getHeader("user-agent");
1645        if ((browser != null) && (browser.indexOf("MSIE") > -1)) {
1646            return ("".equals(styleIE)) ? "" : servletPath + styleIE;
1647        } else {
1648            // return NS style as default value
1649
return ("".equals(styleNS)) ? "" : servletPath + styleNS;
1650        }
1651
1652    }
1653}
1654
Popular Tags