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