View Javadoc

1   /*
2    * Copyright 2000-2001,2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.apache.jetspeed.services.template;
18  
19  // java.io
20  import java.io.File;
21  
22  // java.util
23  import java.util.Iterator;
24  import java.util.List;
25  import java.util.ArrayList;
26  import java.util.Map;
27  import java.util.HashMap;
28  import java.util.Locale;
29  
30  import javax.servlet.ServletConfig;
31  
32  // turbine.util
33  import org.apache.turbine.util.RunData;
34  
35  // turbine.services
36  import org.apache.turbine.services.TurbineBaseService;
37  import org.apache.turbine.services.TurbineServices;
38  import org.apache.turbine.services.InitializationException;
39  import org.apache.turbine.services.servlet.TurbineServlet;
40  import org.apache.turbine.services.jsp.JspService;
41  import org.apache.turbine.services.resources.TurbineResources;
42  import org.apache.turbine.services.template.TurbineTemplate;
43  import org.apache.turbine.services.velocity.VelocityService;
44  import org.apache.turbine.services.localization.LocalizationService;
45  
46  // jetspeed.capability
47  import org.apache.commons.configuration.Configuration;
48  import org.apache.jetspeed.capability.CapabilityMap;
49  
50  // jetspeed.services
51  import org.apache.jetspeed.services.resources.JetspeedResources;
52  import org.apache.jetspeed.services.rundata.JetspeedRunData;
53  import org.apache.jetspeed.services.Profiler;
54  import org.apache.jetspeed.services.logging.JetspeedLogFactoryService;
55  import org.apache.jetspeed.services.logging.JetspeedLogger;
56  import org.apache.jetspeed.services.customlocalization.CustomLocalizationService;
57  import org.apache.jetspeed.util.ServiceUtil;
58  /***
59   * <p>Implements all template location related operations.
60   * Template location algorithms are different from the Velocity template location,
61   * since Jetspeed has a specialized template directory structure.
62   * This is a fix to get us through unti the TurbineTemplateService can locate
63   * resources by NLS and mediatype. Then it can be removed</p>
64   *
65   * <p>The directory structure is currently layout out in the following order:
66   *    /templateType/mediaType/LanguageCode/CountryCode</p>
67   * <p>Example: /screens/html/en/US/resource.vm</p>
68   *
69   * @author <a href="mailto:taylor@apache.org">David Sean Taylor</a>
70   * @author <a href="mailto:rapahel@apache.org">Raphael Luta</a>
71   * @author <a href="mailto:paulsp@apache.org">Paul Spener</a>
72   * @author <a href="mailto:kimptoc_mail@yahoo.com">Chris Kimpton</a>
73   * @author <a href="mailto:weaver@apache.org">Scott T. Weaver</a>
74   * @version $Id: JetspeedTemplateLocatorService.java,v 1.22 2004/02/23 03:38:54 jford Exp $
75   */
76  
77  public class JetspeedTemplateLocatorService
78      extends TurbineBaseService
79      implements TemplateLocatorService
80  {
81      /***
82       * Static initialization of the logger for this class
83       */    
84      private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(JetspeedTemplateLocatorService.class.getName());
85      
86      private final static String CONFIG_TEMPLATE_ROOT = ".templateRoot";
87      private final static String CONFIG_PORTLET_GLOBAL_SEARCH = ".portlet.global.search";
88      private final static String CONFIG_HOT_DEPLOY = ".hot.deploy";
89      private final static String DIR_SCREENS = "/screens";
90      private final static String DIR_LAYOUTS = "/layouts";
91      private final static String DIR_PORTLETS = "/portlets";
92      private final static String DIR_CONTROLS = "/controls";
93      private final static String DIR_CONTROLLERS = "/controllers";
94      private final static String DIR_NAVIGATIONS = "/navigations";
95      private final static String DIR_PARAMETERS = "/parameters";
96      private final static String DIR_EMAILS = "/emails";
97      private static final String PATH_SEPARATOR = "/";
98  
99      // messages
100     private final static String MSG_MISSING_PARAMETER =
101         "JetspeedTemplateLocatorService initialization failed. Missing parameter:";
102 
103     // Template Service Constants
104     private static final String TEMPLATE_EXTENSION = "template.extension";
105     private static final String DEFAULT_LAYOUT = "default.layout.template";
106 
107     // Template services
108     private static VelocityService velocityService;
109 
110     private static JspService jspService;
111 
112     // the template root directories, webapp relative
113     private String[] templateRoots;
114 
115     // check the file system if template not found in name cache
116     private boolean hotDeploy = false;
117 
118     // template name cache
119     private Map templateMap = null;
120 
121     // include screens when searching for portlet template
122     private boolean useGlobalPortletSearch = false;
123 
124     /***
125      * This is the early initialization method called by the
126      * Turbine <code>Service</code> framework
127      * @param conf The <code>ServletConfig</code>
128      * @exception throws a <code>InitializationException</code> if the service
129      * fails to initialize
130      */
131     public synchronized void init(ServletConfig conf) throws InitializationException
132     {
133         // already initialized
134         if (getInit())
135         {
136             return;
137         }
138 
139         initConfiguration();
140 
141         // initialization done
142         setInit(true);
143     }
144 
145     public void init() throws InitializationException
146     {
147         logger.info("Late init for JetspeedTemplateLocatorService called");
148         while (!getInit())
149         {
150             //Not yet...
151             try
152             {
153                 Thread.sleep(100);
154                 logger.info("Waiting for init of JetspeedTemplateLocatorService...");
155             }
156             catch (InterruptedException ie)
157             {
158                 logger.error("Exception", ie);
159             }
160         }
161     }
162 
163     /***
164      * This is the shutdown method called by the
165      * Turbine <code>Service</code> framework
166      */
167     public void shutdown()
168     {
169     }
170 
171     /***
172      * Locate a screen template using Jetspeed template location algorithm, searching by
173      * mediatype and language criteria extracted from the request state in rundata.
174      *
175      * @param data The rundata for the request.
176      * @param template The name of the template.
177      *
178      * @return The path relative to the screens directory for the requested screen template,
179      *          or null if not found.
180      */
181     public String locateScreenTemplate(RunData data, String template)
182     {
183         List templatePaths = localizeTemplateName(data);
184         Iterator i = templatePaths.iterator();
185         String located = null;
186 
187         while (i.hasNext())
188         {
189             String path = (String) i.next();
190             located = locateTemplate(data, DIR_SCREENS, path, template);
191 
192             if (null != located)
193             {
194                 return located;
195             }
196         }
197 
198         if (null == located)
199         {
200             //we have not found the requested sreen but still need to return
201             //something, search for the default screen
202 
203             i = templatePaths.iterator();
204             template = "/default." + getTemplateExtension(template);
205             while (i.hasNext())
206             {
207                 String path = (String) i.next();
208                 located = locateTemplate(data, DIR_SCREENS, path, template);
209 
210                 if (null != located)
211                 {
212                     return located;
213                 }
214             }
215         }
216 
217         return located;
218     }
219 
220     /***
221      * Locate a layout template using Jetspeed template location algorithm, searching by
222      * mediatype and language criteria extracted from the request state in rundata.
223      *
224      * @param data The rundata for the request.
225      * @param template The name of the template.
226      *
227      * @return The path relative to the layouts directory for the requested layout template,
228      *          or null if not found.
229      */
230     public String locateLayoutTemplate(RunData data, String template)
231     {
232         List templatePaths = localizeTemplateName(data);
233         Iterator i = templatePaths.iterator();
234         String located = null;
235 
236         while (i.hasNext())
237         {
238             String path = (String) i.next();
239             located = locateTemplate(data, DIR_LAYOUTS, path, template);
240 
241             if (null != located)
242             {
243                 return located;
244             }
245         }
246 
247         if (null == located)
248         {
249             //we have not found the requested layout but still need to return
250             //something, search for the default layout
251 
252             i = templatePaths.iterator();
253 
254              //template = "/default." + getTemplateExtension(template);
255             template = getTemplateLayout(getTemplateExtension(template));
256             while (i.hasNext())
257             {
258                 String path = (String) i.next();
259                 located = locateTemplate(data, DIR_LAYOUTS, path, template);
260 
261                 if (null != located)
262                 {
263                     return located;
264                 }
265             }
266         }
267 
268         return located;
269     }
270 
271     /***
272      * Locate a controller template using Jetspeed template location algorithm, searching by
273      * mediatype and language criteria extracted from the request state in rundata.
274      *
275      * @param data The rundata for the request.
276      * @param template The name of the template.
277      *
278      * @return The path relative to the controllers directory for the requested controller template,
279      *          or null if not found.
280      */
281     public String locateNavigationTemplate(RunData data, String template)
282     {
283         List templatePaths = localizeTemplateName(data);
284         Iterator i = templatePaths.iterator();
285 
286         while (i.hasNext())
287         {
288             String path = (String) i.next();
289             String located = locateTemplate(data, DIR_NAVIGATIONS, path, template);
290 
291             if (null != located)
292             {
293                 return located;
294             }
295         }
296 
297         return null;
298     }
299 
300     /***
301      * Locate a portlet template using Jetspeed template location algorithm, searching by
302      * mediatype and language criteria extracted from the request state in rundata.
303      *
304      * @param data The rundata for the request.
305      * @param template The name of the template.
306      *
307      * @return The path relative to the portlets directory for the requested portlet template,
308      *          or null if not found.
309      */
310     public String locatePortletTemplate(RunData data, String template)
311     {
312         List templatePaths = localizeTemplateName(data);
313         Iterator i = templatePaths.iterator();
314 
315         while (i.hasNext())
316         {
317             String path = (String) i.next();
318             String located = locateTemplate(data, DIR_PORTLETS, path, template);
319 
320             if (null != located)
321             {
322                 return DIR_PORTLETS + located;
323             }
324         }
325 
326         // Use "wide" search when required
327         if (useGlobalPortletSearch == true)
328         {
329             String located = locateScreenTemplate(data, template);
330             if (located != null)
331             {
332                 return DIR_SCREENS + located;
333             }
334         }
335 
336         return null;
337     }
338 
339     /***
340      * Locate a control template using Jetspeed template location algorithm, searching by
341      * mediatype and language criteria extracted from the request state in rundata.
342      *
343      * @param data The rundata for the request.
344      * @param template The name of the template.
345      *
346      * @return The path relative to the controls directory for the requested control template,
347      *          or null if not found.
348      */
349     public String locateControlTemplate(RunData data, String template)
350     {
351         List templatePaths = localizeTemplateName(data);
352         Iterator i = templatePaths.iterator();
353 
354         while (i.hasNext())
355         {
356             String path = (String) i.next();
357             String located = locateTemplate(data, DIR_CONTROLS, path, template);
358 
359             if (null != located)
360             {
361                 return DIR_CONTROLS + located;
362             }
363         }
364 
365         return null;
366     }
367 
368     /***
369      * Locate a controller template using Jetspeed template location algorithm, searching by
370      * mediatype and language criteria extracted from the request state in rundata.
371      *
372      * @param data The rundata for the request.
373      * @param template The name of the template.
374      *
375      * @return The path relative to the controllers directory for the requested controller template,
376      *          or null if not found.
377      */
378     public String locateControllerTemplate(RunData data, String template)
379     {
380         List templatePaths = localizeTemplateName(data);
381         Iterator i = templatePaths.iterator();
382 
383         while (i.hasNext())
384         {
385             String path = (String) i.next();
386             String located = locateTemplate(data, DIR_CONTROLLERS, path, template);
387 
388             if (null != located)
389             {
390                 return DIR_CONTROLLERS + located;
391             }
392         }
393 
394         return null;
395     }
396 
397     /***
398      * Locate an email template using Jetspeed template location algorithm, searching by
399      * mediatype and language criteria extracted from the request state in rundata.
400      *
401      * @param data The rundata for the request.
402      * @param template The name of the template.
403      *
404      * @return The path relative to the emails directory for the requested email template,
405      *          or null if not found.
406      */
407     public String locateEmailTemplate(RunData data, String template)
408     {
409         CustomLocalizationService locService = (CustomLocalizationService) ServiceUtil.getServiceByName(
410             LocalizationService.SERVICE_NAME);
411         return locateEmailTemplate(data, template, locService.getLocale(data));
412     }
413 
414     /***
415      * Locate an email template using Jetspeed template location algorithm, searching by
416      * mediatype and language.
417      *
418      * @param data The rundata for the request.
419      * @param template The name of the template.
420      * @param locale The name of the language.
421      *
422      * @return The path relative to the emails directory for the requested email template,
423      *          or null if not found.
424      */
425     public String locateEmailTemplate(RunData data, String template, Locale locale)
426     {
427         List templatePaths = localizeTemplateName(data, locale);
428         Iterator i = templatePaths.iterator();
429 
430         while (i.hasNext())
431         {
432             String path = (String) i.next();
433             String located = locateTemplate(data, DIR_EMAILS, path, template);
434 
435             if (null != located)
436             {
437                 return DIR_EMAILS + located;
438             }
439         }
440 
441         return null;
442     }
443 
444     /***
445      * Locate a parameter style template using Jetspeed template location algorithm, searching by
446      * mediatype and language criteria extracted from the request state in rundata.
447      *
448      * @param data The rundata for the request.
449      * @param template The name of the template.
450      *
451      * @return The path relative to the portlets directory for the requested portlet template,
452      *          or null if not found.
453      */
454     public String locateParameterTemplate(RunData data, String template)
455     {
456         List templatePaths = localizeTemplateName(data);
457         Iterator i = templatePaths.iterator();
458 
459         while (i.hasNext())
460         {
461             String path = (String) i.next();
462             String located = locateTemplate(data, DIR_PARAMETERS, path, template);
463 
464             if (null != located)
465             {
466                 return DIR_PARAMETERS + located;
467             }
468         }
469 
470         return null;
471     }
472 
473     /***
474      * General template location algorithm. Starts with the most specific resource,
475      * including mediatype + nls specification, and fallsback to least specific.
476      *
477      * @param data The rundata for the request.
478      * @param resourceType The path specific to the resource type sought (eg /screens).
479      * @param path The fullest path to the template based on simple NLS/mediatype directory.
480      * @param template The name of the template.
481      *
482      * @return the exact path to the template, or null if not found.
483      */
484     private String locateTemplate(RunData data, String resourceType, String path, String template)
485     {
486         String located = null;
487 
488         // Iterate through each of the template roots
489         for (int i = 0; i < templateRoots.length; i++)
490         {
491             located = locateTemplate(data, resourceType, path, template, templateRoots[i]);
492             if (located != null)
493             {
494                 break;
495             }
496         }
497 
498         return located;
499     }
500 
501     /***
502      * General template location algorithm. Starts with the most specific resource,
503      * including mediatype + nls specification, and fallsback to least specific.
504      *
505      * @param data The rundata for the request.
506      * @param resourceType The path specific to the resource type sought (eg /screens).
507      * @param path The fullest path to the template based on simple NLS/mediatype directory.
508      * @param template The name of the template.
509      * @param templateRoot The template root to be searched.
510      *
511      * @return the exact path to the template, or null if not found.
512      */
513     private String locateTemplate(
514         RunData data,
515         String resourceType,
516         String path,
517         String template,
518         String templateRoot)
519     {
520         String finalPath;
521 
522         // make sure resourceType doesn't end with "/" but starts with "/"
523         if (resourceType.endsWith(PATH_SEPARATOR))
524         {
525             resourceType = resourceType.substring(0, resourceType.length() - 1);
526         }
527         if (!resourceType.startsWith(PATH_SEPARATOR))
528         {
529             resourceType = PATH_SEPARATOR + resourceType;
530         }
531         // make sure path doesn't end with "/" but starts with "/"
532         if (path.endsWith(PATH_SEPARATOR))
533         {
534             path = path.substring(0, path.length() - 1);
535         }
536         if (!path.startsWith(PATH_SEPARATOR))
537         {
538             path = PATH_SEPARATOR + path;
539         }
540         // make sure template starts with "/"
541         if (!template.startsWith(PATH_SEPARATOR))
542         {
543             template = PATH_SEPARATOR + template;
544         }
545 
546         StringBuffer fullPath = new StringBuffer(templateRoot);
547 
548         if (!templateRoot.endsWith(PATH_SEPARATOR))
549         {
550             fullPath.append(PATH_SEPARATOR);
551         }
552 
553         fullPath.append(getTemplateExtension(template));
554         fullPath.append(resourceType);
555 
556         String basePath = fullPath.toString();
557         String realPath = null;
558         String workingPath = null;
559 
560         do
561         {
562             workingPath = path + template;
563             realPath = TurbineServlet.getRealPath(basePath + workingPath);
564 
565             // the current template exists in cache, return the corresponding path
566             if (templateExists(realPath, true))
567             {
568                 if (logger.isDebugEnabled())
569                 {
570                     logger.debug(
571                         "TemplateLocator: template exists in cache: "
572                             + realPath
573                             + " returning "
574                             + workingPath);
575                 }
576 
577                 return workingPath;
578             }
579             else if (this.hotDeploy == true)
580             {
581                 // Try to locate it directly on file system, perhaps it was recently added
582                 if (templateExists(realPath, false))
583                 {
584                     if (logger.isDebugEnabled())
585                     {
586                         logger.debug(
587                             "TemplateLocator: template exists on the file system: "
588                                 + realPath
589                                 + " returning "
590                                 + workingPath);
591                     }
592 
593                     // add it to the map
594                     //templateMap.put(workingPath, null);
595                     templateMap.put(realPath, null);
596 
597                     return workingPath;
598                 }
599             }
600             // else strip path of one of its components and loop
601             int pt = path.lastIndexOf(PATH_SEPARATOR);
602             if (pt > -1)
603             {
604                 path = path.substring(0, pt);
605             }
606             else
607             {
608                 path = null;
609             }
610         }
611         while (path != null);
612 
613         return null;
614     }
615 
616     /***
617      * Helper function for template locator to find a localized (NLS) resource.
618      * Considers both language and country resources as well as all the possible
619      * media-types for the request
620      *
621      * @param data The rundata for the request.
622      *
623      * @return The possible paths to a localized template ordered by
624      * descending preference
625      */
626     private List localizeTemplateName(RunData data)
627     {
628         return localizeTemplateName(data, null);
629     }
630 
631     /***
632      * Helper function for template locator to find a localized (NLS) resource.
633      * Considers both language and country resources as well as all the possible
634      * media-types for the request
635      *
636      * @param data The rundata for the request.
637      * @param locale The locale for the request.
638      *
639      * @return The possible paths to a localized template ordered by
640      * descending preference
641      */
642     private List localizeTemplateName(RunData data, Locale inLocale)
643     {
644         List templates = new ArrayList();
645         Locale tmplocale = null;
646 
647         if (inLocale != null)
648         {
649             tmplocale = inLocale;
650         }
651         else
652         {
653             CustomLocalizationService locService = (CustomLocalizationService) ServiceUtil.getServiceByName(
654                 LocalizationService.SERVICE_NAME);
655             tmplocale = locService.getLocale(data);
656         }
657 
658         // Get the locale store it in the user object
659         if (tmplocale == null)
660         {
661             tmplocale =
662                 new Locale(
663                     TurbineResources.getString("locale.default.language", "en"),
664                     TurbineResources.getString("locale.default.country", "US"));
665         }
666 
667         data.getUser().setTemp("locale", tmplocale);
668 
669         StringBuffer templatePath = new StringBuffer();
670 
671         // retrieve all the possible media types
672         String type = data.getParameters().getString(Profiler.PARAM_MEDIA_TYPE, null);
673         List types = new ArrayList();
674         CapabilityMap cm = ((JetspeedRunData) data).getCapability();
675 
676         // Grab the Locale from the temporary storage in the User object
677         Locale locale = (Locale) data.getUser().getTemp("locale");
678         String language = locale.getLanguage();
679         String country = locale.getCountry();
680 
681         if (null != type)
682         {
683             types.add(type);
684         }
685         else
686         {
687             Iterator i = cm.listMediaTypes();
688             while (i.hasNext())
689             {
690                 types.add(i.next());
691             }
692         }
693 
694         Iterator typeIterator = types.iterator();
695 
696         while (typeIterator.hasNext())
697         {
698             type = (String) typeIterator.next();
699 
700             if ((type != null) && (type.length() > 0))
701             {
702                 templatePath.append(PATH_SEPARATOR).append(type);
703             }
704 
705             if ((language != null) && (language.length() > 0))
706             {
707                 templatePath.append(PATH_SEPARATOR).append(language);
708             }
709 
710             if ((country != null) && (country.length() > 0))
711             {
712                 templatePath.append(PATH_SEPARATOR).append(country);
713             }
714 
715             templates.add(templatePath.toString());
716             templatePath.setLength(0);
717         }
718 
719         return templates;
720     }
721 
722     /***
723      * Returns the extension for the specified template
724      *
725      * @param template the template name to scan for an extension
726      * @return the template extension if it exists or the default
727      * template extension
728      */
729     private String getTemplateExtension(String template)
730     {
731         String ext = TurbineTemplate.getDefaultExtension();
732 
733         int idx = template.lastIndexOf(".");
734 
735         if (idx > 0)
736         {
737             ext = template.substring(idx + 1);
738         }
739 
740         return ext;
741     }
742 
743     /***
744      * Checks for the existence of a template resource given a key.
745      * The key are absolute paths to the templates, and are cached
746      * in a template cache for performance.
747      *
748      * @param key The absolute path to the template resource.
749      *
750      * @return True when the template is found, otherwise false.
751      */
752     public boolean templateExists(String templateKey, boolean useNameCache)
753     {
754         if (null == templateKey)
755         {
756             return false;
757         }
758 
759         if (useNameCache == true)
760         {
761             return templateMap.containsKey(templateKey);
762         }
763 
764         return (new File(templateKey).exists());
765     }
766 
767     /***
768      * Loads the configuration parameters for this service from the
769      * JetspeedResources.properties file.
770      *
771      * @exception throws a <code>InitializationException</code> if the service
772      * fails to initialize
773      */
774     private void initConfiguration() throws InitializationException
775     {
776 
777         templateRoots =
778             JetspeedResources.getStringArray(
779                 TurbineServices.SERVICE_PREFIX
780                     + TemplateLocatorService.SERVICE_NAME
781                     + CONFIG_TEMPLATE_ROOT);
782 
783         if ((templateRoots == null) || (templateRoots.length == 0))
784         {
785             throw new InitializationException(MSG_MISSING_PARAMETER + CONFIG_TEMPLATE_ROOT);
786         }
787 
788         templateMap = new HashMap();
789 
790         for (int i = 0; i < templateRoots.length; i++)
791         {
792             String templateRoot = templateRoots[i];
793 
794             if (!templateRoot.endsWith(PATH_SEPARATOR))
795             {
796                 templateRoot = templateRoot + PATH_SEPARATOR;
797             }
798 
799             if (logger.isDebugEnabled())
800             {
801                 logger.debug("TemplateLocator: Adding templateRoot:" + templateRoot);
802             }
803 
804             // traverse starting from the root template directory and add resources
805             String templateRootPath = TurbineServlet.getRealPath(templateRoot);
806             if (null != templateRootPath)
807             {
808                 loadNameCache(templateRootPath, "");
809             }
810         }
811 
812         
813         velocityService =
814             (VelocityService) TurbineServices.getInstance().getService(
815                 VelocityService.SERVICE_NAME);
816 
817         jspService = (JspService) TurbineServices.getInstance().getService(JspService.SERVICE_NAME);
818 
819         useGlobalPortletSearch = JetspeedResources.getBoolean(
820                 TurbineServices.SERVICE_PREFIX
821                     + TemplateLocatorService.SERVICE_NAME
822                     + CONFIG_PORTLET_GLOBAL_SEARCH, false);
823 
824         hotDeploy = JetspeedResources.getBoolean(
825                 TurbineServices.SERVICE_PREFIX
826                     + TemplateLocatorService.SERVICE_NAME
827                     + CONFIG_HOT_DEPLOY, true);
828 
829     }
830 
831     /***
832      * Loads the template name cache map to accelerate template searches.
833      *
834      * @param path The template
835      * @param name just the name of the resource
836      */
837     private void loadNameCache(String path, String name)
838     {
839         File file = new File(path);
840         if (file.isFile())
841         {
842             // add it to the map
843             templateMap.put(path, null);
844         }
845         else
846         {
847             if (file.isDirectory())
848             {
849                 if (!path.endsWith(File.separator))
850                 {
851                     path += File.separator;
852                 }
853 
854                 String list[] = file.list();
855 
856                 // Process all files recursivly
857                 for (int ix = 0; list != null && ix < list.length; ix++)
858                 {
859                     loadNameCache(path + list[ix], list[ix]);
860                 }
861             }
862         }
863     }
864 
865     /***
866      * Correctly locate the default layout based on the 
867      * default.layout.template property of the appropriate
868      * template service.
869      * @author <a href="mailto:sweaver@rippe.com">Scott Weaver</a>
870      */
871     private String getTemplateLayout(String extension)
872     {
873         String dftLayout = "/default." + extension;
874 
875         Configuration velocityCfg = null;
876         Configuration jspCfg = null;
877         if (velocityService != null)
878         {
879             velocityCfg = velocityService.getConfiguration();
880         }
881 
882         if (jspService != null)
883         {
884             jspCfg = jspService.getConfiguration();
885         }
886 
887         if (velocityCfg != null
888             && velocityCfg.getString(TEMPLATE_EXTENSION).indexOf(extension) > -1)
889         {
890             return velocityCfg.getString(DEFAULT_LAYOUT, dftLayout);
891         }
892         else if (jspCfg != null && jspCfg.getString(TEMPLATE_EXTENSION).indexOf(extension) > -1)
893         {
894             return jspCfg.getString(DEFAULT_LAYOUT, dftLayout);
895         }
896         else
897         {
898             return dftLayout;
899         }
900     }
901 }