mirror of
https://github.com/2006-Scape/apollo.git
synced 2026-07-05 16:49:04 +00:00
Modularise! Also add some unit tests.
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A utility class which contains {@link ByteBuffer}-related utility methods.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class BufferUtil {
|
||||
|
||||
/**
|
||||
* Reads a 'smart' (either a {@code byte} or {@code short} depending on the value) from the specified buffer.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
* @return The 'smart'.
|
||||
*/
|
||||
public static int readSmart(ByteBuffer buffer) {
|
||||
// Reads a single byte from the buffer without modifying the current position.
|
||||
int peek = buffer.get(buffer.position()) & 0xFF;
|
||||
int value = peek > Byte.MAX_VALUE ? (buffer.getShort() & 0xFFFF) + Short.MIN_VALUE : buffer.get() & 0xFF;
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string from the specified {@link ByteBuffer}.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
public static String readString(ByteBuffer buffer) {
|
||||
StringBuilder bldr = new StringBuilder();
|
||||
char character;
|
||||
while ((character = (char) buffer.get()) != BufferUtil.STRING_TERMINATOR) {
|
||||
bldr.append(character);
|
||||
}
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a string from the specified {@link ByteBuf}.
|
||||
*
|
||||
* @param buffer The buffer.
|
||||
* @return The string.
|
||||
*/
|
||||
public static String readString(ByteBuf buffer) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
int character;
|
||||
while (buffer.isReadable() && (character = buffer.readUnsignedByte()) != BufferUtil.STRING_TERMINATOR) {
|
||||
builder.append((char) character);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a 24-bit medium integer from the specified {@link ByteBuffer}s current position and increases the buffers
|
||||
* position by 3.
|
||||
*
|
||||
* @param buffer The {@link ByteBuffer} to read from.
|
||||
* @return The read 24-bit medium integer.
|
||||
*/
|
||||
public static int readUnsignedMedium(ByteBuffer buffer) {
|
||||
return (buffer.getShort() & 0xFFFF) << 8 | buffer.get() & 0xFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* The terminator of a string.
|
||||
*/
|
||||
public static final int STRING_TERMINATOR = 10;
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation.
|
||||
*/
|
||||
private BufferUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Queue;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* A utility class containing helper methods for various {@link Collection} objects.
|
||||
*
|
||||
* @author Ryley
|
||||
*/
|
||||
public final class CollectionUtil {
|
||||
|
||||
/**
|
||||
* Polls every element within the specified {@link Queue} and performs the specified {@link Consumer} event for each
|
||||
* element.
|
||||
*
|
||||
* @param queue The Queue to poll each element for, may not be {@code null}.
|
||||
* @param consumer The Consumer event to execute for each polled element, may not be {@code null}.
|
||||
*/
|
||||
public static <T> void pollAll(Queue<T> queue, Consumer<T> consumer) {
|
||||
Preconditions.checkNotNull(queue, "Queue may not be null");
|
||||
Preconditions.checkNotNull(consumer, "Consumer may not be null");
|
||||
|
||||
T element;
|
||||
while ((element = queue.poll()) != null) {
|
||||
consumer.accept(element);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppresses the default public constructor to discourage normal instantiation outside of this class.
|
||||
*/
|
||||
private CollectionUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream;
|
||||
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
|
||||
|
||||
/**
|
||||
* A utility class for performing compression/decompression.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class CompressionUtil {
|
||||
|
||||
/**
|
||||
* Bzip2s the specified array, removing the header.
|
||||
*
|
||||
* @param uncompressed The uncompressed array.
|
||||
* @return The compressed array.
|
||||
* @throws IOException If there is an error compressing the array.
|
||||
*/
|
||||
public static byte[] bzip2(byte[] uncompressed) throws IOException {
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
try (BZip2CompressorOutputStream os = new BZip2CompressorOutputStream(bout, 1)) {
|
||||
os.write(uncompressed);
|
||||
os.finish();
|
||||
|
||||
byte[] compressed = bout.toByteArray();
|
||||
byte[] newCompressed = new byte[compressed.length - 4]; // Strip the header
|
||||
System.arraycopy(compressed, 4, newCompressed, 0, newCompressed.length);
|
||||
return newCompressed;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gzips the specified array.
|
||||
*
|
||||
* @param uncompressed The uncompressed array.
|
||||
* @return The compressed array.
|
||||
* @throws IOException If there is an error compressing the array.
|
||||
*/
|
||||
public static byte[] gzip(byte[] uncompressed) throws IOException {
|
||||
ByteArrayOutputStream bout = new ByteArrayOutputStream();
|
||||
try (DeflaterOutputStream os = new GZIPOutputStream(bout)) {
|
||||
os.write(uncompressed);
|
||||
os.finish();
|
||||
return bout.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debzip2s the compressed array and places the result into the decompressed array.
|
||||
*
|
||||
* @param compressed The compressed array, <strong>without</strong> the header.
|
||||
* @param decompressed The decompressed array.
|
||||
* @throws IOException If there is an error decompressing the array.
|
||||
*/
|
||||
public static void debzip2(byte[] compressed, byte[] decompressed) throws IOException {
|
||||
byte[] newCompressed = new byte[compressed.length + 4];
|
||||
newCompressed[0] = 'B';
|
||||
newCompressed[1] = 'Z';
|
||||
newCompressed[2] = 'h';
|
||||
newCompressed[3] = '1';
|
||||
System.arraycopy(compressed, 0, newCompressed, 4, compressed.length);
|
||||
|
||||
try (DataInputStream is = new DataInputStream(new BZip2CompressorInputStream(new ByteArrayInputStream(newCompressed)))) {
|
||||
is.readFully(decompressed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Degzips the compressed array and places the results into the decompressed array.
|
||||
*
|
||||
* @param compressed The compressed array.
|
||||
* @param decompressed The decompressed array.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public static void degzip(byte[] compressed, byte[] decompressed) throws IOException {
|
||||
try (DataInputStream is = new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(compressed)))) {
|
||||
is.readFully(decompressed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Degzips the compressed {@link ByteBuffer} and returns the result as a byte array.
|
||||
*
|
||||
* @param compressed The compressed buffer.
|
||||
* @return The decompressed array.
|
||||
* @throws IOException If there is an error decompressing the buffer.
|
||||
*/
|
||||
public static byte[] degzip(ByteBuffer compressed) throws IOException {
|
||||
byte[] data = new byte[compressed.remaining()];
|
||||
compressed.get(data);
|
||||
|
||||
try (InputStream is = new GZIPInputStream(new ByteArrayInputStream(data)); ByteArrayOutputStream os = new ByteArrayOutputStream()) {
|
||||
while (true) {
|
||||
byte[] buf = new byte[1024];
|
||||
int read = is.read(buf, 0, buf.length);
|
||||
if (read == -1) {
|
||||
break;
|
||||
}
|
||||
os.write(buf, 0, read);
|
||||
}
|
||||
|
||||
return os.toByteArray();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation.
|
||||
*/
|
||||
private CompressionUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A utility class for wrapping old {@link Enumeration} objects inside an {@link Iterator} to allow for greater
|
||||
* compatibility.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class EnumerationUtil {
|
||||
|
||||
/**
|
||||
* Returns an {@link Iterator} which wraps around the specified {@link Enumeration}.
|
||||
*
|
||||
* @param enumeration The {@link Enumeration}.
|
||||
* @return An {@link Iterator}.
|
||||
*/
|
||||
public static <E> Iterator<E> asIterator(final Enumeration<E> enumeration) {
|
||||
return new Iterator<E>() {
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return enumeration.hasMoreElements();
|
||||
}
|
||||
|
||||
@Override
|
||||
public E next() {
|
||||
return enumeration.nextElement();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
throw new UnsupportedOperationException("Cannot remove an element using this wrapper.");
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation by other classes.
|
||||
*/
|
||||
private EnumerationUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package org.apollo.util;
|
||||
|
||||
/**
|
||||
* Contains language-related utility methods.
|
||||
*
|
||||
* @author Graham
|
||||
* @author Major
|
||||
*/
|
||||
public final class LanguageUtil {
|
||||
|
||||
/**
|
||||
* Gets the indefinite article of the specified String.
|
||||
*
|
||||
* @param string The String.
|
||||
* @return The indefinite article.
|
||||
*/
|
||||
public static String getIndefiniteArticle(String string) {
|
||||
char first = Character.toLowerCase(string.charAt(0));
|
||||
if (allUpperCase(string)) {
|
||||
if (first == 'f' || first == 'l' | first == 'm' || first == 'n' || first == 's') {
|
||||
return "an";
|
||||
}
|
||||
}
|
||||
|
||||
boolean vowel = first == 'a' || first == 'e' || first == 'i' || first == 'o' || first == 'u';
|
||||
return vowel ? "an" : "a";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the each letter in the specified String is upper case (i.e. digits etc are ignored).
|
||||
*
|
||||
* @param string The string.
|
||||
* @return {@code true} if no letters in the specified String are lower case, otherwise {@code false}.
|
||||
*/
|
||||
private static boolean allUpperCase(String string) {
|
||||
for (char character : string.toCharArray()) {
|
||||
if (Character.isLowerCase(character)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sole private constructor to prevent instantiation.
|
||||
*/
|
||||
private LanguageUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
/**
|
||||
* A class which contains name-related utility methods.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class NameUtil {
|
||||
|
||||
/**
|
||||
* An array of valid characters in a player name encoded as a long.
|
||||
*/
|
||||
private static final char[] NAME_CHARS = { '_', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
|
||||
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+', '=', ':', ';', '.', '>', '<', ',',
|
||||
'"', '[', ']', '|', '?', '/', '`' };
|
||||
|
||||
/**
|
||||
* Converts a long to a player name.
|
||||
*
|
||||
* @param l The long.
|
||||
* @return The player name.
|
||||
*/
|
||||
public static String decodeBase37(long l) {
|
||||
int i = 0;
|
||||
char[] chars = new char[12];
|
||||
while (l != 0L) {
|
||||
long tmp = l;
|
||||
l /= 37L;
|
||||
chars[11 - i++] = NAME_CHARS[(int) (tmp - l * 37L)];
|
||||
}
|
||||
return new String(chars, 12 - i, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a player name to a long.
|
||||
*
|
||||
* @param name The player name.
|
||||
* @return The long.
|
||||
*/
|
||||
public static long encodeBase37(String name) {
|
||||
Preconditions.checkArgument(name.length() <= 12, "Name too long.");
|
||||
|
||||
long l = 0;
|
||||
for (int index = 0; index < name.length(); index++) {
|
||||
char c = name.charAt(index);
|
||||
l *= 37;
|
||||
if (c >= 'A' && c <= 'Z') {
|
||||
l += 1 + c - 65;
|
||||
} else if (c >= 'a' && c <= 'z') {
|
||||
l += 1 + c - 97;
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
l += 27 + c - 48;
|
||||
}
|
||||
}
|
||||
|
||||
for (; l % 37L == 0L && l != 0L; l /= 37L) {
|
||||
;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation.
|
||||
*/
|
||||
private NameUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.apollo.util;
|
||||
|
||||
/**
|
||||
* Represents a point on a 2-dimensional Cartesian plane.
|
||||
*
|
||||
* @author Major
|
||||
*/
|
||||
public final class Point {
|
||||
|
||||
/**
|
||||
* The x coordinate.
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The y coordinate.
|
||||
*/
|
||||
private final int y;
|
||||
|
||||
/**
|
||||
* Creates a new point with the specified coordinates.
|
||||
*
|
||||
* @param x The x coordinate.
|
||||
* @param y The y coordinate.
|
||||
*/
|
||||
public Point(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the x coordinate of this point.
|
||||
*
|
||||
* @return The x coordinate.
|
||||
*/
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the y coordinate of this point.
|
||||
*
|
||||
* @return The y coordinate.
|
||||
*/
|
||||
public int getY() {
|
||||
return y;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A stateful implementation of a {@link ByteToMessageDecoder} which may be extended and used by other classes. The
|
||||
* current state is tracked by this class and is a user-specified enumeration.
|
||||
*
|
||||
* The state may be changed by calling the {@link StatefulFrameDecoder#setState} method.
|
||||
*
|
||||
* The current state is supplied as a parameter in the {@link StatefulFrameDecoder#decode} and
|
||||
* {@link StatefulFrameDecoder#decodeLast} methods.
|
||||
*
|
||||
* This class is not thread safe: it is recommended that the state is only set in the decode methods overridden.
|
||||
*
|
||||
* @author Graham
|
||||
* @param <T> The state enumeration.
|
||||
*/
|
||||
public abstract class StatefulFrameDecoder<T extends Enum<T>> extends ByteToMessageDecoder {
|
||||
|
||||
/**
|
||||
* The current state.
|
||||
*/
|
||||
private T state;
|
||||
|
||||
/**
|
||||
* Creates the stateful frame decoder with the specified initial state.
|
||||
*
|
||||
* @param state The initial state.
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public StatefulFrameDecoder(T state) {
|
||||
setState(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new state.
|
||||
*
|
||||
* @param state The new state.
|
||||
* @throws NullPointerException If the state is {@code null}.
|
||||
*/
|
||||
public final void setState(T state) {
|
||||
this.state = Objects.requireNonNull(state, "State cannot be null.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
decode(ctx, in, out, state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decodes the received packets into a frame.
|
||||
*
|
||||
* @param ctx The current context of this handler.
|
||||
* @param in The cumulative buffer, which may contain zero or more bytes.
|
||||
* @param out The {@link List} of objects to pass forward through the pipeline.
|
||||
* @param state The current state. The state may be changed by calling {@link #setState}.
|
||||
* @throws Exception If there is an exception when decoding a frame.
|
||||
*/
|
||||
protected abstract void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out, T state) throws Exception;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* A class which contains {@link InputStream}- and {@link OutputStream}-related utility methods.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class StreamUtil {
|
||||
|
||||
/**
|
||||
* Reads a string from the specified input stream.
|
||||
*
|
||||
* @param is The input stream.
|
||||
* @return The string.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public static String readString(InputStream is) throws IOException {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
char character;
|
||||
while ((character = (char) is.read()) != -1 && character != '\0') {
|
||||
builder.append(character);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a string to the specified output stream.
|
||||
*
|
||||
* @param os The output stream.
|
||||
* @param str The string.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
public static void writeString(OutputStream os, String str) throws IOException {
|
||||
for (char c : str.toCharArray()) {
|
||||
os.write(c);
|
||||
}
|
||||
os.write('\0');
|
||||
}
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation.
|
||||
*/
|
||||
private StreamUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
package org.apollo.util;
|
||||
|
||||
/**
|
||||
* A class which contains text-related utility methods.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class TextUtil {
|
||||
|
||||
/**
|
||||
* An array of characters ordered by frequency - the elements with lower indices (generally) appear more often in
|
||||
* chat messages.
|
||||
*/
|
||||
public static final char[] FREQUENCY_ORDERED_CHARS = { ' ', 'e', 't', 'a', 'o', 'i', 'h', 'n', 's', 'r', 'd', 'l',
|
||||
'u', 'm', 'w', 'c', 'y', 'f', 'g', 'p', 'b', 'v', 'k', 'x', 'j', 'q', 'z', '0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', ' ', '!', '?', '.', ',', ':', ';', '(', ')', '-', '&', '*', '\\', '\'', '@', '#', '+',
|
||||
'=', '\243', '$', '%', '"', '[', ']' };
|
||||
|
||||
/**
|
||||
* Capitalizes the string correctly.
|
||||
*
|
||||
* @param str The input string.
|
||||
* @return The string with correct capitalization.
|
||||
*/
|
||||
public static String capitalize(String str) {
|
||||
boolean capitalize = true;
|
||||
StringBuilder bldr = new StringBuilder(str);
|
||||
for (int index = 0, length = str.length(); index < length; index++) {
|
||||
char character = bldr.charAt(index);
|
||||
if (character == '.' || character == '!' || character == '?') {
|
||||
capitalize = true;
|
||||
} else if (capitalize && !Character.isWhitespace(character)) {
|
||||
bldr.setCharAt(index, Character.toUpperCase(character));
|
||||
capitalize = false;
|
||||
}
|
||||
}
|
||||
return bldr.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compresses the input text ({@code in}) and places the result in the {@code out} array.
|
||||
*
|
||||
* @param in The input text.
|
||||
* @param out The output array.
|
||||
* @return The number of bytes written to the output array.
|
||||
*/
|
||||
public static int compress(String in, byte[] out) {
|
||||
if (in.length() > 80) {
|
||||
in = in.substring(0, 80);
|
||||
}
|
||||
in = in.toLowerCase();
|
||||
|
||||
int carry = -1;
|
||||
int outPos = 0;
|
||||
for (int inPos = 0; inPos < in.length(); inPos++) {
|
||||
char c = in.charAt(inPos);
|
||||
int tblPos = 0;
|
||||
for (int i = 0; i < FREQUENCY_ORDERED_CHARS.length; i++) {
|
||||
if (c == FREQUENCY_ORDERED_CHARS[i]) {
|
||||
tblPos = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (tblPos > 12) {
|
||||
tblPos += 195;
|
||||
}
|
||||
if (carry == -1) {
|
||||
if (tblPos < 13) {
|
||||
carry = tblPos;
|
||||
} else {
|
||||
out[outPos++] = (byte) tblPos;
|
||||
}
|
||||
} else if (tblPos < 13) {
|
||||
out[outPos++] = (byte) ((carry << 4) + tblPos);
|
||||
carry = -1;
|
||||
} else {
|
||||
out[outPos++] = (byte) ((carry << 4) + (tblPos >> 4));
|
||||
carry = tblPos & 0xF;
|
||||
}
|
||||
}
|
||||
if (carry != -1) {
|
||||
out[outPos++] = (byte) (carry << 4);
|
||||
}
|
||||
return outPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters invalid characters from the specified string.
|
||||
*
|
||||
* @param str The input string.
|
||||
* @return The filtered string.
|
||||
*/
|
||||
public static String filterInvalidCharacters(String str) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (char c : str.toLowerCase().toCharArray()) {
|
||||
for (char validChar : FREQUENCY_ORDERED_CHARS) {
|
||||
if (c == validChar) {
|
||||
builder.append(c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Uncompresses the compressed data ({@code in}) with the length ({@code len}) and returns the uncompressed
|
||||
* {@link String}.
|
||||
*
|
||||
* @param in The compressed input data.
|
||||
* @param len The length.
|
||||
* @return The uncompressed {@link String}.
|
||||
*/
|
||||
public static String decompress(byte[] in, int len) {
|
||||
byte[] out = new byte[4096];
|
||||
int outPos = 0;
|
||||
int carry = -1;
|
||||
|
||||
for (int i = 0; i < len * 2; i++) {
|
||||
int tblPos = in[i / 2] >> 4 - 4 * (i % 2) & 0xF;
|
||||
if (carry == -1) {
|
||||
if (tblPos < 13) {
|
||||
out[outPos++] = (byte) FREQUENCY_ORDERED_CHARS[tblPos];
|
||||
} else {
|
||||
carry = tblPos;
|
||||
}
|
||||
} else {
|
||||
out[outPos++] = (byte) FREQUENCY_ORDERED_CHARS[(carry << 4) + tblPos - 195];
|
||||
carry = -1;
|
||||
}
|
||||
}
|
||||
return new String(out, 0, outPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation.
|
||||
*/
|
||||
private TextUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import java.lang.Thread.UncaughtExceptionHandler;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
|
||||
/**
|
||||
* A static utility class which provides ease of use functionality for {@link Thread}s
|
||||
*
|
||||
* @author Ryley
|
||||
* @author Major
|
||||
*/
|
||||
public final class ThreadUtil {
|
||||
|
||||
/**
|
||||
* Returns the amount of available processors available to the Java virtual machine.
|
||||
*/
|
||||
public static final int AVAILABLE_PROCESSORS = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
/**
|
||||
* A {@link Logger} used to debug messages to the console.
|
||||
*/
|
||||
private static final Logger LOGGER = Logger.getLogger(ThreadUtil.class.getSimpleName());
|
||||
|
||||
/**
|
||||
* The default {@link UncaughtExceptionHandler} which raises an error from the logger with the exception and name of
|
||||
* the specified thread the exception occurred in.
|
||||
*/
|
||||
private static final UncaughtExceptionHandler DEFAULT_EXCEPTION_HANDLER = (thread, exception) -> LOGGER.log(Level.SEVERE,
|
||||
"Exception occured in thread " + thread.getName(), exception);
|
||||
|
||||
/**
|
||||
* Builds a {@link ThreadFactory} using the specified {@code String} name-format, normal thread priority and the
|
||||
* default {@link UncaughtExceptionHandler}.
|
||||
*
|
||||
* @see #DEFAULT_EXCEPTION_HANDLER
|
||||
*
|
||||
* @param name The name-format used when creating threads, may not be {@code null}.
|
||||
* @return A new {@link ThreadFactory} from the specified parameters, never {@code null}.
|
||||
*/
|
||||
public static ThreadFactory create(String name) {
|
||||
return create(name, Thread.NORM_PRIORITY, DEFAULT_EXCEPTION_HANDLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link ThreadFactory} using the specified {@code String} name-format, priority and the
|
||||
* {@link #DEFAULT_EXCEPTION_HANDLER}.
|
||||
*
|
||||
* @param name The name-format used when creating threads, may not be {@code null}.
|
||||
* @param priority The priority used when creating threads.
|
||||
* @return A new {@link ThreadFactory} from the specified parameters, never {@code null}.
|
||||
*/
|
||||
public static ThreadFactory create(String name, int priority) {
|
||||
return create(name, priority, DEFAULT_EXCEPTION_HANDLER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link ThreadFactory} using the specified {@code String} name-format, priority and
|
||||
* {@link UncaughtExceptionHandler}.
|
||||
*
|
||||
* @param name The name-format used when creating threads. Must not be {@code null}.
|
||||
* @param priority The priority used when creating threads.
|
||||
* @param handler The {@link UncaughtExceptionHandler} used when creating threads. Must not be {@code null}.
|
||||
* @return A new {@link ThreadFactory} using the specified parameters.
|
||||
*/
|
||||
public static ThreadFactory create(String name, int priority, UncaughtExceptionHandler handler) {
|
||||
Objects.requireNonNull(priority);
|
||||
|
||||
ThreadFactoryBuilder builder = new ThreadFactoryBuilder();
|
||||
builder.setNameFormat(name);
|
||||
builder.setPriority(priority);
|
||||
builder.setUncaughtExceptionHandler(handler);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sole private constructor to prevent instantiation.
|
||||
*/
|
||||
private ThreadUtil() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains utility classes.
|
||||
*/
|
||||
package org.apollo.util;
|
||||
@@ -0,0 +1,287 @@
|
||||
package org.apollo.util.security;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* An implementation of the <a href="http://www.burtleburtle.net/bob/rand/isaacafa.html">ISAAC</a> psuedorandom number
|
||||
* generator.
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* ------------------------------------------------------------------------------
|
||||
* Rand.java: By Bob Jenkins. My random number generator, ISAAC.
|
||||
* rand.init() -- initialize
|
||||
* rand.val() -- get a random value
|
||||
* MODIFIED:
|
||||
* 960327: Creation (addition of randinit, really)
|
||||
* 970719: use context, not global variables, for internal state
|
||||
* 980224: Translate to Java
|
||||
* ------------------------------------------------------------------------------
|
||||
* </pre>
|
||||
* <p>
|
||||
* This class has been changed to be more conformant to Java and javadoc conventions.
|
||||
* </p>
|
||||
*
|
||||
* @author Bob Jenkins
|
||||
*/
|
||||
public final class IsaacRandom {
|
||||
|
||||
/**
|
||||
* The golden ratio.
|
||||
*/
|
||||
private static final int GOLDEN_RATIO = 0x9e3779b9;
|
||||
|
||||
/**
|
||||
* The log of the size of the result and state arrays.
|
||||
*/
|
||||
private static final int LOG_SIZE = Long.BYTES;
|
||||
|
||||
/**
|
||||
* The size of the result and states arrays.
|
||||
*/
|
||||
private static final int SIZE = 1 << LOG_SIZE;
|
||||
|
||||
/**
|
||||
* A mask for pseudo-random lookup.
|
||||
*/
|
||||
private static int MASK = SIZE - 1 << 2;
|
||||
|
||||
/**
|
||||
* The results given to the user.
|
||||
*/
|
||||
private final int[] results = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The internal state.
|
||||
*/
|
||||
private final int[] state = new int[SIZE];
|
||||
|
||||
/**
|
||||
* The count through the results in the results array.
|
||||
*/
|
||||
private int count = SIZE;
|
||||
|
||||
/**
|
||||
* The accumulator.
|
||||
*/
|
||||
private int accumulator;
|
||||
|
||||
/**
|
||||
* The last result.
|
||||
*/
|
||||
private int last;
|
||||
|
||||
/**
|
||||
* The counter.
|
||||
*/
|
||||
private int counter;
|
||||
|
||||
/**
|
||||
* Creates the random number generator with the specified seed.
|
||||
*
|
||||
* @param seed The seed.
|
||||
*/
|
||||
public IsaacRandom(int[] seed) {
|
||||
int length = Math.min(seed.length, results.length);
|
||||
System.arraycopy(seed, 0, results, 0, length);
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates 256 results.
|
||||
*/
|
||||
private void isaac() {
|
||||
int i, j, x, y;
|
||||
|
||||
last += ++counter;
|
||||
for (i = 0, j = SIZE / 2; i < SIZE / 2;) {
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 13;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 6;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 2;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 16;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
}
|
||||
|
||||
for (j = 0; j < SIZE / 2;) {
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 13;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 6;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator << 2;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
|
||||
x = state[i];
|
||||
accumulator ^= accumulator >>> 16;
|
||||
accumulator += state[j++];
|
||||
state[i] = y = state[(x & MASK) >> 2] + accumulator + last;
|
||||
results[i++] = last = state[(y >> LOG_SIZE & MASK) >> 2] + x;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this random number generator.
|
||||
*/
|
||||
private void init() {
|
||||
int i;
|
||||
int a, b, c, d, e, f, g, h;
|
||||
a = b = c = d = e = f = g = h = GOLDEN_RATIO;
|
||||
|
||||
for (i = 0; i < 4; ++i) {
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
}
|
||||
|
||||
for (i = 0; i < SIZE; i += 8) { /* fill in mem[] with messy stuff */
|
||||
a += results[i];
|
||||
b += results[i + 1];
|
||||
c += results[i + 2];
|
||||
d += results[i + 3];
|
||||
e += results[i + 4];
|
||||
f += results[i + 5];
|
||||
g += results[i + 6];
|
||||
h += results[i + 7];
|
||||
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
state[i] = a;
|
||||
state[i + 1] = b;
|
||||
state[i + 2] = c;
|
||||
state[i + 3] = d;
|
||||
state[i + 4] = e;
|
||||
state[i + 5] = f;
|
||||
state[i + 6] = g;
|
||||
state[i + 7] = h;
|
||||
}
|
||||
|
||||
for (i = 0; i < SIZE; i += 8) {
|
||||
a += state[i];
|
||||
b += state[i + 1];
|
||||
c += state[i + 2];
|
||||
d += state[i + 3];
|
||||
e += state[i + 4];
|
||||
f += state[i + 5];
|
||||
g += state[i + 6];
|
||||
h += state[i + 7];
|
||||
a ^= b << 11;
|
||||
d += a;
|
||||
b += c;
|
||||
b ^= c >>> 2;
|
||||
e += b;
|
||||
c += d;
|
||||
c ^= d << 8;
|
||||
f += c;
|
||||
d += e;
|
||||
d ^= e >>> 16;
|
||||
g += d;
|
||||
e += f;
|
||||
e ^= f << 10;
|
||||
h += e;
|
||||
f += g;
|
||||
f ^= g >>> 4;
|
||||
a += f;
|
||||
g += h;
|
||||
g ^= h << 8;
|
||||
b += g;
|
||||
h += a;
|
||||
h ^= a >>> 9;
|
||||
c += h;
|
||||
a += b;
|
||||
state[i] = a;
|
||||
state[i + 1] = b;
|
||||
state[i + 2] = c;
|
||||
state[i + 3] = d;
|
||||
state[i + 4] = e;
|
||||
state[i + 5] = f;
|
||||
state[i + 6] = g;
|
||||
state[i + 7] = h;
|
||||
}
|
||||
|
||||
isaac();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the next random value.
|
||||
*
|
||||
* @return The next random value.
|
||||
*/
|
||||
public int nextInt() {
|
||||
if (0 == count--) {
|
||||
isaac();
|
||||
count = SIZE - 1;
|
||||
}
|
||||
return results[count];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package org.apollo.util.security;
|
||||
|
||||
|
||||
/**
|
||||
* A pair of two {@link IsaacRandom} random number generators used as a stream cipher. One takes the role of an encoder
|
||||
* for this endpoint, the other takes the role of a decoder for this endpoint.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class IsaacRandomPair {
|
||||
|
||||
/**
|
||||
* The random number generator used to decode data.
|
||||
*/
|
||||
private final IsaacRandom decodingRandom;
|
||||
|
||||
/**
|
||||
* The random number generator used to encode data.
|
||||
*/
|
||||
private final IsaacRandom encodingRandom;
|
||||
|
||||
/**
|
||||
* Creates the pair of random number generators.
|
||||
*
|
||||
* @param encodingRandom The random number generator used for encoding.
|
||||
* @param decodingRandom The random number generator used for decoding.
|
||||
*/
|
||||
public IsaacRandomPair(IsaacRandom encodingRandom, IsaacRandom decodingRandom) {
|
||||
this.encodingRandom = encodingRandom;
|
||||
this.decodingRandom = decodingRandom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random number generator used for decoding.
|
||||
*
|
||||
* @return The random number generator used for decoding.
|
||||
*/
|
||||
public IsaacRandom getDecodingRandom() {
|
||||
return decodingRandom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the random number generator used for encoding.
|
||||
*
|
||||
* @return The random number generator used for encoding.
|
||||
*/
|
||||
public IsaacRandom getEncodingRandom() {
|
||||
return encodingRandom;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package org.apollo.util.security;
|
||||
|
||||
import org.apollo.util.NameUtil;
|
||||
|
||||
/**
|
||||
* Holds the credentials for a player.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class PlayerCredentials {
|
||||
|
||||
/**
|
||||
* The player's username encoded as a long.
|
||||
*/
|
||||
private final long encodedUsername;
|
||||
|
||||
/**
|
||||
* The player's password.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
/**
|
||||
* The computer's unique identifier.
|
||||
*/
|
||||
private final int uid;
|
||||
|
||||
/**
|
||||
* The player's username.
|
||||
*/
|
||||
private final String username;
|
||||
|
||||
/**
|
||||
* The hash of the player's username.
|
||||
*/
|
||||
private final int usernameHash;
|
||||
|
||||
/**
|
||||
* The Player's host address, represented as a String.
|
||||
*/
|
||||
private final String hostAddress;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PlayerCredentials} object with the specified name, password and uid.
|
||||
*
|
||||
* @param username The player's username.
|
||||
* @param password The player's password.
|
||||
* @param usernameHash The hash of the player's username.
|
||||
* @param uid The computer's uid.
|
||||
* @param hostAddress The Player's connecting host address.
|
||||
*/
|
||||
public PlayerCredentials(String username, String password, int usernameHash, int uid, String hostAddress) {
|
||||
this.username = username;
|
||||
encodedUsername = NameUtil.encodeBase37(username);
|
||||
this.password = password;
|
||||
this.usernameHash = usernameHash;
|
||||
this.uid = uid;
|
||||
this.hostAddress = hostAddress;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's username encoded as a long.
|
||||
*
|
||||
* @return The username as encoded by {@link NameUtil#encodeBase37(String)}.
|
||||
*/
|
||||
public long getEncodedUsername() {
|
||||
return encodedUsername;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the player's password
|
||||
*
|
||||
* @param password The player's new password
|
||||
*/
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's password.
|
||||
*
|
||||
* @return The player's password.
|
||||
*/
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the computer's uid.
|
||||
*
|
||||
* @return The computer's uid.
|
||||
*/
|
||||
public int getUid() {
|
||||
return uid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the player's username.
|
||||
*
|
||||
* @return The player's username.
|
||||
*/
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the username hash.
|
||||
*
|
||||
* @return The username hash.
|
||||
*/
|
||||
public int getUsernameHash() {
|
||||
return usernameHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Player's connecting host address.
|
||||
*
|
||||
* @return The Player's host address, represented as a String.
|
||||
*/
|
||||
public String getHostAddress() {
|
||||
return hostAddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Long.hashCode(encodedUsername);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof PlayerCredentials) {
|
||||
PlayerCredentials other = (PlayerCredentials) obj;
|
||||
return encodedUsername == other.encodedUsername;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains classes related to security and cryptography.
|
||||
*/
|
||||
package org.apollo.util.security;
|
||||
@@ -0,0 +1,102 @@
|
||||
package org.apollo.util.tools;
|
||||
|
||||
/**
|
||||
* Contains equipment name constants.
|
||||
*
|
||||
* @author Graham
|
||||
* @author Palidino76
|
||||
*/
|
||||
public final class EquipmentConstants {
|
||||
|
||||
/**
|
||||
* Amulets.
|
||||
*/
|
||||
public static final String[] AMULETS = { "amulet", "necklace", "Amulet of" };
|
||||
|
||||
/**
|
||||
* Arrows.
|
||||
*/
|
||||
public static final String[] ARROWS = { "arrow", "arrows", "arrow(p)", "arrow(+)", "arrow(s)", "bolt", "Bolt rack",
|
||||
"Opal bolts", "Dragon bolts" };
|
||||
|
||||
/**
|
||||
* Bodies.
|
||||
*/
|
||||
public static final String[] BODY = { "platebody", "chainbody", "robetop", "leathertop", "platemail", "top",
|
||||
"brassard", "Robe top", "body", "platebody (t)", "platebody (g)", "body(g)", "body_(g)", "chestplate",
|
||||
"torso", "shirt" };
|
||||
|
||||
/**
|
||||
* Boots.
|
||||
*/
|
||||
public static final String[] BOOTS = { "boots", "Boots" };
|
||||
|
||||
/**
|
||||
* Capes.
|
||||
*/
|
||||
public static final String[] CAPES = { "cape", "Cape" };
|
||||
|
||||
/**
|
||||
* Full bodies.
|
||||
*/
|
||||
public static final String[] FULL_BODIES = { "top", "shirt", "platebody", "Ahrims robetop", "Karils leathertop",
|
||||
"brassard", "Robe top", "robetop", "platebody (t)", "platebody (g)", "chestplate", "torso" };
|
||||
|
||||
/**
|
||||
* Full hats.
|
||||
*/
|
||||
public static final String[] FULL_HATS = { "med helm", "coif", "Dharoks helm", "hood", "Initiate helm", "Coif",
|
||||
"Helm of neitiznot" };
|
||||
|
||||
/**
|
||||
* Full masks.
|
||||
*/
|
||||
public static final String[] FULL_MASKS = { "full helm", "mask", "Veracs helm", "Guthans helm", "Torags helm",
|
||||
"Karils coif", "full helm (t)", "full helm (g)", "mask" };
|
||||
|
||||
/**
|
||||
* Gloves.
|
||||
*/
|
||||
public static final String[] GLOVES = { "gloves", "gauntlets", "Gloves", "vambraces", "vamb", "bracers" };
|
||||
|
||||
/**
|
||||
* Hats.
|
||||
*/
|
||||
public static final String[] HATS = { "tiara", "helm", "hood", "coif", "Coif", "hat", "partyhat", "Hat",
|
||||
"full helm (t)", "full helm (g)", "hat (t)", "hat (g)", "cav", "boater", "helmet", "mask",
|
||||
"Helm of neitiznot" };
|
||||
|
||||
/**
|
||||
* Legs.
|
||||
*/
|
||||
public static final String[] LEGS = { "platelegs", "plateskirt", "skirt", "bottoms", "chaps", "platelegs (t)",
|
||||
"platelegs (g)", "bottom", "skirt", "skirt (g)", "skirt (t)", "chaps (g)", "chaps (t)", "tassets", "legs",
|
||||
"Flared trousers" };
|
||||
|
||||
/**
|
||||
* Rings.
|
||||
*/
|
||||
public static final String[] RINGS = { "ring", "Ring of" };
|
||||
|
||||
/**
|
||||
* Shields.
|
||||
*/
|
||||
public static final String[] SHIELDS = { "kiteshield", "sq shield", "Toktz-ket", "books", "book", "kiteshield (t)",
|
||||
"kiteshield (g)", "kiteshield(h)", "defender", "shield" };
|
||||
|
||||
/**
|
||||
* Weapons.
|
||||
*/
|
||||
public static final String[] WEAPONS = { "scimitar", "longsword", "sword", "longbow", "shortbow", "dagger", "mace",
|
||||
"halberd", "spear", "Abyssal whip", "axe", "flail", "crossbow", "Torags hammers", "dagger(p)", "dagger(+)",
|
||||
"dagger(s)", "spear(p)", "spear(+)", "spear(s)", "spear(kp)", "maul", "dart", "dart(p)", "javelin",
|
||||
"javelin(p)", "knife", "knife(p)", "Longbow", "Shortbow", "Crossbow", "Toktz-xil", "Toktz-mej",
|
||||
"Tzhaar-ket", "staff", "Staff", "godsword", "c'bow", "Crystal bow", "Dark bow", "Magic butterfly net" };
|
||||
|
||||
/**
|
||||
* Default private constructor to prevent instantiation.
|
||||
*/
|
||||
private EquipmentConstants() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.apollo.util.tools;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* An RSA key generator.
|
||||
*
|
||||
* @author Graham
|
||||
* @author Major
|
||||
*/
|
||||
public final class RsaKeyGenerator {
|
||||
|
||||
/**
|
||||
* The bit count. <strong>Strongly</strong> recommended to be at least 2,048.
|
||||
*/
|
||||
private static final int BIT_COUNT = 2_048;
|
||||
|
||||
/**
|
||||
* The entry point of the RsaKeyGenerator.
|
||||
*
|
||||
* @param args The application arguments.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
Random random = new SecureRandom();
|
||||
|
||||
BigInteger publicKey = BigInteger.valueOf(65_537);
|
||||
BigInteger p, q, phi, modulus, privateKey;
|
||||
|
||||
do {
|
||||
p = BigInteger.probablePrime(BIT_COUNT / 2, random);
|
||||
q = BigInteger.probablePrime(BIT_COUNT / 2, random);
|
||||
phi = p.subtract(BigInteger.ONE).multiply(q.subtract(BigInteger.ONE));
|
||||
|
||||
modulus = p.multiply(q);
|
||||
privateKey = publicKey.modInverse(phi);
|
||||
} while (modulus.bitLength() != BIT_COUNT || privateKey.bitLength() != BIT_COUNT || !phi.gcd(publicKey).equals(BigInteger.ONE));
|
||||
|
||||
System.out.println("modulus: " + modulus);
|
||||
System.out.println("public key: " + publicKey);
|
||||
System.out.println("private key: " + privateKey);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains several stand-alone utilities.
|
||||
*/
|
||||
package org.apollo.util.tools;
|
||||
@@ -0,0 +1,247 @@
|
||||
package org.apollo.util.xml;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A class which represents a single node in the DOM tree, maintaining information about its children, attributes, value
|
||||
* and name.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class XmlNode implements Iterable<XmlNode> {
|
||||
|
||||
/**
|
||||
* The attribute map.
|
||||
*/
|
||||
private final Map<String, String> attributes = new HashMap<>();
|
||||
|
||||
/**
|
||||
* The list of child nodes.
|
||||
*/
|
||||
private final List<XmlNode> children = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The name of this node.
|
||||
*/
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* The value of this node, or {@code null} if it has no value.
|
||||
*/
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* Creates a new {@link XmlNode} with the specified name.
|
||||
*
|
||||
* @param name The name of this node.
|
||||
*/
|
||||
public XmlNode(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a child {@link XmlNode}.
|
||||
*
|
||||
* @param child The child to add.
|
||||
*/
|
||||
public void addChild(XmlNode child) {
|
||||
children.add(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an attribute with the specified name exists.
|
||||
*
|
||||
* @param name The attribute's name.
|
||||
* @return {@code true} if an attribute with that name exists, {@code false} otherwise.
|
||||
*/
|
||||
public boolean containsAttribute(String name) {
|
||||
return attributes.containsKey(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an attribute by it's name.
|
||||
*
|
||||
* @param name The name of the attribute.
|
||||
* @return The attribute's value, or {@code null} if it doesn't exist.
|
||||
*/
|
||||
public String getAttribute(String name) {
|
||||
return attributes.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute count.
|
||||
*
|
||||
* @return The number of attributes.
|
||||
*/
|
||||
public int getAttributeCount() {
|
||||
return attributes.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Set} of attribute names.
|
||||
*
|
||||
* @return The set of names.
|
||||
*/
|
||||
public Set<String> getAttributeNames() {
|
||||
return attributes.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Set} of attribute map entries.
|
||||
*
|
||||
* @return The set of entries.
|
||||
*/
|
||||
public Set<Map.Entry<String, String>> getAttributes() {
|
||||
return attributes.entrySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the first child with the specified name.
|
||||
*
|
||||
* @param name The name of the child.
|
||||
* @return The {@link XmlNode} if a child was found with a matching name, {@code null} otherwise.
|
||||
*/
|
||||
public XmlNode getChild(String name) {
|
||||
for (XmlNode child : children) {
|
||||
if (child.getName().equals(name)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the child count.
|
||||
*
|
||||
* @return The number of child {@link XmlNode}s.
|
||||
*/
|
||||
public int getChildCount() {
|
||||
return children.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a {@link Collection} of child {@link XmlNode}s.
|
||||
*
|
||||
* @return The collection.
|
||||
*/
|
||||
public Collection<XmlNode> getChildren() {
|
||||
return Collections.unmodifiableCollection(children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this node.
|
||||
*
|
||||
* @return The name of this node.
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this node.
|
||||
*
|
||||
* @return The value of this node, or {@code null} if it has no value.
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of this node, wrapped in an {@link Optional}
|
||||
*
|
||||
* @return The value of this node if it exists otherwise {@link Optional#empty()} is returned
|
||||
*/
|
||||
public Optional<String> getOptionalValue() {
|
||||
return Optional.ofNullable(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this node has a value.
|
||||
*
|
||||
* @return {@code true} if so, {@code false} if not.
|
||||
*/
|
||||
public boolean hasValue() {
|
||||
return value != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<XmlNode> iterator() {
|
||||
return children.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all attributes.
|
||||
*/
|
||||
public void removeAllAttributes() {
|
||||
attributes.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all children.
|
||||
*/
|
||||
public void removeAllChildren() {
|
||||
children.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an attribute.
|
||||
*
|
||||
* @param name The name of the attribute.
|
||||
*/
|
||||
public void removeAttribute(String name) {
|
||||
attributes.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a child {@link XmlNode}.
|
||||
*
|
||||
* @param child The child to remove.
|
||||
*/
|
||||
public void removeChild(XmlNode child) {
|
||||
children.remove(child);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the value of this node.
|
||||
*/
|
||||
public void removeValue() {
|
||||
value = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an attribute. It will overwrite an existing attribute if it exists.
|
||||
*
|
||||
* @param name The name of the attribute.
|
||||
* @param value The value of the attribute.
|
||||
*/
|
||||
public void setAttribute(String name, String value) {
|
||||
attributes.put(name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this node.
|
||||
*
|
||||
* @param name The name of this node.
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of this node.
|
||||
*
|
||||
* @param value The value of this node.
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package org.apollo.util.xml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.XMLReader;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
import org.xml.sax.helpers.XMLReaderFactory;
|
||||
|
||||
/**
|
||||
* A simple XML parser that uses the internal {@link org.xml.sax} API to create a tree of {@link XmlNode} objects.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class XmlParser {
|
||||
|
||||
/**
|
||||
* A class which handles SAX events.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
private final class XmlHandler extends DefaultHandler {
|
||||
|
||||
@Override
|
||||
public void characters(char[] ch, int start, int length) throws SAXException {
|
||||
currentNode.setValue(new String(ch, start, length));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException {
|
||||
if (!nodeStack.isEmpty()) {
|
||||
currentNode = nodeStack.pop();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
|
||||
XmlNode next = new XmlNode(localName);
|
||||
|
||||
if (rootNode == null) {
|
||||
rootNode = currentNode = next;
|
||||
} else {
|
||||
currentNode.addChild(next);
|
||||
nodeStack.add(currentNode);
|
||||
currentNode = next;
|
||||
}
|
||||
|
||||
if (attributes != null) {
|
||||
int attributeCount = attributes.getLength();
|
||||
for (int i = 0; i < attributeCount; i++) {
|
||||
String attribLocalName = attributes.getLocalName(i);
|
||||
currentNode.setAttribute(attribLocalName, attributes.getValue(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The current node.
|
||||
*/
|
||||
private XmlNode currentNode;
|
||||
|
||||
/**
|
||||
* The SAX event handler.
|
||||
*/
|
||||
private final XmlHandler eventHandler;
|
||||
|
||||
/**
|
||||
* The stack of nodes, used when traversing the document and going through child nodes.
|
||||
*/
|
||||
private final Stack<XmlNode> nodeStack = new Stack<>();
|
||||
|
||||
/**
|
||||
* The current root node.
|
||||
*/
|
||||
private XmlNode rootNode;
|
||||
|
||||
/**
|
||||
* The {@link XMLReader} backing this {@link XmlParser}.
|
||||
*/
|
||||
private final XMLReader xmlReader;
|
||||
|
||||
/**
|
||||
* Creates the XML parser.
|
||||
*
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
*/
|
||||
public XmlParser() throws SAXException {
|
||||
xmlReader = XMLReaderFactory.createXMLReader();
|
||||
eventHandler = this.new XmlHandler();
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises this parser.
|
||||
*/
|
||||
private void init() {
|
||||
xmlReader.setContentHandler(eventHandler);
|
||||
xmlReader.setDTDHandler(eventHandler);
|
||||
xmlReader.setEntityResolver(eventHandler);
|
||||
xmlReader.setErrorHandler(eventHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses XML data from the {@link InputSource}.
|
||||
*
|
||||
* @param source The {@link InputSource}.
|
||||
* @return The root {@link XmlNode}.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
*/
|
||||
private XmlNode parse(InputSource source) throws IOException, SAXException {
|
||||
rootNode = null;
|
||||
xmlReader.parse(source);
|
||||
if (rootNode == null) {
|
||||
throw new SAXException("No root element.");
|
||||
}
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses XML data from the given {@link InputStream}.
|
||||
*
|
||||
* @param is The {@link InputStream}.
|
||||
* @return The root {@link XmlNode}.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
*/
|
||||
public XmlNode parse(InputStream is) throws IOException, SAXException {
|
||||
synchronized (this) {
|
||||
return parse(new InputSource(is));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses XML data from the given {@link Reader}.
|
||||
*
|
||||
* @param reader The {@link Reader}.
|
||||
* @return The root {@link XmlNode}.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
*/
|
||||
public XmlNode parse(Reader reader) throws IOException, SAXException {
|
||||
synchronized (this) {
|
||||
return parse(new InputSource(reader));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Contains classes which parse XML data into an object tree.
|
||||
*/
|
||||
package org.apollo.util.xml;
|
||||
@@ -0,0 +1,49 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Contains tests for {@link BufferUtil}.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public class TestBufferUtil {
|
||||
|
||||
/**
|
||||
* Tests the {@link BufferUtil#readUnsignedMedium} method.
|
||||
*/
|
||||
@Test
|
||||
public void testReadUnsignedTriByte() {
|
||||
ByteBuffer buf = ByteBuffer.allocate(3);
|
||||
buf.put((byte) 123);
|
||||
buf.put((byte) 45);
|
||||
buf.put((byte) 67);
|
||||
buf.flip();
|
||||
|
||||
assertEquals(8072515, BufferUtil.readUnsignedMedium(buf));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the {@link BufferUtil#readString(ByteBuffer)} method.
|
||||
*/
|
||||
@Test
|
||||
public void testReadString() {
|
||||
ByteBuffer buf = ByteBuffer.allocate(8);
|
||||
buf.put((byte) 'h');
|
||||
buf.put((byte) 'e');
|
||||
buf.put((byte) 'l');
|
||||
buf.put((byte) 'l');
|
||||
buf.put((byte) 'o');
|
||||
buf.put((byte) BufferUtil.STRING_TERMINATOR);
|
||||
buf.put((byte) 66);
|
||||
buf.put((byte) 6);
|
||||
buf.flip();
|
||||
|
||||
assertEquals("hello", BufferUtil.readString(buf));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Contains tests for {@link ByteBuf} methods in {@link BufferUtil}.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class TestByteBufUtil {
|
||||
|
||||
/**
|
||||
* Test the {@link BufferUtil#readString(ByteBuf)} method.
|
||||
*/
|
||||
@Test
|
||||
public void testReadString() {
|
||||
ByteBuf buf = Unpooled.buffer(6);
|
||||
buf.writeBytes(new byte[] { 'H', 'e', 'l', 'l', 'o', 10 });
|
||||
String str = BufferUtil.readString(buf);
|
||||
assertEquals("Hello", str);
|
||||
|
||||
buf = Unpooled.buffer(5);
|
||||
buf.writeBytes(new byte[] { 'W', 'o', 'r', 'l', 'd' });
|
||||
str = BufferUtil.readString(buf);
|
||||
assertEquals("World", str);
|
||||
|
||||
buf = Unpooled.buffer(3);
|
||||
buf.writeByte('!');
|
||||
buf.writeByte(10);
|
||||
buf.writeByte('.');
|
||||
|
||||
str = BufferUtil.readString(buf);
|
||||
assertEquals("!", str);
|
||||
|
||||
str = BufferUtil.readString(buf);
|
||||
assertEquals(".", str);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Contains tests for {@link CompressionUtil}.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public class TestCompressionUtil {
|
||||
|
||||
/**
|
||||
* Tests the {@link CompressionUtil#bzip2(byte[])} and {@link CompressionUtil#debzip2} methods.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testBzip2() throws IOException {
|
||||
String str = "Hello, World!";
|
||||
byte[] data = str.getBytes();
|
||||
byte[] compressed = CompressionUtil.bzip2(data);
|
||||
CompressionUtil.debzip2(compressed, data);
|
||||
assertEquals(str, new String(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the {@link CompressionUtil#gzip(byte[])} and {@link CompressionUtil#degzip} methods.
|
||||
*
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testGzip() throws IOException {
|
||||
String str = "Hello, World!";
|
||||
byte[] data = str.getBytes();
|
||||
byte[] compressed = CompressionUtil.gzip(data);
|
||||
CompressionUtil.degzip(compressed, data);
|
||||
assertEquals(str, new String(data));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* Contains tests for {@link LanguageUtil}.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public class TestLanguageUtil {
|
||||
|
||||
/**
|
||||
* Tests the {@link LanguageUtil#getIndefiniteArticle} method.
|
||||
*/
|
||||
@Test
|
||||
public void testIndefiniteArticle() {
|
||||
assertEquals("an", LanguageUtil.getIndefiniteArticle("apple"));
|
||||
assertEquals("an", LanguageUtil.getIndefiniteArticle("urn"));
|
||||
assertEquals("a", LanguageUtil.getIndefiniteArticle("nose"));
|
||||
assertEquals("a", LanguageUtil.getIndefiniteArticle("foot"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.apollo.util;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
/**
|
||||
* A test for the {@link TextUtil} class.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public class TestTextUtil {
|
||||
|
||||
/**
|
||||
* Tests the {@link TextUtil#capitalize} method.
|
||||
*/
|
||||
@Test
|
||||
public void testCapitalize() {
|
||||
String str = "tHiS is BAD capitAliZation. do You AGreE? YES!";
|
||||
String capitalized = "This is bad capitalization. Do you agree? Yes!";
|
||||
assertEquals(capitalized, TextUtil.capitalize(str));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the {@link TextUtil#compress} and {@link TextUtil#decompress} methods.
|
||||
*/
|
||||
@Test
|
||||
public void testCompression() {
|
||||
String str = "hello, world!";
|
||||
|
||||
byte[] compressed = new byte[128];
|
||||
int len = TextUtil.compress(str, compressed);
|
||||
String uncompressed = TextUtil.decompress(compressed, len);
|
||||
|
||||
assertEquals(str, uncompressed);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the {@link TextUtil#filterInvalidCharacters(String)} method.
|
||||
*/
|
||||
@Test
|
||||
public void testFilter() {
|
||||
String str = "this contains <<< invalid characters";
|
||||
String filtered = "this contains invalid characters";
|
||||
assertEquals(filtered, TextUtil.filterInvalidCharacters(str));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
package org.apollo.util.xml;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* A test for the {@link XmlParser} class.
|
||||
*
|
||||
* @author Graham
|
||||
*/
|
||||
public final class TestXmlParser {
|
||||
|
||||
/**
|
||||
* A test for the {@link XmlParser#parse} method.
|
||||
*
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testParseInputStream() throws SAXException, IOException {
|
||||
XmlParser parser = new XmlParser();
|
||||
InputStream input = new ByteArrayInputStream("<root a='1' b='2' c='3'><z><y><x></x></y></z></root>".getBytes());
|
||||
XmlNode root = parser.parse(input);
|
||||
|
||||
assertEquals(root.getName(), "root");
|
||||
assertEquals(root.getAttributeCount(), 3);
|
||||
assertEquals(root.getChildCount(), 1);
|
||||
assertFalse(root.hasValue());
|
||||
|
||||
Set<String> names = root.getAttributeNames();
|
||||
assertTrue(names.contains("a"));
|
||||
assertTrue(names.contains("b"));
|
||||
assertTrue(names.contains("c"));
|
||||
assertFalse(names.contains("z"));
|
||||
assertFalse(names.contains("y"));
|
||||
assertFalse(names.contains("x"));
|
||||
|
||||
assertEquals("1", root.getAttribute("a"));
|
||||
assertEquals("2", root.getAttribute("b"));
|
||||
assertEquals("3", root.getAttribute("c"));
|
||||
assertNull(root.getAttribute("z"));
|
||||
assertNull(root.getAttribute("y"));
|
||||
assertNull(root.getAttribute("x"));
|
||||
|
||||
XmlNode[] first = root.getChildren().toArray(new XmlNode[1]);
|
||||
assertEquals(1, first.length);
|
||||
assertEquals("z", first[0].getName());
|
||||
|
||||
XmlNode[] second = first[0].getChildren().toArray(new XmlNode[1]);
|
||||
assertEquals(1, second.length);
|
||||
assertEquals("y", second[0].getName());
|
||||
|
||||
XmlNode[] third = second[0].getChildren().toArray(new XmlNode[1]);
|
||||
assertEquals(1, third.length);
|
||||
assertEquals("x", third[0].getName());
|
||||
|
||||
assertEquals(0, third[0].getChildCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* A test for the {@link XmlParser#parse(java.io.Reader)} method.
|
||||
*
|
||||
* @throws SAXException If a SAX error occurs.
|
||||
* @throws IOException If an I/O error occurs.
|
||||
*/
|
||||
@Test
|
||||
public void testParseReader() throws SAXException, IOException {
|
||||
XmlParser parser = new XmlParser();
|
||||
Reader reader = new StringReader("<alphabet><a>1</a><b>2</b><c>3</c></alphabet>");
|
||||
XmlNode root = parser.parse(reader);
|
||||
|
||||
assertEquals(root.getName(), "alphabet");
|
||||
assertEquals(root.getAttributeCount(), 0);
|
||||
assertEquals(root.getChildCount(), 3);
|
||||
assertFalse(root.hasValue());
|
||||
|
||||
XmlNode[] children = root.getChildren().toArray(new XmlNode[3]);
|
||||
|
||||
assertEquals(children[0].getName(), "a");
|
||||
assertEquals(children[1].getName(), "b");
|
||||
assertEquals(children[2].getName(), "c");
|
||||
|
||||
assertEquals(children[0].getValue(), "1");
|
||||
assertEquals(children[1].getValue(), "2");
|
||||
assertEquals(children[2].getValue(), "3");
|
||||
|
||||
for (int index = 0; index < 3; index++) {
|
||||
assertTrue(children[index].hasValue());
|
||||
assertEquals(children[index].getAttributeCount(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user