diff --git a/build.gradle b/build.gradle index d629aea..513f0c6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,22 +1,13 @@ -buildscript { - repositories { - maven { - url 'https://xbib.org/repository' - } - } - dependencies { - classpath "org.xbib.gradle.plugin:gradle-plugin-shadow:1.1.1" - } -} plugins { - id "de.marcphilipp.nexus-publish" version "0.4.0" - id "io.codearte.nexus-staging" version "0.21.1" - id "org.xbib.gradle.plugin.asciidoctor" version "2.5.2.1" - id "org.cyclonedx.bom" version "1.7.2" - id "com.github.spotbugs" version "5.0.13" id "checkstyle" id "pmd" + id 'maven-publish' + id 'signing' + id "io.github.gradle-nexus.publish-plugin" version "1.3.0" + id "com.github.spotbugs" version "5.0.14" + id "org.cyclonedx.bom" version "1.7.2" + id "org.xbib.gradle.plugin.asciidoctor" version "2.5.2.2" } wrapper { diff --git a/gradle.properties b/gradle.properties index 7649515..8064cf2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ group = org.xbib name = net-http -version = 3.1.0 +version = 3.2.0 org.gradle.warning.mode = ALL diff --git a/gradle/compile/java.gradle b/gradle/compile/java.gradle index ebbce6c..c81f3e6 100644 --- a/gradle/compile/java.gradle +++ b/gradle/compile/java.gradle @@ -2,6 +2,8 @@ apply plugin: 'java-library' java { modularity.inferModulePath.set(true) + withSourcesJar() + withJavadocJar() } compileJava { @@ -21,20 +23,6 @@ jar { duplicatesStrategy = DuplicatesStrategy.INCLUDE } -task sourcesJar(type: Jar, dependsOn: classes) { - classifier 'sources' - from sourceSets.main.allSource -} - -task javadocJar(type: Jar, dependsOn: javadoc) { - classifier 'javadoc' - from javadoc.destinationDir -} - -artifacts { - archives sourcesJar, javadocJar -} - tasks.withType(JavaCompile) { options.compilerArgs.add('-Xlint:all,-exports') options.encoding = 'UTF-8' diff --git a/gradle/publish/maven.gradle b/gradle/publish/maven.gradle index 4ada9c0..ce6a26f 100644 --- a/gradle/publish/maven.gradle +++ b/gradle/publish/maven.gradle @@ -1,13 +1,10 @@ -apply plugin: "de.marcphilipp.nexus-publish" - publishing { publications { - mavenJava(MavenPublication) { + "${project.name}"(MavenPublication) { from components.java - artifact sourcesJar - artifact javadocJar pom { + artifactId = project.name name = project.name description = rootProject.ext.description url = rootProject.ext.url @@ -49,18 +46,6 @@ publishing { if (project.hasProperty("signing.keyId")) { apply plugin: 'signing' signing { - sign publishing.publications.mavenJava - } -} - -if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword')) { - nexusPublishing { - repositories { - sonatype { - username = project.property('ossrhUsername') - password = project.property('ossrhPassword') - packageGroup = "org.xbib" - } - } + sign publishing.publications."${project.name}" } } diff --git a/gradle/publish/sonatype.gradle b/gradle/publish/sonatype.gradle index e1813f3..5d739de 100644 --- a/gradle/publish/sonatype.gradle +++ b/gradle/publish/sonatype.gradle @@ -1,11 +1,11 @@ - if (project.hasProperty('ossrhUsername') && project.hasProperty('ossrhPassword')) { - - apply plugin: 'io.codearte.nexus-staging' - - nexusStaging { - username = project.property('ossrhUsername') - password = project.property('ossrhPassword') - packageGroup = "org.xbib" + nexusPublishing { + repositories { + sonatype { + username = project.property('ossrhUsername') + password = project.property('ossrhPassword') + packageGroup = "org.xbib" + } + } } } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 249e583..ccebba7 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fad3f5..761b8f0 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-all.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index a69d9cb..79a61d4 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/gradlew.bat b/gradlew.bat index 53a6b23..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% diff --git a/net-http-server-application-config/src/main/java/org/xbib/net/http/server/application/config/ConfigApplicationModule.java b/net-http-server-application-config/src/main/java/org/xbib/net/http/server/application/config/ConfigApplicationModule.java index 007a8c4..f9979d6 100644 --- a/net-http-server-application-config/src/main/java/org/xbib/net/http/server/application/config/ConfigApplicationModule.java +++ b/net-http-server-application-config/src/main/java/org/xbib/net/http/server/application/config/ConfigApplicationModule.java @@ -6,9 +6,9 @@ import org.xbib.config.ConfigLoader; import org.xbib.config.ConfigLogger; import org.xbib.config.ConfigParams; import org.xbib.config.SystemConfigLogger; +import org.xbib.net.http.server.HttpRequest; import org.xbib.net.http.server.application.Application; import org.xbib.net.http.server.application.BaseApplicationModule; -import org.xbib.net.http.server.HttpRequest; import org.xbib.net.http.server.HttpServerContext; import org.xbib.net.http.server.service.HttpService; import org.xbib.settings.Settings; @@ -24,27 +24,21 @@ public class ConfigApplicationModule extends BaseApplicationModule { bootLogger = optionalBootLogger.orElse(new SystemConfigLogger()); } - private ConfigParams configParams; + private final ConfigParams configParams; - private ConfigLoader configLoader; + private final ConfigLoader configLoader; - private Settings settings; + private final Settings settings; public ConfigApplicationModule(Application application, String name, Settings settings) { super(application, name, settings); - } - - @Override - public void onOpen(Application application, Settings settings) { String profile = System.getProperty("application.profile"); if (profile == null) { profile = "developer"; } - String[] args = profile.split(";"); this.configParams = new ConfigParams() - .withArgs(args) - .withDirectoryName("application") - .withFileNamesWithoutSuffix(args[0]) + .withDirectoryName(name) + .withFileNamesWithoutSuffix(profile) .withSystemEnvironment() .withSystemProperties(); this.configLoader = ConfigLoader.getInstance() @@ -53,14 +47,9 @@ public class ConfigApplicationModule extends BaseApplicationModule { } @Override - public void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService) { + public void onOpen(HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { httpServerContext.getAttributes().put("configparams", configParams); httpServerContext.getAttributes().put("configloader", configLoader); httpServerContext.getAttributes().put("settings", settings); } - - @Override - public void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { - // do nothing - } } diff --git a/net-http-server-application-database/src/main/java/org/xbib/net/http/server/application/database/DatabaseApplicationModule.java b/net-http-server-application-database/src/main/java/org/xbib/net/http/server/application/database/DatabaseApplicationModule.java index ec11d5a..c09ef12 100644 --- a/net-http-server-application-database/src/main/java/org/xbib/net/http/server/application/database/DatabaseApplicationModule.java +++ b/net-http-server-application-database/src/main/java/org/xbib/net/http/server/application/database/DatabaseApplicationModule.java @@ -16,20 +16,16 @@ import java.util.Properties; import java.util.logging.Level; import java.util.logging.Logger; -public class DatabaseApplicationModule extends BaseApplicationModule { +public class DatabaseApplicationModule extends BaseApplicationModule { private static final Logger logger = Logger.getLogger(DatabaseApplicationModule.class.getName()); - private DataSource dataSource; + private final DataSource dataSource; - private DatabaseProvider databaseProvider; + private final DatabaseProvider databaseProvider; public DatabaseApplicationModule(Application application, String name, Settings settings) { super(application, name, settings); - } - - @Override - public void onOpen(Application application, Settings settings) throws Exception { this.dataSource = createDataSource(); String flavor = System.getProperty("database.flavor"); this.databaseProvider = flavor != null ? @@ -37,7 +33,7 @@ public class DatabaseApplicationModule extends BaseApplic } @Override - public void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService) { + public void onOpen(HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { if (dataSource != null) { httpServerContext.getAttributes().put("datasource", dataSource); } @@ -46,12 +42,7 @@ public class DatabaseApplicationModule extends BaseApplic } } - @Override - public void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { - // nothing - } - - private DataSource createDataSource() throws Exception { + private DataSource createDataSource() { Properties properties = new Properties(); System.getProperties().forEach((key, value) -> { if (key.toString().startsWith("database.") && !key.toString().equals("database.flavor")) { @@ -72,7 +63,11 @@ public class DatabaseApplicationModule extends BaseApplic config.setConnectionTimeout(getAsLong(properties, "timeout", 15L * 1000L)); // 15 seconds config.setHousekeepingPeriodMs(getAsLong(properties, "housekeeping", 600L * 1000L)); // 10 minutes config.setAutoCommit(getAsBoolean(properties, "autocommit", true)); - return new PoolDataSource(config); + try { + return new PoolDataSource(config); + } catch (Exception e) { + throw new IllegalStateException(e); + } } private int getAsInt(Properties properties, String key, int defaultValue) { diff --git a/net-http-server-netty/src/main/java/org/xbib/net/http/server/netty/NettyHttpServer.java b/net-http-server-netty/src/main/java/org/xbib/net/http/server/netty/NettyHttpServer.java index 15093e8..663a2fa 100644 --- a/net-http-server-netty/src/main/java/org/xbib/net/http/server/netty/NettyHttpServer.java +++ b/net-http-server-netty/src/main/java/org/xbib/net/http/server/netty/NettyHttpServer.java @@ -67,7 +67,7 @@ public class NettyHttpServer implements HttpServer { logger.log(Level.FINE, "parent event loop group = " + parentEventLoopGroup + " child event loop group = " + childEventLoopGroup + " socket channel class = " + socketChannelClass + - " router addresses = " + getApplication().getAddresses()); + " router addresses = " + builder.application.getAddresses()); } public static NettyHttpServerBuilder builder() { @@ -84,8 +84,8 @@ public class NettyHttpServer implements HttpServer { @Override public void bind() throws BindException { - Set httpAddressSet = getApplication().getAddresses(); - logger.log(Level.FINE, "http adresses = " + httpAddressSet); + Set httpAddressSet = builder.application.getAddresses(); + logger.log(Level.FINE, "http addresses = " + httpAddressSet); for (HttpAddress httpAddress : httpAddressSet) { SocketConfig socketConfig = httpAddress.getSocketConfig(); ServerBootstrap bootstrap = new ServerBootstrap() @@ -198,8 +198,7 @@ public class NettyHttpServer implements HttpServer { channelFuture.cancel(true); } } - // close application - getApplication().close(); + builder.application.close(); logger.log(Level.INFO, "server shutdown complete"); } diff --git a/net-http-server-nio/src/main/java/org/xbib/net/http/server/nio/NioHttpServer.java b/net-http-server-nio/src/main/java/org/xbib/net/http/server/nio/NioHttpServer.java index 7f35b2a..f3f3abc 100644 --- a/net-http-server-nio/src/main/java/org/xbib/net/http/server/nio/NioHttpServer.java +++ b/net-http-server-nio/src/main/java/org/xbib/net/http/server/nio/NioHttpServer.java @@ -26,8 +26,6 @@ import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; @@ -39,13 +37,10 @@ public class NioHttpServer implements HttpServer { private final NioHttpServerBuilder builder; - private final ExecutorService workerPool; - private final Map serverSockets; NioHttpServer(NioHttpServerBuilder builder) { this.builder = builder; - this.workerPool = Executors.newCachedThreadPool(); this.serverSockets = new HashMap<>(); } @@ -55,7 +50,7 @@ public class NioHttpServer implements HttpServer { @Override public void bind() throws BindException { - for (HttpAddress httpAddress : getApplication().getAddresses()) { + for (HttpAddress httpAddress : builder.application.getAddresses()) { try { logger.log(Level.INFO, () -> "trying to bind to " + httpAddress); ServerSocketChannel channel = ServerSocketChannel.open(); @@ -106,7 +101,7 @@ public class NioHttpServer implements HttpServer { httpAddress, (InetSocketAddress) socketChannel.getLocalAddress(), (InetSocketAddress) socketChannel.getRemoteAddress()); - handle(requestBuilder, responseBuilder); + builder.application.dispatch(requestBuilder, responseBuilder); socketChannel.close(); } catch (IOException e) { logger.log(Level.SEVERE, e.getMessage(), e); @@ -137,10 +132,6 @@ public class NioHttpServer implements HttpServer { return builder.application; } - public void handle(HttpRequestBuilder httpRequestBuilder, HttpResponseBuilder httpResponseBuilder) throws IOException { - getApplication().dispatch(httpRequestBuilder, httpResponseBuilder); - } - @Override public void close() throws IOException { for (Map.Entry entry : serverSockets.entrySet()) { diff --git a/net-http-server-simple/src/main/java/org/xbib/net/http/server/simple/SimpleHttpServer.java b/net-http-server-simple/src/main/java/org/xbib/net/http/server/simple/SimpleHttpServer.java index 4f4093a..c03c598 100644 --- a/net-http-server-simple/src/main/java/org/xbib/net/http/server/simple/SimpleHttpServer.java +++ b/net-http-server-simple/src/main/java/org/xbib/net/http/server/simple/SimpleHttpServer.java @@ -55,7 +55,7 @@ public class SimpleHttpServer implements HttpServer { @Override public void bind() throws BindException { // bind only once per HttpAddress in all domains - for (HttpAddress httpAddress : getApplication().getAddresses()) { + for (HttpAddress httpAddress : builder.application.getAddresses()) { logger.log(Level.INFO, () -> "trying to bind to " + httpAddress); try { InetSocketAddress inetSocketAddress = httpAddress.getInetSocketAddress(); @@ -76,7 +76,7 @@ public class SimpleHttpServer implements HttpServer { if (serverSocket.isBound()) { serverSockets.put(httpAddress, serverSocket); logger.log(Level.INFO, () -> "server socket = " + serverSocket + - " domains = " + getApplication().getAddresses() + " bound, listening on " + inetSocketAddress); + " domains = " + builder.application.getAddresses() + " bound, listening on " + inetSocketAddress); } else { logger.log(Level.WARNING, "server socket " + serverSocket + " not bound, something is wrong"); } @@ -108,7 +108,7 @@ public class SimpleHttpServer implements HttpServer { httpAddress, (InetSocketAddress) socket.getLocalSocketAddress(), (InetSocketAddress) socket.getRemoteSocketAddress()); - getApplication().dispatch(httpRequestBuilder, httpResponseBuilder); + builder.application.dispatch(httpRequestBuilder, httpResponseBuilder); } catch (Throwable t) { logger.log(Level.SEVERE, t.getMessage(), t); } finally { diff --git a/net-http-server-simple/src/test/java/org/xbib/net/http/server/simple/test/HttpRouterTest.java b/net-http-server-simple/src/test/java/org/xbib/net/http/server/simple/test/HttpRouterTest.java index 7da753b..c781930 100644 --- a/net-http-server-simple/src/test/java/org/xbib/net/http/server/simple/test/HttpRouterTest.java +++ b/net-http-server-simple/src/test/java/org/xbib/net/http/server/simple/test/HttpRouterTest.java @@ -56,8 +56,7 @@ public class HttpRouterTest { .setMethod(HttpMethod.DELETE) .setRequestURI("/demo") .addHeader(HttpHeaderNames.HOST, httpAddress.hostAndPort()); - router.setApplication(BaseApplication.builder().build()); - router.route(httpRequest, httpResponse); + router.route(BaseApplication.builder().build(), httpRequest, httpResponse); String string = outputStream.toString(StandardCharsets.UTF_8); Logger.getAnonymousLogger().log(Level.INFO, "the response string is = " + string); assertTrue(string.contains("/demo")); diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/Application.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/Application.java index 295da79..75e3302 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/Application.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/Application.java @@ -38,13 +38,19 @@ public interface Application extends SessionListener, Resolver, Closeable Collection getModules(); /** - * Dispatch a regular request. + * Dispatch a request. * @param requestBuilder the request * @param responseBuilder the response */ void dispatch(HttpRequestBuilder requestBuilder, HttpResponseBuilder responseBuilder); + /** + * Dispatch a status. + * @param requestBuilder the request + * @param responseBuilder the response + * @param httpResponseStatus the status + */ void dispatch(HttpRequestBuilder requestBuilder, HttpResponseBuilder responseBuilder, HttpResponseStatus httpResponseStatus); diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationBuilder.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationBuilder.java index 518be93..f0afe23 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationBuilder.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationBuilder.java @@ -3,6 +3,7 @@ package org.xbib.net.http.server.application; import java.nio.file.Path; import java.time.ZoneId; import java.util.Locale; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import org.xbib.net.http.server.route.HttpRouter; import org.xbib.net.mime.MimeTypeService; @@ -17,6 +18,8 @@ public interface ApplicationBuilder { ApplicationBuilder setKeepAliveTimeUnit(TimeUnit keepAliveTimeUnit); + ApplicationBuilder setExecutor(ThreadPoolExecutor executor); + ApplicationBuilder setHome(Path home); ApplicationBuilder setContextPath(String contextPath); diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/RouterCallable.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationCallable.java similarity index 63% rename from net-http-server/src/main/java/org/xbib/net/http/server/application/RouterCallable.java rename to net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationCallable.java index a357db0..0b0c789 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/RouterCallable.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationCallable.java @@ -3,5 +3,5 @@ package org.xbib.net.http.server.application; import java.util.concurrent.Callable; import org.xbib.net.buffer.Releasable; -public interface RouterCallable extends Callable, Releasable { +public interface ApplicationCallable extends Callable, Releasable { } diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationModule.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationModule.java index 15e1426..cd83bbb 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationModule.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationModule.java @@ -4,25 +4,20 @@ import org.xbib.net.http.server.HttpRequest; import org.xbib.net.http.server.HttpServerContext; import org.xbib.net.http.server.service.HttpService; import org.xbib.net.http.server.session.Session; -import org.xbib.settings.Settings; public interface ApplicationModule { String getName(); - void onOpen(Application application, Settings settings) throws Exception; + void onOpen(HttpServerContext httpServerContext); - void onOpen(Application application, HttpServerContext httpServerContext); + void onOpen(HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest); - void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService); + void onClose(HttpServerContext httpServerContext); - void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest); + void onOpen(Session session); - void onClose(Application application, HttpServerContext httpServerContext); + void onClose(Session session); - void onOpen(Application application, Session session); - - void onClose(Application application, Session session); - - void onClose(Application application); + void onClose(); } diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/RouterTask.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationTask.java similarity index 74% rename from net-http-server/src/main/java/org/xbib/net/http/server/application/RouterTask.java rename to net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationTask.java index 1a90102..00c6659 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/RouterTask.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationTask.java @@ -3,11 +3,11 @@ package org.xbib.net.http.server.application; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; -public class RouterTask extends FutureTask { +public class ApplicationTask extends FutureTask { private final Callable callable; - public RouterTask(Callable callable) { + public ApplicationTask(Callable callable) { super(callable); this.callable = callable; } diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationThreadPoolExecutor.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationThreadPoolExecutor.java index 8d46547..76e543c 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationThreadPoolExecutor.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/ApplicationThreadPoolExecutor.java @@ -15,8 +15,10 @@ public class ApplicationThreadPoolExecutor extends ThreadPoolExecutor { private final Logger logger = Logger.getLogger(ApplicationThreadPoolExecutor.class.getName()); - public ApplicationThreadPoolExecutor(int nThreads, int maxQueue, - long keepAliveTime, TimeUnit timeUnit, + public ApplicationThreadPoolExecutor(int nThreads, + int maxQueue, + long keepAliveTime, + TimeUnit timeUnit, ThreadFactory threadFactory) { super(nThreads, nThreads, keepAliveTime, timeUnit, createBlockingQueue(maxQueue), threadFactory); logger.log(Level.FINE, () -> "threadpool executor up with nThreads = " + nThreads + @@ -26,13 +28,13 @@ public class ApplicationThreadPoolExecutor extends ThreadPoolExecutor { " threadFactory = " + threadFactory); } - private static BlockingQueue createBlockingQueue(int max) { - return max == Integer.MAX_VALUE ? new SynchronousQueue<>(true) : new ArrayBlockingQueue<>(max); + private static BlockingQueue createBlockingQueue(int maxQueue) { + return maxQueue == 0 ? new SynchronousQueue<>(true) : new ArrayBlockingQueue<>(maxQueue); } @Override protected RunnableFuture newTaskFor(Callable callable) { - return new RouterTask<>(callable); + return new ApplicationTask<>(callable); } @Override @@ -43,10 +45,10 @@ public class ApplicationThreadPoolExecutor extends ThreadPoolExecutor { logger.log(Level.SEVERE, terminationCause.getMessage(), terminationCause); return; } - if (runnable instanceof RouterTask routerTask) { - RouterCallable routerCallable = (RouterCallable) routerTask.getCallable(); - logger.log(Level.FINEST, () -> "releasing " + routerCallable); - routerCallable.release(); + if (runnable instanceof ApplicationTask applicationTask) { + ApplicationCallable applicationCallable = (ApplicationCallable) applicationTask.getCallable(); + logger.log(Level.FINEST, () -> "releasing " + applicationCallable); + applicationCallable.release(); } } } diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplication.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplication.java index 56f3ee4..d28b33f 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplication.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplication.java @@ -35,7 +35,6 @@ import org.xbib.net.http.server.session.Session; import org.xbib.net.http.server.session.memory.MemoryPropertiesSessionCodec; import org.xbib.net.http.server.validate.HttpRequestValidator; import org.xbib.net.mime.MimeTypeService; -import org.xbib.net.util.NamedThreadFactory; import org.xbib.net.util.RandomUtil; import org.xbib.settings.Settings; @@ -45,8 +44,6 @@ public class BaseApplication implements Application { protected BaseApplicationBuilder builder; - private final ApplicationThreadPoolExecutor executor; - private final HttpRequestValidator httpRequestValidator; protected final String sessionName; @@ -65,11 +62,6 @@ public class BaseApplication implements Application { protected BaseApplication(BaseApplicationBuilder builder) { this.builder = builder; - this.executor = new ApplicationThreadPoolExecutor(builder.blockingThreadCount, builder.blockingThreadQueueCount, - builder.blockingThreadKeepAliveTime, builder.blockingThreadKeepAliveTimeUnit, - new NamedThreadFactory("org-xbib-net-http-server-application")); - this.executor.setRejectedExecutionHandler((runnable, threadPoolExecutor) -> - logger.log(Level.SEVERE, "rejected " + runnable + " for thread pool executor = " + threadPoolExecutor)); this.sessionName = getSettings().get("session.name", "SESS"); this.httpRequestValidator = newRequestValidator(); this.incomingCookieHandler = newIncomingCookieHandler(); @@ -139,10 +131,11 @@ public class BaseApplication implements Application { @Override public void dispatch(HttpRequestBuilder httpRequestBuilder, HttpResponseBuilder httpResponseBuilder) { - RouterCallable routerCallable = new RouterCallable() { + final Application application = this; + ApplicationCallable applicationCallable = new ApplicationCallable<>() { @Override - public Boolean call() { - getRouter().route(httpRequestBuilder, httpResponseBuilder); + public Object call() { + getRouter().route(application, httpRequestBuilder, httpResponseBuilder); return true; } @@ -152,7 +145,7 @@ public class BaseApplication implements Application { httpResponseBuilder.release(); } }; - Future future = executor.submit(routerCallable); + Future future = builder.executor.submit(applicationCallable); logger.log(Level.FINEST, "dispatched " + future); } @@ -161,9 +154,9 @@ public class BaseApplication implements Application { HttpResponseBuilder httpResponseBuilder, HttpResponseStatus httpResponseStatus) { HttpServerContext httpServerContext = createContext(null, httpRequestBuilder, httpResponseBuilder); - RouterCallable routerCallable = new RouterCallable() { + ApplicationCallable applicationCallable = new ApplicationCallable<>() { @Override - public Boolean call() { + public Object call() { getRouter().routeStatus(httpResponseStatus, httpServerContext); return true; } @@ -174,7 +167,7 @@ public class BaseApplication implements Application { httpResponseBuilder.release(); } }; - Future future = executor.submit(routerCallable); + Future future = builder.executor.submit(applicationCallable); logger.log(Level.FINEST, "dispatched status " + future); } @@ -249,13 +242,13 @@ public class BaseApplication implements Application { @Override public void onCreated(Session session) { logger.log(Level.FINER, "session name = " + sessionName + " created = " + session); - builder.applicationModuleList.forEach(module -> module.onOpen(this, session)); + builder.applicationModuleList.forEach(module -> module.onOpen(session)); } @Override public void onDestroy(Session session) { logger.log(Level.FINER, "session name = " + sessionName + " destroyed = " + session); - builder.applicationModuleList.forEach(module -> module.onClose(this, session)); + builder.applicationModuleList.forEach(module -> module.onClose(session)); } @Override @@ -271,7 +264,7 @@ public class BaseApplication implements Application { incomingSessionHandler.handle(httpServerContext); } // call modules after request/cookie/session setup - builder.applicationModuleList.forEach(module -> module.onOpen(this, httpServerContext)); + builder.applicationModuleList.forEach(module -> module.onOpen(httpServerContext)); } catch (HttpException e) { getRouter().routeException(e); httpServerContext.fail(); @@ -285,7 +278,7 @@ public class BaseApplication implements Application { public void onClose(HttpServerContext httpServerContext) { try { // call modules before session/cookie - builder.applicationModuleList.forEach(module -> module.onClose(this, httpServerContext)); + builder.applicationModuleList.forEach(module -> module.onClose(httpServerContext)); if (builder.sessionsEnabled && outgoingSessionHandler != null) { outgoingSessionHandler.handle(httpServerContext); } @@ -329,19 +322,19 @@ public class BaseApplication implements Application { public void close() throws IOException { logger.log(Level.INFO, "application closing"); // stop dispatching and stop dispatched requests - executor.shutdown(); + builder.executor.shutdown(); try { - if (!executor.awaitTermination(10, TimeUnit.SECONDS)) { - List list = executor.shutdownNow(); + if (!builder.executor.awaitTermination(10, TimeUnit.SECONDS)) { + List list = builder.executor.shutdownNow(); logger.log(Level.WARNING, "unable to stop runnables " + list); } } catch (InterruptedException e) { - List list = executor.shutdownNow(); + List list = builder.executor.shutdownNow(); logger.log(Level.WARNING, "unable to stop runnables " + list); } builder.applicationModuleList.forEach(module -> { logger.log(Level.FINE, "application closing module " + module); - module.onClose(this); + module.onClose(); }); if (outgoingSessionHandler != null && (outgoingSessionHandler instanceof Closeable)) { logger.log(Level.FINE, "application closing outgoing session handler"); diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationBuilder.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationBuilder.java index c78cb2e..ae628cd 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationBuilder.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationBuilder.java @@ -10,6 +10,7 @@ import java.util.Map; import java.util.Optional; import java.util.ServiceLoader; import java.util.Set; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -19,6 +20,7 @@ import org.xbib.config.ConfigParams; import org.xbib.config.SystemConfigLogger; import org.xbib.net.http.server.route.HttpRouter; import org.xbib.net.mime.MimeTypeService; +import org.xbib.net.util.NamedThreadFactory; import org.xbib.settings.Settings; public class BaseApplicationBuilder implements ApplicationBuilder { @@ -44,6 +46,8 @@ public class BaseApplicationBuilder implements ApplicationBuilder { protected TimeUnit blockingThreadKeepAliveTimeUnit; + protected ThreadPoolExecutor executor; + protected Path home; protected String contextPath; @@ -73,7 +77,7 @@ public class BaseApplicationBuilder implements ApplicationBuilder { protected BaseApplicationBuilder() { this.classLoader = getClass().getClassLoader(); this.blockingThreadCount = Runtime.getRuntime().availableProcessors(); - this.blockingThreadQueueCount = Integer.MAX_VALUE; + this.blockingThreadQueueCount = 0; // use fair synchronous queue this.blockingThreadKeepAliveTime = 60; this.blockingThreadKeepAliveTimeUnit = TimeUnit.SECONDS; this.home = Paths.get(System.getProperties().containsKey("application.home") ? System.getProperty("application.home") : "."); @@ -115,6 +119,12 @@ public class BaseApplicationBuilder implements ApplicationBuilder { return this; } + @Override + public BaseApplicationBuilder setExecutor(ThreadPoolExecutor executor) { + this.executor = executor; + return this; + } + @Override public BaseApplicationBuilder setHome(Path home) { this.home = home; @@ -205,12 +215,16 @@ public class BaseApplicationBuilder implements ApplicationBuilder { if (staticFileSuffixes == null) { staticFileSuffixes = DEFAULT_SUFFIXES; } + if (this.executor == null) { + this.executor = new ApplicationThreadPoolExecutor(blockingThreadCount, blockingThreadQueueCount, + blockingThreadKeepAliveTime, blockingThreadKeepAliveTimeUnit, + new NamedThreadFactory("org-xbib-net-http-server-application")); + this.executor.setRejectedExecutionHandler((runnable, threadPoolExecutor) -> + logger.log(Level.SEVERE, "rejected " + runnable + " for thread pool executor = " + threadPoolExecutor)); + } } protected void setupApplication(Application application) { - if (router != null) { - router.setApplication(application); - } for (Map.Entry entry : settings.getGroups("module").entrySet()) { String moduleName = entry.getKey(); Settings moduleSettings = entry.getValue(); @@ -223,7 +237,6 @@ public class BaseApplicationBuilder implements ApplicationBuilder { ApplicationModule applicationModule = clazz.getConstructor(Application.class, String.class, Settings.class) .newInstance(application, moduleName, moduleSettings); applicationModuleList.add(applicationModule); - applicationModule.onOpen(application, moduleSettings); } catch (Exception e) { logger.log(Level.WARNING, e.getMessage(), e); throw new IllegalArgumentException("class not found or not loadable: " + e.getMessage()); diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationModule.java b/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationModule.java index 79525fb..8dfad9c 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationModule.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/application/BaseApplicationModule.java @@ -26,34 +26,26 @@ public abstract class BaseApplicationModule implements ApplicationModule { } @Override - public void onOpen(Application application, Settings settings) throws Exception { + public void onOpen(HttpServerContext httpServerContext) { } @Override - public void onOpen(Application application, HttpServerContext httpServerContext) { + public void onOpen(HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { } @Override - public void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService) { + public void onClose(HttpServerContext httpServerContext) { } @Override - public void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { + public void onOpen(Session session) { } @Override - public void onClose(Application application, HttpServerContext httpServerContext) { + public void onClose(Session session) { } @Override - public void onOpen(Application application, Session session) { - } - - @Override - public void onClose(Application application, Session session) { - } - - @Override - public void onClose(Application application) { + public void onClose() { } } diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/route/BaseHttpRouter.java b/net-http-server/src/main/java/org/xbib/net/http/server/route/BaseHttpRouter.java index f2697de..ad75d82 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/route/BaseHttpRouter.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/route/BaseHttpRouter.java @@ -39,8 +39,6 @@ public class BaseHttpRouter implements HttpRouter { private final HttpRouteResolver httpRouteResolver; - private Application application; - protected BaseHttpRouter(BaseHttpRouterBuilder builder) { this.builder = builder; HttpRouteResolver.Builder httpRouteResolverBuilder = newHttpRouteResolverBuilder(); @@ -69,12 +67,6 @@ public class BaseHttpRouter implements HttpRouter { return BaseHttpRouteResolver.builder(); } - @Override - public void setApplication(Application application) { - Objects.requireNonNull(application); - this.application = application; - } - @Override public Collection getDomains() { return builder.domains; @@ -86,7 +78,8 @@ public class BaseHttpRouter implements HttpRouter { } @Override - public void route(HttpRequestBuilder requestBuilder, + public void route(Application application, + HttpRequestBuilder requestBuilder, HttpResponseBuilder responseBuilder) { Objects.requireNonNull(requestBuilder); Objects.requireNonNull(requestBuilder.getRequestURI()); @@ -104,64 +97,64 @@ public class BaseHttpRouter implements HttpRouter { true); httpRouteResolver.resolve(httpRoute, httpRouteResolverResults::add); HttpServerContext httpServerContext = application.createContext(httpDomain, requestBuilder, responseBuilder); - route(httpServerContext, httpRouteResolverResults); - } - - protected void route(HttpServerContext httpServerContext, - List> httpRouteResolverResults) { application.onOpen(httpServerContext); try { - if (httpServerContext.isFailed()) { - return; - } - if (httpRouteResolverResults.isEmpty()) { - logger.log(Level.FINE, "route resolver results is empty, generating a not found message"); - httpServerContext.setResolverResult(null); - routeStatus(NOT_FOUND, httpServerContext); - return; - } - for (HttpRouteResolver.Result httpRouteResolverResult : httpRouteResolverResults) { - try { - // first: create the final request - httpServerContext.setResolverResult(httpRouteResolverResult); - HttpService httpService = httpRouteResolverResult.getValue(); - HttpRequest httpRequest = httpServerContext.httpRequest(); - application.getModules().forEach(module -> module.onOpen(application, httpServerContext, httpService, httpRequest)); - // second: security check, authentication etc. - if (httpService.getSecurityDomain() != null) { - logger.log(Level.FINEST, () -> "handling security domain service " + httpService); - for (HttpHandler httpHandler : httpService.getSecurityDomain().getHandlers()) { - logger.log(Level.FINEST, () -> "handling security domain handler " + httpHandler); - httpHandler.handle(httpServerContext); - } - } - if (httpServerContext.isDone() || httpServerContext.isFailed()) { - break; - } - // after security checks, accept service, open and execute service - httpServerContext.getAttributes().put("service", httpService); - application.getModules().forEach(module -> module.onOpen(application, httpServerContext, httpService)); - logger.log(Level.FINEST, () -> "handling service " + httpService); - httpService.handle(httpServerContext); - // if service signals that work is done, break - if (httpServerContext.isDone() || httpServerContext.isFailed()) { - break; - } - } catch (HttpException e) { - logger.log(Level.SEVERE, e.getMessage(), e); - routeException(e); - break; - } catch (Throwable t) { - logger.log(Level.SEVERE, t.getMessage(), t); - routeToErrorHandler(httpServerContext, t); - break; - } - } + route(application, httpServerContext, httpRouteResolverResults); } finally { application.onClose(httpServerContext); } } + protected void route(Application application, + HttpServerContext httpServerContext, + List> httpRouteResolverResults) { + if (httpServerContext.isFailed()) { + return; + } + if (httpRouteResolverResults.isEmpty()) { + logger.log(Level.FINE, "route resolver results is empty, generating a not found message"); + httpServerContext.setResolverResult(null); + routeStatus(NOT_FOUND, httpServerContext); + return; + } + for (HttpRouteResolver.Result httpRouteResolverResult : httpRouteResolverResults) { + try { + // first: create the final request + httpServerContext.setResolverResult(httpRouteResolverResult); + HttpService httpService = httpRouteResolverResult.getValue(); + HttpRequest httpRequest = httpServerContext.httpRequest(); + application.getModules().forEach(module -> module.onOpen(httpServerContext, httpService, httpRequest)); + // second: security check, authentication etc. + if (httpService.getSecurityDomain() != null) { + logger.log(Level.FINEST, () -> "handling security domain service " + httpService); + for (HttpHandler httpHandler : httpService.getSecurityDomain().getHandlers()) { + logger.log(Level.FINEST, () -> "handling security domain handler " + httpHandler); + httpHandler.handle(httpServerContext); + } + } + if (httpServerContext.isDone() || httpServerContext.isFailed()) { + break; + } + // after security checks, accept service, open and execute service + httpServerContext.getAttributes().put("service", httpService); + logger.log(Level.FINEST, () -> "handling service " + httpService); + httpService.handle(httpServerContext); + // if service signals that work is done, break + if (httpServerContext.isDone() || httpServerContext.isFailed()) { + break; + } + } catch (HttpException e) { + logger.log(Level.SEVERE, e.getMessage(), e); + routeException(e); + break; + } catch (Throwable t) { + logger.log(Level.SEVERE, t.getMessage(), t); + routeToErrorHandler(httpServerContext, t); + break; + } + } + } + @Override public void routeException(HttpException e) { routeStatus(e.getResponseStatus(), e.getHttpServerContext()); diff --git a/net-http-server/src/main/java/org/xbib/net/http/server/route/HttpRouter.java b/net-http-server/src/main/java/org/xbib/net/http/server/route/HttpRouter.java index a29d357..f3c0e6f 100644 --- a/net-http-server/src/main/java/org/xbib/net/http/server/route/HttpRouter.java +++ b/net-http-server/src/main/java/org/xbib/net/http/server/route/HttpRouter.java @@ -15,13 +15,12 @@ public interface HttpRouter { DomainsByAddress getDomainsByAddress(); - void setApplication(Application application); - - void route(HttpRequestBuilder requestBuilder, HttpResponseBuilder responseBuilder); - - void routeException(HttpException e); + void route(Application application, HttpRequestBuilder requestBuilder, HttpResponseBuilder responseBuilder); void routeStatus(HttpResponseStatus httpResponseStatus, HttpServerContext httpServerContext); void routeToErrorHandler(HttpServerContext httpServerContext, Throwable t); + + void routeException(HttpException e); + } diff --git a/net-http-template-groovy/src/main/java/org/xbib/net/http/template/groovy/GroovyTemplateApplicationModule.java b/net-http-template-groovy/src/main/java/org/xbib/net/http/template/groovy/GroovyTemplateApplicationModule.java index b53d40a..743ee3d 100644 --- a/net-http-template-groovy/src/main/java/org/xbib/net/http/template/groovy/GroovyTemplateApplicationModule.java +++ b/net-http-template-groovy/src/main/java/org/xbib/net/http/template/groovy/GroovyTemplateApplicationModule.java @@ -18,16 +18,12 @@ public class GroovyTemplateApplicationModule extends BaseApplicationModule { private static final Logger logger = Logger.getLogger(GroovyTemplateApplicationModule.class.getName()); - private GroovyMarkupTemplateHandler groovyMarkupTemplateHandler; + private final GroovyMarkupTemplateHandler groovyMarkupTemplateHandler; - private GroovyTemplateRenderer groovyTemplateRenderer; + private final GroovyTemplateRenderer groovyTemplateRenderer; public GroovyTemplateApplicationModule(Application application, String name, Settings settings) { super(application, name, settings); - } - - @Override - public void onOpen(Application application, Settings settings) { ClassLoader classLoader = GroovyMarkupTemplateHandler.class.getClassLoader(); String defaultMarkupTemplate = settings.get("markup.templateClass", "org.xbib.net.http.template.DefaultMarkupTemplate"); @@ -54,7 +50,7 @@ public class GroovyTemplateApplicationModule extends BaseApplicationModule { } @Override - public void onOpen(Application application, HttpServerContext httpServerContext) { + public void onOpen(HttpServerContext httpServerContext) { try { groovyMarkupTemplateHandler.handle(httpServerContext); } catch (IOException e) { @@ -63,14 +59,14 @@ public class GroovyTemplateApplicationModule extends BaseApplicationModule { } @Override - public void onOpen(Application application, HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { + public void onOpen(HttpServerContext httpServerContext, HttpService httpService, HttpRequest httpRequest) { httpServerContext.getAttributes().put("request", httpRequest); httpServerContext.getAttributes().put("params", httpRequest.getParameter().asSingleValuedMap()); application.getModules().forEach(module -> httpServerContext.getAttributes().put(module.getName(), module)); } @Override - public void onClose(Application application, HttpServerContext httpServerContext) { + public void onClose(HttpServerContext httpServerContext) { try { groovyTemplateRenderer.handle(httpServerContext); } catch (IOException e) { diff --git a/settings.gradle b/settings.gradle index 682d6a0..651cc71 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,14 +1,14 @@ dependencyResolutionManagement { versionCatalogs { libs { - version('gradle', '7.5.1') + version('gradle', '8.0.2') version('junit', '5.9.2') - version('groovy', '4.0.10') + version('groovy', '4.0.11') version('netty', '4.1.90.Final') version('netty-tcnative', '2.0.59.Final') version('datastructures', '2.0.0') version('config', '5.0.2') - version('net', '3.1.0') + version('net', '3.2.0') library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit') library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit') library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')