Skip to content
This repository has been archived by the owner on Feb 23, 2023. It is now read-only.

Commit

Permalink
Fix static resource handling with GraalVM 21.2
Browse files Browse the repository at this point in the history
  • Loading branch information
sdeleuze committed Oct 28, 2021
1 parent c601eb2 commit 2d0d301
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 1 deletion.
1 change: 1 addition & 0 deletions samples/webmvc-tomcat/src/main/resources/static/foo.html
@@ -0,0 +1 @@
Foo
7 changes: 6 additions & 1 deletion samples/webmvc-tomcat/verify.sh
@@ -1,7 +1,12 @@
#!/usr/bin/env bash
RESPONSE=`curl -s localhost:8080/`
if [[ "$RESPONSE" == 'Hello from Spring MVC and Tomcat' ]]; then
exit 0
RESPONSE=`curl -s localhost:8080/foo.html`
if [[ "$RESPONSE" == 'Foo' ]]; then
exit 0
else
exit 1
fi
else
exit 1
fi
@@ -0,0 +1,17 @@
package org.springframework.nativex.substitutions.framework;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.TargetClass;

import org.springframework.context.ApplicationContext;
import org.springframework.nativex.substitutions.OnlyIfPresent;

@TargetClass(className = "org.springframework.context.support.ApplicationObjectSupport", onlyWith = OnlyIfPresent.class)
final class Target_ApplicationObjectSupport {

@Alias
protected ApplicationContext obtainApplicationContext() {
return null;
}

}
@@ -0,0 +1,85 @@
package org.springframework.nativex.substitutions.framework;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;

import org.springframework.context.ApplicationContext;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.nativex.substitutions.OnlyIfPresent;
import org.springframework.util.StringValueResolver;
import org.springframework.web.context.support.ServletContextResource;

// Workaround for https://github.com/spring-projects-experimental/spring-native/issues/1174 with GraalVM 21.2.0 (works fine with GraalVM 21.3.0)
@TargetClass(className = "org.springframework.web.servlet.resource.ResourceHttpRequestHandler", onlyWith = OnlyIfPresent.class)
final class Target_ResourceHttpRequestHandler {

@Alias
private List<String> locationValues;

@Alias
private List<Resource> locationResources;

@Alias
private List<Resource> locationsToUse;

@Alias
private Map<Resource, Charset> locationCharsets;

@Alias
private StringValueResolver embeddedValueResolver;

@Substitute
private void resolveResourceLocations() {
List<Resource> result = new ArrayList<>();
if (!this.locationValues.isEmpty()) {
ApplicationContext applicationContext = ((Target_ApplicationObjectSupport)(Object)this).obtainApplicationContext();
for (String location : this.locationValues) {
if (this.embeddedValueResolver != null) {
String resolvedLocation = this.embeddedValueResolver.resolveStringValue(location);
if (resolvedLocation == null) {
throw new IllegalArgumentException("Location resolved to null: " + location);
}
location = resolvedLocation;
}
Charset charset = null;
location = location.trim();
if (location.startsWith("[charset=")) {
int endIndex = location.indexOf(']', "[charset=".length());
if (endIndex == -1) {
throw new IllegalArgumentException("Invalid charset syntax in location: " + location);
}
String value = location.substring("[charset=".length(), endIndex);
charset = Charset.forName(value);
location = location.substring(endIndex + 1);
}
Resource resource = applicationContext.getResource(location);
if (location.equals("/") && !(resource instanceof ServletContextResource)) {
throw new IllegalStateException(
"The String-based location \"/\" should be relative to the web application root " +
"but resolved to a Resource of type: " + resource.getClass() + ". " +
"If this is intentional, please pass it as a pre-configured Resource via setLocations.");
}
result.add(resource);
if (charset != null) {
if (!(resource instanceof UrlResource)) {
throw new IllegalArgumentException("Unexpected charset for non-UrlResource: " + resource);
}
this.locationCharsets.put(resource, charset);
}
}
}

result.addAll(this.locationResources);

this.locationsToUse.clear();
this.locationsToUse.addAll(result);
}

}
@@ -0,0 +1,49 @@
package org.springframework.nativex.substitutions.framework;

import java.util.ArrayList;
import java.util.List;

import com.oracle.svm.core.annotate.Alias;
import com.oracle.svm.core.annotate.Substitute;
import com.oracle.svm.core.annotate.TargetClass;

import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.nativex.substitutions.OnlyIfPresent;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

// Workaround for https://github.com/spring-projects-experimental/spring-native/issues/1174 with GraalVM 21.2.0 (works fine with GraalVM 21.3.0)
@TargetClass(className = "org.springframework.web.reactive.resource.ResourceWebHandler", onlyWith = OnlyIfPresent.class)
final class Target_ResourceWebHandler {

@Alias
private List<String> locationValues;

@Alias
private List<Resource> locationResources;

@Alias
private List<Resource> locationsToUse;

@Alias
private ResourceLoader resourceLoader;

@Substitute
private void resolveResourceLocations() {
List<Resource> result = new ArrayList<>(this.locationResources);

if (!this.locationValues.isEmpty()) {
Assert.notNull(this.resourceLoader,
"ResourceLoader is required when \"locationValues\" are configured.");
Assert.isTrue(CollectionUtils.isEmpty(this.locationResources), "Please set " +
"either Resource-based \"locations\" or String-based \"locationValues\", but not both.");
for (String location : this.locationValues) {
result.add(this.resourceLoader.getResource(location));
}
}

this.locationsToUse.clear();
this.locationsToUse.addAll(result);
}
}

0 comments on commit 2d0d301

Please sign in to comment.