You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by in...@apache.org on 2001/03/08 17:10:13 UTC

cvs commit: jakarta-jetspeed/src/java/org/apache/jetspeed/services/template JetspeedTemplateService.java

ingo        01/03/08 08:10:13

  Added:       src/java/org/apache/jetspeed/services/template
                        JetspeedTemplateService.java
  Log:
  [MLS] Multi- markup & language support. First "simple" implementation.
  
  Revision  Changes    Path
  1.1                  jakarta-jetspeed/src/java/org/apache/jetspeed/services/template/JetspeedTemplateService.java
  
  Index: JetspeedTemplateService.java
  ===================================================================
  package org.apache.jetspeed.services.template;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  
  
  // Java Core Classes
  import java.util.*;
  import java.io.File;
  import javax.servlet.*;
  
  // Turbine Utility Classes
  import org.apache.turbine.util.*;
  import org.apache.turbine.services.*;
  import org.apache.turbine.services.template.TemplateService;
  import org.apache.turbine.services.resources.TurbineResources;
  import org.apache.turbine.modules.*;
  
  /**
   * This service extends the TurbineTemplateService to modify its behaviour:
   * Not only layout and screen packages, but also the screen templates
   * are searched in the template neames filepath, so that a fallback
   * strategy is provided, that can be used for multi-language, multi-device 
   * and browser-specific support support.
   * E.g: a template name "/html/en/US/IE/mytemplate" would search for 
   * following files (in the given order):
   * 1. /html/en/US/IE/mytemplate
   * 2. /html/en/US/mytemplate
   * 3. /html/en/mytemplate
   * 4. /html/mytemplate
   * 5. /mytemplate
   *
   * @author <a href="mailto:ingo@apache.org">Ingo Schuster</a>
   * @version
   */
  public class JetspeedTemplateService
      extends TurbineBaseService
      implements TemplateService
  {
      /** The hashtable used to cache Screen names. */
      private Hashtable screenCache = null;
  
      /** The hashtable used to cache screen template names. */
      private Hashtable templateCache = null;
  
      /** The hashtable used to cache Navigation names. */
      private Hashtable navCache = null;
  
      /** The hashtable used to cache layout template names. */
      private Hashtable layoutCache = null;
  
      /** Flag set if cache is to be used. */
      private boolean useCache = false;
  
      /** Default extension. */
      private String extension;
  
      /** Default layout template. */
      private String defaultLayoutTemplate;
  
      /** Default Navigation module. */
      private String defaultNavigation;
  
      /** Default Screen module. */
      private String defaultScreen;
  
      /**
       * The absolute paths where the appropriate template engine will
       * be searching for templates.
       */
      private String[] templateRoot = null;
  
      /**
       * Called the first time the Service is used.
       *
       * @param config A ServletConfig.
       */
      public void init(ServletConfig config)
          throws InitializationException
      {
          try
          {
              initTemplate(config);
              setInit(true);
              org.apache.turbine.util.Log.info ("TemplateService " +
                                                "init()....finished!");
          }
          catch (Exception e)
          {
              throw new InitializationException("TurbineTemplateService failed to initialize", e);
          }
      }
  
      /**
       * TODO: Document this class.
       *
       * @param config A ServletConfig.
       * @exception Exception, a generic exception.
       */
      private void initTemplate(ServletConfig config)
          throws Exception
      {
          useCache = TurbineResources.getBoolean("modules.cache", true);
          Properties props = getProperties();
  
          if (useCache)
          {
              int layoutSize = Integer
                  .parseInt(props.getProperty("layout.cache.size", "5"));
              int navigationSize = Integer
                  .parseInt(props.getProperty("navigation.cache.size", "10"));
              int screenSize = Integer
                  .parseInt(props.getProperty("screen.cache.size", "5"));
              int templateSize = Integer
                  .parseInt(props.getProperty("screen.cache.size", "50"));
              layoutCache = new Hashtable( (int)(1.25*layoutSize) + 1);
              navCache = new Hashtable( (int)(1.25*navigationSize) + 1);
              screenCache = new Hashtable( (int)(1.25*screenSize) + 1);
              templateCache = new Hashtable( (int)(1.25*templateSize) + 1);
          }
          // relative to the webapp root directory
          String templatePaths = props
              .getProperty("template.path", "/templates");
  
          // If possible, transform paths to be webapp root relative.
          templatePaths = ServletUtils.expandRelative(config,
                                                       templatePaths);
  
          // store the converted paths in service properties for 
          // Turbine based providers 
          props.put("template.path", templatePaths);
  
          // tokenize the template.path property and assign to an array
          String pathSep = System.getProperty("path.separator");
          StringTokenizer st = new StringTokenizer(templatePaths,pathSep);
          templateRoot = new String[st.countTokens()];
          int pos = 0;
          while(st.hasMoreTokens())
          {
              templateRoot[pos++] = st.nextToken();
          }
  
          // the extension that is added to layout templates (e.g.)
          extension = props.getProperty("default.extension", "html");              
  
          // the default modules 
          defaultNavigation = props
              .getProperty("default.navigation", "TemplateNavigation");
          defaultScreen = props.getProperty("default.screen", "TemplateScreen");  
          
          // the default layout template
          defaultLayoutTemplate = props
              .getProperty("default.layout.template", "/default." + extension);
          
          if (defaultLayoutTemplate.indexOf('.') == -1)
          {
              defaultLayoutTemplate = defaultLayoutTemplate + "." + extension;
          }
      }
  
      /**
       *  Adds the object into the hashtable.
       *
       * @param key The String key for the object.
       * @param value The Object.
       * @param h The Hashtable.
       */
      private void addToCache ( String key,
                                Object value,
                                Hashtable h )
      {
          if (useCache && value != null)
          {
              h.put(key, value);
          }
      }
  
      /**
       * Get the Screen template given in the properties file.
       *
       * @return A String which is the value of the TemplateService 
       * default.screen property.
       */
      public String getDefaultScreen()
      {
          return defaultScreen;
      }
      
      /**
       * Get the default Navigation given in the properties file.
       *
       * @return A String which is the value of the TemplateService 
       * default.navigation property.
       */
      public String getDefaultNavigation()
      {
          return defaultNavigation;
      }
  
      /**
       * Get the default layout template given in the properties file.
       *
       * @return A String which is the value of the TemplateService 
       * default.layout.template property.
       */
      public String getDefaultLayoutTemplate()
      {
          return defaultLayoutTemplate;
      }
  
      
      /**
       * Locate and return the name of a screen template.
       *
       *
       * @param name A String which is the key to the template.
       * @return A String with the screen template path.
       * @exception Exception, a generic exception.
       */
      public String getScreenTemplateName(String key)
          throws Exception
      {
          if (name==null)
              throw new Exception ("TurbineTemplateService: " + 
                  "getLayoutTemplateName() was passed in a null value.");
  
          String name = null;
  
          if (  useCache && templateCache.containsKey(key) )
          {
              name = (String)templateCache.get(key);
          }
          else
          {
              String[] names = parseScreenTemplate(key);
              name = names[2];
              addToCache( key, names[0], screenCache );
              addToCache( key, names[1], layoutCache );
              addToCache( key, names[2], templateCache );
          }
          return name;
      }
      /**
       * Locate and return the name of a layout template.
       *
       *
       * @param name A String with the name of the template.
       * @return A String with the layout template path.
       * @exception Exception, a generic exception.
       */
      public String getLayoutTemplateName(String name)
          throws Exception
      {
          if (name==null)
              throw new Exception ("TurbineTemplateService: " + 
                  "getLayoutTemplateName() was passed in a null value.");
  
          String layoutName = null;
  
          if (  useCache && layoutCache.containsKey(name) )
          {
              layoutName = (String)layoutCache.get(name);
          }
          else
          {
              String[] names = parseScreenTemplate(name);
              layoutName = names[1];
              addToCache( name, names[0], screenCache );
              addToCache( name, names[1], layoutCache );
              addToCache( name, names[2], templateCache );
          }
          return layoutName;
      }
  
      /**
       * Locate and return the name of a Navigation module.
       *
       * @param name A String with the name of the template.
       * @return A String with the name of the navigation.
       * @exception Exception, a generic exception.
       */
      public String getNavigationName(String name)
          throws Exception
      {
          if (name==null)
              throw new Exception ("TurbineTemplateService: " + 
                  "getNavigationName() was passed in a null value.");
  
          String nav_name = null;
  
          if (  useCache && navCache.containsKey(name) )
          {
              nav_name = (String)navCache.get(name);
          }
          else
          {
              nav_name = parseNavigationTemplate(name);
              addToCache( name, nav_name, navCache );
          }
          return nav_name;
      }
  
      /**
       * Locate and return the name of a Screen module.
       *
       * @param name A String with the name of the template.
       * @return A String with the name of the screen.
       * @exception Exception, a generic exception.
       */
      public String getScreenName(String name)
          throws Exception
      {
  
          if (name==null)
              throw new Exception ("TurbineTemplateService: " + 
                  "getScreenName() was passed in a null value.");
  
          String screenName = null;
  
          if (  useCache && screenCache.containsKey(name) )
          {
              screenName = (String)screenCache.get(name);
          }
          else
          {
              String[] names = parseScreenTemplate(name);
              screenName = names[0];
              addToCache( name, names[0], screenCache );
              addToCache( name, names[1], layoutCache );
              addToCache( name, names[2], templateCache );
          }
          return screenName;
      }
  
      /**
       * Get the default extension given in the properties file.
       *
       * @return A String with the extension.
       */
      public String getDefaultExtension()
      {
          return extension;
      }
  
      /**
       * This method takes the template parameter and parses it, so that
       * relevant Screen/Layout-template information can be extracted.
       *
       * @param template A String with the template name.
       * @return A String[] where the first element is the Screen name
       *         and the second element is the layout template.
       */
      protected String[] parseScreenTemplate( String template ) throws Exception
      {
          // check if an extension was included.  if not, add the default
          if ( template.indexOf('.') == -1 )
          {
              template = template + "." + getDefaultExtension(); 
          }
  
          Log.note("JetspeedTemplateService.parseScreen: template = " + template);
          
          StringTokenizer st = new StringTokenizer(template, "/");
          List tokens = new ArrayList(st.countTokens());
          while(st.hasMoreTokens())
          {
              String token = st.nextToken();
              if (!token.equals(""))
              {
                  tokens.add(token);
              }
          }
          Log.note("JetspeedTemplateService.parseScreen: tokens1: " + tokens);
          String fileName = (String)tokens.get(tokens.size() - 1);
          tokens.remove(tokens.size()-1);
          int dot = fileName.lastIndexOf('.');
          String className = null;
          if (dot>0)
          {
              className = fileName.substring(0, dot);
          }
          else
          {
              className = fileName;
          }
          String firstChar = String.valueOf(className.charAt(0));
          firstChar = firstChar.toUpperCase();
          className = firstChar + className.substring(1);
          Log.note("JetspeedTemplateService.parseScreen: tokens2: " + tokens);
  
          // make sure the template exists and determine the correct
          // templateRoot path
          String pathRoot = null;
          String allPaths = "";
          String pathSep = System.getProperty("path.separator");
          for (int i=0; i<templateRoot.length; i++)
          {
          Log.note("JetspeedTemplateService.parseScreen: templateRoot " + i + " " + templateRoot[i]);
  
              String templatePath = null;
          
              for (int k=tokens.size(); k>=0;  k--)
              {
                  StringBuffer path = new StringBuffer();
                  for (int j=0; j<k; j++)
                  {
                      path.append("/").append((String)tokens.get(j));
                  }
                  StringBuffer distinctPath = new StringBuffer(path.toString()).append("/").append(fileName);
                  templatePath = distinctPath.toString();
                  Log.note("JetspeedTemplateService.parseScreen: Path: " + templatePath);
           
                  if (new File(templateRoot[i] + "/screens" + templatePath).exists())
                  {
                      template = templatePath;
                      Log.note("JetspeedTemplateService.parseScreen: template found: " + template);
                      break;
                  }
                  templatePath = null;
              }
              if (templatePath != null) {
                  pathRoot = templateRoot[i];
                  Log.note("JetspeedTemplateService.parseScreen: pathRoot: " + pathRoot);
                  break;
              }
              allPaths += pathSep + templateRoot[i];
          }
          if (pathRoot == null)
          {
              throw new Exception("The screen template: " +
                                  template +
                                  " does not exist in " +
                                  allPaths.substring(pathSep.length()) +
                                  ", so the TemplateService could not " +
                                  "determine associated templates.");
          }
  
          String[] paths = new String[tokens.size() + 2];
          String[] pkgs = new String[tokens.size() + 2];
          int arrayIndex = 0;
          for (int i=tokens.size(); i>=0;  i--)
          {
              StringBuffer path = new StringBuffer();
              StringBuffer pkg = new StringBuffer();
              for (int j=0; j<i; j++)
              {
                  path.append("/").append((String)tokens.get(j));
                  pkg.append((String)tokens.get(j)).append('.');
              }
              if ( i == tokens.size() )
              {
                  StringBuffer distinctPath = new StringBuffer(path.toString());
                  StringBuffer distinctPkg = new StringBuffer(pkg.toString());
                  paths[arrayIndex] = distinctPath.append('/').append(fileName).toString();
                  pkgs[arrayIndex] = distinctPkg.append(className).toString();
                  arrayIndex++;
              }
              paths[arrayIndex] = path.append(defaultLayoutTemplate).toString();
              pkgs[arrayIndex] = pkg.append("Default").toString();
              arrayIndex++;
          }
  
          String[] holder = new String[3];
          holder[0] = getScreenName(pkgs);
          holder[1] = getLayoutTemplateName(pathRoot, paths);
          holder[2] = template;
          return holder;
      }
  
      /**
       * Parse the template name out to a package path to locate the
       * Navigation module.  This is different than the Screen/Layout
       * parser in that it only looks for packages.  Note: If caching is
       * enabled, this is only performed once for each unique template.
       *
       * @param String The template name (i.e folder/headernav.wm).
       * @return A String with the name of the Navigation module to use
       * for the template.
       */
      protected String parseNavigationTemplate( String template )
      {
          StringTokenizer st = new StringTokenizer(template, "/");
          List tokens = new ArrayList(st.countTokens());
          while(st.hasMoreTokens())
          {
              String token = st.nextToken();
              if (!token.equals(""))
              {
                  tokens.add(token);
              }
          }
          String fileName = (String)tokens.get(tokens.size() - 1);
          tokens.remove(tokens.size() - 1);
          int dot = fileName.lastIndexOf('.');
          String className = null;
          if (dot>0)
          {
              className = fileName.substring(0, dot);
          }
          else
          {
              className = fileName;
          }
          String firstChar = String.valueOf(className.charAt(0));
          firstChar = firstChar.toUpperCase();
          className = firstChar + className.substring(1);
  
          String[] pkgs = new String[tokens.size() + 2];
          int arrayIndex = 0;
          for (int i=tokens.size(); i>=0;  i--)
          {
              StringBuffer pkg = new StringBuffer();
              for (int j=0; j<i; j++)
              {
                  pkg.append((String)tokens.get(j)).append('.');
              }
              if ( i == tokens.size() )
              {
                  StringBuffer distinctPkg = new StringBuffer(pkg.toString());
                  pkgs[arrayIndex] = distinctPkg.append(className).toString();
                  arrayIndex++;
              }
              pkgs[arrayIndex] = pkg.append("Default").toString();
              arrayIndex++;
          }
          return getNavigationName( pkgs);
      }
  
      /**
       * Extract possible layouts paths.
       *
       * @param possiblePaths A String[] with possible paths to search.
       * @return A String with the name of the layout template.
       */
      private String getLayoutTemplateName(String pathRoot, String[] possiblePaths)
      {
          for (int i=0; i<possiblePaths.length; i++)
          {
              if (new File(pathRoot, "layouts" + possiblePaths[i]).exists())
              {
                  return possiblePaths[i];
              }
          }
          return defaultLayoutTemplate;
      }
  
      /**
       * Extract a possible Screen from the packages.
       *
       * @param possibleScreens A String[] with possible paths to
       * search.
       * @return A String with the name of the Screen class to use.
       */
      private String getScreenName( String[] possibleScreens)
      {
          for (int i=0; i<possibleScreens.length; i++)
          {
              try
              {
                  ScreenLoader.getInstance().getInstance(possibleScreens[i]);
                  return possibleScreens[i];
              }
              catch (Exception e) {}
          }
          return defaultScreen;
      }
  
  
      /**
       * Seaches for the Navigation class that may match the
       * name of the Navigation template.
       *
       * @param possibleNavigations A String[] with possible navigation
       * packages.
       * @return A String with the name of the Navigation class to use.
       */
      private String getNavigationName( String[] possibleNavigations)
      {
          for (int i=0; i<possibleNavigations.length; i++)
          {
              try
              {
                  NavigationLoader.getInstance().getInstance(possibleNavigations[i]);
                  return possibleNavigations[i];
              }
              catch (Exception e) {}
          }
          return defaultNavigation;
      }
  }
  
  
  
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jetspeed-dev-help@jakarta.apache.org