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