View Javadoc

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  public class CoberturaLineStatMerge extends BaseStatMerge {
62      private static final String COBERTURA_LINE = "cobertura-line";
63  
64      private int totalLineRate = 0;
65  
66      private int totalBranchRate = 0;
67  
68      private boolean skipCurrentElement = false;
69  
70      // ~ Methods
71      // ------------------------------------------------------------------------
72  
73      /**
74       * @return cobertura-line
75       */
76      public String getType() {
77          return COBERTURA_LINE;
78      }
79  
80      protected final String getSummaryTag() {
81          return "coverage";
82      }
83  
84      private Object getFileTag() {
85          return "class";
86      }
87  
88      /**
89       * 
90       * @return "filename" the attribute tag for file.
91       */
92      private String getFileNameAttribute() {
93          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         String local = localname;
115 
116         if ("".equals(local)) {
117             local = qualifiedname;
118         }
119 
120         // if (!isQuiet()) {
121         // getTaskLogger().log("Start :" + local);
122         // }
123 
124         if (getSummaryTag().equals(local)) {
125             final String lineRate = Util.getAttributeValue(attrs, "line-rate",
126                     isQuiet(), getTaskLogger());
127             final String branchRate = Util.getAttributeValue(attrs,
128                     "branch-rate", isQuiet(), getTaskLogger());
129             totalLineRate = new BigDecimal(lineRate).movePointRight(2)
130                     .intValue();
131             totalBranchRate = new BigDecimal(branchRate).movePointRight(2)
132                     .intValue();
133         } else if (getFileTag().equals(local)) {
134             // check if it is an inner class... and if so, leave it!!
135             String className = Util.getAttributeValue(attrs, "name", isQuiet(),
136                     getTaskLogger());
137 
138             if (className != null && className.indexOf('$') > 0) {
139                 skipCurrentElement = true;
140                 return;
141             }
142 
143             // this is the start of a new file.
144             resetFileStatistics();
145             incrementFileCount(1);
146             setFileName(attrs);
147 
148             final String lineRate = Util.getAttributeValue(attrs, "line-rate",
149                     isQuiet(), getTaskLogger());
150             final String branchRate = Util.getAttributeValue(attrs,
151                     "branch-rate", isQuiet(), getTaskLogger());
152 
153             if (!isQuiet()) {
154                 getTaskLogger().log(
155                         "lineRate=" + lineRate + " branchRate=" + branchRate);
156             }
157 
158             if (getType().equals(COBERTURA_LINE)) {
159                 int lineAsPercent = new BigDecimal(lineRate).movePointRight(2)
160                         .intValue();
161                 addFileStatistics(lineAsPercent);
162             } else {
163                 // branches
164                 int lineAsPercent = new BigDecimal(branchRate)
165                         .movePointRight(2).intValue();
166                 addFileStatistics(lineAsPercent);
167             }
168         }
169     }
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         if (getFileTag().equals(qualifiedname)) {
192             if (!skipCurrentElement) {
193                 addNewResults();
194             } else {
195                 skipCurrentElement = false;
196             }
197         }
198     }
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         String fileName = Util.getAttributeValue(att, getFileNameAttribute(),
208                 isQuiet(), getTaskLogger());
209 
210         // if (!isQuiet()) {
211         // getTaskLogger().log("File:" + fileName);
212         // }
213 
214         fileName = FilenameUtil.trimFilename(fileName, getSrcDir());
215 
216         if (!isQuiet()) {
217             getTaskLogger().log(
218                     "setCurrentFileName FILE [" + fileName + "] srcDir ["
219                             + getSrcDir() + "]");
220         }
221 
222         setCurrentFile(fileName);
223     }
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         if (getType().equals(COBERTURA_LINE)) {
232             return totalLineRate;
233         } else {
234             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         StringBuffer buf = new StringBuffer();
244         InputStream reader = source.getByteStream();
245         int i = -1;
246         // the InputSource could be either an InputStream or a Reader
247         // we need to cope with both...
248         if (reader != null) {
249             do {
250                 try {
251                     i = reader.read();
252                 } catch (IOException e) {
253                     getTaskLogger().log(e.toString());
254                 }
255                 buf.append((char) i);
256             } while (i >= 0);
257         } else {
258             Reader rd = source.getCharacterStream();
259             do {
260                 try {
261                     i = rd.read();
262                 } catch (IOException e) {
263                     getTaskLogger().log(e.toString());
264                 }
265                 buf.append((char) i);
266             } while (i >= 0);
267         }
268         int idx = buf.indexOf("<coverage");
269         if (idx >= 0) {
270             buf = buf.delete(0, idx);
271         }
272 
273         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  */