1
2
3
4
5
6 package pt.digitalis.dif.codegen.util;
7
8 import java.util.HashMap;
9 import java.util.Map;
10
11 import javassist.CannotCompileException;
12 import pt.digitalis.dif.codegen.CGAncillaries;
13 import pt.digitalis.dif.codegen.templates.ApplicationCGTemplate;
14 import pt.digitalis.dif.codegen.templates.ProviderCGTemplate;
15 import pt.digitalis.dif.codegen.templates.ServiceCGTemplate;
16 import pt.digitalis.dif.codegen.templates.StageCGTemplate;
17 import pt.digitalis.dif.codegen.templates.StageInstanceCGTemplate;
18 import pt.digitalis.dif.dem.Entity;
19 import pt.digitalis.dif.exception.codegen.DIFCodeGenerationException;
20 import pt.digitalis.dif.utils.ObjectFormatter;
21 import pt.digitalis.utils.CodeGenUtil4Javassist;
22 import pt.digitalis.utils.bytecode.exceptions.CodeGenerationException;
23 import pt.digitalis.utils.bytecode.holders.ClassHolder;
24 import pt.digitalis.utils.inspection.exception.ResourceNotFoundException;
25
26
27
28
29
30
31
32 public class ClassEnhancementContext {
33
34
35 final static private int INITIAL_CAPACITY = 2;
36
37
38 final static private float LOAD_FACTOR = 1.0f;
39
40
41
42
43
44
45
46
47
48
49 private Map<String, ClassEnhancements> classEnhancements = new HashMap<String, ClassEnhancements>(INITIAL_CAPACITY,
50 LOAD_FACTOR);
51
52
53 private String entityClassID;
54
55
56 private Entity entityType;
57
58
59 private ClassHolder theOriginalClass;
60
61
62
63
64
65
66
67
68
69
70
71
72 public ClassEnhancementContext(ClassHolder classHolder) throws ResourceNotFoundException, CodeGenerationException
73 {
74
75
76 this.theOriginalClass = classHolder;
77
78
79 this.entityType = Entity.getEntityTypeFromClass(this.theOriginalClass);
80
81
82 if (this.entityType == null)
83 throw new CodeGenerationException(this.theOriginalClass.getFQName()
84 + " is not a valid DEM entity and thus cannot be enhanced! Aborting...");
85
86
87
88
89 if (entityType.equals(Entity.STAGE))
90 {
91 this.prepareStageEnhancement();
92 }
93
94 else
95 {
96 this.prepareNonStageEnhancement();
97 }
98 }
99
100
101
102
103
104
105
106
107
108
109
110 public ClassEnhancementContext(String originalClassID) throws ResourceNotFoundException, CodeGenerationException
111 {
112 this(new ClassHolder(originalClassID));
113 }
114
115
116
117
118
119
120
121
122
123
124 public void addEnhancement(String className, ClassMethodEnhancement enhancement) throws DIFCodeGenerationException
125 {
126 try
127 {
128 this.classEnhancements.get(className).addEnhancement(enhancement);
129 }
130 catch (Exception e)
131 {
132 DIFCodeGenerationException codeGenException = new DIFCodeGenerationException(
133 "Error adding enhancement to class", e);
134 codeGenException.addToExceptionContext("Original Class Name", theOriginalClass.getFQName());
135 codeGenException.addToExceptionContext("Entity ID", entityClassID);
136 codeGenException.addToExceptionContext("Entity Type", entityType);
137 codeGenException.addToExceptionContext("Class Name", className);
138 codeGenException.addToExceptionContext("Enhancement", enhancement);
139
140 throw codeGenException;
141 }
142 }
143
144
145
146
147
148
149
150
151
152
153
154 public void addEnhancement(String methodName, String enhancement) throws DIFCodeGenerationException
155 {
156 if (entityType == Entity.STAGE)
157 addEnhancement(CGAncillaries.STAGE_PROXY_ID, methodName, enhancement);
158 else
159 addEnhancement(CGAncillaries.NON_STAGE_ENRICHED_CLASS_ID, methodName, enhancement);
160 }
161
162
163
164
165
166
167
168
169
170
171
172
173 public void addEnhancement(String className, String methodName, String enhancement)
174 throws DIFCodeGenerationException
175 {
176 try
177 {
178 this.classEnhancements.get(className).addSource(methodName, enhancement);
179 }
180 catch (Exception e)
181 {
182 DIFCodeGenerationException codeGenException = new DIFCodeGenerationException(
183 "Error adding enhancement to class", e);
184 codeGenException.addToExceptionContext("Original Class Name", theOriginalClass.getFQName());
185 codeGenException.addToExceptionContext("Entity ID", entityClassID);
186 codeGenException.addToExceptionContext("Entity Type", entityType);
187 codeGenException.addToExceptionContext("Class Name", className);
188 codeGenException.addToExceptionContext("Method Name", methodName);
189 codeGenException.addToExceptionContext("Enhancement", enhancement);
190
191 throw codeGenException;
192 }
193 }
194
195
196
197
198
199
200
201
202
203
204
205
206 public void addEnhancementTerminatorCode(String className, String methodName, String terminator)
207 throws DIFCodeGenerationException
208 {
209 try
210 {
211 this.classEnhancements.get(className).setTerminator(methodName, terminator);
212 }
213 catch (Exception e)
214 {
215 DIFCodeGenerationException codeGenException = new DIFCodeGenerationException(
216 "Error adding enhancement to class", e);
217 codeGenException.addToExceptionContext("Original Class Name", theOriginalClass.getFQName());
218 codeGenException.addToExceptionContext("Entity ID", entityClassID);
219 codeGenException.addToExceptionContext("Entity Type", entityType);
220 codeGenException.addToExceptionContext("Class Name", className);
221 codeGenException.addToExceptionContext("Method Name", methodName);
222 codeGenException.addToExceptionContext("Terminator", terminator);
223
224 throw codeGenException;
225 }
226 }
227
228
229
230
231
232
233
234
235
236 public void commitEnhancements() throws ResourceNotFoundException, CodeGenerationException
237 {
238 for (String className: this.classEnhancements.keySet())
239 {
240 try
241 {
242 this.classEnhancements.get(className).commitEnhancements();
243 }
244 catch (Exception e)
245 {
246 DIFCodeGenerationException codeGenException = new DIFCodeGenerationException(
247 "Error adding enhancement to class", e);
248 codeGenException.addToExceptionContext("Original Class Name", theOriginalClass.getFQName());
249 codeGenException.addToExceptionContext("Entity ID", entityClassID);
250 codeGenException.addToExceptionContext("Entity Type", entityType);
251 codeGenException.addToExceptionContext("Class Name", className);
252 }
253 }
254 }
255
256
257
258
259
260
261
262
263 public boolean containsEnhancement(String methodName)
264 {
265 if (entityType == Entity.STAGE)
266 return containsEnhancement(CGAncillaries.STAGE_PROXY_ID, methodName);
267 else
268 return containsEnhancement(CGAncillaries.NON_STAGE_ENRICHED_CLASS_ID, methodName);
269 }
270
271
272
273
274
275
276
277
278
279
280 public boolean containsEnhancement(String className, String methodName)
281 {
282 return this.classEnhancements.get(className).getMethodEnhancements().containsKey(methodName);
283 }
284
285
286
287
288
289
290 public Map<String, ClassEnhancements> getClassEnhancements()
291 {
292 return this.classEnhancements;
293 }
294
295
296
297
298
299
300 public ClassHolder getEntityClass()
301 {
302 return classEnhancements.get(entityClassID).getClassObject();
303 }
304
305
306
307
308
309
310 public ClassHolder getOriginalClassObject()
311 {
312 return this.theOriginalClass;
313 }
314
315
316
317
318
319
320 public String getOriginalClassName()
321 {
322 return this.theOriginalClass.getFQName();
323 }
324
325
326
327
328
329
330
331
332
333 final private void prepareNonStageEnhancement() throws CodeGenerationException, ResourceNotFoundException
334 {
335
336 this.entityClassID = CGAncillaries.NON_STAGE_ENRICHED_CLASS_ID;
337 ClassHolder enrichedClassHolder = CodeGenUtil4Javassist.createNewClassHolder(this.theOriginalClass.getFQName()
338 + CGAncillaries.NON_STAGE_ENRICHED_CLASS_ID);
339 try
340 {
341
342 enrichedClassHolder.setSuperClass(this.theOriginalClass.getFQName());
343 }
344 catch (CannotCompileException cannotCompileException)
345 {
346 throw new CodeGenerationException("Class " + this.theOriginalClass.getFQName()
347 + " already extends from another class! Unable to compile...", cannotCompileException);
348 }
349
350
351 switch (entityType)
352 {
353 case VALIDATOR:
354
355
356 break;
357 case PROVIDER:
358 enrichedClassHolder.copyAllFromClass(new ClassHolder(ProviderCGTemplate.class.getCanonicalName()));
359 break;
360 case APPLICATION:
361 enrichedClassHolder.copyAllFromClass(new ClassHolder(ApplicationCGTemplate.class.getCanonicalName()));
362 break;
363 case SERVICE:
364 enrichedClassHolder.copyAllFromClass(new ClassHolder(ServiceCGTemplate.class.getCanonicalName()));
365 break;
366 default:
367 throw new CodeGenerationException("Invalid entity type: " + this.theOriginalClass.getFQName()
368 + "!! Aborting...");
369 }
370
371
372 ClassEnhancements enrichedClassEnhancements = new ClassEnhancements(enrichedClassHolder);
373
374
375 classEnhancements.put(CGAncillaries.NON_STAGE_ENRICHED_CLASS_ID, enrichedClassEnhancements);
376 }
377
378
379
380
381
382
383
384
385
386 final private void prepareStageEnhancement() throws CodeGenerationException, ResourceNotFoundException
387 {
388
389 this.entityClassID = CGAncillaries.STAGE_PROXY_ID;
390 ClassHolder stageProxyClassHolder = CodeGenUtil4Javassist.createNewClassHolder(this.theOriginalClass
391 .getFQName() + CGAncillaries.STAGE_PROXY_ID);
392
393 stageProxyClassHolder.copyAllFromClass(new ClassHolder(StageCGTemplate.class.getCanonicalName()));
394
395 ClassEnhancements stageProxyClassEnhancements = new ClassEnhancements(stageProxyClassHolder);
396
397
398 ClassHolder stageInstanceClassHolder = CodeGenUtil4Javassist.createNewClassHolder(this.theOriginalClass
399 .getFQName() + CGAncillaries.STAGE_INSTANCE_ID);
400
401 try
402 {
403
404 stageInstanceClassHolder.setSuperClass(this.theOriginalClass.getFQName());
405 }
406 catch (CannotCompileException cannotCompileException)
407 {
408 throw new CodeGenerationException("Class " + this.theOriginalClass.getFQName()
409 + " already extends from another class! Unable to compile...", cannotCompileException);
410 }
411
412 stageInstanceClassHolder.copyAllFromClass(new ClassHolder(StageInstanceCGTemplate.class.getCanonicalName()));
413
414
415 ClassEnhancements stageInstanceClassEnhancements = new ClassEnhancements(stageInstanceClassHolder);
416
417
418 stageProxyClassEnhancements.registerMethodAsIncremental(CGAncillaries.STAGE_INJECTED_VIEWS_BUILDER);
419 stageProxyClassEnhancements.registerMethodAsIncremental(CGAncillaries.STAGE_INJECTED_ERRORVIEWS_BUILDER);
420 stageProxyClassEnhancements.registerMethodAsIncremental(CGAncillaries.STAGE_INJECTED_STAGES_BUILDER);
421 stageProxyClassEnhancements.registerMethodAsIncremental(CGAncillaries.STAGE_INJECTED_ERRORSTAGES_BUILDER);
422 stageProxyClassEnhancements.registerMethodAsIncremental(CGAncillaries.STAGE_EVENT_HANDLERS_BUILDER);
423
424
425
426 stageInstanceClassEnhancements
427 .registerMethodAsIncremental(CGAncillaries.STAGE_INJECTED_ATTRIBUTES_INIT_METHOD_NAME);
428 stageInstanceClassEnhancements.registerMethodAsIncremental(CGAncillaries.STAGE_POSTPROCESSING_METHOD_NAME);
429 stageInstanceClassEnhancements.registerMethodAsIncremental(CGAncillaries.CALL_EXEC_ONEVENT_METHOD);
430 stageInstanceClassEnhancements.registerMethodAsIncremental(CGAncillaries.CALL_EVENT_METHOD);
431
432
433 classEnhancements.put(CGAncillaries.STAGE_PROXY_ID, stageProxyClassEnhancements);
434 classEnhancements.put(CGAncillaries.STAGE_INSTANCE_ID, stageInstanceClassEnhancements);
435 }
436
437
438
439
440
441
442
443
444
445
446
447 public void setEnhancements(String className, String methodName, String enhancement)
448 {
449 this.classEnhancements.get(className).addSource(methodName, enhancement);
450 }
451
452
453
454
455 @Override
456 public String toString()
457 {
458 ObjectFormatter formatter = new ObjectFormatter();
459
460 formatter.addItem("Original Class Name", this.getOriginalClassName());
461 formatter.addItem("Entity Class Type", this.entityType);
462 formatter.addItem("Entity Class Name", this.entityClassID);
463 formatter.addItem("Classes", this.classEnhancements);
464
465 return formatter.getFormatedObject();
466 }
467 }