| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| CoberturaLineStatMerge | 
 | 
 | 3.0;3 | 
| 1 |  //////////////////////////////////////////////////////////////////////////////// | |
| 2 |  // | |
| 3 |  //                  ObjectLab is sponsoring QALab | |
| 4 |  //  | |
| 5 |  // Based in London, we are world leaders in the design and development  | |
| 6 |  // of bespoke applications for the Securities Financing markets. | |
| 7 |  //  | |
| 8 |  // <a href="http://www.objectlab.co.uk/open">Click here to learn more</a> | |
| 9 |  //           ___  _     _           _   _          _ | |
| 10 |  //          / _ \| |__ (_) ___  ___| |_| |    __ _| |__ | |
| 11 |  //         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \ | |
| 12 |  //         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) | | |
| 13 |  //          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/ | |
| 14 |  //                   |__/ | |
| 15 |  // | |
| 16 |  //                   http://www.ObjectLab.co.uk | |
| 17 |  // --------------------------------------------------------------------------- | |
| 18 |  // | |
| 19 |  //QALab is released under the GNU General Public License. | |
| 20 |  // | |
| 21 |  //QALab: Collects QA Statistics from your build over time. | |
| 22 |  //2005+, ObjectLab Ltd | |
| 23 |  // | |
| 24 |  //This library is free software; you can redistribute it and/or | |
| 25 |  //modify it under the terms of the GNU General Public | |
| 26 |  //License as published by the Free Software Foundation; either | |
| 27 |  //version 2.1 of the License, or (at your option) any later version. | |
| 28 |  // | |
| 29 |  //This library is distributed in the hope that it will be useful, | |
| 30 |  //but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 31 |  //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | |
| 32 |  //General Public License for more details. | |
| 33 |  // | |
| 34 |  //You should have received a copy of the GNU General Public | |
| 35 |  //License along with this library; if not, write to the Free Software | |
| 36 |  //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | |
| 37 |  // | |
| 38 |  //////////////////////////////////////////////////////////////////////////////// | |
| 39 |  package net.objectlab.qalab.parser; | |
| 40 | ||
| 41 |  import java.io.IOException; | |
| 42 |  import java.io.InputStream; | |
| 43 |  import java.io.Reader; | |
| 44 |  import java.io.StringReader; | |
| 45 |  import java.math.BigDecimal; | |
| 46 | ||
| 47 |  import net.objectlab.qalab.util.FilenameUtil; | |
| 48 |  import net.objectlab.qalab.util.Util; | |
| 49 | ||
| 50 |  import org.xml.sax.Attributes; | |
| 51 |  import org.xml.sax.InputSource; | |
| 52 |  import org.xml.sax.SAXException; | |
| 53 | ||
| 54 |  /** | |
| 55 |   * This class is able to read the XML output from Cobertura (LINE INFORMATION) | |
| 56 |   * and integrate the violation results into our "qalab" xml format. | |
| 57 |   *  | |
| 58 |   * @author Benoit Xhenseval | |
| 59 |   * @version $Revision$ | |
| 60 |   */ | |
| 61 | 6 | public class CoberturaLineStatMerge extends BaseStatMerge { | 
| 62 | private static final String COBERTURA_LINE = "cobertura-line"; | |
| 63 | ||
| 64 | 6 | private int totalLineRate = 0; | 
| 65 | ||
| 66 | 6 | private int totalBranchRate = 0; | 
| 67 | ||
| 68 | 6 | private boolean skipCurrentElement = false; | 
| 69 | ||
| 70 |      // ~ Methods | |
| 71 |      // ------------------------------------------------------------------------ | |
| 72 | ||
| 73 |      /** | |
| 74 |       * @return cobertura-line | |
| 75 |       */ | |
| 76 |      public String getType() { | |
| 77 | 81 |          return COBERTURA_LINE; | 
| 78 | } | |
| 79 | ||
| 80 | protected final String getSummaryTag() { | |
| 81 | 15714 | return "coverage"; | 
| 82 | } | |
| 83 | ||
| 84 |      private Object getFileTag() { | |
| 85 | 31422 | return "class"; | 
| 86 | } | |
| 87 | ||
| 88 |      /** | |
| 89 |       *  | |
| 90 |       * @return "filename" the attribute tag for file. | |
| 91 |       */ | |
| 92 |      private String getFileNameAttribute() { | |
| 93 | 150 | return "filename"; | 
| 94 | } | |
| 95 | ||
| 96 |      /** | |
| 97 |       * At the start of a new element, capture the filename and if the element is | |
| 98 |       * a result one, create a SingleStat to store for the given type. | |
| 99 |       *  | |
| 100 |       * @param ignoreNamespaceURI | |
| 101 |       *            ignore (present for interface implementation). | |
| 102 |       * @param localname | |
| 103 |       *            name of the current element. | |
| 104 |       * @param qualifiedname | |
| 105 |       *            element name. | |
| 106 |       * @param attrs | |
| 107 |       *            the XML attribute of the current element. | |
| 108 |       * @throws SAXException | |
| 109 |       *             any SAX issue | |
| 110 |       */ | |
| 111 | public final void startElement(final String ignoreNamespaceURI, // NOPMD | |
| 112 | final String localname, final String qualifiedname, | |
| 113 | final Attributes attrs) throws SAXException { | |
| 114 | 15714 | String local = localname; | 
| 115 | ||
| 116 | 15714 | if ("".equals(local)) { | 
| 117 | 15714 | local = qualifiedname; | 
| 118 | } | |
| 119 | ||
| 120 |          // if (!isQuiet()) { | |
| 121 |          // getTaskLogger().log("Start :" + local); | |
| 122 |          // } | |
| 123 | ||
| 124 | 15714 |          if (getSummaryTag().equals(local)) { | 
| 125 | 6 | final String lineRate = Util.getAttributeValue(attrs, "line-rate", | 
| 126 | isQuiet(), getTaskLogger()); | |
| 127 | 6 |              final String branchRate = Util.getAttributeValue(attrs, | 
| 128 |                      "branch-rate", isQuiet(), getTaskLogger()); | |
| 129 | 6 |              totalLineRate = new BigDecimal(lineRate).movePointRight(2) | 
| 130 | .intValue(); | |
| 131 | 6 |              totalBranchRate = new BigDecimal(branchRate).movePointRight(2) | 
| 132 | .intValue(); | |
| 133 | 6 | } else if (getFileTag().equals(local)) { | 
| 134 |              // check if it is an inner class... and if so, leave it!! | |
| 135 | 150 |              String className = Util.getAttributeValue(attrs, "name", isQuiet(), | 
| 136 | getTaskLogger()); | |
| 137 | ||
| 138 | 150 | if (className != null && className.indexOf('$') > 0) { | 
| 139 | 0 |                  skipCurrentElement = true; | 
| 140 | 0 |                  return; | 
| 141 | } | |
| 142 | ||
| 143 |              // this is the start of a new file. | |
| 144 | 150 | resetFileStatistics(); | 
| 145 | 150 | incrementFileCount(1); | 
| 146 | 150 | setFileName(attrs); | 
| 147 | ||
| 148 | 150 | final String lineRate = Util.getAttributeValue(attrs, "line-rate", | 
| 149 | isQuiet(), getTaskLogger()); | |
| 150 | 150 |              final String branchRate = Util.getAttributeValue(attrs, | 
| 151 |                      "branch-rate", isQuiet(), getTaskLogger()); | |
| 152 | ||
| 153 | 150 |              if (!isQuiet()) { | 
| 154 | 150 | getTaskLogger().log( | 
| 155 | "lineRate=" + lineRate + " branchRate=" + branchRate); | |
| 156 | } | |
| 157 | ||
| 158 | 150 |              if (getType().equals(COBERTURA_LINE)) { | 
| 159 | 75 | int lineAsPercent = new BigDecimal(lineRate).movePointRight(2) | 
| 160 | .intValue(); | |
| 161 | 75 | addFileStatistics(lineAsPercent); | 
| 162 | 75 |              } else { | 
| 163 |                  // branches | |
| 164 | 75 | int lineAsPercent = new BigDecimal(branchRate) | 
| 165 | .movePointRight(2).intValue(); | |
| 166 | 75 | addFileStatistics(lineAsPercent); | 
| 167 | } | |
| 168 | } | |
| 169 | 15714 | } | 
| 170 | ||
| 171 |      /** | |
| 172 |       * At the end of an element, check if it is a file one and add the results | |
| 173 |       * found. | |
| 174 |       *  | |
| 175 |       * @param ignoreNamespaceURI | |
| 176 |       *            ignore (present for interface implementation). | |
| 177 |       * @param ignoreSimplename | |
| 178 |       *            ignore (present for interface implementation). | |
| 179 |       * @param qualifiedname | |
| 180 |       *            the name of the element. | |
| 181 |       * @throws SAXException | |
| 182 |       *             any SAX issue | |
| 183 |       */ | |
| 184 | public final void endElement(final String ignoreNamespaceURI, // NOPMD | |
| 185 | final String ignoreSimplename, final String qualifiedname) // NOPMD | |
| 186 |              throws SAXException { | |
| 187 |          // if (!isQuiet()) { | |
| 188 |          // getTaskLogger().log("End :" + qualifiedname); | |
| 189 |          // } | |
| 190 | ||
| 191 | 15714 |          if (getFileTag().equals(qualifiedname)) { | 
| 192 | 150 |              if (!skipCurrentElement) { | 
| 193 | 150 | addNewResults(); | 
| 194 | 150 |              } else { | 
| 195 | 0 |                  skipCurrentElement = false; | 
| 196 | } | |
| 197 | } | |
| 198 | 15714 | } | 
| 199 | ||
| 200 |      /** | |
| 201 |       * set the file name from the attributes from Findbugs XML. | |
| 202 |       *  | |
| 203 |       * @param att | |
| 204 |       *            xml attributes | |
| 205 |       */ | |
| 206 | protected void setFileName(final Attributes att) { | |
| 207 | 150 | String fileName = Util.getAttributeValue(att, getFileNameAttribute(), | 
| 208 | isQuiet(), getTaskLogger()); | |
| 209 | ||
| 210 |          // if (!isQuiet()) { | |
| 211 |          // getTaskLogger().log("File:" + fileName); | |
| 212 |          // } | |
| 213 | ||
| 214 | 150 | fileName = FilenameUtil.trimFilename(fileName, getSrcDir()); | 
| 215 | ||
| 216 | 150 |          if (!isQuiet()) { | 
| 217 | 150 | getTaskLogger().log( | 
| 218 | "setCurrentFileName FILE [" + fileName + "] srcDir [" | |
| 219 |                              + getSrcDir() + "]"); | |
| 220 | } | |
| 221 | ||
| 222 | 150 | setCurrentFile(fileName); | 
| 223 | 150 | } | 
| 224 | ||
| 225 |      /** | |
| 226 |       * For Cobertura the total statistics is the average of coverage, ie sum of | |
| 227 |       * all percentages divided by the TOTAL number of files (ie we do not report | |
| 228 |       * ZERO % coverage but they should count). | |
| 229 |       */ | |
| 230 | public int getTotalStatistics() { | |
| 231 | 12 |          if (getType().equals(COBERTURA_LINE)) { | 
| 232 | 6 |              return totalLineRate; | 
| 233 |          } else { | |
| 234 | 6 |              return totalBranchRate; | 
| 235 | } | |
| 236 | } | |
| 237 | ||
| 238 |      /** | |
| 239 |       * This is required to get rid of the SYSTEM DTD otherwise one cannot parse | |
| 240 |       * coverage.xml behind most firewalls or offline. | |
| 241 |       */ | |
| 242 |      protected InputSource preProcessSource(InputSource source) { | |
| 243 | 6 |          StringBuffer buf = new StringBuffer(); | 
| 244 | 6 | InputStream reader = source.getByteStream(); | 
| 245 | 6 |          int i = -1; | 
| 246 |          // the InputSource could be either an InputStream or a Reader | |
| 247 |          // we need to cope with both... | |
| 248 | 6 | if (reader != null) { | 
| 249 |              do { | |
| 250 |                  try { | |
| 251 | 911358 | i = reader.read(); | 
| 252 | 0 |                  } catch (IOException e) { | 
| 253 | 0 |                      getTaskLogger().log(e.toString()); | 
| 254 | 911358 | } | 
| 255 | 911358 |                  buf.append((char) i); | 
| 256 | 911358 |              } while (i >= 0); | 
| 257 | 6 |          } else { | 
| 258 | 0 |              Reader rd = source.getCharacterStream(); | 
| 259 |              do { | |
| 260 |                  try { | |
| 261 | 0 |                      i = rd.read(); | 
| 262 | 0 |                  } catch (IOException e) { | 
| 263 | 0 |                      getTaskLogger().log(e.toString()); | 
| 264 | 0 |                  } | 
| 265 | 0 |                  buf.append((char) i); | 
| 266 | 0 |              } while (i >= 0); | 
| 267 | } | |
| 268 | 6 | int idx = buf.indexOf("<coverage"); | 
| 269 | 6 |          if (idx >= 0) { | 
| 270 | 6 | buf = buf.delete(0, idx); | 
| 271 | } | |
| 272 | ||
| 273 | 6 | return new InputSource(new StringReader(buf.toString())); | 
| 274 | } | |
| 275 | } | |
| 276 |  /* | |
| 277 |   *                   ObjectLab is sponsoring QALab | |
| 278 |   *  | |
| 279 |   * Based in London, we are world leaders in the design and development  | |
| 280 |   * of bespoke applications for the securities financing markets. | |
| 281 |   *  | |
| 282 |   * <a href="http://www.objectlab.co.uk/open">Click here to learn more about us</a> | |
| 283 |   *           ___  _     _           _   _          _ | |
| 284 |   *          / _ \| |__ (_) ___  ___| |_| |    __ _| |__ | |
| 285 |   *         | | | | '_ \| |/ _ \/ __| __| |   / _` | '_ \ | |
| 286 |   *         | |_| | |_) | |  __/ (__| |_| |__| (_| | |_) | | |
| 287 |   *          \___/|_.__// |\___|\___|\__|_____\__,_|_.__/ | |
| 288 |   *                   |__/ | |
| 289 |   * | |
| 290 |   *                     www.ObjectLab.co.uk | |
| 291 |   */ |