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
12
* http://www.apache.org/licenses/LICENSE-2.0
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
20
* ====================================================================
26
#include <apr_atomic.h>
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"
35
#include "jni_channel.hpp"
36
#include "jni_io_stream.hpp"
37
#include "jni_list.hpp"
38
#include "jni_string_map.hpp"
40
#include "../SubversionException.hpp"
41
#include "../AuthnCallback.hpp"
42
#include "../Credential.hpp"
43
#include "../ExternalItem.hpp"
44
#include "../EditorCallbacks.hpp"
48
/* This class behaves like a dumbed-down std:auto_ptr, but it
49
implements atomic access and modification of the wrapped
53
typedef ::Java::Object::ClassImpl ClassImpl;
56
/* Default constructor; initializes the wrapped pointer to NULL */
57
explicit ClassImplPtr()
61
/* Initializing constructor; sets the wrapped pointer to PTR */
62
explicit ClassImplPtr(ClassImpl* ptr)
66
/* Destructor deletes the object and resets the wrapped pointer to NULL. */
69
delete static_cast<ClassImpl*>(
70
apr_atomic_casptr(&m_ptr, NULL, get()));
73
/* Sets the wrapped pointer to PTR iff it is NULL, and returns the
75
ClassImpl* test_and_set(ClassImpl* ptr)
77
return static_cast<ClassImpl*>(
78
apr_atomic_casptr(&m_ptr, ptr, NULL));
81
/* Returns the current value of the the wrapped pointer. */
82
ClassImpl* get() const
84
return static_cast<ClassImpl*>(
85
apr_atomic_casptr(&m_ptr, NULL, NULL));
90
ClassImplPtr(const ClassImplPtr&);
91
ClassImplPtr& operator=(const ClassImplPtr&);
93
mutable volatile void* m_ptr;
95
} // anonymous namespace
103
friend class ClassCache;
105
// We only statically initialize a few of the common class wrappers.
106
explicit ClassCacheImpl(Env env) :
108
#define JNIWRAPPER_INIT_CACHED_CLASS(M, C) \
109
m_impl_##M(new C::ClassImpl(env, env.FindClass(C::m_class_name)))
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
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)
123
#define JNIWRAPPER_STATIC_CACHED_CLASS(M, C) \
124
C::static_init(env, m_impl_##M->get_class())
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
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) \
139
return m_impl_##M.get(); \
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
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) \
153
Object::ClassImpl* pimpl = m_impl_##M.get(); \
156
std::auto_ptr<Object::ClassImpl> tmp( \
158
env, env.FindClass(C::m_class_name))); \
159
pimpl = m_impl_##M.test_and_set(tmp.get()); \
161
pimpl = tmp.release(); \
166
JNIWRAPPER_DEFINE_CACHED_CLASS(exc_index_out_of_bounds,
167
IndexOutOfBoundsException);
168
JNIWRAPPER_DEFINE_CACHED_CLASS(exc_no_such_element,
169
NoSuchElementException);
171
JNIWRAPPER_DEFINE_CACHED_CLASS(iterator, BaseIterator);
173
JNIWRAPPER_DEFINE_CACHED_CLASS(list, BaseImmutableList);
174
JNIWRAPPER_DEFINE_CACHED_CLASS(array_list, BaseList);
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);
181
JNIWRAPPER_DEFINE_CACHED_CLASS(input_stream, InputStream);
182
JNIWRAPPER_DEFINE_CACHED_CLASS(output_stream, OutputStream);
184
JNIWRAPPER_DEFINE_CACHED_CLASS(byte_buffer,
185
ByteChannel::ByteBuffer);
187
JNIWRAPPER_DEFINE_CACHED_CLASS(subversion_exception,
188
::JavaHL::SubversionException);
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);
201
JNIWRAPPER_DEFINE_CACHED_CLASS(credential,
202
::JavaHL::Credential);
203
JNIWRAPPER_DEFINE_CACHED_CLASS(credential_kind,
204
::JavaHL::Credential::Kind);
206
JNIWRAPPER_DEFINE_CACHED_CLASS(external_item,
207
::JavaHL::ExternalItem);
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
223
ClassCacheImpl* ClassCache::m_impl = NULL;
225
void ClassCache::create()
227
const char* exception_message = NULL;
232
m_impl = new ClassCacheImpl(env);
233
m_impl->static_init(env);
235
catch (const SignalExceptionThrown&)
237
catch (const std::exception& ex)
239
exception_message = ex.what();
243
exception_message = "Caught unknown C++ exception";
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())
250
jobject cause = jenv->ExceptionOccurred();
252
jenv->ExceptionClear();
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)
260
const jstring msg = jenv->NewStringUTF(exception_message);
261
cause = jenv->NewObject(rtx, ctor, msg, jthrowable(0));
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));
270
void ClassCache::destroy()
272
ClassCacheImpl* const pimpl = m_impl;
277
#define JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(M) \
278
const Object::ClassImpl* ClassCache::get_##M(Env env) \
280
return m_impl->get_##M(env); \
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);
288
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(exc_index_out_of_bounds);
289
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(exc_no_such_element);
291
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(list);
292
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(array_list);
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);
300
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(input_stream);
301
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(output_stream);
303
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(byte_buffer);
305
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(subversion_exception);
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);
314
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(credential);
315
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(credential_kind);
317
JNIWRAPPER_IMPL_CLASS_CACHE_ACCESSOR(external_item);
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