Move jni interface classes from batphone repo

This commit is contained in:
Jeremy Lakeman 2014-02-12 13:07:31 +10:30
parent 37e4d65b2a
commit 99fb8b6108
17 changed files with 764 additions and 100 deletions

View File

@ -46,7 +46,7 @@ LOCAL_SRC_FILES:= $(SERVALD_SRC_FILES) $(SERVAL_BASE)version_servald.c
LOCAL_CFLAGS += $(SERVALD_LOCAL_CFLAGS) -Iserval-dna/nacl/include
LOCAL_LDLIBS := $(SERVALD_LOCAL_LDLIBS)
LOCAL_STATIC_LIBRARIES := $(SERVALD_LOCAL_STATIC_LIBRARIES)
LOCAL_MODULE:= serval
LOCAL_MODULE:= servald
include $(BUILD_SHARED_LIBRARY)
# Build libserval.so wrapper

View File

@ -169,16 +169,16 @@ int Throw(JNIEnv *env, const char *class, const char *msg)
/* JNI entry point to command line. See org.servalproject.servald.ServalD class for the Java side.
JNI method descriptor: "(Ljava/util/List;[Ljava/lang/String;)I"
*/
JNIEXPORT jint JNICALL Java_org_servalproject_servald_ServalD_rawCommand(JNIEnv *env, jobject UNUSED(this), jobject outv, jobjectArray args)
JNIEXPORT jint JNICALL Java_org_servalproject_servaldna_ServalDCommand_rawCommand(JNIEnv *env, jobject UNUSED(this), jobject outv, jobjectArray args)
{
struct cli_context context;
bzero(&context, sizeof(context));
// find jni results methods
if (!IJniResults){
IJniResults = (*env)->FindClass(env, "org/servalproject/servald/IJniResults");
IJniResults = (*env)->FindClass(env, "org/servalproject/servaldna/IJniResults");
if (IJniResults==NULL)
return Throw(env, "java/lang/IllegalStateException", "Unable to locate class org.servalproject.servald.IJniResults");
return Throw(env, "java/lang/IllegalStateException", "Unable to locate class org.servalproject.servaldna.IJniResults");
startResultSet = (*env)->GetMethodID(env, IJniResults, "startResultSet", "(I)V");
if (startResultSet==NULL)
return Throw(env, "java/lang/IllegalStateException", "Unable to locate method startResultSet");

View File

@ -1,56 +0,0 @@
package org.servalproject.servald;
import java.lang.reflect.*;
import java.util.Arrays;
import java.util.List;
import java.util.LinkedList;
import org.servalproject.servald.ServalD;
class ServalDTests
{
public static void main(String[] args)
{
try {
Method m = ServalDTests.class.getMethod(args[0], String[].class);
m.invoke(null, (Object) Arrays.copyOfRange(args, 1, args.length));
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
public static void repeat(String[] args)
{
int repeat = Integer.decode(args[0]);
ServalD servald = new ServalD();
for (int i = 0; i != repeat; ++i) {
servald.command(Arrays.copyOfRange(args, 1, args.length));
System.out.print(servald.status);
for (byte[] a: servald.outv) {
System.out.print(":");
System.out.print(new String(a));
}
System.out.println("");
}
System.exit(0);
}
public static void nullArg(String[] args)
{
ServalD servald = new ServalD();
for (int i = 0; i != args.length; ++i)
if ("(null)".equals(args[i]))
args[i] = null;
servald.command(Arrays.copyOfRange(args, 0, args.length));
System.out.print(servald.status);
for (byte[] a: servald.outv) {
System.out.print(":");
System.out.print(new String(a));
}
System.out.println("");
System.exit(0);
}
}

View File

@ -0,0 +1,126 @@
/**
* Copyright (C) 2011 The Serval Project
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
public abstract class AbstractId {
abstract int getBinarySize();
public static class InvalidHexException extends Exception {
private static final long serialVersionUID = 1L;
private InvalidHexException(AbstractId id, String message) {
super(id.getClass().getName() + ": " + message);
}
}
public static class InvalidBinaryException extends Exception {
private static final long serialVersionUID = 1L;
private InvalidBinaryException(AbstractId id, String message) {
super(id.getClass().getName() + ": " + message);
}
}
private final byte[] binary;
public AbstractId(String hex) throws InvalidHexException {
if (hex.length() != getBinarySize())
throw new InvalidHexException(this, "invalid length " + hex.length() + " (should be " + (getBinarySize() * 2) + ") of '" + hex + "'");
binary = new byte[getBinarySize()];
int j = 0;
for (int i = 0; i != binary.length; i++) {
int d1 = Character.digit(hex.charAt(j++), 16);
int d2 = Character.digit(hex.charAt(j++), 16);
if (d1 == -1 || d2 == -1)
throw new InvalidHexException(this, "non-hex digit in '" + hex + "'");
binary[i] = (byte) ((d1 << 4) | d2);
}
}
public AbstractId(ByteBuffer b) throws InvalidBinaryException {
this.binary = new byte[getBinarySize()];
try {
b.get(this.binary);
}
catch (BufferUnderflowException e) {
throw new InvalidBinaryException(this, "not enough bytes (expecting " + getBinarySize() + ")");
}
}
public AbstractId(byte[] binary) throws InvalidBinaryException {
if (binary.length != getBinarySize())
throw new InvalidBinaryException(this, "invalid number of bytes (" + binary.length + "), should be " + getBinarySize());
this.binary = binary;
}
@Override
public boolean equals(Object other) {
// must be the exact same type with the same binary contents to be considered equal
if (other.getClass() == this.getClass()) {
AbstractId oBinary = (AbstractId) other;
for (int i = 0; i < this.binary.length; i++)
if (this.binary[i] != oBinary.binary[i])
return false;
return true;
}
return false;
}
@Override
public int hashCode() {
int hashCode = 0;
for (int i = 0; i < this.binary.length; i++)
hashCode = (hashCode << 8 | hashCode >>> 24) ^ this.binary[i];
return hashCode;
}
public String toHex(int offset, int len) {
StringBuilder sb = new StringBuilder();
for (int i = offset; i < offset + len && i < binary.length; i++) {
sb.append(Character.forDigit(((binary[i]) & 0xf0) >> 4, 16));
sb.append(Character.forDigit((binary[i]) & 0x0f, 16));
}
return sb.toString().toUpperCase();
}
public String toHex(int len) {
return toHex(0, len);
}
public String toHex() {
return toHex(0, binary.length);
}
public String abbreviation() {
return toHex(0, 4);
}
@Override
public String toString() {
return toHex();
}
}

View File

@ -1,4 +1,4 @@
package org.servalproject.servald;
package org.servalproject.servaldna;
public abstract class AbstractJniResults implements IJniResults {

View File

@ -18,39 +18,27 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servald;
package org.servalproject.servaldna;
import java.util.List;
import java.util.LinkedList;
import java.nio.ByteBuffer;
class ServalD
{
int status;
List<byte[]> outv;
public class BundleId extends AbstractId {
static
{
String property = System.getProperty("java.library.path");
System.err.println("Attempting to load libservald.so from "+property);
System.loadLibrary("servald");
@Override
public int getBinarySize() {
return 32;
}
private static native int rawCommand(IJniResults outv, String[] args);
public void command(String... args)
{
this.outv = new LinkedList<byte[]>();
IJniResults results = new JniResultsList(outv);
this.status = this.rawCommand(results, args);
public BundleId(String hex) throws InvalidHexException {
super(hex);
}
public static void main(String[] args)
{
ServalD servald = new ServalD();
servald.command(args);
for (byte[] a: servald.outv) {
System.out.println(new String(a));
public BundleId(ByteBuffer b) throws InvalidBinaryException {
super(b);
}
System.exit(servald.status);
public BundleId(byte[] binary) throws InvalidBinaryException {
super(binary);
}
}

View File

@ -0,0 +1,44 @@
/**
* Copyright (C) 2011 The Serval Project
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
import java.nio.ByteBuffer;
public class BundleKey extends AbstractId {
@Override
public int getBinarySize() {
return 32;
}
public BundleKey(String hex) throws InvalidHexException {
super(hex);
}
public BundleKey(ByteBuffer b) throws InvalidBinaryException {
super(b);
}
public BundleKey(byte[] binary) throws InvalidBinaryException {
super(binary);
}
}

View File

@ -0,0 +1,46 @@
/**
* Copyright (C) 2012 Serval Project, Inc.
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
import java.nio.ByteBuffer;
public class FileHash extends AbstractId {
public static final int BINARY_SIZE = 64;
@Override
public int getBinarySize() {
return BINARY_SIZE;
}
public FileHash(String hex) throws InvalidHexException {
super(hex);
}
public FileHash(ByteBuffer b) throws InvalidBinaryException {
super(b);
}
public FileHash(byte[] binary) throws InvalidBinaryException {
super(binary);
}
}

View File

@ -1,4 +1,4 @@
package org.servalproject.servald;
package org.servalproject.servaldna;
public interface IJniResults {
public void startResultSet(int columns);

View File

@ -1,11 +1,11 @@
package org.servalproject.servald;
package org.servalproject.servaldna;
import java.util.List;
public class JniResultsList extends AbstractJniResults implements IJniResults {
final List<byte[]> list;
private byte[] empty = new byte[0];
JniResultsList(List<byte[]> list) {
public JniResultsList(List<byte[]> list) {
this.list = list;
}

View File

@ -0,0 +1,92 @@
/**
* Copyright (C) 2011 The Serval Project
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
import java.util.LinkedList;
public class ServalDCommand
{
private ServalDCommand(){
}
static
{
System.loadLibrary("servald");
}
/**
* Low-level JNI entry point into servald command line.
*
* @param results Interface that will receive each value from the command
* @param args The words to pass on the command line (ie, argv[1]...argv[n])
* @return The servald exit status code (normally 0 indicates success)
*/
private static native int rawCommand(IJniResults results, String[] args)
throws ServalDInterfaceError;
/**
* Common entry point into servald command line.
*
* @param callback
* Each result will be passed to callback.result(String)
* immediately.
* @param args
* The parameters as passed on the command line, eg: res =
* servald.command("config", "set", "debug", "peers");
* @return The servald exit status code (normally0 indicates success)
*/
public static synchronized int command(final IJniResults callback, String... args)
throws ServalDInterfaceError
{
return ServalDCommand.rawCommand(callback, args);
}
/**
* Common entry point into servald command line.
*
* @param args
* The parameters as passed on the command line, eg: res =
* servald.command("config", "set", "debug", "peers");
* @return An object containing the servald exit status code (normally0
* indicates success) and zero or more output fields that it would
* have sent to standard output if invoked via a shell command line.
*/
public static synchronized ServalDResult command(String... args)
throws ServalDInterfaceError
{
LinkedList<byte[]> results = new LinkedList<byte[]>();
int status = rawCommand(new JniResultsList(results), args);
return new ServalDResult(args, status, results.toArray(new byte[results.size()][]));
}
public static void main(String[] args)
{
LinkedList<byte[]> outv = new LinkedList<byte[]>();
IJniResults results = new JniResultsList(outv);
int status = rawCommand(results, args);
for (byte[] a: outv) {
System.out.println(new String(a));
}
System.exit(status);
}
}

View File

@ -0,0 +1,43 @@
/**
* Copyright (C) 2011 The Serval Project
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
import org.servalproject.servaldna.ServalDResult;
/**
* Thrown when a request to a servald JNI method fails. This typically means that the returned
* status is non-zero, or some other result was returned that indicated the operation failed.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
public class ServalDFailureException extends Exception
{
private static final long serialVersionUID = 1L;
public ServalDFailureException(String message, ServalDResult result) {
super(message + " for command: " + result.getCommandString());
}
public ServalDFailureException(String message) {
super(message);
}
}

View File

@ -0,0 +1,48 @@
/**
* Copyright (C) 2011 The Serval Project
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
/**
* Indicates an internal (coding) error in the JNI interface to servald. Typically encountered when
* unpacking the outv strings returned by a servald operation, and indicates that the C code in
* servald that constructs the outv array is not consistent with the Java code that unpacks the outv
* strings.
*/
public class ServalDInterfaceError extends Error
{
private static final long serialVersionUID = 1L;
public ServalDInterfaceError(String message, ServalDResult result) {
super(message + ": " + result);
}
public ServalDInterfaceError(String message, ServalDResult result, Throwable cause) {
super(message + ": " + result, cause);
}
public ServalDInterfaceError(ServalDResult result, Throwable cause) {
super("" + result, cause);
}
public ServalDInterfaceError(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -0,0 +1,217 @@
/**
* Copyright (C) 2011 The Serval Project
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/** Represents the result of invoking servald via the JNI command-line interface. The 'args'
* attribute contains a copy of the arguments that were passed to the call that produced this
* result, to facilitate diagnosis of failures and errors. The results of a call are an integer
* 'status' value (normally the process exit status) and a list of strings in 'outv', called "output
* fields". These strings must be interpreted depending on the operation that produced them.
*
* Many operations return information about their outcome as a sequence of key-value pairs of
* fields. The getField() method and variants offer an order-independent means to query these
* fields by key and optionally enforce a type on the value. If the operation produces output
* that is not in the key-value structure, then the caller simply avoids using these methods,
* and accesses the 'outv' array directly.
*
* @author Andrew Bettison <andrew@servalproject.com>
*/
public class ServalDResult
{
public static final int STATUS_ERROR = 255;
public final String[] args;
public final int status;
public final byte[][] outv;
private HashMap<String,byte[]> keyValue;
public ServalDResult(String[] args, int status, byte[][] outv) {
this.args = args;
this.status = status;
this.outv = outv;
this.keyValue = null;
}
public ServalDResult(ServalDResult orig) {
this.args = orig.args;
this.status = orig.status;
this.outv = orig.outv;
this.keyValue = orig.keyValue;
}
public String getCommandString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < this.args.length; i++) {
if (i > 0)
sb.append(' ');
sb.append(args[i]);
}
return sb.toString();
}
@Override
public String toString() {
String[] outvstr = new String[this.outv.length];
for (int i = 0; i != this.outv.length; ++i)
outvstr[i] = new String(this.outv[i]);
return this.getClass().getName() + "(args=" + Arrays.deepToString(this.args) + ", status=" + this.status + ", outv=" + Arrays.deepToString(outvstr) + ")";
}
public void failIfStatusError() throws ServalDFailureException {
if (this.status == STATUS_ERROR)
throw new ServalDFailureException("error exit status", this);
}
public void failIfStatusNonzero() throws ServalDFailureException {
if (this.status != 0)
throw new ServalDFailureException("non-zero exit status", this);
}
protected void makeKeyValueMap() {
if (this.keyValue == null) {
if (this.outv.length % 2 != 0)
throw new ServalDInterfaceError("odd number of fields", this);
this.keyValue = new HashMap<String,byte[]>();
for (int i = 0; i != this.outv.length; i += 2)
this.keyValue.put(new String(this.outv[i]), this.outv[i + 1]);
}
}
public Map<String,byte[]> getKeyValueMap() {
makeKeyValueMap();
return new HashMap<String,byte[]>(this.keyValue);
}
protected byte[] getFieldOrNull(String fieldName) {
makeKeyValueMap();
if (!this.keyValue.containsKey(fieldName))
return null;
return this.keyValue.get(fieldName);
}
protected byte[] getField(String fieldName) throws ServalDInterfaceError {
byte[] value = getFieldOrNull(fieldName);
if (value == null)
throw new ServalDInterfaceError("missing '" + fieldName + "' field", this);
return value;
}
public byte[] getFieldByteArray(String fieldName, byte[] defaultValue) {
byte[] value = getFieldOrNull(fieldName);
if (value == null)
return defaultValue;
return value;
}
public String getFieldString(String fieldName, String defaultValue) {
byte[] value = getFieldOrNull(fieldName);
if (value == null)
return defaultValue;
return new String(value);
}
public String getFieldString(String fieldName) throws ServalDInterfaceError {
return new String(getField(fieldName));
}
public String getFieldStringNonEmptyOrNull(String fieldName) throws ServalDInterfaceError {
String value = getFieldString(fieldName, "");
return value.length() == 0 ? null : value;
}
public long getFieldLong(String fieldName) throws ServalDInterfaceError {
String value = getFieldString(fieldName);
try {
return Long.valueOf(value);
}
catch (NumberFormatException e) {
throw new ServalDInterfaceError("field " + fieldName + "='" + value + "' is not of type long", this, e);
}
}
public int getFieldInt(String fieldName) throws ServalDInterfaceError {
String value = getFieldString(fieldName);
try {
return Integer.valueOf(value);
}
catch (NumberFormatException e) {
throw new ServalDInterfaceError("field " + fieldName + "='" + value + "' is not of type int", this, e);
}
}
public boolean getFieldBoolean(String fieldName) throws ServalDInterfaceError {
String value = getFieldString(fieldName);
try {
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes") || value.equalsIgnoreCase("on"))
return true;
if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no") || value.equalsIgnoreCase("off"))
return false;
return Integer.parseInt(value) != 0;
}
catch (NumberFormatException e) {
throw new ServalDInterfaceError("field " + fieldName + "='" + value + "' is not of type boolean", this, e);
}
}
public SubscriberId getFieldSubscriberId(String fieldName, SubscriberId defaultValue) throws ServalDInterfaceError {
byte[] value = getFieldOrNull(fieldName);
if (value == null)
return defaultValue;
String str = new String(value);
try {
return new SubscriberId(str);
}
catch (AbstractId.InvalidHexException e) {
throw new ServalDInterfaceError("field " + fieldName + "='" + str + "' is not a Bundle ID: " + e.getMessage(), this);
}
}
public SubscriberId getFieldSubscriberId(String fieldName) throws ServalDInterfaceError {
SubscriberId value = getFieldSubscriberId(fieldName, null);
if (value == null)
throw new ServalDInterfaceError("missing '" + fieldName + "' field", this);
return value;
}
public BundleId getFieldBundleId(String fieldName) throws ServalDInterfaceError {
String value = getFieldString(fieldName);
try {
return new BundleId(value);
}
catch (BundleId.InvalidHexException e) {
throw new ServalDInterfaceError("field " + fieldName + "='" + value + "' is not a Bundle ID: " + e.getMessage(), this, e);
}
}
public FileHash getFieldFileHash(String fieldName) throws ServalDInterfaceError {
String value = getFieldString(fieldName);
try {
return new FileHash(value);
}
catch (BundleId.InvalidHexException e) {
throw new ServalDInterfaceError("field " + fieldName + "='" + value + "' is not a file hash: " + e.getMessage(), this);
}
}
}

View File

@ -0,0 +1,72 @@
/**
* Copyright (C) 2012 Serval Project, Inc.
*
* This file is part of Serval Software (http://www.servalproject.org)
*
* Serval Software is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This source code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this source code; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package org.servalproject.servaldna;
import java.nio.ByteBuffer;
public class SubscriberId extends AbstractId {
public static final int BINARY_SIZE = 32;
@Override
public int getBinarySize() {
return BINARY_SIZE;
}
public SubscriberId(String hex) throws InvalidHexException {
super(hex);
}
public SubscriberId(ByteBuffer b) throws InvalidBinaryException {
super(b);
}
public SubscriberId(byte[] binary) throws InvalidBinaryException {
super(binary);
}
@Override
public String abbreviation() {
return "sid:" + toHex(6) + "*";
}
/** Return true iff this SID is a broadcast address.
*
* At the moment, a broadcast address is defined as one whose bits are all 1 except
* for the final 64 bits, which could be anything. This definition may change in
* future, so treat this code with a grain of salt.
*/
public boolean isBroadcast() {
return this.equals(broadcastSid);
}
public static SubscriberId broadcastSid;
static {
byte buff[] = new byte[BINARY_SIZE];
for (int i = 0; i < BINARY_SIZE; i++)
buff[i] = (byte) 0xff;
try {
broadcastSid = new SubscriberId(buff);
} catch (InvalidBinaryException e) {
// TODO log error?
}
}
}

View File

@ -0,0 +1,42 @@
package org.servalproject.test;
import org.servalproject.servaldna.ServalDCommand;
import org.servalproject.servaldna.ServalDResult;
import java.util.Arrays;
class ServalDTests
{
public static void main(String[] args)
{
try {
for (int i = 0; i != args.length; ++i)
if ("(null)".equals(args[i]))
args[i] = null;
int repeatCount=1;
if (args[0].equals("repeat")){
repeatCount = Integer.decode(args[1]);
args = Arrays.copyOfRange(args, 2, args.length);
}
while(repeatCount>0){
ServalDResult result = ServalDCommand.command(args);
System.out.print(result.status);
for (byte[] a: result.outv) {
System.out.print(":");
System.out.print(new String(a));
}
System.out.println("");
repeatCount--;
}
}
catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
System.exit(0);
}
}

View File

@ -24,7 +24,9 @@ source "${0%/*}/../testconfig.sh"
setup() {
setup_servald
executeOk_servald config set debug.verbose 1
executeOk_servald config \
set debug.verbose 1 \
set log.console.level debug
assert_echo_works
compile_java_classes
setup_servald_so
@ -33,10 +35,10 @@ setup() {
compile_java_classes() {
assert --message='Java compiler was detected by ./configure' [ "$JAVAC" ]
mkdir classes
assert $JAVAC -Xlint:unchecked -d classes "$servald_source_root"/java/org/servalproject/servald/*.java
assert [ -r classes/org/servalproject/servald/ServalD.class ]
assert [ -r classes/org/servalproject/servald/IJniResults.class ]
assert [ -r classes/org/servalproject/servald/ServalDTests.class ]
assert find "$servald_source_root"/java/ -name *.java | xargs $JAVAC -Xlint:unchecked -d classes
assert [ -r classes/org/servalproject/servaldna/ServalDCommand.class ]
assert [ -r classes/org/servalproject/servaldna/IJniResults.class ]
assert [ -r classes/org/servalproject/test/ServalDTests.class ]
}
# Make sure that the normal echo command-line works, without JNI.
@ -47,7 +49,7 @@ assert_echo_works() {
doc_Echo="Serval JNI echo Hello world"
test_Echo() {
executeOk java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalD 'echo' '-e' 'Hello,\ttab' 'world\0!'
executeOk java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servaldna.ServalDCommand 'echo' '-e' 'Hello,\ttab' 'world\0!'
assertStdoutIs -e 'Hello,\ttab\nworld\0!\n'
}
@ -64,14 +66,14 @@ test_Delim() {
doc_Repeat="Serval JNI repeated calls in same process"
test_Repeat() {
executeOk --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalDTests repeat 50 'echo' 'Hello,' 'world!'
executeOk --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.test.ServalDTests repeat 50 'echo' 'Hello,' 'world!'
assertStdoutLineCount '==' 50
assertStdoutGrep --matches=50 '^0:Hello,:world!$'
}
doc_NullArg="Serval JNI null arguments throw exception"
test_NullArg() {
execute --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalDTests nullArg 'echo' '(null)'
execute --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.test.ServalDTests 'echo' '(null)'
tfw_cat --stdout --stderr
assertExitStatus '!=' 0
assertStderrGrep 'NullPointerException: null element in argv'
@ -79,7 +81,7 @@ test_NullArg() {
doc_help="Serval JNI returns help text"
test_help() {
execute --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servald.ServalD 'help'
execute --core-backtrace java "-Djava.library.path=$LD_LIBRARY_PATH" -classpath "$PWD/classes" org.servalproject.servaldna.ServalDCommand 'help'
tfw_cat --stdout --stderr
assertExitStatus '==' 0
assertStdoutGrep 'Serval DNA version '