add j2html
This commit is contained in:
parent
30926d6052
commit
d38f2d351e
11 changed files with 546 additions and 5 deletions
4
net-http-j2html/build.gradle
Normal file
4
net-http-j2html/build.gradle
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
dependencies {
|
||||||
|
api project(':net-http-server')
|
||||||
|
api libs.j2html
|
||||||
|
}
|
9
net-http-j2html/src/main/java/module-info.java
Normal file
9
net-http-j2html/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
module org.xbib.net.http.j2html {
|
||||||
|
exports org.xbib.net.http.j2html;
|
||||||
|
requires org.xbib.net;
|
||||||
|
requires org.xbib.net.http;
|
||||||
|
requires org.xbib.net.http.server;
|
||||||
|
requires org.xbib.config;
|
||||||
|
requires com.j2html;
|
||||||
|
requires java.logging;
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package org.xbib.net.http.j2html;
|
||||||
|
|
||||||
|
import org.xbib.net.Attributes;
|
||||||
|
import org.xbib.net.Resource;
|
||||||
|
import org.xbib.net.buffer.DataBuffer;
|
||||||
|
import org.xbib.net.http.HttpResponseStatus;
|
||||||
|
import org.xbib.net.http.server.application.Application;
|
||||||
|
import org.xbib.net.http.server.resource.HtmlTemplateResource;
|
||||||
|
import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler;
|
||||||
|
import org.xbib.net.http.server.route.HttpRouterContext;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import static j2html.TagCreator.body;
|
||||||
|
import static j2html.TagCreator.h1;
|
||||||
|
import static org.xbib.net.http.HttpHeaderNames.CONTENT_TYPE;
|
||||||
|
|
||||||
|
public class J2HtmlResourceHandler extends HtmlTemplateResourceHandler {
|
||||||
|
|
||||||
|
public J2HtmlResourceHandler() {
|
||||||
|
this(null, "java", "index.java");
|
||||||
|
}
|
||||||
|
|
||||||
|
public J2HtmlResourceHandler(Path root, String suffix, String indexFileName) {
|
||||||
|
super(root, suffix, indexFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Resource createResource(HttpRouterContext httpRouterContext) throws IOException {
|
||||||
|
return new J2HtmlResource(this, httpRouterContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static class J2HtmlResource extends HtmlTemplateResource {
|
||||||
|
|
||||||
|
private static final Logger logger = Logger.getLogger(J2HtmlResource.class.getName());
|
||||||
|
|
||||||
|
protected J2HtmlResource(HtmlTemplateResourceHandler templateResourceHandler, HttpRouterContext httpRouterContext) throws IOException {
|
||||||
|
super(templateResourceHandler, httpRouterContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(HttpRouterContext context) throws IOException {
|
||||||
|
Application application = context.getAttributes().get(Application.class, "application");
|
||||||
|
if (application == null) {
|
||||||
|
logger.log(Level.WARNING, "application is null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DataBuffer dataBuffer = context.getDataBufferFactory().allocateBuffer();
|
||||||
|
dataBuffer.write(render(application, context.getAttributes()), StandardCharsets.UTF_8);
|
||||||
|
HttpResponseStatus httpResponseStatus = context.getAttributes().get(HttpResponseStatus.class, "_status", HttpResponseStatus.OK);
|
||||||
|
context.status(httpResponseStatus)
|
||||||
|
.header("cache-control", "no-cache") // override default must-revalidate behavior
|
||||||
|
.header("content-length", Integer.toString(dataBuffer.writePosition()))
|
||||||
|
.header(CONTENT_TYPE, "text/html; charset=" + StandardCharsets.UTF_8.displayName())
|
||||||
|
.body(dataBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String render(Application application, Attributes attributes) {
|
||||||
|
return body(
|
||||||
|
h1("Hello World")
|
||||||
|
).render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.xbib.net.http.j2html;
|
||||||
|
|
||||||
|
import org.xbib.net.http.server.service.BaseHttpService;
|
||||||
|
import org.xbib.net.http.server.service.BaseHttpServiceBuilder;
|
||||||
|
|
||||||
|
public class J2HtmlService extends BaseHttpService {
|
||||||
|
|
||||||
|
protected J2HtmlService(BaseHttpServiceBuilder builder) {
|
||||||
|
super(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static J2HtmlServiceBuilder builder() {
|
||||||
|
return new J2HtmlServiceBuilder();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.xbib.net.http.j2html;
|
||||||
|
|
||||||
|
import org.xbib.net.ParameterDefinition;
|
||||||
|
import org.xbib.net.http.HttpMethod;
|
||||||
|
import org.xbib.net.http.server.HttpHandler;
|
||||||
|
import org.xbib.net.http.server.domain.HttpSecurityDomain;
|
||||||
|
import org.xbib.net.http.server.service.BaseHttpServiceBuilder;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class J2HtmlServiceBuilder extends BaseHttpServiceBuilder {
|
||||||
|
|
||||||
|
protected Path prefix;
|
||||||
|
|
||||||
|
protected String suffix;
|
||||||
|
|
||||||
|
public J2HtmlServiceBuilder() {
|
||||||
|
super();
|
||||||
|
this.prefix = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public J2HtmlServiceBuilder setPath(String path) {
|
||||||
|
super.setPath(path);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public J2HtmlServiceBuilder setMethod(HttpMethod... httpMethod) {
|
||||||
|
super.setMethod(httpMethod);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public J2HtmlServiceBuilder setHandler(HttpHandler... handler) {
|
||||||
|
super.setHandler(handler);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public J2HtmlServiceBuilder setParameterDefinition(ParameterDefinition... parameterDefinition) {
|
||||||
|
super.setParameterDefinition(parameterDefinition);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public J2HtmlServiceBuilder setSecurityDomain(HttpSecurityDomain securityDomain) {
|
||||||
|
super.setSecurityDomain(securityDomain);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public J2HtmlServiceBuilder setPrefix(Path prefix) {
|
||||||
|
this.prefix = prefix;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public J2HtmlServiceBuilder setSuffix(String suffix) {
|
||||||
|
this.suffix = suffix;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public J2HtmlService build() {
|
||||||
|
if (this.handlers == null) {
|
||||||
|
HttpHandler httpHandler = new J2HtmlResourceHandler(prefix, suffix, "index.java");
|
||||||
|
setHandler(httpHandler);
|
||||||
|
}
|
||||||
|
return new J2HtmlService(this);
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ dependencies {
|
||||||
api project(':net-http-server-netty-secure')
|
api project(':net-http-server-netty-secure')
|
||||||
api project(':net-http-server-application-config')
|
api project(':net-http-server-application-config')
|
||||||
api project(':net-http-template-groovy')
|
api project(':net-http-template-groovy')
|
||||||
|
api project(':net-http-j2html')
|
||||||
api libs.jdbc.query
|
api libs.jdbc.query
|
||||||
implementation libs.webjars.bootstrap
|
implementation libs.webjars.bootstrap
|
||||||
implementation libs.webjars.jquery
|
implementation libs.webjars.jquery
|
||||||
|
@ -12,7 +13,7 @@ dependencies {
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
mainClass.set('org.xbib.net.http.server.application.web.Bootstrap')
|
mainClass.set('org.xbib.net.http.server.application.web.j2html.Bootstrap')
|
||||||
applicationDefaultJvmArgs = [
|
applicationDefaultJvmArgs = [
|
||||||
'-Dfile.encoding=UTF-8',
|
'-Dfile.encoding=UTF-8',
|
||||||
'-Duser.language=de',
|
'-Duser.language=de',
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
module org.xbib.net.http.server.application.web {
|
module org.xbib.net.http.server.application.web {
|
||||||
uses org.xbib.config.ConfigLogger;
|
uses org.xbib.config.ConfigLogger;
|
||||||
exports org.xbib.net.http.server.application.web;
|
exports org.xbib.net.http.server.application.web;
|
||||||
|
exports org.xbib.net.http.server.application.web.groovy;
|
||||||
requires org.xbib.net;
|
requires org.xbib.net;
|
||||||
requires org.xbib.net.mime;
|
requires org.xbib.net.mime;
|
||||||
requires org.xbib.net.http;
|
requires org.xbib.net.http;
|
||||||
|
@ -8,8 +9,10 @@ module org.xbib.net.http.server.application.web {
|
||||||
requires org.xbib.net.http.server.netty;
|
requires org.xbib.net.http.server.netty;
|
||||||
requires org.xbib.net.http.server.netty.secure;
|
requires org.xbib.net.http.server.netty.secure;
|
||||||
requires org.xbib.net.http.template.groovy;
|
requires org.xbib.net.http.template.groovy;
|
||||||
|
requires org.xbib.net.http.j2html;
|
||||||
requires org.xbib.datastructures.tiny;
|
requires org.xbib.datastructures.tiny;
|
||||||
requires org.xbib.jdbc.query;
|
requires org.xbib.jdbc.query;
|
||||||
requires org.xbib.config;
|
requires org.xbib.config;
|
||||||
requires java.logging;
|
requires java.logging;
|
||||||
|
requires com.j2html;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package org.xbib.net.http.server.application.web;
|
package org.xbib.net.http.server.application.web.groovy;
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
import org.xbib.config.ConfigLoader;
|
import org.xbib.config.ConfigLoader;
|
||||||
|
@ -14,6 +15,9 @@ import org.xbib.net.http.HttpHeaderNames;
|
||||||
import org.xbib.net.http.HttpHeaderValues;
|
import org.xbib.net.http.HttpHeaderValues;
|
||||||
import org.xbib.net.http.HttpResponseStatus;
|
import org.xbib.net.http.HttpResponseStatus;
|
||||||
import org.xbib.net.http.HttpVersion;
|
import org.xbib.net.http.HttpVersion;
|
||||||
|
import org.xbib.net.http.j2html.J2HtmlResourceHandler;
|
||||||
|
import org.xbib.net.http.j2html.J2HtmlService;
|
||||||
|
import org.xbib.net.http.server.application.web.WebApplication;
|
||||||
import org.xbib.net.http.server.domain.BaseHttpDomain;
|
import org.xbib.net.http.server.domain.BaseHttpDomain;
|
||||||
import org.xbib.net.http.server.domain.BaseHttpSecurityDomain;
|
import org.xbib.net.http.server.domain.BaseHttpSecurityDomain;
|
||||||
import org.xbib.net.http.server.domain.HttpSecurityDomain;
|
import org.xbib.net.http.server.domain.HttpSecurityDomain;
|
||||||
|
@ -39,7 +43,6 @@ import org.xbib.net.http.template.groovy.GroovyInternalServerErrorHandler;
|
||||||
import org.xbib.net.http.template.groovy.GroovyHttpStatusHandler;
|
import org.xbib.net.http.template.groovy.GroovyHttpStatusHandler;
|
||||||
import org.xbib.net.http.template.groovy.GroovyTemplateResourceHandler;
|
import org.xbib.net.http.template.groovy.GroovyTemplateResourceHandler;
|
||||||
import org.xbib.net.http.template.groovy.GroovyTemplateService;
|
import org.xbib.net.http.template.groovy.GroovyTemplateService;
|
||||||
import org.xbib.net.mime.stream.Hex;
|
|
||||||
import org.xbib.settings.Settings;
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
public final class Bootstrap {
|
public final class Bootstrap {
|
||||||
|
@ -164,7 +167,7 @@ public final class Bootstrap {
|
||||||
.setHandler(ctx -> {
|
.setHandler(ctx -> {
|
||||||
ctx.status(HttpResponseStatus.OK)
|
ctx.status(HttpResponseStatus.OK)
|
||||||
.header(HttpHeaderNames.CONTENT_TYPE, "image/x-icon")
|
.header(HttpHeaderNames.CONTENT_TYPE, "image/x-icon")
|
||||||
.body(NettyDataBufferFactory.getInstance().wrap(Hex.fromHex(hexFavIcon)))
|
.body(NettyDataBufferFactory.getInstance().wrap(fromHex(hexFavIcon)))
|
||||||
.done();
|
.done();
|
||||||
})
|
})
|
||||||
.build())
|
.build())
|
||||||
|
@ -173,6 +176,11 @@ public final class Bootstrap {
|
||||||
.setHandler(new ClassLoaderResourceHandler(Bootstrap.class.getClassLoader(), "META-INF/resources/"))
|
.setHandler(new ClassLoaderResourceHandler(Bootstrap.class.getClassLoader(), "META-INF/resources/"))
|
||||||
.build())
|
.build())
|
||||||
.addService(httpService)
|
.addService(httpService)
|
||||||
|
.addService(J2HtmlService.builder()
|
||||||
|
.setPrefix("/j2html")
|
||||||
|
.setPath("glob:**")
|
||||||
|
.setHandler(new J2HtmlResourceHandler())
|
||||||
|
.build())
|
||||||
.addService(GroovyTemplateService.builder()
|
.addService(GroovyTemplateService.builder()
|
||||||
.setTemplateName("index.gtpl")
|
.setTemplateName("index.gtpl")
|
||||||
.setSecurityDomain(securityDomain)
|
.setSecurityDomain(securityDomain)
|
||||||
|
@ -205,5 +213,66 @@ public final class Bootstrap {
|
||||||
|
|
||||||
|
|
||||||
private static final String hexFavIcon =
|
private static final String hexFavIcon =
|
||||||
"00000100010010100000010020006804000016000000280000001000000020000000010020000000000040040000130b0000130b0000000000000000000000000000000000000000000000000000000000005140322f62524a536050475f5140322f5140320c000000000000000000000000000000000000000000000000000000000000000000000000fffffe40b1a9a5c76f605bff6f605bff6f605bff6f605bff6b5b55f38f7d71ff978473bf877465100000000000000000000000000000000000000000fffffe8ff2eeeafff2f0eeffb7b0adff786a65ff6f605bff6f605bff6f605bff6f605bff72625af77f6d60bf00000000000000000000000000000000fffffe8fd9ccc0fffbfaf9fffbfaf8fffbfaf8fff6f5f5ff9c928eff6f605bff786a65ff6f605bff6f605bff716159ff6d5d4f9f0000000000000000fffffe40e7e0d8ffcfbfb2ffc4b2a0ffcebdafffccbbabffe1d6ceffe7ded7ffd2cdccff786a65ff6f605bff6f605bff6c5c54ff6a5a4ffb6050425000000000faf9f6afd3c5b8ffd4c6baffcfc1b2ffd5c7bbffcab9a9ffe7ded7fff2f0efff786a65ff6f605bff6f605bff6f605bff6c5c53ff6b5b53fb5d4d3fdf00000000e9e2dbffd8ccc0ffdcd1c5ffdcd1c6ffd4c7b9ffdacec3ffffffffffd2cdccff6f605bff6f605bff6f605bff6f605bff6a5a4fff6b5b52ff5b4b3eef53443660ece7e0ffdbd0c5ffe0d6ccffe9e2d9ffe3dad1fff1ece8ffffffffffc0b9b7ff6f605bff6f605bff6f605bff6f605bff685749ff6a5a4fff5e4e43cf5142348fefe9e3ffe0d7ccffe9e1d9ffeae3dbffe3dbd0fff4f0ecffffffffffdbd7d6ff6f605bff6f605bff6f605bff6d5e56ff675648ff6a5a4fff5e4f44af514233bfefeae4ffe8e0d7ffebe5ddffede8dfffebe5dcfff2eee8ffffffffffffffffff817470ff6f605bff6f605aff69594dff685749ff6b5b52ff5c4d429f5142338ff9f7f4afeae3dbffe7e1d6ffece7ddffefebe3fff1ece7ffffffffffffffffffdbd7d6ff6f605bff6a5a4fff68574bff6a5a50ff6b5b54f7554638574f403150fffffe40f1ede7ffece7dfffebe5dcffeae3dbfffbf9f7fffffffffffffffffff8f5f3ff83756dff69584dff69584cff6b5b52ff675750af000000004e3f304000000000fcfbf99fede7e0ffe4dbd1fff6f3effffffffffff9f8f6ffe1d7ceffdbcfc5ff9b8a7cff68574aff6a594eff6b5b54e751403218000000004e3f30100000000000000000fbfaf89fece6dfffeee9e3ffe4dbd2ffd8cbbfffd8ccc0ffcdbcadff6f5e52ff6a5a50ff6b5b54e75d4d4328000000000000000000000000000000000000000000000000fffffe60f6f4f0cff1ece7ffe2d9d0ffdbcec3ffccc1b7ff6a5a52f7675750af51403218000000000000000000000000000000000000000000000000000000000000000000000000fffffe10fffffe40fffffe40fffffe205140320c000000000000000000000000000000000000000000000000f83f9407e0070000c0079807800300000001603f0001603f0000603f0000603f0000e13e0000e23e0000e23e0002e23e8002e23ec007e33ee00fe33ef83fe33";
|
"000001000100101000000100200068040000160000002800000010000000" +
|
||||||
|
"200000000100200000000000000000000000000000000000000000000000" +
|
||||||
|
"000099330000993300009933000099330000993300009933000099330000" +
|
||||||
|
"993300009933000099330000993300009933000099330000993300009933" +
|
||||||
|
"00009933000099330000993300009933000099330000993300ff993300ff" +
|
||||||
|
"993300ff993300ff993300ff993300ff993300ff993300ff993300ff9933" +
|
||||||
|
"0000993300009933000099330000993300009933000099330000993300ff" +
|
||||||
|
"993300ff993300ff993300ff993300ff993300ff993300ff993300ff9933" +
|
||||||
|
"00ff99330000993300009933000099330000993300009933000099330000" +
|
||||||
|
"993300ff9933000099330000993300009933000099330000993300009933" +
|
||||||
|
"00009933000099330000993300009933000099330000993300ff993300ff" +
|
||||||
|
"99330000993300ff99330000993300ff993300ff993300ff993300ff9933" +
|
||||||
|
"00ff993300ff993300ff993300ff993300ff9933000099330000993300ff" +
|
||||||
|
"993300ff99330000993300ff99330000993300ff993300ff993300ff9933" +
|
||||||
|
"00ff993300ff993300ff993300ff993300ff993300ff9933000000000000" +
|
||||||
|
"993300ff993300ff00000000993300ff0000000000000000000000000000" +
|
||||||
|
"00000000000000000000000000000000000099330000993300ff99330000" +
|
||||||
|
"00000000993300ff993300ff00000000993300ff00000000000000000000" +
|
||||||
|
"0000000000000000000000000000993300ff993300ff00000000993300ff" +
|
||||||
|
"0000000000000000993300ff993300ff00000000993300ff993300009933" +
|
||||||
|
"000099330000993300009933000099330000993300ff993300ff99330000" +
|
||||||
|
"993300ff9933000000000000993300ff993300ff00000000993300ff9933" +
|
||||||
|
"00009933000099330000993300009933000099330000993300ff993300ff" +
|
||||||
|
"99330000993300ff9933000000000000993300ff993300ff000000009933" +
|
||||||
|
"00ff993300009933000099330000993300009933000099330000993300ff" +
|
||||||
|
"993300ff99330000993300ff9933000000000000993300ff993300ff0000" +
|
||||||
|
"000099330000993300009933000099330000993300009933000099330000" +
|
||||||
|
"993300ff993300ff99330000993300ff9933000000000000993300ff9933" +
|
||||||
|
"00ff00000000993300ff993300ff993300ff993300ff993300ff993300ff" +
|
||||||
|
"993300ff993300ff993300ff99330000993300ff99330000000000009933" +
|
||||||
|
"00ff993300ff000000009933000099330000993300009933000099330000" +
|
||||||
|
"993300009933000099330000993300009933000099330000993300000000" +
|
||||||
|
"0000993300ff993300ff993300ff993300ff993300ff993300ff993300ff" +
|
||||||
|
"993300ff993300ff993300ff993300ff993300ff99330000993300009933" +
|
||||||
|
"000000000000000000000000000000000000993300009933000099330000" +
|
||||||
|
"993300009933000099330000993300009933000099330000993300009933" +
|
||||||
|
"000099330000ffff0000f0070000f0070000f7ff00009401000094010000" +
|
||||||
|
"97fd000097e5000097e5000097e5000097e500009fe50000900500009fff" +
|
||||||
|
"000080070000ffff0000";
|
||||||
|
|
||||||
|
|
||||||
|
private static byte[] fromHex(String hex) {
|
||||||
|
Objects.requireNonNull(hex);
|
||||||
|
int len = hex.length();
|
||||||
|
byte[] data = new byte[len / 2];
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data[i / 2] = (byte) fromHex(hex.charAt(i), hex.charAt(i + 1));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int fromHex(int b1, int b2) {
|
||||||
|
int i1 = Character.digit(b1, 16);
|
||||||
|
if (i1 == -1) {
|
||||||
|
throw new IllegalArgumentException("invalid character in hexadecimal: " + b1);
|
||||||
|
}
|
||||||
|
int i2 = Character.digit(b2, 16);
|
||||||
|
if (i2 == -1) {
|
||||||
|
throw new IllegalArgumentException("invalid character in hexadecimal: " + b2);
|
||||||
|
}
|
||||||
|
return (i1 << 4) + i2;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,264 @@
|
||||||
|
package org.xbib.net.http.server.application.web.j2html;
|
||||||
|
|
||||||
|
import org.xbib.config.ConfigLoader;
|
||||||
|
import org.xbib.config.ConfigLogger;
|
||||||
|
import org.xbib.config.ConfigParams;
|
||||||
|
import org.xbib.config.SystemConfigLogger;
|
||||||
|
import org.xbib.net.NetworkClass;
|
||||||
|
import org.xbib.net.http.HttpHeaderNames;
|
||||||
|
import org.xbib.net.http.HttpHeaderValues;
|
||||||
|
import org.xbib.net.http.HttpResponseStatus;
|
||||||
|
import org.xbib.net.http.HttpVersion;
|
||||||
|
import org.xbib.net.http.j2html.J2HtmlResourceHandler;
|
||||||
|
import org.xbib.net.http.j2html.J2HtmlService;
|
||||||
|
import org.xbib.net.http.server.application.web.WebApplication;
|
||||||
|
import org.xbib.net.http.server.auth.BasicAuthenticationHandler;
|
||||||
|
import org.xbib.net.http.server.auth.FormAuthenticationHandler;
|
||||||
|
import org.xbib.net.http.server.domain.BaseHttpDomain;
|
||||||
|
import org.xbib.net.http.server.domain.BaseHttpSecurityDomain;
|
||||||
|
import org.xbib.net.http.server.domain.HttpSecurityDomain;
|
||||||
|
import org.xbib.net.http.server.executor.BaseExecutor;
|
||||||
|
import org.xbib.net.http.server.executor.Executor;
|
||||||
|
import org.xbib.net.http.server.ldap.LdapContextFactory;
|
||||||
|
import org.xbib.net.http.server.ldap.LdapGroupMapping;
|
||||||
|
import org.xbib.net.http.server.ldap.LdapRealm;
|
||||||
|
import org.xbib.net.http.server.ldap.LdapUserMapping;
|
||||||
|
import org.xbib.net.http.server.netty.NettyHttpServer;
|
||||||
|
import org.xbib.net.http.server.netty.buffer.NettyDataBufferFactory;
|
||||||
|
import org.xbib.net.http.server.netty.secure.HttpsAddress;
|
||||||
|
import org.xbib.net.http.server.netty.secure.HttpsRequest;
|
||||||
|
import org.xbib.net.http.server.netty.secure.NettyHttpsServerConfig;
|
||||||
|
import org.xbib.net.http.server.resource.ClassLoaderResourceHandler;
|
||||||
|
import org.xbib.net.http.server.route.BaseHttpRouter;
|
||||||
|
import org.xbib.net.http.server.route.HttpRouter;
|
||||||
|
import org.xbib.net.http.server.service.BaseHttpService;
|
||||||
|
import org.xbib.net.http.server.service.HttpService;
|
||||||
|
import org.xbib.settings.Settings;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
public final class Bootstrap {
|
||||||
|
|
||||||
|
private static final ConfigLogger bootLogger;
|
||||||
|
|
||||||
|
static {
|
||||||
|
// early loading of boot logger during static initialization block
|
||||||
|
ServiceLoader<ConfigLogger> serviceLoader = ServiceLoader.load(ConfigLogger.class);
|
||||||
|
Optional<ConfigLogger> optionalBootLogger = serviceLoader.findFirst();
|
||||||
|
bootLogger = optionalBootLogger.orElse(new SystemConfigLogger());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bootstrap() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
String profile = args.length > 0 ? args[0] : System.getProperty("application.profile");
|
||||||
|
ConfigParams configParams;
|
||||||
|
ConfigLoader configLoader;
|
||||||
|
Settings settings;
|
||||||
|
configParams = new ConfigParams()
|
||||||
|
.withArgs(args)
|
||||||
|
.withDirectoryName("application")
|
||||||
|
.withFileNamesWithoutSuffix(profile)
|
||||||
|
.withSystemEnvironment()
|
||||||
|
.withSystemProperties();
|
||||||
|
configLoader = ConfigLoader.getInstance()
|
||||||
|
.withLogger(bootLogger);
|
||||||
|
settings = configLoader.load(configParams);
|
||||||
|
int rc = 1;
|
||||||
|
try {
|
||||||
|
rc = runApplication(settings);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
// always hard-exit the JVM, maybe there are threads hanging
|
||||||
|
System.exit(rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int runApplication(Settings settings) throws Exception {
|
||||||
|
HttpsAddress httpsAddress = HttpsAddress.builder()
|
||||||
|
.setSecure(true)
|
||||||
|
.setVersion(HttpVersion.HTTP_2_0)
|
||||||
|
.setHost("localhost")
|
||||||
|
.setPort(8443)
|
||||||
|
.setSelfCert("localhost")
|
||||||
|
.build();
|
||||||
|
NettyHttpsServerConfig serverConfig = new NettyHttpsServerConfig();
|
||||||
|
serverConfig.setServerName("WebApplication", Bootstrap.class.getPackage().getImplementationVersion());
|
||||||
|
serverConfig.setNetworkClass(NetworkClass.SITE);
|
||||||
|
serverConfig.setDebug(true);
|
||||||
|
|
||||||
|
Map<String, LdapContextFactory> contextFactories = new HashMap<>();
|
||||||
|
LdapContextFactory contextFactory = new LdapContextFactory("simple",
|
||||||
|
"com.sun.jndi.ldap.LdapCtxFactory",
|
||||||
|
null,
|
||||||
|
"ldap://localhost:1389",
|
||||||
|
false,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
"follow"
|
||||||
|
);
|
||||||
|
contextFactories.put("default", contextFactory);
|
||||||
|
Map<String, LdapUserMapping> userMappings = new HashMap<>();
|
||||||
|
LdapUserMapping userMapping = new LdapUserMapping("ou=People,dc=example.org",
|
||||||
|
"(&(objectclass=posixAccount)(uid:caseExactMatch:={0}))",
|
||||||
|
"uid",
|
||||||
|
"cn"
|
||||||
|
);
|
||||||
|
userMappings.put("default", userMapping);
|
||||||
|
Map<String, LdapGroupMapping> groupMappings = new HashMap<>();
|
||||||
|
LdapGroupMapping groupMapping = new LdapGroupMapping("ou=group,dc=example.org",
|
||||||
|
"cn",
|
||||||
|
"(&(objectclass=posixGroup)(memberUid:caseExactMatch:={0}))",
|
||||||
|
new String[] { "uid" }
|
||||||
|
);
|
||||||
|
groupMappings.put("default", groupMapping);
|
||||||
|
LdapRealm ldapRealm = new LdapRealm("Web Application Realm", contextFactories, userMappings, groupMappings);
|
||||||
|
|
||||||
|
BasicAuthenticationHandler basicAuthenticationHandler =
|
||||||
|
new BasicAuthenticationHandler(ldapRealm);
|
||||||
|
|
||||||
|
FormAuthenticationHandler formAuthenticationHandler =
|
||||||
|
new FormAuthenticationHandler("j_username", "j_password", "j_remember",
|
||||||
|
"demo/auth/form/index.gtpl", ldapRealm);
|
||||||
|
|
||||||
|
HttpSecurityDomain securityDomain = BaseHttpSecurityDomain.builder()
|
||||||
|
.setSecurityRealm(ldapRealm)
|
||||||
|
.setHandlers(formAuthenticationHandler)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpService httpService = BaseHttpService.builder()
|
||||||
|
.setPath("/secure")
|
||||||
|
.setHandler(ctx -> {
|
||||||
|
ctx.status(HttpResponseStatus.OK)
|
||||||
|
.header(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.TEXT_PLAIN)
|
||||||
|
.charset(StandardCharsets.UTF_8)
|
||||||
|
.body("secure domain: " +
|
||||||
|
" SNI host = " + ctx.getRequest().as(HttpsRequest.class).getSNIHost() +
|
||||||
|
" SSL session = " + ctx.getRequest().as(HttpsRequest.class).getSSLSession() +
|
||||||
|
" base URL = " + ctx.getRequest().getBaseURL() +
|
||||||
|
" parameter = " + ctx.getRequest().getParameter().allToString() +
|
||||||
|
" attributes = " + ctx.getAttributes() +
|
||||||
|
" local address = " + ctx.getRequest().getLocalAddress() +
|
||||||
|
" remote address = " + ctx.getRequest().getRemoteAddress());
|
||||||
|
ctx.done();
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HttpRouter httpRouter = BaseHttpRouter.builder()
|
||||||
|
.setHandler(500, new InternalServerErrorHandler())
|
||||||
|
.addDomain(BaseHttpDomain.builder()
|
||||||
|
.setHttpAddress(httpsAddress)
|
||||||
|
.addService(BaseHttpService.builder()
|
||||||
|
.setPath("/favicon.ico")
|
||||||
|
.setHandler(ctx -> {
|
||||||
|
ctx.status(HttpResponseStatus.OK)
|
||||||
|
.header(HttpHeaderNames.CONTENT_TYPE, "image/x-icon")
|
||||||
|
.body(NettyDataBufferFactory.getInstance().wrap(fromHex(hexFavIcon)))
|
||||||
|
.done();
|
||||||
|
})
|
||||||
|
.build())
|
||||||
|
.addService(BaseHttpService.builder()
|
||||||
|
.setPath("/webjars/**")
|
||||||
|
.setHandler(new ClassLoaderResourceHandler(Bootstrap.class.getClassLoader(), "META-INF/resources/"))
|
||||||
|
.build())
|
||||||
|
.addService(httpService)
|
||||||
|
.addService(J2HtmlService.builder()
|
||||||
|
.setPath("glob:**")
|
||||||
|
.setHandler(new J2HtmlResourceHandler())
|
||||||
|
.build())
|
||||||
|
.build())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Executor executor = BaseExecutor.builder()
|
||||||
|
.build();
|
||||||
|
|
||||||
|
WebApplication application = WebApplication.builder()
|
||||||
|
.setSettings(settings)
|
||||||
|
.setSecret("1088e6b7ad58d64d09961e1357bf95544447051c6ad1332cd626e3a33bb5786b")
|
||||||
|
.setExecutor(executor)
|
||||||
|
.setRouter(httpRouter)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
try (NettyHttpServer server = NettyHttpServer.builder()
|
||||||
|
.setHttpServerConfig(serverConfig)
|
||||||
|
.setApplication(application)
|
||||||
|
.build()) {
|
||||||
|
server.bind();
|
||||||
|
server.loop();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static final String hexFavIcon =
|
||||||
|
"000001000100101000000100200068040000160000002800000010000000" +
|
||||||
|
"200000000100200000000000000000000000000000000000000000000000" +
|
||||||
|
"000099330000993300009933000099330000993300009933000099330000" +
|
||||||
|
"993300009933000099330000993300009933000099330000993300009933" +
|
||||||
|
"00009933000099330000993300009933000099330000993300ff993300ff" +
|
||||||
|
"993300ff993300ff993300ff993300ff993300ff993300ff993300ff9933" +
|
||||||
|
"0000993300009933000099330000993300009933000099330000993300ff" +
|
||||||
|
"993300ff993300ff993300ff993300ff993300ff993300ff993300ff9933" +
|
||||||
|
"00ff99330000993300009933000099330000993300009933000099330000" +
|
||||||
|
"993300ff9933000099330000993300009933000099330000993300009933" +
|
||||||
|
"00009933000099330000993300009933000099330000993300ff993300ff" +
|
||||||
|
"99330000993300ff99330000993300ff993300ff993300ff993300ff9933" +
|
||||||
|
"00ff993300ff993300ff993300ff993300ff9933000099330000993300ff" +
|
||||||
|
"993300ff99330000993300ff99330000993300ff993300ff993300ff9933" +
|
||||||
|
"00ff993300ff993300ff993300ff993300ff993300ff9933000000000000" +
|
||||||
|
"993300ff993300ff00000000993300ff0000000000000000000000000000" +
|
||||||
|
"00000000000000000000000000000000000099330000993300ff99330000" +
|
||||||
|
"00000000993300ff993300ff00000000993300ff00000000000000000000" +
|
||||||
|
"0000000000000000000000000000993300ff993300ff00000000993300ff" +
|
||||||
|
"0000000000000000993300ff993300ff00000000993300ff993300009933" +
|
||||||
|
"000099330000993300009933000099330000993300ff993300ff99330000" +
|
||||||
|
"993300ff9933000000000000993300ff993300ff00000000993300ff9933" +
|
||||||
|
"00009933000099330000993300009933000099330000993300ff993300ff" +
|
||||||
|
"99330000993300ff9933000000000000993300ff993300ff000000009933" +
|
||||||
|
"00ff993300009933000099330000993300009933000099330000993300ff" +
|
||||||
|
"993300ff99330000993300ff9933000000000000993300ff993300ff0000" +
|
||||||
|
"000099330000993300009933000099330000993300009933000099330000" +
|
||||||
|
"993300ff993300ff99330000993300ff9933000000000000993300ff9933" +
|
||||||
|
"00ff00000000993300ff993300ff993300ff993300ff993300ff993300ff" +
|
||||||
|
"993300ff993300ff993300ff99330000993300ff99330000000000009933" +
|
||||||
|
"00ff993300ff000000009933000099330000993300009933000099330000" +
|
||||||
|
"993300009933000099330000993300009933000099330000993300000000" +
|
||||||
|
"0000993300ff993300ff993300ff993300ff993300ff993300ff993300ff" +
|
||||||
|
"993300ff993300ff993300ff993300ff993300ff99330000993300009933" +
|
||||||
|
"000000000000000000000000000000000000993300009933000099330000" +
|
||||||
|
"993300009933000099330000993300009933000099330000993300009933" +
|
||||||
|
"000099330000ffff0000f0070000f0070000f7ff00009401000094010000" +
|
||||||
|
"97fd000097e5000097e5000097e5000097e500009fe50000900500009fff" +
|
||||||
|
"000080070000ffff0000";
|
||||||
|
|
||||||
|
|
||||||
|
private static byte[] fromHex(String hex) {
|
||||||
|
Objects.requireNonNull(hex);
|
||||||
|
int len = hex.length();
|
||||||
|
byte[] data = new byte[len / 2];
|
||||||
|
for (int i = 0; i < len; i += 2) {
|
||||||
|
data[i / 2] = (byte) fromHex(hex.charAt(i), hex.charAt(i + 1));
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int fromHex(int b1, int b2) {
|
||||||
|
int i1 = Character.digit(b1, 16);
|
||||||
|
if (i1 == -1) {
|
||||||
|
throw new IllegalArgumentException("invalid character in hexadecimal: " + b1);
|
||||||
|
}
|
||||||
|
int i2 = Character.digit(b2, 16);
|
||||||
|
if (i2 == -1) {
|
||||||
|
throw new IllegalArgumentException("invalid character in hexadecimal: " + b2);
|
||||||
|
}
|
||||||
|
return (i1 << 4) + i2;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package org.xbib.net.http.server.application.web.j2html;
|
||||||
|
|
||||||
|
import org.xbib.net.Attributes;
|
||||||
|
import org.xbib.net.http.j2html.J2HtmlResourceHandler;
|
||||||
|
import org.xbib.net.http.server.application.Application;
|
||||||
|
import org.xbib.net.http.server.resource.HtmlTemplateResourceHandler;
|
||||||
|
import org.xbib.net.http.server.route.HttpRouterContext;
|
||||||
|
import org.xbib.net.util.ExceptionFormatter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static j2html.TagCreator.body;
|
||||||
|
import static j2html.TagCreator.code;
|
||||||
|
import static j2html.TagCreator.div;
|
||||||
|
import static j2html.TagCreator.h1;
|
||||||
|
import static j2html.TagCreator.pre;
|
||||||
|
|
||||||
|
public class InternalServerErrorHandler extends J2HtmlResourceHandler {
|
||||||
|
|
||||||
|
protected static class InternalServerErrorResource extends J2HtmlResource {
|
||||||
|
|
||||||
|
protected InternalServerErrorResource(HtmlTemplateResourceHandler templateResourceHandler, HttpRouterContext httpRouterContext) throws IOException {
|
||||||
|
super(templateResourceHandler, httpRouterContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String render(Application application, Attributes attributes) {
|
||||||
|
String message = attributes.get(String.class, "_message");
|
||||||
|
Throwable throwable = attributes.get(Throwable.class, "_throwable");
|
||||||
|
String stackTrace = ExceptionFormatter.format(throwable);
|
||||||
|
return body(
|
||||||
|
h1("Internal Server Error"),
|
||||||
|
div(message),
|
||||||
|
pre(code(stackTrace))
|
||||||
|
).render();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ dependencyResolutionManagement {
|
||||||
library('webjars-bootstrap', 'org.webjars', 'bootstrap').version('5.2.3')
|
library('webjars-bootstrap', 'org.webjars', 'bootstrap').version('5.2.3')
|
||||||
library('webjars-jquery', 'org.webjars', 'jquery').version('3.6.4')
|
library('webjars-jquery', 'org.webjars', 'jquery').version('3.6.4')
|
||||||
library('webjars-fontawesome', 'org.webjars', 'font-awesome').version('6.3.0')
|
library('webjars-fontawesome', 'org.webjars', 'font-awesome').version('6.3.0')
|
||||||
|
library('j2html', 'com.j2html', 'j2html').version('1.6.0')
|
||||||
library('net', 'org.xbib', 'net').versionRef('net')
|
library('net', 'org.xbib', 'net').versionRef('net')
|
||||||
library('net-mime', 'org.xbib', 'net-mime').versionRef('net')
|
library('net-mime', 'org.xbib', 'net-mime').versionRef('net')
|
||||||
library('net-security', 'org.xbib', 'net-security').versionRef('net')
|
library('net-security', 'org.xbib', 'net-security').versionRef('net')
|
||||||
|
@ -61,6 +62,7 @@ include 'net-http-server-nio'
|
||||||
include 'net-http-server-simple'
|
include 'net-http-server-simple'
|
||||||
include 'net-http-server-simple-secure'
|
include 'net-http-server-simple-secure'
|
||||||
include 'net-http-template-groovy'
|
include 'net-http-template-groovy'
|
||||||
|
include 'net-http-j2html'
|
||||||
include 'net-http-server-application-web'
|
include 'net-http-server-application-web'
|
||||||
include 'net-http-server-application-config'
|
include 'net-http-server-application-config'
|
||||||
include 'net-http-server-application-database'
|
include 'net-http-server-application-database'
|
||||||
|
|
Loading…
Reference in a new issue