KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jetspeed > services > template > JetspeedTemplateService


1 package org.apache.jetspeed.services.template;
2
3 /*
4  * Copyright 2000-2004 The Apache Software Foundation.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19
20
21 // Java Core Classes
22
import java.util.ArrayList JavaDoc;
23 import java.util.Properties JavaDoc;
24 import java.util.Hashtable JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
27 import java.io.File JavaDoc;
28 import javax.servlet.ServletConfig JavaDoc;
29
30 // Turbine Utility Classes
31
import org.apache.turbine.util.ServletUtils;
32 import org.apache.turbine.services.TurbineBaseService;
33 import org.apache.turbine.services.InitializationException;
34 import org.apache.turbine.services.resources.TurbineResources;
35 import org.apache.turbine.modules.ScreenLoader;
36 import org.apache.turbine.modules.NavigationLoader;
37
38 // Jetspeed classes
39
import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
40 import org.apache.jetspeed.services.logging.JetspeedLogger;
41
42 /**
43  * <p>This service extends the TurbineTemplateService to modify its behaviour:
44  * Not only layout and screen packages, but also the screen templates
45  * are searched in the template neames filepath, so that a fallback
46  * strategy is provided, that can be used for multi-language, multi-device
47  * and browser-specific support support.</p>
48  * <p>E.g: a template name "/html/en/US/IE/mytemplate" would search for
49  * following files (in the given order):
50  * <ol>
51  * <li>. /html/en/US/IE/mytemplate</li>
52  * <li>. /html/en/US/mytemplate</li>
53  * <li>. /html/en/mytemplate</li>
54  * <li>. /html/mytemplate</li>
55  * <li>. /mytemplate</li>
56  * </ol>
57  * </p>
58  * <p>
59  * TurbineTemplateService part:
60  * @author <a HREF="mailto:john.mcnally@clearink.com">John D. McNally</a>
61  * @author <a HREF="mailto:mbryson@mont.mindspring.com">Dave Bryson</a>
62  * JetspeedTemplateService part:
63  * @author <a HREF="mailto:ingo@apache.org">Ingo Schuster</a>
64  * @version $Id: JetspeedTemplateService.java,v 1.11 2004/02/23 03:38:54 jford Exp $
65  */

66 public class JetspeedTemplateService
67     extends TurbineBaseService
68   // implements TemplateService
69
// removed dst: 2001/06/03, TDK 2.2 integration
70
{
71     /**
72      * Static initialization of the logger for this class
73      */

74     private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedTemplateService.class.getName());
75     
76     /** The hashtable used to cache Screen names. */
77     private Hashtable JavaDoc screenCache = null;
78
79     /** The hashtable used to cache screen template names. */
80     private Hashtable JavaDoc templateCache = null;
81
82     /** The hashtable used to cache Navigation names. */
83     private Hashtable JavaDoc navCache = null;
84
85     /** The hashtable used to cache layout template names. */
86     private Hashtable JavaDoc layoutCache = null;
87
88     /** Flag set if cache is to be used. */
89     private boolean useCache = false;
90
91     /** Default extension. */
92     private String JavaDoc extension;
93
94     /** Default layout template. */
95     private String JavaDoc defaultLayoutTemplate;
96
97     /** Default Navigation module. */
98     private String JavaDoc defaultNavigation;
99
100     /** Default Screen module. */
101     private String JavaDoc defaultScreen;
102
103     /**
104      * The absolute paths where the appropriate template engine will
105      * be searching for templates.
106      */

107     private String JavaDoc[] templateRoot = null;
108
109     /**
110      * Called the first time the Service is used.
111      *
112      * @param config A ServletConfig.
113      */

114     public void init(ServletConfig JavaDoc config)
115         throws InitializationException
116     {
117         try
118         {
119             initTemplate(config);
120             setInit(true);
121             logger.info ("TemplateService init()....finished!");
122         }
123         catch (Exception JavaDoc e)
124         {
125             logger.error( "TurbineTemplateService failed to initialize", e );
126             throw new InitializationException("TurbineTemplateService failed to initialize", e);
127         }
128     }
129
130     /**
131      * TODO: Document this class.
132      *
133      * @param config A ServletConfig.
134      * @exception Exception, a generic exception.
135      */

136     private void initTemplate(ServletConfig JavaDoc config)
137         throws Exception JavaDoc
138     {
139         useCache = TurbineResources.getBoolean("modules.cache", true);
140         Properties JavaDoc props = getProperties();
141
142         if (useCache)
143         {
144             int layoutSize = Integer
145                 .parseInt(props.getProperty("layout.cache.size", "5"));
146             int navigationSize = Integer
147                 .parseInt(props.getProperty("navigation.cache.size", "10"));
148             int screenSize = Integer
149                 .parseInt(props.getProperty("screen.cache.size", "5"));
150             int templateSize = Integer
151                 .parseInt(props.getProperty("screen.cache.size", "50"));
152             layoutCache = new Hashtable JavaDoc( (int)(1.25*layoutSize) + 1);
153             navCache = new Hashtable JavaDoc( (int)(1.25*navigationSize) + 1);
154             screenCache = new Hashtable JavaDoc( (int)(1.25*screenSize) + 1);
155             templateCache = new Hashtable JavaDoc( (int)(1.25*templateSize) + 1);
156         }
157         // relative to the webapp root directory
158
String JavaDoc templatePaths = props
159             .getProperty("template.path", "/templates");
160
161         // If possible, transform paths to be webapp root relative.
162
templatePaths = ServletUtils.expandRelative(config,
163                                                      templatePaths);
164
165         // store the converted paths in service properties for
166
// Turbine based providers
167
props.put("template.path", templatePaths);
168
169         // tokenize the template.path property and assign to an array
170
String JavaDoc pathSep = System.getProperty("path.separator");
171         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(templatePaths,pathSep);
172         templateRoot = new String JavaDoc[st.countTokens()];
173         int pos = 0;
174         while(st.hasMoreTokens())
175         {
176             templateRoot[pos++] = st.nextToken();
177         }
178
179         // the extension that is added to layout templates (e.g.)
180
extension = props.getProperty("default.extension", "html");
181
182         // the default modules
183
defaultNavigation = props
184             .getProperty("default.navigation", "TemplateNavigation");
185         defaultScreen = props.getProperty("default.screen", "TemplateScreen");
186         
187         // the default layout template
188
defaultLayoutTemplate = props
189             .getProperty("default.layout.template", "/default." + extension);
190         
191         if (defaultLayoutTemplate.indexOf('.') == -1)
192         {
193             defaultLayoutTemplate = defaultLayoutTemplate + "." + extension;
194         }
195     }
196
197     /**
198      * Adds the object into the hashtable.
199      *
200      * @param key The String key for the object.
201      * @param value The Object.
202      * @param h The Hashtable.
203      */

204     private void addToCache ( String JavaDoc key,
205                               Object JavaDoc value,
206                               Hashtable JavaDoc h )
207     {
208         if (useCache && value != null)
209         {
210             h.put(key, value);
211         }
212     }
213
214     /**
215      * Get the Screen template given in the properties file.
216      *
217      * @return A String which is the value of the TemplateService
218      * default.screen property.
219      */

220     public String JavaDoc getDefaultScreen()
221     {
222         return defaultScreen;
223     }
224     
225     /**
226      * Get the default Navigation given in the properties file.
227      *
228      * @return A String which is the value of the TemplateService
229      * default.navigation property.
230      */

231     public String JavaDoc getDefaultNavigation()
232     {
233         return defaultNavigation;
234     }
235
236     /**
237      * Get the default layout template given in the properties file.
238      *
239      * @return A String which is the value of the TemplateService
240      * default.layout.template property.
241      */

242     public String JavaDoc getDefaultLayoutTemplate()
243     {
244         return defaultLayoutTemplate;
245     }
246
247     
248     /**
249      * Locate and return the name of a screen template.
250      *
251      *
252      * @param name A String which is the key to the template.
253      * @return A String with the screen template path.
254      * @exception Exception, a generic exception.
255      */

256     public String JavaDoc getScreenTemplateName(String JavaDoc key)
257         throws Exception JavaDoc
258     {
259         if (name==null)
260             throw new Exception JavaDoc ("TurbineTemplateService: " +
261                 "getLayoutTemplateName() was passed in a null value.");
262
263         String JavaDoc name = null;
264
265         if ( useCache && templateCache.containsKey(key) )
266         {
267             name = (String JavaDoc)templateCache.get(key);
268         }
269         else
270         {
271             if ( logger.isDebugEnabled() )
272             {
273                 logger.debug("JetspeedTemplatePage.getLayoutTemplateName(" + key + ")");
274             }
275             String JavaDoc[] names = parseScreenTemplate(key);
276             name = names[2];
277             addToCache( key, names[0], screenCache );
278             addToCache( key, names[1], layoutCache );
279             addToCache( key, names[2], templateCache );
280         }
281         return name;
282     }
283     /**
284      * Locate and return the name of a layout template.
285      *
286      *
287      * @param name A String with the name of the template.
288      * @return A String with the layout template path.
289      * @exception Exception, a generic exception.
290      */

291     public String JavaDoc getLayoutTemplateName(String JavaDoc name)
292         throws Exception JavaDoc
293     {
294         if (name==null)
295             throw new Exception JavaDoc ("TurbineTemplateService: " +
296                 "getLayoutTemplateName() was passed in a null value.");
297
298         String JavaDoc layoutName = null;
299
300         if ( useCache && layoutCache.containsKey(name) )
301         {
302             layoutName = (String JavaDoc)layoutCache.get(name);
303         }
304         else
305         {
306             String JavaDoc[] names = parseScreenTemplate(name);
307             layoutName = names[1];
308             addToCache( name, names[0], screenCache );
309             addToCache( name, names[1], layoutCache );
310             addToCache( name, names[2], templateCache );
311         }
312         return layoutName;
313     }
314
315     /**
316      * Locate and return the name of a Navigation module.
317      *
318      * @param name A String with the name of the template.
319      * @return A String with the name of the navigation.
320      * @exception Exception, a generic exception.
321      */

322     public String JavaDoc getNavigationName(String JavaDoc name)
323         throws Exception JavaDoc
324     {
325         if (name==null)
326             throw new Exception JavaDoc ("TurbineTemplateService: " +
327                 "getNavigationName() was passed in a null value.");
328
329         String JavaDoc nav_name = null;
330
331         if ( useCache && navCache.containsKey(name) )
332         {
333             nav_name = (String JavaDoc)navCache.get(name);
334         }
335         else
336         {
337             nav_name = parseNavigationTemplate(name);
338             addToCache( name, nav_name, navCache );
339         }
340         return nav_name;
341     }
342
343     /**
344      * Locate and return the name of a Screen module.
345      *
346      * @param name A String with the name of the template.
347      * @return A String with the name of the screen.
348      * @exception Exception, a generic exception.
349      */

350     public String JavaDoc getScreenName(String JavaDoc name)
351         throws Exception JavaDoc
352     {
353
354         if (name==null)
355             throw new Exception JavaDoc ("TurbineTemplateService: " +
356                 "getScreenName() was passed in a null value.");
357
358         String JavaDoc screenName = null;
359
360         if ( useCache && screenCache.containsKey(name) )
361         {
362             screenName = (String JavaDoc)screenCache.get(name);
363         }
364         else
365         {
366             String JavaDoc[] names = parseScreenTemplate(name);
367             screenName = names[0];
368             addToCache( name, names[0], screenCache );
369             addToCache( name, names[1], layoutCache );
370             addToCache( name, names[2], templateCache );
371         }
372         return screenName;
373     }
374
375     /**
376      * Get the default extension given in the properties file.
377      *
378      * @return A String with the extension.
379      */

380     public String JavaDoc getDefaultExtension()
381     {
382         return extension;
383     }
384
385     /**
386      * This method takes the template parameter and parses it, so that
387      * relevant Screen/Layout-template information can be extracted.
388      *
389      * @param template A String with the template name.
390      * @return A String[] where the first element is the Screen name
391      * and the second element is the layout template.
392      */

393     protected String JavaDoc[] parseScreenTemplate( String JavaDoc template ) throws Exception JavaDoc
394     {
395         // check if an extension was included. if not, add the default
396
if ( template.indexOf('.') == -1 )
397         {
398             template = template + "." + getDefaultExtension();
399         }
400
401         if ( logger.isDebugEnabled() )
402         {
403             logger.debug("JetspeedTemplateService.parseScreen: template = " + template);
404         }
405         
406         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(template, "/");
407         List JavaDoc tokens = new ArrayList JavaDoc(st.countTokens());
408         while(st.hasMoreTokens())
409         {
410             String JavaDoc token = st.nextToken();
411             if (!token.equals(""))
412             {
413                 tokens.add(token);
414             }
415         }
416         if ( logger.isDebugEnabled() )
417         {
418             logger.debug("JetspeedTemplateService.parseScreen: tokens1: " + tokens);
419         }
420         String JavaDoc fileName = (String JavaDoc)tokens.get(tokens.size() - 1);
421         tokens.remove(tokens.size()-1);
422         int dot = fileName.lastIndexOf('.');
423         String JavaDoc className = null;
424         if (dot>0)
425         {
426             className = fileName.substring(0, dot);
427         }
428         else
429         {
430             className = fileName;
431         }
432         String JavaDoc firstChar = String.valueOf(className.charAt(0));
433         firstChar = firstChar.toUpperCase();
434         className = firstChar + className.substring(1);
435         if ( logger.isDebugEnabled() )
436         {
437             logger.debug("JetspeedTemplateService.parseScreen: tokens2: " + tokens);
438         }
439
440         // make sure the template exists and determine the correct
441
// templateRoot path
442
String JavaDoc pathRoot = null;
443         String JavaDoc allPaths = "";
444         String JavaDoc pathSep = System.getProperty("path.separator");
445         for (int i=0; i<templateRoot.length; i++)
446         {
447             if ( logger.isDebugEnabled() )
448             {
449                 logger.debug("JetspeedTemplateService.parseScreen: templateRoot " + i + " " + templateRoot[i]);
450             }
451
452             String JavaDoc templatePath = null;
453         
454             for (int k=tokens.size(); k>=0; k--)
455             {
456                 StringBuffer JavaDoc path = new StringBuffer JavaDoc();
457                 for (int j=0; j<k; j++)
458                 {
459                     path.append("/").append((String JavaDoc)tokens.get(j));
460                 }
461                 StringBuffer JavaDoc distinctPath = new StringBuffer JavaDoc(path.toString()).append("/").append(fileName);
462                 templatePath = distinctPath.toString();
463                 if ( logger.isDebugEnabled() )
464                 {
465                     logger.debug("JetspeedTemplateService.parseScreen: Path: " + templatePath);
466                 }
467          
468                 if (new File JavaDoc(templateRoot[i] + "/screens" + templatePath).exists())
469                 {
470                     template = templatePath;
471                     if ( logger.isDebugEnabled() )
472                     {
473                         logger.debug("JetspeedTemplateService.parseScreen: template found: " + template);
474                     }
475                     break;
476                 }
477                 templatePath = null;
478             }
479             if (templatePath != null) {
480                 pathRoot = templateRoot[i];
481                 if ( logger.isDebugEnabled() )
482                 {
483                     logger.debug("JetspeedTemplateService.parseScreen: pathRoot: " + pathRoot);
484                 }
485                 break;
486             }
487             allPaths += pathSep + templateRoot[i];
488         }
489         if (pathRoot == null)
490         {
491             throw new Exception JavaDoc("The screen template: " +
492                                 template +
493                                 " does not exist in " +
494                                 allPaths.substring(pathSep.length()) +
495                                 ", so the TemplateService could not " +
496                                 "determine associated templates.");
497         }
498
499         /*
500         String[] paths = new String[tokens.size() + 2];
501         String[] pkgs = new String[tokens.size() + 2];
502         int arrayIndex = 0;
503         for (int i=tokens.size(); i>=0; i--)
504         {
505             StringBuffer path = new StringBuffer();
506             StringBuffer pkg = new StringBuffer();
507             for (int j=0; j<i; j++)
508             {
509                 path.append("/").append((String)tokens.get(j));
510                 pkg.append((String)tokens.get(j)).append('.');
511             }
512             if ( i == tokens.size() )
513             {
514                 StringBuffer distinctPath = new StringBuffer(path.toString());
515                 StringBuffer distinctPkg = new StringBuffer(pkg.toString());
516                 paths[arrayIndex] = distinctPath.append('/').append(fileName).toString();
517                 pkgs[arrayIndex] = distinctPkg.append(className).toString();
518                 arrayIndex++;
519             }
520             paths[arrayIndex] = path.append(defaultLayoutTemplate).toString();
521             pkgs[arrayIndex] = pkg.append("Default").toString();
522             arrayIndex++;
523         }
524         */

525
526         String JavaDoc[] paths = new String JavaDoc[2 * tokens.size() +2];
527         String JavaDoc[] pkgs = new String JavaDoc[2 * tokens.size() +2];
528         int arrayIndex = 0;
529         for (int i=tokens.size(); i>=0; i--)
530         {
531             StringBuffer JavaDoc path = new StringBuffer JavaDoc();
532             StringBuffer JavaDoc pkg = new StringBuffer JavaDoc();
533             for (int j=0; j<i; j++)
534             {
535                 path.append("/").append((String JavaDoc)tokens.get(j));
536                 pkg.append((String JavaDoc)tokens.get(j)).append('.');
537             }
538             paths[arrayIndex] = path.append("/").append(fileName).toString();
539             pkgs[arrayIndex] = pkg.append("/").append(className).toString();
540             arrayIndex++;
541         }
542         
543         for (int i=tokens.size(); i>=0; i--)
544         {
545             StringBuffer JavaDoc path = new StringBuffer JavaDoc();
546             StringBuffer JavaDoc pkg = new StringBuffer JavaDoc();
547             for (int j=0; j<i; j++)
548             {
549                 path.append("/").append((String JavaDoc)tokens.get(j));
550                 pkg.append((String JavaDoc)tokens.get(j)).append('.');
551             }
552             paths[arrayIndex] = path.append(defaultLayoutTemplate).toString();
553             pkgs[arrayIndex] = pkg.append("Default").toString();
554             arrayIndex++;
555         }
556
557         if ( logger.isDebugEnabled() )
558         {
559             for (int i=0; i<paths.length; i++)
560             {
561                 logger.debug("JetspeedTemplateService.parseScreen: paths[" + i + "] = " + paths[i]);
562             }
563         }
564
565         String JavaDoc[] holder = new String JavaDoc[3];
566         holder[0] = getScreenName(pkgs);
567         holder[1] = getLayoutTemplateName(pathRoot, paths);
568         holder[2] = template;
569         return holder;
570     }
571
572     /**
573      * Parse the template name out to a package path to locate the
574      * Navigation module. This is different than the Screen/Layout
575      * parser in that it only looks for packages. Note: If caching is
576      * enabled, this is only performed once for each unique template.
577      *
578      * @param String The template name (i.e folder/headernav.wm).
579      * @return A String with the name of the Navigation module to use
580      * for the template.
581      */

582     protected String JavaDoc parseNavigationTemplate( String JavaDoc template )
583     {
584         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(template, "/");
585         List JavaDoc tokens = new ArrayList JavaDoc(st.countTokens());
586         while(st.hasMoreTokens())
587         {
588             String JavaDoc token = st.nextToken();
589             if (!token.equals(""))
590             {
591                 tokens.add(token);
592             }
593         }
594         String JavaDoc fileName = (String JavaDoc)tokens.get(tokens.size() - 1);
595         tokens.remove(tokens.size() - 1);
596         int dot = fileName.lastIndexOf('.');
597         String JavaDoc className = null;
598         if (dot>0)
599         {
600             className = fileName.substring(0, dot);
601         }
602         else
603         {
604             className = fileName;
605         }
606         String JavaDoc firstChar = String.valueOf(className.charAt(0));
607         firstChar = firstChar.toUpperCase();
608         className = firstChar + className.substring(1);
609
610         String JavaDoc[] pkgs = new String JavaDoc[tokens.size() + 2];
611         int arrayIndex = 0;
612         for (int i=tokens.size(); i>=0; i--)
613         {
614             StringBuffer JavaDoc pkg = new StringBuffer JavaDoc();
615             for (int j=0; j<i; j++)
616             {
617                 pkg.append((String JavaDoc)tokens.get(j)).append('.');
618             }
619             if ( i == tokens.size() )
620             {
621                 StringBuffer JavaDoc distinctPkg = new StringBuffer JavaDoc(pkg.toString());
622                 pkgs[arrayIndex] = distinctPkg.append(className).toString();
623                 arrayIndex++;
624             }
625             pkgs[arrayIndex] = pkg.append("Default").toString();
626             arrayIndex++;
627         }
628         return getNavigationName( pkgs);
629     }
630
631     /**
632      * Extract possible layouts paths.
633      *
634      * @param possiblePaths A String[] with possible paths to search.
635      * @return A String with the name of the layout template.
636      */

637     private String JavaDoc getLayoutTemplateName(String JavaDoc pathRoot, String JavaDoc[] possiblePaths)
638     {
639         if ( logger.isDebugEnabled() )
640         {
641             logger.debug("JetspeedTemplatePage.getLayoutTemplateName: pathRoot " + pathRoot);
642         
643             for (int i=0; i<possiblePaths.length; i++)
644             {
645                 logger.debug("JetspeedTemplatePage.getLayoutTemplateName: possiblePaths[" + i + "]=" + possiblePaths[i]);
646             }
647         }
648         for (int i=0; i<possiblePaths.length; i++)
649         {
650             if (new File JavaDoc(pathRoot, "layouts" + possiblePaths[i]).exists())
651             {
652                 if ( logger.isDebugEnabled() )
653                 {
654                     logger.debug("JetspeedTemplatePage.getLayoutTemplateName: " + pathRoot + "/layouts" + possiblePaths[i] + " found.");
655                 }
656                 return possiblePaths[i];
657             }
658             else
659             {
660                 if ( logger.isDebugEnabled() )
661                 {
662                     logger.debug("JetspeedTemplatePage.getLayoutTemplateName: " + pathRoot + "/layouts" + possiblePaths[i] + " NOT found.");
663                 }
664             }
665         }
666         return defaultLayoutTemplate;
667     }
668
669     /**
670      * Extract a possible Screen from the packages.
671      *
672      * @param possibleScreens A String[] with possible paths to
673      * search.
674      * @return A String with the name of the Screen class to use.
675      */

676     private String JavaDoc getScreenName( String JavaDoc[] possibleScreens)
677     {
678         for (int i=0; i<possibleScreens.length; i++)
679         {
680             try
681             {
682                 ScreenLoader.getInstance().getInstance(possibleScreens[i]);
683                 return possibleScreens[i];
684             }
685             catch (Exception JavaDoc e)
686             {
687                 logger.error( "Exception in getScreenName", e );
688             }
689         }
690         return defaultScreen;
691     }
692
693
694     /**
695      * Seaches for the Navigation class that may match the
696      * name of the Navigation template.
697      *
698      * @param possibleNavigations A String[] with possible navigation
699      * packages.
700      * @return A String with the name of the Navigation class to use.
701      */

702     private String JavaDoc getNavigationName( String JavaDoc[] possibleNavigations)
703     {
704         for (int i=0; i<possibleNavigations.length; i++)
705         {
706             try
707             {
708                 NavigationLoader.getInstance().getInstance(possibleNavigations[i]);
709                 return possibleNavigations[i];
710             }
711             catch (Exception JavaDoc e)
712             {
713                 logger.error( "Exception in getNavigationName", e );
714             }
715         }
716         return defaultNavigation;
717     }
718 }
719
720
721
722
Popular Tags