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 * @file OutputStream.cpp
24 * @brief Implementation of the class OutputStream
25 */
26
27 #include "OutputStream.h"
28 #include "JNIUtil.h"
29 #include "JNIByteArray.h"
30
31 /**
32 * Create an OutputStream object.
33 * @param jthis the Java object to be stored
34 */
OutputStream(jobject jthis)35 OutputStream::OutputStream(jobject jthis)
36 {
37 m_jthis = jthis;
38 }
39
40 /**
41 * Destroy an Inputer object.
42 */
~OutputStream()43 OutputStream::~OutputStream()
44 {
45 // The m_jthis does not need to be destroyed, because it is the
46 // passed in parameter to the Java method.
47 }
48
49 /**
50 * Create a svn_stream_t structure for this object. This will be used
51 * as an output stream by Subversion.
52 * @param pool the pool, from which the structure is allocated
53 * @return the output stream
54 */
getStream(const SVN::Pool & pool)55 svn_stream_t *OutputStream::getStream(const SVN::Pool &pool)
56 {
57 // Create a stream with this as the baton and set the write and
58 // close functions.
59 svn_stream_t *ret = svn_stream_create(this, pool.getPool());
60 svn_stream_set_write(ret, OutputStream::write);
61 svn_stream_set_close(ret, OutputStream::close);
62 return ret;
63 }
64
65 /**
66 * Implements svn_write_fn_t to write data out from Subversion.
67 * @param baton an OutputStream object for the callback
68 * @param buffer the buffer for the write data
69 * @param len on input the buffer len, on output the number of written
70 * bytes
71 * @return a subversion error or SVN_NO_ERROR
72 */
write(void * baton,const char * buffer,apr_size_t * len)73 svn_error_t *OutputStream::write(void *baton, const char *buffer,
74 apr_size_t *len)
75 {
76 JNIEnv *env = JNIUtil::getEnv();
77
78 // An object of our class is passed in as the baton.
79 OutputStream *that = static_cast<OutputStream *>(baton);
80
81 // The method id will not change during the time this library is
82 // loaded, so it can be cached.
83 static jmethodID mid = 0;
84 if (mid == 0)
85 {
86 jclass clazz = env->FindClass("java/io/OutputStream");
87 if (JNIUtil::isJavaExceptionThrown())
88 return SVN_NO_ERROR;
89
90 mid = env->GetMethodID(clazz, "write", "([B)V");
91 if (JNIUtil::isJavaExceptionThrown() || mid == 0)
92 return SVN_NO_ERROR;
93
94 env->DeleteLocalRef(clazz);
95 }
96
97 // convert the data to a Java byte array
98 jbyteArray data = JNIUtil::makeJByteArray(buffer, static_cast<int>(*len));
99 if (JNIUtil::isJavaExceptionThrown())
100 return SVN_NO_ERROR;
101
102 // write the data
103 env->CallObjectMethod(that->m_jthis, mid, data);
104 if (JNIUtil::isJavaExceptionThrown())
105 return SVN_NO_ERROR;
106
107 env->DeleteLocalRef(data);
108
109 return SVN_NO_ERROR;
110 }
111
112 /**
113 * Implements svn_close_fn_t to close the output stream.
114 * @param baton an OutputStream object for the callback
115 * @return a subversion error or SVN_NO_ERROR
116 */
close(void * baton)117 svn_error_t *OutputStream::close(void *baton)
118 {
119 JNIEnv *env = JNIUtil::getEnv();
120
121 // An object of our class is passed in as the baton
122 OutputStream *that = reinterpret_cast<OutputStream*>(baton);
123
124 // The method id will not change during the time this library is
125 // loaded, so it can be cached.
126 static jmethodID mid = 0;
127 if (mid == 0)
128 {
129 jclass clazz = env->FindClass("java/io/OutputStream");
130 if (JNIUtil::isJavaExceptionThrown())
131 return SVN_NO_ERROR;
132
133 mid = env->GetMethodID(clazz, "close", "()V");
134 if (JNIUtil::isJavaExceptionThrown() || mid == 0)
135 return SVN_NO_ERROR;
136
137 env->DeleteLocalRef(clazz);
138 }
139
140 // Call the Java object, to close the stream.
141 env->CallVoidMethod(that->m_jthis, mid);
142 // No need to check for exception here because we return anyway.
143
144 return SVN_NO_ERROR;
145 }
146