Updated storage info. Updated netty, passes all unit tests
This commit is contained in:
parent
ee6c01e371
commit
7665e116ed
@ -6,7 +6,6 @@
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/4"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/logging/logback-classic-1.0.13.jar" sourcepath="/Dependencies/logging/logback-classic-1.0.13-sources.zip"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/logging/logback-core-1.0.13.jar" sourcepath="/Dependencies/logging/logback-core-1.0.13-sources.zip"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/kryo/reflectasm.jar"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/javassist/javassist.jar"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/BouncyCastleCrypto/bcpkix-jdk15on-151.jar" sourcepath="/Dependencies/BouncyCastleCrypto/bcpkix-jdk15on-151-src.zip"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/BouncyCastleCrypto/bcprov-debug-jdk15on-151.jar" sourcepath="/Dependencies/BouncyCastleCrypto/bcprov-jdk15on-151-src.zip"/>
|
||||
@ -23,9 +22,10 @@
|
||||
<attribute name="javadoc_location" value="jar:platform:/resource/Dependencies/netty/netty-all-4.1.0-javadoc.zip!/"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="lib" path="/Dependencies/dorkbox/object_pool/ObjectPool_v1.1.jar" sourcepath="/Dependencies/dorkbox/object_pool/ObjectPool_v1.1_src.zip"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/asm/asm-5.0.4.jar"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/dorkbox/message_bus/MessageBus_v1.0.jar" sourcepath="/Dependencies/dorkbox/message_bus/MessageBus_v1.0_src.zip"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/JCTools/JCTools-v1.1-alpha-MTAQ.jar" sourcepath="/Dependencies/JCTools/JCTools-1.1-alpha-MTAQ-src.zip"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/kryo/reflectasm-1.11.0.jar" sourcepath="/Dependencies/kryo/reflectasm-1.11.0-sources.zip"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/dorkbox/object_pool/ObjectPool_v1.2.jar" sourcepath="/Dependencies/dorkbox/object_pool/ObjectPool_v1.2_src.zip"/>
|
||||
<classpathentry kind="output" path="classes"/>
|
||||
</classpath>
|
||||
|
94
Dorkbox-Util/src/dorkbox/util/SerializationManager.java
Normal file
94
Dorkbox-Util/src/dorkbox/util/SerializationManager.java
Normal file
@ -0,0 +1,94 @@
|
||||
package dorkbox.util;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.KryoException;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public
|
||||
interface SerializationManager {
|
||||
|
||||
|
||||
/**
|
||||
* Registers the class using the lowest, next available integer ID and the
|
||||
* {@link Kryo#getDefaultSerializer(Class) default serializer}. If the class
|
||||
* is already registered, the existing entry is updated with the new
|
||||
* serializer. Registering a primitive also affects the corresponding
|
||||
* primitive wrapper.
|
||||
* <p/>
|
||||
* Because the ID assigned is affected by the IDs registered before it, the
|
||||
* order classes are registered is important when using this method. The
|
||||
* order must be the same at deserialization as it was for serialization.
|
||||
*/
|
||||
void register(Class<?> clazz);
|
||||
|
||||
/**
|
||||
* Registers the class using the lowest, next available integer ID and the
|
||||
* specified serializer. If the class is already registered, the existing
|
||||
* entry is updated with the new serializer. Registering a primitive also
|
||||
* affects the corresponding primitive wrapper.
|
||||
* <p/>
|
||||
* Because the ID assigned is affected by the IDs registered before it, the
|
||||
* order classes are registered is important when using this method. The
|
||||
* order must be the same at deserialization as it was for serialization.
|
||||
*/
|
||||
void register(Class<?> clazz, Serializer<?> serializer);
|
||||
|
||||
|
||||
/**
|
||||
* Registers the class using the specified ID and serializer. If the ID is
|
||||
* already in use by the same type, the old entry is overwritten. If the ID
|
||||
* is already in use by a different type, a {@link KryoException} is thrown.
|
||||
* Registering a primitive also affects the corresponding primitive wrapper.
|
||||
* <p/>
|
||||
* IDs must be the same at deserialization as they were for serialization.
|
||||
*
|
||||
* @param id Must be >= 0. Smaller IDs are serialized more efficiently. IDs
|
||||
* 0-8 are used by default for primitive types and String, but
|
||||
* these IDs can be repurposed.
|
||||
*/
|
||||
void register(Class<?> clazz, Serializer<?> serializer, int id);
|
||||
|
||||
/**
|
||||
* Waits until a kryo is available to write, using CAS operations to prevent having to synchronize.
|
||||
* <p/>
|
||||
* No crypto and no sequence number
|
||||
* <p/>
|
||||
* There is a small speed penalty if there were no kryo's available to use.
|
||||
*/
|
||||
void write(ByteBuf buffer, Object message);
|
||||
|
||||
/**
|
||||
* Reads an object from the buffer.
|
||||
* <p/>
|
||||
* No crypto and no sequence number
|
||||
*
|
||||
* @param length should ALWAYS be the length of the expected object!
|
||||
*/
|
||||
Object read(ByteBuf buffer, int length);
|
||||
|
||||
/**
|
||||
* Writes the class and object using an available kryo instance
|
||||
*/
|
||||
void writeFullClassAndObject(Output output, Object value);
|
||||
|
||||
/**
|
||||
* Returns a class read from the input
|
||||
*/
|
||||
Object readFullClassAndObject(Input input);
|
||||
|
||||
/**
|
||||
* Borrows a kryo from the threadsafe pool. You must release it back to the pool when done.
|
||||
*/
|
||||
Kryo take() throws InterruptedException;
|
||||
|
||||
/**
|
||||
* Releases the kryo back to the threadsafe pool
|
||||
*/
|
||||
void release(Kryo kryo);
|
||||
}
|
@ -25,7 +25,8 @@ import java.util.Map.Entry;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Sys {
|
||||
public
|
||||
class Sys {
|
||||
public static final int javaVersion = getJavaVersion();
|
||||
public static final boolean isAndroid = getIsAndroid();
|
||||
|
||||
@ -34,9 +35,10 @@ public class Sys {
|
||||
public static final int GIGABYTE = 1024 * MEGABYTE;
|
||||
public static final long TERABYTE = 1024L * GIGABYTE;
|
||||
|
||||
public static char[] HEX_CHARS = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
public static char[] HEX_CHARS = new char[] {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
|
||||
public static final char[] convertStringToChars(String string) {
|
||||
public static final
|
||||
char[] convertStringToChars(String string) {
|
||||
char[] charArray = string.toCharArray();
|
||||
|
||||
eraseString(string);
|
||||
@ -44,7 +46,8 @@ public class Sys {
|
||||
return charArray;
|
||||
}
|
||||
|
||||
private static boolean getIsAndroid() {
|
||||
private static
|
||||
boolean getIsAndroid() {
|
||||
try {
|
||||
Class.forName("android.os.Process");
|
||||
return true;
|
||||
@ -53,31 +56,41 @@ public class Sys {
|
||||
}
|
||||
}
|
||||
|
||||
private static int getJavaVersion() {
|
||||
private static
|
||||
int getJavaVersion() {
|
||||
String fullJavaVersion = System.getProperty("java.version");
|
||||
|
||||
// Converts a java version string, such as "1.7u45", and converts it into 7
|
||||
char versionChar;
|
||||
if (fullJavaVersion.startsWith("1.")) {
|
||||
versionChar = fullJavaVersion.charAt(2);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
versionChar = fullJavaVersion.charAt(0);
|
||||
}
|
||||
|
||||
switch (versionChar) {
|
||||
case '4': return 4;
|
||||
case '5': return 5;
|
||||
case '6': return 6;
|
||||
case '7': return 7;
|
||||
case '8': return 8;
|
||||
case '9': return 9;
|
||||
default: return -1;
|
||||
case '4':
|
||||
return 4;
|
||||
case '5':
|
||||
return 5;
|
||||
case '6':
|
||||
return 6;
|
||||
case '7':
|
||||
return 7;
|
||||
case '8':
|
||||
return 8;
|
||||
case '9':
|
||||
return 9;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final void eraseString(String string) {
|
||||
public static final
|
||||
void eraseString(String string) {
|
||||
// You can change the value of the inner char[] using reflection.
|
||||
//
|
||||
// You must be careful to either change it with an array of the same length,
|
||||
@ -120,10 +133,10 @@ public class Sys {
|
||||
|
||||
/**
|
||||
* FROM: https://www.cqse.eu/en/blog/string-replace-performance/
|
||||
*
|
||||
* <p/>
|
||||
* Replaces all occurrences of keys of the given map in the given string
|
||||
* with the associated value in that map.
|
||||
*
|
||||
* <p/>
|
||||
* This method is semantically the same as calling
|
||||
* {@link String#replace(CharSequence, CharSequence)} for each of the
|
||||
* entries in the map, but may be significantly faster for many replacements
|
||||
@ -131,11 +144,12 @@ public class Sys {
|
||||
* {@link String#replace(CharSequence, CharSequence)} uses regular
|
||||
* expressions internally and results in many String object allocations when
|
||||
* applied iteratively.
|
||||
*
|
||||
* <p/>
|
||||
* The order in which replacements are applied depends on the order of the
|
||||
* map's entry set.
|
||||
*/
|
||||
public static String replaceStringFast(String string, Map<String, String> replacements) {
|
||||
public static
|
||||
String replaceStringFast(String string, Map<String, String> replacements) {
|
||||
StringBuilder sb = new StringBuilder(string);
|
||||
for (Entry<String, String> entry : replacements.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
@ -158,9 +172,10 @@ public class Sys {
|
||||
*
|
||||
* @return index if it's there, -1 if not there
|
||||
*/
|
||||
public static int searchStringFast(String string, char c) {
|
||||
public static
|
||||
int searchStringFast(String string, char c) {
|
||||
int length = string.length();
|
||||
for (int i=0;i<length;i++) {
|
||||
for (int i = 0; i < length; i++) {
|
||||
if (string.charAt(i) == c) {
|
||||
return i;
|
||||
}
|
||||
@ -170,7 +185,8 @@ public class Sys {
|
||||
}
|
||||
|
||||
|
||||
public static String getSizePretty(final long size) {
|
||||
public static
|
||||
String getSizePretty(final long size) {
|
||||
if (size > TERABYTE) {
|
||||
return String.format("%2.2fTB", (float) size / TERABYTE);
|
||||
}
|
||||
@ -190,7 +206,8 @@ public class Sys {
|
||||
/**
|
||||
* Convenient close for a stream.
|
||||
*/
|
||||
public static void close(InputStream inputStream) {
|
||||
public static
|
||||
void close(InputStream inputStream) {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
@ -204,7 +221,8 @@ public class Sys {
|
||||
/**
|
||||
* Convenient close for a stream.
|
||||
*/
|
||||
public static void close(OutputStream outputStream) {
|
||||
public static
|
||||
void close(OutputStream outputStream) {
|
||||
if (outputStream != null) {
|
||||
try {
|
||||
outputStream.close();
|
||||
@ -218,7 +236,8 @@ public class Sys {
|
||||
/**
|
||||
* Convenient close for a Reader.
|
||||
*/
|
||||
public static void close(Reader inputReader) {
|
||||
public static
|
||||
void close(Reader inputReader) {
|
||||
if (inputReader != null) {
|
||||
try {
|
||||
inputReader.close();
|
||||
@ -232,7 +251,8 @@ public class Sys {
|
||||
/**
|
||||
* Convenient close for a Writer.
|
||||
*/
|
||||
public static void close(Writer outputWriter) {
|
||||
public static
|
||||
void close(Writer outputWriter) {
|
||||
if (outputWriter != null) {
|
||||
try {
|
||||
outputWriter.close();
|
||||
@ -245,10 +265,11 @@ public class Sys {
|
||||
|
||||
/**
|
||||
* Copy the contents of the input stream to the output stream.
|
||||
* <p>
|
||||
* <p/>
|
||||
* DOES NOT CLOSE THE STEAMS!
|
||||
*/
|
||||
public static <T extends OutputStream> T copyStream(InputStream inputStream, T outputStream) throws IOException {
|
||||
public static
|
||||
<T extends OutputStream> T copyStream(InputStream inputStream, T outputStream) throws IOException {
|
||||
byte[] buffer = new byte[4096];
|
||||
int read = 0;
|
||||
while ((read = inputStream.read(buffer)) > 0) {
|
||||
@ -261,7 +282,8 @@ public class Sys {
|
||||
/**
|
||||
* Convert the contents of the input stream to a byte array.
|
||||
*/
|
||||
public static byte[] getBytesFromStream(InputStream inputStream) throws IOException {
|
||||
public static
|
||||
byte[] getBytesFromStream(InputStream inputStream) throws IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
@ -275,11 +297,13 @@ public class Sys {
|
||||
return baos.toByteArray();
|
||||
}
|
||||
|
||||
public static final byte[] copyBytes(byte[] src) {
|
||||
public static final
|
||||
byte[] copyBytes(byte[] src) {
|
||||
return copyBytes(src, 0);
|
||||
}
|
||||
|
||||
public static final byte[] copyBytes(byte[] src, int position) {
|
||||
public static final
|
||||
byte[] copyBytes(byte[] src, int position) {
|
||||
int length = src.length - position;
|
||||
|
||||
byte[] b = new byte[length];
|
||||
@ -287,7 +311,8 @@ public class Sys {
|
||||
return b;
|
||||
}
|
||||
|
||||
public static final byte[] concatBytes(byte[]... arrayBytes) {
|
||||
public static final
|
||||
byte[] concatBytes(byte[]... arrayBytes) {
|
||||
int length = 0;
|
||||
for (byte[] bytes : arrayBytes) {
|
||||
length += bytes.length;
|
||||
@ -304,8 +329,11 @@ public class Sys {
|
||||
return concatBytes;
|
||||
}
|
||||
|
||||
/** gets the SHA256 hash + SALT of the specified username, as UTF-16 */
|
||||
public static final byte[] getSha256WithSalt(String username, byte[] saltBytes) {
|
||||
/**
|
||||
* gets the SHA256 hash + SALT of the specified username, as UTF-16
|
||||
*/
|
||||
public static final
|
||||
byte[] getSha256WithSalt(String username, byte[] saltBytes) {
|
||||
if (username == null) {
|
||||
return null;
|
||||
}
|
||||
@ -322,8 +350,11 @@ public class Sys {
|
||||
return usernameHashBytes;
|
||||
}
|
||||
|
||||
/** gets the SHA256 hash of the specified string, as UTF-16 */
|
||||
public static final byte[] getSha256(String string) {
|
||||
/**
|
||||
* gets the SHA256 hash of the specified string, as UTF-16
|
||||
*/
|
||||
public static final
|
||||
byte[] getSha256(String string) {
|
||||
byte[] charToBytes = Sys.charToBytes(string.toCharArray());
|
||||
|
||||
SHA256Digest sha256 = new SHA256Digest();
|
||||
@ -334,8 +365,11 @@ public class Sys {
|
||||
return usernameHashBytes;
|
||||
}
|
||||
|
||||
/** gets the SHA256 hash of the specified byte array */
|
||||
public static final byte[] getSha256(byte[] bytes) {
|
||||
/**
|
||||
* gets the SHA256 hash of the specified byte array
|
||||
*/
|
||||
public static final
|
||||
byte[] getSha256(byte[] bytes) {
|
||||
|
||||
SHA256Digest sha256 = new SHA256Digest();
|
||||
byte[] hashBytes = new byte[sha256.getDigestSize()];
|
||||
@ -345,20 +379,24 @@ public class Sys {
|
||||
return hashBytes;
|
||||
}
|
||||
|
||||
/** this saves the char array in UTF-16 format of bytes */
|
||||
public static final byte[] charToBytes(char[] text) {
|
||||
/**
|
||||
* this saves the char array in UTF-16 format of bytes
|
||||
*/
|
||||
public static final
|
||||
byte[] charToBytes(char[] text) {
|
||||
// NOTE: this saves the char array in UTF-16 format of bytes.
|
||||
byte[] bytes = new byte[text.length*2];
|
||||
for(int i=0; i<text.length; i++) {
|
||||
bytes[2*i] = (byte) (text[i] >> 8);
|
||||
bytes[2*i+1] = (byte) text[i];
|
||||
byte[] bytes = new byte[text.length * 2];
|
||||
for (int i = 0; i < text.length; i++) {
|
||||
bytes[2 * i] = (byte) (text[i] >> 8);
|
||||
bytes[2 * i + 1] = (byte) text[i];
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
public static final byte[] intsToBytes(int[] ints) {
|
||||
public static final
|
||||
byte[] intsToBytes(int[] ints) {
|
||||
int length = ints.length;
|
||||
byte[] bytes = new byte[length];
|
||||
|
||||
@ -369,13 +407,14 @@ public class Sys {
|
||||
return new byte[length];
|
||||
}
|
||||
|
||||
bytes[i] = (byte)intValue;
|
||||
bytes[i] = (byte) intValue;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static final int[] bytesToInts(byte[] bytes) {
|
||||
public static final
|
||||
int[] bytesToInts(byte[] bytes) {
|
||||
int length = bytes.length;
|
||||
int[] ints = new int[length];
|
||||
|
||||
@ -386,11 +425,13 @@ public class Sys {
|
||||
return ints;
|
||||
}
|
||||
|
||||
public static final String bytesToHex(byte[] bytes) {
|
||||
public static final
|
||||
String bytesToHex(byte[] bytes) {
|
||||
return bytesToHex(bytes, false);
|
||||
}
|
||||
|
||||
public static final String bytesToHex(byte[] bytes, boolean padding) {
|
||||
public static final
|
||||
String bytesToHex(byte[] bytes, boolean padding) {
|
||||
if (padding) {
|
||||
char[] hexString = new char[3 * bytes.length];
|
||||
int j = 0;
|
||||
@ -402,7 +443,8 @@ public class Sys {
|
||||
}
|
||||
|
||||
return new String(hexString);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
char[] hexString = new char[2 * bytes.length];
|
||||
int j = 0;
|
||||
|
||||
@ -419,47 +461,48 @@ public class Sys {
|
||||
* Converts an ASCII character representing a hexadecimal
|
||||
* value into its integer equivalent.
|
||||
*/
|
||||
public static final int hexByteToInt(byte b) {
|
||||
public static final
|
||||
int hexByteToInt(byte b) {
|
||||
switch (b) {
|
||||
case '0' :
|
||||
case '0':
|
||||
return 0;
|
||||
case '1' :
|
||||
case '1':
|
||||
return 1;
|
||||
case '2' :
|
||||
case '2':
|
||||
return 2;
|
||||
case '3' :
|
||||
case '3':
|
||||
return 3;
|
||||
case '4' :
|
||||
case '4':
|
||||
return 4;
|
||||
case '5' :
|
||||
case '5':
|
||||
return 5;
|
||||
case '6' :
|
||||
case '6':
|
||||
return 6;
|
||||
case '7' :
|
||||
case '7':
|
||||
return 7;
|
||||
case '8' :
|
||||
case '8':
|
||||
return 8;
|
||||
case '9' :
|
||||
case '9':
|
||||
return 9;
|
||||
case 'A' :
|
||||
case 'a' :
|
||||
case 'A':
|
||||
case 'a':
|
||||
return 10;
|
||||
case 'B' :
|
||||
case 'b' :
|
||||
case 'B':
|
||||
case 'b':
|
||||
return 11;
|
||||
case 'C' :
|
||||
case 'c' :
|
||||
case 'C':
|
||||
case 'c':
|
||||
return 12;
|
||||
case 'D' :
|
||||
case 'd' :
|
||||
case 'D':
|
||||
case 'd':
|
||||
return 13;
|
||||
case 'E' :
|
||||
case 'e' :
|
||||
case 'E':
|
||||
case 'e':
|
||||
return 14;
|
||||
case 'F' :
|
||||
case 'f' :
|
||||
case 'F':
|
||||
case 'f':
|
||||
return 15;
|
||||
default :
|
||||
default:
|
||||
throw new IllegalArgumentException("Error decoding byte");
|
||||
}
|
||||
}
|
||||
@ -467,7 +510,8 @@ public class Sys {
|
||||
/**
|
||||
* A 4-digit hex result.
|
||||
*/
|
||||
public static final void hex4(char c, StringBuilder sb) {
|
||||
public static final
|
||||
void hex4(char c, StringBuilder sb) {
|
||||
sb.append(HEX_CHARS[(c & 0xF000) >> 12]);
|
||||
sb.append(HEX_CHARS[(c & 0x0F00) >> 8]);
|
||||
sb.append(HEX_CHARS[(c & 0x00F0) >> 4]);
|
||||
@ -478,12 +522,12 @@ public class Sys {
|
||||
* Returns a string representation of the byte array as a series of
|
||||
* hexadecimal characters.
|
||||
*
|
||||
* @param bytes
|
||||
* byte array to convert
|
||||
* @param bytes byte array to convert
|
||||
* @return a string representation of the byte array as a series of
|
||||
* hexadecimal characters
|
||||
*/
|
||||
public static final String toHexString(byte[] bytes) {
|
||||
public static final
|
||||
String toHexString(byte[] bytes) {
|
||||
char[] hexString = new char[2 * bytes.length];
|
||||
int j = 0;
|
||||
|
||||
@ -501,11 +545,12 @@ public class Sys {
|
||||
* @param originalArray this is the base of the XOR operation.
|
||||
* @param keyArray this is XOR'd into the original array, repeats if necessary.
|
||||
*/
|
||||
public static void xorArrays(byte[] originalArray, byte[] keyArray) {
|
||||
public static
|
||||
void xorArrays(byte[] originalArray, byte[] keyArray) {
|
||||
int keyIndex = 0;
|
||||
int keyLength = keyArray.length;
|
||||
|
||||
for (int i=0;i<originalArray.length;i++) {
|
||||
for (int i = 0; i < originalArray.length; i++) {
|
||||
//XOR the data and start over if necessary
|
||||
originalArray[i] = (byte) (originalArray[i] ^ keyArray[keyIndex++ % keyLength]);
|
||||
}
|
||||
@ -513,7 +558,8 @@ public class Sys {
|
||||
|
||||
|
||||
|
||||
public static final byte[] encodeStringArray(List<String> array) {
|
||||
public static final
|
||||
byte[] encodeStringArray(List<String> array) {
|
||||
int length = 0;
|
||||
for (String s : array) {
|
||||
byte[] bytes = s.getBytes();
|
||||
@ -526,7 +572,7 @@ public class Sys {
|
||||
return new byte[0];
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[length+array.size()];
|
||||
byte[] bytes = new byte[length + array.size()];
|
||||
|
||||
length = 0;
|
||||
for (String s : array) {
|
||||
@ -539,18 +585,19 @@ public class Sys {
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public static final ArrayList<String> decodeStringArray(byte[] bytes) {
|
||||
public static final
|
||||
ArrayList<String> decodeStringArray(byte[] bytes) {
|
||||
int length = bytes.length;
|
||||
int position = 0;
|
||||
byte token = (byte) 0x01;
|
||||
ArrayList<String> list = new ArrayList<String>(0);
|
||||
|
||||
int last = 0;
|
||||
while (last+position < length) {
|
||||
byte b = bytes[last+position++];
|
||||
if (b == token ) {
|
||||
byte[] xx = new byte[position-1];
|
||||
System.arraycopy(bytes, last, xx, 0, position-1);
|
||||
while (last + position < length) {
|
||||
byte b = bytes[last + position++];
|
||||
if (b == token) {
|
||||
byte[] xx = new byte[position - 1];
|
||||
System.arraycopy(bytes, last, xx, 0, position - 1);
|
||||
list.add(new String(xx));
|
||||
last += position;
|
||||
position = 0;
|
||||
@ -561,32 +608,35 @@ public class Sys {
|
||||
return list;
|
||||
}
|
||||
|
||||
public static String printArrayRaw(byte[] bytes) {
|
||||
public static
|
||||
String printArrayRaw(byte[] bytes) {
|
||||
return printArrayRaw(bytes, 0);
|
||||
}
|
||||
|
||||
public static String printArrayRaw(byte[] bytes, int lineLength) {
|
||||
public static
|
||||
String printArrayRaw(byte[] bytes, int lineLength) {
|
||||
if (lineLength > 0) {
|
||||
int mod = lineLength;
|
||||
int length = bytes.length;
|
||||
int comma = length-1;
|
||||
int comma = length - 1;
|
||||
|
||||
StringBuilder builder = new StringBuilder(length + length/mod);
|
||||
StringBuilder builder = new StringBuilder(length + length / mod);
|
||||
for (int i = 0; i < length; i++) {
|
||||
builder.append(bytes[i]);
|
||||
if (i < comma) {
|
||||
builder.append(",");
|
||||
}
|
||||
if (i > 0 && i%mod == 0) {
|
||||
if (i > 0 && i % mod == 0) {
|
||||
builder.append(OS.LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
int length = bytes.length;
|
||||
int comma = length-1;
|
||||
int comma = length - 1;
|
||||
|
||||
StringBuilder builder = new StringBuilder(length + length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
@ -600,25 +650,29 @@ public class Sys {
|
||||
}
|
||||
}
|
||||
|
||||
public static void printArray(byte[] bytes) {
|
||||
public static
|
||||
void printArray(byte[] bytes) {
|
||||
printArray(bytes, bytes.length, true);
|
||||
}
|
||||
|
||||
public static void printArray(byte[] bytes, int length, boolean includeByteCount) {
|
||||
public static
|
||||
void printArray(byte[] bytes, int length, boolean includeByteCount) {
|
||||
printArray(bytes, length, includeByteCount, 40);
|
||||
}
|
||||
|
||||
public static void printArray(byte[] bytes, int length, boolean includeByteCount, int lineLength) {
|
||||
public static
|
||||
void printArray(byte[] bytes, int length, boolean includeByteCount, int lineLength) {
|
||||
if (includeByteCount) {
|
||||
System.err.println("Bytes: " + length);
|
||||
}
|
||||
|
||||
int comma = length-1;
|
||||
int comma = length - 1;
|
||||
|
||||
StringBuilder builder;
|
||||
if (lineLength > 0) {
|
||||
builder = new StringBuilder(length + comma + length/lineLength + 2);
|
||||
} else {
|
||||
builder = new StringBuilder(length + comma + length / lineLength + 2);
|
||||
}
|
||||
else {
|
||||
builder = new StringBuilder(length + comma + 2);
|
||||
}
|
||||
builder.append("{");
|
||||
@ -628,7 +682,7 @@ public class Sys {
|
||||
if (i < comma) {
|
||||
builder.append(",");
|
||||
}
|
||||
if (i > 0 && lineLength > 0 && i%lineLength == 0) {
|
||||
if (i > 0 && lineLength > 0 && i % lineLength == 0) {
|
||||
builder.append(OS.LINE_SEPARATOR);
|
||||
}
|
||||
}
|
||||
@ -658,17 +712,18 @@ public class Sys {
|
||||
* <p/>
|
||||
*
|
||||
* @throws UnknownHostException If the LAN address of the machine cannot be found.
|
||||
*
|
||||
* <p/>
|
||||
* From: https://issues.apache.org/jira/browse/JCS-40
|
||||
*/
|
||||
public static InetAddress getLocalHostLanAddress() throws UnknownHostException {
|
||||
public static
|
||||
InetAddress getLocalHostLanAddress() throws UnknownHostException {
|
||||
try {
|
||||
InetAddress candidateAddress = null;
|
||||
// Iterate all NICs (network interface cards)...
|
||||
for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
|
||||
for (Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements(); ) {
|
||||
NetworkInterface iface = ifaces.nextElement();
|
||||
// Iterate all IP addresses assigned to each card...
|
||||
for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
|
||||
for (Enumeration<InetAddress> inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements(); ) {
|
||||
InetAddress inetAddr = inetAddrs.nextElement();
|
||||
if (!inetAddr.isLoopbackAddress()) {
|
||||
|
||||
@ -700,8 +755,7 @@ public class Sys {
|
||||
throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
|
||||
}
|
||||
return jdkSuppliedAddress;
|
||||
}
|
||||
catch (Exception e) {
|
||||
} catch (Exception e) {
|
||||
UnknownHostException unknownHostException = new UnknownHostException("Failed to determine LAN address: " + e);
|
||||
unknownHostException.initCause(e);
|
||||
throw unknownHostException;
|
||||
@ -711,44 +765,39 @@ public class Sys {
|
||||
|
||||
/**
|
||||
* This will retrieve your IP address via an HTTP server.
|
||||
* <p>
|
||||
* <p/>
|
||||
* <b>NOTE: Use DnsClient.getPublicIp() instead. It's much faster and more reliable as it uses DNS.</b>
|
||||
*
|
||||
* @return the public IP address if found, or null if it didn't find it
|
||||
*/
|
||||
@Deprecated
|
||||
public static String getPublicIpViaHttp() {
|
||||
public static
|
||||
String getPublicIpViaHttp() {
|
||||
// method 1: use DNS servers
|
||||
// dig +short myip.opendns.com @resolver1.opendns.com
|
||||
|
||||
// method 2: use public http servers
|
||||
final String websites[] = {
|
||||
"http://ip.dorkbox.com/",
|
||||
"http://ip.javalauncher.com/",
|
||||
"http://checkip.dyndns.com/",
|
||||
"http://checkip.dyn.com/",
|
||||
"http://curlmyip.com/",
|
||||
"http://tnx.nl/ip",
|
||||
"http://ipecho.net/plain",
|
||||
"http://icanhazip.com/",
|
||||
"http://ip.appspot.com/",
|
||||
};
|
||||
final String websites[] = {"http://ip.dorkbox.com/", "http://ip.javalauncher.com/", "http://checkip.dyndns.com/",
|
||||
"http://checkip.dyn.com/", "http://curlmyip.com/", "http://tnx.nl/ip", "http://ipecho.net/plain",
|
||||
"http://icanhazip.com/", "http://ip.appspot.com/",};
|
||||
|
||||
// loop, since they won't always work.
|
||||
for (int i=0;i<websites.length;i++) {
|
||||
for (int i = 0; i < websites.length; i++) {
|
||||
try {
|
||||
URL autoIP = new URL(websites[i]);
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(autoIP.openStream()));
|
||||
String response = in.readLine().trim();
|
||||
String response = in.readLine()
|
||||
.trim();
|
||||
in.close();
|
||||
|
||||
Pattern pattern = Pattern.compile("\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\b");
|
||||
Matcher matcher = pattern.matcher(response);
|
||||
if (matcher.find()) {
|
||||
String IP = matcher.group().trim();
|
||||
String IP = matcher.group()
|
||||
.trim();
|
||||
return IP;
|
||||
}
|
||||
} catch (Exception e){
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@ -757,9 +806,11 @@ public class Sys {
|
||||
|
||||
/**
|
||||
* Tries to retrieve the IP address from the NIC. Order is ETHx -> EMx -> WLANx
|
||||
*
|
||||
* @return null if not found
|
||||
*/
|
||||
public static InetAddress getIpAddressesFromNic() {
|
||||
public static
|
||||
InetAddress getIpAddressesFromNic() {
|
||||
try {
|
||||
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
|
||||
while (nets.hasMoreElements()) {
|
||||
|
@ -15,38 +15,34 @@
|
||||
*/
|
||||
package dorkbox.util.bytes;
|
||||
|
||||
import org.bouncycastle.crypto.digests.SHA256Digest;
|
||||
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Necessary to provide equals and hashcode methods on a byte arrays, if they are to be used as keys in a map/set/etc
|
||||
*/
|
||||
public final class ByteArrayWrapper {
|
||||
private final byte[] data;
|
||||
public final
|
||||
class ByteArrayWrapper {
|
||||
public static final Charset UTF_8 = Charset.forName("UTF-8");
|
||||
|
||||
private byte[] data;
|
||||
private Integer hashCode;
|
||||
|
||||
/**
|
||||
* Makes a safe copy of the byte array, so that changes to the original do not affect the wrapper.
|
||||
* Side affect is additional memory is used.
|
||||
*/
|
||||
public static ByteArrayWrapper copy(byte[] data) {
|
||||
return new ByteArrayWrapper(data, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Does not make a copy of the data, so changes to the original will also affect the wrapper.
|
||||
* Side affect is no extra memory is needed.
|
||||
*/
|
||||
public static ByteArrayWrapper wrap(byte[] data) {
|
||||
return new ByteArrayWrapper(data, false);
|
||||
private
|
||||
ByteArrayWrapper() {
|
||||
// this is necessary for kryo
|
||||
}
|
||||
|
||||
/**
|
||||
* Permits the re-use of a byte array.
|
||||
*
|
||||
* @param copyBytes if TRUE, then the byteArray is copies. if FALSE, the byte array is uses as-is.
|
||||
* Using FALSE IS DANGEROUS!!!! If the underlying byte array is modified, this changes as well.
|
||||
*/
|
||||
private ByteArrayWrapper(byte[] data, boolean copyBytes) {
|
||||
private
|
||||
ByteArrayWrapper(byte[] data, boolean copyBytes) {
|
||||
if (data == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
@ -56,27 +52,61 @@ public final class ByteArrayWrapper {
|
||||
this.data = new byte[length];
|
||||
// copy so it's immutable as a key.
|
||||
System.arraycopy(data, 0, this.data, 0, length);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] getBytes() {
|
||||
/**
|
||||
* Makes a safe copy of the byte array, so that changes to the original do not affect the wrapper.
|
||||
* Side affect is additional memory is used.
|
||||
*/
|
||||
public static
|
||||
ByteArrayWrapper copy(byte[] data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ByteArrayWrapper(data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does not make a copy of the data, so changes to the original will also affect the wrapper.
|
||||
* Side affect is no extra memory is needed.
|
||||
*/
|
||||
public static
|
||||
ByteArrayWrapper wrap(byte[] data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
return new ByteArrayWrapper(data, false);
|
||||
}
|
||||
|
||||
public static
|
||||
ByteArrayWrapper wrap(String data) {
|
||||
if (data == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
byte[] bytes = data.getBytes(UTF_8);
|
||||
|
||||
SHA256Digest digest = new SHA256Digest();
|
||||
digest.update(bytes, 0, bytes.length);
|
||||
byte[] hashBytes = new byte[digest.getDigestSize()];
|
||||
digest.doFinal(hashBytes, 0);
|
||||
|
||||
return ByteArrayWrapper.wrap(hashBytes);
|
||||
}
|
||||
|
||||
public
|
||||
byte[] getBytes() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof ByteArrayWrapper)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// CANNOT be null, so we don't have to null check!
|
||||
return Arrays.equals(this.data, ((ByteArrayWrapper) other).data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
public
|
||||
int hashCode() {
|
||||
// might be null for a thread because it's stale. who cares, get the value again
|
||||
Integer hashCode = this.hashCode;
|
||||
if (hashCode == null) {
|
||||
@ -87,7 +117,19 @@ public final class ByteArrayWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public
|
||||
boolean equals(Object other) {
|
||||
if (!(other instanceof ByteArrayWrapper)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// CANNOT be null, so we don't have to null check!
|
||||
return Arrays.equals(this.data, ((ByteArrayWrapper) other).data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
String toString() {
|
||||
return "ByteArrayWrapper " + java.util.Arrays.toString(this.data);
|
||||
}
|
||||
}
|
@ -1,29 +1,31 @@
|
||||
package dorkbox.util.crypto.serialization;
|
||||
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import org.bouncycastle.crypto.params.ECDomainParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
import org.bouncycastle.math.ec.ECCurve;
|
||||
import org.bouncycastle.math.ec.ECPoint;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Only public keys are ever sent across the wire.
|
||||
*/
|
||||
public class EccPublicKeySerializer extends Serializer<ECPublicKeyParameters> {
|
||||
public
|
||||
class EccPublicKeySerializer extends Serializer<ECPublicKeyParameters> {
|
||||
|
||||
@Override
|
||||
public void write(Kryo kryo, Output output, ECPublicKeyParameters key) {
|
||||
public
|
||||
void write(Kryo kryo, Output output, ECPublicKeyParameters key) {
|
||||
write(output, key);
|
||||
}
|
||||
|
||||
public static void write(Output output, ECPublicKeyParameters key) {
|
||||
public static
|
||||
void write(Output output, ECPublicKeyParameters key) {
|
||||
byte[] bytes;
|
||||
int length;
|
||||
|
||||
@ -50,12 +52,13 @@ public class EccPublicKeySerializer extends Serializer<ECPublicKeyParameters> {
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
@Override
|
||||
public ECPublicKeyParameters read(Kryo kryo, Input input, Class type) {
|
||||
ECPublicKeyParameters ecPublicKeyParameters = read(input);
|
||||
return ecPublicKeyParameters;
|
||||
public
|
||||
ECPublicKeyParameters read(Kryo kryo, Input input, Class type) {
|
||||
return read(input);
|
||||
}
|
||||
|
||||
public static ECPublicKeyParameters read(Input input) {
|
||||
public static
|
||||
ECPublicKeyParameters read(Input input) {
|
||||
byte[] bytes;
|
||||
int length;
|
||||
|
||||
@ -88,7 +91,6 @@ public class EccPublicKeySerializer extends Serializer<ECPublicKeyParameters> {
|
||||
input.readBytes(bytes, 0, length);
|
||||
ECPoint Q = curve.decodePoint(bytes);
|
||||
|
||||
ECPublicKeyParameters ecPublicKeyParameters = new ECPublicKeyParameters(Q, ecDomainParameters);
|
||||
return ecPublicKeyParameters;
|
||||
return new ECPublicKeyParameters(Q, ecDomainParameters);
|
||||
}
|
||||
}
|
||||
|
116
Dorkbox-Util/src/dorkbox/util/database/DB_Server.java
Normal file
116
Dorkbox-Util/src/dorkbox/util/database/DB_Server.java
Normal file
@ -0,0 +1,116 @@
|
||||
package dorkbox.util.database;
|
||||
|
||||
import dorkbox.util.bytes.ByteArrayWrapper;
|
||||
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
|
||||
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public
|
||||
class DB_Server {
|
||||
/**
|
||||
* Address 0.0.0.0/32 may be used as a source address for this host on this network.
|
||||
*/
|
||||
public static final ByteArrayWrapper IP_0_0_0_0 = ByteArrayWrapper.wrap(new byte[] {0, 0, 0, 0});
|
||||
|
||||
// salt + IP address is used for equals!
|
||||
private byte[] ipAddress;
|
||||
private byte[] salt;
|
||||
|
||||
private ECPrivateKeyParameters privateKey;
|
||||
private ECPublicKeyParameters publicKey;
|
||||
|
||||
// must have empty constructor
|
||||
public
|
||||
DB_Server() {
|
||||
}
|
||||
|
||||
public
|
||||
byte[] getAddress() {
|
||||
if (this.ipAddress == null) {
|
||||
return null;
|
||||
}
|
||||
return this.ipAddress;
|
||||
}
|
||||
|
||||
public
|
||||
void setAddress(byte[] ipAddress) {
|
||||
this.ipAddress = ipAddress;
|
||||
}
|
||||
|
||||
public
|
||||
byte[] getSalt() {
|
||||
return this.salt;
|
||||
}
|
||||
|
||||
public
|
||||
void setSalt(byte[] salt) {
|
||||
this.salt = salt;
|
||||
}
|
||||
|
||||
|
||||
public
|
||||
ECPrivateKeyParameters getPrivateKey() {
|
||||
return this.privateKey;
|
||||
}
|
||||
|
||||
public
|
||||
void setPrivateKey(ECPrivateKeyParameters privateKey) {
|
||||
this.privateKey = privateKey;
|
||||
}
|
||||
|
||||
|
||||
public
|
||||
ECPublicKeyParameters getPublicKey() {
|
||||
return this.publicKey;
|
||||
}
|
||||
|
||||
public
|
||||
void setPublicKey(ECPublicKeyParameters publicKey) {
|
||||
this.publicKey = publicKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + (this.ipAddress == null ? 0 : Arrays.hashCode(this.ipAddress));
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
DB_Server other = (DB_Server) obj;
|
||||
if (this.ipAddress == null) {
|
||||
if (other.ipAddress != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!Arrays.equals(this.ipAddress, other.ipAddress)) {
|
||||
return false;
|
||||
}
|
||||
return Arrays.equals(this.salt, other.salt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
String toString() {
|
||||
byte[] bytes = this.ipAddress;
|
||||
if (bytes != null) {
|
||||
return "DB_Server " + Arrays.toString(bytes);
|
||||
}
|
||||
|
||||
return "DB_Server [no-ip-set]";
|
||||
}
|
||||
}
|
33
Dorkbox-Util/src/dorkbox/util/database/DatabaseStorage.java
Normal file
33
Dorkbox-Util/src/dorkbox/util/database/DatabaseStorage.java
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2014 dorkbox, llc
|
||||
*
|
||||
* 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 dorkbox.util.database;
|
||||
|
||||
import dorkbox.util.bytes.ByteArrayWrapper;
|
||||
|
||||
/**
|
||||
* A list of all of the keys used by the storage database
|
||||
*/
|
||||
public
|
||||
class DatabaseStorage {
|
||||
public static final ByteArrayWrapper SERVERS = ByteArrayWrapper.wrap("servers");
|
||||
public static final ByteArrayWrapper ROOT = ByteArrayWrapper.wrap("root");
|
||||
public static final ByteArrayWrapper USERS = ByteArrayWrapper.wrap("users");
|
||||
public static final ByteArrayWrapper ADMIN_HASH = ByteArrayWrapper.wrap("adminHash");
|
||||
public static final ByteArrayWrapper FILES = ByteArrayWrapper.wrap("files");
|
||||
public static final ByteArrayWrapper GENERIC = ByteArrayWrapper.wrap("generic");
|
||||
|
||||
|
||||
}
|
@ -25,17 +25,21 @@ import java.util.Properties;
|
||||
|
||||
import dorkbox.util.FileUtil;
|
||||
|
||||
public class PropertiesProvider {
|
||||
@SuppressWarnings("unused")
|
||||
public
|
||||
class PropertiesProvider {
|
||||
|
||||
private String comments = "Settings and configuration file. Strings must be escape formatted!";
|
||||
private final Properties properties = new SortedProperties();
|
||||
private final File propertiesFile;
|
||||
|
||||
public PropertiesProvider(String propertiesFile) {
|
||||
public
|
||||
PropertiesProvider(String propertiesFile) {
|
||||
this(new File(propertiesFile));
|
||||
}
|
||||
|
||||
public PropertiesProvider(File propertiesFile) {
|
||||
public
|
||||
PropertiesProvider(File propertiesFile) {
|
||||
if (propertiesFile == null) {
|
||||
throw new NullPointerException("propertiesFile");
|
||||
}
|
||||
@ -43,8 +47,10 @@ public class PropertiesProvider {
|
||||
propertiesFile = FileUtil.normalize(propertiesFile);
|
||||
// make sure the parent dir exists...
|
||||
File parentFile = propertiesFile.getParentFile();
|
||||
if (parentFile != null) {
|
||||
parentFile.mkdirs();
|
||||
if (parentFile != null && !parentFile.exists()) {
|
||||
if (!parentFile.mkdirs()) {
|
||||
throw new RuntimeException("Unable to create directories for: " + propertiesFile);
|
||||
}
|
||||
}
|
||||
|
||||
this.propertiesFile = propertiesFile;
|
||||
@ -52,11 +58,13 @@ public class PropertiesProvider {
|
||||
_load();
|
||||
}
|
||||
|
||||
public void setComments(String comments) {
|
||||
public
|
||||
void setComments(String comments) {
|
||||
this.comments = comments;
|
||||
}
|
||||
|
||||
private final void _load() {
|
||||
private
|
||||
void _load() {
|
||||
if (!this.propertiesFile.canRead() || !this.propertiesFile.exists()) {
|
||||
// in this case, our properties file doesn't exist yet... create one!
|
||||
_save();
|
||||
@ -77,7 +85,8 @@ public class PropertiesProvider {
|
||||
}
|
||||
|
||||
|
||||
private final void _save() {
|
||||
private
|
||||
void _save() {
|
||||
try {
|
||||
FileOutputStream fos = new FileOutputStream(this.propertiesFile);
|
||||
this.properties.store(fos, this.comments);
|
||||
@ -95,18 +104,21 @@ public class PropertiesProvider {
|
||||
}
|
||||
|
||||
|
||||
public synchronized final void remove(final String key) {
|
||||
public final synchronized
|
||||
void remove(final String key) {
|
||||
this.properties.remove(key);
|
||||
_save();
|
||||
}
|
||||
|
||||
public synchronized final void save(final String key, Object value) {
|
||||
@SuppressWarnings("AutoBoxing")
|
||||
public final synchronized
|
||||
void save(final String key, Object value) {
|
||||
if (key == null || value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Color) {
|
||||
value = ((Color)value).getRGB();
|
||||
value = ((Color) value).getRGB();
|
||||
}
|
||||
|
||||
this.properties.setProperty(key, value.toString());
|
||||
@ -114,8 +126,9 @@ public class PropertiesProvider {
|
||||
_save();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public synchronized <T> T get(String key, Class<T> clazz) {
|
||||
@SuppressWarnings({"unchecked", "AutoUnboxing"})
|
||||
public synchronized
|
||||
<T> T get(String key, Class<T> clazz) {
|
||||
if (key == null || clazz == null) {
|
||||
return null;
|
||||
}
|
||||
@ -146,7 +159,8 @@ public class PropertiesProvider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
public
|
||||
String toString() {
|
||||
return "PropertiesProvider [" + this.propertiesFile + "]";
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public
|
||||
class DiskStorage implements DiskStorageIfface {
|
||||
class DiskStorage implements Storage {
|
||||
private final DelayTimer timer;
|
||||
private final ByteArrayWrapper defaultKey;
|
||||
private final StorageBase storage;
|
||||
@ -51,10 +51,14 @@ class DiskStorage implements DiskStorageIfface {
|
||||
* Creates or opens a new database file.
|
||||
*/
|
||||
protected
|
||||
DiskStorage(File storageFile, SerializationManager serializationManager) throws IOException {
|
||||
DiskStorage(File storageFile, SerializationManager serializationManager, final boolean readOnly) throws IOException {
|
||||
this.storage = new StorageBase(storageFile, serializationManager);
|
||||
this.defaultKey = ByteArrayWrapper.wrap("");
|
||||
|
||||
if (readOnly) {
|
||||
this.timer = null;
|
||||
}
|
||||
else {
|
||||
this.timer = new DelayTimer("Storage Writer", false, new DelayTimer.Callback() {
|
||||
@Override
|
||||
public
|
||||
@ -75,6 +79,7 @@ class DiskStorage implements DiskStorageIfface {
|
||||
DiskStorage.this.storage.doActionThings(actions);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.isOpen.set(true);
|
||||
}
|
||||
@ -95,7 +100,9 @@ class DiskStorage implements DiskStorageIfface {
|
||||
|
||||
// flush actions
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
if (timer != null) {
|
||||
this.timer.delay(0L);
|
||||
}
|
||||
|
||||
return this.storage.size();
|
||||
}
|
||||
@ -281,11 +288,13 @@ class DiskStorage implements DiskStorageIfface {
|
||||
throw new RuntimeException("Unable to act on closed storage");
|
||||
}
|
||||
|
||||
if (timer != null) {
|
||||
action(key, object);
|
||||
|
||||
// timer action runs on TIMER thread, not this thread
|
||||
this.timer.delay(this.milliSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given object to the storage using a default (blank) key, OR -- if it has been registered, using it's registered key
|
||||
@ -300,11 +309,13 @@ class DiskStorage implements DiskStorageIfface {
|
||||
throw new RuntimeException("Unable to act on closed storage");
|
||||
}
|
||||
|
||||
if (timer != null) {
|
||||
action(this.defaultKey, object);
|
||||
|
||||
// timer action runs on TIMER thread, not this thread
|
||||
this.timer.delay(this.milliSeconds);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an object from storage. To ALSO remove from the cache, use unRegister(key)
|
||||
@ -321,23 +332,31 @@ class DiskStorage implements DiskStorageIfface {
|
||||
ByteArrayWrapper wrap = ByteArrayWrapper.wrap(key);
|
||||
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
if (timer != null) {
|
||||
this.timer.delay(0L);
|
||||
|
||||
return this.storage.delete(wrap);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the database and file.
|
||||
*/
|
||||
void close() {
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
if (timer != null) {
|
||||
this.timer.delay(0L);
|
||||
}
|
||||
|
||||
// have to "close" it after we run the timer!
|
||||
this.isOpen.set(false);
|
||||
|
||||
if (timer != null) {
|
||||
this.storage.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the file that backs this storage
|
||||
@ -357,7 +376,9 @@ class DiskStorage implements DiskStorageIfface {
|
||||
public final
|
||||
long getFileSize() {
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
if (timer != null) {
|
||||
this.timer.delay(0L);
|
||||
}
|
||||
|
||||
return this.storage.getFileSize();
|
||||
}
|
||||
@ -372,8 +393,13 @@ class DiskStorage implements DiskStorageIfface {
|
||||
throw new RuntimeException("Unable to act on closed storage");
|
||||
}
|
||||
|
||||
if (timer != null) {
|
||||
return this.timer.isWaiting();
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the delay in milliseconds this will wait after the last action to flush the data to the disk
|
||||
@ -457,8 +483,10 @@ class DiskStorage implements DiskStorageIfface {
|
||||
}
|
||||
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
if (timer != null) {
|
||||
this.timer.delay(0L);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the storage to disk, immediately.
|
||||
@ -472,11 +500,12 @@ class DiskStorage implements DiskStorageIfface {
|
||||
throw new RuntimeException("Unable to act on closed storage");
|
||||
}
|
||||
|
||||
action(ByteArrayWrapper.wrap(key), object);
|
||||
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
if (timer != null) {
|
||||
action(ByteArrayWrapper.wrap(key), object);
|
||||
this.timer.delay(0L);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the storage to disk, immediately.
|
||||
@ -490,12 +519,15 @@ class DiskStorage implements DiskStorageIfface {
|
||||
throw new RuntimeException("Unable to act on closed storage");
|
||||
}
|
||||
|
||||
if (timer != null) {
|
||||
action(ByteArrayWrapper.wrap(key), object);
|
||||
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
this.timer.delay(0L);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the storage to disk, immediately.
|
||||
* <p/>
|
||||
@ -508,9 +540,11 @@ class DiskStorage implements DiskStorageIfface {
|
||||
throw new RuntimeException("Unable to act on closed storage");
|
||||
}
|
||||
|
||||
if (timer != null) {
|
||||
action(key, object);
|
||||
|
||||
// timer action runs on THIS thread, not timer thread
|
||||
this.timer.delay(0L);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,14 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
*
|
||||
*/
|
||||
public
|
||||
class MemoryStorage implements DiskStorageIfface {
|
||||
class MemoryStorage implements Storage {
|
||||
private final ConcurrentHashMap<ByteArrayWrapper, Object> storage;
|
||||
private final ByteArrayWrapper defaultKey;
|
||||
private int version;
|
||||
|
||||
private
|
||||
MemoryStorage() throws IOException {
|
||||
|
||||
public
|
||||
MemoryStorage() {
|
||||
this.storage = new ConcurrentHashMap<ByteArrayWrapper, Object>();
|
||||
this.defaultKey = ByteArrayWrapper.wrap("");
|
||||
}
|
||||
@ -122,6 +123,7 @@ class MemoryStorage implements DiskStorageIfface {
|
||||
final Object o = storage.get(key);
|
||||
if (o == null) {
|
||||
storage.put(key, data);
|
||||
return data;
|
||||
}
|
||||
return (T) o;
|
||||
}
|
||||
|
@ -263,7 +263,7 @@ class Metadata {
|
||||
<T> T readData(SerializationManager serializationManager, InflaterInputStream inputStream) {
|
||||
Input input = new Input(inputStream, 1024); // read 1024 at a time
|
||||
@SuppressWarnings("unchecked")
|
||||
T readObject = (T) serializationManager.readClassAndObject(input);
|
||||
T readObject = (T) serializationManager.readFullClassAndObject(input);
|
||||
return readObject;
|
||||
}
|
||||
|
||||
@ -277,7 +277,7 @@ class Metadata {
|
||||
final DeflaterOutputStream outputStream) throws IOException {
|
||||
// HAVE TO LOCK BEFORE THIS IS CALLED! (AND FREE AFTERWARDS!)
|
||||
Output output = new Output(outputStream, 1024); // write 1024 at a time
|
||||
serializationManager.writeClassAndObject(output, data);
|
||||
serializationManager.writeFullClassAndObject(output, data);
|
||||
output.flush();
|
||||
|
||||
outputStream.flush(); // sync-flush is enabled, so the output stream will finish compressing data.
|
||||
|
@ -9,7 +9,7 @@ import java.io.IOException;
|
||||
*
|
||||
*/
|
||||
public
|
||||
interface DiskStorageIfface {
|
||||
interface Storage {
|
||||
/**
|
||||
* Returns the number of objects in the database.
|
||||
*/
|
@ -449,7 +449,7 @@ class StorageBase {
|
||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||
OutputStream outputStream = new DeflaterOutputStream(byteArrayOutputStream, deflater);
|
||||
Output output = new Output(outputStream, 1024); // write 1024 at a time
|
||||
kryo.writeClassAndObject(output, data);
|
||||
kryo.writeFullClassAndObject(output, data);
|
||||
output.flush();
|
||||
|
||||
outputStream.flush();
|
||||
|
@ -1,20 +1,22 @@
|
||||
package dorkbox.util.storage;
|
||||
|
||||
import dorkbox.util.SerializationManager;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import dorkbox.util.SerializationManager;
|
||||
|
||||
public
|
||||
class MakeStorage {
|
||||
class Store {
|
||||
private static final Logger logger = LoggerFactory.getLogger(DiskStorage.class);
|
||||
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
private static final Map<File, DiskStorageIfface> storages = new HashMap<File, DiskStorageIfface>(1);
|
||||
private static final Map<File, Storage> storages = new HashMap<File, Storage>(1);
|
||||
|
||||
public static
|
||||
DiskMaker Disk() {
|
||||
@ -32,7 +34,7 @@ class MakeStorage {
|
||||
public static
|
||||
void close(File file) {
|
||||
synchronized (storages) {
|
||||
DiskStorageIfface storage = storages.get(file);
|
||||
Storage storage = storages.get(file);
|
||||
if (storage != null) {
|
||||
if (storage instanceof DiskStorage) {
|
||||
final DiskStorage diskStorage = (DiskStorage) storage;
|
||||
@ -50,11 +52,10 @@ class MakeStorage {
|
||||
* Closes the storage.
|
||||
*/
|
||||
public static
|
||||
void close(DiskStorageIfface _storage) {
|
||||
void close(Storage _storage) {
|
||||
synchronized (storages) {
|
||||
File file = _storage.getFile();
|
||||
DiskStorageIfface storage = storages.get(file);
|
||||
if (storage != null) {
|
||||
Storage storage = storages.get(file);
|
||||
if (storage instanceof DiskStorage) {
|
||||
final DiskStorage diskStorage = (DiskStorage) storage;
|
||||
boolean isLastOne = diskStorage.decrementReference();
|
||||
@ -65,13 +66,12 @@ class MakeStorage {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static
|
||||
void shutdown() {
|
||||
synchronized (storages) {
|
||||
Collection<DiskStorageIfface> values = storages.values();
|
||||
for (DiskStorageIfface storage : values) {
|
||||
Collection<Storage> values = storages.values();
|
||||
for (Storage storage : values) {
|
||||
if (storage instanceof DiskStorage) {
|
||||
//noinspection StatementWithEmptyBody
|
||||
final DiskStorage diskStorage = (DiskStorage) storage;
|
||||
@ -87,7 +87,7 @@ class MakeStorage {
|
||||
public static
|
||||
void delete(File file) {
|
||||
synchronized (storages) {
|
||||
DiskStorageIfface remove = storages.remove(file);
|
||||
Storage remove = storages.remove(file);
|
||||
if (remove != null && remove instanceof DiskStorage) {
|
||||
((DiskStorage) remove).close();
|
||||
}
|
||||
@ -97,7 +97,7 @@ class MakeStorage {
|
||||
}
|
||||
|
||||
public static
|
||||
void delete(DiskStorageIfface storage) {
|
||||
void delete(Storage storage) {
|
||||
File file = storage.getFile();
|
||||
delete(file);
|
||||
}
|
||||
@ -107,6 +107,7 @@ class MakeStorage {
|
||||
class DiskMaker {
|
||||
private File file;
|
||||
private SerializationManager serializationManager;
|
||||
private boolean readOnly;
|
||||
|
||||
public
|
||||
DiskMaker file(File file) {
|
||||
@ -121,15 +122,15 @@ class MakeStorage {
|
||||
}
|
||||
|
||||
public
|
||||
DiskStorageIfface make() {
|
||||
if (file == null) {
|
||||
Storage make() {
|
||||
if (this.file == null) {
|
||||
throw new IllegalArgumentException("file cannot be null!");
|
||||
}
|
||||
|
||||
// if we load from a NEW storage at the same location as an ALREADY EXISTING storage,
|
||||
// without saving the existing storage first --- whoops!
|
||||
synchronized (storages) {
|
||||
DiskStorageIfface storage = storages.get(file);
|
||||
Storage storage = storages.get(this.file);
|
||||
|
||||
if (storage != null) {
|
||||
if (storage instanceof DiskStorage) {
|
||||
@ -141,13 +142,13 @@ class MakeStorage {
|
||||
((DiskStorage) storage).increaseReference();
|
||||
}
|
||||
else {
|
||||
throw new RuntimeException("Unable to change storage types for: " + file);
|
||||
throw new RuntimeException("Unable to change storage types for: " + this.file);
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
storage = new DiskStorage(file, serializationManager);
|
||||
storages.put(file, storage);
|
||||
storage = new DiskStorage(this.file, this.serializationManager, this.readOnly);
|
||||
storages.put(this.file, storage);
|
||||
} catch (IOException e) {
|
||||
logger.error("Unable to open storage", e);
|
||||
}
|
||||
@ -156,21 +157,20 @@ class MakeStorage {
|
||||
return storage;
|
||||
}
|
||||
}
|
||||
|
||||
public
|
||||
DiskMaker readOnly() {
|
||||
this.readOnly = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static
|
||||
class MemoryMaker {
|
||||
private SerializationManager serializationManager;
|
||||
|
||||
public
|
||||
MemoryMaker serializer(SerializationManager serializationManager) {
|
||||
this.serializationManager = serializationManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
MemoryStorage make() {
|
||||
return null;
|
||||
MemoryStorage make() throws IOException {
|
||||
return new MemoryStorage();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,11 @@
|
||||
package dorkbox.util;
|
||||
|
||||
import com.esotericsoftware.kryo.Kryo;
|
||||
import com.esotericsoftware.kryo.Registration;
|
||||
import com.esotericsoftware.kryo.Serializer;
|
||||
import com.esotericsoftware.kryo.io.Input;
|
||||
import com.esotericsoftware.kryo.io.Output;
|
||||
import dorkbox.util.storage.DiskStorageIfface;
|
||||
import dorkbox.util.storage.MakeStorage;
|
||||
import dorkbox.util.storage.Storage;
|
||||
import dorkbox.util.storage.Store;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.junit.*;
|
||||
import org.junit.runners.MethodSorters;
|
||||
@ -23,19 +22,6 @@ class StorageTest {
|
||||
private static final SerializationManager manager = new SerializationManager() {
|
||||
Kryo kryo = new Kryo();
|
||||
|
||||
@Override
|
||||
public
|
||||
boolean setReferences(final boolean references) {
|
||||
kryo.setReferences(references);
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void setRegistrationRequired(final boolean registrationRequired) {
|
||||
kryo.setRegistrationRequired(registrationRequired);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void register(final Class<?> clazz) {
|
||||
@ -50,16 +36,15 @@ class StorageTest {
|
||||
|
||||
@Override
|
||||
public
|
||||
Registration register(final Class<?> type, final Serializer<?> serializer, final int id) {
|
||||
void register(final Class<?> type, final Serializer<?> serializer, final int id) {
|
||||
kryo.register(type, serializer, id);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void write(final ByteBuf buffer, final Object message) {
|
||||
final Output output = new Output();
|
||||
writeClassAndObject(output, message);
|
||||
writeFullClassAndObject(output, message);
|
||||
buffer.writeBytes(output.getBuffer());
|
||||
}
|
||||
|
||||
@ -69,7 +54,7 @@ class StorageTest {
|
||||
final Input input = new Input();
|
||||
buffer.readBytes(input.getBuffer());
|
||||
|
||||
final Object o = readClassAndObject(input);
|
||||
final Object o = readFullClassAndObject(input);
|
||||
buffer.skipBytes(input.position());
|
||||
|
||||
return o;
|
||||
@ -77,15 +62,26 @@ class StorageTest {
|
||||
|
||||
@Override
|
||||
public
|
||||
void writeClassAndObject(final Output output, final Object value) {
|
||||
void writeFullClassAndObject(final Output output, final Object value) {
|
||||
kryo.writeClassAndObject(output, value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
Object readClassAndObject(final Input input) {
|
||||
Object readFullClassAndObject(final Input input) {
|
||||
return kryo.readClassAndObject(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
Kryo take() throws InterruptedException {
|
||||
return kryo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void release(final Kryo kryo) {
|
||||
}
|
||||
};
|
||||
|
||||
static
|
||||
@ -96,20 +92,20 @@ class StorageTest {
|
||||
@Before
|
||||
public
|
||||
void deleteDB() {
|
||||
MakeStorage.delete(TEST_DB);
|
||||
Store.delete(TEST_DB);
|
||||
}
|
||||
|
||||
@After
|
||||
public
|
||||
void delete2DB() {
|
||||
MakeStorage.delete(TEST_DB);
|
||||
Store.delete(TEST_DB);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public
|
||||
void testCreateDB() throws IOException {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -120,9 +116,9 @@ class StorageTest {
|
||||
Assert.assertEquals("count is not correct", numberOfRecords1, 0);
|
||||
Assert.assertEquals("size is not correct", size1, 208L); // NOTE this will change based on the data size added!
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -132,7 +128,7 @@ class StorageTest {
|
||||
Assert.assertEquals("Record count is not the same", numberOfRecords1, numberOfRecords2);
|
||||
Assert.assertEquals("size is not the same", size1, size2);
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
}
|
||||
|
||||
|
||||
@ -142,7 +138,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -150,8 +146,8 @@ class StorageTest {
|
||||
add(storage, i);
|
||||
}
|
||||
|
||||
MakeStorage.close(storage);
|
||||
storage = MakeStorage.Disk()
|
||||
Store.close(storage);
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -162,7 +158,7 @@ class StorageTest {
|
||||
Assert.assertEquals("Object is not the same", record1Data, readRecord);
|
||||
}
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Error!");
|
||||
@ -175,7 +171,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -189,9 +185,9 @@ class StorageTest {
|
||||
|
||||
Assert.assertEquals("Object is not the same", addRecord, readData);
|
||||
}
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -208,7 +204,7 @@ class StorageTest {
|
||||
Assert.assertEquals("count is not correct", numberOfRecords1, 1);
|
||||
Assert.assertEquals("size is not correct", size1, 235L); // NOTE this will change based on the data size added!
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Error!");
|
||||
@ -221,7 +217,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -241,9 +237,9 @@ class StorageTest {
|
||||
Assert.assertEquals("Object is not the same", record1Data, readRecord);
|
||||
}
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -254,7 +250,7 @@ class StorageTest {
|
||||
Assert.assertEquals("Object is not the same", dataCheck, readRecord);
|
||||
}
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Error!");
|
||||
@ -267,7 +263,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -282,9 +278,9 @@ class StorageTest {
|
||||
Assert.assertEquals("Object is not the same", record1Data, readRecord);
|
||||
}
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -295,7 +291,7 @@ class StorageTest {
|
||||
Assert.assertEquals("Object is not the same", dataCheck, readRecord);
|
||||
}
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Error!");
|
||||
@ -308,7 +304,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -318,9 +314,9 @@ class StorageTest {
|
||||
|
||||
Assert.assertEquals("Object is not the same", addRecord, readRecord);
|
||||
}
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -342,8 +338,8 @@ class StorageTest {
|
||||
storage.load(createKey, data2);
|
||||
Assert.assertEquals("Object is not the same", data, data2);
|
||||
|
||||
MakeStorage.close(storage);
|
||||
storage = MakeStorage.Disk()
|
||||
Store.close(storage);
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -352,7 +348,7 @@ class StorageTest {
|
||||
storage.load(createKey, data2);
|
||||
Assert.assertEquals("Object is not the same", data, data2);
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Error!");
|
||||
@ -366,7 +362,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -376,9 +372,9 @@ class StorageTest {
|
||||
|
||||
Assert.assertEquals("Object is not the same", addRecord, readRecord);
|
||||
}
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -408,9 +404,9 @@ class StorageTest {
|
||||
|
||||
Assert.assertEquals("Object is not the same", dataCheck, addRecord);
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -437,7 +433,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -447,9 +443,9 @@ class StorageTest {
|
||||
|
||||
Assert.assertEquals("Object is not the same", addRecord, readRecord);
|
||||
}
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -458,8 +454,8 @@ class StorageTest {
|
||||
String readRecord = readRecord(storage, 3);
|
||||
Assert.assertEquals("Object is not the same", updateRecord, readRecord);
|
||||
|
||||
MakeStorage.close(storage);
|
||||
storage = MakeStorage.Disk()
|
||||
Store.close(storage);
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -469,8 +465,8 @@ class StorageTest {
|
||||
|
||||
updateRecord = updateRecord(storage, 3, createData(3));
|
||||
|
||||
MakeStorage.close(storage);
|
||||
storage = MakeStorage.Disk()
|
||||
Store.close(storage);
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -478,8 +474,8 @@ class StorageTest {
|
||||
readRecord = readRecord(storage, 3);
|
||||
Assert.assertEquals("Object is not the same", updateRecord, readRecord);
|
||||
|
||||
MakeStorage.close(storage);
|
||||
storage = MakeStorage.Disk()
|
||||
Store.close(storage);
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -488,7 +484,7 @@ class StorageTest {
|
||||
readRecord = readRecord(storage, 0);
|
||||
Assert.assertEquals("Object is not the same", updateRecord, readRecord);
|
||||
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Error!");
|
||||
@ -502,7 +498,7 @@ class StorageTest {
|
||||
int total = 100;
|
||||
|
||||
try {
|
||||
DiskStorageIfface storage = MakeStorage.Disk()
|
||||
Storage storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -513,12 +509,12 @@ class StorageTest {
|
||||
|
||||
storage.put(createKey, data);
|
||||
}
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
|
||||
Data data = new Data();
|
||||
makeData(data);
|
||||
|
||||
storage = MakeStorage.Disk()
|
||||
storage = Store.Disk()
|
||||
.file(TEST_DB)
|
||||
.serializer(manager)
|
||||
.make();
|
||||
@ -529,7 +525,7 @@ class StorageTest {
|
||||
storage.load(createKey, data2);
|
||||
Assert.assertEquals("Object is not the same", data, data2);
|
||||
}
|
||||
MakeStorage.close(storage);
|
||||
Store.close(storage);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Assert.fail("Error!");
|
||||
@ -544,7 +540,7 @@ class StorageTest {
|
||||
}
|
||||
|
||||
public static
|
||||
String add(DiskStorageIfface storage, int number) throws IOException {
|
||||
String add(Storage storage, int number) throws IOException {
|
||||
String record1Data = createData(number);
|
||||
String record1Key = createKey(number);
|
||||
|
||||
@ -554,7 +550,7 @@ class StorageTest {
|
||||
}
|
||||
|
||||
public static
|
||||
String readRecord(DiskStorageIfface storage, int number) throws ClassNotFoundException, IOException {
|
||||
String readRecord(Storage storage, int number) throws ClassNotFoundException, IOException {
|
||||
String record1Key = createKey(number);
|
||||
|
||||
log("reading record " + number + "...");
|
||||
@ -565,7 +561,7 @@ class StorageTest {
|
||||
}
|
||||
|
||||
public static
|
||||
void deleteRecord(DiskStorageIfface storage, int nNumber) throws ClassNotFoundException, IOException {
|
||||
void deleteRecord(Storage storage, int nNumber) throws ClassNotFoundException, IOException {
|
||||
String record1Key = createKey(nNumber);
|
||||
|
||||
log("deleting record " + nNumber + "...");
|
||||
@ -573,7 +569,7 @@ class StorageTest {
|
||||
}
|
||||
|
||||
private static
|
||||
String updateRecord(DiskStorageIfface storage, int number, String newData) throws IOException {
|
||||
String updateRecord(Storage storage, int number, String newData) throws IOException {
|
||||
String record1Key = createKey(number);
|
||||
|
||||
log("updating record " + number + "...");
|
||||
|
@ -35,20 +35,13 @@
|
||||
*/
|
||||
package dorkbox.util;
|
||||
|
||||
import static dorkbox.util.bytes.Unsigned.ubyte;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import dorkbox.util.bytes.UByte;
|
||||
import org.junit.Test;
|
||||
|
||||
import dorkbox.util.bytes.UByte;
|
||||
import java.io.*;
|
||||
|
||||
import static dorkbox.util.bytes.Unsigned.ubyte;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class UByteTest {
|
||||
|
||||
|
@ -1,26 +1,26 @@
|
||||
/**
|
||||
* Copyright (c) 2011-2013, Lukas Eder, lukas.eder@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* <p/>
|
||||
* This software is licensed to you under the Apache License, Version 2.0
|
||||
* (the "License"); You may obtain a copy of the License at
|
||||
*
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* <p/>
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* <p/>
|
||||
* . Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* <p/>
|
||||
* . Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* <p/>
|
||||
* . Neither the name "jOOU" nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* <p/>
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@ -35,39 +35,33 @@
|
||||
*/
|
||||
package dorkbox.util;
|
||||
|
||||
import static dorkbox.util.bytes.Unsigned.uint;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
import static junit.framework.Assert.fail;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
|
||||
import dorkbox.util.bytes.UInteger;
|
||||
import org.junit.Test;
|
||||
|
||||
import dorkbox.util.bytes.UInteger;
|
||||
import java.io.*;
|
||||
|
||||
public class UIntegerTest {
|
||||
private static final int CACHE_SIZE=256;
|
||||
private static final int NEAR_MISS_OFFSET=4;
|
||||
import static dorkbox.util.bytes.Unsigned.uint;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public
|
||||
class UIntegerTest {
|
||||
private static final int CACHE_SIZE = 256;
|
||||
private static final int NEAR_MISS_OFFSET = 4;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testValueOfLong() {
|
||||
for(long l=01; l<=UInteger.MAX_VALUE; l<<=1) {
|
||||
assertEquals(l , uint(l).longValue());
|
||||
public
|
||||
void testValueOfLong() {
|
||||
for (long l = 01; l <= UInteger.MAX_VALUE; l <<= 1) {
|
||||
assertEquals(l, uint(l).longValue());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testValueOfLongCachingShift() {
|
||||
for(long l=01; l<CACHE_SIZE; l<<=1)
|
||||
{
|
||||
public
|
||||
void testValueOfLongCachingShift() {
|
||||
for (long l = 01; l < CACHE_SIZE; l <<= 1) {
|
||||
UInteger a = uint(l);
|
||||
UInteger b = uint(l);
|
||||
assertTrue(a == b);
|
||||
@ -76,9 +70,9 @@ public class UIntegerTest {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testValueOfLongCachingNear() {
|
||||
for(long l=CACHE_SIZE-NEAR_MISS_OFFSET; l<CACHE_SIZE; l++)
|
||||
{
|
||||
public
|
||||
void testValueOfLongCachingNear() {
|
||||
for (long l = CACHE_SIZE - NEAR_MISS_OFFSET; l < CACHE_SIZE; l++) {
|
||||
UInteger a = uint(l);
|
||||
UInteger b = uint(l);
|
||||
assertTrue(a == b);
|
||||
@ -87,9 +81,9 @@ public class UIntegerTest {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testValueOfLongNoCachingShift() {
|
||||
for(long l=CACHE_SIZE; l<=CACHE_SIZE; l<<=1)
|
||||
{
|
||||
public
|
||||
void testValueOfLongNoCachingShift() {
|
||||
for (long l = CACHE_SIZE; l <= CACHE_SIZE; l <<= 1) {
|
||||
UInteger a = uint(l);
|
||||
UInteger b = uint(l);
|
||||
assertFalse(a == b);
|
||||
@ -98,9 +92,9 @@ public class UIntegerTest {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testValueOfLongNoCachingNear() {
|
||||
for(long l=CACHE_SIZE; l<=CACHE_SIZE+NEAR_MISS_OFFSET; l++)
|
||||
{
|
||||
public
|
||||
void testValueOfLongNoCachingNear() {
|
||||
for (long l = CACHE_SIZE; l <= CACHE_SIZE + NEAR_MISS_OFFSET; l++) {
|
||||
UInteger a = uint(l);
|
||||
UInteger b = uint(l);
|
||||
assertFalse(a == b);
|
||||
@ -109,22 +103,24 @@ public class UIntegerTest {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testValueOfLongInvalid() {
|
||||
public
|
||||
void testValueOfLongInvalid() {
|
||||
try {
|
||||
uint(UInteger.MIN_VALUE - 1);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
catch (NumberFormatException e) {}
|
||||
try {
|
||||
uint(UInteger.MAX_VALUE + 1);
|
||||
fail();
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
catch (NumberFormatException e) {}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testSerializeDeserialize() throws ClassNotFoundException, IOException {
|
||||
public
|
||||
void testSerializeDeserialize() throws ClassNotFoundException, IOException {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
ByteArrayInputStream bais;
|
||||
|
@ -35,28 +35,20 @@
|
||||
*/
|
||||
package dorkbox.util;
|
||||
|
||||
import static dorkbox.util.bytes.ULong.MAX_VALUE_LONG;
|
||||
import static dorkbox.util.bytes.Unsigned.ubyte;
|
||||
import static dorkbox.util.bytes.Unsigned.uint;
|
||||
import static dorkbox.util.bytes.Unsigned.ulong;
|
||||
import static dorkbox.util.bytes.Unsigned.ushort;
|
||||
import static java.math.BigInteger.ONE;
|
||||
import static java.util.Arrays.asList;
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
import static junit.framework.Assert.assertFalse;
|
||||
import dorkbox.util.bytes.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import dorkbox.util.bytes.UByte;
|
||||
import dorkbox.util.bytes.UInteger;
|
||||
import dorkbox.util.bytes.ULong;
|
||||
import dorkbox.util.bytes.UNumber;
|
||||
import dorkbox.util.bytes.UShort;
|
||||
import static dorkbox.util.bytes.ULong.MAX_VALUE_LONG;
|
||||
import static dorkbox.util.bytes.Unsigned.*;
|
||||
import static java.math.BigInteger.ONE;
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
|
||||
/**
|
||||
* @author Lukas Eder
|
||||
|
Loading…
Reference in New Issue
Block a user