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
* ====================================================================
23
* @file org_apache_subversion_javahl_util_PropLib.cpp
24
* @brief Implementation of the native methods in the Java class PropLib
30
#include "../include/org_apache_subversion_javahl_util_PropLib.h"
32
#include "jniwrapper/jni_stack.hpp"
33
#include "jniwrapper/jni_array.hpp"
34
#include "jniwrapper/jni_list.hpp"
35
#include "jniwrapper/jni_string.hpp"
36
#include "jniwrapper/jni_io_stream.hpp"
37
#include "ExternalItem.hpp"
38
#include "SubversionException.hpp"
40
#include "EnumMapper.h"
43
#include "svn_props.h"
47
#include "private/svn_wc_private.h"
48
#include "svn_private_config.h"
55
PropGetter(const char* mime_type, svn_stream_t* contents)
56
: m_mime_type(mime_type),
60
static svn_error_t* callback(const svn_string_t** mime_type,
61
svn_stream_t* stream, void* baton,
64
PropGetter* self = static_cast<PropGetter*>(baton);
67
if (self->m_mime_type)
68
*mime_type = svn_string_create(self->m_mime_type, pool);
70
*mime_type = svn_string_create_empty(pool);
73
if (stream && self->m_contents)
75
SVN_ERR(svn_stream_copy3(self->m_contents,
76
svn_stream_disown(stream, pool),
84
const char* m_mime_type;
85
svn_stream_t* m_contents;
90
explicit FormatRevision(const svn_opt_revision_t* const& revarg,
91
const SVN::Pool& poolarg)
92
: rev(revarg), pool(poolarg)
95
const svn_opt_revision_t* const& rev;
96
const SVN::Pool& pool;
99
std::ostream& operator<<(std::ostream& os, const FormatRevision& pr)
101
switch (pr.rev->kind)
103
case svn_opt_revision_number:
104
os << pr.rev->value.number;
106
case svn_opt_revision_date:
108
<< svn_time_to_cstring(pr.rev->value.date, pr.pool.getPool())
112
throw std::logic_error(
113
_("Invalid revision tag; must be a number or a date"));
118
bool operator==(const svn_opt_revision_t& a,
119
const svn_opt_revision_t& b)
121
if (a.kind != b.kind)
123
if (a.kind == svn_opt_revision_number
124
&& a.value.number != b.value.number)
126
if (a.kind == svn_opt_revision_date
127
&& a.value.date != b.value.date)
132
inline bool operator!=(const svn_opt_revision_t& a,
133
const svn_opt_revision_t& b)
141
explicit UnparseFunctor(std::ostringstream& buffer, bool old_format,
144
m_old_format(old_format),
148
void operator()(const JavaHL::ExternalItem& item)
152
const Java::Env env(item.get_env());
153
const Java::LocalFrame frame(env);
157
if (item.revision()->kind != svn_opt_revision_head
158
&& *item.revision() != *item.peg_revision())
161
<< FormatRevision(item.revision(), m_iterpool)
164
if (item.peg_revision()->kind == svn_opt_revision_head)
165
m_buffer << item.url() << ' ';
168
m_buffer << item.url() << '@'
169
<< FormatRevision(item.peg_revision(), m_iterpool)
172
m_buffer << item.target_dir() << '\n';
176
// Sanity check: old format does not support peg revisions
177
if (item.peg_revision()->kind != svn_opt_revision_head
178
&& *item.revision() != *item.peg_revision())
180
JavaHL::SubversionException(env)
181
.raise(_("Clients older than Subversion 1.5"
182
" do not support peg revision syntax"
183
" in the svn:externals property"));
186
// Sanity check: old format does not support relative URLs
187
const std::string url = item.url();
188
if ( (url.size() >= 1 && (url[0] == '.' || url[0] == '/'))
189
|| (url.size() >= 2 && (url[0] == '^' && url[1] == '/')))
191
JavaHL::SubversionException(env)
192
.raise(_("Clients older than Subversion 1.5"
193
" do not support relative URLs"
194
" in the svn:externals property"));
197
m_buffer << item.target_dir() << ' ';
198
if (item.revision()->kind != svn_opt_revision_head)
201
<< FormatRevision(item.revision(), m_iterpool)
204
m_buffer << url << '\n';
209
std::ostringstream& m_buffer;
210
const bool m_old_format;
211
SVN::Pool& m_iterpool;
213
} // anoymous namespace
216
JNIEXPORT jbyteArray JNICALL
217
Java_org_apache_subversion_javahl_util_PropLib_checkNodeProp(
218
JNIEnv* jenv, jobject jthis,
219
jstring jname, jbyteArray jvalue, jstring jpath, jobject jkind,
220
jstring jmime_type, jobject jfile_contents,
221
jboolean jskip_some_checks)
223
SVN_JAVAHL_JNI_TRY(PropLib, checkLocalProp)
225
const Java::Env env(jenv);
227
const svn_node_kind_t kind = EnumMapper::toNodeKind(jkind);
228
SVN_JAVAHL_OLDSTYLE_EXCEPTION_CHECK(env);
230
const Java::String name_str(env, jname);
231
const Java::ByteArray value(env, jvalue);
232
const Java::String path_str(env, jpath);
233
const Java::String mime_type_str(env, jmime_type);
234
Java::InputStream file_contents(env, jfile_contents);
236
// Using a "global" request pool since we don't keep a context
237
// with its own pool around for these functions.
240
const Java::String::Contents name(name_str);
241
const Java::String::Contents path(path_str);
242
const Java::String::Contents mime_type(mime_type_str);
243
PropGetter getter(mime_type.c_str(), file_contents.get_stream(pool));
245
const svn_string_t* canonval;
246
SVN_JAVAHL_CHECK(env,
247
svn_wc_canonicalize_svn_prop(
248
&canonval, name.c_str(),
249
Java::ByteArray::Contents(value).get_string(pool),
251
svn_boolean_t(jskip_some_checks),
252
PropGetter::callback, &getter,
254
return Java::ByteArray(env, canonval->data, jint(canonval->len)).get();
256
SVN_JAVAHL_JNI_CATCH;
261
JNIEXPORT jobject JNICALL
262
Java_org_apache_subversion_javahl_util_PropLib_parseExternals(
263
JNIEnv* jenv, jobject jthis,
264
jbyteArray jdescription, jstring jparent_dir, jboolean jcanonicalize_url)
266
SVN_JAVAHL_JNI_TRY(PropLib, parseExternals)
268
const Java::Env env(jenv);
270
const Java::ByteArray description(env, jdescription);
271
const Java::String parent_dir(env, jparent_dir);
273
// Using a "global" request pool since we don't keep a context
274
// with its own pool around for these functions.
277
apr_array_header_t* externals;
279
// There is no guarantee that the description contents are
280
// null-terminated. Copy them to an svn_string_t to make sure
282
svn_string_t* const description_contents =
283
Java::ByteArray::Contents(description).get_string(pool);
285
SVN_JAVAHL_CHECK(env,
286
svn_wc_parse_externals_description3(
288
Java::String::Contents(parent_dir).c_str(),
289
description_contents->data,
290
svn_boolean_t(jcanonicalize_url),
294
Java::List<JavaHL::ExternalItem> items(env, externals->nelts);
295
for (jint i = 0; i < externals->nelts; ++i)
297
// References to the newly created external items are stored
298
// in the list, so make sure the local reference in this
299
// frame get cleared on each iteration.
300
Java::LocalFrame frame;
302
const svn_wc_external_item2_t* const item =
303
APR_ARRAY_IDX(externals, i, svn_wc_external_item2_t*);
304
items.add(JavaHL::ExternalItem(env,
308
&item->peg_revision));
312
SVN_JAVAHL_JNI_CATCH;
317
JNIEXPORT jbyteArray JNICALL
318
Java_org_apache_subversion_javahl_util_PropLib_unparseExternals(
319
JNIEnv* jenv, jobject jthis,
320
jobject jitems, jstring jparent_dir, jboolean jold_format)
322
SVN_JAVAHL_JNI_TRY(PropLib, unparseExternals)
324
const Java::Env env(jenv);
326
const Java::ImmutableList<JavaHL::ExternalItem> items(env, jitems);
327
const Java::String parent_dir(env, jparent_dir);
329
// Using a "global" iteration pool since we don't keep a context
330
// with its own pool around for these functions.
333
std::ostringstream buffer;
334
items.for_each(UnparseFunctor(buffer, jold_format, iterpool));
335
const std::string description(buffer.str());
337
// Validate the result. Even though we generated the string
338
// ourselves, we did not validate the input paths and URLs.
339
SVN_JAVAHL_CHECK(env,
340
svn_wc_parse_externals_description3(
342
Java::String::Contents(parent_dir).c_str(),
344
false, iterpool.getPool()));
345
return Java::ByteArray(env, description).get();
347
SVN_JAVAHL_JNI_CATCH;
352
JNIEXPORT jstring JNICALL
353
Java_org_apache_subversion_javahl_util_PropLib_resolveExternalsUrl(
354
JNIEnv* jenv, jobject jthis,
355
jobject jitem, jstring jrepos_root_url, jstring jparent_dir_url)
357
SVN_JAVAHL_JNI_TRY(PropLib, unparseExternals)
359
const Java::Env env(jenv);
361
const Java::String repos_root_url(env, jrepos_root_url);
362
const Java::String parent_dir_url(env, jparent_dir_url);
363
const JavaHL::ExternalItem item(env, jitem);
365
// Using a "global" request pool since we don't keep a context
366
// with its own pool around for these functions.
369
const char* resolved_url;
370
SVN_JAVAHL_CHECK(env,
371
svn_wc__resolve_relative_external_url(
373
item.get_external_item(pool),
374
Java::String::Contents(repos_root_url).c_str(),
375
Java::String::Contents(parent_dir_url).c_str(),
376
pool.getPool(), pool.getPool()));
377
return Java::String(env, resolved_url).get();
379
SVN_JAVAHL_JNI_CATCH;