1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package eteg.sinon.dao.xml;
24
25 import eteg.sinon.core.Action;
26 import eteg.sinon.core.Catalog;
27 import eteg.sinon.core.Collector;
28 import eteg.sinon.core.CollectorConfiguration;
29 import eteg.sinon.core.DataExtraction;
30 import eteg.sinon.core.LoopStep;
31 import eteg.sinon.core.Page;
32 import eteg.sinon.core.PageConfiguration;
33 import eteg.sinon.core.PageStorageConfiguration;
34 import eteg.sinon.core.Parameter;
35 import eteg.sinon.core.ParameterSet;
36 import eteg.sinon.core.PositioningStep;
37 import eteg.sinon.core.StartPage;
38 import eteg.sinon.core.Step;
39 import eteg.sinon.dao.CollectorDAO;
40 import eteg.sinon.exception.SinonException;
41 import org.jdom.CDATA;
42 import org.jdom.Content;
43 import org.jdom.Document;
44 import org.jdom.Element;
45 import org.jdom.JDOMException;
46 import org.jdom.Text;
47 import org.jdom.input.SAXBuilder;
48 import org.jdom.output.Format;
49 import org.jdom.output.XMLOutputter;
50
51 import java.io.File;
52 import java.io.FileOutputStream;
53 import java.io.IOException;
54 import java.io.FileFilter;
55 import java.util.*;
56
57 /***
58 * Implementation of {@link CollectorDAO} that read and write instances of
59 * {@link Collector} in XML files. These files must have <code>.xml</code>
60 * suffix. Files are written and read from the directory passed to
61 * {@link XMLCollectorDAO#XMLCollectorDAO}.
62 *
63 * @author <a href="mailto:thiagohp at users.sourceforge.net">Thiago H. de Paula Figueiredo</a>
64 * @author Last modified by $Author: thiagohp $
65 * @version $Revision: 1.2 $
66 * @todo improve implementation to write files exactly as they were read.
67 */
68 public class XMLCollectorDAO implements CollectorDAO {
69
70 /***
71 * Sufixo que todos os arquivox XML descrevendo coletores devem usar.
72 */
73 public static final String COLLECTOR_SUFFIX = ".xml";
74
75 final private static XMLFileFilter XML_FILE_FILTER = new XMLFileFilter();
76
77 final private static String ID_ATTRIBUTE = "id";
78 final private static String CONFIG_TAG = "config";
79 final private static String CATALOG_TAG = "catalog";
80 final private static String GLOBAL_DATA_EXTRACTIONS_TAG =
81 "global-data-extractions";
82 final private static String DATA_EXTRACTION_TAG = "data-extraction";
83 final private static String DATA_EXTRACTIONS_TAG = "data-extractions";
84 final private static String TRIM_ATTRIBUTE = "trim";
85 final private static String DIRECTION_ATTRIBUTE = "direction";
86 final private static String START_PAGES_TAG = "start-pages";
87 final private static String REFID_ATTRIBUTE = "refid";
88 final private static String PROPERTY_TAG = "property";
89 final private static String NAME_ATTRIBUTE = "name";
90 final private static String VALUE_ATTRIBUTE = "value";
91 final private static String PAGE_TAG = "page";
92 final private static String FOLLOW_REDIRECT_ATTRIBUTE = "follow-redirect";
93 final private static String URL_ATTRIBUTE = "url";
94 final private static String PAGE_CONFIG_TAG = "page-config";
95 final private static String PARAMETER_SET_TAG = "parameter-set";
96 final private static String INCLUDE_PARAMETER_SET_TAG =
97 "include-parameter-set";
98 final private static String PARAMETER_TAG = "parameter";
99 final private static String HEADERS_TAG = "headers";
100 final private static String HEADER_TAG = "header";
101 final private static String THINK_TIME_TAG = "thinkTime";
102 final private static String CLASS_ATTRIBUTE = "class";
103 final private static String COLLECTOR_TAG = "collector";
104 final private static String DO_DATA_EXTRACTION_TAG = "do-data-extraction";
105 final private static String RESET_POSITION_ATTRIBUTE = "resetPosition";
106 final private static String LOOP_TAG = "loop";
107 final private static String LIST_ATTRIBUTE = "list";
108 final private static String CONDITION_ATTRIBUTE = "condition";
109
110 final private static String ACTION_TAG = "action";
111 final private static String PAGE_ID_ATTRIBUTE = "pageId";
112 final private static String FOREACH_ATTRIBUTE = "foreach";
113 final private static String VARIABLE_ATTRIBUTE = "variable";
114 final private static String INDEX_ATTRIBUTE = "index";
115 final private static String PROPERTY_ID_ATTRIBUTE = "propertyId";
116 final private static String PAGE_LISTENERS_TAG = "listeners";
117 final private static String ON_ERROR_TAG = "on-error";
118 final private static String ON_STATE_CHANGE_TAG = "on-state-change";
119 final private static String ON_PROMPT_TAG = "on-prompt";
120 final private static String METHOD_ATTRIBUTE = "method";
121 final private static String START_PAGE_TAG = "start-page";
122 final private static String TIMEOUT_TAG = "timeout";
123 final private static String RETRIES_TAG = "retries";
124 final private static String SAVE_TAG = "save";
125 final private static String FILE_ATTRIBUTE = "file";
126 final private static String FAIL_ON_ERROR_ATTRIBUTE = "failOnError";
127 final private static String VALUE_ON_ERROR_ATTRIBUTE = "valueOnError";
128 final private static String NEWLINE_TAG = "newline";
129 final private static String ALLOW_DUPLICATES_ATTRIBUTE =
130 "allowDuplicates";
131 final private static String ON_CATALOG_STATE_CHANGE_TAG =
132 "on-catalog-state-change";
133 final private static String PROPERTIES_TAG = "properties";
134 final private static String BEFORE_ATTRIBUTE = "before";
135 final private static String ENCODING_ATTRIBUTE = "encoding";
136 final private static String FAIL_IF_FOUND_ATTRIBUTE = "failIfFound";
137 final private static String BACKWARDS_ATTRIBUTE = "backwards";
138
139 /***
140 * Collector directory used when no one is specified. Value:
141 * <code>collectors</code>.
142 */
143 final public static String DEFAULT_COLLECTOR_DIRECTORY = "collectors";
144
145 private Catalog currentCatalog;
146
147 /***
148 * Directory where the XML configuration files are stored.
149 */
150 private File collectorDirectory;
151
152 /***
153 * Constructor that receives a <code>File</code> pointing to the
154 * configurations file directory.
155 *
156 * @param collectorDirectory a <code>java.io.File</code>.
157 * @throws IllegalArgumentException if <code>collectorDirectory</code> is
158 * <code>null</code>.
159 */
160 public XMLCollectorDAO(File collectorDirectory) {
161
162 if (collectorDirectory == null) {
163
164 throw new IllegalArgumentException(
165 "Parameter collectorDirectory cannot be null.");
166
167 }
168
169 this.collectorDirectory = collectorDirectory;
170
171 }
172
173 /***
174 * No-arg constructor. The collectors file directory is the current one.
175 */
176 public XMLCollectorDAO() {
177 this(new File(DEFAULT_COLLECTOR_DIRECTORY));
178 }
179
180 /***
181 * Returns the collectors file directory.
182 *
183 * @return a <code>File</code>.
184 */
185 public File getCollectorDirectory() {
186 return collectorDirectory;
187 }
188
189 /***
190 * Writes <code>collector</code> in
191 * <code>collectorDirectory + "/" + collector.getId() + ".xml"</code>.
192 *
193 * @param collector a {@link Collector} instance.
194 * @throws SinonException if some error ocurrs.
195 */
196 public void store(Collector collector) throws SinonException {
197
198 final File destination =
199 new File(collectorDirectory + "/" + collector.getId() + ".xml");
200
201 store(collector, destination);
202
203 }
204
205 /***
206 * Writes <code>collector</code> in a given <code>destination</code>
207 * directory.
208 *
209 * @param collector a {@link Collector} instance.
210 * @param destination a <code>java.util.File</code>.
211 * @throws SinonException if some error ocurrs.
212 */
213 public void store(Collector collector, File destination)
214 throws SinonException {
215
216 Format format = getXMLFormat();
217
218 XMLOutputter outputter = new XMLOutputter(format);
219
220 FileOutputStream outputStream = null;
221 Element rootElement = createRootElement(collector);
222 Document document = new Document(rootElement);
223
224 try {
225
226 outputStream = new FileOutputStream(destination);
227 outputter.output(document, outputStream);
228
229 } catch (IOException e) {
230
231 throw new SinonException("Problemas ao salvar o arquivo " +
232 destination.getAbsolutePath(), null);
233
234 }
235
236 }
237
238 /***
239 * Returns all available collectors.
240 *
241 * @return a <code>java.util.List</code>.
242 * @throws Exception if some error ocurrs.
243 */
244 public List findAll() throws Exception {
245
246 File[] files = collectorDirectory.listFiles(XML_FILE_FILTER);
247 ArrayList collectors = new ArrayList();
248
249 for (int i = 0; i < files.length; i++) {
250
251 String name = files[i].getName();
252 name = name.substring(0, name.length() - COLLECTOR_SUFFIX.length());
253 collectors.add(load(name));
254
255 }
256
257 return collectors;
258
259 }
260
261 private Format getXMLFormat() {
262
263 Format format = Format.getPrettyFormat();
264 format.setEncoding("ISO-8859-1");
265 format.setIndent(" ");
266 format.setLineSeparator("\n");
267 format.setExpandEmptyElements(false);
268 format.setTextMode(Format.TextMode.PRESERVE);
269
270 return format;
271
272 }
273
274 private Element createRootElement(Collector collector) {
275
276 Element element = new Element(COLLECTOR_TAG);
277 element.setAttribute(ID_ATTRIBUTE, collector.getId());
278
279 element.addContent(createConfigElement(collector));
280
281 if (collector.getCatalogStateListenerClassName() != null) {
282 element.addContent(createOnCatalogStateChangeElement(collector));
283 }
284
285 Catalog[] catalogs = collector.getCatalogs();
286
287 for (int i = 0; i < catalogs.length; i++) {
288 element.addContent(createCatalogElement(catalogs[i]));
289 }
290
291 return element;
292
293 }
294
295 private Content createCatalogElement(Catalog catalog) {
296
297 Element element = new Element(CATALOG_TAG);
298 element.setAttribute(ID_ATTRIBUTE, catalog.getId());
299
300 element.addContent(createPropertiesElement(catalog.getProperties()));
301
302 element.addContent(createStartPageElement(catalog.getStartPages()));
303
304 ParameterSet[] parameterSets = catalog.getParameterSets();
305
306 for (int i = 0; i < parameterSets.length; i++) {
307 element.addContent(createParameterSetElement(parameterSets[i]));
308 }
309
310 DataExtraction[] globalDataExtractions = catalog.getDataExtractions();
311 element.addContent(createlDataExtractionElement(
312 GLOBAL_DATA_EXTRACTIONS_TAG, globalDataExtractions));
313
314 Page[] pages = catalog.getPages();
315
316 for (int i = 0; i < pages.length; i++) {
317 element.addContent(createPageElement(pages[i]));
318 }
319
320 return element;
321
322 }
323
324 private Element createPageElement(Page page) {
325
326 Element element = new Element(PAGE_TAG);
327 element.setAttribute(ID_ATTRIBUTE, page.getId());
328 element.setAttribute(URL_ATTRIBUTE, page.getUrl());
329
330 if (page.getFollowRedirects() == false) {
331 element.setAttribute(FOLLOW_REDIRECT_ATTRIBUTE,
332 String.valueOf(page.getFollowRedirects()));
333 }
334
335 String method = page.getMethod() == Page.POST_METHOD ? "post" : "get";
336 element.setAttribute(METHOD_ATTRIBUTE, method);
337
338 PageConfiguration configuration = page.getConfiguration();
339
340 if (configuration != null) {
341 element.addContent(createPageConfigurationElement(configuration));
342 }
343
344 PageStorageConfiguration storageConfiguration =
345 page.getStorageConfiguration();
346
347 if (storageConfiguration.getFilename() != null) {
348 element.addContent(createPageStorageConfigurationElement(
349 storageConfiguration));
350 }
351
352 Element dataExtractions = new Element(DATA_EXTRACTIONS_TAG);
353 Step[] steps = page.getSteps();
354
355 for (int i = 0; i < steps.length; i++) {
356 dataExtractions.addContent(createStepElement(steps[i]));
357 }
358
359 element.addContent(createPageStateListenerElement(page));
360
361 element.addContent(dataExtractions);
362
363 Action[] actions = page.getActions();
364
365 for (int i = 0; i < actions.length; i++) {
366 element.addContent(createActionElement(actions[i]));
367 }
368
369 return element;
370
371 }
372
373 private Element createPageStateListenerElement(Page page) {
374
375 Element element = new Element(PAGE_LISTENERS_TAG);
376
377 String stateListener = page.getPageStateListenerClassName();
378 String promptListener = page.getPromptListenerClassName();
379 String errorListener = page.getErrorListenerClassName();
380
381 if (stateListener != null) {
382
383 Element stateTag = new Element(ON_STATE_CHANGE_TAG);
384 stateTag.setAttribute(CLASS_ATTRIBUTE, stateListener);
385 element.addContent(stateTag);
386
387 }
388
389 if (promptListener != null) {
390
391 Element promptTag = new Element(ON_PROMPT_TAG);
392 promptTag.setAttribute(CLASS_ATTRIBUTE, promptListener);
393 element.addContent(promptTag);
394
395 }
396
397 if (errorListener != null) {
398
399 Element errorTag = new Element(ON_ERROR_TAG);
400 errorTag.setAttribute(CLASS_ATTRIBUTE, errorListener);
401 element.addContent(errorTag);
402
403 }
404
405 return element;
406
407 }
408
409 private Element createActionElement(Action action) {
410
411 Element element = new Element(ACTION_TAG);
412 element.setAttribute(PAGE_ID_ATTRIBUTE, action.getPageId());
413
414 if (action.getUrl() != null) {
415 element.setAttribute(URL_ATTRIBUTE, action.getUrl());
416 }
417
418 if (action.getForeach() != null) {
419
420 element.setAttribute(FOREACH_ATTRIBUTE, action.getForeach());
421 element.setAttribute(VARIABLE_ATTRIBUTE, action.getVariable());
422
423 if (action.getIndex() != null) {
424 element.setAttribute(INDEX_ATTRIBUTE, action.getIndex());
425 }
426
427 }
428
429 if (action.getCondition() != null) {
430
431 element.setAttribute(CONDITION_ATTRIBUTE, action.getCondition());
432 element.setAttribute(PROPERTY_ID_ATTRIBUTE, action.getPropertyId());
433
434 }
435
436 final PageConfiguration configuration = action.getConfiguration();
437
438 if (configuration != null) {
439 element.addContent(createPageConfigurationElement(configuration));
440 }
441
442 return element;
443
444 }
445
446 private Element createPageStorageConfigurationElement(
447 PageStorageConfiguration configuration) {
448
449 Element element = new Element(SAVE_TAG);
450 element.setAttribute(FILE_ATTRIBUTE, configuration.getFilename());
451
452 return element;
453
454 }
455
456 private Element createPageConfigurationElement(
457 PageConfiguration configuration) {
458
459 Element element = new Element(PAGE_CONFIG_TAG);
460 element.addContent(createParameterSetElement(
461 configuration.getParameterSet()));
462
463 return element;
464
465 }
466
467 private Element createlDataExtractionElement(
468 String tagName, DataExtraction[] dataExtractions) {
469
470 Element element = new Element(tagName);
471
472 for (int i = 0; i < dataExtractions.length; i++) {
473 element.addContent(createDataExtractionElement(dataExtractions[i]));
474 }
475
476 return element;
477
478 }
479
480 private Element createStepElement(Step step) {
481
482 if (step.isDataExtraction()) {
483 return createDataExtractionElement((DataExtraction) step);
484 } else if (step.isPositioningStep()) {
485 return createPositioningStepElement((PositioningStep) step);
486 } else if (step.isLoop()) {
487 return createLoopElement((LoopStep) step);
488 } else if (step.isAction()) {
489 return new Element("actionXMLTagNotImplementedYet");
490 } else {
491 throw new RuntimeException("Unknown extraction step type.");
492 }
493
494 }
495
496 private Element createLoopElement(LoopStep loop) {
497
498 Element element = new Element(LOOP_TAG);
499 element.setAttribute(CONDITION_ATTRIBUTE, loop.getCondition());
500
501 if (loop.getValue() != null) {
502 element.setAttribute(VALUE_ATTRIBUTE, loop.getValue());
503 }
504
505 Step[] steps = loop.getSteps();
506
507 for (int i = 0; i < steps.length; i++) {
508 element.addContent(createStepElement(steps[i]));
509 }
510
511 return element;
512
513 }
514
515 /***
516 * @param step
517 * @return
518 */
519 private Element createPositioningStepElement(PositioningStep step) {
520
521 Element element = new Element(step.getType());
522
523 if (step.getBefore() != null) {
524 element.setAttribute(BEFORE_ATTRIBUTE, step.getBefore());
525 }
526
527 if (step.getDirection() == PositioningStep.BACKWARD) {
528 element.setAttribute(DIRECTION_ATTRIBUTE, BACKWARDS_ATTRIBUTE);
529 }
530
531 if (step.isMustTrimReference() == false) {
532 element.setAttribute(TRIM_ATTRIBUTE,
533 String.valueOf(step.isMustTrimReference()));
534 }
535
536 if (step.isFailIfFound() == true) {
537 element.setAttribute(FAIL_IF_FOUND_ATTRIBUTE,
538 String.valueOf(step.isFailIfFound()));
539 }
540
541 element.addContent(new CDATA(step.getReference()));
542
543 return element;
544
545 }
546
547 private Element createDataExtractionElement(DataExtraction dataExtraction) {
548
549 Element element = new Element(DATA_EXTRACTION_TAG);
550 element.setAttribute(ID_ATTRIBUTE, dataExtraction.getId());
551 element.setAttribute(TRIM_ATTRIBUTE,
552 String.valueOf(dataExtraction.isTrimValueNeeded()));
553 element.setAttribute(LIST_ATTRIBUTE,
554 String.valueOf(dataExtraction.isMultivalued()));
555
556 if (dataExtraction.isMultivalued()) {
557 element.setAttribute(ALLOW_DUPLICATES_ATTRIBUTE,
558 String.valueOf(dataExtraction.isAllowDuplicates()));
559 }
560
561 if (dataExtraction.isResetPositionNeeded()) {
562 element.setAttribute(RESET_POSITION_ATTRIBUTE,
563 String.valueOf(dataExtraction.isResetPositionNeeded()));
564 }
565
566 if (dataExtraction.isFailOnError() == false) {
567
568 element.setAttribute(FAIL_ON_ERROR_ATTRIBUTE,
569 String.valueOf(dataExtraction.isFailOnError()));
570
571 element.setAttribute(VALUE_ON_ERROR_ATTRIBUTE,
572 dataExtraction.getValueOnError());
573
574 }
575
576 Step[] steps = dataExtraction.getSteps();
577
578 for (int i = 0; i < steps.length; i++) {
579 element.addContent(createStepElement(steps[i]));
580 }
581
582 return element;
583
584 }
585
586 private Content createStartPageElement(StartPage[] startPages) {
587
588 Element element = new Element(START_PAGES_TAG);
589
590 for (int i = 0; i < startPages.length; i++) {
591
592 StartPage startPage = startPages[i];
593
594 Element startPageElement = new Element(START_PAGE_TAG);
595 startPageElement.setAttribute(
596 REFID_ATTRIBUTE, startPage.getRefid());
597
598 Properties properties = startPage.getProperties();
599
600 Enumeration enumeration = properties.keys();
601
602 while (enumeration.hasMoreElements()) {
603
604 String name = (String) enumeration.nextElement();
605 String value = properties.getProperty(name);
606
607 Element property = new Element(PROPERTY_TAG);
608 property.setAttribute(NAME_ATTRIBUTE, name);
609 property.setAttribute(VALUE_ATTRIBUTE, value);
610
611 startPageElement.addContent(property);
612
613 }
614
615 element.addContent(startPageElement);
616
617 }
618
619 return element;
620
621 }
622
623 private Content createParameterSetElement(ParameterSet parameterSet) {
624
625 Element element = new Element(PARAMETER_SET_TAG);
626
627 if (parameterSet.getId() != null) {
628 element.setAttribute(ID_ATTRIBUTE, parameterSet.getId());
629 }
630
631 Map map = parameterSet.getParameters();
632
633 Iterator iterator = map.keySet().iterator();
634
635 while (iterator.hasNext()) {
636
637 String name = (String) iterator.next();
638 Parameter value = (Parameter) map.get(name);
639
640 Element parameter = new Element(PARAMETER_TAG);
641 parameter.setAttribute(NAME_ATTRIBUTE, name);
642 parameter.setAttribute(VALUE_ATTRIBUTE, value.getValue());
643
644 element.addContent(parameter);
645
646 }
647
648 return element;
649
650 }
651
652 private Element createPropertiesElement(Properties properties) {
653
654 Element element = new Element(PROPERTIES_TAG);
655
656 Enumeration enumeration = properties.keys();
657
658 while (enumeration.hasMoreElements()) {
659
660 String name = (String) enumeration.nextElement();
661 String value = properties.getProperty(name);
662
663 Element property = new Element(PROPERTY_TAG);
664 property.setAttribute(NAME_ATTRIBUTE, name);
665 property.setAttribute(VALUE_ATTRIBUTE, value);
666
667 element.addContent(property);
668
669 }
670
671 return element;
672
673 }
674
675 private Element createOnCatalogStateChangeElement(Collector collector) {
676
677 Element element = new Element(ON_CATALOG_STATE_CHANGE_TAG);
678 element.setAttribute(CLASS_ATTRIBUTE,
679 collector.getCatalogStateListenerClassName());
680
681 return element;
682
683
684 }
685
686 private Content createConfigElement(Collector collector) {
687
688 Element element = new Element(CONFIG_TAG);
689 CollectorConfiguration configuration = collector.getConfiguration();
690
691 element.addContent(createHeadersTag(configuration));
692 element.addContent(createThinkTimeTag(configuration));
693 element.addContent(createTimeoutTag(configuration));
694 element.addContent(createRetriesTag(configuration));
695
696 return element;
697
698 }
699
700 private Content createRetriesTag(CollectorConfiguration configuration) {
701
702 Element element = new Element(RETRIES_TAG);
703 element.setAttribute(VALUE_ATTRIBUTE,
704 String.valueOf(configuration.getRetries()));
705
706 return element;
707
708 }
709
710 private Content createTimeoutTag(CollectorConfiguration configuration) {
711
712 Element element = new Element(TIMEOUT_TAG);
713 element.setAttribute(VALUE_ATTRIBUTE,
714 String.valueOf(configuration.getTimeout()));
715
716 return element;
717
718 }
719
720 private Content createThinkTimeTag(CollectorConfiguration configuration) {
721
722 Element element = new Element(THINK_TIME_TAG);
723 element.setAttribute(CLASS_ATTRIBUTE,
724 configuration.getThinkTimeImplementationClassName());
725
726 Properties properties = configuration.getThinkTimeProperties();
727
728 Enumeration enumeration = properties.keys();
729
730 while (enumeration.hasMoreElements()) {
731
732 String name = (String) enumeration.nextElement();
733 String value = properties.getProperty(name);
734
735 Element property = new Element(PROPERTY_TAG);
736 property.setAttribute(NAME_ATTRIBUTE, name);
737 property.setAttribute(VALUE_ATTRIBUTE, value);
738
739 element.addContent(property);
740
741 }
742
743 return element;
744
745 }
746
747 private Content createHeadersTag(CollectorConfiguration configuration) {
748
749 Element element = new Element(HEADERS_TAG);
750
751 final Properties headers = configuration.getHttpHeaders();
752
753 Enumeration keys = headers.keys();
754
755 while (keys.hasMoreElements()) {
756
757 String name = (String) keys.nextElement();
758 String value = headers.getProperty(name);
759
760 Element header = new Element(HEADER_TAG);
761 header.setAttribute(NAME_ATTRIBUTE, name);
762 header.setAttribute(VALUE_ATTRIBUTE, value);
763
764 element.addContent(header);
765
766 }
767
768 return element;
769
770 }
771
772 /***
773 * Loads the collector which id is <code>id</code>.
774 *
775 * @param id a <code>String</code> containing the collector id.
776 * @return a {@link Collector} instance.
777 * @throws SinonException if some error ocurrs.
778 */
779 public Collector load(String id) throws SinonException {
780
781 File file = new File(collectorDirectory, id + ".xml");
782 Collector collector = null;
783
784 if (file.exists() == false) {
785
786 throw new SinonException("There is no collector named " + id +
787 ".xml in directory " + collectorDirectory);
788
789 }
790
791 if (file.canRead() == false) {
792
793 throw new SinonException("You do not have access to file " + id +
794 ".xml in directory " + collectorDirectory);
795
796 }
797
798 try {
799 collector = processCollectorXMLFile(file, id);
800 } catch (SinonException e) {
801 throw e;
802 } catch (Exception e) {
803 throw new SinonException(e);
804 }
805
806 return collector;
807
808 }
809
810 /***
811 * Reads a collector from an XML file.
812 *
813 * @param file a <code>File</code> pointing to the XML file.
814 * @param id a <code>String</code> containing the collector id.
815 * @return a {@link Collector} instance.
816 */
817 private Collector processCollectorXMLFile(File file, String id)
818 throws SinonException, JDOMException, IOException {
819
820 SAXBuilder builder = new SAXBuilder();
821
822 Document doc = builder.build(file);
823
824 Element collectorTag = doc.getRootElement();
825
826 if (collectorTag.getName().equals(COLLECTOR_TAG) == false) {
827
828 throw new SinonException("Every Sinon configuration XML file " +
829 "must have a " + COLLECTOR_TAG + " as root element");
830
831 }
832
833 return parseCollector(collectorTag, id);
834
835 }
836
837 private Collector parseCollector(Element collectorTag, String id)
838 throws SinonException {
839
840 Collector collector = new Collector();
841
842 String thisId = collectorTag.getAttributeValue(ID_ATTRIBUTE);
843
844 if (thisId == null || thisId.trim().length() == 0) {
845
846 throw new SinonException("Tag " + COLLECTOR_TAG + " must have " +
847 "an " + ID_ATTRIBUTE + " attribute whose value is not " +
848 "comprised of white space.");
849
850 }
851
852 thisId = thisId.trim();
853
854 if (thisId.equals(id) == false) {
855
856 throw new SinonException("The value of attribute " + ID_ATTRIBUTE +
857 " (tag " + COLLECTOR_TAG + ") in file " +
858 id + COLLECTOR_SUFFIX + " must be " + id + " instead of " +
859 thisId);
860
861 }
862
863 collector.setId(thisId);
864
865 Element configTag = collectorTag.getChild(CONFIG_TAG);
866
867 collector.setConfiguration(parseCollectorConfiguration(configTag));
868
869 Element element = collectorTag.getChild(ON_CATALOG_STATE_CHANGE_TAG);
870
871 if (element != null) {
872
873 final String className = element.getAttributeValue(CLASS_ATTRIBUTE);
874 collector.setCatalogStateListenerClassName(className);
875
876 }
877
878 addCatalogs(collectorTag, collector);
879
880 return collector;
881
882 }
883
884 private void addCatalogs(Element collectorTag, Collector collector)
885 throws SinonException {
886
887 List catalogTags = collectorTag.getChildren(CATALOG_TAG);
888
889 for (int i = 0; i < catalogTags.size(); i++) {
890
891 Element catalogTag = (Element) catalogTags.get(i);
892 collector.addCatalog(parseCatalog(catalogTag));
893
894 }
895
896 }
897
898 private Catalog parseCatalog(Element catalogTag) throws SinonException {
899
900 Catalog catalog = new Catalog();
901
902 currentCatalog = catalog;
903
904 String id = catalogTag.getAttributeValue(ID_ATTRIBUTE);
905
906 if (id == null) {
907
908 throw new SinonException("Tag " + CATALOG_TAG + " must have an " +
909 ID_ATTRIBUTE + " attribute.");
910
911 }
912
913 id = id.trim();
914
915 if (id.length() == 0) {
916
917 throw new SinonException("Attribute " + ID_ATTRIBUTE +
918 " (tag " + CATALOG_TAG + ") cannot " +
919 "be empty or comprised of only white space.");
920
921 }
922
923 catalog.setId(id);
924
925 addParameterSets(catalogTag, catalog);
926
927 addDataExtractions(catalogTag, catalog);
928
929 addPages(catalogTag, catalog);
930
931 addStartPages(catalogTag, catalog);
932
933 Element propertiesTag = catalogTag.getChild(PROPERTIES_TAG);
934
935 if (propertiesTag != null) {
936
937 List propertyTags = propertiesTag.getChildren(PROPERTY_TAG);
938
939 final int size = propertyTags.size();
940 Element element;
941 Properties properties = catalog.getProperties();
942
943 for (int i = 0; i < size; i++) {
944
945 element = (Element) propertyTags.get(i);
946 String name = element.getAttributeValue(NAME_ATTRIBUTE);
947 String value = element.getAttributeValue(VALUE_ATTRIBUTE);
948
949 if (name == null || value == null) {
950
951 throw new SinonException("Every property tag must have " +
952 "a " + NAME_ATTRIBUTE + " and a " +
953 VALUE_ATTRIBUTE + " attributes.");
954
955 }
956
957 name = name.trim();
958
959 if (name.length() == 0) {
960
961 throw new SinonException("Attribute " + NAME_ATTRIBUTE +
962 " cannot be empty or comprised of only white " +
963 "space");
964
965 }
966
967 properties.setProperty(name, value);
968
969 }
970
971
972 }
973
974 return catalog;
975
976 }
977
978 private void addDataExtractions(Element catalogTag, Catalog catalog)
979 throws SinonException {
980
981 Element globalDataExtractionsTag =
982 catalogTag.getChild(GLOBAL_DATA_EXTRACTIONS_TAG);
983
984 if (globalDataExtractionsTag == null) {
985 return;
986 }
987
988 List dataExtractions =
989 getGlobalDataExtractions(globalDataExtractionsTag);
990
991 for (int i = 0; i < dataExtractions.size(); i++) {
992
993 DataExtraction dataExtraction =
994 (DataExtraction) dataExtractions.get(i);
995
996 catalog.addDataExtraction(dataExtraction);
997
998 }
999
1000 }
1001
1002 private List getGlobalDataExtractions(Element element)
1003 throws SinonException {
1004
1005 ArrayList dataExtractions = new ArrayList();
1006
1007 List dataExtractionTags = element.getChildren(DATA_EXTRACTION_TAG);
1008
1009 for (int i = 0; i < dataExtractionTags.size(); i++) {
1010
1011 Element dataExtractionTag = (Element) dataExtractionTags.get(i);
1012 DataExtraction dataExtraction;
1013
1014 dataExtraction = getDataExtraction(dataExtractionTag);
1015
1016 dataExtractions.add(dataExtraction);
1017
1018 }
1019
1020 return dataExtractions;
1021
1022 }
1023
1024 private List getSteps(Element element) throws SinonException {
1025
1026
1027
1028 ArrayList steps = new ArrayList();
1029
1030 List stepTags = element.getChildren();
1031
1032 for (int i = 0; i < stepTags.size(); i++) {
1033
1034 Element dataExtractionTag = (Element) stepTags.get(i);
1035 String type = dataExtractionTag.getName();
1036 DataExtraction dataExtraction = null;
1037
1038 if (type.equals(DATA_EXTRACTION_TAG)) {
1039
1040 dataExtraction = getDataExtraction(dataExtractionTag);
1041
1042 } else if (type.equals(DO_DATA_EXTRACTION_TAG)) {
1043
1044 dataExtraction = getDoDataExtraction(dataExtractionTag);
1045
1046 } else if (type.equals(LOOP_TAG)) {
1047
1048 LoopStep loopStep = getLoopStep(dataExtractionTag);
1049 steps.add(loopStep);
1050
1051 continue;
1052
1053 } else if (type.equals(ACTION_TAG)) {
1054
1055 throw new SinonException("The action tag cannot be put " +
1056 "inside a data extraction or loop.");
1057
1058 } else {
1059
1060 PositioningStep step = getPositioningStep(dataExtractionTag);
1061 steps.add(step);
1062
1063 continue;
1064
1065 }
1066
1067 String resetPosition = dataExtractionTag.getAttributeValue(
1068 RESET_POSITION_ATTRIBUTE);
1069
1070 if (resetPosition != null) {
1071
1072 Boolean mustResetPosition = Boolean.valueOf(resetPosition);
1073 dataExtraction.setResetPositionNeeded(
1074 mustResetPosition.booleanValue());
1075
1076 }
1077
1078 steps.add(dataExtraction);
1079
1080 }
1081
1082 return steps;
1083
1084 }
1085
1086 private Action getAction(Element element) throws SinonException {
1087
1088 Action action = new Action();
1089
1090 String pageId = element.getAttributeValue(PAGE_ID_ATTRIBUTE);
1091 action.setPageId(pageId);
1092
1093 if (pageId == null || pageId.trim().length() == 0) {
1094
1095 throw new SinonException("Every action tag must have a " +
1096 PAGE_ID_ATTRIBUTE + " attribute.");
1097
1098 }
1099
1100 String foreach = element.getAttributeValue(FOREACH_ATTRIBUTE);
1101 action.setForeach(foreach);
1102
1103 String variable = element.getAttributeValue(VARIABLE_ATTRIBUTE);
1104 action.setVariable(variable);
1105
1106 if (foreach != null && variable == null) {
1107
1108 throw new SinonException("Every action tag with a + " +
1109 FOREACH_ATTRIBUTE + " must have a " + VARIABLE_ATTRIBUTE +
1110 " attribute.");
1111
1112 }
1113
1114 String index = element.getAttributeValue(INDEX_ATTRIBUTE);
1115 action.setIndex(index);
1116
1117 String condition = element.getAttributeValue(CONDITION_ATTRIBUTE);
1118 action.setCondition(condition);
1119
1120 String propertyId = element.getAttributeValue(PROPERTY_ID_ATTRIBUTE);
1121 action.setPropertyId(propertyId);
1122
1123 if (condition != null && propertyId == null) {
1124
1125 throw new SinonException("Todo action com " + CONDITION_ATTRIBUTE +
1126 " deve ter um atributo " + PROPERTY_ID_ATTRIBUTE);
1127
1128 }
1129
1130 String url = element.getAttributeValue(URL_ATTRIBUTE);
1131
1132 if (url != null) {
1133
1134 url = url.trim();
1135
1136 if (url.length() == 0) {
1137
1138 throw new SinonException("Attribute " + URL_ATTRIBUTE +
1139 " (tag " + ACTION_TAG + ") is optional but cannot " +
1140 "be empty or comprised of only white space.");
1141
1142 }
1143
1144 action.setUrl(url);
1145
1146 }
1147
1148 Element pageConfigurationTag = element.getChild(PAGE_CONFIG_TAG);
1149
1150 if (pageConfigurationTag != null) {
1151
1152 PageConfiguration pageConfiguration =
1153 parsePageConfiguration(pageConfigurationTag);
1154
1155 action.setConfiguration(pageConfiguration);
1156
1157 }
1158
1159 return action;
1160
1161 }
1162
1163 private PositioningStep getPositioningStep(Element element) {
1164
1165 PositioningStep step = new PositioningStep();
1166
1167 step.setType(element.getName());
1168
1169 String direction = element.getAttributeValue(DIRECTION_ATTRIBUTE);
1170
1171 if (direction != null) {
1172
1173 boolean backwards = direction.equalsIgnoreCase(BACKWARDS_ATTRIBUTE);
1174 if (backwards) {
1175 step.setDirection(PositioningStep.BACKWARD);
1176 } else {
1177 step.setDirection(PositioningStep.FORWARD);
1178 }
1179
1180 }
1181
1182 String before = element.getAttributeValue(BEFORE_ATTRIBUTE);
1183 step.setBefore(before);
1184
1185 String mustTrimReference = element.getAttributeValue(TRIM_ATTRIBUTE);
1186
1187 Boolean trim;
1188
1189 if (mustTrimReference != null) {
1190 trim = Boolean.valueOf(mustTrimReference);
1191 } else {
1192 trim = Boolean.TRUE;
1193 }
1194
1195 step.setMustTrimReference(trim.booleanValue());
1196
1197 StringBuffer referenceBuffer = new StringBuffer();
1198
1199 List contents = element.getContent();
1200
1201 final int size = contents.size();
1202 Content content;
1203
1204 for (int i = 0; i < size; i++) {
1205
1206 content = (Content) contents.get(i);
1207
1208 if (content instanceof Text) {
1209
1210 Text text = (Text) content;
1211 referenceBuffer.append(text.getText());
1212
1213 } else if (content instanceof Element) {
1214
1215 Element text = (Element) content;
1216
1217 if (text.getName().equals(NEWLINE_TAG)) {
1218 referenceBuffer.append("\n");
1219 }
1220
1221 }
1222
1223 }
1224
1225 String reference = referenceBuffer.toString();
1226
1227 if (trim.booleanValue()) {
1228 reference = reference.trim();
1229 }
1230
1231 step.setReference(reference);
1232
1233 String failIfFound = element.getAttributeValue(FAIL_IF_FOUND_ATTRIBUTE);
1234
1235 if (failIfFound != null) {
1236 Boolean fif = Boolean.valueOf(failIfFound);
1237 step.setFailIfFound(fif.booleanValue());
1238 }
1239
1240 return step;
1241
1242 }
1243
1244 private LoopStep getLoopStep(Element element)
1245 throws SinonException {
1246
1247 LoopStep loopStep = new LoopStep();
1248
1249 String condition = element.getAttributeValue(CONDITION_ATTRIBUTE);
1250 loopStep.setCondition(condition);
1251
1252 if (condition == null) {
1253
1254 throw new SinonException("Tag " + LOOP_TAG + " must have a " +
1255 CONDITION_ATTRIBUTE + " attribute.");
1256
1257 }
1258
1259 condition = condition.trim();
1260
1261 if (condition.length() == 0) {
1262
1263 throw new SinonException("Attribute " + CONDITION_ATTRIBUTE +
1264 " (tag " + LOOP_TAG + ") cannot be empty of comprised of " +
1265 "only white space");
1266
1267 }
1268
1269 String value = element.getAttributeValue(VALUE_ATTRIBUTE);
1270 loopStep.setValue(value);
1271
1272 List steps = getSteps(element);
1273
1274 for (int i = 0; i < steps.size(); i++) {
1275
1276 Step step = (Step) steps.get(i);
1277 loopStep.addStep(step);
1278
1279 }
1280
1281 return loopStep;
1282
1283 }
1284
1285 private DataExtraction getDoDataExtraction(Element dataExtractionTag)
1286 throws SinonException {
1287
1288 DataExtraction dataExtraction;
1289 String refid =
1290 dataExtractionTag.getAttributeValue(REFID_ATTRIBUTE);
1291
1292 DataExtraction referred =
1293 currentCatalog.getDataExtraction(refid);
1294
1295 if (referred == null) {
1296
1297 throw new SinonException("There is no data extraction whose id " +
1298 "is " + refid);
1299
1300 }
1301
1302 dataExtraction = referred.copy();
1303
1304 if (dataExtraction == null) {
1305
1306 throw new SinonException("There is no data extraction whose id " +
1307 "is " + refid);
1308
1309 }
1310
1311 return dataExtraction;
1312
1313 }
1314
1315 private DataExtraction getDataExtraction(Element dataExtractionTag)
1316 throws SinonException {
1317
1318 DataExtraction dataExtraction;
1319 dataExtraction = new DataExtraction();
1320
1321 String id = dataExtractionTag.getAttributeValue(ID_ATTRIBUTE);
1322 dataExtraction.setId(id);
1323
1324 if (id == null) {
1325
1326 throw new SinonException("Every " + DATA_EXTRACTION_TAG +
1327 " tag must have an " + ID_ATTRIBUTE + " attribute");
1328
1329 }
1330
1331 id = id.trim();
1332
1333 if (id.length() == 0) {
1334
1335 throw new SinonException("Attribute " + ID_ATTRIBUTE +
1336 " (tag " + DATA_EXTRACTION_TAG +
1337 ") cannot be empty or comprised of only white space.");
1338
1339 }
1340
1341 String trimValue =
1342 dataExtractionTag.getAttributeValue(TRIM_ATTRIBUTE);
1343
1344 if (trimValue != null) {
1345
1346 Boolean trim = Boolean.valueOf(trimValue);
1347 dataExtraction.setTrimValueNeeded(trim.booleanValue());
1348
1349 }
1350
1351 String multivaluedString =
1352 dataExtractionTag.getAttributeValue(LIST_ATTRIBUTE);
1353
1354 if (multivaluedString != null) {
1355
1356 Boolean multivalued = Boolean.valueOf(multivaluedString);
1357 dataExtraction.setMultivalued(multivalued.booleanValue());
1358
1359 }
1360
1361 String failOnErrorString =
1362 dataExtractionTag.getAttributeValue(FAIL_ON_ERROR_ATTRIBUTE);
1363
1364 if (failOnErrorString != null) {
1365
1366 Boolean failOnError = Boolean.valueOf(failOnErrorString);
1367 dataExtraction.setFailOnError(failOnError.booleanValue());
1368
1369 }
1370
1371 String allowDuplicatesString =
1372 dataExtractionTag.getAttributeValue(ALLOW_DUPLICATES_ATTRIBUTE);
1373
1374 if (allowDuplicatesString != null) {
1375
1376 Boolean allowDuplicates = Boolean.valueOf(allowDuplicatesString);
1377 dataExtraction.setAllowDuplicates(allowDuplicates.booleanValue());
1378
1379 }
1380
1381 String valueOnError =
1382 dataExtractionTag.getAttributeValue(VALUE_ON_ERROR_ATTRIBUTE);
1383
1384 if (valueOnError != null) {
1385 dataExtraction.setValueOnError(valueOnError);
1386 }
1387
1388 List steps = getSteps(dataExtractionTag);
1389
1390 for (int i = 0; i < steps.size(); i++) {
1391
1392 Step step = (Step) steps.get(i);
1393 dataExtraction.addStep(step);
1394
1395 }
1396
1397 return dataExtraction;
1398
1399 }
1400
1401 private void addStartPages(Element catalogTag, Catalog catalog)
1402 throws SinonException {
1403
1404 Element startPagesTag = catalogTag.getChild(START_PAGES_TAG);
1405
1406 if (startPagesTag == null) {
1407
1408 throw new SinonException("Catalog " + catalog.getId() + " does " +
1409 "not have any " + START_PAGES_TAG + " tag.");
1410
1411 }
1412
1413 List startPageTags = startPagesTag.getChildren(START_PAGE_TAG);
1414
1415 if (startPageTags.size() == 0) {
1416
1417 throw new SinonException("Catalog " + catalog.getId() + " does " +
1418 "not have any start page.");
1419
1420 }
1421
1422 for (int i = 0; i < startPageTags.size(); i++) {
1423
1424 Element element = (Element) startPageTags.get(i);
1425 StartPage startPage = new StartPage();
1426
1427 String refid = element.getAttributeValue(REFID_ATTRIBUTE);
1428
1429 if (refid == null) {
1430
1431 throw new SinonException("Every " + START_PAGE_TAG + " must " +
1432 "have a " + REFID_ATTRIBUTE + " attribute");
1433
1434 }
1435
1436 startPage.setRefid(refid);
1437
1438 Properties properties = new Properties();
1439
1440 List propertyTags = element.getChildren(PROPERTY_TAG);
1441
1442 for (int j = 0; j < propertyTags.size(); j++) {
1443
1444 Element propertyElement = (Element) propertyTags.get(j);
1445
1446 String name = propertyElement.getAttributeValue(NAME_ATTRIBUTE);
1447 String value =
1448 propertyElement.getAttributeValue(VALUE_ATTRIBUTE);
1449
1450 properties.setProperty(name, value);
1451
1452 }
1453
1454 startPage.setProperties(properties);
1455
1456 catalog.addStartPage(startPage);
1457
1458 }
1459
1460 }
1461
1462 private void addPages(Element catalogTag, Catalog catalog)
1463 throws SinonException {
1464
1465 List pageTags = catalogTag.getChildren(PAGE_TAG);
1466
1467 for (int i = 0; i < pageTags.size(); i++) {
1468
1469 Element element = (Element) pageTags.get(i);
1470 catalog.addPage(parsePage(element));
1471
1472 }
1473
1474 }
1475
1476 private void addParameterSets(Element catalogTag, Catalog catalog)
1477 throws SinonException {
1478
1479 List parameterSetTags = catalogTag.getChildren(PARAMETER_SET_TAG);
1480
1481 for (int i = 0; i < parameterSetTags.size(); i++) {
1482
1483 Element element = (Element) parameterSetTags.get(i);
1484 catalog.addParameterSet(parseParameterSet(element));
1485
1486 }
1487
1488 }
1489
1490 private Page parsePage(Element pageTag) throws SinonException {
1491
1492 Page page = new Page();
1493
1494 String id = pageTag.getAttributeValue(ID_ATTRIBUTE);
1495
1496 if (id == null) {
1497
1498 throw new SinonException("Every " + PAGE_TAG + " tag must have " +
1499 "an " + ID_ATTRIBUTE + " attribute");
1500
1501 }
1502
1503 id = id.trim();
1504
1505 if (id.length() == 0) {
1506
1507 throw new SinonException("Attribute " + ID_ATTRIBUTE +
1508 " (tag " + PAGE_TAG + ") cannot be empty or " +
1509 "comprised of only white space.");
1510
1511 }
1512
1513 page.setId(id);
1514
1515 String followRedirectAttribute =
1516 pageTag.getAttributeValue(FOLLOW_REDIRECT_ATTRIBUTE);
1517
1518 if (followRedirectAttribute != null) {
1519
1520 final Boolean followRedirect =
1521 Boolean.valueOf(followRedirectAttribute);
1522 page.setFollowRedirects(followRedirect.booleanValue());
1523
1524 }
1525
1526 String urlAttribute = pageTag.getAttributeValue(URL_ATTRIBUTE);
1527
1528 page.setUrl(urlAttribute);
1529
1530 String methodAttribute = pageTag.getAttributeValue(METHOD_ATTRIBUTE);
1531
1532 if (methodAttribute != null) {
1533
1534 if (methodAttribute.equalsIgnoreCase("post")) {
1535 page.setMethod(Page.POST_METHOD);
1536 } else if (methodAttribute.equalsIgnoreCase("get")) {
1537 page.setMethod(Page.GET_METHOD);
1538 } else {
1539 throw new SinonException("Unknown method: " + methodAttribute);
1540 }
1541
1542 }
1543
1544 Element pageConfigurationTag = pageTag.getChild(PAGE_CONFIG_TAG);
1545
1546 if (pageConfigurationTag != null) {
1547 page.setConfiguration(parsePageConfiguration(pageConfigurationTag));
1548 }
1549
1550 Element storageConfigurationTag = pageTag.getChild(SAVE_TAG);
1551
1552 if (storageConfigurationTag != null) {
1553
1554 String file =
1555 storageConfigurationTag.getAttributeValue(FILE_ATTRIBUTE);
1556
1557 if (file == null) {
1558
1559 throw new SinonException("Tag " + SAVE_TAG + " must have a " +
1560 FILE_ATTRIBUTE + " attribute");
1561
1562 }
1563
1564 file = file.trim();
1565
1566 if (file.length() == 0) {
1567
1568 throw new SinonException("Attribute " + FILE_ATTRIBUTE +
1569 " (tag " + SAVE_TAG + ") cannot be empty or " +
1570 "comprised of only white space.");
1571
1572 }
1573
1574 page.getStorageConfiguration().setFilename(file);
1575
1576 }
1577
1578 addSteps(pageTag, page);
1579
1580 List actions = pageTag.getChildren(ACTION_TAG);
1581
1582 for (int i = 0; i < actions.size(); i++) {
1583
1584 Element element = (Element) actions.get(i);
1585 page.addAction(getAction(element));
1586
1587 }
1588
1589 Element listenersTag = pageTag.getChild(PAGE_LISTENERS_TAG);
1590
1591 if (listenersTag != null) {
1592 addListeners(listenersTag, page);
1593 }
1594
1595 return page;
1596
1597 }
1598
1599 private void addListeners(Element listenersTag, Page page)
1600 throws SinonException {
1601
1602 List listeners = listenersTag.getChildren();
1603
1604 for (int i = 0; i < listeners.size(); i++) {
1605
1606 Element element = (Element) listeners.get(i);
1607 String type = element.getName();
1608
1609 String className = element.getAttributeValue(CLASS_ATTRIBUTE);
1610
1611 if (type.equals(ON_ERROR_TAG)) {
1612
1613 if (className == null || className.trim().length() == 0) {
1614
1615 throw new SinonException("Tag " + ON_ERROR_TAG +
1616 " must have a " + CLASS_ATTRIBUTE +
1617 " attribute");
1618
1619 }
1620
1621 page.setErrorListenerClassName(className);
1622
1623 } else if (type.equals(ON_STATE_CHANGE_TAG)) {
1624
1625 if (className == null || className.trim().length() == 0) {
1626
1627 throw new SinonException("Tag " + ON_STATE_CHANGE_TAG +
1628 " must have a " + CLASS_ATTRIBUTE + " attribute.");
1629
1630 }
1631
1632 page.setPageStateListenerClassName(className);
1633
1634 } else if (type.equals(ON_PROMPT_TAG)) {
1635
1636 if (className == null || className.trim().length() == 0) {
1637
1638 throw new SinonException("Tag " + ON_PROMPT_TAG +
1639 " must have an " + CLASS_ATTRIBUTE + " attribute");
1640
1641 }
1642
1643 page.setPromptListenerClassName(className);
1644
1645 } else {
1646 throw new SinonException("Unknown listener type: " + type);
1647 }
1648
1649 }
1650
1651 }
1652
1653 /***
1654 * Chamado por {@link #parsePage}.
1655 *
1656 * @param pageTag
1657 * @param page
1658 * @throws SinonException
1659 */
1660 private void addSteps(Element pageTag, Page page)
1661 throws SinonException {
1662
1663 Element dataExtractionsTag = pageTag.getChild(DATA_EXTRACTIONS_TAG);
1664
1665 if (dataExtractionsTag == null) {
1666 return;
1667 }
1668
1669 List steps = getSteps(dataExtractionsTag);
1670
1671 final int size = steps.size();
1672 Step step;
1673
1674 for (int i = 0; i < size; i++) {
1675
1676 step = (Step) steps.get(i);
1677 page.addStep(step);
1678
1679 }
1680
1681 }
1682
1683 private PageConfiguration parsePageConfiguration(
1684 Element pageConfigurationTag)
1685 throws SinonException {
1686
1687 PageConfiguration pageConfiguration = new PageConfiguration();
1688
1689 Element parameterSetTag =
1690 pageConfigurationTag.getChild(PARAMETER_SET_TAG);
1691
1692 pageConfiguration.setParameterSet(parseParameterSet(parameterSetTag));
1693
1694 return pageConfiguration;
1695
1696 }
1697
1698 /***
1699 * @param parameterSetTag
1700 * @return
1701 */
1702 private ParameterSet parseParameterSet(Element parameterSetTag)
1703 throws SinonException {
1704
1705 ParameterSet parameterSet;
1706
1707 Element includeTag =
1708 parameterSetTag.getChild(INCLUDE_PARAMETER_SET_TAG);
1709
1710 if (includeTag != null) {
1711
1712 String refid = includeTag.getAttributeValue(REFID_ATTRIBUTE);
1713 ParameterSet included = currentCatalog.getParameterSet(refid);
1714
1715 if (included == null) {
1716
1717 throw new SinonException("There is no parameter set with id " +
1718 refid);
1719
1720 }
1721
1722 parameterSet = new ParameterSet(included);
1723
1724 } else {
1725 parameterSet = new ParameterSet();
1726 }
1727
1728 List parameters = parameterSetTag.getChildren(PARAMETER_TAG);
1729
1730 String id = parameterSetTag.getAttributeValue(ID_ATTRIBUTE);
1731 parameterSet.setId(id);
1732
1733 for (int i = 0; i < parameters.size(); i++) {
1734
1735 Element parameter = (Element) parameters.get(i);
1736
1737 String name = parameter.getAttributeValue(NAME_ATTRIBUTE);
1738 String value = parameter.getAttributeValue(VALUE_ATTRIBUTE);
1739 String encoding =
1740 parameter.getAttributeValue(ENCODING_ATTRIBUTE);
1741
1742 if (name == null || value == null) {
1743
1744 throw new SinonException("Tag " + PROPERTY_TAG + " must have " +
1745 " a " + NAME_ATTRIBUTE + " and a " +
1746 VALUE_ATTRIBUTE + " attributes.");
1747
1748 }
1749
1750 name = name.trim();
1751
1752 if (name.length() == 0) {
1753
1754 throw new SinonException("Attribute " + NAME_ATTRIBUTE +
1755 " cannot be empty or comprised of only white space.");
1756
1757 }
1758
1759 Parameter newParameter = new Parameter();
1760
1761 if (encoding != null) {
1762 newParameter.setEncoding(encoding);
1763 }
1764
1765 newParameter.setName(name);
1766 newParameter.setValue(value);
1767
1768 parameterSet.setParameter(newParameter);
1769
1770 }
1771
1772 return parameterSet;
1773
1774 }
1775
1776 /***
1777 * Retorna um {@link CollectorConfiguration} de acordo com a descrição
1778 * em <code>configTag</code>.
1779 *
1780 * @param configTag um <code>org.jdom.Element</code> descrevendo um
1781 * {@link CollectorConfiguration}.
1782 * @return um {@link CollectorConfiguration}.
1783 */
1784 private CollectorConfiguration parseCollectorConfiguration(
1785 Element configTag)
1786 throws SinonException {
1787
1788 if (configTag == null) {
1789
1790 throw new SinonException("Every " + COLLECTOR_TAG + " tag " +
1791 " must contain a " + CONFIG_TAG + " tag.");
1792
1793 }
1794
1795 CollectorConfiguration configuration = new CollectorConfiguration();
1796
1797 Element httpHeadersTag = configTag.getChild(HEADERS_TAG);
1798
1799 if (httpHeadersTag != null) {
1800
1801 List httpHeaderTag = httpHeadersTag.getChildren(HEADER_TAG);
1802
1803 for (int i = 0; i < httpHeaderTag.size(); i++) {
1804
1805 Element element = (Element) httpHeaderTag.get(i);
1806 String name = element.getAttributeValue(NAME_ATTRIBUTE);
1807 String value = element.getAttributeValue(VALUE_ATTRIBUTE);
1808
1809 if (name == null || value == null) {
1810
1811 throw new SinonException("Every " + HEADER_TAG + " tag " +
1812 " must have a " + NAME_ATTRIBUTE + " and a " +
1813 VALUE_ATTRIBUTE + " attributes");
1814
1815 }
1816
1817 name = name.trim();
1818
1819 if (name.length() == 0) {
1820
1821 throw new SinonException("The " + NAME_ATTRIBUTE +
1822 " name attribute (header tag) cannot be empty " +
1823 "or comprised of white space only.");
1824
1825 }
1826
1827 configuration.setHTTPHeader(name, value);
1828
1829 }
1830
1831 }
1832
1833 Element thinkTimeTag = configTag.getChild(THINK_TIME_TAG);
1834
1835 addThinkTime(configuration, thinkTimeTag);
1836
1837 addTimeout(configTag, configuration);
1838
1839 addRetries(configTag, configuration);
1840
1841 return configuration;
1842
1843 }
1844
1845 private void addRetries(Element configTag,
1846 CollectorConfiguration configuration)
1847 throws SinonException {
1848
1849 Element retriesTag = configTag.getChild(RETRIES_TAG);
1850
1851 if (retriesTag == null) {
1852
1853 throw new SinonException("Every " + CONFIG_TAG + " tag must " +
1854 "contain a " + RETRIES_TAG + " tag.");
1855
1856 }
1857
1858 String retries = retriesTag.getAttributeValue(VALUE_ATTRIBUTE);
1859
1860 if (retries == null) {
1861
1862 throw new SinonException("Every " + RETRIES_TAG + " tag must " +
1863 "have a " + VALUE_ATTRIBUTE + " attribute.");
1864
1865 }
1866
1867 boolean throwException = false;
1868
1869 try {
1870 configuration.setRetries(Integer.parseInt(retries));
1871 } catch (NumberFormatException e) {
1872 throwException = true;
1873 }
1874
1875 if (throwException || configuration.getRetries() < 0) {
1876 throw new SinonException("Invalid retries value : " + retries);
1877 }
1878
1879 }
1880
1881 private void addTimeout(Element configTag,
1882 CollectorConfiguration configuration)
1883 throws SinonException {
1884
1885 Element timeoutTag = configTag.getChild(TIMEOUT_TAG);
1886
1887 if (timeoutTag == null) {
1888
1889 throw new SinonException("Every " + CONFIG_TAG + " " +
1890 "tag must contain a " + TIMEOUT_TAG + " tag.");
1891
1892 }
1893
1894 String timeout = timeoutTag.getAttributeValue(VALUE_ATTRIBUTE);
1895
1896 if (timeout == null) {
1897
1898 throw new SinonException("Every " + TIMEOUT_TAG + " tag must " +
1899 "have a " + VALUE_ATTRIBUTE + " attribute.");
1900
1901 }
1902
1903 boolean throwException = false;
1904
1905 try {
1906 configuration.setTimeout(Integer.parseInt(timeout));
1907 } catch (NumberFormatException e) {
1908 throwException = true;
1909 }
1910
1911 if (throwException || configuration.getTimeout() < 0) {
1912
1913 throw new SinonException("Invalid timeout value : " + timeout);
1914
1915 }
1916
1917 }
1918
1919 private void addThinkTime(CollectorConfiguration configuration,
1920 Element thinkTimeTag) throws SinonException {
1921
1922 if (thinkTimeTag == null) {
1923
1924 throw new SinonException("Every " + CONFIG_TAG + " tag must " +
1925 "contain a " + THINK_TIME_TAG + " tag.");
1926
1927 }
1928
1929 String thinkTimeImplementationName =
1930 thinkTimeTag.getAttributeValue(CLASS_ATTRIBUTE);
1931
1932 if (thinkTimeImplementationName == null) {
1933
1934 throw new SinonException("Every " + THINK_TIME_TAG + " must have " +
1935 " a " + CLASS_ATTRIBUTE + " attribute.");
1936
1937 }
1938
1939 thinkTimeImplementationName = thinkTimeImplementationName.trim();
1940
1941 if (thinkTimeImplementationName.length() == 0) {
1942
1943 throw new SinonException("Attribute " + CLASS_ATTRIBUTE +
1944 "(tag " + THINK_TIME_TAG + ") cannot be empty or " +
1945 "comprised of white space only.");
1946
1947 }
1948
1949 configuration.setThinkTimeImplementationClassName(
1950 thinkTimeImplementationName);
1951
1952 List propertyTags = thinkTimeTag.getChildren(PROPERTY_TAG);
1953
1954 for (int i = 0; i < propertyTags.size(); i++) {
1955
1956 Element element = (Element) propertyTags.get(i);
1957 String name = element.getAttributeValue(NAME_ATTRIBUTE);
1958 String value = element.getAttributeValue(VALUE_ATTRIBUTE);
1959
1960 configuration.setThinkTimeProperty(name, value);
1961
1962 }
1963
1964 }
1965
1966 /***
1967 * <code>FileFilter</code> que aceita apenas arquivos com
1968 * sufixo <code>.xml</code>.
1969 */
1970 private static class XMLFileFilter implements FileFilter {
1971
1972 public boolean accept(File pathname) {
1973 return pathname.getAbsolutePath().endsWith(COLLECTOR_SUFFIX);
1974 }
1975
1976 }
1977
1978 }