1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.perfidix.element;
28
29 import java.lang.annotation.Annotation;
30 import java.lang.reflect.Method;
31 import java.lang.reflect.Modifier;
32 import java.util.ArrayList;
33 import java.util.List;
34
35 import org.perfidix.annotation.AfterBenchClass;
36 import org.perfidix.annotation.AfterEachRun;
37 import org.perfidix.annotation.AfterLastRun;
38 import org.perfidix.annotation.BeforeBenchClass;
39 import org.perfidix.annotation.BeforeEachRun;
40 import org.perfidix.annotation.BeforeFirstRun;
41 import org.perfidix.annotation.Bench;
42 import org.perfidix.annotation.BenchClass;
43 import org.perfidix.annotation.SkipBench;
44 import org.perfidix.exceptions.PerfidixMethodCheckException;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60 public final class BenchmarkMethod {
61
62
63
64
65 private transient final Method methodToBench;
66
67
68
69
70
71
72
73
74
75 public BenchmarkMethod(final Method paramMethod) {
76 methodToBench = paramMethod;
77 if (!isBenchmarkable(methodToBench)) {
78 throw new IllegalArgumentException(new StringBuilder(
79 "Only benchmarkable methods allowed but method ").append(paramMethod).append(
80 " is not benchmarkable.").toString());
81 }
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100 public Method[] findBeforeFirstRun() throws PerfidixMethodCheckException {
101
102 Method method = null;
103
104 final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
105 if (benchAnno != null && !benchAnno.beforeFirstRun().equals("")) {
106 List<Method> returnval = new ArrayList<Method>();
107
108 try {
109
110 final Class<?>[] setUpParams = {};
111
112 String[] methods = benchAnno.beforeFirstRun().split(",");
113 for (String methodString : methods) {
114
115 method =
116 getMethodToBench().getDeclaringClass().getDeclaredMethod(methodString.trim(), setUpParams);
117
118 if (isReflectedExecutable(method, BeforeFirstRun.class)) {
119 returnval.add(method);
120 } else {
121 throw new PerfidixMethodCheckException(new IllegalAccessException(new StringBuilder(
122 "Failed to execute BeforeFirstRun-annotated method ").append(method).toString()),
123 method, BeforeFirstRun.class);
124 }
125 }
126 return returnval.toArray(new Method[returnval.size()]);
127
128 } catch (final SecurityException e) {
129 throw new PerfidixMethodCheckException(e, method, BeforeFirstRun.class);
130 } catch (final NoSuchMethodException e) {
131 throw new PerfidixMethodCheckException(e, method, BeforeFirstRun.class);
132 }
133 }
134
135
136
137
138 else {
139 Method meth =
140 findAndCheckAnyMethodByAnnotation(getMethodToBench().getDeclaringClass(),
141 BeforeFirstRun.class);
142 if (meth == null) {
143 return new Method[0];
144 } else {
145 return new Method[] {
146 meth
147 };
148 }
149 }
150
151 }
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169 public Method[] findBeforeEachRun() throws PerfidixMethodCheckException {
170
171 Method method = null;
172
173 final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
174 if (benchAnno != null && !benchAnno.beforeEachRun().equals("")) {
175 List<Method> returnval = new ArrayList<Method>();
176 try {
177
178 final Class<?>[] setUpParams = {};
179
180 String[] methods = benchAnno.beforeEachRun().split(",");
181 for (String methodString : methods) {
182
183
184 method =
185 getMethodToBench().getDeclaringClass().getDeclaredMethod(methodString.trim(), setUpParams);
186
187 if (isReflectedExecutable(method, BeforeEachRun.class)) {
188 returnval.add(method);
189 } else {
190 throw new PerfidixMethodCheckException(new IllegalAccessException(new StringBuilder(
191 " Failed to execute BeforeEachRun-annotated method ").append(method).toString()),
192 method, BeforeEachRun.class);
193 }
194 }
195 return returnval.toArray(new Method[returnval.size()]);
196
197 } catch (SecurityException e) {
198 throw new PerfidixMethodCheckException(e, method, BeforeEachRun.class);
199 } catch (NoSuchMethodException e) {
200 throw new PerfidixMethodCheckException(e, method, BeforeEachRun.class);
201 }
202 } else {
203
204
205
206 Method meth =
207 findAndCheckAnyMethodByAnnotation(getMethodToBench().getDeclaringClass(), BeforeEachRun.class);
208 if (meth == null) {
209 return new Method[0];
210 } else {
211 return new Method[] {
212 meth
213 };
214 }
215
216 }
217 }
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235 public Method[] findAfterEachRun() throws PerfidixMethodCheckException {
236
237 Method method = null;
238
239 final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
240 if (benchAnno != null && !benchAnno.afterEachRun().equals("")) {
241 List<Method> returnval = new ArrayList<Method>();
242 try {
243
244 final Class<?>[] setUpParams = {};
245
246 String[] methods = benchAnno.afterEachRun().split(",");
247 for (String methodString : methods) {
248
249 method =
250 getMethodToBench().getDeclaringClass().getDeclaredMethod(methodString.trim(), setUpParams);
251 if (isReflectedExecutable(method, AfterEachRun.class)) {
252 returnval.add(method);
253 } else {
254 throw new PerfidixMethodCheckException(new IllegalAccessException(new StringBuilder(
255 "AfterEachRun-annotated method ").append(method).append(" is not executable.")
256 .toString()), method, AfterEachRun.class);
257 }
258 }
259 return returnval.toArray(new Method[returnval.size()]);
260 } catch (SecurityException e) {
261 throw new PerfidixMethodCheckException(e, method, AfterEachRun.class);
262 } catch (NoSuchMethodException e) {
263 throw new PerfidixMethodCheckException(e, method, AfterEachRun.class);
264 }
265 } else {
266
267
268 Method meth =
269 findAndCheckAnyMethodByAnnotation(getMethodToBench().getDeclaringClass(), AfterEachRun.class);
270 if (meth == null) {
271 return new Method[0];
272 } else {
273 return new Method[] {
274 meth
275 };
276 }
277
278 }
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 public Method[] findAfterLastRun() throws PerfidixMethodCheckException {
298
299 Method method = null;
300
301 final Bench benchAnno = getMethodToBench().getAnnotation(Bench.class);
302 if (benchAnno != null && !benchAnno.afterLastRun().equals("")) {
303 List<Method> returnval = new ArrayList<Method>();
304 try {
305
306 final Class<?>[] setUpParams = {};
307
308 String[] methods = benchAnno.afterLastRun().split(",");
309 for (String methodString : methods) {
310
311 method =
312 getMethodToBench().getDeclaringClass().getDeclaredMethod(methodString.trim(), setUpParams);
313
314 if (isReflectedExecutable(method, AfterLastRun.class)) {
315 returnval.add(method);
316 } else {
317 throw new PerfidixMethodCheckException(new IllegalAccessException(new StringBuilder(
318 "AfterLastRun-annotated method ").append(method).append(" is not executable.")
319 .toString()), method, AfterLastRun.class);
320 }
321 }
322 return returnval.toArray(new Method[returnval.size()]);
323 } catch (final SecurityException e) {
324 throw new PerfidixMethodCheckException(e, method, AfterLastRun.class);
325 } catch (final NoSuchMethodException e) {
326 throw new PerfidixMethodCheckException(e, method, AfterLastRun.class);
327 }
328 } else {
329
330
331 Method meth =
332 findAndCheckAnyMethodByAnnotation(getMethodToBench().getDeclaringClass(), AfterLastRun.class);
333 if (meth == null) {
334 return new Method[0];
335 } else {
336 return new Method[] {
337 meth
338 };
339 }
340 }
341 }
342
343
344
345
346
347
348 public Method getMethodToBench() {
349 return methodToBench;
350 }
351
352
353
354
355
356
357
358
359
360
361
362 public static int getNumberOfAnnotatedRuns(final Method meth) {
363 if (!isBenchmarkable(meth)) {
364 throw new IllegalArgumentException(new StringBuilder("Method ").append(meth).append(
365 " must be a benchmarkable method.").toString());
366 }
367 final Bench benchAnno = meth.getAnnotation(Bench.class);
368 final BenchClass benchClassAnno = meth.getDeclaringClass().getAnnotation(BenchClass.class);
369 int returnVal;
370 if (benchAnno == null) {
371 returnVal = benchClassAnno.runs();
372 } else {
373 returnVal = benchAnno.runs();
374
375 if((returnVal == Bench.NONE_RUN) && (benchClassAnno != null)) {
376 returnVal = benchClassAnno.runs();
377 }
378 }
379 return returnVal;
380 }
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397 public static Method findAndCheckAnyMethodByAnnotation(final Class<?> clazz,
398 final Class<? extends Annotation> anno) throws PerfidixMethodCheckException {
399
400 Method anyMethod = null;
401
402
403 final Method[] possAnnoMethods = clazz.getDeclaredMethods();
404 for (final Method meth : possAnnoMethods) {
405 if (meth.getAnnotation(anno) != null) {
406
407
408 if (anyMethod == null) {
409
410
411 if (isReflectedExecutable(meth, anno)) {
412 anyMethod = meth;
413 } else {
414 throw new PerfidixMethodCheckException(new IllegalAccessException(new StringBuilder(
415 anno.toString()).append("-annotated method ").append(meth).append(
416 " is not executable.").toString()), meth, anno);
417 }
418 } else {
419 throw new PerfidixMethodCheckException(new IllegalAccessException(new StringBuilder(
420 "Please use only one ").append(anno.toString()).append("-annotation in one class.")
421 .toString()), meth, anno);
422 }
423 }
424 }
425
426 return anyMethod;
427 }
428
429
430
431
432
433
434
435
436
437
438 public static boolean isBenchmarkable(final Method meth) {
439 boolean returnVal = true;
440
441
442
443 final Bench benchAnno = meth.getAnnotation(Bench.class);
444
445
446
447 final SkipBench skipBenchAnno = meth.getAnnotation(SkipBench.class);
448 if (skipBenchAnno != null) {
449 returnVal = false;
450 }
451
452
453
454
455
456 final BeforeBenchClass beforeClass = meth.getAnnotation(BeforeBenchClass.class);
457 if (beforeClass != null && benchAnno == null) {
458 returnVal = false;
459 }
460
461 final BeforeFirstRun beforeFirstRun = meth.getAnnotation(BeforeFirstRun.class);
462 if (beforeFirstRun != null && benchAnno == null) {
463 returnVal = false;
464 }
465
466 final BeforeEachRun beforeEachRun = meth.getAnnotation(BeforeEachRun.class);
467 if (beforeEachRun != null && benchAnno == null) {
468 returnVal = false;
469 }
470
471 final AfterEachRun afterEachRun = meth.getAnnotation(AfterEachRun.class);
472 if (afterEachRun != null && benchAnno == null) {
473 returnVal = false;
474 }
475
476 final AfterLastRun afterLastRun = meth.getAnnotation(AfterLastRun.class);
477 if (afterLastRun != null && benchAnno == null) {
478 returnVal = false;
479 }
480
481 final AfterBenchClass afterClass = meth.getAnnotation(AfterBenchClass.class);
482 if (afterClass != null && benchAnno == null) {
483 returnVal = false;
484 }
485
486
487
488
489 final BenchClass classBenchAnno = meth.getDeclaringClass().getAnnotation(BenchClass.class);
490 if (benchAnno == null && classBenchAnno == null) {
491 returnVal = false;
492 }
493
494
495 if (!isReflectedExecutable(meth, Bench.class)) {
496 returnVal = false;
497 }
498 return returnVal;
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513 public static boolean isReflectedExecutable(final Method meth, final Class<? extends Annotation> anno) {
514 boolean returnVal = true;
515
516 if (meth.getGenericParameterTypes().length > 0) {
517 returnVal = false;
518 }
519
520 if (!(anno.equals(BeforeBenchClass.class)) && Modifier.isStatic(meth.getModifiers())) {
521 returnVal = false;
522 }
523
524 if (!Modifier.isPublic(meth.getModifiers())) {
525 returnVal = false;
526 }
527
528
529 if (!meth.getGenericReturnType().equals(Void.TYPE)) {
530 returnVal = false;
531 }
532
533 return returnVal;
534 }
535
536
537 @Override
538 public int hashCode() {
539 final int prime = 31;
540 int result = 1;
541 if (methodToBench == null) {
542 result = prime * result;
543 } else {
544 result = prime * result + methodToBench.hashCode();
545 }
546
547 return result;
548 }
549
550
551 @Override
552 public boolean equals(final Object obj) {
553 boolean returnVal = true;
554 if (this == obj) {
555 returnVal = true;
556 }
557 if (obj == null) {
558 returnVal = false;
559 }
560 if (getClass() != obj.getClass()) {
561 returnVal = false;
562 }
563 final BenchmarkMethod other = (BenchmarkMethod)obj;
564 if (methodToBench == null) {
565 if (other.methodToBench != null) {
566 returnVal = false;
567 }
568 } else {
569 if (!methodToBench.equals(other.methodToBench)) {
570 returnVal = false;
571
572 }
573 }
574 return returnVal;
575 }
576
577
578
579
580 @Override
581 public String toString() {
582 return new StringBuilder(methodToBench.getName()).toString();
583 }
584
585
586
587
588
589
590
591
592 public String getMethodWithClassName() {
593
594 return new StringBuilder(methodToBench.getDeclaringClass().getName() + "." + methodToBench.getName())
595 .toString();
596 }
597 }