Skip to content

Commit 6f81d06

Browse files
committed
[test] Add distribution portal coverage and PR review follow-ups
Add PortalRedirectTest for GET / in distribution layout. Deploy the portal with org.exist.jetty.WebAppContext so Windows PathResource wrapping applies, and skip BrokerPool.stopAll when that static-only context stops. Document CHAIN_PRIORITY spacing, WindowsPathResource instanceof audit, and LEGACY_TOKEN_SEPARATOR removal tied to HC4 Phase 5 in PR eXist-db#6393.
1 parent bf86241 commit 6f81d06

7 files changed

Lines changed: 103 additions & 7 deletions

File tree

exist-core/src/main/java/org/exist/indexing/IndexWorker.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ public interface IndexWorker {
5555

5656
/**
5757
* Lower values run earlier in {@link IndexController} listener chains and {@link #flush()}.
58+
* Gaps reserve room for future workers: {@code 0} structural, {@code 1–99} pre-statistics,
59+
* {@code 100–999} pre-Lucene, {@code 1000+} Lucene and later; unranked workers use
60+
* {@link Integer#MAX_VALUE}.
5861
*/
5962
int CHAIN_PRIORITY_STRUCTURAL = 0;
6063
int CHAIN_PRIORITY_STATISTICS = 100;

exist-core/src/main/java/org/exist/jetty/WebAppContext.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727

2828
/**
2929
* eXist {@link org.eclipse.jetty.ee10.webapp.WebAppContext} with Windows path handling for
30-
* Jetty 12.1 ({@link WindowsPathResource}).
30+
* Jetty 12.1 ({@link WindowsPathResource}). Used for the main webapp ({@code /exist} or
31+
* standalone {@code /}) and the distribution portal at {@code /}.
3132
*
3233
* @author <a href="mailto:shabanovd@gmail.com">Dmitriy Shabanov</a>
3334
*/
@@ -52,6 +53,26 @@ public Resource newResource(final String urlOrPath) {
5253
protected void doStop() throws Exception {
5354
super.doStop();
5455

55-
BrokerPool.stopAll(true);
56+
if (ownsBrokerPoolLifecycle()) {
57+
BrokerPool.stopAll(true);
58+
}
59+
}
60+
61+
/**
62+
* Main eXist webapps stop the embedded database; the distribution portal at {@code /} is
63+
* static-only and must not tear down {@link BrokerPool} when Jetty stops it alongside {@code /exist}.
64+
*/
65+
private boolean ownsBrokerPoolLifecycle() {
66+
if ("/exist".equals(getContextPath())) {
67+
return true;
68+
}
69+
if (!"/".equals(getContextPath())) {
70+
return false;
71+
}
72+
final Resource baseResource = getBaseResource();
73+
if (baseResource == null) {
74+
return true;
75+
}
76+
return !baseResource.toString().replace('\\', '/').contains("/webapps/portal");
5677
}
5778
}

exist-core/src/main/java/org/exist/jetty/WindowsPathResource.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,10 @@
4242
* {@code WebAppContext.getWebInf()}. Remove when upstream Jetty restores safe Windows resolve.
4343
* <p>
4444
* This class extends {@link Resource}, not {@link PathResource}. Jetty internals that use
45-
* {@code instanceof PathResource} will not treat wrapped resources as path resources; CI and
46-
* integration tests validate that the exploded-webapp startup path does not depend on that.
45+
* {@code instanceof PathResource} will not treat wrapped resources as path resources. eXist
46+
* production code has no {@code instanceof PathResource} checks on resources that may be wrapped;
47+
* CI and integration tests validate that the exploded-webapp startup path does not depend on
48+
* Jetty-internal type checks either.
4749
* <p>
4850
* Only {@link #resolve(String)} differs from Jetty 12.1 {@link PathResource} behaviour. Other
4951
* {@link Resource} methods delegate to the wrapped resource or rely on inherited defaults that
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* eXist-db Open Source Native XML Database
3+
* Copyright (C) 2001 The eXist-db Authors
4+
*
5+
* info@exist-db.org
6+
* http://www.exist-db.org
7+
*
8+
* This library is free software; you can redistribute it and/or
9+
* modify it under the terms of the GNU Lesser General Public
10+
* License as published by the Free Software Foundation; either
11+
* version 2.1 of the License, or (at your option) any later version.
12+
*
13+
* This library is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16+
* Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public
19+
* License along with this library; if not, write to the Free Software
20+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21+
*/
22+
package org.exist.http;
23+
24+
import org.apache.http.HttpResponse;
25+
import org.apache.http.HttpStatus;
26+
import org.apache.http.client.fluent.Request;
27+
import org.apache.http.util.EntityUtils;
28+
import org.exist.test.ExistWebServer;
29+
import org.junit.ClassRule;
30+
import org.junit.Test;
31+
32+
import java.io.IOException;
33+
import java.nio.charset.StandardCharsets;
34+
35+
import static org.junit.Assert.assertEquals;
36+
import static org.junit.Assert.assertTrue;
37+
38+
/**
39+
* Distribution-mode portal at {@code /} — landing page and redirect target to {@code /exist}.
40+
*/
41+
public class PortalRedirectTest extends AbstractHttpTest {
42+
43+
@ClassRule
44+
public static final ExistWebServer existWebServer = new ExistWebServer(true, false, true, true, false);
45+
46+
@Test
47+
public void portalRootServesLandingPageWithExistRedirect() throws IOException {
48+
final Request request = Request.Get(portalUri(existWebServer));
49+
final HttpResponse response = withHttpExecutor(existWebServer,
50+
executor -> executor.execute(request).returnResponse());
51+
52+
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
53+
54+
final String body = EntityUtils.toString(response.getEntity(), StandardCharsets.UTF_8);
55+
assertTrue("Expected portal title", body.contains("Open Source Native XML Database"));
56+
assertTrue("Expected JS redirect to /exist", body.contains("window.location.replace(\"/exist\")"));
57+
assertTrue("Expected noscript fallback link to /exist", body.contains("href=\"/exist\""));
58+
}
59+
60+
private static String portalUri(final ExistWebServer existWebServer) {
61+
return "http://localhost:" + existWebServer.getPort() + "/";
62+
}
63+
}

exist-jetty-config/src/main/resources/org/exist/jetty/etc/jetty-deploy.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<!-- Portal webapp at / — serves the redirect page to /exist -->
3939
<Call name="addHandler">
4040
<Arg>
41-
<New id="portal" class="org.eclipse.jetty.ee10.webapp.WebAppContext">
41+
<New id="portal" class="org.exist.jetty.WebAppContext">
4242
<Set name="contextPath">/</Set>
4343
<Set name="war"><SystemProperty name="exist.jetty.portal.dir"><Default><Property name="jetty.home" default="."/>/../../../exist-jetty-config/src/main/resources/org/exist/jetty/etc/webapps/portal/</Default></SystemProperty></Set>
4444
<Set name="defaultsDescriptor"><Property name="jetty.home" default="."/>/etc/webdefault.xml</Set>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
3-
<Configure id="exist-portal-context" class="org.eclipse.jetty.ee10.webapp.WebAppContext">
3+
<Configure id="exist-portal-context" class="org.exist.jetty.WebAppContext">
44
<Set name="contextPath">/</Set>
55
<Set name="defaultsDescriptor"><Property name="jetty.home" default="."/>/etc/webdefault.xml</Set>
66
</Configure>

extensions/modules/persistentlogin/src/main/java/org/exist/xquery/modules/persistentlogin/PersistentLogin.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,14 @@ public class PersistentLogin {
6666
*/
6767
private static final String TOKEN_SEPARATOR = "|";
6868

69-
/** Historical separator; still accepted when parsing incoming cookies. */
69+
/**
70+
* Historical separator; still accepted when parsing incoming cookies issued before the
71+
* {@link #TOKEN_SEPARATOR} switch ({@code :} breaks HC4 Set-Cookie parsing — see
72+
* <a href="https://github.com/eXist-db/exist/pull/6393">PR #6393</a>). Remove
73+
* {@link #splitTokenValue} dual parsing once HC4 is fully removed from the codebase
74+
* (Phase 5 in #6393, after expath Gate B). In-flight browser cookies are not a concern:
75+
* a new eXist release install expects users to reauthenticate anyway.
76+
*/
7077
private static final String LEGACY_TOKEN_SEPARATOR = ":";
7178

7279
private Map<String, LoginDetails> seriesMap = Collections.synchronizedMap(new HashMap<>());

0 commit comments

Comments
 (0)