1 /* |
|
2 * Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 package com.nokia.helium.metadata.ant.types; |
|
19 |
|
20 import java.io.*; |
|
21 import java.util.*; |
|
22 import java.util.regex.Pattern; |
|
23 import java.util.regex.Matcher; |
|
24 import org.apache.log4j.Logger; |
|
25 import javax.xml.stream.XMLStreamReader; |
|
26 import com.nokia.helium.jpa.entity.metadata.Metadata; |
|
27 import com.nokia.helium.metadata.CustomMetaDataProvider; |
|
28 import com.nokia.helium.metadata.db.ORMMetadataDB; |
|
29 import javax.xml.stream.XMLInputFactory; |
|
30 import javax.xml.stream.events.XMLEvent; |
|
31 import javax.xml.stream.FactoryConfigurationError; |
|
32 import javax.xml.stream.XMLStreamException; |
|
33 |
|
34 |
|
35 /** |
|
36 * This Type is to specify and use the sbs logparsertype to |
|
37 * parse and store the data based on xmlstreamreader. |
|
38 * <pre> |
|
39 * <hlm:metadatafilterset id="sbs.metadata.filter"> |
|
40 * <metadatafilterset filterfile="common.csv" /> |
|
41 * </hlm:metadatafilterset> |
|
42 * |
|
43 * <hlm:sbsmetadatainput > |
|
44 * <fileset dir="${project.dir}/../data/"> |
|
45 * <include name="*compile.log"/> |
|
46 * </fileset> |
|
47 * <metadatafilterset refid="sbs.metadata.filter" /> |
|
48 * </hlm:sbsmetadatainput> |
|
49 * </pre> |
|
50 * @ant.task name="sbsmetadatainput" category="Metadata" |
|
51 */ |
|
52 public class SBSLogMetaDataInput extends XMLLogMetaDataInput implements CustomMetaDataProvider { |
|
53 |
|
54 |
|
55 private static final String DRIVE_LETTER_REGEX = "^(([a-zA-Z]):(\\\\|/))(.*)(/bld\\.inf)$"; |
|
56 |
|
57 private static final String FAILED_STATUS_MESSAGE = "ERROR: recipe exit status is failed."; |
|
58 |
|
59 private Logger logger = Logger.getLogger(SBSLogMetaDataInput.class); |
|
60 |
|
61 private String currentComponent; |
|
62 |
|
63 private float currentElapsedTime; |
|
64 |
|
65 private String logTextInfo = ""; |
|
66 |
|
67 private String recipeStatus = "ok"; |
|
68 |
|
69 private HashMap<String, List <CategoryEntry>> generalTextEntries = new HashMap<String, List <CategoryEntry>>(); |
|
70 |
|
71 private List<Metadata.WhatLogMember> members = new ArrayList<Metadata.WhatLogMember>(); |
|
72 |
|
73 private List<SpecialRegex> specialRegexPatternList = new ArrayList<SpecialRegex>(); |
|
74 |
|
75 private int lineNumber; |
|
76 |
|
77 private boolean inMainDataSection; |
|
78 |
|
79 private boolean inWhatLogSection; |
|
80 |
|
81 private boolean recordText; |
|
82 |
|
83 private HashMap<String, TimeEntry> componentTimeMap = new HashMap<String, TimeEntry>(); |
|
84 |
|
85 private Pattern buildTimeMatcher = Pattern.compile("^Run time\\s+(\\d+)\\s+seconds$"); |
|
86 |
|
87 private int buildTime; |
|
88 |
|
89 private File cleanLogFile; |
|
90 |
|
91 private boolean categorizationCompleted; |
|
92 |
|
93 private CategorizationHandler categorizationHandler; |
|
94 |
|
95 /** |
|
96 * Constructor |
|
97 */ |
|
98 public SBSLogMetaDataInput() { |
|
99 specialRegexPatternList.add(new SpecialRegex("(make.exe|make): \\*\\*\\* No rule to make target.*needed by `(.*)'.*", 2)); |
|
100 specialRegexPatternList.add(new SpecialRegex("(make.exe|make): \\*\\*\\* \\[(.*)\\].*", 2)); |
|
101 } |
|
102 |
|
103 |
|
104 /** |
|
105 * Removes the bld inf and the drive letter from the text |
|
106 * @param text in which the bld.inf and drive letter to be removed |
|
107 * @return updated string. |
|
108 */ |
|
109 static String removeDriveAndBldInf(String text) { |
|
110 // Some light linux support |
|
111 if (File.separatorChar == '/' && text.endsWith("/bld.inf")) { |
|
112 int start = 0; |
|
113 if (text.startsWith("/")) { |
|
114 start = 1; |
|
115 } |
|
116 return text.substring(start, text.length() - 8); |
|
117 } else { |
|
118 Matcher matcher = (Pattern.compile(DRIVE_LETTER_REGEX)).matcher(text); |
|
119 if (matcher.matches()) { |
|
120 return matcher.group(4); |
|
121 } |
|
122 } |
|
123 return text; |
|
124 } |
|
125 |
|
126 /** |
|
127 * Removes the bld inf and the drive letter from the text |
|
128 * @param text in which the bld.inf and drive letter to be removed |
|
129 * @return updated string. |
|
130 */ |
|
131 static String getComponent(XMLStreamReader streamReader) { |
|
132 String currentComponent = getAttribute("bldinf", streamReader); |
|
133 if ( currentComponent != null && currentComponent.equals("")) { |
|
134 return null; |
|
135 } |
|
136 if (currentComponent != null ) { |
|
137 currentComponent = removeDriveAndBldInf(currentComponent); |
|
138 } |
|
139 return currentComponent; |
|
140 } |
|
141 |
|
142 /** |
|
143 * Generic function to return the attribute value of an attribute from stream |
|
144 * @param attribute for which the value from xml stream to be returned. |
|
145 * @return the attribute value of an attribute. |
|
146 */ |
|
147 static String getAttribute(String attribute, XMLStreamReader streamReader) { |
|
148 int count = streamReader.getAttributeCount() ; |
|
149 for (int i = 0 ; i < count ; i++) { |
|
150 if ( streamReader.getAttributeLocalName(i).equals(attribute) ) { |
|
151 return streamReader.getAttributeValue(i); |
|
152 } |
|
153 } |
|
154 return null; |
|
155 } |
|
156 |
|
157 /** |
|
158 * Helper function to set the clean log file. |
|
159 * @param logFile which is the clean log file to process for additional categories |
|
160 * @deprecated |
|
161 */ |
|
162 @Deprecated |
|
163 public void setCleanLogFile(File logFile) { |
|
164 log("The usage of the cleanLogFile is deprecated."); |
|
165 } |
|
166 |
|
167 /** |
|
168 * Helper function to set the clean log file. |
|
169 * @param logFile which is the what log file to process for missing |
|
170 * components |
|
171 * @deprecated |
|
172 */ |
|
173 @Deprecated |
|
174 public void setWhatLogFile(File logFile) { |
|
175 log("The usage of the cleanLogFile is deprecated."); |
|
176 } |
|
177 |
|
178 /** |
|
179 * Function to process the characters event of xml stream callback. |
|
180 * @param streamReader: the input stream reader which contains the xml data to be parsed for recording data. |
|
181 * @return true if there are any element to be added to the database. |
|
182 */ |
|
183 public boolean characters (XMLStreamReader streamReader) { |
|
184 HashMap<String, Integer> toProcess = new HashMap<String, Integer>(); |
|
185 if (recordText) { |
|
186 logTextInfo += streamReader.getText(); |
|
187 } else { |
|
188 if (inMainDataSection) { |
|
189 String cdataText = streamReader.getText().trim(); |
|
190 String [] textList = cdataText.split("\n"); |
|
191 int i = 0; |
|
192 for (String text : textList) { |
|
193 boolean added = false; |
|
194 if (text.trim().equals("")) { |
|
195 continue; |
|
196 } |
|
197 for (SpecialRegex specialRegex : specialRegexPatternList) { |
|
198 Matcher matcher = specialRegex.getRegexPattern().matcher(text); |
|
199 int groupPosition = specialRegex.getGroupPosition(); |
|
200 List <CategoryEntry> entryList = null; |
|
201 if (matcher.matches()) { |
|
202 if (cleanLogFile == null) { |
|
203 cleanLogFile = new File(getCurrentFile().toString()); |
|
204 } |
|
205 String componentName = matcher.group(groupPosition).toLowerCase(); |
|
206 CategoryEntry newEntry = new CategoryEntry(text, componentName , |
|
207 "error", streamReader.getLocation().getLineNumber(), getCurrentFile().toString()); |
|
208 entryList = generalTextEntries.get(componentName); |
|
209 if (entryList == null) { |
|
210 entryList = new ArrayList<CategoryEntry>(); |
|
211 generalTextEntries.put(componentName, entryList); |
|
212 } |
|
213 entryList.add(newEntry); |
|
214 added = true; |
|
215 break; |
|
216 } |
|
217 } |
|
218 if (!added) { |
|
219 toProcess.put(text.trim(), streamReader.getLocation().getLineNumber() + i); |
|
220 } |
|
221 i++; |
|
222 } |
|
223 boolean entryCreated = false; |
|
224 //Check for any general errors. |
|
225 for (String textString : toProcess.keySet()) { |
|
226 boolean created = findAndAddEntries(textString, "general", |
|
227 getCurrentFile().toString(), toProcess.get(textString)); |
|
228 if (created && !entryCreated ) { |
|
229 entryCreated = true; |
|
230 } |
|
231 } |
|
232 } |
|
233 } |
|
234 return false; |
|
235 } |
|
236 |
|
237 /** |
|
238 * Function to process the start event of xml stream callback. |
|
239 * @param streamReader: the input stream reader which contains the xml data to be parsed for recording data. |
|
240 * @return true if there are any element to be added to the database. |
|
241 */ |
|
242 public boolean startElement (XMLStreamReader streamReader) { |
|
243 String tagName = streamReader.getLocalName(); |
|
244 if (tagName.equalsIgnoreCase("buildlog")) { |
|
245 logger.debug("starting with buildlog"); |
|
246 inMainDataSection = true; |
|
247 } |
|
248 if (tagName.equalsIgnoreCase("recipe") ) { |
|
249 lineNumber = streamReader.getLocation().getLineNumber(); |
|
250 currentComponent = getComponent(streamReader); |
|
251 recordText = true; |
|
252 inMainDataSection = false; |
|
253 recipeStatus = "ok"; |
|
254 } if (tagName.equalsIgnoreCase("status") ) { |
|
255 String exit = streamReader.getAttributeValue(null, "exit"); |
|
256 recipeStatus = (exit != null) ? exit : "ok"; |
|
257 } else if (tagName.equalsIgnoreCase("error") |
|
258 || tagName.equalsIgnoreCase("warning")) { |
|
259 lineNumber = streamReader.getLocation().getLineNumber(); |
|
260 currentComponent = getComponent(streamReader); |
|
261 recordText = true; |
|
262 inMainDataSection = false; |
|
263 } else if (tagName.equalsIgnoreCase("whatlog")) { |
|
264 members.clear(); |
|
265 currentComponent = getComponent(streamReader); |
|
266 inMainDataSection = false; |
|
267 inWhatLogSection = true; |
|
268 } else if (inWhatLogSection && tagName.equals("export")) { |
|
269 String text = SBSLogMetaDataInput.getAttribute("destination", streamReader); |
|
270 if (text != null && text.trim().length() > 0) { |
|
271 String member = SBSLogMetaDataInput.removeDriveAndBldInf(text); |
|
272 boolean exists = (new File(text)).exists(); |
|
273 Metadata.WhatLogMember entry = new Metadata.WhatLogMember(member, exists); |
|
274 members.add(entry); |
|
275 } |
|
276 } else if (inWhatLogSection && !tagName.equals("export")) { |
|
277 logTextInfo = ""; |
|
278 recordText = true; |
|
279 } else if (tagName.equalsIgnoreCase("time")) { |
|
280 inMainDataSection = false; |
|
281 currentElapsedTime = Float.valueOf(getAttribute("elapsed", streamReader)).floatValue(); |
|
282 logger.debug("currentElapsedTime: " + currentElapsedTime); |
|
283 if (currentComponent != null) { |
|
284 TimeEntry timeObject = componentTimeMap.get(currentComponent); |
|
285 logger.debug("currentComponent:" + currentComponent); |
|
286 if (timeObject == null) { |
|
287 timeObject = new TimeEntry(currentElapsedTime, getCurrentFile().toString()); |
|
288 componentTimeMap.put(currentComponent, timeObject); |
|
289 logger.debug("creating to new time object"); |
|
290 } else { |
|
291 timeObject.addElapsedTime(currentElapsedTime); |
|
292 logger.debug("adding it to existing time object"); |
|
293 } |
|
294 } |
|
295 } else if (tagName.equalsIgnoreCase("clean")) { |
|
296 inMainDataSection = false; |
|
297 } else if (tagName.equalsIgnoreCase("info")) { |
|
298 inMainDataSection = false; |
|
299 recordText = true; |
|
300 } |
|
301 return false; |
|
302 } |
|
303 |
|
304 /** |
|
305 * Checks whether is there any additional entry. During log parsing, all the text which are not part of any tag |
|
306 * and are part of CDATA are recorded in a list and checked in this function for any matching errors and processed |
|
307 * for their categorization. |
|
308 * @return true if there are any element to be added to the database. |
|
309 */ |
|
310 public boolean isAdditionalEntry() { |
|
311 if (!componentTimeMap.isEmpty()) { |
|
312 Set<String> componentSet = componentTimeMap.keySet(); |
|
313 for (String component : componentSet) { |
|
314 |
|
315 TimeEntry entry = componentTimeMap.get(component); |
|
316 addEntry("default", component, entry.getFilePath(), -1, |
|
317 null, entry.getElapsedTime(), null); |
|
318 componentTimeMap.remove(component); |
|
319 return true; |
|
320 } |
|
321 } |
|
322 if (!categorizationCompleted) { |
|
323 if (cleanLogFile != null) { |
|
324 if (categorizationHandler == null ) { |
|
325 logger.debug("initializing categorization handler"); |
|
326 categorizationHandler = |
|
327 new CategorizationHandler(cleanLogFile, generalTextEntries); |
|
328 } |
|
329 } |
|
330 if (categorizationHandler != null && categorizationHandler.hasNext()) { |
|
331 try { |
|
332 CategoryEntry entry = categorizationHandler.getNext(); |
|
333 if (entry != null) { |
|
334 addEntry(entry.getSeverity(), entry.getCategory(), entry.getLogFile(), |
|
335 entry.getLineNumber(), entry.getText()); |
|
336 return true; |
|
337 } |
|
338 } catch (XMLStreamException ex) { |
|
339 logger.debug("Exception during categorization handler", ex); |
|
340 return false; |
|
341 } |
|
342 } |
|
343 categorizationCompleted = true; |
|
344 } |
|
345 return false; |
|
346 } |
|
347 |
|
348 /** |
|
349 * Function to process the end event of xml stream callback. |
|
350 * @param streamReader: the input stream reader which contains the xml data to be parsed for recording data. |
|
351 * @return true if there are any element to be added to the database. |
|
352 */ |
|
353 public boolean endElement(XMLStreamReader streamReader) { |
|
354 String tagName = streamReader.getLocalName(); |
|
355 if (tagName.equalsIgnoreCase("recipe")) { |
|
356 inMainDataSection = true; |
|
357 recordText = false; |
|
358 if (logTextInfo != null) { |
|
359 if (currentComponent == null) { |
|
360 currentComponent = "general"; |
|
361 } |
|
362 Statistics stat = new Statistics(); |
|
363 boolean entryCreated = findAndAddEntries(logTextInfo, currentComponent, |
|
364 getCurrentFile().toString(), lineNumber, stat); |
|
365 if (stat.getSeveriry("error") == 0 && recipeStatus.equals("failed")) { |
|
366 addEntry("error", currentComponent, getCurrentFile().toString(), |
|
367 lineNumber, FAILED_STATUS_MESSAGE); |
|
368 entryCreated = true; |
|
369 } |
|
370 logTextInfo = ""; |
|
371 recipeStatus = "ok"; |
|
372 return entryCreated; |
|
373 } |
|
374 } else if (tagName.equalsIgnoreCase("error") |
|
375 || tagName.equalsIgnoreCase("warning")) { |
|
376 inMainDataSection = true; |
|
377 recordText = false; |
|
378 if (currentComponent == null) { |
|
379 currentComponent = "general"; |
|
380 } |
|
381 addEntry(tagName, currentComponent, getCurrentFile().toString(), lineNumber, |
|
382 logTextInfo); |
|
383 logTextInfo = ""; |
|
384 return true; |
|
385 } else if (tagName.equalsIgnoreCase("whatlog") ) { |
|
386 inWhatLogSection = false; |
|
387 inMainDataSection = true; |
|
388 recordText = false; |
|
389 logTextInfo = ""; |
|
390 addEntry("default", currentComponent, getCurrentFile().toString(), |
|
391 streamReader.getLocation().getLineNumber(), "what log info", -1, new Metadata.WhatEntry(currentComponent, members)); |
|
392 return true; |
|
393 } else if (inWhatLogSection && !tagName.equalsIgnoreCase("export") && !tagName.equalsIgnoreCase("whatlog")) { |
|
394 if (logTextInfo.trim().length() > 0) { |
|
395 String member = SBSLogMetaDataInput.removeDriveAndBldInf(logTextInfo.trim()); |
|
396 boolean exists = (new File(logTextInfo.trim())).exists(); |
|
397 Metadata.WhatLogMember entry = new Metadata.WhatLogMember(member, exists); |
|
398 members.add(entry); |
|
399 } |
|
400 logTextInfo = ""; |
|
401 recordText = false; |
|
402 } else if (tagName.equalsIgnoreCase("clean")) { |
|
403 inMainDataSection = true; |
|
404 } else if (tagName.equalsIgnoreCase("info")) { |
|
405 inMainDataSection = true; |
|
406 recordText = false; |
|
407 if (logTextInfo != null) { |
|
408 Matcher matcher = buildTimeMatcher.matcher(logTextInfo); |
|
409 if (matcher.matches()) { |
|
410 buildTime = Integer.parseInt(matcher.group(1)); |
|
411 logger.info("Run time: " + buildTime); |
|
412 } |
|
413 } |
|
414 logTextInfo = ""; |
|
415 } |
|
416 return false; |
|
417 } |
|
418 |
|
419 |
|
420 @Override |
|
421 public void provide(ORMMetadataDB db, String logPath) { |
|
422 logger.debug("!!!!!!!!!!!!!!!!!!Logpath: " + logPath); |
|
423 db.addExecutionTime(logPath, buildTime); |
|
424 } |
|
425 } |
|
426 |
|
427 class SpecialRegex { |
|
428 private Pattern regexPattern; |
|
429 private int groupPosition; |
|
430 |
|
431 public SpecialRegex(String exp, int pos) { |
|
432 regexPattern = Pattern.compile(exp); |
|
433 groupPosition = pos; |
|
434 } |
|
435 |
|
436 public Pattern getRegexPattern() { |
|
437 return regexPattern; |
|
438 } |
|
439 |
|
440 public int getGroupPosition() { |
|
441 return groupPosition; |
|
442 } |
|
443 } |
|
444 |
|
445 |
|
446 /* This class stores the temporary Time entry which is being recorded for each data |
|
447 * at the end of the build and during isAdditionalEntry function, the time for the component |
|
448 * is updated in the database. |
|
449 */ |
|
450 class TimeEntry { |
|
451 |
|
452 private float elapsedTime; |
|
453 private String filePath; |
|
454 |
|
455 /** |
|
456 * Constructor to store the elapsedTime and the path which are to be updated to the database. |
|
457 * @param elapsedTime: time duration of the component. |
|
458 * @path of the component. |
|
459 */ |
|
460 public TimeEntry(float time, String path) { |
|
461 elapsedTime = time; |
|
462 filePath = path; |
|
463 } |
|
464 |
|
465 |
|
466 /** |
|
467 * Helper function to add time to the previous elapsed time. |
|
468 * @param time to be added to the elapsed timet. |
|
469 */ |
|
470 public void addElapsedTime(float time) { |
|
471 elapsedTime += time; |
|
472 } |
|
473 |
|
474 /** |
|
475 * Helper function to return the elapsed time |
|
476 * @return elapsed time of this time entry. |
|
477 */ |
|
478 public float getElapsedTime() { |
|
479 return elapsedTime; |
|
480 } |
|
481 |
|
482 /** |
|
483 * Helper function to return the file path of this entry |
|
484 * @return path of this time entry. |
|
485 */ |
|
486 public String getFilePath() { |
|
487 return filePath; |
|
488 } |
|
489 } |
|
490 /* This class stores the temporary category entry which is processed during |
|
491 * at the end of the build and categorized and written to the database. |
|
492 */ |
|
493 class CategoryEntry { |
|
494 |
|
495 private String text; |
|
496 private int lineNumber; |
|
497 private String fileName; |
|
498 private String severity; |
|
499 private String category; |
|
500 |
|
501 |
|
502 /** |
|
503 * Constructor of the category entry |
|
504 * @param txt - text message of the entry |
|
505 * @param ctgry - category of the entry |
|
506 * @param svrty - severity of this entry |
|
507 * @param lnNo - line number of this entry |
|
508 * @param flName - name of the file being processed. |
|
509 * @return path of this time entry. |
|
510 */ |
|
511 public CategoryEntry(String txt, String ctgry, |
|
512 String svrty, int lnNo, String flName) { |
|
513 text = txt; |
|
514 lineNumber = lnNo; |
|
515 fileName = flName; |
|
516 severity = svrty; |
|
517 category = "general"; |
|
518 if (ctgry != null) { |
|
519 category = ctgry; |
|
520 } |
|
521 } |
|
522 |
|
523 /** |
|
524 * Helper function to set the category |
|
525 * @param set the category |
|
526 */ |
|
527 void setCategory(String ctgry) { |
|
528 category = ctgry; |
|
529 } |
|
530 |
|
531 /** |
|
532 * Helper function to return the category |
|
533 * @return the category of this entry. |
|
534 */ |
|
535 String getCategory() { |
|
536 return category; |
|
537 } |
|
538 |
|
539 /** |
|
540 * Returns the logfile of this entry |
|
541 * @return logfile of this entry |
|
542 */ |
|
543 String getLogFile() { |
|
544 return fileName; |
|
545 } |
|
546 |
|
547 /** |
|
548 * Helper function returns the severity of this entry |
|
549 * @return severity of this entry |
|
550 */ |
|
551 String getSeverity() { |
|
552 return severity; |
|
553 } |
|
554 |
|
555 /** |
|
556 * Helper function returns the line number of this entry |
|
557 * @return the line number of this entry. |
|
558 */ |
|
559 |
|
560 int getLineNumber() { |
|
561 return lineNumber; |
|
562 } |
|
563 |
|
564 /** |
|
565 * Helper function returns the text message of this entry |
|
566 * @return text message of this entry |
|
567 */ |
|
568 String getText() { |
|
569 return text; |
|
570 } |
|
571 |
|
572 } |
|
573 /* This class handles the categorization of scanlog errors based on the clean log output |
|
574 * from raptor. |
|
575 */ |
|
576 class CategorizationHandler { |
|
577 |
|
578 private String currentComponent; |
|
579 private boolean isInFileTag; |
|
580 |
|
581 private HashMap<String, List <CategoryEntry>> categoryList; |
|
582 |
|
583 private List<CategoryEntry> currentList; |
|
584 |
|
585 private XMLInputFactory xmlInputFactory; |
|
586 |
|
587 private XMLStreamReader xmlStreamReader; |
|
588 |
|
589 private Logger log = Logger.getLogger(CategorizationHandler.class); |
|
590 |
|
591 /** |
|
592 * Constructor |
|
593 * @param clean log file input using which the CDATA text are categorized |
|
594 * @param list of entries to be categorized |
|
595 */ |
|
596 public CategorizationHandler(File cleanLogFile, HashMap<String, List <CategoryEntry>> ctgMap) { |
|
597 categoryList = ctgMap; |
|
598 if (cleanLogFile != null ) { |
|
599 try { |
|
600 xmlInputFactory = XMLInputFactory.newInstance(); |
|
601 xmlStreamReader = xmlInputFactory.createXMLStreamReader(cleanLogFile.toString(), |
|
602 new BufferedInputStream(new FileInputStream(cleanLogFile))); |
|
603 } catch ( XMLStreamException ex) { |
|
604 log.debug("exception while initializing stax processor",ex); |
|
605 } catch (FactoryConfigurationError er) { |
|
606 log.debug("exception while creating xmlinput factory",er); |
|
607 } catch (java.io.FileNotFoundException iex) { |
|
608 log.debug("clean log file not found:" + cleanLogFile,iex); |
|
609 } |
|
610 } |
|
611 } |
|
612 |
|
613 /** |
|
614 * Checks whether is there any entry (by checking for categorization of the recorded CDATA text) |
|
615 * @return true if there any entry that are being categorized. |
|
616 */ |
|
617 public boolean hasNext() { |
|
618 boolean generalEntriesStatus = categoryList != null && !categoryList.isEmpty(); |
|
619 boolean currentListStatus = currentList != null && ! currentList.isEmpty(); |
|
620 return generalEntriesStatus || currentListStatus; |
|
621 } |
|
622 |
|
623 /** |
|
624 * Process the start element event of XML Stream from clean log. |
|
625 * @param streamReader clean log xml stream reader to be processed |
|
626 * @return true if there are any entry to be added. |
|
627 */ |
|
628 |
|
629 public boolean startElement(XMLStreamReader streamReader) { |
|
630 String tagName = streamReader.getLocalName(); |
|
631 if (tagName.equals("clean")) { |
|
632 currentComponent = getCategory(streamReader); |
|
633 if (currentComponent != null) { |
|
634 currentComponent = SBSLogMetaDataInput.removeDriveAndBldInf(currentComponent); |
|
635 } |
|
636 } |
|
637 if (tagName.equals("file")) { |
|
638 isInFileTag = true; |
|
639 } |
|
640 return false; |
|
641 } |
|
642 |
|
643 /** |
|
644 * Process the end element event of XML Stream from clean log. |
|
645 * @param streamReader clean log xml stream reader to be processed |
|
646 * @return true if there are any entry to be added. |
|
647 */ |
|
648 |
|
649 public boolean endElement (XMLStreamReader streamReader) { |
|
650 String tagName = streamReader.getLocalName(); |
|
651 if (tagName.equals("file")) { |
|
652 isInFileTag = false; |
|
653 } |
|
654 return false; |
|
655 } |
|
656 |
|
657 /** |
|
658 * Internal function to find bld inf from the component |
|
659 * @param streamReader clean log xml stream reader to be processed |
|
660 * @return the bld.inf attribute. |
|
661 */ |
|
662 private String getCategory(XMLStreamReader streamReader) { |
|
663 int count = streamReader.getAttributeCount() ; |
|
664 for (int i = 0 ; i < count ; i++) { |
|
665 if ( streamReader.getAttributeLocalName(i).equals("bldinf") ) { |
|
666 return streamReader.getAttributeValue(i); |
|
667 } |
|
668 } |
|
669 return null; |
|
670 } |
|
671 |
|
672 /** |
|
673 * Internal function to find the CDATA text of the file attribute. |
|
674 * @param streamReader clean log xml stream reader to be processed |
|
675 * @return the CDATA text of <file> tag. |
|
676 */ |
|
677 private String characters(XMLStreamReader xmlStreamReader) { |
|
678 if (isInFileTag) { |
|
679 return xmlStreamReader.getText().toLowerCase(); |
|
680 } |
|
681 return null; |
|
682 } |
|
683 |
|
684 /** |
|
685 * Gets the entry which matches the input path. For each line of <file> tag attribute, the entry list |
|
686 * is compared with that and if there is any match, then it returns the entry from the list, which |
|
687 * is being mtached. |
|
688 * @param path for which matching entry is looked for. |
|
689 * @return entry which matched the path from the clean log file. |
|
690 */ |
|
691 private List<CategoryEntry> getEntry(String path) { |
|
692 Set<String> categorySet = categoryList.keySet(); |
|
693 for (String key : categorySet) { |
|
694 if (path.toLowerCase().equals(key)) { |
|
695 |
|
696 List<CategoryEntry> entry = categoryList.get(key); |
|
697 categoryList.remove(key); |
|
698 return entry; |
|
699 } |
|
700 } |
|
701 return null; |
|
702 } |
|
703 |
|
704 /** |
|
705 * Internal function to update the category entries of the list. |
|
706 * @param categoryList for which the category. |
|
707 * @param category which is to be updated to the list. |
|
708 */ |
|
709 private void updateCategoryEntries(List<CategoryEntry> categoryList, String category) { |
|
710 for (CategoryEntry entry : categoryList) { |
|
711 entry.setCategory(category); |
|
712 } |
|
713 } |
|
714 |
|
715 /** |
|
716 * Gets the next entry from the stream based on categorization. |
|
717 * @return the category entry which is identified as categorized entry. |
|
718 */ |
|
719 public CategoryEntry getNext() throws XMLStreamException { |
|
720 try { |
|
721 if (currentList != null && !currentList.isEmpty()) { |
|
722 CategoryEntry entry = currentList.get(0); |
|
723 currentList.remove(0); |
|
724 return entry; |
|
725 } |
|
726 if (xmlStreamReader != null ) { |
|
727 while (xmlStreamReader.hasNext()) { |
|
728 int eventType = xmlStreamReader.next(); |
|
729 switch (eventType) { |
|
730 case XMLEvent.START_ELEMENT: |
|
731 startElement(xmlStreamReader); |
|
732 break; |
|
733 case XMLEvent.END_ELEMENT: |
|
734 endElement(xmlStreamReader); |
|
735 break; |
|
736 case XMLEvent.CHARACTERS: |
|
737 String path = characters(xmlStreamReader); |
|
738 if (path != null ) { |
|
739 currentList = getEntry(path); |
|
740 if (currentList != null && !currentList.isEmpty()) { |
|
741 if (currentComponent != null) { |
|
742 updateCategoryEntries(currentList, currentComponent); |
|
743 CategoryEntry entry = (CategoryEntry)currentList.remove(0); |
|
744 return entry; |
|
745 } |
|
746 } |
|
747 } |
|
748 break; |
|
749 default: |
|
750 break; |
|
751 } |
|
752 } |
|
753 if (xmlStreamReader != null) { |
|
754 close(); |
|
755 } |
|
756 } |
|
757 Set<String> categorySet = categoryList.keySet(); |
|
758 for (String key : categorySet) { |
|
759 currentList = categoryList.remove(key); |
|
760 if (currentList != null && !currentList.isEmpty()) { |
|
761 updateCategoryEntries(currentList, "general"); |
|
762 CategoryEntry entry = (CategoryEntry)currentList.remove(0); |
|
763 return entry; |
|
764 } |
|
765 } |
|
766 } catch ( XMLStreamException ex) { |
|
767 log.debug("exception in categorization",ex); |
|
768 throw ex; |
|
769 } |
|
770 return null; |
|
771 } |
|
772 /** |
|
773 * Internal function to close the clean log file stream |
|
774 */ |
|
775 private void close() { |
|
776 try { |
|
777 if (xmlStreamReader != null) { |
|
778 xmlStreamReader.close(); |
|
779 xmlStreamReader = null; |
|
780 } |
|
781 } catch (XMLStreamException ex) { |
|
782 log.debug("exception while closing xml stream",ex); |
|
783 } |
|
784 |
|
785 } |
|
786 } |
|