summaryrefslogtreecommitdiff
path: root/subversion/bindings/javahl/native/JNIStackElement.cpp
blob: 2ca6c6e7f2fa5bfda3289cbc9f98f6b6feebb462 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/**
 * @copyright
 * ====================================================================
 *    Licensed to the Apache Software Foundation (ASF) under one
 *    or more contributor license agreements.  See the NOTICE file
 *    distributed with this work for additional information
 *    regarding copyright ownership.  The ASF licenses this file
 *    to you under the Apache License, Version 2.0 (the
 *    "License"); you may not use this file except in compliance
 *    with the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing,
 *    software distributed under the License is distributed on an
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 *    KIND, either express or implied.  See the License for the
 *    specific language governing permissions and limitations
 *    under the License.
 * ====================================================================
 * @endcopyright
 *
 * @file JNIStackElement.cpp
 * @brief Implementation of the class JNIStackElement
 */

#include "JNIStackElement.h"
#include "JNIUtil.h"
#include "JNIStringHolder.h"
#include "JNIThreadData.h"
#include <apr_strings.h>

/**
 * Create a new object and generate a log message,if requested
 * @param env       the JNI-environment
 * @param clazz     the class name of the method
 * @param method    the name of the method
 * @param jthis     the Java object for which the method is call
 */
JNIStackElement::JNIStackElement(JNIEnv *env, const char *clazz,
                                 const char *method, jobject jthis)
{
  JNIUtil::JNIInit(env);
  // Generating a log message is expensive.
  if (JNIUtil::getLogLevel() >= JNIUtil::entryLog)
    {
      jclass jlo = env->FindClass("java/lang/Object");
      if (JNIUtil::isJavaExceptionThrown())
        return;

      // The method id will not change during the time this library
      // is loaded, so it can be cached.
      static jmethodID mid = 0;
      if (mid == 0)
        {
          mid = env->GetMethodID(jlo, "toString", "()Ljava/lang/String;");
          if (JNIUtil::isJavaExceptionThrown())
            return;
        }

      *m_objectID = 0;

      if(jthis == NULL)
        {
          strcpy(m_objectID, "<static>");
        }
      else
        {
          // This will call java.lang.Object.toString, even when it is
          // overriden.
          jobject oStr = env->CallNonvirtualObjectMethod(jthis, jlo, mid);
          if (JNIUtil::isJavaExceptionThrown())
            return;

          // Copy the result to a buffer.
          JNIStringHolder name(reinterpret_cast<jstring>(oStr));
          strncat(m_objectID, name, JNIUtil::formatBufferSize -1);
          env->DeleteLocalRef(oStr);
        }

      // Release the Java string.
      env->DeleteLocalRef(jlo);

      // Remember the parameter for the exit of the method.
      m_clazz = clazz;
      m_method = method;

      // Generate the log message.
      char *buffer = JNIUtil::getFormatBuffer();
      apr_snprintf(buffer, JNIUtil::formatBufferSize,
                   "entry class %s method %s object %s", m_clazz, m_method,
                   m_objectID);
      JNIUtil::logMessage(buffer);
    }
  else
    {
      // Initialize the object cleanly.
      m_clazz = NULL;
      m_method = NULL;
      *m_objectID = 0;
    }
}

/**
 * Destroy an object and create a log message for the exit of the
 * method, if one was create for the entry.
 */
JNIStackElement::~JNIStackElement()
{
  if (m_clazz != NULL)
    {
      // Generate a log message.
      char *buffer = JNIUtil::getFormatBuffer();
      apr_snprintf(buffer, JNIUtil::formatBufferSize,
                   "exit class %s method %s object %s", m_clazz,
                   m_method, m_objectID);
      JNIUtil::logMessage(buffer);
    }
  JNIThreadData::popThreadData();
}