~ubuntu-branches/debian/sid/subversion/sid

« back to all changes in this revision

Viewing changes to subversion/bindings/javahl/native/jniwrapper/jni_class_cache.cpp

  • Committer: Package Import Robot
  • Author(s): James McCoy
  • Date: 2015-08-07 21:32:47 UTC
  • mfrom: (0.2.15) (4.1.7 experimental)
  • Revision ID: package-import@ubuntu.com-20150807213247-ozyewtmgsr6tkewl
Tags: 1.9.0-1
* Upload to unstable
* New upstream release.
  + Security fixes
    - CVE-2015-3184: Mixed anonymous/authenticated path-based authz with
      httpd 2.4
    - CVE-2015-3187: svn_repos_trace_node_locations() reveals paths hidden
      by authz
* Add >= 2.7 requirement for python-all-dev Build-Depends, needed to run
  tests.
* Remove Build-Conflicts against ruby-test-unit.  (Closes: #791844)
* Remove patches/apache_module_dependency in favor of expressing the
  dependencies in authz_svn.load/dav_svn.load.
* Build-Depend on apache2-dev (>= 2.4.16) to ensure ap_some_authn_required()
  is available when building mod_authz_svn and Depend on apache2-bin (>=
  2.4.16) for runtime support.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/**
 
2
 * @copyright
 
3
 * ====================================================================
 
4
 *    Licensed to the Apache Software Foundation (ASF) under one
 
5
 *    or more contributor license agreements.  See the NOTICE file
 
6
 *    distributed with this work for additional information
 
7
 *    regarding copyright ownership.  The ASF licenses this file
 
8
 *    to you under the Apache License, Version 2.0 (the
 
9
 *    "License"); you may not use this file except in compliance
 
10
 *    with the License.  You may obtain a copy of the License at
 
11
 *
 
12
 *      http://www.apache.org/licenses/LICENSE-2.0
 
13
 *
 
14
 *    Unless required by applicable law or agreed to in writing,
 
15
 *    software distributed under the License is distributed on an
 
16
 *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 
17
 *    KIND, either express or implied.  See the License for the
 
18
 *    specific language governing permissions and limitations
 
19
 *    under the License.
 
20
 * ====================================================================
 
21
 * @endcopyright
 
22
 */
 
23
 
 
24
#include <stdexcept>
 
25
 
 
26
#include <apr_atomic.h>
 
27
 
 
28
#define SVN_JAVAHL_JNIWRAPPER_LOG(expr)
 
29
#include "jni_env.hpp"
 
30
#include "jni_globalref.hpp"
 
31
#include "jni_exception.hpp"
 
32
#include "jni_object.hpp"
 
33
#include "jni_string.hpp"
 
34
 
 
35
#include "jni_channel.hpp"
 
36
#include "jni_io_stream.hpp"
 
37
#include "jni_list.hpp"
 
38
#include "jni_string_map.hpp"
 
39
 
 
40
#include "../SubversionException.hpp"
 
41
#include "../AuthnCallback.hpp"
 
42
#include "../Credential.hpp"
 
43
#include "../ExternalItem.hpp"
 
44
#include "../EditorCallbacks.hpp"
 
45
 
 
46
namespace
 
47
{
 
48
/* This class behaves like a dumbed-down std:auto_ptr, but it
 
49
   implements atomic access and modification of the wrapped
 
50
   pointer. */
 
51
class ClassImplPtr
 
52
{
 
53
  typedef ::Java::Object::ClassImpl ClassImpl;
 
54
 
 
55
 public:
 
56
  /* Default constructor; initializes the wrapped pointer to NULL */
 
57
  explicit ClassImplPtr()
 
58
    : m_ptr(NULL)
 
59
  {}
 
60
 
 
61
  /* Initializing constructor; sets the wrapped pointer to PTR */
 
62
  explicit ClassImplPtr(ClassImpl* ptr)
 
63
    : m_ptr(ptr)
 
64
  {}
 
65
 
 
66
  /* Destructor deletes the object and resets the wrapped pointer to NULL. */
 
67
  ~ClassImplPtr()
 
68
    {
 
69
      delete static_cast<ClassImpl*>(
 
70
          apr_atomic_casptr(&m_ptr, NULL, get()));
 
71
    }
 
72
 
 
73
  /* Sets the wrapped pointer to PTR iff it is NULL, and returns the
 
74
     old value. */
 
75
  ClassImpl* test_and_set(ClassImpl* ptr)
 
76
    {
 
77
      return static_cast<ClassImpl*>(
 
78
          apr_atomic_casptr(&m_ptr, ptr, NULL));
 
79
    }
 
80
 
 
81
  /* Returns the current value of the the wrapped pointer. */
 
82
  ClassImpl* get() const
 
83
    {
 
84
      return static_cast<ClassImpl*>(
 
85
          apr_atomic_casptr(&m_ptr, NULL, NULL));
 
86
    }
 
87
 
 
88
private:
 
89
  // Non-copyable
 
90
  ClassImplPtr(const ClassImplPtr&);
 
91
  ClassImplPtr& operator=(const ClassImplPtr&);
 
92
 
 
93
  mutable volatile void* m_ptr;
 
94
};
 
95
} // anonymous namespace
 
96
 
 
97
 
 
98
namespace Java {
 
99
 
 
100
class ClassCacheImpl
 
101
{
 
102
 
 
103
  friend class ClassCache;
 
104
 
 
105
  // We only statically initialize a few of the common class wrappers.
 
106
  explicit ClassCacheImpl(Env env) :
 
107
 
 
108
#define JNIWRAPPER_INIT_CACHED_CLASS(M, C)     \
 
109
  m_impl_##M(new C::ClassImpl(env, env.FindClass(C::m_class_name)))
 
110
 
 
111
      JNIWRAPPER_INIT_CACHED_CLASS(object, Object),
 
112
      JNIWRAPPER_INIT_CACHED_CLASS(classtype, Class),
 
113
      JNIWRAPPER_INIT_CACHED_CLASS(throwable, Exception),
 
114
      JNIWRAPPER_INIT_CACHED_CLASS(string, String)
 
115
#undef JNIWRAPPER_INIT_CACHED_CLASS
 
116
    {}
 
117
 
 
118
  // We can't do this in the constructor above, because the satic
 
119
  // initializers will expect that ClassCache::m_impl is already set;
 
120
  // that doesn't happen until the constructor returns.
 
121
  void static_init(Env env)
 
122
    {
 
123
#define JNIWRAPPER_STATIC_CACHED_CLASS(M, C)            \
 
124
      C::static_init(env, m_impl_##M->get_class())
 
125
 
 
126
      // No-op JNIWRAPPER_STATIC_CACHED_CLASS(object, Object);
 
127
      JNIWRAPPER_STATIC_CACHED_CLASS(classtype, Class);
 
128
      JNIWRAPPER_STATIC_CACHED_CLASS(throwable, Exception);
 
129
      // No-op JNIWRAPPER_STATIC_CACHED_CLASS(string, String);
 
130
#undef JNIWRAPPER_STATIC_CACHED_CLASS
 
131
    }
 
132
 
 
133
  // The statically initialized calss wrappers are always defined and
 
134
  // therefore do not need atomic access.
 
135
#define JNIWRAPPER_DEFINE_CACHED_CLASS(M, C)            \
 
136
  std::auto_ptr<Object::ClassImpl> m_impl_##M;          \
 
137
  const Object::ClassImpl* get_##M(Env)                 \
 
138
    {                                                   \
 
139
      return m_impl_##M.get();                          \
 
140
    }
 
141
 
 
142
  JNIWRAPPER_DEFINE_CACHED_CLASS(object, Object)
 
143
  JNIWRAPPER_DEFINE_CACHED_CLASS(classtype, Class)
 
144
  JNIWRAPPER_DEFINE_CACHED_CLASS(throwable, Exception)
 
145
  JNIWRAPPER_DEFINE_CACHED_CLASS(string, String)
 
146
#undef JNIWRAPPER_DEFINE_CACHED_CLASS
 
147
 
 
148
  // All other class wrappers must be atomically initialized
 
149
#define JNIWRAPPER_DEFINE_CACHED_CLASS(M, C)                    \
 
150
  ClassImplPtr m_impl_##M;                                      \
 
151
  const Object::ClassImpl* get_##M(Env env)                     \
 
152
    {                                                           \
 
153
      Object::ClassImpl* pimpl = m_impl_##M.get();              \
 
154
      if (!pimpl)                                               \
 
155
        {                                                       \
 
156
          std::auto_ptr<Object::ClassImpl> tmp(                 \
 
157
              new C::ClassImpl(                                 \
 
158
                  env, env.FindClass(C::m_class_name)));        \
 
159
          pimpl = m_impl_##M.test_and_set(tmp.get());           \
 
160
          if (!pimpl)                                           \
 
161
            pimpl = tmp.release();                              \
 
162
        }                                                       \
 
163
      return pimpl;                                             \
 
164
    }
 
165
 
 
166
  JNIWRAPPER_DEFINE_CACHED_CLASS(exc_index_out_of_bounds,
 
167
                                 IndexOutOfBoundsException);
 
168
  JNIWRAPPER_DEFINE_CACHED_CLASS(exc_no_such_element,
 
169
                                 NoSuchElementException);
 
170
 
 
171
  JNIWRAPPER_DEFINE_CACHED_CLASS(iterator, BaseIterator);
 
172
 
 
173
  JNIWRAPPER_DEFINE_CACHED_CLASS(list, BaseImmutableList);
 
174
  JNIWRAPPER_DEFINE_CACHED_CLASS(array_list, BaseList);
 
175
 
 
176
  JNIWRAPPER_DEFINE_CACHED_CLASS(map, BaseImmutableMap);
 
177
  JNIWRAPPER_DEFINE_CACHED_CLASS(set, BaseImmutableMap::Set);
 
178
  JNIWRAPPER_DEFINE_CACHED_CLASS(map_entry, BaseImmutableMap::Entry);
 
179
  JNIWRAPPER_DEFINE_CACHED_CLASS(hash_map, BaseMap);
 
180
 
 
181
  JNIWRAPPER_DEFINE_CACHED_CLASS(input_stream, InputStream);
 
182
  JNIWRAPPER_DEFINE_CACHED_CLASS(output_stream, OutputStream);
 
183
 
 
184
  JNIWRAPPER_DEFINE_CACHED_CLASS(byte_buffer,
 
185
                                 ByteChannel::ByteBuffer);
 
186
 
 
187
  JNIWRAPPER_DEFINE_CACHED_CLASS(subversion_exception,
 
188
                                 ::JavaHL::SubversionException);
 
189
 
 
190
  JNIWRAPPER_DEFINE_CACHED_CLASS(authn_cb,
 
191
                                 ::JavaHL::AuthnCallback);
 
192
  JNIWRAPPER_DEFINE_CACHED_CLASS(authn_result,
 
193
                                 ::JavaHL::AuthnCallback::AuthnResult);
 
194
  JNIWRAPPER_DEFINE_CACHED_CLASS(authn_ssl_server_cert_failures,
 
195
                                 ::JavaHL::AuthnCallback::SSLServerCertFailures);
 
196
  JNIWRAPPER_DEFINE_CACHED_CLASS(authn_ssl_server_cert_info,
 
197
                                 ::JavaHL::AuthnCallback::SSLServerCertInfo);
 
198
  JNIWRAPPER_DEFINE_CACHED_CLASS(user_passwd_cb,
 
199
                                 ::JavaHL::UserPasswordCallback);
 
200
 
 
201
  JNIWRAPPER_DEFINE_CACHED_CLASS(credential,
 
202
                                 ::JavaHL::Credential);
 
203
  JNIWRAPPER_DEFINE_CACHED_CLASS(credential_kind,
 
204
                                 ::JavaHL::Credential::Kind);
 
205
 
 
206
  JNIWRAPPER_DEFINE_CACHED_CLASS(external_item,
 
207
                                 ::JavaHL::ExternalItem);
 
208
 
 
209
  JNIWRAPPER_DEFINE_CACHED_CLASS(editor_provide_base_cb,
 
210
                                 ::JavaHL::ProvideBaseCallback);
 
211
  JNIWRAPPER_DEFINE_CACHED_CLASS(editor_provide_base_cb_ret,
 
212
                                 ::JavaHL::ProvideBaseCallback::ReturnValue);
 
213
  JNIWRAPPER_DEFINE_CACHED_CLASS(editor_provide_props_cb,
 
214
                                 ::JavaHL::ProvidePropsCallback);
 
215
  JNIWRAPPER_DEFINE_CACHED_CLASS(editor_provide_props_cb_ret,
 
216
                                 ::JavaHL::ProvidePropsCallback::ReturnValue);
 
217
  JNIWRAPPER_DEFINE_CACHED_CLASS(editor_get_kind_cb,
 
218
                                 ::JavaHL::GetNodeKindCallback);
 
219
#undef JNIWRAPPER_DEFINE_CACHED_CLASS
 
220
};
 
221
 
 
222
 
 
223
ClassCacheImpl* ClassCache::m_impl = NULL;
 
224
 
 
225
void ClassCache::create()
 
226
{
 
227
  const char* exception_message = NULL;
 
228
 
 
229
  try
 
230
    {
 
231
      const Env env;
 
232
      m_impl = new ClassCacheImpl(env);
 
233
      m_impl->static_init(env);
 
234
    }
 
235
  catch (const SignalExceptionThrown&)
 
236
    {}
 
237
  catch (const std::exception& ex)
 
238
    {
 
239
      exception_message = ex.what();
 
240
    }
 
241
  catch (...)
 
242
    {
 
243
      exception_message = "Caught unknown C++ exception";
 
244
    }
 
245
 
 
246
  // Do not throw any more exceptions from here, so use the raw environment.
 
247
  ::JNIEnv* const jenv = Env().get();
 
248
  if (exception_message || jenv->ExceptionCheck())
 
249
    {
 
250
      jobject cause = jenv->ExceptionOccurred();
 
251
      if (cause)
 
252
        jenv->ExceptionClear();
 
253
 
 
254
      const jclass rtx = jenv->FindClass("java/lang/RuntimeException");
 
255
      const jmethodID ctor = jenv->GetMethodID(rtx, "<init>",
 
256
                                               "(Ljava/lang/String;"
 
257
                                               "Ljava/lang/Throwable;)V");
 
258
      if (!cause && exception_message)
 
259
        {
 
260
          const jstring msg = jenv->NewStringUTF(exception_message);
 
261
          cause = jenv->NewObject(rtx, ctor, msg, jthrowable(0));
 
262
        }
 
263
      const jstring reason =
 
264
        jenv->NewStringUTF("JavaHL native library initialization failed");
 
265
      const jobject exception = jenv->NewObject(rtx, ctor, reason, cause);
 
266
      jenv->Throw(jthrowable(exception));
 
267
    }
 
268
}
 
269
 
 
270
void ClassCache::destroy()
 
271
{
 
272
  ClassCacheImpl* const pimpl = m_impl;
 
273
  m_impl = NULL;
 
274
  delete pimpl;
 
275
}
 
276
 
 
277
#define JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(M)         \
 
278
const Object::ClassImpl* ClassCache::get_##M(Env env)   \
 
279
{                                                       \
 
280
  return m_impl->get_##M(env);                          \
 
281
}
 
282
 
 
283
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(object);
 
284
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(classtype);
 
285
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(throwable);
 
286
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(string);
 
287
 
 
288
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(exc_index_out_of_bounds);
 
289
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(exc_no_such_element);
 
290
 
 
291
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(list);
 
292
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(array_list);
 
293
 
 
294
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(map);
 
295
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(set);
 
296
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(iterator);
 
297
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(map_entry);
 
298
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(hash_map);
 
299
 
 
300
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(input_stream);
 
301
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(output_stream);
 
302
 
 
303
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(byte_buffer);
 
304
 
 
305
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(subversion_exception);
 
306
 
 
307
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(authn_cb);
 
308
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(authn_result);
 
309
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(authn_ssl_server_cert_failures);
 
310
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(authn_ssl_server_cert_info);
 
311
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(user_passwd_cb);
 
312
 
 
313
 
 
314
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(credential);
 
315
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(credential_kind);
 
316
 
 
317
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(external_item);
 
318
 
 
319
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(editor_provide_base_cb);
 
320
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(editor_provide_base_cb_ret);
 
321
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(editor_provide_props_cb);
 
322
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(editor_provide_props_cb_ret);
 
323
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(editor_get_kind_cb);
 
324
#undef JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR
 
325
 
 
326
} // namespace Java