1 /*
2 ContractChecker
3
4 Copyright (C) 2003 Jose San Leandro Armend?riz
5 jsanleandro@yahoo.es
6 chousz@yahoo.com
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public
10 License as published by the Free Software Foundation; either
11 version 2 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
17
18 You should have received a copy of the GNU General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
22 Thanks to ACM S.L. for distributing this library under the GPL license.
23 Contact info: jsr000@terra.es
24 Postal Address: c/Playa de Lagoa, 1
25 Urb. Valdecaba?as
26 Boadilla del monte
27 28660 Madrid
28 Spain
29
30 ******************************************************************************
31 *
32 * Filename: $RCSfile: ContractCheckerDoclet.java,v $
33 *
34 * Author: Jose San Leandro Armend?riz
35 *
36 * Description: QDox doclet for retrieving methods' pre- and post-conditions.
37 *
38 * Last modified by: $Author: chous $ at $Date: 2004/01/11 19:44:06 $
39 *
40 * File version: $Revision: 1.8 $
41 *
42 * Project version: $Name: $
43 *
44 * $Id: ContractCheckerDoclet.java,v 1.8 2004/01/11 19:44:06 chous Exp $
45 *
46 */
47 package org.acmsl.contractchecker;
48
49 /*
50 * Importing project-specific classes.
51 */
52 import org.acmsl.contractchecker.ContractCheckerAspectTemplate;
53 import org.acmsl.contractchecker.ContractCheckerAspectTemplateGenerator;
54 import org.acmsl.contractchecker.ContractCheckerException;
55
56 /*
57 * Importing Qdox classes.
58 */
59 import com.thoughtworks.qdox.ant.AbstractQdoxTask;
60 import com.thoughtworks.qdox.model.DocletTag;
61 import com.thoughtworks.qdox.model.JavaClass;
62 import com.thoughtworks.qdox.model.JavaMethod;
63 import com.thoughtworks.qdox.model.JavaSource;
64
65 /*
66 * Importing Ant classes.
67 */
68 import org.apache.tools.ant.BuildException;
69 import org.apache.tools.ant.types.FileSet;
70 import org.apache.tools.ant.types.Path;
71
72 /*
73 * Importing some JDK classes.
74 */
75 import java.io.IOException;
76 import java.io.File;
77 import java.util.ArrayList;
78 import java.util.Collection;
79 import java.util.Iterator;
80 import java.util.List;
81
82 /***
83 * QDox doclet for retrieving methods' pre- and post-conditions.
84 * @author <a href="mailto:jsanleandro@yahoo.es">Jose San Leandro</a>
85 * @version $Revision: 1.8 $
86 */
87 public class ContractCheckerDoclet
88 extends AbstractQdoxTask
89 {
90 /***
91 * The precondition tag.
92 */
93 public static final String PRECONDITION_TAG =
94 "precondition";
95
96 /***
97 * The default exception.
98 */
99 public static final String DEFAULT_VIOLATION_EXCEPTION =
100 ContractViolation.class.getName();
101
102 /***
103 * Cached empty javaclass array.
104 */
105 protected static final JavaClass[] EMPTY_JAVACLASS_ARRAY =
106 new JavaClass[0];
107
108 /***
109 * Cached empty javamethod array.
110 */
111 protected static final JavaMethod[] EMPTY_JAVAMETHOD_ARRAY =
112 new JavaMethod[0];
113
114 /***
115 * Cached empty contractcheckeraspecttemplate array.
116 */
117 protected static final ContractCheckerAspectTemplate[]
118 EMPTY_ASPECTTEMPLATE_ARRAY = new ContractCheckerAspectTemplate[0];
119
120 /***
121 * The output folder.
122 */
123 private File m__OutputFolder;
124
125 /***
126 * The aspectj template factory class.
127 */
128 private String m__strTemplateFactoryClass;
129
130 /***
131 * The input files.
132 */
133 private Path m__InputPath;
134
135 /***
136 * The contract violation exception.
137 */
138 private String m__strViolationException;
139
140 /***
141 * Specifies the output folder.
142 * @param folder the output folder.
143 */
144 public void setOutputfolder(File folder)
145 {
146 m__OutputFolder = folder;
147 }
148
149 /***
150 * Retrieves the output folder.
151 * @return such folder.
152 */
153 public File getOutputfolder()
154 {
155 return m__OutputFolder;
156 }
157
158 /***
159 * Specifies the template factory class.
160 * @param factoryClass the factory class.
161 */
162 public void setTemplatefactoryclass(String factoryClass)
163 {
164 m__strTemplateFactoryClass = factoryClass;
165 }
166
167 /***
168 * Retrieves the template factory class.
169 * @return such class.
170 */
171 public String getTemplatefactoryclass()
172 {
173 return m__strTemplateFactoryClass;
174 }
175
176 /***
177 * Specifies the input path.
178 * @param input the input.
179 */
180 public void setInput(Path input)
181 {
182 m__InputPath = input;
183 }
184
185 /***
186 * Retrieves the input path.
187 * @return such path.
188 */
189 public Path getInput()
190 {
191 return m__InputPath;
192 }
193
194 /***
195 * Specifies the contract violation exception.
196 * @param exception such exception.
197 */
198 public void setViolationexception(String exception)
199 {
200 m__strViolationException = exception;
201 }
202
203 /***
204 * Retrieves the contract violation exception.
205 * @return such exception.
206 */
207 public String getViolationexception()
208 {
209 return m__strViolationException;
210 }
211
212 /***
213 * Builds the file sets.
214 */
215 protected void buildFileSets()
216 {
217 ContractCheckerUtils t_Utils = ContractCheckerUtils.getInstance();
218
219 Path t_Input = getInput();
220
221 if ( (t_Utils != null)
222 && (t_Input != null))
223 {
224 FileSet[] t_aFileSets = t_Utils.toFileSets(t_Input);
225
226 if (t_aFileSets != null)
227 {
228 for (int t_iFileSetIndex = 0;
229 t_iFileSetIndex < t_aFileSets.length;
230 t_iFileSetIndex++)
231 {
232 addFileset(t_aFileSets[t_iFileSetIndex]);
233 }
234 }
235 }
236 }
237
238 /***
239 * Processes given sources.
240 * @param sources the source code to process.
241 */
242 protected void processSources(JavaSource[] sources)
243 {
244 if (sources != null)
245 {
246 for (int t_iSourceIndex = 0;
247 t_iSourceIndex < sources.length;
248 t_iSourceIndex++)
249 {
250 processSource(sources[t_iSourceIndex]);
251 }
252 }
253 }
254
255 /***
256 * Processes given source.
257 * @param source the source to process.
258 */
259 protected void processSource(JavaSource source)
260 {
261 if (source != null)
262 {
263 super.allSources.add(source);
264 JavaClass[] t_aClasses = source.getClasses();
265 processClasses(t_aClasses);
266 }
267 }
268
269 /***
270 * Processes given classes.
271 * @param classes the classes to process.
272 */
273 protected void processClasses(JavaClass[] classes)
274 {
275 if (classes != null)
276 {
277 for (int t_iClassIndex = 0;
278 t_iClassIndex < classes.length;
279 t_iClassIndex++)
280 {
281 processClass(classes[t_iClassIndex]);
282 }
283 }
284 }
285
286 /***
287 * Processes given class.
288 * @param javaClass the class to process.
289 */
290 protected void processClass(JavaClass javaClass)
291 {
292 if (javaClass != null)
293 {
294 super.allClasses.add(javaClass);
295 }
296 }
297
298 /***
299 * Tag information retrieval starting point.
300 * @throws BuildException if the source code cannot be processed.
301 */
302 public void execute()
303 throws BuildException
304 {
305 buildFileSets();
306
307 super.execute();
308
309 try
310 {
311 Collection t_cGuardedClasses =
312 findGuardedClasses(super.allClasses);
313
314 ContractCheckerAspectTemplateFactory t_Factory =
315 instantiateFactory(getTemplatefactoryclass());
316
317 String t_strViolationException = getViolationexception();
318
319 if (t_strViolationException == null)
320 {
321 t_strViolationException = DEFAULT_VIOLATION_EXCEPTION;
322 }
323
324 ContractCheckerAspectTemplate[] t_aTemplates =
325 buildTemplates(
326 t_cGuardedClasses, t_Factory, t_strViolationException);
327
328 writeTemplates(t_aTemplates, getOutputfolder());
329 }
330 catch (ContractCheckerException contractCheckerException)
331 {
332 throw
333 new BuildException(
334 "Cannot continue", contractCheckerException);
335 }
336 }
337
338 /***
339 * Creates the factory instance.
340 * @param className the factory class name.
341 * @return the factory instance.
342 * @throws ContractCheckerException if the factory cannot be
343 * instantiated.
344 */
345 protected ContractCheckerAspectTemplateFactory instantiateFactory(
346 String className)
347 throws ContractCheckerException
348 {
349 ContractCheckerAspectTemplateFactory result = null;
350
351 if (className != null)
352 {
353 try
354 {
355 Class t_Class = Class.forName(className);
356
357 if (t_Class != null)
358 {
359 Object t_Factory = t_Class.newInstance();
360
361 if ( (t_Factory != null)
362 && ( t_Factory
363 instanceof ContractCheckerAspectTemplateFactory))
364 {
365 result =
366 (ContractCheckerAspectTemplateFactory) t_Factory;
367 }
368 else
369 {
370 throw
371 new ContractCheckerException(
372 "invalid.template.factory.class");
373 }
374 }
375 }
376 catch (Exception exception)
377 {
378 throw
379 new ContractCheckerException(
380 "cannot.instantiate.template.factory",
381 exception);
382 }
383 }
384
385 if (result == null)
386 {
387 result = ContractCheckerAspectTemplateGenerator.getInstance();
388 }
389
390 return result;
391 }
392
393 /***
394 * Finds the guarded classes from given collection.
395 * @param classes the complete class set.
396 * @return the subset consisting only in guarded classes.
397 */
398 protected Collection findGuardedClasses(Collection classes)
399 {
400 Collection result = new ArrayList();
401
402 if (classes != null)
403 {
404 Iterator t_itClassIterator = classes.iterator();
405
406 if (t_itClassIterator != null)
407 {
408 while (t_itClassIterator.hasNext())
409 {
410 JavaClass t_CurrentClass =
411 (JavaClass) t_itClassIterator.next();
412
413 if (t_CurrentClass != null)
414 {
415 JavaMethod[] t_Methods =
416 findGuardedMethods(
417 t_CurrentClass.getMethods(), true);
418
419 if ( (t_Methods != null)
420 && (t_Methods.length > 0))
421 {
422 result.add(t_CurrentClass);
423 }
424 }
425 }
426 }
427 }
428
429 return result;
430 }
431
432 /***
433 * Finds the guarded method from given collection.
434 * @param methods the complete method set.
435 * @param stopOnFirst whether to stop on first guarded method.
436 * Therefore, if it's set to <code>true</code> the resulting
437 * array will contain 0 or 1 element.
438 * @return the subset consisting only in guarded methods.
439 */
440 protected static JavaMethod[] findGuardedMethods(
441 JavaMethod[] methods, boolean stopOnFirst)
442 {
443 Collection t_cResult = new ArrayList();
444
445 if (methods != null)
446 {
447 for (int t_iMethodIndex = 0;
448 t_iMethodIndex < methods.length;
449 t_iMethodIndex++)
450 {
451 JavaMethod t_CurrentMethod = methods[t_iMethodIndex];
452
453 if (t_CurrentMethod != null)
454 {
455 DocletTag[] t_Tags =
456 t_CurrentMethod.getTagsByName(
457 PRECONDITION_TAG);
458
459 if ( (t_Tags != null)
460 && (t_Tags.length > 0))
461 {
462 t_cResult.add(t_CurrentMethod);
463
464 if (stopOnFirst)
465 {
466 break;
467 }
468 }
469 }
470 }
471 }
472
473 return (JavaMethod[]) t_cResult.toArray(EMPTY_JAVAMETHOD_ARRAY);
474 }
475
476 /***
477 * Builds the templates for given classes.
478 * @param classes the classes.
479 * @param factory the template factory.
480 * @param defaultException the default exception.
481 * @return the associated contract-checker templates.
482 */
483 protected ContractCheckerAspectTemplate[] buildTemplates(
484 Collection classes,
485 ContractCheckerAspectTemplateFactory factory,
486 String defaultException)
487 {
488 List t_lResult = new ArrayList();
489
490 if (classes != null)
491 {
492 Iterator t_itClassIterator = classes.iterator();
493
494 if (t_itClassIterator != null)
495 {
496 JavaClass t_CurrentClass = null;
497
498 while (t_itClassIterator.hasNext())
499 {
500 t_CurrentClass =
501 (JavaClass) t_itClassIterator.next();
502
503 ContractCheckerAspectTemplate t_Template =
504 buildTemplate(
505 t_CurrentClass, factory, defaultException);
506
507 if (t_Template != null)
508 {
509 int t_iTemplatePosition =
510 t_lResult.indexOf(t_Template);
511
512 if (t_iTemplatePosition > -1)
513 {
514 t_Template =
515 (ContractCheckerAspectTemplate)
516 t_lResult.get(t_iTemplatePosition);
517 }
518 else
519 {
520 t_lResult.add(t_Template);
521 }
522
523 t_Template.addClass(t_CurrentClass);
524 }
525 }
526 }
527 }
528
529 return
530 (ContractCheckerAspectTemplate[])
531 t_lResult.toArray(EMPTY_ASPECTTEMPLATE_ARRAY);
532 }
533
534 /***
535 * Builds a ContractCheckerAspectTemplate from information provided
536 * by given class.
537 * @param javaClass the Java class.
538 * @param factory the template factory.
539 * @param defaultException the default exception.
540 * @return such kind of template.
541 */
542 protected ContractCheckerAspectTemplate buildTemplate(
543 JavaClass javaClass,
544 ContractCheckerAspectTemplateFactory factory,
545 String defaultException)
546 {
547 ContractCheckerAspectTemplate result = null;
548
549 if (javaClass != null)
550 {
551 // Inversion of control pattern.
552 result =
553 buildTemplate(
554 javaClass.getName(),
555 javaClass.getFullyQualifiedName(),
556 factory,
557 defaultException,
558 ContractCheckerUtils.getInstance());
559 }
560
561 return result;
562 }
563
564 /***
565 * Builds a ContractCheckerAspectTemplate from information provided
566 * by given class.
567 * @param name the Java class' name.
568 * @param qualifiedName the Java class' qualified name.
569 * @param factory the template factory.
570 * @param defaultException the default exception.
571 * @param contractCheckerUtils the helper instance.
572 * @return such kind of template.
573 */
574 protected ContractCheckerAspectTemplate buildTemplate(
575 String name,
576 String qualifiedName,
577 ContractCheckerAspectTemplateFactory factory,
578 String defaultException,
579 ContractCheckerUtils contractCheckerUtils)
580 {
581 ContractCheckerAspectTemplate result = null;
582
583 if ( (name != null)
584 && (qualifiedName != null)
585 && (factory != null)
586 && (defaultException != null)
587 && (contractCheckerUtils != null))
588 {
589 String t_strPackageName = name;
590
591 int t_iIndex =
592 qualifiedName.lastIndexOf(name) - 1;
593
594 if (t_iIndex > -1)
595 {
596 t_strPackageName =
597 qualifiedName.substring(0, t_iIndex);
598 }
599
600 result =
601 factory.createContractCheckerAspectTemplate(
602 contractCheckerUtils.retrieveAspectPackage(
603 t_strPackageName),
604 defaultException);
605 }
606
607 return result;
608 }
609
610 /***
611 * Writes given templates.
612 * @param templates the templates to write.
613 * @param outputFolder the output folder.
614 * @return <code>true</code> if the templates are written successfully.
615 * @throws ContractCheckerException if the template cannot be written for
616 * any reason.
617 */
618 protected boolean writeTemplates(
619 ContractCheckerAspectTemplate[] templates,
620 File outputFolder)
621 throws ContractCheckerException
622 {
623 boolean result = false;
624
625 if ( (templates != null)
626 && (outputFolder != null))
627 {
628 try
629 {
630 ContractCheckerAspectTemplateGenerator t_Generator =
631 ContractCheckerAspectTemplateGenerator.getInstance();
632
633 if (t_Generator != null)
634 {
635 for (int t_iTemplateIndex = 0;
636 t_iTemplateIndex < templates.length;
637 t_iTemplateIndex++)
638 {
639 t_Generator.write(
640 templates[t_iTemplateIndex],
641 outputFolder);
642 }
643
644 result = true;
645 }
646 }
647 catch (IOException ioException)
648 {
649 throw
650 new ContractCheckerException(
651 "Cannot write the templates", ioException);
652 }
653 }
654
655 return result;
656 }
657 }
This page was automatically generated by Maven