You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

HttpTestCase.java 6.7KB

Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
Add support to follow HTTP redirects git-core follows HTTP redirects so JGit should also provide this. Implement config setting http.followRedirects with possible values "false" (= never), "true" (= always), and "initial" (only on GET, but not on POST).[1] We must do our own redirect handling and cannot rely on the support that the underlying real connection may offer. At least the JDK's HttpURLConnection has two features that get in the way: * it does not allow cross-protocol redirects and thus fails on http->https redirects (for instance, on Github). * it translates a redirect after a POST to a GET unless the system property "http.strictPostRedirect" is set to true. We don't want to manipulate that system setting nor require it. Additionally, git has its own rules about what redirects it accepts;[2] for instance, it does not allow a redirect that adds query arguments. We handle response codes 301, 302, 303, and 307 as per RFC 2616.[3] On POST we do not handle 303, and we follow redirects only if http.followRedirects == true. Redirects are followed only a certain number of times. There are two ways to control that limit: * by default, the limit is given by the http.maxRedirects system property that is also used by the JDK. If the system property is not set, the default is 5. (This is much lower than the JDK default of 20, but I don't see the value of following so many redirects.) * this can be overwritten by a http.maxRedirects git config setting. The JGit http.* git config settings are currently all global; JGit has no support yet for URI-specific settings "http.<pattern>.name". Adding support for that is well beyond the scope of this change. Like git-core, we log every redirect attempt (LOG.info) so that users may know about the redirection having occurred. Extends the test framework to configure an AppServer with HTTPS support so that we can test cloning via HTTPS and redirections involving HTTPS. [1] https://git-scm.com/docs/git-config [2] https://kernel.googlesource.com/pub/scm/git/git/+/6628eb41db5189c0cdfdced6d8697e7c813c5f0f [3] https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html CQ: 13987 Bug: 465167 Change-Id: I86518cb76842f7d326b51f8715e3bbf8ada89859 Signed-off-by: Matthias Sohn <matthias.sohn@sap.com> Signed-off-by: Thomas Wolf <thomas.wolf@paranor.ch>
9 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. /*
  2. * Copyright (C) 2009-2017, Google Inc. and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.junit.http;
  11. import static org.junit.Assert.fail;
  12. import java.io.IOException;
  13. import java.net.URI;
  14. import java.net.URISyntaxException;
  15. import java.util.Collection;
  16. import java.util.Collections;
  17. import java.util.HashSet;
  18. import java.util.List;
  19. import java.util.Set;
  20. import org.eclipse.jetty.servlet.ServletContextHandler;
  21. import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
  22. import org.eclipse.jgit.junit.TestRepository;
  23. import org.eclipse.jgit.lib.AnyObjectId;
  24. import org.eclipse.jgit.lib.Constants;
  25. import org.eclipse.jgit.lib.ObjectId;
  26. import org.eclipse.jgit.lib.Repository;
  27. import org.eclipse.jgit.revwalk.RevCommit;
  28. import org.eclipse.jgit.revwalk.RevObject;
  29. import org.eclipse.jgit.transport.RefSpec;
  30. import org.eclipse.jgit.transport.RemoteRefUpdate;
  31. import org.eclipse.jgit.transport.URIish;
  32. /**
  33. * Base class for HTTP related transport testing.
  34. */
  35. public abstract class HttpTestCase extends LocalDiskRepositoryTestCase {
  36. /** Constant <code>master="Constants.R_HEADS + Constants.MASTER"</code> */
  37. protected static final String master = Constants.R_HEADS + Constants.MASTER;
  38. /** In-memory application server; subclass must start. */
  39. protected AppServer server;
  40. /** {@inheritDoc} */
  41. @Override
  42. public void setUp() throws Exception {
  43. super.setUp();
  44. server = createServer();
  45. }
  46. /** {@inheritDoc} */
  47. @Override
  48. public void tearDown() throws Exception {
  49. server.tearDown();
  50. super.tearDown();
  51. }
  52. /**
  53. * Create the {@link AppServer}.This default implementation creates a server
  54. * without SSLsupport listening for HTTP connections on a dynamically chosen
  55. * port, which can be gotten once the server has been started via its
  56. * {@link org.eclipse.jgit.junit.http.AppServer#getPort()} method.
  57. * Subclasses may override if they need a more specialized server.
  58. *
  59. * @return the {@link org.eclipse.jgit.junit.http.AppServer}.
  60. * @since 4.9
  61. */
  62. protected AppServer createServer() {
  63. return new AppServer();
  64. }
  65. /**
  66. * Create TestRepository
  67. *
  68. * @return the TestRepository
  69. * @throws IOException
  70. */
  71. protected TestRepository<Repository> createTestRepository()
  72. throws IOException {
  73. return new TestRepository<>(createBareRepository());
  74. }
  75. /**
  76. * Convert path to URIish
  77. *
  78. * @param path
  79. * @return the URIish
  80. * @throws URISyntaxException
  81. */
  82. protected URIish toURIish(String path) throws URISyntaxException {
  83. URI u = server.getURI().resolve(path);
  84. return new URIish(u.toString());
  85. }
  86. /**
  87. * Convert a path relative to the app's context path to a URIish
  88. *
  89. * @param app
  90. * @param name
  91. * @return the warnings (if any) from the last execution
  92. * @throws URISyntaxException
  93. */
  94. protected URIish toURIish(ServletContextHandler app, String name)
  95. throws URISyntaxException {
  96. String p = app.getContextPath();
  97. if (!p.endsWith("/") && !name.startsWith("/"))
  98. p += "/";
  99. p += name;
  100. return toURIish(p);
  101. }
  102. /**
  103. * Get requests.
  104. *
  105. * @return list of events
  106. */
  107. protected List<AccessEvent> getRequests() {
  108. return server.getRequests();
  109. }
  110. /**
  111. * Get requests.
  112. *
  113. * @param base
  114. * @param path
  115. *
  116. * @return list of events
  117. */
  118. protected List<AccessEvent> getRequests(URIish base, String path) {
  119. return server.getRequests(base, path);
  120. }
  121. /**
  122. * Get requests.
  123. *
  124. * @param path
  125. *
  126. * @return list of events
  127. */
  128. protected List<AccessEvent> getRequests(String path) {
  129. return server.getRequests(path);
  130. }
  131. /**
  132. * Run fsck
  133. *
  134. * @param db
  135. * @param tips
  136. * @throws Exception
  137. */
  138. protected static void fsck(Repository db, RevObject... tips)
  139. throws Exception {
  140. try (TestRepository<? extends Repository> tr =
  141. new TestRepository<>(db)) {
  142. tr.fsck(tips);
  143. }
  144. }
  145. /**
  146. * Mirror refs
  147. *
  148. * @param refs
  149. * @return set of RefSpecs
  150. */
  151. protected static Set<RefSpec> mirror(String... refs) {
  152. HashSet<RefSpec> r = new HashSet<>();
  153. for (String name : refs) {
  154. RefSpec rs = new RefSpec(name);
  155. rs = rs.setDestination(name);
  156. rs = rs.setForceUpdate(true);
  157. r.add(rs);
  158. }
  159. return r;
  160. }
  161. /**
  162. * Push a commit
  163. *
  164. * @param from
  165. * @param q
  166. * @return collection of RefUpdates
  167. * @throws IOException
  168. */
  169. protected static Collection<RemoteRefUpdate> push(TestRepository from,
  170. RevCommit q) throws IOException {
  171. final Repository db = from.getRepository();
  172. final String srcExpr = q.name();
  173. final String dstName = master;
  174. final boolean forceUpdate = true;
  175. final String localName = null;
  176. final ObjectId oldId = null;
  177. RemoteRefUpdate u = new RemoteRefUpdate(db, srcExpr, dstName,
  178. forceUpdate, localName, oldId);
  179. return Collections.singleton(u);
  180. }
  181. /**
  182. * Create loose object path
  183. *
  184. * @param base
  185. * @param id
  186. * @return path of the loose object
  187. */
  188. public static String loose(URIish base, AnyObjectId id) {
  189. final String objectName = id.name();
  190. final String d = objectName.substring(0, 2);
  191. final String f = objectName.substring(2);
  192. return join(base, "objects/" + d + "/" + f);
  193. }
  194. /**
  195. * Join a base URIish and a path
  196. *
  197. * @param base
  198. * @param path
  199. * a relative path
  200. * @return the joined path
  201. */
  202. public static String join(URIish base, String path) {
  203. if (path.startsWith("/"))
  204. fail("Cannot join absolute path " + path + " to URIish " + base);
  205. String dir = base.getPath();
  206. if (!dir.endsWith("/"))
  207. dir += "/";
  208. return dir + path;
  209. }
  210. /**
  211. * Rewrite a url
  212. *
  213. * @param url
  214. * @param newProtocol
  215. * @param newPort
  216. * @return the rewritten url
  217. */
  218. protected static String rewriteUrl(String url, String newProtocol,
  219. int newPort) {
  220. String newUrl = url;
  221. if (newProtocol != null && !newProtocol.isEmpty()) {
  222. int schemeEnd = newUrl.indexOf("://");
  223. if (schemeEnd >= 0) {
  224. newUrl = newProtocol + newUrl.substring(schemeEnd);
  225. }
  226. }
  227. if (newPort > 0) {
  228. newUrl = newUrl.replaceFirst(":\\d+/", ":" + newPort + "/");
  229. } else {
  230. // Remove the port, if any
  231. newUrl = newUrl.replaceFirst(":\\d+/", "/");
  232. }
  233. return newUrl;
  234. }
  235. /**
  236. * Extend a path
  237. *
  238. * @param uri
  239. * @param pathComponents
  240. * @return the extended URIish
  241. * @throws URISyntaxException
  242. */
  243. protected static URIish extendPath(URIish uri, String pathComponents)
  244. throws URISyntaxException {
  245. String raw = uri.toString();
  246. String newComponents = pathComponents;
  247. if (!newComponents.startsWith("/")) {
  248. newComponents = '/' + newComponents;
  249. }
  250. if (!newComponents.endsWith("/")) {
  251. newComponents += '/';
  252. }
  253. int i = raw.lastIndexOf('/');
  254. raw = raw.substring(0, i) + newComponents + raw.substring(i + 1);
  255. return new URIish(raw);
  256. }
  257. }