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 RevisionRange.cpp
24  * @brief Implementation of the class RevisionRange.
25  */
26 
27 #include <apr_pools.h>
28 #include "svn_client.h"
29 #include "svn_types.h"
30 
31 #include "JNIUtil.h"
32 #include "RevisionRange.h"
33 #include "Revision.h"
34 #include "Pool.h"
35 
RevisionRange(jobject jrevisionRange)36 RevisionRange::RevisionRange(jobject jrevisionRange)
37 {
38     m_range = jrevisionRange;
39 }
40 
~RevisionRange()41 RevisionRange::~RevisionRange()
42 {
43     // m_range is assume to be managed externally, and thus is not
44     // explicitly destroyed.
45 }
46 
47 namespace {
get_range_info(jobject jrange,svn_opt_revision_t * range_start,svn_opt_revision_t * range_end,svn_boolean_t * range_inheritable)48 void get_range_info(jobject jrange,
49                     svn_opt_revision_t* range_start,
50                     svn_opt_revision_t* range_end,
51                     svn_boolean_t* range_inheritable)
52 {
53   JNIEnv *env = JNIUtil::getEnv();
54 
55   jclass clazz = env->FindClass(JAVAHL_CLASS("/types/RevisionRange"));
56   if (JNIUtil::isExceptionThrown())
57     return;
58 
59   if (range_start)
60     {
61 
62       static jmethodID fmid = 0;
63       if (fmid == 0)
64         {
65           fmid = env->GetMethodID(clazz, "getFromRevision",
66                                   "()" JAVAHL_ARG("/types/Revision;"));
67           if (JNIUtil::isJavaExceptionThrown())
68             return;
69         }
70 
71       jobject jstartRevision = env->CallObjectMethod(jrange, fmid);
72       if (JNIUtil::isExceptionThrown())
73         return;
74 
75       Revision startRevision(jstartRevision);
76       if (JNIUtil::isExceptionThrown())
77         return;
78 
79       *range_start = *startRevision.revision();
80       if (JNIUtil::isExceptionThrown())
81         return;
82     }
83 
84   if (range_end)
85     {
86       static jmethodID tmid = 0;
87       if (tmid == 0)
88         {
89           tmid = env->GetMethodID(clazz, "getToRevision",
90                                   "()" JAVAHL_ARG("/types/Revision;"));
91           if (JNIUtil::isJavaExceptionThrown())
92             return;
93         }
94 
95       jobject jendRevision = env->CallObjectMethod(jrange, tmid);
96       if (JNIUtil::isExceptionThrown())
97         return;
98 
99       Revision endRevision(jendRevision);
100       if (JNIUtil::isExceptionThrown())
101         return;
102 
103       *range_end = *endRevision.revision();
104       if (JNIUtil::isExceptionThrown())
105         return;
106     }
107 
108   if (range_inheritable)
109     {
110       static jmethodID imid = 0;
111       if (imid == 0 && range_inheritable)
112         {
113           imid = env->GetMethodID(clazz, "isInheritable", "()Z");
114           if (JNIUtil::isJavaExceptionThrown())
115             return;
116         }
117 
118       jboolean inheritable = env->CallBooleanMethod(jrange, imid);
119       if (JNIUtil::isExceptionThrown())
120         return;
121       *range_inheritable = inheritable;
122     }
123 }
124 } // anonymous namespace
125 
toMergeRange(SVN::Pool & pool) const126 svn_merge_range_t* RevisionRange::toMergeRange(SVN::Pool &pool) const
127 {
128   svn_opt_revision_t range_start, range_end;
129   svn_boolean_t range_inheritable;
130   get_range_info(m_range, &range_start, &range_end, &range_inheritable);
131   if (JNIUtil::isExceptionThrown())
132     return NULL;
133 
134   if (range_start.kind != svn_opt_revision_number
135       || range_end.kind != svn_opt_revision_number)
136     JNIUtil::raiseThrowable("java.lang.InvalidStateException",
137                             "Revsision ranges must contain revision numbers");
138 
139   svn_merge_range_t* range =
140     static_cast<svn_merge_range_t*>
141       (apr_palloc(pool.getPool(), sizeof(*range)));
142 
143   range->start = range_start.value.number;
144   range->end = range_end.value.number;
145   range->inheritable = range_inheritable;
146   return range;
147 }
148 
toRange(SVN::Pool & pool) const149 svn_opt_revision_range_t *RevisionRange::toRange(SVN::Pool &pool) const
150 {
151   svn_opt_revision_range_t *range =
152     static_cast<svn_opt_revision_range_t *>
153       (apr_palloc(pool.getPool(), sizeof(*range)));
154 
155   get_range_info(m_range, &range->start, &range->end, NULL);
156   if (JNIUtil::isExceptionThrown())
157     range = NULL;
158   return range;
159 }
160 
161 jobject
makeJRevisionRange(svn_merge_range_t * range)162 RevisionRange::makeJRevisionRange(svn_merge_range_t *range)
163 {
164     JNIEnv *env = JNIUtil::getEnv();
165 
166     jclass rangeClazz = env->FindClass(JAVAHL_CLASS("/types/RevisionRange"));
167     if (JNIUtil::isJavaExceptionThrown())
168         return NULL;
169     static jmethodID rangeCtor = 0;
170     if (rangeCtor == 0)
171     {
172         rangeCtor = env->GetMethodID(rangeClazz, "<init>", "(JJZ)V");
173         if (JNIUtil::isJavaExceptionThrown())
174             return NULL;
175     }
176     jobject jrange = env->NewObject(rangeClazz, rangeCtor,
177                                     jlong(range->start),
178                                     jlong(range->end),
179                                     jboolean(range->inheritable));
180     if (JNIUtil::isJavaExceptionThrown())
181         return NULL;
182 
183     return jrange;
184 }
185