buildframework/helium/sf/java/metadata/src/com/nokia/helium/metadata/ant/types/SBSLogMetaDataInput.java
changeset 628 7c4a911dc066
parent 588 c7c26511138f
child 629 541af5ee3ed9
equal deleted inserted replaced
588:c7c26511138f 628:7c4a911dc066
     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  * &lt;hlm:metadatafilterset id="sbs.metadata.filter"&gt;
       
    40  *    &lt;metadatafilterset filterfile="common.csv" /&gt;
       
    41  * &lt;/hlm:metadatafilterset&gt;
       
    42  * 
       
    43  * &lt;hlm:sbsmetadatainput &gt
       
    44  *    &lt;fileset dir="${project.dir}/../data/"&gt;
       
    45  *        &lt;include name="*compile.log"/&gt;
       
    46  *    &lt;/fileset&gt;
       
    47  *    &lt;metadatafilterset refid="sbs.metadata.filter" /&gt;
       
    48  * &lt;/hlm:sbsmetadatainput&gt;
       
    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 }