Skip to content

Commit

Permalink
Merge pull request #1826 from adamretter/hotfix/url-rewrite-controlle…
Browse files Browse the repository at this point in the history
…r-selection

Fix regression with URL Rewrite controller selection
  • Loading branch information
wolfgangmm authored Apr 16, 2018
2 parents 55b8172 + ee7f4c4 commit e05feca
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 35 deletions.
9 changes: 0 additions & 9 deletions .idea/libraries/ant.xml

This file was deleted.

2 changes: 2 additions & 0 deletions .idea/libraries/extensions.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion eXist-db.iml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@
<orderEntry type="library" exported="" name="optional" level="project" />
<orderEntry type="library" exported="" name="user" level="project" />
<orderEntry type="library" exported="" name="test" level="project" />
<orderEntry type="library" exported="" name="ant" level="project" />
<orderEntry type="library" exported="" name="tools" level="project" />
<orderEntry type="library" name="exquery-restxq" level="project" />
<orderEntry type="library" name="exquery-core" level="project" />
Expand Down
50 changes: 28 additions & 22 deletions src/org/exist/http/urlrewrite/XQueryURLRewrite.java
Original file line number Diff line number Diff line change
Expand Up @@ -723,8 +723,11 @@ SourceInfo findSourceFromDb(final DBBroker broker, final String basePath, final
DocumentImpl controllerDoc = null;
try {
final XmldbURI locationUri = XmldbURI.xmldbUriFor(basePath);

controllerDoc = findDbControllerXql(broker, locationUri, components);
XmldbURI resourceUri = locationUri;
for(final String component : components) {
resourceUri = resourceUri.append(component);
}
controllerDoc = findDbControllerXql(broker, locationUri, resourceUri);

if (controllerDoc == null) {
LOG.warn("XQueryURLRewrite controller could not be found for path: " + path);
Expand Down Expand Up @@ -757,32 +760,35 @@ SourceInfo findSourceFromDb(final DBBroker broker, final String basePath, final
/**
* Finds a `controller.xql` file within a Collection hierarchy.
* Most specific collections are considered first.
* <p>
*
* For example, given the collectionUri `/db/apps`
* and the pathPomponents `['myapp', 'data']`, the
* and the resourceUri /db/apps/myapp/data, the
* order or search will be:
* <p>
* /db/apps/myapp/data/collection.xconf
* /db/apps/myapp/collection.xconf
* /db/apps/collection.xconf
*
* /db/apps/myapp/data/controller.xql
* /db/apps/myapp/controller.xql
* /db/apps/controller.xql
*
* @param broker The database broker
* @param collectionUri The root collection URI, below which we should not descend
* @param pathComponents The path within the collectionUri to the most specific Collection
* @param resourceUri The path to the most specific document or collection for which we should find a controller
* @return The most relevant controller.xql document (with a READ_LOCK), or null if it could not be found.
*/
//@tailrec
private @Nullable
DocumentImpl findDbControllerXql(final DBBroker broker, final XmldbURI collectionUri, final String[] pathComponents) {
DocumentImpl findDbControllerXql(final DBBroker broker, final XmldbURI collectionUri, final XmldbURI resourceUri) {
if (collectionUri.compareTo(resourceUri) > 0) {
return null;
}

Collection collection = null;
try {
collection = broker.openCollection(collectionUri, LockMode.READ_LOCK);
if (collection == null) {
return null;
}

if (pathComponents.length == 0 || !collection.hasChildCollection(broker, XmldbURI.createInternal(pathComponents[0]))) {
return collection.getDocumentWithLock(broker, XQUERY_CONTROLLER_URI, LockMode.READ_LOCK);
collection = broker.openCollection(resourceUri, LockMode.READ_LOCK);
if (collection != null) {
final DocumentImpl doc = collection.getDocumentWithLock(broker, XQUERY_CONTROLLER_URI, LockMode.READ_LOCK);
if (doc != null) {
return doc;
}
}
} catch (final PermissionDeniedException e) {
if (LOG.isDebugEnabled()) {
Expand All @@ -800,12 +806,12 @@ DocumentImpl findDbControllerXql(final DBBroker broker, final XmldbURI collectio
}
}

final XmldbURI subCollectionUri = collectionUri.append(pathComponents[0]);
final String[] subPathComponents = new String[pathComponents.length - 1];
if (subPathComponents.length > 0) {
System.arraycopy(pathComponents, 1, subPathComponents, 0, subPathComponents.length);
if(resourceUri.numSegments() == 2) {
return null;
}
return findDbControllerXql(broker, subCollectionUri, subPathComponents);
final XmldbURI subResourceUri = resourceUri.removeLastSegment();

return findDbControllerXql(broker, collectionUri, subResourceUri);
}

private SourceInfo findSourceFromFs(final String basePath, final String[] components) {
Expand Down
13 changes: 11 additions & 2 deletions src/org/exist/jetty/JettyStart.java
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ public JettyStart() {
}

public synchronized void run() {
run(true);
}

public synchronized void run(final boolean standalone) {
final String jettyProperty = Optional.ofNullable(System.getProperty(JETTY_HOME_PROP))
.orElseGet(() -> {
final Optional<Path> home = ConfigurationHelper.getExistHome();
Expand All @@ -110,8 +114,13 @@ public synchronized void run() {
return jettyPath;
});

final Path standaloneFile = Paths.get(jettyProperty).resolve("etc").resolve(Main.STANDALONE_ENABLED_JETTY_CONFIGS);
run(new String[] { standaloneFile.toAbsolutePath().toString() }, null);
final Path jettyConfig;
if (standalone) {
jettyConfig = Paths.get(jettyProperty).resolve("etc").resolve(Main.STANDALONE_ENABLED_JETTY_CONFIGS);
} else {
jettyConfig = Paths.get(jettyProperty).resolve("etc").resolve(Main.STANDARD_ENABLED_JETTY_CONFIGS);
}
run(new String[] { jettyConfig.toAbsolutePath().toString() }, null);
}

public synchronized void run(final String[] args, final Observer observer) {
Expand Down
114 changes: 114 additions & 0 deletions test/src/org/exist/http/urlrewrite/URLRewritingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/*
* eXist Open Source Native XML Database
* Copyright (C) 2001-2018 The eXist Project
* http://exist-db.org
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/

package org.exist.http.urlrewrite;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.fluent.Executor;
import org.apache.http.client.fluent.Request;
import org.apache.http.entity.ContentType;
import org.exist.TestUtils;
import org.exist.test.ExistWebServer;
import org.exist.util.io.FastByteArrayOutputStream;
import org.exist.xmldb.XmldbURI;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;

import java.io.IOException;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.exist.http.urlrewrite.XQueryURLRewrite.XQUERY_CONTROLLER_FILENAME;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class URLRewritingTest {

private static final XmldbURI TEST_COLLECTION_NAME = XmldbURI.create("controller-test");
private static final XmldbURI TEST_COLLECTION = XmldbURI.create("/db/apps").append(TEST_COLLECTION_NAME);

private static final String TEST_CONTROLLER = "xquery version \"3.1\";\n<controller>{fn:current-dateTime()}</controller>";
private static Executor executor = null;

@ClassRule
public static final ExistWebServer existWebServer = new ExistWebServer(true, false, true, true, false);

@Test
public void findsParentController() throws IOException {
final XmldbURI nestedCollectionName = XmldbURI.create("nested");
final XmldbURI docName = XmldbURI.create("test.xml");
final String testDocument = "<hello>world</hello>";

final String storeDocUri = getRestUri() + TEST_COLLECTION.append(nestedCollectionName).append(docName);
HttpResponse response = executor.execute(Request
.Put(storeDocUri)
.bodyString(testDocument, ContentType.APPLICATION_XML)
).returnResponse();
assertEquals(HttpStatus.SC_CREATED, response.getStatusLine().getStatusCode());

final String retrieveDocUri = getAppsUri() + "/" + TEST_COLLECTION_NAME.append(nestedCollectionName).append(docName);
response = executor.execute(Request
.Get(retrieveDocUri)
).returnResponse();
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
final String responseBody;
try (final FastByteArrayOutputStream baos = new FastByteArrayOutputStream((int)response.getEntity().getContentLength())) {
response.getEntity().writeTo(baos);
responseBody = baos.toString(UTF_8);
}
assertTrue(responseBody.matches("<controller>.+</controller>"));
}

@BeforeClass
public static void setup() throws IOException {
executor = Executor.newInstance()
.auth(TestUtils.ADMIN_DB_USER, TestUtils.ADMIN_DB_PWD)
.authPreemptive("localhost");

final HttpResponse response = executor.execute(Request
.Put(getRestUri() + TEST_COLLECTION + "/" + XQUERY_CONTROLLER_FILENAME)
.bodyString(TEST_CONTROLLER, ContentType.create("application/xquery"))
).returnResponse();
assertEquals(HttpStatus.SC_CREATED, response.getStatusLine().getStatusCode());
}

@AfterClass
public static void cleanup() throws IOException {

final HttpResponse response = executor.execute(Request
.Delete(getRestUri() + TEST_COLLECTION)
).returnResponse();
assertEquals(HttpStatus.SC_OK, response.getStatusLine().getStatusCode());
}

private static String getServerUri() {
return "http://localhost:" + existWebServer.getPort() + "/exist";
}

private static String getRestUri() {
return getServerUri() + "/rest";
}

private static String getAppsUri() {
return getServerUri() + "/apps";
}
}
8 changes: 7 additions & 1 deletion test/src/org/exist/test/ExistWebServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class ExistWebServer extends ExternalResource {
private final boolean disableAutoDeploy;
private final boolean useTemporaryStorage;
private Optional<Path> temporaryStorage = Optional.empty();
private final boolean jettyStandaloneMode;

public ExistWebServer() {
this(false);
Expand All @@ -57,10 +58,15 @@ public ExistWebServer(final boolean useRandomPort, final boolean cleanupDbOnShut
}

public ExistWebServer(final boolean useRandomPort, final boolean cleanupDbOnShutdown, final boolean disableAutoDeploy, final boolean useTemporaryStorage) {
this(useRandomPort, cleanupDbOnShutdown, disableAutoDeploy, useTemporaryStorage, true);
}

public ExistWebServer(final boolean useRandomPort, final boolean cleanupDbOnShutdown, final boolean disableAutoDeploy, final boolean useTemporaryStorage, final boolean jettyStandaloneMode) {
this.useRandomPort = useRandomPort;
this.cleanupDbOnShutdown = cleanupDbOnShutdown;
this.disableAutoDeploy = disableAutoDeploy;
this.useTemporaryStorage = useTemporaryStorage;
this.jettyStandaloneMode = jettyStandaloneMode;
}

public final int getPort() {
Expand Down Expand Up @@ -94,7 +100,7 @@ protected void before() throws Throwable {
System.setProperty(PROP_JETTY_SSL_PORT, Integer.toString(nextFreePort(MIN_RANDOM_PORT, MAX_RANDOM_PORT)));

server = new JettyStart();
server.run();
server.run(jettyStandaloneMode);
}
} else {
server = new JettyStart();
Expand Down

0 comments on commit e05feca

Please sign in to comment.