From 83ce0cfe108f9c46047034db2634e8ae23be1422 Mon Sep 17 00:00:00 2001 From: Claude Brisson Date: Thu, 8 Jun 2023 22:24:30 +0200 Subject: [PATCH] New packaging in progress --- README.md | 9 +- api-webapp/pom.xml | 5 - application/pom.xml | 60 +++++- application/src/assembly/livewar.xml | 21 +-- bootstrap/pom.xml | 31 ---- .../java/jetty/bootstrap/JettyBootstrap.java | 61 ------- .../jetty/bootstrap/LiveWarClassLoader.java | 171 ------------------ container/pom.xml | 83 --------- .../pairgoth/container/ServerMain.java | 157 ---------------- .../main/resources/jetty-logging.properties | 2 - debug.sh | 2 +- pom.xml | 14 +- run.sh | 2 +- view-webapp/pom.xml | 5 - webserver/pom.xml | 170 +++++++++++++++++ .../jeudego/pairgoth/application/Pairgoth.kt | 50 +++++ 16 files changed, 303 insertions(+), 540 deletions(-) delete mode 100644 bootstrap/pom.xml delete mode 100644 bootstrap/src/main/java/jetty/bootstrap/JettyBootstrap.java delete mode 100644 bootstrap/src/main/java/jetty/bootstrap/LiveWarClassLoader.java delete mode 100644 container/pom.xml delete mode 100644 container/src/main/java/org/jeudego/pairgoth/container/ServerMain.java delete mode 100644 container/src/main/resources/jetty-logging.properties create mode 100644 webserver/pom.xml create mode 100644 webserver/src/main/kotlin/org/jeudego/pairgoth/application/Pairgoth.kt diff --git a/README.md b/README.md index 10d50d5..91ab105 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,7 @@ ├── run.bat ................................... Executable run script, windows ├── test.sh ................................... Executable test script, linux ├── application ............................... Executable final packaging -├── bootstrap ................................. Executable entry point -├── container ................................. Web container +├── webserver ................................. Web container ├── docker .................................... Docker packaging │   ├── pairgoth.properties.example ........... Docker property file to instanciate │   └── run.sh ................................ Docker launch script @@ -24,6 +23,7 @@ │   └── WEB-INF ................... Engine API webapp configuration └── test └── kotlin ........................ Engine webapp API unit tests +└── view-webapp ............................... Web interface ``` ## API Webapp sources structure @@ -37,7 +37,6 @@ api-webapp/src/main/kotlin/org/jeudego/pairgoth ├── store .................................. Persistence handlers ├── util ................................... Various utilities └── web .................................... Web interface - └── sse ................................ Server Sent Events interface ``` Tests are located in `webapp/src/test/kotlin` @@ -48,12 +47,10 @@ Tests are located in `webapp/src/test/kotlin` You need maven installed. -Copy and adapt `pairgoth.properties.example` towards `pairgoth.properties`. +Copy and adapt `pairgoth.properties.example` towards `pairgoth.properties`, if needed. Otherwise pairgoth will use default properties (TODO - list them) Just running `./run.sh` or `./run.bat` shoud build and run the engine . -Run `/test.sh` to test the engine. - ### Docker Under windows, please use the WSL. diff --git a/api-webapp/pom.xml b/api-webapp/pom.xml index ef8e7ca..9f884e0 100644 --- a/api-webapp/pom.xml +++ b/api-webapp/pom.xml @@ -16,10 +16,6 @@ PairGoth pairing system TODO - 1.8.21 - official - 10 - true 5.7.1 @@ -30,7 +26,6 @@ org.jetbrains.kotlin kotlin-maven-plugin - ${kotlin.version} compile diff --git a/application/pom.xml b/application/pom.xml index faf561e..0d65280 100644 --- a/application/pom.xml +++ b/application/pom.xml @@ -7,7 +7,7 @@ 1.0-SNAPSHOT application - pom + jar UTF-8 ${project.build.directory}/servermanifest @@ -21,18 +21,34 @@ ${project.groupId} - bootstrap + view-webapp ${project.version} + war ${project.groupId} - container + webserver ${project.version} pairgoth-engine + + org.apache.maven.plugins + maven-jar-plugin + + org.apache.maven.plugins maven-dependency-plugin @@ -47,7 +63,7 @@ ${project.groupId} - bootstrap + webserver ${project.version} ${serverManifestDirectory} META-INF/MANIFEST.MF @@ -55,6 +71,42 @@ + diff --git a/application/src/assembly/livewar.xml b/application/src/assembly/livewar.xml index e547269..6b5417d 100644 --- a/application/src/assembly/livewar.xml +++ b/application/src/assembly/livewar.xml @@ -4,24 +4,23 @@ live-war / - war + jar - - /WEB-INF/jetty-server/ - true - false - - ${project.groupId}:container - - / true false - ${project.groupId}:api-webapp - ${project.groupId}:bootstrap + ${project.groupId}:webserver + + + + /META-INF/webapps/ + false + false + + *:war diff --git a/bootstrap/pom.xml b/bootstrap/pom.xml deleted file mode 100644 index 70ff372..0000000 --- a/bootstrap/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - 4.0.0 - - org.jeudego.pairgoth - engine-parent - 1.0-SNAPSHOT - - bootstrap - jar - Simple Bootstrap for the Server UberJar (when packaged in a WAR) - - UTF-8 - - - - - org.apache.maven.plugins - maven-jar-plugin - - - - true - jetty.bootstrap.JettyBootstrap - - - - - - - diff --git a/bootstrap/src/main/java/jetty/bootstrap/JettyBootstrap.java b/bootstrap/src/main/java/jetty/bootstrap/JettyBootstrap.java deleted file mode 100644 index 51a88b2..0000000 --- a/bootstrap/src/main/java/jetty/bootstrap/JettyBootstrap.java +++ /dev/null @@ -1,61 +0,0 @@ -// -// ======================================================================== -// Copyright (c) Mort Bay Consulting Pty Ltd and others. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package jetty.bootstrap; - -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Method; -import java.net.URL; - -public class JettyBootstrap -{ - public static void main(String[] args) - { - try - { - URL warLocation = JettyBootstrap.class.getProtectionDomain().getCodeSource().getLocation(); - if (warLocation == null) - { - throw new IOException("JettyBootstrap not discoverable"); - } - - LiveWarClassLoader clWar = new LiveWarClassLoader(warLocation); - System.err.println("Using ClassLoader: " + clWar); - Thread.currentThread().setContextClassLoader(clWar); - - File warFile = new File(warLocation.toURI()); - System.setProperty("org.eclipse.jetty.livewar.LOCATION",warFile.toPath().toRealPath().toString()); - - // CB we want colorized output on linux - if (System.getProperty("os.name").equalsIgnoreCase("linux")) - { - System.setProperty("org.eclipse.jetty.logging.appender.MESSAGE_ESCAPE", "false"); - } - - Class mainClass = Class.forName("org.jeudego.pairgoth.container.ServerMain",false,clWar); - Method mainMethod = mainClass.getMethod("main",args.getClass()); - mainMethod.invoke(mainClass,new Object[] { args }); - } - catch (Throwable t) - { - t.printStackTrace(System.err); - System.exit(-1); - } - } -} diff --git a/bootstrap/src/main/java/jetty/bootstrap/LiveWarClassLoader.java b/bootstrap/src/main/java/jetty/bootstrap/LiveWarClassLoader.java deleted file mode 100644 index 6499bc4..0000000 --- a/bootstrap/src/main/java/jetty/bootstrap/LiveWarClassLoader.java +++ /dev/null @@ -1,171 +0,0 @@ -// -// ======================================================================== -// Copyright (c) Mort Bay Consulting Pty Ltd and others. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package jetty.bootstrap; - -import java.io.ByteArrayOutputStream; -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Enumeration; -import java.util.List; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; - -public class LiveWarClassLoader extends ClassLoader implements Closeable -{ - private static final String ID = LiveWarClassLoader.class.getSimpleName(); - private static final boolean DEBUG = Boolean.getBoolean("jetty.bootstrap.debug"); - private static final String CLASSES_BASE = "WEB-INF/jetty-server/"; - private final URI warFileUri; - private JarFile warFile; - - public LiveWarClassLoader(URL warFileUrl) throws URISyntaxException, IOException - { - this.warFileUri = warFileUrl.toURI(); - this.warFile = new JarFile(new File(warFileUri)); - } - - public void close() throws IOException - { - warFile.close(); - } - - private void debug(String format, Object... args) - { - if (DEBUG) - { - System.err.printf('[' + ID + "] " + format + "%n",args); - } - } - - @Override - protected Class findClass(String name) throws ClassNotFoundException - { - debug("findClass: %s",name); - String path = name.replace('.','/').concat(".class"); - ZipEntry entry = findEntry(path); - if (entry != null) - { - try - { - return loadClass(name,entry); - } - catch (IOException e) - { - throw new ClassNotFoundException(name,e); - } - } - else - { - throw new ClassNotFoundException(name); - } - } - - private ZipEntry findEntry(String name) - { - StringBuilder path = new StringBuilder(); - path.append(CLASSES_BASE); - if (name.charAt(0) == '/') - { - path.append(name.substring(1)); - } - else - { - path.append(name); - } - ZipEntry entry = warFile.getEntry(path.toString()); - debug("findEntry(%s) %s => %s",name,path,entry); - return entry; - } - - @Override - protected URL findResource(String name) - { - debug("findResource: %s",name); - ZipEntry entry = findEntry(name); - if (entry != null) - { - try - { - return URI.create("jar:" + this.warFileUri.toASCIIString() + "!/" + entry.getName()).toURL(); - } - catch (MalformedURLException e) - { - e.printStackTrace(System.err); - return null; - } - } - return null; - } - - @Override - protected Enumeration findResources(String name) throws IOException - { - debug("findResources: %s",name); - List urls = new ArrayList<>(); - URL self = findResource(name); - if (self != null) - { - urls.add(self); - } - - if (getParent() != null) - { - Enumeration parent = getParent().getResources(name); - while (parent.hasMoreElements()) - { - urls.add(parent.nextElement()); - } - } - - return Collections.enumeration(urls); - } - - private Class loadClass(String name, ZipEntry entry) throws IOException - { - try (InputStream in = warFile.getInputStream(entry); ByteArrayOutputStream out = new ByteArrayOutputStream()) - { - int len = 0; - int bufferSize = 4096; - byte[] buffer = new byte[bufferSize]; - while (true) - { - len = in.read(buffer,0,bufferSize); - if (len < 0) - break; - out.write(buffer,0,len); - } - byte[] classBytes = out.toByteArray(); - return defineClass(name,classBytes,0,classBytes.length); - } - } - - @Override - public String toString() - { - return String.format("%s[%s]",this.getClass().getName(),this.warFileUri); - } -} diff --git a/container/pom.xml b/container/pom.xml deleted file mode 100644 index 352b942..0000000 --- a/container/pom.xml +++ /dev/null @@ -1,83 +0,0 @@ - - 4.0.0 - - org.jeudego.pairgoth - engine-parent - 1.0-SNAPSHOT - - container - jar - Creates a UberJar consisting of all classes needed to start Jetty - - UTF-8 - - - - org.eclipse.jetty - jetty-webapp - ${jetty.version} - - - - org.eclipse.jetty - jetty-slf4j-impl - ${jetty.version} - - - org.eclipse.jetty - jetty-jndi - ${jetty.version} - - - - - - - org.apache.maven.plugins - maven-shade-plugin - - - rebuild-war - package - - shade - - - false - - - *:* - - - - - *:* - - META-INF/MANIFEST.MF - META-INF/VERSION.txt - - - - - - - - - - - - - diff --git a/container/src/main/java/org/jeudego/pairgoth/container/ServerMain.java b/container/src/main/java/org/jeudego/pairgoth/container/ServerMain.java deleted file mode 100644 index e9d1f65..0000000 --- a/container/src/main/java/org/jeudego/pairgoth/container/ServerMain.java +++ /dev/null @@ -1,157 +0,0 @@ -// -// ======================================================================== -// Copyright (c) Mort Bay Consulting Pty Ltd and others. -// ------------------------------------------------------------------------ -// All rights reserved. This program and the accompanying materials -// are made available under the terms of the Eclipse Public License v1.0 -// and Apache License v2.0 which accompanies this distribution. -// -// The Eclipse Public License is available at -// http://www.eclipse.org/legal/epl-v10.html -// -// The Apache License v2.0 is available at -// http://www.opensource.org/licenses/apache2.0.php -// -// You may elect to redistribute this code under either of these licenses. -// ======================================================================== -// - -package org.jeudego.pairgoth.container; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Map; -import java.util.Properties; - -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.handler.ContextHandlerCollection; -import org.eclipse.jetty.util.resource.PathResource; -import org.eclipse.jetty.webapp.WebAppContext; - -public class ServerMain -{ - enum OperationalMode - { - DEV, - PROD - } - - private Path apiBasePath = null; - private Path viewBasePath = null; - - public static void main(String[] args) - { - try - { - new ServerMain().run(); - } - catch (Throwable t) - { - t.printStackTrace(); - } - } - - private void run() throws Throwable - { - // create server and web context - Server server = new Server(8080); - - WebAppContext apiContext = new WebAppContext() { - @Override - public boolean isServerResource(String name, URL url) - { - return super.isServerResource(name, url) || url.getFile().contains("/WEB-INF/jetty-server/"); - } - }; - apiContext.setContextPath("/api"); - - WebAppContext viewContext = new WebAppContext() { - @Override - public boolean isServerResource(String name, URL url) - { - return super.isServerResource(name, url) || url.getFile().contains("/WEB-INF/jetty-server/"); - } - }; - viewContext.setContextPath("/"); - - // pairgoth runtime properties - File properties = new File("./pairgoth.properties"); - if (properties.exists()) { - Properties props = new Properties(); - props.load(new FileReader(properties)); - for (Map.Entry entry: props.entrySet()) { - String property = (String)entry.getKey(); - String value = (String)entry.getValue(); - if (property.startsWith("logger.")) { - apiContext.setInitParameter("webapp-slf4j-logger." + property.substring(7), value); - } else { - System.setProperty("pairgoth." + property, value); - } - } - } - - switch (getOperationalMode()) - { - case PROD: - // Configure as WAR - apiContext.setWar(apiBasePath.toString()); - viewContext.setWar(viewBasePath.toString()); - break; - case DEV: - // Configuring from Development Base - - apiContext.setBaseResource(new PathResource(apiBasePath.resolve("src/main/webapp"))); - // Add webapp compiled classes & resources (copied into place from src/main/resources) - Path apiClassesPath = apiBasePath.resolve("target/webapp/WEB-INF/classes"); - apiContext.setExtraClasspath(apiClassesPath.toAbsolutePath().toString()); - - viewContext.setBaseResource(new PathResource(viewBasePath.resolve("src/main/webapp"))); - // Add webapp compiled classes & resources (copied into place from src/main/resources) - Path viewClassesPath = viewBasePath.resolve("target/webapp/WEB-INF/classes"); - viewContext.setExtraClasspath(viewClassesPath.toAbsolutePath().toString()); - - server.setDumpAfterStart(true); - break; - default: - throw new FileNotFoundException("Unable to configure WebAppContext base resource undefined"); - } - - server.setHandler(new ContextHandlerCollection(apiContext, viewContext)); - - server.start(); - server.join(); - } - - private OperationalMode getOperationalMode() throws IOException - { - // Property set by jetty.bootstrap.JettyBootstrap - String warLocation = System.getProperty("org.eclipse.jetty.livewar.LOCATION"); - if (warLocation != null) - { - Path warPath = new File(warLocation).toPath().toRealPath(); - if (Files.exists(warPath) && Files.isRegularFile(warPath)) - { - this.apiBasePath = warPath; - this.viewBasePath = warPath; - return OperationalMode.PROD; - } - } - - // We are in development mode, likely building and testing from an IDE. - Path apiDevPath = new File("../api-webapp").toPath().toRealPath(); - Path viewDevPath = new File("../view-webapp").toPath().toRealPath(); - if (Files.exists(apiDevPath) && Files.isDirectory(apiDevPath) && Files.exists(viewDevPath) && Files.isDirectory(viewDevPath)) - { - this.apiBasePath = apiDevPath; - this.viewBasePath = viewDevPath; - return OperationalMode.DEV; - } - - return null; - } -} diff --git a/container/src/main/resources/jetty-logging.properties b/container/src/main/resources/jetty-logging.properties deleted file mode 100644 index d4922ad..0000000 --- a/container/src/main/resources/jetty-logging.properties +++ /dev/null @@ -1,2 +0,0 @@ -org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog -org.eclipse.jetty.LEVEL=INFO diff --git a/debug.sh b/debug.sh index 31b1999..beadb52 100755 --- a/debug.sh +++ b/debug.sh @@ -1,3 +1,3 @@ #!/bin/sh -mvn package && java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5006 -jar application/target/pairgoth-engine.war +mvn package && java -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5006 -jar application/target/pairgoth-engine.jar diff --git a/pom.xml b/pom.xml index 14177a4..1856055 100644 --- a/pom.xml +++ b/pom.xml @@ -56,13 +56,18 @@ 4.0.4 10.0.15 2.0.7 + + + 1.8.21 + official + 10 + true api-webapp view-webapp - container - bootstrap + webserver application @@ -144,6 +149,11 @@ license-maven-plugin ${license.plugin.version} + + org.jetbrains.kotlin + kotlin-maven-plugin + ${kotlin.version} + diff --git a/run.sh b/run.sh index fa204ca..a0cf0d2 100755 --- a/run.sh +++ b/run.sh @@ -1,3 +1,3 @@ #!/bin/sh -mvn package && java -jar application/target/pairgoth-engine.war +mvn package && java -jar application/target/pairgoth-engine.jar diff --git a/view-webapp/pom.xml b/view-webapp/pom.xml index f6afb56..d1f80e2 100644 --- a/view-webapp/pom.xml +++ b/view-webapp/pom.xml @@ -16,10 +16,6 @@ PairGoth pairing system TODO - 1.8.21 - official - 10 - true 5.7.1 @@ -30,7 +26,6 @@ org.jetbrains.kotlin kotlin-maven-plugin - ${kotlin.version} compile diff --git a/webserver/pom.xml b/webserver/pom.xml new file mode 100644 index 0000000..cb76603 --- /dev/null +++ b/webserver/pom.xml @@ -0,0 +1,170 @@ + + 4.0.0 + + org.jeudego.pairgoth + engine-parent + 1.0-SNAPSHOT + + webserver + jar + Pairgoth Launcher + + UTF-8 + + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-test-junit5 + 1.8.21 + test + + + org.junit.jupiter + junit-jupiter-engine + 5.9.1 + test + + + org.eclipse.jetty + jetty-webapp + ${jetty.version} + + + org.eclipse.jetty + jetty-slf4j-impl + ${jetty.version} + + + org.eclipse.jetty + jetty-jndi + ${jetty.version} + + + commons-io + commons-io + 2.11.0 + + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + + + compile + compile + + compile + + + + src/main/kotlin + + + + + test-compile + test-compile + + test-compile + + + + + 1.8 + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + org.jeudego.pairgoth.application.PairgothKt + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + compile + compile + + compile + + + + testCompile + test-compile + + testCompile + + + + + + maven-surefire-plugin + + + maven-failsafe-plugin + + + org.apache.maven.plugins + maven-shade-plugin + + + rebuild-war + package + + shade + + + false + + + *:* + + + + + *:* + + + META-INF/VERSION.txt + + + + + + + + + + + + + diff --git a/webserver/src/main/kotlin/org/jeudego/pairgoth/application/Pairgoth.kt b/webserver/src/main/kotlin/org/jeudego/pairgoth/application/Pairgoth.kt new file mode 100644 index 0000000..e49974f --- /dev/null +++ b/webserver/src/main/kotlin/org/jeudego/pairgoth/application/Pairgoth.kt @@ -0,0 +1,50 @@ +package org.jeudego.pairgoth.application + +import org.apache.commons.io.FileUtils +import org.eclipse.jetty.server.Server +import java.net.JarURLConnection +import java.nio.file.Files +import java.nio.file.Path +import java.util.jar.JarFile + + +fun main(vararg args: String) { + try { + extractWarFiles() + launchServer() + } catch (t: Throwable) { + t.printStackTrace(System.err) + } +} + +fun extractWarFiles() { + // val jarLocation = object{}::class.java.protectionDomain.codeSource.location + // prepare output directory + val tmp = System.getProperty("java.io.tmpdir") + val targetPath = Path.of("${tmp}/pairgoth/webapps") + FileUtils.deleteDirectory(targetPath.toFile()) + Files.createDirectories(targetPath) + + // extract wars + val webappsFolderURL = object{}::class.java.enclosingClass.getResource("/META-INF/webapps") ?: throw Error("webapps not found") + val jarConnection = webappsFolderURL.openConnection() as JarURLConnection + val jarFile: JarFile = jarConnection.getJarFile() + jarFile.entries().toList().filter { entry -> + entry.name.startsWith(jarConnection.entryName) + }.forEach { entry -> + if (!entry.isDirectory) { + jarFile.getInputStream(entry).use { entryInputStream -> + Files.copy(entryInputStream, targetPath.resolve(entry.name.removePrefix("META-INF/webapps/"))) + } + } + } +} + +fun launchServer() { + + // create server + val server = Server(8080) + + // register webapps +// server. +} \ No newline at end of file