1
2
3
4
5
6
7
8
9
10 package it.imolinfo.jbi4cics.webservices.utils.generators;
11
12 import static org.objectweb.asm.Opcodes.ACC_PRIVATE;
13 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
14 import static org.objectweb.asm.Opcodes.ACC_SUPER;
15 import static org.objectweb.asm.Opcodes.ALOAD;
16 import static org.objectweb.asm.Opcodes.ARETURN;
17 import static org.objectweb.asm.Opcodes.GETFIELD;
18 import static org.objectweb.asm.Opcodes.ILOAD;
19 import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
20 import static org.objectweb.asm.Opcodes.INVOKESTATIC;
21 import static org.objectweb.asm.Opcodes.IRETURN;
22 import static org.objectweb.asm.Opcodes.PUTFIELD;
23 import static org.objectweb.asm.Opcodes.RETURN;
24 import static org.objectweb.asm.Opcodes.V1_1;
25 import it.imolinfo.jbi4cics.Logger;
26 import it.imolinfo.jbi4cics.LoggerFactory;
27 import it.imolinfo.jbi4cics.exception.ClassGenerationException;
28 import it.imolinfo.jbi4cics.exception.FormatException;
29 import it.imolinfo.jbi4cics.jbi.BCELClassLoader;
30 import it.imolinfo.jbi4cics.messageformat.FieldDescriptor;
31 import it.imolinfo.jbi4cics.messageformat.MappingDescriptor;
32 import it.imolinfo.jbi4cics.typemapping.cobol.CobolType;
33 import it.imolinfo.jbi4cics.typemapping.cobol.CobolTypeDescriptor;
34 import it.imolinfo.jbi4cics.webservices.descriptor.ServiceDescriptor;
35 import java.util.Map;
36 import org.objectweb.asm.ClassWriter;
37 import org.objectweb.asm.FieldVisitor;
38 import org.objectweb.asm.MethodVisitor;
39 import org.objectweb.asm.Type;
40
41 public final class ServiceBeanGenerator {
42
43
44
45
46 private static final Logger LOG
47 = LoggerFactory.getLogger(ServiceBeanGenerator.class);
48
49
50
51
52
53 private final String completeClassName;
54
55
56
57
58
59
60 private final String internalClassName;
61
62
63
64
65 private final MappingDescriptor mappingDescriptor;
66
67
68
69
70
71
72 private final ClassWriter classWriter = new ClassWriter(true);
73
74 public ServiceBeanGenerator(final ServiceDescriptor desc,
75 final boolean input) {
76 this(desc.getServiceInterfacePackageName() + "."
77 + (input ? desc.getInputBeanClassName()
78 : desc.getOutputBeanClassName()),
79 input ? desc.getInputMappingDescriptor()
80 : desc.getOutputMappingDescriptor());
81 }
82
83 private ServiceBeanGenerator(final String completeClassName,
84 final MappingDescriptor mappingDescriptor) {
85 this.completeClassName = completeClassName;
86 this.mappingDescriptor = mappingDescriptor;
87
88 internalClassName = completeClassName.replace('.', '/');
89 classWriter.visit(V1_1, ACC_PUBLIC + ACC_SUPER, internalClassName, null,
90 "java/lang/Object", null);
91 }
92
93
94
95
96
97
98
99 public Class generateBeanClass(final BCELClassLoader loader)
100 throws ClassGenerationException {
101 boolean debug = LOG.isDebugEnabled();
102 Class clazz;
103
104 addDefaultConstructor();
105 addToStringMethod();
106 addEqualsMethod();
107 addHashCodeMethod();
108 try {
109 Map<String, FieldDescriptor> fields
110 = mappingDescriptor.getFieldMap();
111
112 for (Map.Entry<String, FieldDescriptor> entry : fields.entrySet()) {
113 String propertyName = entry.getKey();
114 FieldDescriptor fieldDescriptor = entry.getValue();
115 Type type;
116
117 if (fieldDescriptor instanceof CobolTypeDescriptor) {
118 CobolTypeDescriptor cobolTypeDescriptor
119 = (CobolTypeDescriptor) fieldDescriptor;
120 CobolType cobolType = cobolTypeDescriptor.getType();
121
122 if ((cobolType == CobolType.NESTED_COMMAREA)
123 || (cobolType == CobolType.OCCURS)) {
124
125
126 String innerClassName =
127 completeClassName.substring(0, completeClassName.lastIndexOf('.') + 1)
128 + propertyName;
129 ServiceBeanGenerator inner = new ServiceBeanGenerator(
130 innerClassName,
131 cobolTypeDescriptor.getNestedCommarea());
132
133 inner.generateBeanClass(loader);
134 }
135 }
136
137
138 if (debug) {
139 LOG.debug("handling property name: " + propertyName);
140 }
141 type = Type.getType(fieldDescriptor.getPreferredJavaType());
142 addPrivateField(propertyName, type);
143 addSetMethod(propertyName, type);
144 addGetMethod(propertyName, type);
145 }
146 } catch (FormatException e) {
147 Object[] args = new Object[] { completeClassName };
148
149 LOG.error("CIC002400_Class_generation_error", args, e);
150 throw new ClassGenerationException(
151 "CIC002400_Class_generation_error", args, e);
152 }
153
154 loader.addClass(completeClassName, classWriter.toByteArray());
155 try {
156 clazz = loader.loadClass(completeClassName);
157 } catch (ClassNotFoundException e) {
158 Object[] args = new Object[] { completeClassName };
159
160 LOG.error("CIC002400_Class_generation_error", args, e);
161 throw new ClassGenerationException(
162 "CIC002400_Class_generation_error", args, e);
163 }
164 mappingDescriptor.setBeanClass(clazz);
165 return clazz;
166 }
167
168
169
170
171
172 private void addDefaultConstructor() {
173 MethodVisitor mv = classWriter.visitMethod(
174 ACC_PUBLIC, "<init>", "()V", null, null);
175
176
177 mv.visitVarInsn(ALOAD, 0);
178
179
180 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V");
181 mv.visitInsn(RETURN);
182
183
184 mv.visitMaxs(1, 1);
185 mv.visitEnd();
186 }
187
188
189
190
191
192
193
194
195
196
197 private void addToStringMethod() {
198 MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC,
199 "toString", "()Ljava/lang/String;", null, null);
200
201 mv.visitVarInsn(ALOAD, 0);
202 mv.visitMethodInsn(INVOKESTATIC,
203 "org/apache/commons/lang/builder/ReflectionToStringBuilder",
204 "toString", "(Ljava/lang/Object;)Ljava/lang/String;");
205 mv.visitInsn(ARETURN);
206 mv.visitMaxs(0, 0);
207 mv.visitEnd();
208 }
209
210
211
212
213
214
215
216
217
218
219 private void addEqualsMethod() {
220 MethodVisitor mv = classWriter.visitMethod(
221 ACC_PUBLIC, "equals", "(Ljava/lang/Object;)Z", null, null);
222
223 mv.visitVarInsn(ALOAD, 0);
224 mv.visitVarInsn(ALOAD, 1);
225 mv.visitMethodInsn(INVOKESTATIC,
226 "org/apache/commons/lang/builder/EqualsBuilder",
227 "reflectionEquals", "(Ljava/lang/Object;Ljava/lang/Object;)Z");
228 mv.visitInsn(IRETURN);
229 mv.visitMaxs(0, 0);
230 mv.visitEnd();
231 }
232
233
234
235
236
237
238
239
240
241
242 private void addHashCodeMethod() {
243 MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, "hashCode",
244 "()I", null, null);
245
246 mv.visitVarInsn(ALOAD, 0);
247 mv.visitMethodInsn(INVOKESTATIC,
248 "org/apache/commons/lang/builder/HashCodeBuilder",
249 "reflectionHashCode", "(Ljava/lang/Object;)I");
250 mv.visitInsn(IRETURN);
251 mv.visitMaxs(0, 0);
252 mv.visitEnd();
253 }
254
255
256
257
258
259
260
261 private void addPrivateField(final String fieldName, final Type fieldType) {
262 FieldVisitor fv = classWriter.visitField(
263 ACC_PRIVATE, fieldName, fieldType.getDescriptor(), null, null);
264
265 fv.visitEnd();
266 }
267
268
269
270
271
272
273
274
275
276 private void addGetMethod(final String propertyName,
277 final Type propertyType) {
278 StringBuilder methodName = new StringBuilder(propertyName);
279 String returnType = propertyType.getDescriptor();
280 MethodVisitor mv;
281
282 methodName.setCharAt(0, Character.toUpperCase(methodName.charAt(0)));
283 methodName.insert(0, "get");
284
285 mv = classWriter.visitMethod(ACC_PUBLIC, methodName.toString(),
286 "()".concat(returnType), null, null);
287 mv.visitVarInsn(ALOAD, 0);
288 mv.visitFieldInsn(GETFIELD, internalClassName, propertyName,
289 returnType);
290 mv.visitInsn(propertyType.getOpcode(IRETURN));
291 mv.visitMaxs(0, 0);
292 }
293
294
295
296
297
298
299
300
301
302 private void addSetMethod(final String propertyName,
303 final Type propertyType) {
304 StringBuilder methodName = new StringBuilder(propertyName);
305 String desc = propertyType.getDescriptor();
306 MethodVisitor mv;
307
308 methodName.setCharAt(0, Character.toUpperCase(methodName.charAt(0)));
309 methodName.insert(0, "set");
310
311 mv = classWriter.visitMethod(ACC_PUBLIC, methodName.toString(),
312 "(" + desc + ")V", null, null);
313 mv.visitVarInsn(ALOAD, 0);
314 mv.visitVarInsn(propertyType.getOpcode(ILOAD), 1);
315 mv.visitFieldInsn(PUTFIELD, internalClassName, propertyName, desc);
316 mv.visitInsn(RETURN);
317 mv.visitMaxs(0, 0);
318 }
319 }