Created
November 17, 2015 16:00
-
-
Save ieugen/6a02788daa0cff050920 to your computer and use it in GitHub Desktop.
Vertx Fix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import io.vertx.core.AsyncResult; | |
import io.vertx.core.Future; | |
import io.vertx.core.Handler; | |
import io.vertx.core.Vertx; | |
import io.vertx.core.VertxException; | |
import io.vertx.core.buffer.Buffer; | |
import io.vertx.core.file.FileSystem; | |
import io.vertx.ext.web.RoutingContext; | |
import io.vertx.ext.web.impl.Utils; | |
import io.vertx.ext.web.templ.ThymeleafTemplateEngine; | |
import lombok.Data; | |
import org.thymeleaf.TemplateEngine; | |
import org.thymeleaf.TemplateProcessingParameters; | |
import org.thymeleaf.context.IContext; | |
import org.thymeleaf.context.VariablesMap; | |
import org.thymeleaf.resourceresolver.IResourceResolver; | |
import org.thymeleaf.templateresolver.TemplateResolver; | |
import java.io.BufferedInputStream; | |
import java.io.ByteArrayInputStream; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.io.UnsupportedEncodingException; | |
import java.io.Writer; | |
import java.nio.file.Paths; | |
import java.util.List; | |
/** | |
* Fixed in master ( > 3.1.0): https://github.com/vert-x3/vertx-web/issues/242 | |
*/ | |
@Data | |
public class ThymeleafTemplateEngineImpl implements ThymeleafTemplateEngine { | |
private final TemplateEngine engine = new TemplateEngine(); | |
private final TemplateResolver templateResolver; | |
private final ResourceResolver resolver = new ResourceResolver(); | |
public ThymeleafTemplateEngineImpl() { | |
templateResolver = new TemplateResolver(); | |
templateResolver.setTemplateMode(io.vertx.ext.web.templ.ThymeleafTemplateEngine.DEFAULT_TEMPLATE_MODE); | |
templateResolver.setResourceResolver(resolver); | |
engine.setTemplateResolver(templateResolver); | |
} | |
@Override | |
public io.vertx.ext.web.templ.ThymeleafTemplateEngine setMode(String mode) { | |
templateResolver.setTemplateMode(mode); | |
return this; | |
} | |
@Override | |
public void render(RoutingContext context, String templateFileName, Handler<AsyncResult<Buffer>> handler) { | |
Buffer buffer = Buffer.buffer(); | |
try { | |
// Not very happy making a copy here... and it seems Thymeleaf copies the data again internally as well... | |
VariablesMap<String, Object> data = new VariablesMap<>(); | |
data.put("context", context); | |
// Need to synchronized to make sure right Vert.x is used! | |
synchronized (this) { | |
resolver.setVertx(context.vertx()); | |
final List<io.vertx.ext.web.Locale> acceptableLocales = context.acceptableLocales(); | |
io.vertx.ext.web.Locale locale; | |
if (acceptableLocales.size() == 0) { | |
locale = io.vertx.ext.web.Locale.create(); | |
} else { | |
// this is the users preferred locale | |
locale = acceptableLocales.get(0); | |
} | |
engine.process(templateFileName, new WebIContext(data, locale), new Writer() { | |
@Override | |
public void write(char[] cbuf, int off, int len) throws IOException { | |
buffer.appendString(new String(cbuf, off, len)); | |
} | |
@Override | |
public void flush() throws IOException { | |
} | |
@Override | |
public void close() throws IOException { | |
} | |
}); | |
} | |
handler.handle(Future.succeededFuture(buffer)); | |
} catch (Exception ex) { | |
handler.handle(Future.failedFuture(ex)); | |
} | |
} | |
@Override | |
public TemplateEngine getThymeleafTemplateEngine() { | |
return engine; | |
} | |
/* | |
We extend VariablesMap to avoid copying all context map data for each render | |
We put the context data Map directly into the variable map and we also provide | |
variables called: | |
_context - this is the routing context itself | |
_request - this is the HttpServerRequest object | |
_response - this is the HttpServerResponse object | |
*/ | |
private static class WebIContext implements IContext { | |
private final VariablesMap<String, Object> data; | |
private final java.util.Locale locale; | |
private WebIContext(VariablesMap<String, Object> data, io.vertx.ext.web.Locale locale) { | |
this.data = data; | |
this.locale = new java.util.Locale(locale.language() == null ? "" : locale.language(), | |
locale.country() == null ? "" : locale.country(), | |
locale.variant() == null ? "" : locale.variant()); | |
} | |
@Override | |
public VariablesMap<String, Object> getVariables() { | |
return data; | |
} | |
@Override | |
public java.util.Locale getLocale() { | |
return locale; | |
} | |
@Override | |
public void addContextExecutionInfo(String templateName) { | |
} | |
} | |
private static class ResourceResolver implements IResourceResolver { | |
private Vertx vertx; | |
void setVertx(Vertx vertx) { | |
this.vertx = vertx; | |
} | |
@Override | |
public String getName() { | |
return "vertx-web/Thymeleaf"; | |
} | |
@Override | |
public InputStream getResourceAsStream(TemplateProcessingParameters templateProcessingParameters, String resourceName) { | |
String resolvedResourceName = resolveTemplateName(resourceName); | |
String str = Utils.readFileToString(vertx, resolvedResourceName); | |
try { | |
ByteArrayInputStream bis = new ByteArrayInputStream(str.getBytes("UTF-8")); | |
return new BufferedInputStream(bis); | |
} catch (UnsupportedEncodingException e) { | |
throw new VertxException(e); | |
} | |
} | |
private String resolveTemplateName(String resourceName) { | |
String withHtml = resourceName + ".html"; | |
String withIndexHtml = Paths.get(resourceName, "index.html").toString(); | |
if (resourceIsFile(resourceName)) { | |
return resourceName; | |
} else if (resourceIsFile(withHtml)) { | |
return withHtml; | |
} else if (resourceIsFile(withIndexHtml)) { | |
return withIndexHtml; | |
} | |
throw new VertxException("Template not found " + resourceName); | |
} | |
private boolean resourceIsFile(String resourceName) { | |
FileSystem fs = vertx.fileSystem(); | |
return fs.existsBlocking(resourceName) && fs.propsBlocking(resourceName).isRegularFile(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment