001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License.
018     */
019    
020    package org.apache.geronimo.mavenplugins.testsuite;
021    
022    import java.io.File;
023    import java.io.IOException;
024    
025    import java.util.ArrayList;
026    
027    import org.codehaus.mojo.pluginsupport.MojoSupport;
028    import org.codehaus.mojo.pluginsupport.ant.AntHelper;
029    
030    import org.apache.maven.project.MavenProject;
031    
032    import org.apache.maven.plugin.MojoExecutionException;
033    import org.apache.maven.plugin.MojoFailureException;
034    import org.codehaus.plexus.util.FileUtils;
035    
036    import org.apache.tools.ant.Project;
037    import org.apache.tools.ant.taskdefs.Property;
038    import org.apache.tools.ant.taskdefs.XmlProperty;
039    
040    /**
041     * Create a surefire xml file by concatenating the surefire xmls of the child poms that are invoked using maven-maven-plugin:invoke
042     *
043     * @goal generate-surefire-xml
044     *
045     * @version $Rev: 524717 $ $Date: 2007-04-01 23:39:19 -0400 (Sun, 01 Apr 2007) $
046     */
047    public class SurefireXMLGeneratorMojo
048        extends MojoSupport
049    {
050        /**
051         * @component
052         */
053        protected AntHelper ant;
054    
055        /**
056         * @parameter default-value="${project.build.directory}"
057         * @read-only
058         */
059        private File currentBuildDirectory;
060    
061        private File currentReportsDirectory;
062    
063        /**
064         * @parameter default-value="${project.basedir}"
065         * @read-only
066         */
067        private File currentBaseDirectory;
068    
069        /**
070         * @parameter default-value="${project.parent.basedir}/target"
071         * @read-only
072         */
073        private File parentBuildDirectory;
074    
075        private File parentReportsDirectory;
076    
077        /**
078         * Sometimes it is necessary to generate the surefire xml in a grand parent project because
079         * the current pom was not invoked by the maven-maven-plugin by a parent project.
080         * Such a parent project whose packaging is set to pom will not transfer the surefire data to it's parent.
081         * So we will directly write to the grandparent's surefire-reports dir.
082         * 
083         * @parameter default-value="false"
084         */
085        private boolean grandParent;
086    
087        //
088        // MojoSupport Hooks
089        //
090    
091        /**
092         * The maven project.
093         *
094         * @parameter expression="${project}"
095         * @required
096         * @readonly
097         */
098        protected MavenProject project = null;
099    
100        protected MavenProject getProject()
101        {
102            return project;
103        }
104    
105        protected void init() throws MojoExecutionException, MojoFailureException {
106            super.init();
107    
108            ant.setProject(getProject());
109    
110            currentReportsDirectory = new File(currentBuildDirectory, "surefire-reports");
111            if (grandParent) {
112                log.debug(getProject().getParent().getParent().getArtifactId() + " -- " + getProject().getParent().getParent().getBasedir().getAbsolutePath());
113                parentBuildDirectory = new File(getProject().getParent().getParent().getBasedir(), "target");
114            }
115            parentReportsDirectory = new File(parentBuildDirectory, "surefire-reports");
116            log.info("Updating directory: " + parentReportsDirectory.getAbsolutePath() );
117        }
118    
119        protected void doExecute() throws Exception {
120            if ( !currentReportsDirectory.exists() )
121            {
122                log.info("No surefire-reports directory here");
123                return;
124            }
125    
126            String parent_tests = "0";
127            String parent_skipped = "0";
128            String parent_errors = "0";
129            String parent_failures = "0";
130            String parent_time = "0";
131    
132            String artifactName = FileUtils.filename(currentBaseDirectory.getAbsolutePath());
133            if ( !parentReportsDirectory.exists() )
134            {
135                parentReportsDirectory.mkdirs();
136            }
137            File parentSurefireXMLFile = new File(parentReportsDirectory, "TEST-" + artifactName + ".xml");
138            if ( parentSurefireXMLFile.exists() )
139            {
140                parentSurefireXMLFile.delete();
141            }
142    
143            if (grandParent) {
144                artifactName = project.getParent().getBasedir().getName() + "@" + artifactName;
145            }
146    
147            ArrayList xmlFiles = (ArrayList) FileUtils.getFiles(currentReportsDirectory, "TEST*.xml", null);
148            for ( int i=0; i < xmlFiles.size(); i++ )
149            {
150                File xmlFile = (File) xmlFiles.get(i);
151                log.info("Loading surefire xml for xmlproperty: " + xmlFile.getAbsolutePath());
152    
153                String prefix = String.valueOf(System.currentTimeMillis());
154                loadXMLProperty(xmlFile, prefix);
155    
156                String tests = ant.getAnt().getProperty(prefix + ".testsuite.tests");
157                String skipped = ant.getAnt().getProperty(prefix + ".testsuite.skipped");
158                String errors = ant.getAnt().getProperty(prefix + ".testsuite.errors");
159                String failures = ant.getAnt().getProperty(prefix + ".testsuite.failures");
160                String time = ant.getAnt().getProperty(prefix + ".testsuite.time");
161                log.debug("tests=" + tests + "; skipped=" + skipped + ", errors=" + errors + ", failures=" + failures + ", time=" + time);
162    
163                if ( parentSurefireXMLFile.exists() )
164                {
165                    log.info("Loading parent surefire xml for xmlproperty: " + parentSurefireXMLFile.getAbsolutePath() );
166                    String parentPrefix = "parent" + prefix;
167                    loadXMLProperty(parentSurefireXMLFile, parentPrefix);
168    
169                    parent_tests = ant.getAnt().getProperty(parentPrefix + ".testsuite.tests");
170                    parent_skipped = ant.getAnt().getProperty(parentPrefix + ".testsuite.skipped");
171                    parent_errors = ant.getAnt().getProperty(parentPrefix + ".testsuite.errors");
172                    parent_failures = ant.getAnt().getProperty(parentPrefix + ".testsuite.failures");
173                    parent_time = ant.getAnt().getProperty(parentPrefix + ".testsuite.time");
174                    log.debug("tests=" + parent_tests + "; skipped=" + parent_skipped + ", errors=" + parent_errors + ", failures=" + parent_failures + ", time=" + parent_time);
175                }
176    
177                int testsNum = Integer.parseInt(parent_tests) + Integer.parseInt(tests);
178                int skippedNum = Integer.parseInt(parent_skipped) + Integer.parseInt(skipped);
179                int errorsNum = Integer.parseInt(parent_errors) + Integer.parseInt(errors);
180                int failuresNum = Integer.parseInt(parent_failures) + Integer.parseInt(failures);
181                float timeNum = Float.parseFloat(parent_time) + Float.parseFloat(time);
182    
183                writeParentXML(testsNum,skippedNum,errorsNum,failuresNum,timeNum,artifactName,parentSurefireXMLFile);
184            }
185        }
186    
187        /**
188         * http://ant.apache.org/manual/CoreTasks/xmlproperty.html
189         */
190        private void loadXMLProperty(File src, String prefix)
191        {
192            XmlProperty xmlProperty = (XmlProperty)ant.createTask("xmlproperty");
193            xmlProperty.setFile(src);
194            if ( prefix != null )
195            {
196                xmlProperty.setPrefix(prefix);
197            }
198            xmlProperty.setCollapseAttributes(true);
199            xmlProperty.execute();
200        }
201    
202        /**
203         * (over)writes the surefire xml file in the parent's surefire-reports dir
204         */
205        private void writeParentXML(int testsNum,int skippedNum,int errorsNum,
206                                    int failuresNum, float timeNum, 
207                                    String artifactName, File parentSurefireXMLFile ) throws IOException {
208    
209            final String header = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>";
210            String testSuite = "<testsuite errors=\"" + errorsNum + "\" skipped=\"" + skippedNum + "\" tests=\"" + testsNum + "\" time=\"" + timeNum + "\" failures=\"" + failuresNum + "\" name=\"" + artifactName + "#.\"/>";
211    
212            String parentSurefireXMLFileName = parentSurefireXMLFile.getAbsolutePath();
213    
214            log.debug(testSuite);
215    
216            FileUtils.fileWrite(parentSurefireXMLFileName, header + "\n" + testSuite);
217    
218            return;
219        }
220    }