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