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"));
     }


Reply via email to