w3c.css.util.Utf8Properties Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of cssvalidator Show documentation
Show all versions of cssvalidator Show documentation
Backend for the W3C CSS Validation Service
// $Id$
// From Jean-Guilhem Rouel
//
// (c) COPYRIGHT MIT, ERCIM and Keio, 2005.
// Please first read the full copyright statement in file COPYRIGHT.html
package org.w3c.css.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;
/**
* This class extends the Properties class to provide the ability
* to load properties file using UTF-8 encoding (original Java Properties class
* uses ISO-8859-1, and unicode escaped characters)
*
* @see java.util.Properties
*/
public class Utf8Properties extends Properties {
/**
* use serialVersionUID from JDK 1.1.X for interoperability
*/
private static final long serialVersionUID = 5907218757225133892L;
/**
* Encoding used to read properties from a file
*/
public static final String ENCODING = "UTF-8";
/**
* Characters used to write comment lines in a property file
*/
private static final String COMMENT = "#!";
/**
* Possible Separator between key and value of a property in a property
* file
*/
private static final String keyValueSeparators = "=: \t\r\n\f";
/**
* Creates an empty property list with no default values.
*
* @see java.util.Properties#Properties()
*/
public Utf8Properties() {
this(null);
}
/**
* Creates an empty property list with the specified defaults.
*
* @param defaults the defaults.
* @see java.util.Properties#Properties(java.util.Properties)
*/
public Utf8Properties(Properties defaults) {
this.defaults = defaults;
}
/**
* Reads a property list (key and element pairs) from the input
* stream. The stream is assumed to be using the UTF-8
* character encoding or compatible.
* Characters can be written with their unicode escape sequence.
*
* @param inStream the input stream.
* @throws IOException if an error occurred when reading from the
* input stream.
* @throws IllegalArgumentException if the input stream contains a
* malformed Unicode escape sequence.
* @see java.util.Properties#load(java.io.InputStream)
*/
public synchronized void load(InputStream inStream) throws IOException {
BufferedReader in = new BufferedReader(new InputStreamReader(inStream, ENCODING));
String line = in.readLine();
while (line != null) {
line = removeWhiteSpaces(line);
if (!line.equals("") && COMMENT.indexOf(line.charAt(0)) == -1) {
// Removes the beginning separators
String property = line;
// Reads the whole property if it is on multiple lines
while (continueLine(line)) {
property = property.substring(0, property.length() - 1);
line = in.readLine();
property += line;
}
//property = new String(property.getBytes(ENCODING), ENCODING);
if (!property.equals("")) {
int endOfKey = 0;
// calculates the ending index of the key
int l = property.length();
while (endOfKey < l && (keyValueSeparators.indexOf(property.charAt(endOfKey)) == -1)) {
endOfKey++;
}
String key = property.substring(0, endOfKey);
String value = property.substring(endOfKey + 1, property.length());
key = loadConversion(key);
value = loadConversion(removeWhiteSpaces(value));
put(key, value);
//// For debugging only
//System.out.println("key: " + key);
//System.out.println("value: " + value);
//System.out.println("-----------");
}
}
line = in.readLine();
}
}
/**
* A simple method to remove white spaces
* at the beginning of a String
*
* @param line the String to treat
* @return the same String without white spaces at the beginning
*/
public static String removeWhiteSpaces(String line) {
int index = 0;
while (index < line.length() && keyValueSeparators.indexOf(line.charAt(index)) != -1) {
index++;
}
return line.substring(index, line.length());
}
/**
* Replaces all characters preceded by a '\' with the corresponding special
* character and converts unicode escape sequences to their value
*
* @param line the String to treat
* @return the converted line
*/
private String loadConversion(String line) {
StringBuilder val = new StringBuilder(line.length());
int index = 0;
// Replace all the "\." substrings with their corresponding
// escaped characters
for (; index < line.length(); index++) {
char currentChar = line.charAt(index);
if (currentChar == '\\') {
index++;
currentChar = line.charAt(index);
switch (currentChar) {
case 't':
currentChar = '\t';
break;
case 'r':
currentChar = '\r';
break;
case 'n':
currentChar = '\n';
break;
case 'f':
currentChar = '\f';
break;
case 'u':
index++;
// Read the xxxx
int value = 0;
for (int i = 0; i < 4; i++) {
currentChar = line.charAt(index++);
//System.out.println(currentChar);
switch (currentChar) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
value = (value << 4) + currentChar - '0';
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
value = (value << 4) + 10 + currentChar - 'a';
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
value = (value << 4) + 10 + currentChar - 'A';
break;
default:
throw new IllegalArgumentException(
"Malformed \\uxxxx encoding.");
}
}
// index must point on the last character of the escaped
// sequence to avoid missing the next character
index--;
currentChar = (char) value;
default:
break;
}
}
val.append(currentChar);
}
return val.toString();
}
/**
* Replaces special characters with their '2-chars' representation.
* For example, '\n' becomes '\\' followed by 'n'
*
* @param line the String to treat
* @return the resulting String
*/
private String storeConversion(String line) {
int length = line.length();
StringBuilder outBuffer = new StringBuilder(length * 2);
for (int i = 0; i < length; i++) {
char currentChar = line.charAt(i);
switch (currentChar) {
case '\\':
outBuffer.append('\\');
outBuffer.append('\\');
break;
case '\t':
outBuffer.append('\\');
outBuffer.append('t');
break;
case '\n':
outBuffer.append('\\');
outBuffer.append('n');
break;
case '\r':
outBuffer.append('\\');
outBuffer.append('r');
break;
case '\f':
outBuffer.append('\\');
outBuffer.append('f');
break;
default:
outBuffer.append(currentChar);
break;
}
}
return outBuffer.toString();
}
/**
* Indicates wether the property continues on the next line or not
*
* @param line the beginning of the property that might be continued
* on the next line
* @return true if the propertiy continues on the following line,
* false otherwise
*/
private boolean continueLine(String line) {
if (line != null && !line.equals("")) {
return line.charAt(line.length() - 1) == '\\';
}
return false;
}
/**
* The same method as java.util.Properties.store(...)
*
* @param out an output stream
* @param header a description of the property list
* @see java.util.Properties#store(java.io.OutputStream, java.lang.String)
*/
public void store(OutputStream out, String header) throws IOException {
BufferedWriter output;
output = new BufferedWriter(new OutputStreamWriter(out, ENCODING));
if (header != null) {
output.write('#' + header);
output.newLine();
}
output.write('#' + (new Date()).toString());
output.newLine();
// we do not want that a Thread could modify this Utf8Properties
// while storing it
synchronized (this) {
Enumeration e = keys();
while (e.hasMoreElements()) {
String key = storeConversion((String) e.nextElement());
String val = storeConversion((String) get(key));
output.write(key + '=' + val);
output.newLine();
}
}
output.flush();
}
public synchronized Set
© 2015 - 2025 Weber Informatics LLC | Privacy Policy