You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by mi...@apache.org on 2004/06/06 10:49:28 UTC

cvs commit: jakarta-tapestry/framework/src/org/apache/tapestry ConfigurationDefaults.properties

mindbridge    2004/06/06 01:49:28

  Modified:    framework/src/org/apache/tapestry/engine AbstractEngine.java
                        DefaultComponentMessagesSource.java
                        DefaultTemplateSource.java
               framework/src/org/apache/tapestry
                        ConfigurationDefaults.properties
  Added:       framework/src/org/apache/tapestry/engine
                        DefaultComponentPropertySource.java
                        DefaultPropertySource.java
               framework/src/org/apache/tapestry/util/text
                        ICharacterMatcher.java WhitespaceMatcher.java
                        CompoundMatcher.java AsciiCharacterMatcher.java
                        InverseMatcher.java LocalizedPropertiesLoader.java
                        ExtendedReader.java LocalizedProperties.java
  Log:
  Code for reading the property files using an appropriate character set
  
  Revision  Changes    Path
  1.32      +2 -48     jakarta-tapestry/framework/src/org/apache/tapestry/engine/AbstractEngine.java
  
  Index: AbstractEngine.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/engine/AbstractEngine.java,v
  retrieving revision 1.31
  retrieving revision 1.32
  diff -u -r1.31 -r1.32
  --- AbstractEngine.java	30 Apr 2004 15:16:30 -0000	1.31
  +++ AbstractEngine.java	6 Jun 2004 08:49:27 -0000	1.32
  @@ -27,7 +27,6 @@
   import java.util.List;
   import java.util.Locale;
   import java.util.Map;
  -import java.util.ResourceBundle;
   
   import javax.servlet.RequestDispatcher;
   import javax.servlet.ServletContext;
  @@ -62,12 +61,6 @@
   import org.apache.tapestry.request.RequestContext;
   import org.apache.tapestry.request.ResponseOutputStream;
   import org.apache.tapestry.spec.IApplicationSpecification;
  -import org.apache.tapestry.util.DelegatingPropertySource;
  -import org.apache.tapestry.util.PropertyHolderPropertySource;
  -import org.apache.tapestry.util.ResourceBundlePropertySource;
  -import org.apache.tapestry.util.ServletContextPropertySource;
  -import org.apache.tapestry.util.ServletPropertySource;
  -import org.apache.tapestry.util.SystemPropertiesPropertySource;
   import org.apache.tapestry.util.exception.ExceptionAnalyzer;
   import org.apache.tapestry.util.io.DataSqueezer;
   import org.apache.tapestry.util.pool.Pool;
  @@ -2058,17 +2051,6 @@
       }
   
       /**
  -     *  Name of an application extension that can provide configuration properties.
  -     *
  -     *  @see #createPropertySource(RequestContext)
  -     *  @since 2.3
  -     *
  -     **/
  -
  -    private static final String EXTENSION_PROPERTY_SOURCE_NAME =
  -        "org.apache.tapestry.property-source";
  -
  -    /**
        *  Creates a shared property source that will be stored into
        *  the servlet context.
        *  Subclasses may override this method to build thier
  @@ -2091,35 +2073,7 @@
   
       protected IPropertySource createPropertySource(RequestContext context)
       {
  -        DelegatingPropertySource result = new DelegatingPropertySource();
  -
  -        ApplicationServlet servlet = context.getServlet();
  -        IApplicationSpecification spec = servlet.getApplicationSpecification();
  -
  -        result.addSource(new PropertyHolderPropertySource(spec));
  -        result.addSource(new ServletPropertySource(servlet.getServletConfig()));
  -        result.addSource(new ServletContextPropertySource(servlet.getServletContext()));
  -
  -        if (spec.checkExtension(EXTENSION_PROPERTY_SOURCE_NAME))
  -        {
  -            IPropertySource source =
  -                (IPropertySource) spec.getExtension(
  -                    EXTENSION_PROPERTY_SOURCE_NAME,
  -                    IPropertySource.class);
  -
  -            result.addSource(source);
  -        }
  -
  -        result.addSource(SystemPropertiesPropertySource.getInstance());
  -
  -        // Lastly, add a final source to handle "factory defaults".
  -
  -        ResourceBundle bundle =
  -            ResourceBundle.getBundle("org.apache.tapestry.ConfigurationDefaults");
  -
  -        result.addSource(new ResourceBundlePropertySource(bundle));
  -
  -        return result;
  +        return new DefaultPropertySource(context);
       }
   
       /**
  
  
  
  1.8       +54 -20    jakarta-tapestry/framework/src/org/apache/tapestry/engine/DefaultComponentMessagesSource.java
  
  Index: DefaultComponentMessagesSource.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/engine/DefaultComponentMessagesSource.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- DefaultComponentMessagesSource.java	30 Apr 2004 15:16:30 -0000	1.7
  +++ DefaultComponentMessagesSource.java	6 Jun 2004 08:49:28 -0000	1.8
  @@ -28,8 +28,10 @@
   import org.apache.hivemind.Messages;
   import org.apache.hivemind.Resource;
   import org.apache.tapestry.IComponent;
  +import org.apache.tapestry.IRequestCycle;
   import org.apache.tapestry.Tapestry;
   import org.apache.tapestry.util.MultiKey;
  +import org.apache.tapestry.util.text.LocalizedProperties;
   
   /**
    *  Global object (stored in the servlet context) that accesses
  @@ -48,6 +50,14 @@
       private Properties _emptyProperties = new Properties();
   
       /**
  +     *  The name of the component/application/etc property that will be used to
  +     *  determine the encoding to use when loading the messages
  +     * 
  +     **/ 
  +         
  +    public static final String MESSAGES_ENCODING_PROPERTY_NAME = "org.apache.tapestry.messages-encoding";
  +    
  +    /**
        *  Map of {@link Properties}, keyed on a {@link MultiKey} of
        *  component specification path and locale.
        * 
  @@ -83,7 +93,7 @@
   
           // Not found, create it now.
   
  -        result = assembleProperties(specificationLocation, locale);
  +        result = assembleProperties(component, specificationLocation, locale);
   
           _cache.put(key, result);
   
  @@ -92,7 +102,7 @@
   
       private static final String SUFFIX = ".properties";
   
  -    private Properties assembleProperties(Resource baseResourceLocation, Locale locale)
  +    private Properties assembleProperties(IComponent component, Resource baseResourceLocation, Locale locale)
       {
           boolean debug = LOG.isDebugEnabled();
           if (debug)
  @@ -111,12 +121,12 @@
   
           if (parent == null)
           {
  -            parent = readProperties(baseResourceLocation, baseName, null, null);
  +            parent = readProperties(component, baseResourceLocation, baseName, null, null);
   
  -            if (parent == null)
  +            if (parent == null) {
                   parent = _emptyProperties;
  -
  -            _cache.put(baseResourceLocation, parent);
  +                _cache.put(baseResourceLocation, parent);
  +            }
           }
   
           Properties result = parent;
  @@ -128,10 +138,10 @@
   
               result = (Properties) _cache.get(key);
   
  -            if (result == null)
  -                result = readProperties(baseResourceLocation, baseName, l, parent);
  -
  -            _cache.put(key, result);
  +            if (result == null) {
  +                result = readProperties(component, baseResourceLocation, baseName, l, parent);
  +                _cache.put(key, result);
  +            }
   
               parent = result;
           }
  @@ -145,10 +155,10 @@
   
               result = (Properties) _cache.get(key);
   
  -            if (result == null)
  -                result = readProperties(baseResourceLocation, baseName, l, parent);
  -
  -            _cache.put(key, result);
  +            if (result == null) {
  +                result = readProperties(component, baseResourceLocation, baseName, l, parent);
  +                _cache.put(key, result);
  +            }
   
               parent = result;
           }
  @@ -162,10 +172,10 @@
   
               result = (Properties) _cache.get(key);
   
  -            if (result == null)
  -                result = readProperties(baseResourceLocation, baseName, l, parent);
  -
  -            _cache.put(key, result);
  +            if (result == null) {
  +                result = readProperties(component, baseResourceLocation, baseName, l, parent);
  +                _cache.put(key, result);
  +            }
           }
   
           return result;
  @@ -177,6 +187,7 @@
       }
   
       private Properties readProperties(
  +    	IComponent component,
           Resource baseLocation,
           String baseName,
           Locale locale,
  @@ -206,11 +217,17 @@
           else
               result = new Properties(parent);
   
  +        LocalizedProperties localizedResult = new LocalizedProperties(result);
  +        String encoding = getMessagesEncoding(component, locale);
  +        
           try
           {
               InputStream input = propertiesURL.openStream();
   
  -            result.load(input);
  +            if (encoding == null)
  +            	localizedResult.load(input);
  +            else
  +            	localizedResult.load(input, encoding);
   
               input.close();
           }
  @@ -239,6 +256,23 @@
           return new ComponentMessages(
               component.getPage().getLocale(),
               getLocalizedProperties(component));
  +    }
  +
  +    private String getMessagesEncoding(IComponent component, Locale locale)
  +    {
  +    	String encoding = null;
  +
  +    	IRequestCycle cycle = component.getPage().getRequestCycle();
  +    	if (cycle != null) {
  +	    	IPropertySource applicationSource = cycle.getEngine().getPropertySource();
  +	        IPropertySource source = new DefaultComponentPropertySource(component, applicationSource, locale);
  +
  +	        encoding = source.getPropertyValue(MESSAGES_ENCODING_PROPERTY_NAME);
  +	        if (encoding == null)
  +	        	encoding = source.getPropertyValue(DefaultTemplateSource.TEMPLATE_ENCODING_PROPERTY_NAME);
  +    	}
  +        
  +        return encoding;
       }
   
   }
  
  
  
  1.15      +3 -33     jakarta-tapestry/framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java
  
  Index: DefaultTemplateSource.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/engine/DefaultTemplateSource.java,v
  retrieving revision 1.14
  retrieving revision 1.15
  diff -u -r1.14 -r1.15
  --- DefaultTemplateSource.java	30 Apr 2004 15:16:30 -0000	1.14
  +++ DefaultTemplateSource.java	6 Jun 2004 08:49:28 -0000	1.15
  @@ -46,11 +46,8 @@
   import org.apache.tapestry.resolver.ComponentSpecificationResolver;
   import org.apache.tapestry.spec.IApplicationSpecification;
   import org.apache.tapestry.spec.IComponentSpecification;
  -import org.apache.tapestry.util.DelegatingPropertySource;
   import org.apache.tapestry.util.IRenderDescription;
  -import org.apache.tapestry.util.LocalizedPropertySource;
   import org.apache.tapestry.util.MultiKey;
  -import org.apache.tapestry.util.PropertyHolderPropertySource;
   
   /**
    *  Default implementation of {@link ITemplateSource}.  Templates, once parsed,
  @@ -72,7 +69,7 @@
       // The name of the component/application/etc property that will be used to
       // determine the encoding to use when loading the template
            
  -    private static final String TEMPLATE_ENCODING_PROPERTY_NAME = "org.apache.tapestry.template-encoding"; 
  +    public static final String TEMPLATE_ENCODING_PROPERTY_NAME = "org.apache.tapestry.template-encoding"; 
   
       // Cache of previously retrieved templates.  Key is a multi-key of 
       // specification resource path and locale (local may be null), value
  @@ -636,34 +633,7 @@
       
       private String getTemplateEncoding(IRequestCycle cycle, IComponent component, Locale locale)
       {
  -        IPropertySource source = getComponentPropertySource(cycle, component);
  -
  -        if (locale != null)
  -            source = new LocalizedPropertySource(locale, source);
  -
  -        return getTemplateEncodingProperty(source);
  -    }
  -    
  -    private IPropertySource getComponentPropertySource(IRequestCycle cycle, IComponent component)
  -    {
  -        DelegatingPropertySource source = new DelegatingPropertySource();
  -
  -        // Search for the encoding property in the following order:
  -        // First search the component specification
  -        source.addSource(new PropertyHolderPropertySource(component.getSpecification()));
  -
  -        // Then search its library specification
  -        source.addSource(new PropertyHolderPropertySource(component.getNamespace().getSpecification()));
  -
  -        // Then search the rest of the standard path
  -        source.addSource(cycle.getEngine().getPropertySource());
  -        
  -        return source;
  -    }
  -    
  -    private String getTemplateEncodingProperty(IPropertySource source)
  -    {
  +        IPropertySource source = new DefaultComponentPropertySource(component, cycle.getEngine().getPropertySource(), locale);
           return source.getPropertyValue(TEMPLATE_ENCODING_PROPERTY_NAME);
       }
  -    
   }
  
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/engine/DefaultComponentPropertySource.java
  
  Index: DefaultComponentPropertySource.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.engine;
  
  import java.util.Locale;
  
  import org.apache.tapestry.IComponent;
  import org.apache.tapestry.util.DelegatingPropertySource;
  import org.apache.tapestry.util.LocalizedPropertySource;
  import org.apache.tapestry.util.PropertyHolderPropertySource;
  
  /**
   *  The default property source for component configuration properties.
   *  The search order this property source follows is the following:<br>
   *  <ul>
   *    <li>Component specification
   *    <li>Namespace (library) specification
   *    <li>the rest of the search path as defined in the application property source
   *  </ul>
   *
   *  <p>If a locale has been passed to this object, it will first search for 
   *  the localized versions of the requested property (e.g. property_en_us, 
   *  property_en) and will look at the property itself only at the end.  
   *  
   *  @author mb
   *  @version $Id: DefaultComponentPropertySource.java,v 1.1 2004/06/06 08:49:27 mindbridge Exp $
   *  @since 3.1
   */
  public class DefaultComponentPropertySource implements IPropertySource
  {
      private IPropertySource _degatingPropertySource;
  
  	/**
  	 * Creates a new default component property source with no associate locale.
  	 * The property source will only use the path specified in the class documentation.
  	 * 
  	 * @param component the component for which the properties will be looked up
  	 * @param applicationPropertySource the property source for the application
  	 */
  	public DefaultComponentPropertySource(IComponent component, IPropertySource applicationPropertySource) {
  		this(component, applicationPropertySource, null);
  	}
  	
  	/**
  	 * Creates a new default component property source that is associated with the given locale.
  	 * The property source will search property path specified in the class documentation for 
  	 * the localized versions of the property first.
  	 * 
  	 * @param component the component for which the properties will be looked up
  	 * @param applicationPropertySource the property source for the application
  	 * @param locale the locale to be used for localizing the properties
  	 */
  	public DefaultComponentPropertySource(IComponent component, IPropertySource applicationPropertySource, Locale locale) {
          DelegatingPropertySource source = new DelegatingPropertySource();
  
          // Search for the encoding property in the following order:
          // First search the component specification
          source.addSource(new PropertyHolderPropertySource(component.getSpecification()));
  
          // Then search its library specification
          source.addSource(new PropertyHolderPropertySource(component.getNamespace().getSpecification()));
  
          // Then search the rest of the standard path
          source.addSource(applicationPropertySource);
  
          if (locale != null)
              source = new LocalizedPropertySource(locale, source);
          
          _degatingPropertySource = source;
  	}
  	
  	/**
  	 * @see org.apache.tapestry.engine.IPropertySource#getPropertyValue(java.lang.String)
  	 */
  	public String getPropertyValue(String propertyName)
  	{
  		return _degatingPropertySource.getPropertyValue(propertyName);
  	}
  }
  
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/engine/DefaultPropertySource.java
  
  Index: DefaultPropertySource.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.engine;
  
  import java.util.ResourceBundle;
  
  import org.apache.tapestry.ApplicationServlet;
  import org.apache.tapestry.request.RequestContext;
  import org.apache.tapestry.spec.IApplicationSpecification;
  import org.apache.tapestry.util.DelegatingPropertySource;
  import org.apache.tapestry.util.PropertyHolderPropertySource;
  import org.apache.tapestry.util.ResourceBundlePropertySource;
  import org.apache.tapestry.util.ServletContextPropertySource;
  import org.apache.tapestry.util.ServletPropertySource;
  import org.apache.tapestry.util.SystemPropertiesPropertySource;
  
  /**
   *  The default property source for application configuration properties.
   *  The search order this property source follows is the following:<br>
   *  <ul>
   *    <li>Application specification
   *    <li>Servlet properties
   *    <li>Servlet context
   *    <li>Property source extension defined in the application specification
   *    <li>System properties
   *    <li>Factory defaults
   *  </ul>
   *
   *  <p>If the application specification contains an extension
   *  named "org.apache.tapestry.property-source" it is inserted
   *  in the search path just before
   *  the property source for JVM System Properties.  This is a simple
   *  hook that allows application-specific methods of obtaining
   *  configuration values (typically, from a database or from JMX,
   *  in some way).  
   *  
   *  @author mb
   *  @version $Id: DefaultPropertySource.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   *  @since 3.1
   */
  public class DefaultPropertySource implements IPropertySource
  {
      /**
       *  Name of an application extension that can provide configuration properties.
       *
       *  @since 2.3
       *
       **/
      private static final String EXTENSION_PROPERTY_SOURCE_NAME =
          "org.apache.tapestry.property-source";
  
      private IPropertySource _degatingPropertySource;
      
  	/**
  	 * Creates a new default property source for looking up application-specific
  	 * properties. The search order of the property source is shown in the
  	 * documentation of this class.
  	 * 
  	 * @param context the request context for which this property source will be created
  	 */
  	public DefaultPropertySource(RequestContext context) {
          DelegatingPropertySource result = new DelegatingPropertySource();
  
          ApplicationServlet servlet = context.getServlet();
          IApplicationSpecification spec = servlet.getApplicationSpecification();
  
          result.addSource(new PropertyHolderPropertySource(spec));
          result.addSource(new ServletPropertySource(servlet.getServletConfig()));
          result.addSource(new ServletContextPropertySource(servlet.getServletContext()));
  
          if (spec.checkExtension(EXTENSION_PROPERTY_SOURCE_NAME))
          {
              IPropertySource source =
                  (IPropertySource) spec.getExtension(
                      EXTENSION_PROPERTY_SOURCE_NAME,
                      IPropertySource.class);
  
              result.addSource(source);
          }
  
          result.addSource(SystemPropertiesPropertySource.getInstance());
  
          // Lastly, add a final source to handle "factory defaults".
  
          ResourceBundle bundle =
              ResourceBundle.getBundle("org.apache.tapestry.ConfigurationDefaults");
  
          result.addSource(new ResourceBundlePropertySource(bundle));
  
          _degatingPropertySource = result;
  	}
  	
  	/**
  	 * @see org.apache.tapestry.engine.IPropertySource#getPropertyValue(java.lang.String)
  	 */
  	public String getPropertyValue(String propertyName)
  	{
  		return _degatingPropertySource.getPropertyValue(propertyName);
  	}
  }
  
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/ICharacterMatcher.java
  
  Index: ICharacterMatcher.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  /**
   * An interface for determining whether a character matches a particular rule.
   * 
   * @author mb
   * @version $Id: ICharacterMatcher.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  interface ICharacterMatcher 
  {
      /**
       * Determine whether the given character matches the implemented rule
       * 
       * @param ch the character to be matched
       * @return true if the character matches the rule
       */
      boolean matches(char ch);
  }
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/WhitespaceMatcher.java
  
  Index: WhitespaceMatcher.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  /**
   * Matches a whitespace character.
   * 
   * @author mb
   * @version $Id: WhitespaceMatcher.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  class WhitespaceMatcher implements ICharacterMatcher 
  {
      private boolean _matchEndLines;
      
      /**
       * Creates an object that matches all whitespace characters, line terminators included
       */
      public WhitespaceMatcher()
      {
          this(true);
      }
      
      /**
       * Creates an object that matches whitespace characters. 
       * Line terminators are included only if this is specified.
       * 
       * @param matchEndLines match line terminators as well
       */
      public WhitespaceMatcher(boolean matchEndLines)
      {
          _matchEndLines = matchEndLines;
      }
      
      /**
       * Matches whitespace characters. Line terminators may be matched 
       * depending on the constructor used to create the object.
       * 
       * @see org.apache.tapestry.util.text.ICharacterMatcher#matches(char)
       */
      public boolean matches(char ch)
      {
          if (!_matchEndLines)
              if (ch == '\n' || ch == '\r')
                  return false;
          
          return Character.isWhitespace(ch);
      }
  }
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/CompoundMatcher.java
  
  Index: CompoundMatcher.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  /**
   * Combine a set of character matchers. A given character will be matched if any
   * of the provided objects matches it.
   * 
   * @author mb
   * @version $Id: CompoundMatcher.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  class CompoundMatcher implements ICharacterMatcher
  {
      private ICharacterMatcher[] _matchers;
      
      /**
       * Create a new object that will match a character if any of the provided objects matches it.
       * 
       * @param matchers the array of objects that will be queried if a character matches
       */
      public CompoundMatcher(ICharacterMatcher[] matchers) {
          _matchers = matchers;
      }
      
      /**
       * Match the character if any of the provided objects matches it.
       * 
       * @see org.apache.tapestry.util.text.ICharacterMatcher#matches(char)
       */
      public boolean matches(char ch)
      {
          for (int i = 0; i < _matchers.length; i++) {
              if (_matchers[i].matches(ch))
                  return true;
          }
          return false;
      }
  }
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/AsciiCharacterMatcher.java
  
  Index: AsciiCharacterMatcher.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  /**
   * An object for matching a set of provided ASCII characters.
   * 
   * @author mb
   * @version $Id: AsciiCharacterMatcher.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  class AsciiCharacterMatcher implements ICharacterMatcher 
  {
      private boolean[] _charMap;
      
      /**
       * Create a new ASCII character matcher for identifying the set of provided ASCII characters
       * 
       * @param chars the character that this matcher should identify
       */
      public AsciiCharacterMatcher(String chars) {
          _charMap = new boolean[128];
          for (int i = 0; i < chars.length(); i++) {
              char ch = chars.charAt(i);
              if (ch > 127)
                  continue;
              _charMap[ch] = true;
          }
      }
      
      /**
       * Match the characters provided in the constructor
       * 
       * @see org.apache.tapestry.util.text.ICharacterMatcher#matches(char)
       */
      public boolean matches(char ch)
      {
          if (ch > 127)
              return false;
          return _charMap[ch];
      }
  }
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/InverseMatcher.java
  
  Index: InverseMatcher.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  /**
   * Matches a given character only if the provided object does NOT match it.
   * 
   * @author mb
   * @version $Id: InverseMatcher.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  public class InverseMatcher implements ICharacterMatcher
  {
      private ICharacterMatcher _matcher;
      
      /**
       * Creates a new object that inverts the matching rule of the provided matcher
       * 
       * @param matcher the matcher whose behaviour will be inverted
       */
      public InverseMatcher(ICharacterMatcher matcher)
      {
          _matcher = matcher;
      }
      
      /**
       * Matches the character only if the provided object does NOT match it.
       * 
       * @see org.apache.tapestry.util.text.ICharacterMatcher#matches(char)
       */
      public boolean matches(char ch)
      {
          return !_matcher.matches(ch);
      }
  }
  
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/LocalizedPropertiesLoader.java
  
  Index: LocalizedPropertiesLoader.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.Reader;
  import java.io.UnsupportedEncodingException;
  import java.util.Map;
  
  /**
   * An object that loads a properties file from the provided input stream or reader.
   * This class reads the property file exactly like java.util.Properties,
   * except that it also allows the files to use an encoding other than ISO-8859-1
   * and all non-ASCII characters are read correctly using the given encoding.
   * In short, non-latin characters no longer need to be quoted using native2ascii.
   * 
   * @author mb
   * @version $Id: LocalizedPropertiesLoader.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  public class LocalizedPropertiesLoader
  {
      private static final String HEX_DIGITS = "0123456789ABCDEF";
      
      private static final ICharacterMatcher WHITESPACE = new WhitespaceMatcher(false);
      private static final ICharacterMatcher LINE_SEPARATOR = new AsciiCharacterMatcher("\n\r");
      private static final ICharacterMatcher NOT_LINE_SEPARATOR = new InverseMatcher(LINE_SEPARATOR);
      private static final ICharacterMatcher KEY_VALUE_SEPARATOR = new AsciiCharacterMatcher("=:");
      private static final ICharacterMatcher SEPARATOR = new AsciiCharacterMatcher("=:\r\n");
      private static final ICharacterMatcher COMMENT = new AsciiCharacterMatcher("#!");
      private static final ICharacterMatcher WHITESPACE_OR_SEPARATOR = 
          new CompoundMatcher(new ICharacterMatcher[] { WHITESPACE, SEPARATOR });
  
      private ExtendedReader _extendedReader;
  
      private ExtendedReader m_objExtendedReader;
      
      /**
       * Creates a new loader that will load the properties from the given input stream
       * using the default character encoding
       * 
       * @param ins the input stream to load the properties from
       */
      public LocalizedPropertiesLoader(InputStream ins)
      {
          this(new InputStreamReader(ins));
      }
      
      /**
       * Creates a new loader that will load the properties from the given input stream
       * using the provided character encoding
       * 
       * @param ins the input stream to load the properties from
       * @param encoding the character encoding the be used when reading from the stream
       * @throws UnsupportedEncodingException if the name of the encoding cannot be recognized
       */
      public LocalizedPropertiesLoader(InputStream ins, String encoding) throws UnsupportedEncodingException
      {
          this(new InputStreamReader(ins, encoding));
      }
      
      /**
       * Creates a new loader that will load the properties from the given reader
       * 
       * @param reader the Reader to load the properties from
       */
      public LocalizedPropertiesLoader(Reader reader)
      {
          _extendedReader = new ExtendedReader(new BufferedReader(reader));
      }
      
      /**
       * Read the properties from the provided stream and store them into the given map
       * 
       * @param properties the map where the properties will be stored
       * @throws IOException if an error occurs
       */
      public void load(Map properties) throws IOException
      {
          while (!isAtEndOfStream()) {
          	// we are at the beginning of a line.
          	// check whether it is a comment and if it is, skip it
              int nextChar = _extendedReader.peek();
              if (COMMENT.matches((char) nextChar)) {
                  _extendedReader.skipCharacters(NOT_LINE_SEPARATOR);
                  continue;
              }
              
              _extendedReader.skipCharacters(WHITESPACE);
              if (!isAtEndOfLine()) {
              	// this line does not consist only of whitespace. the next word is the key
                  String key = readQuotedLine(WHITESPACE_OR_SEPARATOR);
                  _extendedReader.skipCharacters(WHITESPACE);
                  
                  // if the next char is a key-value separator, read it and skip the following spaces
                  nextChar = _extendedReader.peek();
                  if (nextChar > 0 && KEY_VALUE_SEPARATOR.matches((char) nextChar)) {
                      _extendedReader.read();
                      _extendedReader.skipCharacters(WHITESPACE);
                  }
  
                  // finally, read the value
                  String value = readQuotedLine(LINE_SEPARATOR);
                  
                  properties.put(key, value);
              }
              _extendedReader.skipCharacters(LINE_SEPARATOR);
          }
      }
      
      
      private boolean isAtEndOfStream() throws IOException
      {
          int nextChar = _extendedReader.peek();
          return (nextChar < 0);
      }
      
      
      private boolean isAtEndOfLine() throws IOException
      {
          int nextChar = _extendedReader.peek();
          if (nextChar < 0)
              return true;
          return LINE_SEPARATOR.matches((char) nextChar);
      }
      
      
      private String readQuotedLine(ICharacterMatcher terminators) throws IOException
      {
          StringBuffer buf = new StringBuffer();
          
          while (true) {
              // see what the next char is
              int nextChar = _extendedReader.peek();
              
              // if at end of stream or the char is one of the terminators, stop
              if (nextChar < 0 || terminators.matches((char) nextChar))
                  break;
  
              try {
                  // read the char (and possibly unquote it)
                  char ch = readQuotedChar();
                  buf.append(ch);
              } catch (IgnoreCharacterException e) {
                  // simply ignore -- no character was read
              }
          }
          
          return buf.toString();
      }
      
  
      private char readQuotedChar() throws IOException, IgnoreCharacterException
      {
          int nextChar = _extendedReader.read();
          if (nextChar < 0)
              throw new IgnoreCharacterException();
          char ch = (char) nextChar;
          
          // if the char is not the quotation char, simply return it
          if (ch != '\\') 
              return ch;
  
          // the character is a quotation character. unquote it
          nextChar = _extendedReader.read();
  
          // if at the end of the stream, stop
          if (nextChar < 0)
              throw new IgnoreCharacterException();
          
          ch = (char) nextChar;
          switch (ch) {
              case 'u' :
                  char res = 0;
                  for (int i = 0; i < 4; i++) {
                      nextChar = _extendedReader.read();
                      if (nextChar < 0)
                          throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
                      char digitChar = (char) nextChar;
                      int digit = HEX_DIGITS.indexOf(Character.toUpperCase(digitChar));
                      if (digit < 0)
                          throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
                      res = (char) (res * 16 + digit);
                  }
                  return res;
  
              case '\r' :
                  // if the next char is \n, read it and fall through
                  nextChar = _extendedReader.peek();
                  if (nextChar == '\n')
                      _extendedReader.read();
              case '\n' :
                  _extendedReader.skipCharacters(WHITESPACE);
                  throw new IgnoreCharacterException();
                  
              case 't' :  return '\t';
              case 'n' :  return '\n';
              case 'r' :  return '\r';
              default:    return ch;
          }
      }
      
  
      private static class IgnoreCharacterException extends Exception 
      {
      }    
  }
  
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/ExtendedReader.java
  
  Index: ExtendedReader.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  import java.io.IOException;
  import java.io.Reader;
  
  /**
   * A Reader that provides some additional functionality, such as peek().
   * 
   * @author mb
   * @version $Id: ExtendedReader.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  public class ExtendedReader extends Reader
  {
      private Reader _reader;
      private boolean _hasBufferedChar = false;
      private char _bufferedChar;
      
      /**
       * Creates a new extended reader that reads from the provided object
       * 
       * @param in the Reader to get data from
       */
      public ExtendedReader(Reader in)
      {
          _reader = in;
      }
  
      /**
       * Returns the next character in the stream without actually comitting the read.
       * Multiple consequtive invocations of this method should return the same value.
       * 
       * @return the next character waiting in the stream or -1 if the end of the stream is reached
       * @throws IOException if an error occurs
       */
      public synchronized int peek() throws IOException
      {
          if (!_hasBufferedChar) {
              int bufferedChar = read();
              if (bufferedChar < 0)
                  return bufferedChar;
              _bufferedChar = (char) bufferedChar;
              _hasBufferedChar = true;
          }
          return _bufferedChar;
      }
      
      /**
       * Determines whether the end of the stream is reached
       * 
       * @return true if at the end of stream
       * @throws IOException if an error occurs
       */
      public synchronized boolean isEndOfStream() throws IOException
      {
          return peek() < 0;
      }
  
      /**
       * Skips the next characters until a character that does not match the provided rule is reached.
       * 
       * @param matcher the object determining whether a character should be skipped
       * @throws IOException if an error occurs
       */
      public synchronized void skipCharacters(ICharacterMatcher matcher) throws IOException
      {
          while (true) {
              if (isEndOfStream())
                  break;
              char ch = (char) peek();
              if (!matcher.matches(ch))
                  break;
              read();
          }
      }
      
      /**
       * Reads the next characters until a character that does not match the provided rule is reached.
       * 
       * @param matcher the object determining whether a character should be read
       * @return the string of characters read
       * @throws IOException if an error occurs
       */
      public synchronized String readCharacters(ICharacterMatcher matcher) throws IOException
      {
          StringBuffer buf = new StringBuffer();
          while (true) {
              if (isEndOfStream())
                  break;
              char ch = (char) peek();
              if (!matcher.matches(ch))
                  break;
              buf.append(read());
          }
          return buf.toString();
      }
      
      /** 
       * @see java.io.FilterReader#read(char[], int, int)
       */
      public synchronized int read(char[] cbuf, int off, int len) throws IOException
      {
          if (len <= 0)
              return 0;
          
          boolean extraChar = _hasBufferedChar;
          if (_hasBufferedChar) {
              _hasBufferedChar = false;
              cbuf[off++] = _bufferedChar;
              len--;
          }
  
          int read = _reader.read(cbuf, off, len);
          if (extraChar)
              read++;
          return read;
      }
      
      /** 
       * @see java.io.FilterReader#ready()
       */
      public synchronized boolean ready() throws IOException
      {
          if (_hasBufferedChar)
              return true;
          return _reader.ready();
      }
      
      /** 
       * @see java.io.FilterReader#markSupported()
       */
      public synchronized boolean markSupported()
      {
          return false;
      }
      
      /** 
       * @see java.io.FilterReader#reset()
       */
      public synchronized void reset() throws IOException
      {
          _hasBufferedChar = false;
          _reader.reset();
      }
      
      /** 
       * @see java.io.FilterReader#skip(long)
       */
      public synchronized long skip(long n) throws IOException
      {
          if (_hasBufferedChar && n > 0) {
              _hasBufferedChar = false;
              n--;
          }
          return _reader.skip(n);
      }
  
      /** 
       * @see java.io.Reader#close()
       */
      public synchronized void close() throws IOException
      {
          _hasBufferedChar = false;
          _reader.close();
      }
      
  }
  
  
  
  1.1                  jakarta-tapestry/framework/src/org/apache/tapestry/util/text/LocalizedProperties.java
  
  Index: LocalizedProperties.java
  ===================================================================
  //Copyright 2004 The Apache Software Foundation
  //
  // Licensed under the Apache License, Version 2.0 (the "License");
  // you may not use this file except in compliance with the License.
  // You may obtain a copy of the License at
  //
  //     http://www.apache.org/licenses/LICENSE-2.0
  //
  // Unless required by applicable law or agreed to in writing, software
  // distributed under the License is distributed on an "AS IS" BASIS,
  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  // See the License for the specific language governing permissions and
  // limitations under the License.
  
  package org.apache.tapestry.util.text;
  
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.Reader;
  import java.io.UnsupportedEncodingException;
  import java.util.HashMap;
  import java.util.Map;
  
  /**
   * A version of java.util.Properties that can read the properties from files
   * using an encoding other than ISO-8859-1. All non-latin characters are read 
   * correctly using the given encoding and no longer need to be quoted using native2ascii.
   * 
   * In addition, the properties may be stored in an arbitrary map, rather than
   * only in Properties. For example, using LinkedHashMap will preserve the order
   * of the properties as defined in the file. 
   * 
   * @author mb
   * @version $Id: LocalizedProperties.java,v 1.1 2004/06/06 08:49:28 mindbridge Exp $
   * @since 3.1
   */
  public class LocalizedProperties
  {
      private Map _propertyMap;
      
      /**
       * Create a new object with an empty property storage 
       */
      public LocalizedProperties()
      {
          this(new HashMap());
      }
  
      /**
       * Use the provided argument as the storage location for the properties managed
       * by this object. This allows different types of Map implementations to be used,
       * such as a LinkedHashMap to preserve the order of the keys, for example.
       * The provided map may contain the default property values as well.
       * 
       * @param propertyMap the map where properties are to be stored
       */
      public LocalizedProperties(Map propertyMap)
      {
          _propertyMap = propertyMap;
      }
      
      /**
       * Returns the property value corresponding the provided key. If there is no such property,
       * or the value in the provided map is not of type String, null is returned.
       * 
       * @param key the property key
       * @return the value of the property, or null if there is no such property
       */
      public String getProperty(String key)
      {
         Object value = _propertyMap.get(key);
         if (value instanceof String)
             return (String) value;
         return null;
      }
      
      /**
       * Returns the property value corresponding to the provided key, 
       * or the provided default value if no such property exists.
       * 
       * @param key the property key
       * @param defaultValue the default value of the property
       * @return the value of the property, or the default value if there is no such property
       */
      public String getProperty(String key, String defaultValue)
      {
          String value = getProperty(key);
          if (value != null)
              return value;
          return defaultValue;
      }
      
      /**
       * Stores a property value
       * 
       * @param key the property key
       * @param value the property value
       */
      public void setProperty(String key, String value)
      {
          _propertyMap.put(key, value);
      }
      
      /**
       * Returns the map containing all properties. The map can be used to enumerate the 
       * properties or their keys. 
       * 
       * @return a map containing the properties
       */
      public Map getPropertyMap()
      {
          return _propertyMap;
      }
      
      /**
       * Loads the properties from the given stream using the default character encoding.
       * This method operates in the same way as the equivalent method in {@link java.util.Properties},
       * but it also handles non-ascii symbols. 
       * 
       * @param ins the stream to load the properties from
       * @throws IOException
       */
      public void load(InputStream ins) throws IOException
      {
      	LocalizedPropertiesLoader loader = new LocalizedPropertiesLoader(ins);
          loader.load(_propertyMap);
      }
      
      /**
       * Loads the properties from the given stream using the provided character encoding.
       * This method operates in the same way as the equivalent method in {@link java.util.Properties},
       * but it also handles non-ascii symbols. 
       * 
       * @param ins the stream to load the properties from
       * @param encoding the encoding the use when parsing the stream
       * @throws IOException
       */
      public void load(InputStream ins, String encoding) throws UnsupportedEncodingException, IOException
      {
      	LocalizedPropertiesLoader loader = new LocalizedPropertiesLoader(ins, encoding);
          loader.load(_propertyMap);
      }
      
      /**
       * Loads the properties from the given reader.
       * This method operates in the same way as the equivalent method in {@link java.util.Properties},
       * but it also handles non-ascii symbols. 
       * 
       * @param reader the reader to load the properties from
       * @throws IOException
       */
      public void load(Reader reader) throws IOException
      {
      	LocalizedPropertiesLoader loader = new LocalizedPropertiesLoader(reader);
          loader.load(_propertyMap);
      }
  }
  
  
  
  1.2       +3 -2      jakarta-tapestry/framework/src/org/apache/tapestry/ConfigurationDefaults.properties
  
  Index: ConfigurationDefaults.properties
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/org/apache/tapestry/ConfigurationDefaults.properties,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ConfigurationDefaults.properties	5 Mar 2003 22:59:22 -0000	1.1
  +++ ConfigurationDefaults.properties	6 Jun 2004 08:49:28 -0000	1.2
  @@ -1,4 +1,5 @@
   # $Id$
   
   org.apache.tapestry.default-script-language=jython
  -org.apache.tapestry.visit-class=java.util.HashMap
  \ No newline at end of file
  +org.apache.tapestry.visit-class=java.util.HashMap
  +org.apache.tapestry.output-encoding=UTF-8
  \ No newline at end of file
  
  
  

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