001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *  
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017     
018    package org.apache.geronimo.mavenplugins.testsuite.report;
019    
020    import org.xml.sax.Attributes;
021    import org.xml.sax.SAXException;
022    import org.xml.sax.helpers.DefaultHandler;
023    
024    import javax.xml.parsers.ParserConfigurationException;
025    import javax.xml.parsers.SAXParser;
026    import javax.xml.parsers.SAXParserFactory;
027    import java.io.File;
028    import java.io.IOException;
029    import java.text.NumberFormat;
030    import java.text.ParseException;
031    import java.util.ArrayList;
032    import java.util.Collections;
033    import java.util.List;
034    import java.util.Map;
035    import java.util.StringTokenizer;
036    
037    public class ReportTestSuite
038        extends DefaultHandler
039    {
040        private List testCases;
041    
042        private int numberOfErrors;
043    
044        private int numberOfFailures;
045        
046        private int numberOfSkipped;
047    
048        private int numberOfTests;
049    
050        private String name;
051    
052        private String fullClassName;
053    
054        private String packageName;
055    
056        private float timeElapsed;
057    
058        private NumberFormat numberFormat = NumberFormat.getInstance();
059    
060        /**
061         * @noinspection StringBufferField
062         */
063        private StringBuffer currentElement;
064    
065        private ReportTestCase testCase;
066    
067        public void parse( String xmlPath )
068            throws ParserConfigurationException, SAXException, IOException
069        {
070            SAXParserFactory factory = SAXParserFactory.newInstance();
071    
072            SAXParser saxParser = factory.newSAXParser();
073    
074            saxParser.parse( new File( xmlPath ), this );
075        }
076    
077        
078        private int getAttributeAsInt( Attributes attributes, String name )
079        {
080            // may or may not exist
081            String valueAsString = attributes.getValue( name );
082            if ( valueAsString != null )
083            {
084                return Integer.parseInt( valueAsString );
085            }
086            return 0;
087        }
088        
089        public void startElement( String uri, String localName, String qName, Attributes attributes )
090            throws SAXException
091        {
092            try
093            {
094                if ( "testsuite".equals( qName ) )
095                {
096                    numberOfErrors = getAttributeAsInt( attributes, "errors" );
097                    numberOfFailures = getAttributeAsInt( attributes, "failures" );
098                    numberOfSkipped = getAttributeAsInt( attributes, "skipped" );
099                    numberOfTests = getAttributeAsInt( attributes, "tests" );
100    
101                    Number time = numberFormat.parse( attributes.getValue( "time" ) );
102    
103                    timeElapsed = time.floatValue();
104    
105                    //check if group attribute is existing
106                    if ( attributes.getValue( "group" ) != null && !"".equals( attributes.getValue( "group" ) ) )
107                    {
108                        packageName = attributes.getValue( "group" );
109    
110                        name = attributes.getValue( "name" );
111    
112                        fullClassName = packageName + "." + name;
113                    }
114                    else
115                    {
116                        fullClassName = attributes.getValue( "name" );
117    
118                        name = fullClassName.substring( fullClassName.lastIndexOf( "." ) + 1, fullClassName.length() );
119    
120                        int lastDotPosition = fullClassName.lastIndexOf( "." );
121                        if ( lastDotPosition < 0 )
122                        {
123                            /* no package name */
124                            packageName = "";
125                        }
126                        else
127                        {
128                            packageName = fullClassName.substring( 0, lastDotPosition );
129                        }
130                    }
131    
132                    testCases = new ArrayList();
133                }
134                else if ( "testcase".equals( qName ) )
135                {
136                    currentElement = new StringBuffer();
137    
138                    testCase = new ReportTestCase();
139    
140                    testCase.setFullClassName( fullClassName );
141    
142                    testCase.setName( attributes.getValue( "name" ) );
143    
144                    testCase.setClassName( name );
145    
146                    String timeAsString = attributes.getValue( "time" );
147    
148                    Number time = new Integer( 0 );
149    
150                    if ( timeAsString != null )
151                    {
152                        time = numberFormat.parse( timeAsString );
153                    }
154    
155                    testCase.setTime( time.floatValue() );
156    
157                    testCase.setFullName( packageName + "." + name + "." + testCase.getName() );
158                }
159                else if ( "failure".equals( qName ) )
160                {
161                    testCase.addFailure( attributes.getValue( "message" ), attributes.getValue( "type" ) );
162                }
163                else if ( "error".equals( qName ) )
164                {
165                    testCase.addFailure( attributes.getValue( "message" ), attributes.getValue( "type" ) );
166                }
167            }
168            catch ( ParseException e )
169            {
170                throw new SAXException( e.getMessage(), e );
171            }
172        }
173    
174        public void endElement( String uri, String localName, String qName )
175            throws SAXException
176        {
177            if ( "testcase".equals( qName ) )
178            {
179                testCases.add( testCase );
180            }
181            else if ( "failure".equals( qName ) )
182            {
183                Map failure = testCase.getFailure();
184    
185                failure.put( "detail", parseCause( currentElement.toString() ) );
186            }
187            else if ( "error".equals( qName ) )
188            {
189                Map error = testCase.getFailure();
190    
191                error.put( "detail", parseCause( currentElement.toString() ) );
192            }
193        }
194    
195        public void characters( char[] ch, int start, int length )
196            throws SAXException
197        {
198            String s = new String( ch, start, length );
199    
200            if ( ! "".equals( s.trim() ) )
201            {
202                currentElement.append( s );
203            }
204        }
205    
206        public List getTestCases()
207        {
208            return this.testCases;
209        }
210    
211        public int getNumberOfErrors()
212        {
213            return numberOfErrors;
214        }
215    
216        public void setNumberOfErrors( int numberOfErrors )
217        {
218            this.numberOfErrors = numberOfErrors;
219        }
220    
221        public int getNumberOfFailures()
222        {
223            return numberOfFailures;
224        }
225    
226        public void setNumberOfFailures( int numberOfFailures )
227        {
228            this.numberOfFailures = numberOfFailures;
229        }
230        
231        public int getNumberOfSkipped()
232        {
233            return numberOfSkipped;
234        }
235        
236        public void setNumberOfSkipped( int numberOfSkipped )
237        {
238            this.numberOfSkipped = numberOfSkipped;
239        }
240    
241        public int getNumberOfTests()
242        {
243            return numberOfTests;
244        }
245    
246        public void setNumberOfTests( int numberOfTests )
247        {
248            this.numberOfTests = numberOfTests;
249        }
250    
251        public String getName()
252        {
253            return name;
254        }
255    
256        public void setName( String name )
257        {
258            this.name = name;
259        }
260    
261        public String getFName()
262        {
263            return name;
264        }
265    
266        public void setFName( String name )
267        {
268            this.name = name;
269        }
270    
271        public String getPackageName()
272        {
273            return packageName;
274        }
275    
276        public void setPackageName( String packageName )
277        {
278            this.packageName = packageName;
279        }
280    
281        public float getTimeElapsed()
282        {
283            return this.timeElapsed;
284        }
285    
286        public void setTimeElapsed( float timeElapsed )
287        {
288            this.timeElapsed = timeElapsed;
289        }
290    
291        private List parseCause( String detail )
292        {
293            String fullName = testCase.getFullName();
294            String name = fullName.substring( fullName.lastIndexOf( "." ) + 1 );
295            return parseCause( detail, name );
296        }
297    
298        private List parseCause( String detail, String compareTo )
299        {
300            StringTokenizer stringTokenizer = new StringTokenizer( detail, "\n" );
301            List parsedDetail = new ArrayList( stringTokenizer.countTokens() );
302    
303            while ( stringTokenizer.hasMoreTokens() )
304            {
305                String lineString = stringTokenizer.nextToken().trim();
306                parsedDetail.add( lineString );
307                if ( lineString.indexOf( compareTo ) >= 0 )
308                {
309                    break;
310                }
311            }
312    
313            return parsedDetail;
314        }
315    
316        public void setTestCases( List testCases )
317        {
318            this.testCases = Collections.unmodifiableList( testCases );
319        }
320    }