KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > opencms > defaults > CmsShowContent


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

24
25 package com.opencms.defaults;
26
27 import org.opencms.file.CmsObject;
28 import org.opencms.main.CmsException;
29 import org.opencms.main.CmsLog;
30
31 import com.opencms.legacy.CmsLegacyException;
32 import com.opencms.template.A_CmsXmlContent;
33 import com.opencms.template.CmsCacheDirectives;
34 import com.opencms.template.CmsXmlTemplate;
35 import com.opencms.template.CmsXmlTemplateFile;
36
37 import java.lang.reflect.Constructor JavaDoc;
38 import java.lang.reflect.InvocationTargetException JavaDoc;
39 import java.lang.reflect.Method JavaDoc;
40 import java.util.ArrayList JavaDoc;
41 import java.util.Hashtable JavaDoc;
42 import java.util.StringTokenizer JavaDoc;
43 import java.util.Vector JavaDoc;
44
45 /**
46  * Generic class for showing information encapsulated by contentdefinition objects.
47  * There are mainly two user methods in this template class for this purpose:
48  * getEntry and getList. The getEntry method accepts an id or read it from
49  * the url parameters (it has to be named id to be found) if given
50  * and set datablocks inside the template with
51  * values returned by all public get-methods of the contentdefinition that
52  * returns a String and have no parameters. This method must be called in the
53  * template before acccessing any of this data with process tags.
54  * The getList method builds a list of contentdefinition entries. It invokes
55  * a filtermethod defined inside a datablock named <filtermethod>.
56  * The user parameter of type String passed to the filtermethod is taken from
57  * the url parameters or from a default value. The getList method accepts a name
58  * and a defaut value in a comma seperated String in this way : name, defaultvalue.
59  * The entrys for the list will be filled by appending a processed datablock
60  * with the name listentry. Every get-method will be invoked for every entry
61  * unless a tag named <method> is given where a commaseperated list of
62  * exactly typed get-method names can be given that results in invoking only
63  * this methods (for performance improvement if not all values are needed and
64  * many get-methods are given). The filtermethod is assumed to have the following
65  * signature: filtermehodname(CmsObject, String). If one wants to use filtermethods
66  * with other signatures he has to derive from this class and override the
67  * method invokeFilterMethod where the filtermethod is actually invoked.
68  * For both methods the fully qualified classname of the contentdefinition
69  * has to be stated in a datablock with the name <contentdefinition_class>.
70  * Note: the method getUniqueId(CmsObject) will be invoked for the contentdefinition
71  * class in any case, and the datablock uniqueid can be used in the template to refer
72  * to the id of an contentdefinition object
73  * @author Michael Dernen
74  *
75  * changed: the tagcontent parameter for getList may only use filterparameter0 to
76  * filterparameter9.
77  *
78  * @deprecated Will not be supported past the OpenCms 6 release.
79  */

80 public class CmsShowContent extends CmsXmlTemplate {
81
82     /**
83      * The name of the datablock containing the contentdefinition's fully qualified classname.
84      */

85      protected static final String JavaDoc C_CONTENTDEFINITION_CLASS_DATABLOCK =
86         "contentdefinition_class";
87
88     /**
89      * The name of the datablock containing the name of the filtermethod to use.
90      */

91      protected static final String JavaDoc C_FILTERMETHOD_DATABLOCK =
92         "filtermethod";
93
94     /**
95      * replaces the tagcontent for usermethod "getList"
96      */

97     protected static final String JavaDoc C_FILTER_PARAMETERS_START = "filterparameter";
98
99     /**
100      * The name of the datablock to define which get-methods to invoke.
101      * If a datablock with this name is not given all get-methods will be invoked.
102      */

103      protected static final String JavaDoc C_METHODS_TO_USE_DATABLOCK =
104         "methods";
105
106     /**
107      * The name of the datablock to define a listentry.
108      */

109      protected static final String JavaDoc C_LISTENTRY_DATABLOCK = "listentry";
110
111      /**
112      * Error message for a missing id parameter.
113      */

114      protected static final String JavaDoc C_MISSING_ID_PARAMETER =
115         "Missing id parameter: "
116         + "You have to provide a parameter id (as tagcontent or url parameter) to specify the "
117         + "dataentry you want to show";
118
119     /**
120      * Error message if the constructor in case the contentdefinition class throws an exception.
121      */

122      protected static final String JavaDoc C_CONSTRUCTOR_THROWED_EXCEPTION =
123         "Failed to create contentdefinition object: "
124         + "The constructor of the contentdefinition class throwed an exception";
125
126     /**
127      * Error message in case the constructor is not a subclass of A_CmsContentDefinition.
128      */

129      protected static final String JavaDoc C_CONSTRUCTOR_IS_NOT_SUBCLASS_OF_A_CMSCONTENTDEFINITION =
130         "Your contentdefinition class is not a subclass of the abstract A_CmsContentDefinition class";
131
132     /**
133      * Error message in case a non-numerical id parameter is given.
134      */

135      protected static final String JavaDoc C_NON_NUMERICAL_ID_PARAMETER =
136         "The parameter id is not a numerical value";
137
138     /**
139     * Error text that will be set inside the template if a get-method throws an exception.
140     */

141     protected static final String JavaDoc C_ERROR_TEXT = "ERROR";
142
143     /**
144      * The name of the id parameter.
145      */

146      protected static final String JavaDoc C_ID_PARAMETER = "id";
147
148     /**
149      * Usermethod to fill template datablocks with values of a contentdefinition's get-methods.
150      * @param cms CmsObject Object for accessing system resources.
151      * @param tagcontent the tagcontent passed to the method. This can be an id
152      * value which will be used if the parameter id is not found parameters passed
153      * with the request (url parameters).
154      * @param doc reference to the A_CmsXmlContent object of the initiating XLM document
155      * @param userObject normally the Hashtable with the url parameters
156      * @return String or byte[] with the content of this subelement
157      * @throws org.opencms.main.CmsException in case of unrecoverable errors
158      */

159     public Object JavaDoc getEntry(CmsObject cms, String JavaDoc tagcontent,
160             A_CmsXmlContent doc, Object JavaDoc userObject) throws CmsException {
161
162         CmsXmlTemplateFile template = (CmsXmlTemplateFile)doc;
163
164         String JavaDoc paramId = null;
165         if (tagcontent != null && !tagcontent.trim().equals("")) {
166             // if a tagcontent is given take it as the id of the entry to be shown
167
paramId = tagcontent;
168         } else {
169             // get the id of the entry to be shown from the url parameters
170
paramId = (String JavaDoc)((Hashtable JavaDoc)userObject).get(C_ID_PARAMETER);
171         }
172         Integer JavaDoc id = null;
173         if (paramId != null) {
174             // try to convert the id to an Integer object
175
try {
176                 id = new Integer JavaDoc(paramId);
177             } catch (NumberFormatException JavaDoc e) {
178                 // throw exception if the id is not numeric
179
throw new CmsLegacyException(C_NON_NUMERICAL_ID_PARAMETER, CmsLegacyException.C_UNKNOWN_EXCEPTION);
180             }
181         } else {
182             // throw exception if id is not given (not as a tagcontent or url parameter)
183
throw new CmsLegacyException(C_MISSING_ID_PARAMETER);
184         }
185         // first get the contentdefinition's classname from a datablock
186
String JavaDoc cdClassname = template.getDataValue(C_CONTENTDEFINITION_CLASS_DATABLOCK);
187         try {
188             ArrayList JavaDoc getMethods = null;
189             // try to get class object might throws ClassNotFoundException
190
Class JavaDoc cdClass = Class.forName(cdClassname);
191             // might throws NoSuchMethodException
192
Constructor JavaDoc constructor = cdClass.getConstructor(new Class JavaDoc[] {CmsObject.class, Integer JavaDoc.class});
193             // might throws InvocationTargetException, ClassCastException
194
A_CmsContentDefinition cdObject = (A_CmsContentDefinition)constructor.newInstance(new Object JavaDoc[]{cms, id});
195             // register the CD for the variantdependencies
196
Vector JavaDoc cdVec = new Vector JavaDoc();
197             cdVec.add(cdObject);
198             registerVariantDeps(cms, doc.getAbsoluteFilename(), null, null,
199                                 (Hashtable JavaDoc)userObject, null, cdVec, null);
200             boolean showIt = true;
201             if (cdObject.isTimedContent()) {
202                 I_CmsTimedContentDefinition curTimed = (I_CmsTimedContentDefinition)cdObject;
203                 long currentTime = System.currentTimeMillis();
204                 if (((curTimed.getPublicationDate() != 0) && (currentTime < curTimed.getPublicationDate()))
205                         || ((curTimed.getPurgeDate() != 0) && (currentTime > curTimed.getPurgeDate()))) {
206                     showIt = false;
207                 }
208             }
209             if (!showIt) {
210                 // TODO: read an datablock from the template and set all the proccesstags with it then remove this exception
211
throw new CmsLegacyException("requested content is not valid.");
212             }
213             if (template.hasData(C_METHODS_TO_USE_DATABLOCK)) {
214                 // if the datablock methods is set inside the template
215
// only take the methods that are listed in this datablock
216
// (the methods should be listed as a comma seperated list of names)
217
String JavaDoc datablockContent = template.getDataValue(C_METHODS_TO_USE_DATABLOCK);
218                 StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(datablockContent, ",");
219                 int tokens = tokenizer.countTokens();
220                 String JavaDoc[] names = new String JavaDoc[tokens];
221                 for (int i=0; i < tokens; i++) {
222                     names[i] = tokenizer.nextToken().trim();
223                 }
224                 getMethods = getGetMethodsByName(cdClass, names);
225             } else {
226                 // get all public getMethods that return a String and have no parameters
227
getMethods = getGetMethods(cdClass);
228             }
229             try {
230                 Method JavaDoc getUniqueIdMethod = cdClass.getMethod("getUniqueId", new Class JavaDoc[] {CmsObject.class});
231                 template.setData("uniqueid", (String JavaDoc)getUniqueIdMethod.invoke(cdObject, new Object JavaDoc[] {cms}));
232             } catch (Exception JavaDoc e) { }
233             setDatablocks(template, cdObject, getMethods);
234         } catch (InvocationTargetException JavaDoc e) {
235             // the constructor has throwed an exception, InvocationTargetExceptions of the egt-methods
236
// will be catched inside the setDatablocks method and cannot propagate to this point
237
throw new CmsLegacyException(C_CONSTRUCTOR_THROWED_EXCEPTION, e.getTargetException());
238         } catch (ClassCastException JavaDoc e) {
239             // in this case the cast to A_CmsContentDefinition failed
240
throw new CmsLegacyException(C_CONSTRUCTOR_IS_NOT_SUBCLASS_OF_A_CMSCONTENTDEFINITION, e);
241         } catch (Exception JavaDoc e) {
242             // rethrow any other exception
243
if (e instanceof CmsException) {
244                 throw (CmsException)e;
245             } else {
246                 // encapsulate in CmsException
247
throw new CmsLegacyException (e.getMessage(), e);
248             }
249         }
250         return "";
251     }
252
253     /**
254      * User-method to build a list of contentdefinition entries.
255      * @param cms CmsObject Object for accessing system resources.
256      * @param tagcontent comma separated name, default value pair. The name
257      * is the name of an url parameter which value will be passed to the
258      * filtermethod if given. If the url parameter is not found the default
259      * value will be used as a userparameter for the filtermethod.
260      * @param doc reference to the A_CmsXmlContent object of the initiating XLM document.
261      * @param userObject normally the Hashtable with url parameters.
262      * @return String or byte[] with the content of this subelement.
263      * @throws org.opencms.main.CmsException in case of unrecoverable errors
264      */

265     public Object JavaDoc getList(CmsObject cms, String JavaDoc tagcontent,
266             A_CmsXmlContent doc, Object JavaDoc userObject) throws CmsException {
267         StringBuffer JavaDoc list = new StringBuffer JavaDoc();
268         ArrayList JavaDoc getMethods = null;
269         Hashtable JavaDoc parameters = (Hashtable JavaDoc) userObject;
270         CmsXmlTemplateFile template = (CmsXmlTemplateFile) doc;
271         String JavaDoc contentDefinitionName = template.getDataValue(C_CONTENTDEFINITION_CLASS_DATABLOCK);
272         String JavaDoc filterMethodName = template.getDataValue(C_FILTERMETHOD_DATABLOCK);
273
274         try {
275             // get contentdefinition class might throws ClassNotFoundException
276
Class JavaDoc cdClass = Class.forName(contentDefinitionName);
277             //register the class for the dependencies
278
Vector JavaDoc theClass = new Vector JavaDoc();
279             theClass.add(cdClass);
280             Vector JavaDoc allCdClasses = new Vector JavaDoc();
281             // get getFilterMethods method might throws NoSuchMethodException, IllegalAccessException
282
String JavaDoc userParameter = getUserParameter(parameters, tagcontent);
283             Vector JavaDoc cdObjects = invokeFilterMethod(cms, cdClass, filterMethodName, userParameter);
284             if (template.hasData(C_METHODS_TO_USE_DATABLOCK)) {
285                 // if the datablock methods is set inside the template
286
// only take the methods that are listed in this datablock
287
// (the methods should be listed as a comma seperated list of names)
288
String JavaDoc datablockContent = template.getDataValue(C_METHODS_TO_USE_DATABLOCK);
289                 StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(datablockContent, ",");
290                 int tokens = tokenizer.countTokens();
291                 String JavaDoc[] names = new String JavaDoc[tokens];
292                 for (int i=0; i < tokens; i++) {
293                     names[i] = tokenizer.nextToken().trim();
294                 }
295                 getMethods = getGetMethodsByName(cdClass, names);
296             } else {
297                 // get all public getMethods that return a String and have no parameters
298
getMethods = getGetMethods(cdClass);
299             }
300             // walk through Vector and fill content
301
int size = cdObjects.size();
302             long currentTime = System.currentTimeMillis();
303             for (int i=0; i < size; i++) {
304                 boolean showIt = true;
305                 A_CmsContentDefinition curCont = (A_CmsContentDefinition)cdObjects.elementAt(i);
306                 if (curCont.isTimedContent()) {
307                     allCdClasses.add(curCont);
308                     I_CmsTimedContentDefinition curTimed = (I_CmsTimedContentDefinition)curCont;
309                     if (((curTimed.getPublicationDate() != 0) && (currentTime < curTimed.getPublicationDate()))
310                             || ((curTimed.getPurgeDate() != 0) && (currentTime > curTimed.getPurgeDate()))) {
311                         showIt = false;
312                     }
313                 }
314                 if (showIt) {
315                     try {
316                         Method JavaDoc getUniqueIdMethod = cdClass.getMethod("getUniqueId", new Class JavaDoc[] {CmsObject.class});
317                         template.setData("uniqueid", (String JavaDoc)getUniqueIdMethod.invoke(curCont, new Object JavaDoc[] {cms}));
318                     } catch (Exception JavaDoc e) {
319                     }
320                     setDatablocks(template, curCont, getMethods);
321                     list.append(template.getProcessedDataValue(C_LISTENTRY_DATABLOCK, this));
322                 }
323             }
324             //register the classes for the dependencies
325
registerVariantDeps(cms, doc.getAbsoluteFilename(), null, null, parameters, null, allCdClasses, theClass);
326         } catch (Exception JavaDoc e) {
327             if (e instanceof CmsException) {
328                 throw (CmsException) e;
329             } else {
330                 throw new CmsLegacyException (e.getMessage(), CmsLegacyException.C_UNKNOWN_EXCEPTION, e);
331             }
332         }
333         return list.toString();
334     }
335
336     /**
337      * Gets the userparameter from tagcontent of the getList method-tag or from url parameters.
338      * The tagcontent should contain the name of an url parameter and a default
339      * value for this parameter. For example: name,B.
340      * If the url parameter can be fetched from the parameters Hashtable
341      * this value will be returned otherwise the default value
342      * (in this example B). If the tagcontent contains a String without
343      * any commas this value will be taken as the userparameter.
344      * @param parameters Hashtable with the url parameters
345      * @param tagcontent String with the content of the method tag
346      * @return String with the value of the userparameter
347      * @throws CmsException if something goes wrong
348      */

349    protected String JavaDoc getUserParameter (Hashtable JavaDoc parameters, String JavaDoc tagcontent) throws CmsException {
350         String JavaDoc userparameter = "";
351         String JavaDoc parameterName = null;
352         String JavaDoc parameterValue = null;
353         if (tagcontent != null) {
354             int index = tagcontent.indexOf(",");
355             if (index != -1) {
356                 parameterName = tagcontent.substring(0, index);
357                 // todo: check also if the length is ok and if the last char is in {0,1,..,9}
358
if (!(parameterName.startsWith(C_FILTER_PARAMETERS_START))) {
359                     throw new CmsLegacyException("The filterparameter has to be \""
360                             +C_FILTER_PARAMETERS_START+"N\" where 0 <= N <= 9.");
361                 }
362                 parameterValue = (String JavaDoc)parameters.get(parameterName);
363                 if (parameterValue != null) {
364                     userparameter = parameterValue;
365                 } else if (tagcontent.length() > index+1) {
366                     userparameter = tagcontent.substring(index+1);
367                 }
368             } else {
369                 return tagcontent;
370             }
371         }
372         return userparameter;
373     }
374
375     /**
376     * This methods collects all "getXYZ" methods of the contentdefinition.
377     * @param cdClass the class object of the contentdefinition class
378     * @return ArrayList of java.lang.reflect.Method objects
379     */

380     protected ArrayList JavaDoc getGetMethods (Class JavaDoc cdClass) {
381         // the Vector of methods to return
382
ArrayList JavaDoc getMethods = new ArrayList JavaDoc();
383         // get an array of all public member methods
384
Method JavaDoc[] methods = cdClass.getMethods();
385         Method JavaDoc m = null;
386         String JavaDoc name = null;
387         //get all public get-methods which return a String
388
for (int i=0; i < methods.length; i++) {
389             m = methods[i];
390             name = m.getName().toLowerCase();
391             //now extract all methods whose name starts with a "get"
392
if (name.startsWith("get")) {
393                 //only take methods that have no parameter and return a String
394
if (m.getReturnType().equals(String JavaDoc.class) && m.getParameterTypes().length == 0) {
395                     getMethods.add(m);
396                 }
397             }
398          }
399         return getMethods;
400     }
401
402     /**
403     * This methods collects all get-methods with the names specified in the
404     * String array names. All these methods has to be without parameters and
405     * should return a String (if they don't return a String there might
406     * be thrown an exception, when the return value will be casted to a String
407     * in the method setDatablocks which will result in setting an error text
408     * instead of the output of the method inside the template).<p>
409     *
410     * @param cdClass the class object of the contentdefinition class
411     * @param names array of method names
412     * @return ArrayList of java.lang.reflect.Method objects
413     * @throws NoSuchMethodException in case of unrecoverable errors
414     */

415     protected ArrayList JavaDoc getGetMethodsByName (Class JavaDoc cdClass, String JavaDoc[] names)
416             throws NoSuchMethodException JavaDoc {
417         // the list of methods to return
418
ArrayList JavaDoc getMethods = new ArrayList JavaDoc();
419         Class JavaDoc[] argTypes = new Class JavaDoc[0];
420         for (int i=0; i < names.length; i++) {
421             getMethods.add(cdClass.getMethod(names[i], argTypes));
422         }
423         return getMethods;
424     }
425
426     /**
427     * This method automatically fills all datablocks in the template that fit
428     * to a special name scheme.
429     * A datablock named "xyz" is filled with the value of a "getXYZ" method
430     * form the content defintion.
431     * @param template The template file of this template
432     * @param contentDefinition The actual content defintion object
433     * @param methods A vector of java.lang.reflect.Method objects with all "getXYZ" methods to be used
434     * @throws org.opencms.main.CmsException in case of unrecoverable erros
435     */

436     protected void setDatablocks(CmsXmlTemplateFile template,
437             A_CmsContentDefinition contentDefinition,
438             ArrayList JavaDoc methods) throws CmsException {
439         String JavaDoc datablockName= null;
440         Method JavaDoc method = null;
441         int size = methods.size();
442         Object JavaDoc[] args = new Object JavaDoc[0];
443         for (int i=0; i < size; i++) {
444             // get the method name
445
method = (Method JavaDoc)methods.get(i);
446             //get the datablock name - the methodname without the leading "get"
447
datablockName = (method.getName().substring(3)).toLowerCase();
448             //check if the datablock name ends with a "string" if so, remove it from the datablockname
449
if (datablockName.endsWith("string")) {
450                 datablockName = datablockName.substring(0, datablockName.lastIndexOf("string"));
451             }
452             // now call the method to get the value
453
try {
454                 template.setData(datablockName, (String JavaDoc)method.invoke(contentDefinition, args));
455             } catch (Exception JavaDoc e) {
456                 if (CmsLog.getLog(this).isErrorEnabled()) {
457                     CmsLog.getLog(this).error("Error during automatic call method '" + method.getName(), e);
458                 }
459                 // set datablock with error text to indicate that calling the get-method failed
460
template.setData(datablockName, C_ERROR_TEXT);
461             }
462         } // for
463
}
464
465     /**
466      * Invokes the filtermethod and returns a Vector of contentdefinition
467      * objects returned by the filtermethod.
468      * If you want to use filtermethods with other sinatures you have to override
469      * this method in your own derived subclass.<p>
470      *
471      * @param cms the cms object
472      * @param cdClass Class object of the ContentDefinition class
473      * @param name the name of the filtermethod to invoke
474      * @param userparameter the value of the userparameetr which will be passed to the filtermethod
475      * @return Vector of contentdefinition objects
476      * @throws NoSuchMethodException if the filtermethod doesn't exist
477      * @throws InvocationTargetException if the invoked filtermethod throws an exception itself
478      * @throws IllegalAccessException if the filtermethod is inaccessible
479      */

480      protected Vector JavaDoc invokeFilterMethod (CmsObject cms, Class JavaDoc cdClass, String JavaDoc name, String JavaDoc userparameter)
481             throws NoSuchMethodException JavaDoc, InvocationTargetException JavaDoc, IllegalAccessException JavaDoc {
482         Method JavaDoc method = cdClass.getMethod(name, new Class JavaDoc[] {CmsObject.class, String JavaDoc.class});
483         return (Vector JavaDoc)method.invoke(cdClass, new Object JavaDoc[] {cms, userparameter});
484      }
485
486     /**
487     * Gets the caching information from the current template class.
488     *
489     * @param cms CmsObject Object for accessing system resources
490     * @param templateFile Filename of the template file
491     * @param elementName Element name of this template in our parent template
492     * @param parameters Hashtable with all template class parameters
493     * @param templateSelector template section that should be processed
494     * @return object with caching information
495     */

496     public CmsCacheDirectives getCacheDirectives(CmsObject cms, String JavaDoc templateFile,
497                 String JavaDoc elementName, Hashtable JavaDoc parameters, String JavaDoc templateSelector) {
498
499         CmsCacheDirectives result = new CmsCacheDirectives(true, false, false, false, false);
500         result.setCacheUri(true);
501         result.noAutoRenewAfterPublish();
502         Vector JavaDoc para = new Vector JavaDoc();
503         para.add(C_ID_PARAMETER);
504         for (int i=0; i < 10; i++) {
505             para.add(C_FILTER_PARAMETERS_START + i);
506         }
507         result.setCacheParameters(para);
508
509         return result;
510     }
511 }
Popular Tags