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 "NativeStream.hpp"
25
26 #include "jniwrapper/jni_stack.hpp"
27 #include "jniwrapper/jni_exception.hpp"
28
29 #include "svn_private_config.h"
30
31 namespace JavaHL {
32
33 // Class JavaHL::NativeInputStream
34
35 const char* const NativeInputStream::m_class_name =
36 JAVAHL_CLASS("/types/NativeInputStream");
37
~NativeInputStream()38 NativeInputStream::~NativeInputStream() {}
39
set_stream(svn_stream_t * stream)40 void NativeInputStream::set_stream(svn_stream_t* stream)
41 {
42 if (m_stream)
43 throw std::logic_error(_("Native input stream is already bound"));
44 m_stream = stream;
45 }
46
47 NativeInputStream*
get_self_unsafe(::Java::Env env,jobject jthis)48 NativeInputStream::get_self_unsafe(::Java::Env env, jobject jthis)
49 {
50 jfieldID fid_cppaddr = NULL;
51 const jlong cppaddr =
52 findCppAddrForJObject(jthis, &fid_cppaddr, m_class_name);
53 return reinterpret_cast<NativeInputStream*>(cppaddr);
54 }
55
56 NativeInputStream*
get_self(::Java::Env env,jobject jthis)57 NativeInputStream::get_self(::Java::Env env, jobject jthis)
58 {
59 NativeInputStream* self = get_self_unsafe(env, jthis);
60 if (!self)
61 ::Java::NullPointerException(env).raise(_("this [C++]"));
62 return self;
63 }
64
close(::Java::Env env,jobject jthis)65 void NativeInputStream::close(::Java::Env env, jobject jthis)
66 {
67 SVN_JAVAHL_CHECK(env, svn_stream_close(m_stream));
68 dispose(jthis);
69 }
70
mark_supported(::Java::Env env) const71 bool NativeInputStream::mark_supported(::Java::Env env) const
72 {
73 return svn_stream_supports_mark(m_stream);
74 }
75
mark(::Java::Env env)76 void NativeInputStream::mark(::Java::Env env)
77 {
78 if (!svn_stream_supports_mark(m_stream))
79 return;
80 SVN_JAVAHL_CHECK(env, svn_stream_mark(m_stream, &m_mark, pool.getPool()));
81 }
82
reset(::Java::Env env)83 void NativeInputStream::reset(::Java::Env env)
84 {
85 if (!svn_stream_supports_mark(m_stream))
86 return;
87 if (m_mark)
88 SVN_JAVAHL_CHECK(env, svn_stream_seek(m_stream, m_mark));
89 else
90 ::Java::IOException(env).raise(_("Invalid seek on native stream"));
91 }
92
read(::Java::Env env)93 jint NativeInputStream::read(::Java::Env env)
94 {
95 apr_size_t len = 1;
96 char byte;
97 SVN_JAVAHL_CHECK(env, svn_stream_read_full(m_stream, &byte, &len));
98 if (len == 0)
99 return -1; // EOF
100 if (len == 1)
101 return jint(byte & 0xff);
102 ::Java::IOException(env).raise(_("Read from native stream failed"));
103 return -1;
104 }
105
read(::Java::Env env,::Java::ByteArray::MutableContents & dst,jint offset,jint length)106 jint NativeInputStream::read(::Java::Env env,
107 ::Java::ByteArray::MutableContents& dst,
108 jint offset, jint length)
109 {
110 if (offset < 0 || length < 0 || offset + length > dst.length())
111 ::Java::IndexOutOfBoundsException(env).raise();
112 if (!dst.data())
113 ::Java::NullPointerException(env).raise();
114
115 apr_size_t len = length;
116 if (svn_stream_supports_partial_read(m_stream))
117 SVN_JAVAHL_CHECK(env, svn_stream_read2(m_stream,
118 dst.data() + offset, &len));
119 else
120 SVN_JAVAHL_CHECK(env, svn_stream_read_full(m_stream,
121 dst.data() + offset, &len));
122 if (len == 0)
123 return -1; // EOF
124 if (len <= length)
125 return jint(len);
126 ::Java::IOException(env).raise(_("Read from native stream failed"));
127 return -1;
128 }
129
skip(::Java::Env env,jlong count)130 jlong NativeInputStream::skip(::Java::Env env, jlong count)
131 {
132 const apr_size_t len = count;
133 SVN_JAVAHL_CHECK(env, svn_stream_skip(m_stream, len));
134 return count;
135 }
136
dispose(jobject jthis)137 void NativeInputStream::dispose(jobject jthis)
138 {
139 jfieldID fid_cppaddr = NULL;
140 SVNBase::dispose(jthis, &fid_cppaddr, m_class_name);
141 }
142
143
144 // Class JavaHL::NativeOutputStream
145
146 const char* const NativeOutputStream::m_class_name =
147 JAVAHL_CLASS("/types/NativeOutputStream");
148
~NativeOutputStream()149 NativeOutputStream::~NativeOutputStream() {}
150
set_stream(svn_stream_t * stream)151 void NativeOutputStream::set_stream(svn_stream_t* stream)
152 {
153 if (m_stream)
154 throw std::logic_error(_("Native output stream is already bound"));
155 m_stream = stream;
156 }
157
158 NativeOutputStream*
get_self_unsafe(::Java::Env env,jobject jthis)159 NativeOutputStream::get_self_unsafe(::Java::Env env, jobject jthis)
160 {
161 jfieldID fid_cppaddr = NULL;
162 const jlong cppaddr =
163 findCppAddrForJObject(jthis, &fid_cppaddr, m_class_name);
164 return reinterpret_cast<NativeOutputStream*>(cppaddr);
165 }
166
167 NativeOutputStream*
get_self(::Java::Env env,jobject jthis)168 NativeOutputStream::get_self(::Java::Env env, jobject jthis)
169 {
170 NativeOutputStream* self = get_self_unsafe(env, jthis);
171 if (!self)
172 ::Java::NullPointerException(env).raise(_("this [C++]"));
173 return self;
174 }
175
close(::Java::Env env,jobject jthis)176 void NativeOutputStream::close(::Java::Env env, jobject jthis)
177 {
178 SVN_JAVAHL_CHECK(env, svn_stream_close(m_stream));
179 dispose(jthis);
180 }
181
write(::Java::Env env,jint byte)182 void NativeOutputStream::write(::Java::Env env, jint byte)
183 {
184 const char data = char(byte & 0xff);
185 apr_size_t len = 1;
186 SVN_JAVAHL_CHECK(env, svn_stream_write(m_stream, &data, &len));
187 if (len != 1)
188 ::Java::IOException(env).raise(_("Write to native stream failed"));
189 }
190
write(::Java::Env env,const::Java::ByteArray::Contents & src,jint offset,jint length)191 void NativeOutputStream::write(::Java::Env env,
192 const ::Java::ByteArray::Contents& src,
193 jint offset, jint length)
194 {
195 if (offset < 0 || length < 0 || offset + length > src.length())
196 ::Java::IndexOutOfBoundsException(env).raise();
197 if (!src.data())
198 ::Java::NullPointerException(env).raise();
199
200 apr_size_t len = length;
201 SVN_JAVAHL_CHECK(env, svn_stream_write(m_stream, src.data() + offset, &len));
202 if (len != length)
203 ::Java::IOException(env).raise(_("Write to native stream failed"));
204 }
205
dispose(jobject jthis)206 void NativeOutputStream::dispose(jobject jthis)
207 {
208 jfieldID fid_cppaddr = NULL;
209 SVNBase::dispose(jthis, &fid_cppaddr, m_class_name);
210 }
211
212 } // namespace JavaHL
213
214
215 // Class JavaHL::NativeInputStream native method implementation
216 #include "../include/org_apache_subversion_javahl_types_NativeInputStream.h"
217
218 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_close(JNIEnv * jenv,jobject jthis)219 Java_org_apache_subversion_javahl_types_NativeInputStream_close(
220 JNIEnv* jenv, jobject jthis)
221 {
222 SVN_JAVAHL_JNI_TRY(NativeInputStream, close)
223 {
224 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeInputStream, self);
225 self->close(Java::Env(jenv), jthis);
226 }
227 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
228 }
229
230 JNIEXPORT jboolean JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_markSupported(JNIEnv * jenv,jobject jthis)231 Java_org_apache_subversion_javahl_types_NativeInputStream_markSupported(
232 JNIEnv* jenv, jobject jthis)
233 {
234 SVN_JAVAHL_JNI_TRY(NativeInputStream, markSupported)
235 {
236 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeInputStream, self);
237 self->mark_supported(Java::Env(jenv));
238 }
239 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
240 return false;
241 }
242
243 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_mark(JNIEnv * jenv,jobject jthis,jint)244 Java_org_apache_subversion_javahl_types_NativeInputStream_mark(
245 JNIEnv* jenv, jobject jthis, jint)
246 {
247 SVN_JAVAHL_JNI_TRY(NativeInputStream, mark)
248 {
249 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeInputStream, self);
250 self->mark(Java::Env(jenv));
251 }
252 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
253 }
254
255 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_reset(JNIEnv * jenv,jobject jthis)256 Java_org_apache_subversion_javahl_types_NativeInputStream_reset(
257 JNIEnv* jenv, jobject jthis)
258 {
259 SVN_JAVAHL_JNI_TRY(NativeInputStream, reset)
260 {
261 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeInputStream, self);
262 self->reset(Java::Env(jenv));
263 }
264 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
265 }
266
267 JNIEXPORT jint JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_read__(JNIEnv * jenv,jobject jthis)268 Java_org_apache_subversion_javahl_types_NativeInputStream_read__(
269 JNIEnv* jenv, jobject jthis)
270 {
271 SVN_JAVAHL_JNI_TRY(NativeInputStream, read)
272 {
273 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeInputStream, self);
274 return self->read(Java::Env(jenv));
275 }
276 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
277 return 0;
278 }
279
280 JNIEXPORT jint JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_read___3BII(JNIEnv * jenv,jobject jthis,jbyteArray jdst,jint joffset,jint jlength)281 Java_org_apache_subversion_javahl_types_NativeInputStream_read___3BII(
282 JNIEnv* jenv, jobject jthis, jbyteArray jdst, jint joffset, jint jlength)
283 {
284 SVN_JAVAHL_JNI_TRY(NativeInputStream, read)
285 {
286 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeInputStream, self);
287
288 const Java::Env env(jenv);
289 Java::ByteArray dst(env, jdst);
290 Java::ByteArray::MutableContents dst_contents(dst);
291
292 return self->read(env, dst_contents, joffset, jlength);
293 }
294 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
295 return 0;
296 }
297
298 JNIEXPORT jlong JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_skip(JNIEnv * jenv,jobject jthis,jlong jcount)299 Java_org_apache_subversion_javahl_types_NativeInputStream_skip(
300 JNIEnv* jenv, jobject jthis, jlong jcount)
301 {
302 SVN_JAVAHL_JNI_TRY(NativeInputStream, skip)
303 {
304 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeInputStream, self);
305 return self->skip(Java::Env(jenv), jcount);
306 }
307 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
308 return 0;
309 }
310
311 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeInputStream_finalize(JNIEnv * jenv,jobject jthis)312 Java_org_apache_subversion_javahl_types_NativeInputStream_finalize(
313 JNIEnv* jenv, jobject jthis)
314 {
315 SVN_JAVAHL_JNI_TRY(NativeInputStream, finalize)
316 {
317 JavaHL::NativeInputStream* native =
318 JavaHL::NativeInputStream::get_self_unsafe(Java::Env(jenv), jthis);
319 if (native != NULL)
320 native->finalize();
321 }
322 SVN_JAVAHL_JNI_CATCH;
323 }
324
325
326 // Class JavaHL::NativeOutputStream native method implementation
327 #include "../include/org_apache_subversion_javahl_types_NativeOutputStream.h"
328
329 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeOutputStream_close(JNIEnv * jenv,jobject jthis)330 Java_org_apache_subversion_javahl_types_NativeOutputStream_close(
331 JNIEnv* jenv, jobject jthis)
332 {
333 SVN_JAVAHL_JNI_TRY(NativeOutputStream, close)
334 {
335 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeOutputStream, self);
336 self->close(Java::Env(jenv), jthis);
337 }
338 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
339 }
340
341 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeOutputStream_write__I(JNIEnv * jenv,jobject jthis,jint byte)342 Java_org_apache_subversion_javahl_types_NativeOutputStream_write__I(
343 JNIEnv* jenv, jobject jthis, jint byte)
344 {
345 SVN_JAVAHL_JNI_TRY(NativeOutputStream, write)
346 {
347 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeOutputStream, self);
348 self->write(Java::Env(jenv), byte);
349 }
350 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
351 }
352
353 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeOutputStream_write___3BII(JNIEnv * jenv,jobject jthis,jbyteArray jsrc,jint joffset,jint jlength)354 Java_org_apache_subversion_javahl_types_NativeOutputStream_write___3BII(
355 JNIEnv* jenv, jobject jthis, jbyteArray jsrc, jint joffset, jint jlength)
356 {
357 SVN_JAVAHL_JNI_TRY(NativeOutputStream, write)
358 {
359 SVN_JAVAHL_GET_BOUND_OBJECT(JavaHL::NativeOutputStream, self);
360
361 const Java::Env env(jenv);
362 const Java::ByteArray src(env, jsrc);
363
364 self->write(env, Java::ByteArray::Contents(src), joffset, jlength);
365 }
366 SVN_JAVAHL_JNI_CATCH_TO_EXCEPTION(Java::IOException);
367 }
368
369 JNIEXPORT void JNICALL
Java_org_apache_subversion_javahl_types_NativeOutputStream_finalize(JNIEnv * jenv,jobject jthis)370 Java_org_apache_subversion_javahl_types_NativeOutputStream_finalize(
371 JNIEnv* jenv, jobject jthis)
372 {
373 SVN_JAVAHL_JNI_TRY(NativeOutputStream, finalize)
374 {
375 JavaHL::NativeOutputStream* native =
376 JavaHL::NativeOutputStream::get_self_unsafe(Java::Env(jenv), jthis);
377 if (native != NULL)
378 native->finalize();
379 }
380 SVN_JAVAHL_JNI_CATCH;
381 }
382