forked from I2P_Developers/i2p.i2p
* DataHelper:
- Undeprecate fromProperties() and toProperties() - Undeprecate BOOLEAN_FALSE and BOOLEAN_TRUE - Fix fromProperties() and toProperties() to correctly throw DataFormatExceptions - Add sort option - Efficiency improvements in writeProperties(), toProperties(), storeProps(), and toString()
This commit is contained in:
@ -681,7 +681,11 @@ public class BlockfileNamingService extends DummyNamingService {
|
||||
private static class PropertiesSerializer implements Serializer {
|
||||
public byte[] getBytes(Object o) {
|
||||
Properties p = (Properties) o;
|
||||
return DataHelper.toProperties(p);
|
||||
try {
|
||||
return DataHelper.toProperties(p);
|
||||
} catch (DataFormatException dfe) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object construct(byte[] b) {
|
||||
|
@ -35,6 +35,7 @@ import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TreeMap;
|
||||
import java.util.zip.Deflater;
|
||||
@ -102,6 +103,7 @@ public class DataHelper {
|
||||
/**
|
||||
* Write a mapping to the stream, as defined by the I2P data structure spec,
|
||||
* and store it into a Properties object. See readProperties for the format.
|
||||
* Output is sorted by property name.
|
||||
* Property keys and values must not contain '=' or ';', this is not checked and they are not escaped
|
||||
* Keys and values must be 255 bytes or less,
|
||||
* Formatted length must not exceed 65535 bytes
|
||||
@ -131,16 +133,46 @@ public class DataHelper {
|
||||
*
|
||||
* Use utf8 = false for RouterAddress (fast, non UTF-8)
|
||||
* Use utf8 = true for SessionConfig (slow, UTF-8)
|
||||
* @param props source may be null
|
||||
*/
|
||||
public static void writeProperties(OutputStream rawStream, Properties props, boolean utf8)
|
||||
throws DataFormatException, IOException {
|
||||
writeProperties(rawStream, props, utf8, props != null && !(props instanceof OrderedProperties));
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the props to the stream, sorted by property name if sort == true or
|
||||
* if props is an OrderedProperties.
|
||||
* See readProperties() for the format.
|
||||
* Property keys and values must not contain '=' or ';', this is not checked and they are not escaped
|
||||
* Keys and values must be 255 bytes or less,
|
||||
* Formatted length must not exceed 65535 bytes
|
||||
* @throws DataFormatException if either is too long.
|
||||
*
|
||||
* jrandom disabled UTF-8 in mid-2004, for performance reasons,
|
||||
* i.e. slow foo.getBytes("UTF-8")
|
||||
* Re-enable it so we can pass UTF-8 tunnel names through the I2CP SessionConfig.
|
||||
*
|
||||
* Use utf8 = false for RouterAddress (fast, non UTF-8)
|
||||
* Use utf8 = true for SessionConfig (slow, UTF-8)
|
||||
* @param props source may be null
|
||||
* @param sort should we sort the properties? (set to false if already sorted, e.g. OrderedProperties)
|
||||
* @since 0.8.6
|
||||
*/
|
||||
public static void writeProperties(OutputStream rawStream, Properties props, boolean utf8, boolean sort)
|
||||
throws DataFormatException, IOException {
|
||||
if (props != null) {
|
||||
OrderedProperties p = new OrderedProperties();
|
||||
p.putAll(props);
|
||||
Properties p;
|
||||
if (sort) {
|
||||
p = new OrderedProperties();
|
||||
p.putAll(props);
|
||||
} else {
|
||||
p = props;
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(p.size() * 64);
|
||||
for (Iterator iter = p.keySet().iterator(); iter.hasNext();) {
|
||||
String key = (String) iter.next();
|
||||
String val = p.getProperty(key);
|
||||
for (Map.Entry entry : p.entrySet()) {
|
||||
String key = (String) entry.getKey();
|
||||
String val = (String) entry.getValue();
|
||||
if (utf8)
|
||||
writeStringUTF8(baos, key);
|
||||
else
|
||||
@ -168,36 +200,36 @@ public class DataHelper {
|
||||
* See readProperties() for the format.
|
||||
* Property keys and values must not contain '=' or ';', this is not checked and they are not escaped
|
||||
* Keys and values must be 255 bytes or less,
|
||||
* @throws DataFormatException if too long.
|
||||
* Formatted length must not exceed 65535 bytes
|
||||
* Should throw DataFormatException if too long but it doesn't.
|
||||
* Strings will be UTF-8 encoded in the byte array.
|
||||
* Warning - confusing method name, Properties is the source.
|
||||
*
|
||||
* @deprecated unused
|
||||
*
|
||||
* @param target returned array as specified in data structure spec
|
||||
* @param props source
|
||||
* @param props source may be null
|
||||
* @return new offset
|
||||
* @throws DataFormatException if any string is over 255 bytes long, or if the total length
|
||||
* is greater than 65535 bytes.
|
||||
*/
|
||||
@Deprecated
|
||||
public static int toProperties(byte target[], int offset, Properties props) throws DataFormatException, IOException {
|
||||
if (props != null) {
|
||||
OrderedProperties p = new OrderedProperties();
|
||||
p.putAll(props);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(32);
|
||||
for (Iterator iter = p.keySet().iterator(); iter.hasNext();) {
|
||||
String key = (String) iter.next();
|
||||
String val = p.getProperty(key);
|
||||
// now make sure they're in UTF-8
|
||||
//key = new String(key.getBytes(), "UTF-8");
|
||||
//val = new String(val.getBytes(), "UTF-8");
|
||||
writeString(baos, key);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(p.size() * 64);
|
||||
for (Map.Entry entry : p.entrySet()) {
|
||||
String key = (String) entry.getKey();
|
||||
String val = (String) entry.getValue();
|
||||
writeStringUTF8(baos, key);
|
||||
baos.write(EQUAL_BYTES);
|
||||
writeString(baos, val);
|
||||
writeStringUTF8(baos, val);
|
||||
baos.write(SEMICOLON_BYTES);
|
||||
}
|
||||
baos.close();
|
||||
byte propBytes[] = baos.toByteArray();
|
||||
if (propBytes.length > 65535)
|
||||
throw new DataFormatException("Properties too big (65535 max): " + propBytes.length);
|
||||
toLong(target, offset, 2, propBytes.length);
|
||||
offset += 2;
|
||||
System.arraycopy(propBytes, 0, target, offset, propBytes.length);
|
||||
@ -213,14 +245,12 @@ public class DataHelper {
|
||||
* Reads the props from the byte array and puts them in the Properties target
|
||||
* See readProperties() for the format.
|
||||
* Warning - confusing method name, Properties is the target.
|
||||
*
|
||||
* @deprecated unused
|
||||
* Strings must be UTF-8 encoded in the byte array.
|
||||
*
|
||||
* @param source source
|
||||
* @param target returned Properties
|
||||
* @return new offset
|
||||
*/
|
||||
@Deprecated
|
||||
public static int fromProperties(byte source[], int offset, Properties target) throws DataFormatException, IOException {
|
||||
int size = (int)fromLong(source, offset, 2);
|
||||
offset += 2;
|
||||
@ -231,12 +261,12 @@ public class DataHelper {
|
||||
String key = readString(in);
|
||||
int read = read(in, eqBuf);
|
||||
if ((read != eqBuf.length) || (!eq(eqBuf, EQUAL_BYTES))) {
|
||||
break;
|
||||
throw new DataFormatException("Bad key");
|
||||
}
|
||||
String val = readString(in);
|
||||
read = read(in, semiBuf);
|
||||
if ((read != semiBuf.length) || (!eq(semiBuf, SEMICOLON_BYTES))) {
|
||||
break;
|
||||
throw new DataFormatException("Bad value");
|
||||
}
|
||||
target.put(key, val);
|
||||
}
|
||||
@ -246,24 +276,20 @@ public class DataHelper {
|
||||
/**
|
||||
* Writes the props to returned byte array, not sorted
|
||||
* (unless the opts param is an OrderedProperties)
|
||||
* Strings will be UTF-8 encoded in the byte array.
|
||||
* See readProperties() for the format.
|
||||
* Property keys and values must not contain '=' or ';', this is not checked and they are not escaped
|
||||
* Keys and values must be 255 bytes or less,
|
||||
* Formatted length must not exceed 65535 bytes
|
||||
* Warning - confusing method name, Properties is the source.
|
||||
*
|
||||
* @deprecated unused
|
||||
*
|
||||
* @throws RuntimeException if either is too long.
|
||||
* @throws DataFormatException if key, value, or total is too long
|
||||
*/
|
||||
@Deprecated
|
||||
public static byte[] toProperties(Properties opts) {
|
||||
public static byte[] toProperties(Properties opts) throws DataFormatException {
|
||||
try {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(2);
|
||||
writeProperties(baos, opts);
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(2 + (32 * opts.size()));
|
||||
writeProperties(baos, opts, true, false);
|
||||
return baos.toByteArray();
|
||||
} catch (DataFormatException dfe) {
|
||||
throw new RuntimeException("Format error writing to memory?! " + dfe.getMessage());
|
||||
} catch (IOException ioe) {
|
||||
throw new RuntimeException("IO error writing to memory?! " + ioe.getMessage());
|
||||
}
|
||||
@ -276,9 +302,9 @@ public class DataHelper {
|
||||
public static String toString(Properties options) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (options != null) {
|
||||
for (Iterator iter = options.keySet().iterator(); iter.hasNext();) {
|
||||
String key = (String) iter.next();
|
||||
String val = options.getProperty(key);
|
||||
for (Map.Entry entry : options.entrySet()) {
|
||||
String key = (String) entry.getKey();
|
||||
String val = (String) entry.getValue();
|
||||
buf.append("[").append(key).append("] = [").append(val).append("]");
|
||||
}
|
||||
} else {
|
||||
@ -353,9 +379,9 @@ public class DataHelper {
|
||||
try {
|
||||
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new SecureFileOutputStream(file), "UTF-8")));
|
||||
out.println("# NOTE: This I2P config file must use UTF-8 encoding");
|
||||
for (Iterator iter = props.keySet().iterator(); iter.hasNext(); ) {
|
||||
String name = (String)iter.next();
|
||||
String val = props.getProperty(name);
|
||||
for (Map.Entry entry : props.entrySet()) {
|
||||
String name = (String) entry.getKey();
|
||||
String val = (String) entry.getValue();
|
||||
out.println(name + "=" + val);
|
||||
}
|
||||
out.flush();
|
||||
@ -720,10 +746,8 @@ public class DataHelper {
|
||||
}
|
||||
|
||||
/** deprecated - used only in DatabaseLookupMessage */
|
||||
@Deprecated
|
||||
public static final byte BOOLEAN_TRUE = 0x1;
|
||||
/** deprecated - used only in DatabaseLookupMessage */
|
||||
@Deprecated
|
||||
public static final byte BOOLEAN_FALSE = 0x0;
|
||||
/** @deprecated unused */
|
||||
@Deprecated
|
||||
|
@ -40,15 +40,15 @@ public class OrderedProperties extends Properties {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set entrySet() {
|
||||
TreeSet rv = new TreeSet(new EntryComparator());
|
||||
public Set<Map.Entry<Object, Object>> entrySet() {
|
||||
TreeSet<Map.Entry<Object, Object>> rv = new TreeSet(new EntryComparator());
|
||||
rv.addAll(super.entrySet());
|
||||
return Collections.unmodifiableSortedSet(rv);
|
||||
}
|
||||
|
||||
private static class EntryComparator implements Comparator {
|
||||
public int compare(Object l, Object r) {
|
||||
return ((String)((Map.Entry)l).getKey()).compareTo(((String)((Map.Entry)r).getKey()));
|
||||
private static class EntryComparator implements Comparator<Map.Entry> {
|
||||
public int compare(Map.Entry l, Map.Entry r) {
|
||||
return ((String)l.getKey()).compareTo(((String)r.getKey()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user