/*
This file belongs to the Servoy development and deployment environment, Copyright (C) 1997-2010 Servoy BV
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU Affero General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option) any
later version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along
with this program; if not, see http://www.gnu.org/licenses or write to the Free
Software Foundation,Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
*/
package com.servoy.j2db.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.util.HashMap;
/**
* java.util.Properties class copy with more access possibilities.
* @author jblok
*/
public class OpenProperties extends HashMap<String, String>
{
private static final String keyValueSeparators = "=: \t\r\n\f";
private static final String strictKeyValueSeparators = "=:";
private static final String whiteSpaceChars = " \t\r\n\f";
public synchronized void load(Reader inStream) throws IOException
{
BufferedReader in = new BufferedReader(inStream);
while (true)
{
// Get next line
String line = in.readLine();
if (line == null) return;
if (line.length() > 0)
{
// Find start of key
int len = line.length();
int keyStart;
for (keyStart = 0; keyStart < len; keyStart++)
if (whiteSpaceChars.indexOf(line.charAt(keyStart)) == -1) break;
// Blank lines are ignored
if (keyStart == len) continue;
// Continue lines that end in slashes if they are not comments
char firstChar = line.charAt(keyStart);
if ((firstChar != '#') && (firstChar != '!'))
{
while (continueLine(line))
{
String nextLine = in.readLine();
if (nextLine == null) nextLine = "";
String loppedLine = line.substring(0, len - 1);
// Advance beyond whitespace on new line
int startIndex;
for (startIndex = 0; startIndex < nextLine.length(); startIndex++)
if (whiteSpaceChars.indexOf(nextLine.charAt(startIndex)) == -1) break;
nextLine = nextLine.substring(startIndex, nextLine.length());
line = new String(loppedLine + nextLine);
len = line.length();
}
// Find separation between key and value
int separatorIndex;
for (separatorIndex = keyStart; separatorIndex < len; separatorIndex++)
{
char currentChar = line.charAt(separatorIndex);
if (currentChar == '\\') separatorIndex++;
else if (keyValueSeparators.indexOf(currentChar) != -1) break;
}
// Skip over whitespace after key if any
int valueIndex;
for (valueIndex = separatorIndex; valueIndex < len; valueIndex++)
if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) break;
// Skip over one non whitespace key value separators if any
if (valueIndex < len) if (strictKeyValueSeparators.indexOf(line.charAt(valueIndex)) != -1) valueIndex++;
// Skip over white space after other separators if any
while (valueIndex < len)
{
if (whiteSpaceChars.indexOf(line.charAt(valueIndex)) == -1) break;
valueIndex++;
}
String key = line.substring(keyStart, separatorIndex);
String value = (separatorIndex < len) ? line.substring(valueIndex, len) : "";
// Convert then store key and value
key = loadConvert(key);
value = loadConvert(value);
put(key, value);
}
}
}
}
/*
* Returns true if the given line is a line that must be appended to the next line
*/
private boolean continueLine(String line)
{
int slashCount = 0;
int index = line.length() - 1;
while ((index >= 0) && (line.charAt(index--) == '\\'))
slashCount++;
return (slashCount % 2 == 1);
}
/*
* Converts encoded \uxxxx to unicode chars and changes special saved chars to their original forms
*/
private String loadConvert(String theString)
{
char aChar;
int len = theString.length();
StringBuffer outBuffer = new StringBuffer(len);
for (int x = 0; x < len;)
{
aChar = theString.charAt(x++);
if (aChar == '\\')
{
aChar = theString.charAt(x++);
if (aChar == 'u')
{
// Read the xxxx
int value = 0;
for (int i = 0; i < 4; i++)
{
aChar = theString.charAt(x++);
switch (aChar)
{
case '0' :
case '1' :
case '2' :
case '3' :
case '4' :
case '5' :
case '6' :
case '7' :
case '8' :
case '9' :
value = (value << 4) + aChar - '0';
break;
case 'a' :
case 'b' :
case 'c' :
case 'd' :
case 'e' :
case 'f' :
value = (value << 4) + 10 + aChar - 'a';
break;
case 'A' :
case 'B' :
case 'C' :
case 'D' :
case 'E' :
case 'F' :
value = (value << 4) + 10 + aChar - 'A';
break;
default :
throw new IllegalArgumentException("Malformed \\uxxxx encoding.");
}
}
outBuffer.append((char)value);
}
else
{
if (aChar == 't') aChar = '\t';
else if (aChar == 'r') aChar = '\r';
else if (aChar == 'n') aChar = '\n';
else if (aChar == 'f') aChar = '\f';
outBuffer.append(aChar);
}
}
else outBuffer.append(aChar);
}
return outBuffer.toString();
}
}