buildframework/helium/sf/java/quality/src/com/nokia/helium/quality/ant/taskdefs/CMTSummaryTask.java
/*
* Copyright (c) 2007-2008 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
package com.nokia.helium.quality.ant.taskdefs;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
/**
* This Task searches the index.html files created by CMT and looks for the summary values at the
* end of the file e.g. Files: 12 LOCphy: 137. and takes the info and places it in an XMl file ready
* to be sent to diamonds. The Xml file is placed in the diamonds folder in the output folder and
* these files are then sent to diamonds when the build is finished soall we have to do is create
* the file in the correct folder.
*
* <pre>
* <hlm:cmtmetadatainput
* diamondsHeaderFileName="C:\brtaylor\1\diamonds_header.xml"
* diamondsFooterFileName="C:\brtaylor\1\diamonds_footer.xml"
* outptuFile="Z:\output\diamonds/cmt_summary_componentName_1.xml/"
* inputFile="Z:\output\logs/minibuild_ido_0.0.03_test_cmt_componentName1_cmt/CMTHTML/index.html/>
* </pre>
*
* @ant.task name="cmtsummarytask" category="Quality"
*/
public class CMTSummaryTask extends Task {
// The following 2 variables are indexes to the SEARCH_TERMS_ARRAY
/** Index to the searched for text */
private static final int INPUT_TEXT_INDEX = 0;
/** Index to the text to write to the xml file */
private static final int OUTPUT_ELEMENT_INDEX = 1;
/**
* this array contains the text to be searched for in the inputFile (1st element) and the text
* to be written to the .xml output file (2nd element)
*/
private static final String[][] SEARCH_TERMS_ARRAY = {
// 1st elem 2nd elem
{ "Files:", "files" }, { "LOCphy:", "locphy" }, { "LOCbl:", "locbl" },
{ "LOCpro:", "locpro" }, { "LOCcom:", "loccom" }, { "v(G) :", "vg" },
{ "MI without comments :", "mi_wo_comments" },
{ "MI comment weight :", "mi_comment_weight" }, { "MI:", "mi" } };
/** always accesses the 1st group of the matcher */
private static int matcherGroupNum; // default init is 0
/** indexes to the SEARCH_TERMS_ARRAY */
private int arrayIndex;
private int sizeArray = SEARCH_TERMS_ARRAY.length;
/** the file containing the CMT summary data */
private String inputFile;
/** name of file to write the output to */
private String outputFile;
/** each line of the input file is read into this */
private String line;
/** the regex for a string of digits */
private Pattern digitPattern = Pattern.compile("\\d+");
/** file descriptor for the input file */
private BufferedReader inputFileReader;
/** file handler used to write the summary numbers to the output file **/
private BufferedWriter output; // default init = null
/** tells the main method whether it should be looking for digist or text */
private boolean lineStartsWithDigits; // default init = false
/**
* file name of the default diamonds XML file header part (1st few lines) used so not writing
* the XML text here
*/
private String diamondsHeaderFileName;
/**
* file name of the default diamonds XML file footer part (last line) used so not writing the
* XML text here
*/
private String diamondsFooterFileName;
/**
* @param outputFile set the output file name
* @ant.required
*/
public void setOutputFile(String outputFile) {
this.outputFile = outputFile;
}
/**
* @return the outputFile the output file name
*/
public String getOutputFile() {
return outputFile;
}
/**
* @return the inputFile
*/
public String getinputFile() {
return inputFile;
}
/**
* @param inputFile the name of file to scan and extract data from
* @ant.required
*/
public void setinputFile(String inputFile) {
this.inputFile = inputFile;
}
/**
* @param diamondsFooterFileName set the diamonds footer file name
* @ant.required
*/
public void setdiamondsFooterFileName(String diamondsFooterFileName) {
this.diamondsFooterFileName = diamondsFooterFileName;
}
/**
* @return the diamondsFooterFileName the diamonds footer file name
*/
public String getdiamondsFooterFileName() {
return diamondsFooterFileName;
}
/**
* @param diamondsHeaderFileName set the diamonds header file name
* @ant.required
*/
public void setdiamondsHeaderFileName(String diamondsHeaderFileName) {
this.diamondsHeaderFileName = diamondsHeaderFileName;
}
/**
* @return the diamondsFooterFileName the diamonds footer file name
*/
public String getdiamondsHeaderFileName() {
return diamondsHeaderFileName;
}
/** the main part of the code - the method that is called */
public void execute() {
log("CMTSummaryTask execute method with input file : " + inputFile, Project.MSG_ERR);
boolean inputFileFound = true;
BufferedReader diamondsHeaderFile;
BufferedReader diamondsFooterFile;
log("output File is " + getOutputFile(), Project.MSG_ERR);
try {
// open the file with the CMT results init
inputFileReader = new BufferedReader(new FileReader(inputFile));
}
catch (FileNotFoundException exc) {
log("FileNotFoundException while getting the input file. : " + inputFile + " "
+ exc.getMessage(), Project.MSG_ERR);
inputFileFound = false; // stops an empty output file being created.
}
if (inputFileFound) {
try {
// write the title stuff for the XML diamonds schema
output = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(getOutputFile()), "UTF8"));
}
catch (FileNotFoundException exc) {
log("FileNotFoundException while getting the output file. : " + getOutputFile()
+ " " + exc.getMessage(), Project.MSG_ERR);
}
catch (UnsupportedEncodingException exc) {
// We are Ignoring the errors as no need to fail the build.
log("UnsupportedEncodingException while creating the output file : "
+ getOutputFile() + " " + exc.getMessage(), Project.MSG_ERR);
}
catch (SecurityException exc) {
// We are Ignoring the errors as no need to fail the build.
log("SecurityException while creating the output file : " + getOutputFile() + " "
+ exc.getMessage(), Project.MSG_ERR);
}
if (output != null) {
// managed to open the output file
try {
// write the initial XML text to the file
String tempLine;
diamondsHeaderFile = null;
diamondsHeaderFile = new BufferedReader(new FileReader(getdiamondsHeaderFileName()));
while ((tempLine = diamondsHeaderFile.readLine()) != null) {
output.write(tempLine);
output.newLine();
}
diamondsHeaderFile.close();
output.write(" <cmt>\r\n");
// CheckStyle:InnerAssignment OFF
// process each of the searchterms
while ((arrayIndex < sizeArray)
&& ((line = inputFileReader.readLine()) != null)) {
findTextAndOutput(); // read finput file and write the output
}
// CheckStyle:InnerAssignment ON
// write the end of file text
output.write(" </cmt>");
output.newLine();
diamondsFooterFile = null;
diamondsFooterFile = new BufferedReader(new FileReader(getdiamondsFooterFileName()));
while ((tempLine = diamondsFooterFile.readLine()) != null) {
output.write(tempLine);
output.newLine();
}
output.close(); // close the output file
diamondsFooterFile.close();
}
catch (FileNotFoundException exc) {
log("FileNotFoundException while getting the diamonds header file : "
+ getdiamondsHeaderFileName() + " " + exc.getMessage(), Project.MSG_ERR);
}
catch (IOException exc) {
// We are Ignoring the errors as no need to fail the build.
log("IOException : " + getdiamondsHeaderFileName() + " output file = "
+ getOutputFile() + " " + exc.getMessage(), Project.MSG_ERR);
}
catch (IllegalArgumentException exc) {
// We are Ignoring the errors as no need to fail the build.
log("IllegalArgumentException : " + getdiamondsHeaderFileName()
+ " output file = " + getOutputFile() + " " + exc.getMessage(), Project.MSG_ERR);
}
}
else {
log("Error: no output File available ", Project.MSG_ERR);
}
}
else {
log("Error: no input File available ", Project.MSG_ERR);
}
}
/**
* This is the function that performs the actual file searches and writes the number following
* the searched for text to the output XML file
*/
private void findTextAndOutput() {
final int colonSkip = 2;
byte[] lineBytes = null;
int buffLen;
int lineLen;
int serchTermTextLen;
int spacesLen;
try {
lineLen = line.length();
while ((lineLen > 0) && (arrayIndex < sizeArray)) {
// Process each of the groups of chars in a line
if (line.startsWith(SEARCH_TERMS_ARRAY[arrayIndex][INPUT_TEXT_INDEX])) {
// Found the CMT data type we are looking for so look fo r the digits now
serchTermTextLen = SEARCH_TERMS_ARRAY[arrayIndex][INPUT_TEXT_INDEX].length();
buffLen = writeToOutput();
if ((buffLen > 0) && (arrayIndex < sizeArray)) {
// Skip over the digits so can get the next searchterm near start of line
line = line.substring(line.indexOf(':') + colonSkip + buffLen);
spacesLen = removeAnySpaces();
// Decrease line length for the while loop
lineLen = lineLen - (buffLen + serchTermTextLen + spacesLen);
}
else {
// Didn't find the digits so probably at the end of the line and the digits
// are on the next line
// Convert the line to bytes so we can check for a specific Character
lineBytes = line.getBytes("UTF-8");
int sbLen = lineBytes.length;
// The last real char (i.e. not the EOL) should be '=' if the digits are on
// the next line
if (lineBytes[sbLen - 1] == '=') {
// found the '=' so read the next line in
lineStartsWithDigits = true;
lineLen = 0;
}
else {
log("can't find the '=' at end of line ", Project.MSG_ERR);
lineLen = 0;
}
}
}
else if (lineStartsWithDigits) { // probably got a line with digits on
buffLen = writeToOutput(); // definitely got a line with digits on
lineStartsWithDigits = false;
if ((buffLen > 0) && (arrayIndex < sizeArray)) {
// Now need to get rid of the digits and get to the next
// none digits char
line = line.substring(buffLen);
spacesLen = removeAnySpaces();
// decrease line length for the while loop
lineLen = lineLen - (buffLen + spacesLen);
}
else {
lineLen = 0;
log("can't find the digits at beg of line ", Project.MSG_ERR);
}
}
else {
lineLen = 0;
}
}
}
catch (IOException exc) {
log("IOException Error searching : " + exc.getMessage(), Project.MSG_ERR);
}
}
private int writeToOutput() throws IOException {
String buffer;
int buffLen;
Matcher componentMatch = digitPattern.matcher(line);
if (componentMatch.find()) {
// Found the digits after the search term
buffer = componentMatch.group(matcherGroupNum);
// Write the XML formated <files>nn</files> to the output file (plus the other)
output.write(" <" + SEARCH_TERMS_ARRAY[arrayIndex][OUTPUT_ELEMENT_INDEX] + ">");
output.write(buffer);
output.write("</" + SEARCH_TERMS_ARRAY[arrayIndex++][OUTPUT_ELEMENT_INDEX] + ">");
output.newLine();
buffLen = buffer.length();
}
else {
buffLen = 0;
log("can't find digits may be '=' at end of line ", Project.MSG_ERR);
}
return buffLen;
}
private int removeAnySpaces() throws UnsupportedEncodingException {
byte[] lineBytes;
int num = 0;
int len = line.length();
// Convert the line to bytes so we can check for a specific Character
lineBytes = line.getBytes("UTF-8");
// While there are still spaces at the front of the line shuffle the line along to get rid
// of them
while ((lineBytes[num++] == ' ') && (len > 0)) {
// Remove 1 space at front of line
line = line.substring(1);
len--;
}
return num;
}
}