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 org_apache_subversion_javahl_util_SubstLib.cpp
24  * @brief Implementation of the native methods in the Java class SubstLib
25  */
26 
27 #include <memory>
28 
29 #include "../include/org_apache_subversion_javahl_util_SubstLib.h"
30 
31 #include "jniwrapper/jni_stack.hpp"
32 #include "jniwrapper/jni_array.hpp"
33 #include "jniwrapper/jni_string.hpp"
34 #include "jniwrapper/jni_string_map.hpp"
35 #include "jniwrapper/jni_io_stream.hpp"
36 
37 #include "JNIUtil.h"
38 #include "NativeStream.hpp"
39 #include "Utility.hpp"
40 #include "CxxCompat.hpp"
41 
42 #include <apr_hash.h>
43 
44 #include "svn_subst.h"
45 
46 #include "svn_private_config.h"
47 
48 
49 namespace {
50 apr_hash_t*
build_keywords_common(Java::Env env,const SVN::Pool & pool,jbyteArray jkeywords_value,jlong jrevision,jstring jurl,jstring jrepos_root_url,jobject jdate,jstring jauthor)51 build_keywords_common(Java::Env env, const SVN::Pool& pool,
52                       jbyteArray jkeywords_value, jlong jrevision,
53                       jstring jurl, jstring jrepos_root_url,
54                       jobject jdate, jstring jauthor)
55 {
56   const Java::ByteArray keywords_value(env, jkeywords_value);
57   const Java::String url(env, jurl);
58   const Java::String repos_root_url(env, jrepos_root_url);
59   const Java::String author(env, jauthor);
60 
61   const Java::ByteArray::Contents keywords_contents(keywords_value);
62   svn_string_t* keywords_string = keywords_contents.get_string(pool);
63   const char* revision = (jrevision < 0 ? NULL
64                           : apr_psprintf(pool.getPool(),
65                                          "%" APR_UINT64_T_FMT,
66                                          apr_uint64_t(jrevision)));
67   const Java::String::Contents url_contents(url);
68   const Java::String::Contents root_url_contents(repos_root_url);
69   const Java::String::Contents author_contents(author);
70 
71   apr_hash_t* kw = NULL;
72   SVN_JAVAHL_CHECK(env,
73                    svn_subst_build_keywords3(
74                        &kw,
75                        keywords_string->data,
76                        revision,
77                        url_contents.c_str(),
78                        root_url_contents.c_str(),
79                        (jdate ? JNIUtil::getDate(jdate) : 0),
80                        author_contents.c_str(),
81                        pool.getPool()));
82   return kw;
83 }
84 
85 svn_stream_t*
translate_stream_common(Java::Env env,const SVN::Pool & pool,svn_stream_t * stream,jbyteArray jeol_marker,jboolean jrepair_eol,jobject jkeywords,jboolean juse_keywords,jboolean jexpand_keywords,jbyteArray jkeywords_value,jlong jrevision,jstring jurl,jstring jrepos_root_url,jobject jdate,jstring jauthor)86 translate_stream_common(Java::Env env, const SVN::Pool& pool,
87                         svn_stream_t* stream,
88                         jbyteArray jeol_marker, jboolean jrepair_eol,
89                         jobject jkeywords, jboolean juse_keywords,
90                         jboolean jexpand_keywords,
91                         jbyteArray jkeywords_value, jlong jrevision,
92                         jstring jurl, jstring jrepos_root_url,
93                         jobject jdate, jstring jauthor)
94 {
95   apr_hash_t* const keywords =
96     (juse_keywords
97      ? JavaHL::Util::make_keyword_hash(env, jkeywords, pool)
98      : build_keywords_common(
99          env, pool, jkeywords_value, jrevision,
100          jurl, jrepos_root_url, jdate, jauthor));
101 
102   const Java::ByteArray eol_marker(env, jeol_marker);
103   svn_string_t* const eol_str =
104     Java::ByteArray::Contents(eol_marker).get_string(pool);
105   return svn_subst_stream_translated(stream,
106                                      eol_str->data,
107                                      svn_boolean_t(jrepair_eol),
108                                      keywords,
109                                      svn_boolean_t(jexpand_keywords),
110                                      pool.getPool());
111 }
112 } // anoymous namespace
113 
114 
115 JNIEXPORT jobject JNICALL
Java_org_apache_subversion_javahl_util_SubstLib_buildKeywords(JNIEnv * jenv,jobject jthis,jbyteArray jkeywords_value,jlong jrevision,jstring jurl,jstring jrepos_root_url,jobject jdate,jstring jauthor)116 Java_org_apache_subversion_javahl_util_SubstLib_buildKeywords(
117     JNIEnv* jenv, jobject jthis,
118     jbyteArray jkeywords_value, jlong jrevision,
119     jstring jurl, jstring jrepos_root_url,
120     jobject jdate, jstring jauthor)
121 {
122   typedef Java::Map<Java::ByteArray, jbyteArray> ByteArrayMap;
123 
124   SVN_JAVAHL_JNI_TRY(SubstLib, buildKeywords)
125     {
126       const Java::Env env(jenv);
127 
128       // Using a "global" request pool since we don't keep a context with
129       // its own pool around for these functions.
130       SVN::Pool pool;
131 
132       apr_hash_t* const kw = build_keywords_common(
133           env, pool, jkeywords_value, jrevision,
134           jurl, jrepos_root_url, jdate, jauthor);
135 
136       ByteArrayMap keywords(env, jint(apr_hash_count(kw)));
137       for (apr_hash_index_t* hi = apr_hash_first(pool.getPool(), kw);
138            hi; hi = apr_hash_next(hi))
139         {
140           const void* rkey;
141           void* rval;
142           apr_hash_this(hi, &rkey, NULL, &rval);
143 
144           svn_string_t* const val = static_cast<svn_string_t*>(rval);
145           keywords.put(static_cast<const char*>(rkey),
146                        Java::ByteArray(env, val->data, jsize(val->len)));
147         }
148       return keywords.get();
149     }
150   SVN_JAVAHL_JNI_CATCH;
151   return NULL;
152 }
153 
154 
155 JNIEXPORT jobject JNICALL
Java_org_apache_subversion_javahl_util_SubstLib_translateInputStream(JNIEnv * jenv,jobject jthis,jobject jsource,jbyteArray jeol_marker,jboolean jrepair_eol,jobject jkeywords,jboolean juse_keywords,jboolean jexpand_keywords,jbyteArray jkeywords_value,jlong jrevision,jstring jurl,jstring jrepos_root_url,jobject jdate,jstring jauthor)156 Java_org_apache_subversion_javahl_util_SubstLib_translateInputStream(
157     JNIEnv* jenv, jobject jthis,
158     jobject jsource, jbyteArray jeol_marker, jboolean jrepair_eol,
159     jobject jkeywords, jboolean juse_keywords, jboolean jexpand_keywords,
160     jbyteArray jkeywords_value, jlong jrevision,
161     jstring jurl, jstring jrepos_root_url,
162     jobject jdate, jstring jauthor)
163 {
164   SVN_JAVAHL_JNI_TRY(SubstLib, translateInputStream)
165     {
166       const Java::Env env(jenv);
167 
168       // We'll allocate the stream in the bound object's pool.
169       JavaHL::cxx::owned_ptr<JavaHL::NativeInputStream>
170         translated(new JavaHL::NativeInputStream());
171       svn_stream_t* source = Java::InputStream::get_global_stream(
172           env, jsource, translated->get_pool());
173 
174       translated->set_stream(translate_stream_common(
175                                  env, translated->get_pool(), source,
176                                  jeol_marker, jrepair_eol,
177                                  jkeywords, juse_keywords, jexpand_keywords,
178                                  jkeywords_value, jrevision,
179                                  jurl, jrepos_root_url, jdate, jauthor));
180       const jobject jtranslated = translated->create_java_wrapper();
181       translated.release();
182       return jtranslated;
183     }
184   SVN_JAVAHL_JNI_CATCH;
185   return NULL;
186 }
187 
188 
189 JNIEXPORT jobject JNICALL
Java_org_apache_subversion_javahl_util_SubstLib_translateOutputStream(JNIEnv * jenv,jobject jthis,jobject jdestination,jbyteArray jeol_marker,jboolean jrepair_eol,jobject jkeywords,jboolean juse_keywords,jboolean jexpand_keywords,jbyteArray jkeywords_value,jlong jrevision,jstring jurl,jstring jrepos_root_url,jobject jdate,jstring jauthor)190 Java_org_apache_subversion_javahl_util_SubstLib_translateOutputStream(
191     JNIEnv* jenv, jobject jthis,
192     jobject jdestination, jbyteArray jeol_marker, jboolean jrepair_eol,
193     jobject jkeywords, jboolean juse_keywords, jboolean jexpand_keywords,
194     jbyteArray jkeywords_value, jlong jrevision,
195     jstring jurl, jstring jrepos_root_url,
196     jobject jdate, jstring jauthor)
197 {
198   SVN_JAVAHL_JNI_TRY(SubstLib, translateInputStream)
199     {
200       const Java::Env env(jenv);
201 
202       // We'll allocate the stream in the bound object's pool.
203       JavaHL::cxx::owned_ptr<JavaHL::NativeOutputStream>
204         translated(new JavaHL::NativeOutputStream());
205       svn_stream_t* destination = Java::OutputStream::get_global_stream(
206           env, jdestination, translated->get_pool());
207 
208       translated->set_stream(translate_stream_common(
209                                  env, translated->get_pool(), destination,
210                                  jeol_marker, jrepair_eol,
211                                  jkeywords, juse_keywords, jexpand_keywords,
212                                  jkeywords_value, jrevision,
213                                  jurl, jrepos_root_url, jdate, jauthor));
214       const jobject jtranslated = translated->create_java_wrapper();
215       translated.release();
216       return jtranslated;
217     }
218   SVN_JAVAHL_JNI_CATCH;
219   return NULL;
220 }
221