Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions geowebcache/core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -145,16 +145,18 @@
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
import org.geowebcache.storage.DefaultStorageFinder;
import org.geowebcache.util.ApplicationContextProvider;
import org.geowebcache.util.GWCVars;
import org.jspecify.annotations.NonNull;
import org.springframework.context.ApplicationContext;
import org.springframework.lang.NonNull;
import org.springframework.web.context.WebApplicationContext;

/** Default implementation of ConfigurationResourceProvider that uses the file system. */
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
import static org.geotools.mbtiles.MBTilesFile.SPHERICAL_MERCATOR;
import static org.geotools.mbtiles.MBTilesFile.WORLD_ENVELOPE;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;
Expand All @@ -35,6 +32,9 @@
import org.geowebcache.grid.BoundingBox;
import org.geowebcache.layer.meta.TileJSON;
import org.geowebcache.layer.meta.VectorLayerMetadata;
import tools.jackson.core.JacksonException;
import tools.jackson.core.type.TypeReference;
import tools.jackson.databind.ObjectMapper;

/** Info Object storing basic MBTiles Cached info */
public class MBTilesInfo {
Expand Down Expand Up @@ -146,15 +146,20 @@ public void decorateTileJSON(TileJSON tileJSON) {
int index = -1;
if (json != null && ((index = json.indexOf("[")) > 0)) {
// skip the "vector_layers initial part and go straight to the array
json = json.substring(index, json.length() - 1).trim();
ObjectMapper mapper = new ObjectMapper();
List<VectorLayerMetadata> layers = null;
try {
layers = mapper.readValue(json, new TypeReference<>() {});
} catch (JsonProcessingException e) {
throw new IllegalArgumentException("Exception occurred while parsing the layers metadata. " + e);
// Find the closing bracket for the array
int endIndex = json.indexOf("]", index);
if (endIndex > 0) {
json = json.substring(index, endIndex + 1).trim();
ObjectMapper mapper = new ObjectMapper();
List<VectorLayerMetadata> layers = null;
try {
layers = mapper.readValue(json, new TypeReference<>() {});
} catch (JacksonException e) {
throw new IllegalArgumentException(
"Exception occurred while parsing the layers metadata. " + e);
}
tileJSON.setLayers(layers);
}
tileJSON.setLayers(layers);
}
}
}
Expand Down
16 changes: 4 additions & 12 deletions geowebcache/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@

<properties>
<gt.version>35-SNAPSHOT</gt.version>
<spring.version>6.2.12</spring.version>
<spring.security.version>6.5.5</spring.security.version>
<spring.version>7.0.2</spring.version>
<spring.security.version>7.0.2</spring.security.version>
<xstream.version>1.4.21</xstream.version>
<commons-codec.version>1.18.0</commons-codec.version>
<commons-fileupload.version>2.0.0-M4</commons-fileupload.version>
Expand Down Expand Up @@ -254,7 +254,6 @@
<artifactId>joda-time</artifactId>
<version>${joda-time.version}</version>
</dependency>

<!-- Jackson dependencies managed by platform-dependencies BOM -->
<dependency>
<!-- used for tests that require environment variables -->
Expand All @@ -264,13 +263,6 @@
<scope>test</scope>
</dependency>

<!-- to be moved to GeoTools once it's upgraded to httpclient 5.x -->
<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.4.4</version>
</dependency>

</dependencies>
</dependencyManagement>

Expand Down Expand Up @@ -336,7 +328,7 @@
<plugins>
<plugin>
<artifactId>maven-failsafe-plugin</artifactId>
<version>3.5.3</version>
<version>3.5.4</version>
<executions>
<execution>
<goals>
Expand Down Expand Up @@ -387,7 +379,7 @@

<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.5.3</version>
<version>3.5.4</version>
</plugin>

<plugin>
Expand Down
4 changes: 0 additions & 4 deletions geowebcache/rest/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<dependency>
<groupId>jakarta.servlet</groupId>
<artifactId>jakarta.servlet-api</artifactId>
</dependency>

<!-- test dependencies -->
<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,22 @@ public class SeedController {

/** GET method for querying running GWC tasks */
@RequestMapping(
value = "/seed.json",
value = "/seed",
method = RequestMethod.GET,
produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> doGet(HttpServletRequest req) {
return seedService.getRunningTasks(req);
}

/** GET method for querying running GWC tasks with path extension */
@RequestMapping(
value = "/seed.json",
method = RequestMethod.GET,
produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> doGetJson(HttpServletRequest req) {
return seedService.getRunningTasks(req);
}

/** GET method for querying running tasks for the provided layer */
@RequestMapping(
value = "/seed/{layer:.+}.json",
Expand Down Expand Up @@ -106,7 +115,7 @@ public ResponseEntity doPost(HttpServletRequest request) {
}

/**
* POST method for Seeding and Truncating
* POST method for Seeding and Truncating via form submission
*
* @param params Query parameters, including urlencoded form values
*/
Expand All @@ -133,6 +142,7 @@ public ResponseEntity<?> doPost(
}
}

/** POST method for JSON seeding/truncating with path extension. */
@RequestMapping(value = "/seed/{layer}.json", method = RequestMethod.POST)
public ResponseEntity<?> seedOrTruncateWithJsonPayload(
HttpServletRequest request, InputStream inputStream, @PathVariable(name = "layer") String layerName) {
Expand All @@ -142,6 +152,7 @@ public ResponseEntity<?> seedOrTruncateWithJsonPayload(
return seedService.doSeeding(request, layerName, extension, body);
}

/** POST method for XML seeding/truncating with path extension. */
@RequestMapping(value = "/seed/{layer}.xml", method = RequestMethod.POST)
public ResponseEntity<?> seedOrTruncateWithXmlPayload(
HttpServletRequest request, InputStream inputStream, @PathVariable(name = "layer") String layerName) {
Expand All @@ -151,6 +162,32 @@ public ResponseEntity<?> seedOrTruncateWithXmlPayload(
return seedService.doSeeding(request, layerName, extension, body);
}

/** POST method for JSON seeding/truncating without path extension. */
@RequestMapping(
value = "/seed/{layer:[^.]+}",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<?> seedOrTruncateJson(
HttpServletRequest request, InputStream inputStream, @PathVariable(name = "layer") String layerName) {

String body = readBody(inputStream);
String extension = "json";
return seedService.doSeeding(request, layerName, extension, body);
}

/** POST method for XML seeding/truncating without path extension. */
@RequestMapping(
value = "/seed/{layer:[^.]+}",
method = RequestMethod.POST,
consumes = {MediaType.APPLICATION_XML_VALUE, MediaType.TEXT_XML_VALUE})
public ResponseEntity<?> seedOrTruncateXml(
HttpServletRequest request, InputStream inputStream, @PathVariable(name = "layer") String layerName) {

String body = readBody(inputStream);
String extension = "xml";
return seedService.doSeeding(request, layerName, extension, body);
}

private String readBody(InputStream inputStream) {
return new BufferedReader(new InputStreamReader(inputStream)).lines().collect(Collectors.joining("\n"));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/**
* 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 3 of the License, or (at your option) any
* later version.
*
* <p>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 General Public License for more details.
*
* <p>You should have received a copy of the GNU Lesser General Public License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*
* @author Cécile Vuilleumier, Camptocamp, Copyright 2026
*/
package org.geowebcache.rest.filter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Servlet filter for GeoWebCache
*
* <p>Extracts the path suffix (extension) and stores it for content negotiation. Removes the extension from the path
* for path mapping.
*/
public class SuffixStripFilter implements Filter {

private static final Pattern EXTENSION_PATTERN = Pattern.compile("^(.*?)\\.(json|xml)$");

public static final String FORMAT_ATTRIBUTE = "gwc.formatExtension";

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {

if (request instanceof HttpServletRequest httpRequest) {
String requestURI = httpRequest.getRequestURI();
Matcher matcher = EXTENSION_PATTERN.matcher(requestURI);

if (matcher.matches()) {
String pathWithoutExtension = matcher.group(1);
String extension = matcher.group(2);

// Wrap the request to return modified paths
HttpServletRequestWrapper wrapper = new HttpServletRequestWrapper(httpRequest) {
@Override
public String getRequestURI() {
return pathWithoutExtension;
}

@Override
public StringBuffer getRequestURL() {
StringBuffer url =
new StringBuffer(super.getRequestURL().toString());
int extIndex = url.lastIndexOf("." + extension);
if (extIndex > 0) {
url.delete(extIndex, url.length());
}
return url;
}

@Override
public String getServletPath() {
String servletPath = super.getServletPath();
return servletPath.replaceFirst("\\." + extension + "$", "");
}
};

// Store extension for content negotiation
wrapper.setAttribute(FORMAT_ATTRIBUTE, extension);

chain.doFilter(wrapper, response);
return;
}
}

// No extension found, pass through unchanged
chain.doFilter(request, response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* 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 3 of the License, or (at your option) any
* later version.
*
* <p>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 General Public License for more details.
*
* <p>You should have received a copy of the GNU Lesser General Public License along with this program. If not, see
* <http://www.gnu.org/licenses/>.
*
* @author Cécile Vuilleumier, Camptocamp, Copyright 2026
*/
package org.geowebcache.rest.negotiation;

import jakarta.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.List;
import org.springframework.http.MediaType;
import org.springframework.web.accept.ContentNegotiationStrategy;
import org.springframework.web.context.request.NativeWebRequest;

/**
* Spring ContentNegotiationStrategy for GeoWebCache
*
* <p>Reads the media type stored by {@link org.geowebcache.rest.filter.SuffixStripFilter}
*/
public class SuffixContentNegotiationStrategy implements ContentNegotiationStrategy {

List<MediaType> MEDIA_TYPE_ALL_LIST = Collections.singletonList(MediaType.ALL);

public static final String FORMAT_ATTRIBUTE = "gwc.formatExtension";

@Override
public List<MediaType> resolveMediaTypes(NativeWebRequest request) {
HttpServletRequest servletRequest = request.getNativeRequest(HttpServletRequest.class);
if (servletRequest == null) {
return MEDIA_TYPE_ALL_LIST;
}
// Check if filter stored the extension
String extension = (String) servletRequest.getAttribute(FORMAT_ATTRIBUTE);

if (extension != null) {
if ("json".equals(extension)) {
return Collections.singletonList(MediaType.APPLICATION_JSON);
} else if ("xml".equals(extension)) {
return Collections.singletonList(MediaType.APPLICATION_XML);
}
}
return MEDIA_TYPE_ALL_LIST;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@SuppressWarnings("deprecation")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"file*:/webapp/WEB-INF/web.xml", "file*:/webapp/WEB-INF/geowebcache-servlet.xml"})
public class BoundsControllerTest {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@SuppressWarnings("deprecation")
@RunWith(SpringRunner.class)
@WebAppConfiguration()
@ContextConfiguration({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@SuppressWarnings("deprecation")
@RunWith(SpringRunner.class)
@WebAppConfiguration()
@ContextConfiguration({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@SuppressWarnings("deprecation")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"file*:/webapp/WEB-INF/web.xml", "file*:/webapp/WEB-INF/geowebcache-servlet.xml"})
public class ByteStreamControllerTest {
Expand Down
Loading
Loading