ルート情報を取得するクラス(JNI)
折角ルート情報を取得するクラスを作ったので、これをJavaのクラスとしても利用できるようにJNIで実装してみました。
いつもの様に
RotueInfo.java
package net; import java.util.Vector; public class RouteInfo { private int index = 0; private String dest = null; private String mask = null; private String gateway = null; private int type = 0; private int metric = 0; private boolean defaultGw = false; private boolean primaryGw = false; static { System.loadLibrary("jninet"); init(); } public RouteInfo() { } public String getDest() { return dest; } public String getMask() { return mask; } public String getGateway() { return gateway; } public int getIndex() { return index; } public int getType() { return type; } public int getMetric() { return metric; } public boolean isDefaultGateway() { return defaultGw; } public boolean isPrimaryGateway() { return primaryGw; } public boolean isSameRouteInfo(String dest, String mask, String gateway) { if ((dest == null) || (!dest.equals(this.dest))) return false; if ((mask == null) || (!mask.equals(this.mask))) return false; if ((gateway == null) || (!gateway.equals(this.gateway))) return false; return true; } public static RouteInfo getBestRoute(String dest, String mask, Vector<RouteInfo> table) { RouteInfo[] routeTable = null; if ((table != null) && (table.size() > 0)) { routeTable = new RouteInfo[table.size()]; for (int i = 0; i < table.size(); i++) { routeTable[i] = table.get(i); } } return getBestRoute(dest, mask, routeTable); } private static native void init(); public static native RouteInfo[] getRouteList(); public static native RouteInfo getBestRoute(String dest, String mask, RouteInfo[] table); }
を作ってコンパイルした後で、javahを使ってヘッダファイル作成します。
それから、JNIの実装として
jnirouteinfo.h
#ifndef _JNI_ROUTEINFO_CALL #define _JNI_ROUTEINFO_CALL #include <windows.h> #include "routeinfo.h" using namespace penguin; #include "net_RouteInfo.h" jclass ri_class; /* RouterInfo */ jmethodID ri_ctor; /* RouterInfo() */ jfieldID ri_indexID; /* RouterInfo.index */ jfieldID ri_destID; /* RouterInfo.dest */ jfieldID ri_maskID; /* RouterInfo.mask */ jfieldID ri_gatewayID; /* RouterInfo.gateway */ jfieldID ri_typeID; /* RouterInfo.type */ jfieldID ri_metricID; /* RouterInfo.metric */ jfieldID ri_defaultGwID; /* RouterInfo.defaultGw */ jfieldID ri_primaryGwID; /* RouterInfo.primaryGw */ #endif // _JNI_ROUTEINFO_CALL
と
jnirouteinfo.cpp
#include "jnirouteinfo.h" #include "jninet.h" jobject load_class(JNIEnv *env, RouteInfo info) { jobject netifObj = env->NewObject(ri_class, ri_ctor); env->SetIntField(netifObj, ri_indexID, info.getIndex()); env->SetObjectField(netifObj, ri_destID, stringToJString(env, info.getDest())); env->SetObjectField(netifObj, ri_maskID, stringToJString(env, info.getMask())); env->SetObjectField(netifObj, ri_gatewayID, stringToJString(env, info.getGateway())); env->SetIntField(netifObj, ri_typeID, info.getType()); env->SetIntField(netifObj, ri_metricID, info.getMetric()); env->SetBooleanField(netifObj, ri_defaultGwID, info.isDefaultGateway()); env->SetBooleanField(netifObj, ri_primaryGwID, info.isPrimaryGateway()); return netifObj; } RouteInfo load_value(JNIEnv *env, jobject rt_info) { unsigned long index = env->GetIntField(rt_info, ri_indexID); String dest = jStringToString(env, (jstring)env->GetObjectField(rt_info, ri_destID)); String mask = jStringToString(env, (jstring)env->GetObjectField(rt_info, ri_maskID)); String gateway = jStringToString(env, (jstring)env->GetObjectField(rt_info, ri_gatewayID));; unsigned long type = env->GetIntField(rt_info, ri_typeID); unsigned long metric = env->GetIntField(rt_info, ri_metricID); bool defaultGw = (env->GetBooleanField(rt_info, ri_defaultGwID) != 0) ? true : false; RouteInfo route_entry = RouteInfo(dest, mask, gateway, index, metric, defaultGw); return route_entry; } JNIEXPORT void JNICALL Java_net_RouteInfo_init(JNIEnv *env, jclass cls) { ri_class = (jclass)env->NewGlobalRef(cls); ri_indexID = env->GetFieldID(ri_class, "index", "I"); ri_destID = env->GetFieldID(ri_class, "dest", "Ljava/lang/String;"); ri_maskID = env->GetFieldID(ri_class, "mask", "Ljava/lang/String;"); ri_gatewayID = env->GetFieldID(ri_class, "gateway", "Ljava/lang/String;"); ri_typeID = env->GetFieldID(ri_class, "type", "I"); ri_metricID = env->GetFieldID(ri_class, "metric", "I"); ri_defaultGwID = env->GetFieldID(ri_class, "defaultGw", "Z"); ri_primaryGwID = env->GetFieldID(ri_class, "primaryGw", "Z"); ri_ctor = env->GetMethodID(ri_class, "<init>", "()V"); } JNIEXPORT jobjectArray JNICALL Java_net_RouteInfo_getRouteList(JNIEnv *env, jclass cls) { jobjectArray rt_list = NULL; route_list list = RouteInfo::getRouteList(); if (!list.empty()) { jsize rt_count = (jsize)list.size(); if (rt_count > 0) { rt_list = env->NewObjectArray(rt_count, ri_class, NULL); for (jsize i = 0; i < rt_count; i++) { RouteInfo info = list.at(i); jobject one_route = load_class(env, info); env->SetObjectArrayElement(rt_list, i, one_route); } } list.clear(); } return rt_list; } JNIEXPORT jobject JNICALL Java_net_RouteInfo_getBestRoute(JNIEnv *env, jclass cls, jstring dest, jstring mask, jobjectArray table) { jobject one_route = NULL; String dest_value = jStringToString(env, dest); String mask_value = jStringToString(env, mask); route_list route_table; if (table != NULL) { jsize len = env->GetArrayLength(table); for (jsize i = 0; i < len; i++) { jobject rt_entry = env->GetObjectArrayElement(table, i); RouteInfo entry = load_value(env, rt_entry); route_table.push_back(entry); } } RouteInfo info = RouteInfo::getBestRoute(dest_value, mask_value, route_table); if (info.getIndex() >= 0) { one_route = load_class(env, info); } return one_route; }
を実装します。
JNIのライブラリ(dll)をjninetで前のJNIライブラリと一つにまとめてしまったので、jStringToString()関数をそのままaddrinfo.cppからコピーして使うと、リンク時に同じ名前の関数が存在するということでエラーになってしまうため、
stringToJString()関数と共に、jninet.cppに移動して実装しました。
ちなみにjninet.cppは
String jStringToString(JNIEnv *env, jstring j_string) { const jchar *words = env->GetStringChars(j_string, NULL); _bstr_t orginal = _bstr_t((wchar_t *)words); env->ReleaseStringChars(j_string, words); String c_string = String((_TCHAR *)orginal); return c_string; } jstring stringToJString(JNIEnv *env, String c_string) { _bstr_t value = _bstr_t((_TCHAR *)c_string.c_str()); jstring j_string = env->NewString((const jchar *)((wchar_t *)value), (jsize)value.length()); return j_string; }
が実装されています。
jStringToString()関数とstringToJString()関数は、以前作ったjniifinfoでも利用可能なので、後日そちらも修正しておきます。