NCBI C++ ToolKit
ncbi_java.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: ncbi_java.cpp 87307 2019-08-16 16:59:06Z vasilche $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Michael Kholodov
27  *
28  * File Description: Java toolkit specifics.
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 #include <corelib/impl/ncbi_java.h>
34 
35 #include <assert.h>
36 //#include <jni.h>
37 #include <cstdlib>
38 
39 #include <corelib/ncbiapp_api.hpp>
40 #include <corelib/ncbi_toolkit.hpp>
41 
43 
44 JavaVM* CJniUtil::sm_JVM = NULL;
45 INcbiToolkit_LogHandler* CJniUtil::sm_logHandler = NULL;
46 
47 /////////////////////////////////////////////////////////////////////
48 // Custom log hanlder implementation
49 //
50 class CJavaLogHandler: public INcbiToolkit_LogHandler
51 {
52 public:
53 
54  CJavaLogHandler(jobject logger);
55  virtual ~CJavaLogHandler();
56 
57  virtual void Post(const CNcbiToolkit_LogMessage& msg);
58 
59 private:
60  jobject GetLevel(JNIEnv* env, CNcbiToolkit_LogMessage::ESeverity severity);
61 
62 private:
63 
64  const int PARAM_COUNT;
65 
66  jobject m_logger;
67 
69  jmethodID m_Logger_logId;
70 
72  jmethodID m_LogRecord_ctorId;
74 
75  jclass m_Level_class;
76  jfieldID m_Level_SevereId;
78  jfieldID m_Level_InfoId;
79  jfieldID m_Level_ConfigId;
80  jfieldID m_Level_FineId;
81  jfieldID m_Level_FinerId;
82  jfieldID m_Level_FinestId;
83 
85 };
86 
88 : PARAM_COUNT(6)
89 {
90  JNIEnv *env = CJniUtil::GetEnv();
91 
92  // Obtain global ref to the logger
93  m_logger = env->NewGlobalRef(logger);
95  "CJavaLogHandler ctor: could not create global logger object reference");
96 
97  jclass clazz;
98 
99  // Cache Logger metainfo
100  clazz = env->FindClass("java/util/logging/Logger");
101  JAVA_VALIDATE(clazz != NULL,
102  "CJavaLogHandler ctor: java Logger class could not be found");
103 
104  m_Logger_class = (jclass)env->NewGlobalRef(clazz);
106  "CJavaLogHandler ctor: could not create global Logger reference");
107 
108 
109  m_Logger_logId = env->GetMethodID(clazz, "log", "(Ljava/util/logging/LogRecord;)V");
111  "CJavaLogHandler ctor: java Logger method log(LogRecord) ID could not be returned");
112 
113  env->DeleteLocalRef(clazz);
114 
115  // Cache LogRecord metainfo
116  clazz = env->FindClass("java/util/logging/LogRecord");
117  JAVA_VALIDATE(clazz != NULL,
118  "CJavaLogHandler ctor: java LogRecord class could not be found");
119 
120  m_LogRecord_class = (jclass)env->NewGlobalRef(clazz);
122  "CJavaLogHandler ctor: could not create global LogRecord reference");
123 
124 
125  m_LogRecord_ctorId = env->GetMethodID(clazz, "<init>",
126  "(Ljava/util/logging/Level;Ljava/lang/String;)V");
128  "CJavaLogHandler ctor: java LogRecord constructor ID could not be returned");
129 
130  m_LogRecord_setParametersId = env->GetMethodID(clazz, "setParameters",
131  "([Ljava/lang/Object;)V");
133  "CJavaLogHandler ctor: java LogRecord setParameters ID could not be returned");
134 
135  env->DeleteLocalRef(clazz);
136 
137  // Cache Level metainfo
138  clazz = env->FindClass("java/util/logging/Level");
139  JAVA_VALIDATE(clazz != NULL,
140  "CJavaLogHandler ctor: java Level class could not be found");
141 
142  m_Level_class = (jclass)env->NewGlobalRef(clazz);
144  "CJavaLogHandler ctor: could not create global Level reference");
145 
146  m_Level_SevereId = env->GetStaticFieldID(m_Level_class,
147  "SEVERE", "Ljava/util/logging/Level;");
149  "CJavaLogHandler ctor: Level.SEVERE not found");
150 
151  m_Level_WarningId = env->GetStaticFieldID(m_Level_class,
152  "WARNING", "Ljava/util/logging/Level;");
154  "CJavaLogHandler ctor: Level.WARNING not found");
155 
156  m_Level_InfoId = env->GetStaticFieldID(m_Level_class,
157  "INFO", "Ljava/util/logging/Level;");
159  "CJavaLogHandler ctor: Level.INFO not found");
160 
161  m_Level_ConfigId = env->GetStaticFieldID(m_Level_class,
162  "CONFIG", "Ljava/util/logging/Level;");
164  "CJavaLogHandler ctor: Level.CONFIG not found");
165 
166  m_Level_FineId = env->GetStaticFieldID(m_Level_class,
167  "FINE", "Ljava/util/logging/Level;");
169  "CJavaLogHandler ctor: Level.FINE not found");
170 
171  m_Level_FinerId = env->GetStaticFieldID(m_Level_class,
172  "FINER", "Ljava/util/logging/Level;");
174  "CJavaLogHandler ctor: Level.FINER not found");
175 
176  m_Level_FinestId = env->GetStaticFieldID(m_Level_class,
177  "FINEST", "Ljava/util/logging/Level;");
179  "CJavaLogHandler ctor: Level.FINEST not found");
180 
181  // Cache String metainfo
182  clazz = env->FindClass("java/lang/String");
183  JAVA_VALIDATE(clazz != NULL,
184  "CJavaLogHandler ctor: java String class could not be found");
185 
186  m_String_class = (jclass)env->NewGlobalRef(clazz);
188  "CJavaLogHandler ctor: could not create global String reference");
189 
190  env->DeleteLocalRef(clazz);
191 }
192 
194 {
195 }
196 
197 jobject CJavaLogHandler::GetLevel(JNIEnv* env, CNcbiToolkit_LogMessage::ESeverity severity)
198 {
199  jobject level = NULL;
200  switch(severity)
201  {
202  case eDiag_Info:
203  level = env->GetStaticObjectField(m_Level_class, m_Level_InfoId);
204  break;
205  case eDiag_Warning:
206  level = env->GetStaticObjectField(m_Level_class, m_Level_WarningId);
207  break;
208  case eDiag_Error:
209  case eDiag_Critical:
210  case eDiag_Fatal:
211  level = env->GetStaticObjectField(m_Level_class, m_Level_SevereId);
212  break;
213  case eDiag_Trace:
214  level = env->GetStaticObjectField(m_Level_class, m_Level_FineId);
215  break;
216  default:
217  level = env->GetStaticObjectField(m_Level_class, m_Level_InfoId);
218  break;
219  }
220 
221  return level;
222 }
223 
224 void CJavaLogHandler::Post(const CNcbiToolkit_LogMessage& msg)
225 {
226  JNIEnv *env = CJniUtil::GetEnv();
227 
228  // Create a LogRecord object
229  jobject level = GetLevel(env, msg.Severity());
230  JAVA_VALIDATE(level != NULL, "CJavaLogHandler::Post(): NULL Level returned");
231 
232  jstring jstr = env->NewStringUTF(msg.Message().c_str());
233  jobject lr = env->NewObject(m_LogRecord_class, m_LogRecord_ctorId, level, jstr);
234  JAVA_VALIDATE(lr != NULL, "CJavaLogHandler::Post(): could not create LogRecord object");
235 
236  // Create parameter array and fill it out from msg
237  jobjectArray params = env->NewObjectArray(PARAM_COUNT, m_String_class, NULL);
238 
239  jstr = env->NewStringUTF("1"); // Version of the parameter set
240  env->SetObjectArrayElement(params, 0, jstr);
241 
242  jstr = env->NewStringUTF(NStr::IntToString(msg.Severity()).c_str());
243  env->SetObjectArrayElement(params, 1, jstr);
244 
245  jstr = env->NewStringUTF(NStr::IntToString(msg.ErrCode()).c_str());
246  env->SetObjectArrayElement(params, 2, jstr);
247 
248  jstr = env->NewStringUTF(NStr::IntToString(msg.ErrSubCode()).c_str());
249  env->SetObjectArrayElement(params, 3, jstr);
250 
251  jstr = env->NewStringUTF(msg.File().c_str());
252  env->SetObjectArrayElement(params, 4, jstr);
253 
254  jstr = env->NewStringUTF(NStr::Int8ToString(msg.Line()).c_str());
255  env->SetObjectArrayElement(params, 5, jstr);
256 
257  // Call LogRecord.setParameters(Object[] params)
258  env->CallVoidMethod(lr, m_LogRecord_setParametersId, params);
260 
261 
262  // Call Logger.log(LogRecord lr)
263  env->CallVoidMethod(m_logger, m_Logger_logId, lr);
265 }
266 
267 /////////////////////////////////////////////////////////////////////
268 // CJniUtil implementation
269 //
270 
271 void CJniUtil::SetJVM(JavaVM* vm)
272 {
273  sm_JVM = vm;
274 }
275 
276 JNIEnv* CJniUtil::GetEnv(void)
277 {
278  JNIEnv *env = NULL;
279  switch(sm_JVM->GetEnv((void**)&env, JAVA_CURRENT_VERSION))
280  {
281  case JNI_EVERSION:
282  JAVA_ABORT("Requested Java version not supported");
283  break;
284  case JNI_EDETACHED:
285  if (sm_JVM->AttachCurrentThread((void **)&env, NULL) != 0 )
286  {
287  JAVA_ABORT("Could not attach native thread");
288  }
289  break;
290  case JNI_OK:
291  //printf("%s\n", "In GetJNIEnv - JNI_OK");
292  break;
293  default:
294  JAVA_ABORT("Unknown return code from g_GetJNIEnv");
295  break;
296  }
297  assert(env != NULL);
298 
299  return env;
300 }
301 
302 void CJniUtil::ThrowJavaException(const char *clsName, const char* msg)
303 {
304  JNIEnv *env = GetEnv();
305  jclass newExcCls = env->FindClass(clsName);
306  if (newExcCls != 0)
307  env->ThrowNew(newExcCls, msg);
308  else
309  JAVA_FATAL_ERROR("CJniUtil::ThrowJavaException(): requested exception class not found");
310 }
311 
312 void CJniUtil::JavaFatalError(const char* msg)
313 {
314  JNIEnv *env = GetEnv();
315  env->ExceptionDescribe();
316  env->FatalError(msg);
317 }
318 
320 {
321  JNIEnv *env = GetEnv();
322  env->ExceptionDescribe();
323 }
324 
325 INcbiToolkit_LogHandler* CJniUtil::GetLogHandler()
326 {
327  return sm_logHandler;
328 }
329 
330 void CJniUtil::SetLogHandler(jobject logger)
331 {
332  sm_logHandler = new CJavaLogHandler(logger);
333 }
334 
335 char** CJniUtil::CreateCStyleArgs(JNIEnv *env, jstring progName, jobjectArray argArray)
336 {
337  char **argv;
338 
339  int argc = env->GetArrayLength(argArray);
340  argv = new char* [argc+1];
341 
342  const char *cn = env->GetStringUTFChars(progName, 0);
343  argv[0] = new char[strlen(cn) + 1];
344  strcpy(argv[0], cn);
345 
346  for( int i = 0; i < argc; ++i)
347  {
348  jstring s = (jstring)env->GetObjectArrayElement(argArray, i);
349  const char* p = env->GetStringUTFChars(s, 0);
350  argv[i+1] = new char[strlen(p) + 1];
351  strcpy(argv[i+1], p);
352  }
353 
354  // Release java strings
355  for( int i = 0; i < argc; ++i)
356  {
357  jstring s = (jstring)env->GetObjectArrayElement(argArray, i);
358  env->ReleaseStringUTFChars(s, argv[i+1]);
359  }
360 
361  env->ReleaseStringUTFChars(progName, cn);
362  return argv;
363 }
364 
366 {
367  jobject props = NULL;
368  jclass propsClass;
369  jmethodID midCtor;
370  jmethodID midSetProp;
371 
372  // Prep java objects
373  propsClass = env->FindClass("java/util/Properties");
374  if( propsClass == NULL )
375  return NULL;
376 
377  midCtor = env->GetMethodID(propsClass, "<init>", "()V");
378  if( midCtor == NULL )
379  return NULL;
380 
381  props = env->NewObject(propsClass, midCtor);
382  if( props == NULL )
383  return NULL;
384 
385  midSetProp = env->GetMethodID(propsClass, "setProperty",
386  "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;");
387  if( midSetProp == NULL )
388  return NULL;
389 
390  // Process arguments
391  vector<CRef<CArgValue> > ncbiArgs = app->GetArgs().GetAll();
392  vector<CRef<CArgValue> >::iterator i = ncbiArgs.begin();
393  for( ; i != ncbiArgs.end(); ++i )
394  {
395  string name = (*i)->GetName();
396  jstring key = env->NewStringUTF(name.c_str());
397  jstring val = NULL;
398  if( (*i)->HasValue() )
399  val = env->NewStringUTF((*i)->AsString().c_str());
400 
401  env->CallObjectMethod(props, midSetProp, key, val);
402  }
403  return props;
404 }
405 
407 
408 //////////////////////////////////////////////////////////////////////////////
409 // Java native calls implementation
410 //
412  (JNIEnv *env, jclass, jobject logger)
413 {
415 
416  CJniUtil::SetLogHandler(logger);
417 }
418 
420  (JNIEnv *env, jclass, jobjectArray argArray, jstring progName)
421 {
423 
424  // Get command line
425  try
426  {
427  int argc = env->GetArrayLength(argArray);
428  char **argv = CJniUtil::CreateCStyleArgs(env, progName, argArray);
429 
430  NcbiToolkit_Init(argc + 1, argv, 0, CJniUtil::GetLogHandler());
431 
432  // Release strings
433  for( int i = 0; i < argc + 1; ++i)
434  {
435  delete argv[i];
436  }
437 
438  delete argv;
439  }
440  catch(exception& e)
441  {
442  CJniUtil::ThrowJavaException("java/lang/RuntimeException", e.what());
443  }
444 }
445 
447  (JNIEnv *env, jclass, jstring s)
448 {
449  const char* p = env->GetStringUTFChars(s, 0);
450  LOG_POST(p);
451  //ERR_POST(p);
452  env->ReleaseStringUTFChars(s, p);
453 }
454 
455 /////////////////////////////////////////////////////////////////////
456 // Jni OnLoad implementation
457 //
458 JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
459 {
461 
462  CJniUtil::SetJVM(jvm);
463 
464  return JAVA_CURRENT_VERSION;
465 }
466 
Char * progName
Definition: bzip2.c:208
jmethodID m_Logger_logId
Definition: ncbi_java.cpp:69
jfieldID m_Level_FinerId
Definition: ncbi_java.cpp:81
jobject m_logger
Definition: ncbi_java.cpp:66
jclass m_Logger_class
Definition: ncbi_java.cpp:68
jfieldID m_Level_FineId
Definition: ncbi_java.cpp:80
jclass m_Level_class
Definition: ncbi_java.cpp:75
jmethodID m_LogRecord_ctorId
Definition: ncbi_java.cpp:72
CJavaLogHandler(jobject logger)
Definition: ncbi_java.cpp:87
virtual ~CJavaLogHandler()
Definition: ncbi_java.cpp:193
jfieldID m_Level_SevereId
Definition: ncbi_java.cpp:76
jclass m_String_class
Definition: ncbi_java.cpp:84
jfieldID m_Level_WarningId
Definition: ncbi_java.cpp:77
virtual void Post(const CNcbiToolkit_LogMessage &msg)
Definition: ncbi_java.cpp:224
jfieldID m_Level_FinestId
Definition: ncbi_java.cpp:82
jobject GetLevel(JNIEnv *env, CNcbiToolkit_LogMessage::ESeverity severity)
Definition: ncbi_java.cpp:197
const int PARAM_COUNT
Definition: ncbi_java.cpp:64
jmethodID m_LogRecord_setParametersId
Definition: ncbi_java.cpp:73
jfieldID m_Level_ConfigId
Definition: ncbi_java.cpp:79
jclass m_LogRecord_class
Definition: ncbi_java.cpp:71
jfieldID m_Level_InfoId
Definition: ncbi_java.cpp:78
static char ** CreateCStyleArgs(JNIEnv *env, jstring progName, jobjectArray argArray)
Definition: ncbi_java.cpp:335
static INcbiToolkit_LogHandler * GetLogHandler()
Definition: ncbi_java.cpp:325
static void SetJVM(JavaVM *vm)
Definition: ncbi_java.cpp:271
static JNIEnv * GetEnv(void)
Definition: ncbi_java.cpp:276
static void ThrowJavaException(const char *clsName, const char *msg)
Definition: ncbi_java.cpp:302
static JavaVM * sm_JVM
Definition: ncbi_java.h:98
static jobject GetArgsFromNcbiApp(JNIEnv *env, CNcbiApplication *app)
Definition: ncbi_java.cpp:365
static INcbiToolkit_LogHandler * sm_logHandler
Definition: ncbi_java.h:97
static void SetLogHandler(jobject logger)
Definition: ncbi_java.cpp:330
static void DescribeJavaException(void)
Definition: ncbi_java.cpp:319
static void JavaFatalError(const char *msg)
Definition: ncbi_java.cpp:312
static HENV env
Definition: transaction2.c:38
virtual const CArgs & GetArgs(void) const
Get parsed command line arguments.
Definition: ncbiapp.cpp:305
vector< CRef< CArgValue > > GetAll(void) const
Get all available arguments.
Definition: ncbiargs.cpp:1864
#define NULL
Definition: ncbistd.hpp:225
#define LOG_POST(message)
This macro is deprecated and it's strongly recomended to move in all projects (except tests) to macro...
Definition: ncbidiag.hpp:226
@ eDiag_Trace
Trace message.
Definition: ncbidiag.hpp:657
@ eDiag_Info
Informational message.
Definition: ncbidiag.hpp:651
@ eDiag_Error
Error message.
Definition: ncbidiag.hpp:653
@ eDiag_Warning
Warning message.
Definition: ncbidiag.hpp:652
@ eDiag_Fatal
Fatal error – guarantees exit(or abort)
Definition: ncbidiag.hpp:655
@ eDiag_Critical
Critical error message.
Definition: ncbidiag.hpp:654
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
#define USING_NCBI_SCOPE
For using NCBI namespace code.
Definition: ncbistl.hpp:106
static string Int8ToString(Int8 value, TNumToStringFlags flags=0, int base=10)
Convert Int8 to string.
Definition: ncbistr.hpp:5159
static string IntToString(int value, TNumToStringFlags flags=0, int base=10)
Convert int to string.
Definition: ncbistr.hpp:5084
int i
const struct ncbi::grid::netcache::search::fields::KEY key
JNIEXPORT void JNICALL Java_org_ncbi_toolkit_NcbiToolkit_attachNcbiLogHandler0(JNIEnv *env, jclass, jobject logger)
Definition: ncbi_java.cpp:412
JNIEXPORT void JNICALL Java_org_ncbi_toolkit_NcbiToolkit_testLog(JNIEnv *env, jclass, jstring s)
Definition: ncbi_java.cpp:447
JNIEXPORT void JNICALL Java_org_ncbi_toolkit_NcbiToolkit_init0(JNIEnv *env, jclass, jobjectArray argArray, jstring progName)
Definition: ncbi_java.cpp:420
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved)
Definition: ncbi_java.cpp:458
Defines JNI specific macros and includes.
#define JAVA_CHECK_EXCEPTION(env)
Definition: ncbi_java.h:44
#define JAVA_CURRENT_VERSION
Definition: ncbi_java.h:42
#define JAVA_ABORT(msg)
Definition: ncbi_java.h:64
#define JAVA_FATAL_ERROR(msg)
Definition: ncbi_java.h:53
#define JAVA_VALIDATE(val, msg)
Definition: ncbi_java.h:58
void NcbiToolkit_Init(int argc, const TXChar *const *argv, const TXChar *const *envp, INcbiToolkit_LogHandler *log_handler)
This API provides an easy way to initialize NCBI C++ Toolkit internals to use the Toolkit from other ...
#define assert(x)
Definition: srv_diag.hpp:58
Modified on Thu Jun 13 17:28:29 2024 by modify_doxy.py rev. 669887