|
| 1 | +// Copyright 2020 Open Source Robotics Foundation, Inc. |
| 2 | +// |
| 3 | +// Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | +// you may not use this file except in compliance with the License. |
| 5 | +// You may obtain a copy of the License at |
| 6 | +// |
| 7 | +// http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | +// |
| 9 | +// Unless required by applicable law or agreed to in writing, software |
| 10 | +// distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | +// See the License for the specific language governing permissions and |
| 13 | +// limitations under the License. |
| 14 | + |
| 15 | +#include "org_ros2_rcljava_qos_QoSProfile.h" |
| 16 | + |
| 17 | +#include <jni.h> |
| 18 | +#include <limits> |
| 19 | + |
| 20 | +#include "rcljava_common/exceptions.hpp" |
| 21 | +#include "rmw/qos_profiles.h" |
| 22 | +#include "rmw/types.h" |
| 23 | + |
| 24 | +using rcljava_common::exceptions::rcljava_throw_exception; |
| 25 | + |
| 26 | +static void |
| 27 | +qos_set_duration(JNIEnv * env, uint64_t seconds, uint64_t nanos, jobject jqos, jfieldID fid) |
| 28 | +{ |
| 29 | + if (static_cast<uint64_t>(std::numeric_limits<jlong>::max()) < seconds) { |
| 30 | + // Throwing an exception here would be weird, as we cannot control the durability that was set |
| 31 | + // on all other endpoints in the network. Set jqos seconds to jlong max. |
| 32 | + seconds = static_cast<uint64_t>(std::numeric_limits<jlong>::max()); |
| 33 | + } |
| 34 | + if (static_cast<uint64_t>(std::numeric_limits<jlong>::max()) < nanos) { |
| 35 | + // This should never happen, as nanoseconds within a second can perfectly be represented |
| 36 | + // in a jlong. |
| 37 | + nanos = static_cast<uint64_t>(std::numeric_limits<jlong>::max()); |
| 38 | + } |
| 39 | + jclass duration_clazz = env->FindClass("java/time/Duration"); |
| 40 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 41 | + jmethodID factory_mid = env->GetStaticMethodID( |
| 42 | + duration_clazz, "ofSeconds", "(JJ)Ljava/time/Duration;"); |
| 43 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 44 | + jobject jduration = env->CallStaticObjectMethod( |
| 45 | + duration_clazz, factory_mid, static_cast<jlong>(seconds), static_cast<jlong>(nanos)); |
| 46 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 47 | + env->SetObjectField(jqos, fid, jduration); |
| 48 | +} |
| 49 | + |
| 50 | +static void |
| 51 | +qos_from_rcl(JNIEnv * env, const rmw_qos_profile_t & qos, jobject jqos) |
| 52 | +{ |
| 53 | + // TODO(ivanpauno): class and field lookup could be done at startup time |
| 54 | + jclass clazz = env->GetObjectClass(jqos); |
| 55 | + const char * history_class_path = "Lorg/ros2/rcljava/qos/policies/History;"; |
| 56 | + jfieldID history_fid = env->GetFieldID(clazz, "history", history_class_path); |
| 57 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 58 | + jfieldID depth_fid = env->GetFieldID(clazz, "depth", "I"); |
| 59 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 60 | + const char * reliability_class_path = "Lorg/ros2/rcljava/qos/policies/Reliability;"; |
| 61 | + jfieldID reliability_fid = env->GetFieldID(clazz, "reliability", reliability_class_path); |
| 62 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 63 | + const char * durability_class_path = "Lorg/ros2/rcljava/qos/policies/Durability;"; |
| 64 | + jfieldID durability_fid = env->GetFieldID(clazz, "durability", durability_class_path); |
| 65 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 66 | + jfieldID deadline_fid = env->GetFieldID(clazz, "deadline", "Ljava/time/Duration;"); |
| 67 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 68 | + jfieldID lifespan_fid = env->GetFieldID(clazz, "lifespan", "Ljava/time/Duration;"); |
| 69 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 70 | + const char * liveliness_class_path = "Lorg/ros2/rcljava/qos/policies/Liveliness;"; |
| 71 | + jfieldID liveliness_fid = env->GetFieldID(clazz, "liveliness", liveliness_class_path); |
| 72 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 73 | + jfieldID liveliness_lease_fid = env->GetFieldID( |
| 74 | + clazz, "livelinessLeaseDuration", "Ljava/time/Duration;"); |
| 75 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 76 | + jfieldID avoid_ros_conventions_fid = env->GetFieldID( |
| 77 | + clazz, "avoidROSNamespaceConventions", "Z"); |
| 78 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 79 | + |
| 80 | + jclass history_clazz = env->FindClass("org/ros2/rcljava/qos/policies/History"); |
| 81 | + jfieldID history_value_fid; |
| 82 | + switch (qos.history) { |
| 83 | + case RMW_QOS_POLICY_HISTORY_SYSTEM_DEFAULT: |
| 84 | + history_value_fid = env->GetStaticFieldID( |
| 85 | + history_clazz, "SYSTEM_DEFAULT", history_class_path); |
| 86 | + break; |
| 87 | + case RMW_QOS_POLICY_HISTORY_KEEP_LAST: |
| 88 | + history_value_fid = env->GetStaticFieldID( |
| 89 | + history_clazz, "KEEP_LAST", history_class_path); |
| 90 | + break; |
| 91 | + case RMW_QOS_POLICY_HISTORY_KEEP_ALL: |
| 92 | + history_value_fid = env->GetStaticFieldID( |
| 93 | + history_clazz, "KEEP_ALL", history_class_path); |
| 94 | + break; |
| 95 | + case RMW_QOS_POLICY_HISTORY_UNKNOWN: |
| 96 | + history_value_fid = env->GetStaticFieldID( |
| 97 | + history_clazz, "UNKNOWN", history_class_path); |
| 98 | + break; |
| 99 | + default: |
| 100 | + rcljava_throw_exception( |
| 101 | + env, "java/lang/IllegalStateException", "unknown history policy value"); |
| 102 | + break; |
| 103 | + } |
| 104 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 105 | + jobject history_value = env->GetStaticObjectField(history_clazz, history_value_fid); |
| 106 | + env->SetObjectField(jqos, history_fid, history_value); |
| 107 | + |
| 108 | + env->SetIntField(jqos, depth_fid, qos.depth); |
| 109 | + |
| 110 | + jclass reliability_clazz = env->FindClass("org/ros2/rcljava/qos/policies/Reliability"); |
| 111 | + jfieldID reliability_value_fid; |
| 112 | + switch (qos.reliability) { |
| 113 | + case RMW_QOS_POLICY_RELIABILITY_SYSTEM_DEFAULT: |
| 114 | + reliability_value_fid = env->GetStaticFieldID( |
| 115 | + reliability_clazz, "SYSTEM_DEFAULT", reliability_class_path); |
| 116 | + break; |
| 117 | + case RMW_QOS_POLICY_RELIABILITY_RELIABLE: |
| 118 | + reliability_value_fid = env->GetStaticFieldID( |
| 119 | + reliability_clazz, "RELIABLE", reliability_class_path); |
| 120 | + break; |
| 121 | + case RMW_QOS_POLICY_RELIABILITY_BEST_EFFORT: |
| 122 | + reliability_value_fid = env->GetStaticFieldID( |
| 123 | + reliability_clazz, "BEST_EFFORT", reliability_class_path); |
| 124 | + break; |
| 125 | + case RMW_QOS_POLICY_RELIABILITY_UNKNOWN: |
| 126 | + reliability_value_fid = env->GetStaticFieldID( |
| 127 | + reliability_clazz, "UNKNOWN", reliability_class_path); |
| 128 | + break; |
| 129 | + default: |
| 130 | + rcljava_throw_exception( |
| 131 | + env, "java/lang/IllegalStateException", "unknown reliability policy value"); |
| 132 | + break; |
| 133 | + } |
| 134 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 135 | + jobject reliability_value = env->GetStaticObjectField(reliability_clazz, reliability_value_fid); |
| 136 | + env->SetObjectField(jqos, reliability_fid, reliability_value); |
| 137 | + |
| 138 | + jclass durability_clazz = env->FindClass("org/ros2/rcljava/qos/policies/Durability"); |
| 139 | + jfieldID durability_value_fid; |
| 140 | + switch (qos.durability) { |
| 141 | + case RMW_QOS_POLICY_DURABILITY_SYSTEM_DEFAULT: |
| 142 | + durability_value_fid = env->GetStaticFieldID( |
| 143 | + durability_clazz, "SYSTEM_DEFAULT", durability_class_path); |
| 144 | + break; |
| 145 | + case RMW_QOS_POLICY_DURABILITY_TRANSIENT_LOCAL: |
| 146 | + durability_value_fid = env->GetStaticFieldID( |
| 147 | + durability_clazz, "TRANSIENT_LOCAL", durability_class_path); |
| 148 | + break; |
| 149 | + case RMW_QOS_POLICY_DURABILITY_VOLATILE: |
| 150 | + durability_value_fid = env->GetStaticFieldID( |
| 151 | + durability_clazz, "VOLATILE", durability_class_path); |
| 152 | + break; |
| 153 | + case RMW_QOS_POLICY_DURABILITY_UNKNOWN: |
| 154 | + durability_value_fid = env->GetStaticFieldID( |
| 155 | + durability_clazz, "UNKNOWN", durability_class_path); |
| 156 | + break; |
| 157 | + default: |
| 158 | + rcljava_throw_exception( |
| 159 | + env, "java/lang/IllegalStateException", "unknown durability policy value"); |
| 160 | + break; |
| 161 | + } |
| 162 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 163 | + jobject durability_value = env->GetStaticObjectField(durability_clazz, durability_value_fid); |
| 164 | + env->SetObjectField(jqos, durability_fid, durability_value); |
| 165 | + |
| 166 | + qos_set_duration(env, qos.deadline.sec, qos.deadline.nsec, jqos, deadline_fid); |
| 167 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 168 | + qos_set_duration(env, qos.lifespan.sec, qos.lifespan.nsec, jqos, lifespan_fid); |
| 169 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 170 | + qos_set_duration( |
| 171 | + env, qos.liveliness_lease_duration.sec, |
| 172 | + qos.liveliness_lease_duration.nsec, jqos, liveliness_lease_fid); |
| 173 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 174 | + |
| 175 | + jclass liveliness_clazz = env->FindClass("org/ros2/rcljava/qos/policies/Liveliness"); |
| 176 | + jfieldID liveliness_value_fid; |
| 177 | + switch (qos.liveliness) { |
| 178 | + case RMW_QOS_POLICY_LIVELINESS_SYSTEM_DEFAULT: |
| 179 | + liveliness_value_fid = env->GetStaticFieldID( |
| 180 | + liveliness_clazz, "SYSTEM_DEFAULT", liveliness_class_path); |
| 181 | + break; |
| 182 | + case RMW_QOS_POLICY_LIVELINESS_AUTOMATIC: |
| 183 | + liveliness_value_fid = env->GetStaticFieldID( |
| 184 | + liveliness_clazz, "AUTOMATIC", liveliness_class_path); |
| 185 | + break; |
| 186 | + case RMW_QOS_POLICY_LIVELINESS_MANUAL_BY_TOPIC: |
| 187 | + liveliness_value_fid = env->GetStaticFieldID( |
| 188 | + liveliness_clazz, "MANUAL_BY_TOPIC", liveliness_class_path); |
| 189 | + break; |
| 190 | + case RMW_QOS_POLICY_LIVELINESS_UNKNOWN: |
| 191 | + liveliness_value_fid = env->GetStaticFieldID( |
| 192 | + liveliness_clazz, "UNKNOWN", liveliness_class_path); |
| 193 | + break; |
| 194 | + default: |
| 195 | + rcljava_throw_exception( |
| 196 | + env, "java/lang/IllegalStateException", "unknown liveliness policy value"); |
| 197 | + break; |
| 198 | + } |
| 199 | + RCLJAVA_COMMON_CHECK_FOR_EXCEPTION(env); |
| 200 | + jobject liveliness_value = env->GetStaticObjectField(liveliness_clazz, liveliness_value_fid); |
| 201 | + env->SetObjectField(jqos, liveliness_fid, liveliness_value); |
| 202 | + |
| 203 | + env->SetBooleanField(jqos, avoid_ros_conventions_fid, qos.avoid_ros_namespace_conventions); |
| 204 | +} |
| 205 | + |
| 206 | +JNIEXPORT void JNICALL |
| 207 | +Java_org_ros2_rcljava_qos_QoSProfile_nativeFromRCL(JNIEnv * env, jobject jqos, jlong handle) |
| 208 | +{ |
| 209 | + auto * qos_profile = reinterpret_cast<rmw_qos_profile_t *>(handle); |
| 210 | + if (!handle) { |
| 211 | + rcljava_throw_exception( |
| 212 | + env, "java/lang/IllegalArgumentException", "rmw qos profile handle is NULL"); |
| 213 | + return; |
| 214 | + } |
| 215 | + qos_from_rcl(env, *qos_profile, jqos); |
| 216 | +} |
| 217 | + |
| 218 | +JNIEXPORT jlong JNICALL |
| 219 | +Java_org_ros2_rcljava_qos_QoSProfile_nativeGetHandleFromName( |
| 220 | + JNIEnv * env, jclass, jstring jprofile_name) |
| 221 | +{ |
| 222 | + const rmw_qos_profile_t * qos = NULL; |
| 223 | + const char * profile_name = env->GetStringUTFChars(jprofile_name, NULL); |
| 224 | + if (strcmp(profile_name, "default") == 0) { |
| 225 | + qos = &rmw_qos_profile_default; |
| 226 | + } |
| 227 | + if (strcmp(profile_name, "system_default") == 0) { |
| 228 | + qos = &rmw_qos_profile_system_default; |
| 229 | + } |
| 230 | + if (strcmp(profile_name, "sensor_data") == 0) { |
| 231 | + qos = &rmw_qos_profile_sensor_data; |
| 232 | + } |
| 233 | + if (strcmp(profile_name, "parameters") == 0) { |
| 234 | + qos = &rmw_qos_profile_parameters; |
| 235 | + } |
| 236 | + if (strcmp(profile_name, "services") == 0) { |
| 237 | + qos = &rmw_qos_profile_services_default; |
| 238 | + } |
| 239 | + if (strcmp(profile_name, "parameter_events") == 0) { |
| 240 | + qos = &rmw_qos_profile_parameter_events; |
| 241 | + } |
| 242 | + |
| 243 | + env->ReleaseStringUTFChars(jprofile_name, profile_name); |
| 244 | + if (qos) { |
| 245 | + return reinterpret_cast<jlong>(qos); |
| 246 | + } |
| 247 | + rcljava_throw_exception( |
| 248 | + env, "java/lang/IllegalArgumentException", "unexpected profile identifier"); |
| 249 | + return 0; |
| 250 | +} |
0 commit comments