1 package attrib4j.cfparse;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.DataOutputStream;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.ObjectOutputStream;
9 import java.net.URLClassLoader;
10 import java.util.Arrays;
11
12 import attrib4j.AttributeException;
13 import attrib4j.ClassAnnotator;
14
15 import com.ibm.toad.cfparse.ClassFile;
16 import com.ibm.toad.cfparse.FieldInfo;
17 import com.ibm.toad.cfparse.FieldInfoList;
18 import com.ibm.toad.cfparse.MethodInfo;
19 import com.ibm.toad.cfparse.MethodInfoList;
20 import com.ibm.toad.cfparse.attributes.AttrInfoList;
21 import com.ibm.toad.cfparse.utils.CFUtils;
22 import com.sun.javadoc.MethodDoc;
23
24 /***
25 * The CFParse implementation of a ClassAnnotator. This class will use
26 * the CFParse API to insert attributes into .class files.
27 *
28 * @author <a href="mailto:mpollack@speakeasy.net">Mark Pollack</a>
29 * @author Ted Neward
30 * @version $Revision: 1.5 $ $Date: 2003/09/01 19:56:16 $
31 *
32 */
33 public class CFParseClassAnnotator implements ClassAnnotator {
34
35 ClassFile _cf;
36 MethodInfoList _mil;
37 FieldInfoList _fil;
38
39 /***
40 * Create the instance using an InputStream initialized to the
41 * class file that will be modified/annotated.
42 *
43 * @param InputStream initialized with .class file.
44 * @exception AttributeException if an error occurs
45 */
46 public CFParseClassAnnotator(InputStream classFile)
47 throws AttributeException {
48
49 try {
50 _cf = new ClassFile(classFile);
51 _mil = _cf.getMethods();
52 _fil = _cf.getFields();
53 } catch (IOException e) {
54 new AttributeException("Could not create CFParseClassAnnotator", e);
55 }
56 }
57
58 /***
59 * Insert a custom class attribute into the bytecode.
60 *
61 * @param attribute The attribute to be inserted.
62 */
63 public void insertClassAttribute(Object attribute) {
64 byte[] data = serialize(attribute);
65
66 AttrInfoList ail = _cf.getAttrs();
67 CFCustomAttrInfo cai =
68 (CFCustomAttrInfo) ail.add("attrib4j.cfparse.CFCustom");
69
70 cai.setSerializedData(data);
71 }
72
73 /***
74 * Insert a custom field attribute into the bytecode.
75 *
76 * @param field The name of the field to apply the attribute.
77 * @param attribute The attribute to be inserted.
78 */
79 public void insertFieldAttribute(String field, Object attribute) {
80
81 byte[] data = serialize(attribute);
82
83 for (int i = 0; i < _fil.length(); i++) {
84 if (_fil.getFieldName(i).equals(field)) {
85 FieldInfo fld = _fil.get(i);
86 AttrInfoList ail = fld.getAttrs();
87 CFCustomAttrInfo cai =
88 (CFCustomAttrInfo) ail.add("attrib4j.cfparse.CFCustom");
89
90 cai.setSerializedData(data);
91
92 break;
93 }
94 }
95 }
96
97 /***
98 * Insert a custom method attribute into the bytecode.
99 *
100 * @param methodDoc The Javadoc metadata class defining the method to
101 * annotate.
102 * @param attribute The attribute to be inserted.
103 */
104 public void insertMethodAttribute(MethodDoc methodDoc, Object attribute) {
105 String methodName = methodDoc.name();
106 String[] methodParamTypes = new String[methodDoc.parameters().length];
107 for (int i = 0; i < methodParamTypes.length; i++) {
108 //TODO: MLP should be qualifiedTypeName in order to accept
109 //params other than from the java.lang package?
110 //what about dimension info?
111 methodParamTypes[i] = methodDoc.parameters()[i].typeName();
112 }
113
114 byte[] data = serialize(attribute);
115
116 MethodInfo mi = null;
117 for (int i = 0; i < _mil.length(); i++) {
118 mi = _mil.get(i);
119 if (_mil.getMethodName(i).equals(methodName)
120 && Arrays.equals(methodParamTypes, mi.getParams())) {
121 AttrInfoList ail = mi.getAttrs();
122 CFCustomAttrInfo cai =
123 (CFCustomAttrInfo) ail.add("attrib4j.cfparse.CFCustom");
124 cai.setSerializedData(data);
125 break;
126 }
127 }
128 }
129
130 /***
131 * Write out the modified classfile.
132 *
133 * @param destDir The directory where the modified class fiel should be
134 * written.
135 */
136 public void write(String destDir) {
137 try {
138 String path = destDir + "/" + CFUtils.canonicalize(_cf.getName());
139 //MLP: TODO: directory needs to exist before...
140 FileOutputStream fout = new FileOutputStream(path);
141 DataOutputStream out = new DataOutputStream(fout);
142 _cf.write(out);
143 fout.close();
144 } catch (IOException ioEx) {
145 ioEx.printStackTrace();
146 }
147 }
148
149 /***
150 * Helper method to serialize an object.
151 *
152 * @param obj The object to serialize.
153 * @return The serialized objects byte representation.
154 */
155 private byte[] serialize(Object obj) {
156 try {
157 ByteArrayOutputStream baos = new ByteArrayOutputStream();
158 ObjectOutputStream oos = new ObjectOutputStream(baos);
159 oos.writeObject(obj);
160 return baos.toByteArray();
161 } catch (IOException ioEx) {
162 return null;
163 }
164 }
165
166 /***
167 * Just added to avoid compilation error. Will remove CFParse support soon.
168 * @see attrib4j.ClassAnnotator#createAttributeInstance(java.lang.String, java.net.URLClassLoader, java.lang.String[])
169 */
170 public Object createAttributeInstance(String text, URLClassLoader classLoader, String[] attributePackages) {
171 // TODO Auto-generated method stub
172 return null;
173 }
174
175
176 }
This page was automatically generated by Maven