Author: apetrelli
Date: Sun Dec 3 08:11:53 2006
New Revision: 481785
URL: http://svn.apache.org/viewvc?view=rev&rev=481785
Log:
SB-91
Ported ChannelFactorySet to extend UrlDefinitionsFactory and renamed to
ChannelDefinitionsFactory.
Added:
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelDefinitionsFactory.java
- copied, changed from r481578,
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelFactorySet.java
Removed:
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelFactorySet.java
Modified:
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/SelectChannelAction.java
Copied:
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelDefinitionsFactory.java
(from r481578,
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelFactorySet.java)
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelDefinitionsFactory.java?view=diff&rev=481785&p1=struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelFactorySet.java&r1=481578&p2=struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelDefinitionsFactory.java&r2=481785
==============================================================================
---
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelFactorySet.java
(original)
+++
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/ChannelDefinitionsFactory.java
Sun Dec 3 08:11:53 2006
@@ -24,29 +24,23 @@
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
import java.util.Map;
-import javax.servlet.ServletContext;
-import javax.servlet.ServletRequest;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSession;
-
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.struts.tiles.xmlDefinition.FactorySet;
-import org.apache.struts.tiles.xmlDefinition.XmlDefinitionsSet;
-import org.apache.struts.tiles.xmlDefinition.XmlParser;
-import org.apache.tiles.definition.DefinitionsFactory;
+import org.apache.tiles.context.TilesRequestContext;
+import org.apache.tiles.definition.ComponentDefinition;
+import org.apache.tiles.definition.ComponentDefinitions;
import org.apache.tiles.definition.DefinitionsFactoryException;
-import org.apache.tiles.definition.FactoryNotFoundException;
-import org.xml.sax.SAXException;
+import org.apache.tiles.definition.UrlDefinitionsFactory;
/**
- * Component Definitions factory.
- * This implementation of Component Definitions factory allows i18n
- * Component definitions factory allowing i18n definition.
+ * Channel Definitions factory.
* A definition is retrieved by its name, and using locale setted in
appropriate
* session context. Definitions are defined in different files, one for each
locale.
* A definition file is loaded using common name extended with locale code
@@ -55,164 +49,117 @@
*
* @version $Rev$ $Date$
*/
-public class ChannelFactorySet extends FactorySet {
-
- private static final Log log = LogFactory.getLog(ChannelFactorySet.class);
-
- /**
- * Debug flag.
- * @deprecated This will be removed in a release after Struts 1.2.
- */
- public static final boolean debug = false;
-
- /**
- * Default name.
- */
- public static final String DEFAULT_DEFINITIONS_FILE_NAME =
- "/WEB-INF/templateDefinitions.xml";
+public class ChannelDefinitionsFactory extends UrlDefinitionsFactory {
- /**
- * Config file parameter name.
- */
- public static final String DEFINITIONS_CONFIG_PARAMETER_NAME =
- "definitions-config";
+ // FIXME This class contains too much code from UrlDefinitionsFactory.
+ // Probably that class must be refactored to allow an easier extension, but
+ // maybe we should wait until Dimensions is incubated.
+
+ private static final Log log =
LogFactory.getLog(ChannelDefinitionsFactory.class);
/**
* Config file parameter name.
*/
public static final String FACTORY_SELECTOR_KEY =
- "ChannelFactorySet.factorySelectorKey";
-
- /**
- * Default filenames extension.
- */
- public static final String FILENAME_EXTENSION = ".xml";
-
- /**
- * Default factory.
- */
- protected DefinitionsFactory defaultFactory = null;
-
- /**
- * Xml parser used.
- */
- protected XmlParser xmlParser = null;
-
- /**
- * Names of default file containing definition descriptions.
- */
- private String filename = null;
-
- /**
- * Collection of already loaded definitions set, referenced by their
suffix.
- */
- private Map loaded = null;
-
- /**
- * Parameterless Constructor.
- * Method initFactory must be called prior to any use of created factory.
- */
- public ChannelFactorySet() {
- super();
- }
+ "ChannelDefinitionsFactory.factorySelectorKey";
/**
- * Constructor.
- * Init the factory by reading appropriate configuration file.
- * @throws FactoryNotFoundException Can't find factory configuration file.
+ * Contains a list of locales that have been processed.
*/
- public ChannelFactorySet(ServletContext servletContext, Map properties)
- throws DefinitionsFactoryException {
+ private List<String> processedLocales;
- initFactory(servletContext, properties);
- }
+ private ComponentDefinitions definitions;
/**
- * Initialization method.
- * Init the factory by reading appropriate configuration file.
- * This method is called exactly once immediately after factory creation in
- * case of internal creation (by DefinitionUtil).
- * @param servletContext Servlet Context passed to newly created factory.
- * @param properties Map of name/property passed to newly created factory.
Map can contains
- * more properties than requested.
- * @throws DefinitionsFactoryException An error occur during
initialization.
+ * Returns a ComponentDefinition object that matches the given name and
+ * Tiles context
+ *
+ * @param name The name of the ComponentDefinition to return.
+ * @param tilesContext The Tiles context to use to resolve the definition.
+ * @return the ComponentDefinition matching the given name or null if none
+ * is found.
+ * @throws DefinitionsFactoryException if an error occurs reading
definitions.
*/
- public void initFactory(ServletContext servletContext, Map properties)
+ @Override
+ public ComponentDefinition getDefinition(String name,
+ TilesRequestContext tilesContext)
throws DefinitionsFactoryException {
- // read properties values
- String proposedFilename =
- (String) properties.get(DEFINITIONS_CONFIG_PARAMETER_NAME);
-
- // Compute filenames to use
- boolean isFileSpecified = true;
- if (proposedFilename == null) {
- proposedFilename = DEFAULT_DEFINITIONS_FILE_NAME;
- isFileSpecified = false;
- }
-
- try {
- initFactory(servletContext, proposedFilename);
- return;
-
- } catch (FileNotFoundException ex) {
- // If a filename is specified, throw appropriate error.
- if (isFileSpecified) {
- throw new FactoryNotFoundException(
- ex.getMessage()
- + " : Can't find file '"
- + proposedFilename
- + "'");
+ ComponentDefinitions definitions = getComponentDefinitions();
+ String key = getLocaleKey(tilesContext);
+ Locale locale = getLocale(key);
+
+ if (tilesContext != null) {
+ locale = tilesContext.getRequestLocale();
+ if (!isContextProcessed(tilesContext)) {
+ synchronized (definitions) {
+ addDefinitions(definitions, tilesContext);
+ }
}
}
+ return definitions.getDefinition(name, locale);
}
/**
- * Initialization method.
- * Init the factory by reading appropriate configuration file.
- * This method is called exactly once immediately after factory creation in
- * case of internal creation (by DefinitionUtil).
- * @param servletContext Servlet Context passed to newly created factory.
- * @param proposedFilename File names, comma separated, to use as base
file names.
- * @throws DefinitionsFactoryException An error occur during
initialization.
+ * Appends locale-specific [EMAIL PROTECTED] ComponentDefinition} objects
to an existing
+ * [EMAIL PROTECTED] ComponentDefinitions} set by reading locale-specific
versions of
+ * the applied sources.
+ *
+ * @param definitions The ComponentDefinitions object to append to.
+ * @param tilesContext The requested locale.
+ * @throws DefinitionsFactoryException if an error occurs reading
definitions.
*/
- protected void initFactory(
- ServletContext servletContext,
- String proposedFilename)
- throws DefinitionsFactoryException, FileNotFoundException {
-
- filename = proposedFilename;
- loaded = new HashMap();
- defaultFactory = createDefaultFactory(servletContext);
- }
-
- /**
- * Get default factory.
- * @return Default factory
- */
- protected DefinitionsFactory getDefaultFactory() {
- return defaultFactory;
- }
-
- /**
- * Create default factory .
- * @param servletContext Current servlet context. Used to open file.
- * @return Created default definition factory.
- * @throws DefinitionsFactoryException If an error occur while creating
factory.
- * @throws FileNotFoundException if factory can't be loaded from filenames.
- */
- protected DefinitionsFactory createDefaultFactory(ServletContext
servletContext)
- throws DefinitionsFactoryException, FileNotFoundException {
-
- XmlDefinitionsSet rootXmlConfig = parseXmlKeyFile(servletContext, "",
null);
+ @Override
+ protected void addDefinitions(ComponentDefinitions definitions,
+ TilesRequestContext tilesContext)
+ throws DefinitionsFactoryException {
+ String key = getLocaleKey(tilesContext);
- if (rootXmlConfig == null) {
- throw new FileNotFoundException();
+ if (isContextProcessed(tilesContext)) {
+ return;
+ }
+
+ if (key == null) {
+ return;
}
- rootXmlConfig.resolveInheritances();
- return new DefinitionsFactory(rootXmlConfig);
+ processedLocales.add(key);
+ Locale locale = getLocale(key);
+ List<String> postfixes = calculatePostfixes(locale);
+ Map localeDefsMap = new HashMap();
+ for (Object postfix : postfixes) {
+ // For each postfix, all the sources must be loaded.
+ for (Object source : sources) {
+ URL url = (URL) source;
+ String path = url.toExternalForm();
+
+ String newPath = concatPostfix(path, (String) postfix);
+ try {
+ URL newUrl = new URL(newPath);
+ URLConnection connection = newUrl.openConnection();
+ connection.connect();
+ lastModifiedDates.put(newUrl.toExternalForm(),
+ connection.getLastModified());
+
+ // Definition must be collected, starting from the base
+ // source up to the last localized file.
+ Map defsMap = reader.read(connection.getInputStream());
+ if (defsMap != null) {
+ localeDefsMap.putAll(defsMap);
+ }
+ } catch (FileNotFoundException e) {
+ // File not found. continue.
+ } catch (IOException e) {
+ throw new DefinitionsFactoryException(
+ "I/O error processing configuration.");
+ }
+ }
+ }
+
+ // At the end of definitions loading, they can be assigned to
+ // ComponentDefinitions implementation, to allow inheritance
resolution.
+ definitions.addDefinitions(localeDefsMap, locale);
}
/**
@@ -223,173 +170,49 @@
* @return the key or null if not found.
* @roseuid 3AF6F887018A
*/
- protected Object getDefinitionsFactoryKey(
- String name,
- ServletRequest request,
- ServletContext servletContext) {
- Object key = null;
+ @Override
+ protected boolean isContextProcessed(TilesRequestContext tilesContext) {
+ String key = null;
- HttpSession session = ((HttpServletRequest) request).getSession(false);
+ Map session = tilesContext.getSessionScope();
if (session != null) {
- key = session.getAttribute(FACTORY_SELECTOR_KEY);
+ key = (String) session.get(FACTORY_SELECTOR_KEY);
}
-
- return key;
+
+ return processedLocales.contains(key);
}
- /**
- * Create a factory for specified key.
- * If creation failed, return default factory, and output an error message
in
- * console.
- * @param key
- * @return Definition factory for specified key.
- * @throws DefinitionsFactoryException If an error occur while creating
factory.
- */
- protected DefinitionsFactory createFactory(
- Object key,
- ServletRequest request,
- ServletContext servletContext)
+ private ComponentDefinitions getComponentDefinitions()
throws DefinitionsFactoryException {
-
- if (key == null) {
- return getDefaultFactory();
+ if (definitions == null) {
+ definitions = readDefinitions();
}
-
- // Already loaded ?
- DefinitionsFactory factory = (DefinitionsFactory) loaded.get(key);
- if (factory != null) { // yes, stop loading
- return factory;
- }
-
- // Try to load file associated to key. If fail, stop and return
default factory.
- XmlDefinitionsSet lastXmlFile =
- parseXmlKeyFile(servletContext, "_" + (String) key, null);
-
- if (lastXmlFile == null) {
- log.warn(
- "No definition factory associated to key '"
- + key
- + "'. Use default factory instead.");
-
- factory = getDefaultFactory();
- loaded.put(key, factory);
- return factory;
- }
-
- // Parse default file, and add key file.
- XmlDefinitionsSet rootXmlConfig = parseXmlKeyFile(servletContext, "",
null);
-
- rootXmlConfig.extend(lastXmlFile);
- rootXmlConfig.resolveInheritances();
-
- factory = new DefinitionsFactory(rootXmlConfig);
- loaded.put(key, factory);
-
- log.info(factory);
-
- // return last available found !
- return factory;
- }
-
- /**
- * Parse files associated to postix if they exist.
- * For each name in filenames, append postfix before file extension,
- * then try to load the corresponding file.
- * If file doesn't exist, try next one. Each file description is added to
- * the XmlDefinitionsSet description.
- * The XmlDefinitionsSet description is created only if there is a
definition file.
- * Inheritance is not resolved in the returned XmlDefinitionsSet.
- * If no description file can be opened, and no definiion set is provided,
return null.
- * @param postfix Postfix to add to each description file.
- * @param xmlDefinitions Definitions set to which definitions will be
added. If null, a definitions
- * set is created on request.
- * @return XmlDefinitionsSet The definitions set created or passed as
parameter.
- * @throws DefinitionsFactoryException If an error happen during file
parsing.
- */
- private XmlDefinitionsSet parseXmlKeyFile(
- ServletContext servletContext,
- String postfix,
- XmlDefinitionsSet xmlDefinitions)
- throws DefinitionsFactoryException {
- if (postfix != null && postfix.length() == 0)
- postfix = null;
-
- String fullName = concatPostfix(filename, postfix);
- return parseXmlFile(servletContext, fullName, xmlDefinitions);
+ return definitions;
}
+
+ private String getLocaleKey(TilesRequestContext tilesContext) {
+ String key = null;
- /**
- * Parse specified xml file and add definition to specified definitions
set.
- * This method is used to load several description files in one instances
list.
- * If filename exist and definition set is null, create a new set.
Otherwise, return
- * passed definition set (can be null).
- * @param servletContext Current servlet context. Used to open file.
- * @param filename Name of file to parse.
- * @param xmlDefinitions Definitions set to which definitions will be
added. If null, a definitions
- * set is created on request.
- * @return XmlDefinitionsSet The definitions set created or passed as
parameter.
- * @throws DefinitionsFactoryException If an error happen during file
parsing.
- */
- private XmlDefinitionsSet parseXmlFile(
- ServletContext servletContext,
- String filename,
- XmlDefinitionsSet xmlDefinitions)
- throws DefinitionsFactoryException {
-
- try {
- log.debug("Trying to load '" + filename + "'.");
-
- InputStream input = servletContext.getResourceAsStream(filename);
- if (input == null) {
- return xmlDefinitions;
- }
-
- xmlParser = new XmlParser();
-
- // Check if definition set already exist.
- if (xmlDefinitions == null) {
- xmlDefinitions = new XmlDefinitionsSet();
- }
-
- xmlParser.parse(input, xmlDefinitions);
-
- } catch (SAXException ex) {
- log.debug("Error while parsing file '" + filename + "'.", ex);
-
- throw new DefinitionsFactoryException(
- "Error while parsing file '" + filename + "'. " +
ex.getMessage(),
- ex);
-
- } catch (IOException ex) {
- throw new DefinitionsFactoryException(
- "IO Error while parsing file '" + filename + "'. " +
ex.getMessage(),
- ex);
+ Map session = tilesContext.getSessionScope();
+ if (session != null) {
+ key = (String) session.get(FACTORY_SELECTOR_KEY);
}
-
- return xmlDefinitions;
+
+ return key;
}
-
- /**
- * Concat postfix to the name. Take care of existing filename extension.
- * Transform the given name "name.ext" to have "name" + "postfix" + "ext".
- * If there is no ext, return "name" + "postfix".
- */
- private String concatPostfix(String name, String postfix) {
- if (postfix == null) {
- return name;
+
+ private Locale getLocale(String localeKey) {
+ Locale retValue = null;
+ String[] localeArray;
+
+ if (localeKey != null) {
+ localeArray = localeKey.split("_");
+
+ retValue = new Locale(localeArray.length > 0 ? localeArray[0] :
null,
+ localeArray.length > 1 ? localeArray[1] : null,
+ localeArray.length > 2 ? localeArray[2] : null);
}
-
- //postfix = "_" + postfix;
- // Search file name extension.
- // take care of Unix files starting with .
- int dotIndex = name.lastIndexOf(".");
- int lastNameStart = name.lastIndexOf(java.io.File.pathSeparator);
- if (dotIndex < 1 || dotIndex < lastNameStart)
- return name + postfix;
-
- String ext = name.substring(dotIndex);
- name = name.substring(0, dotIndex);
- return name + postfix + ext;
+
+ return retValue;
}
-
}
Modified:
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/SelectChannelAction.java
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/SelectChannelAction.java?view=diff&rev=481785&r1=481784&r2=481785
==============================================================================
---
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/SelectChannelAction.java
(original)
+++
struts/sandbox/trunk/tiles/tiles-showcase/src/main/java/org/apache/tiles/showcase/channel/SelectChannelAction.java
Sun Dec 3 08:11:53 2006
@@ -70,7 +70,7 @@
// set in session
HttpSession session = request.getSession(false);
if (session != null)
- session.setAttribute(ChannelFactorySet.FACTORY_SELECTOR_KEY, requested);
+ session.setAttribute(ChannelDefinitionsFactory.FACTORY_SELECTOR_KEY,
requested);
System.out.println( "Set channel to '" + requested + "'" );
return (mapping.findForward("success"));
}