package org.codehaus.mojo.fitnesse; /* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, version 2. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Foobar. If not, see <http://www.gnu.org/licenses/>. */ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import org.apache.commons.httpclient.Credentials; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.reporting.MavenReportException; /** * This goal uses the <code>fitnesse.runner.TestRunner</code> class for getting result of a remote FitNesse web page * execution. It's possible to define several pages and/or servers. * * @goal remotecall * @aggregator */ public class FitnesseRemoteRunnerMojo extends FitnesseAbstractMojo { public static final String START_REPORT_TAG_KO = "document.getElementById(\"test-summary\").className = \"fail\""; public static final String START_REPORT_TAG_KO2 = "document.getElementById(\"test-summary\").className = \"error\""; public static final String START_REPORT_TAG_OK = "document.getElementById(\"test-summary\").className = \"pass\""; public void execute() throws MojoExecutionException, MojoFailureException { new File( this.workingDir ).mkdirs(); checkConfiguration(); try { FitnesseReportMojo.copyAllResources( new File( this.workingDir ), getLog(), getClass().getClassLoader() ); } catch ( MavenReportException e ) { throw new MojoExecutionException( "Unable to copy resources", e.getCause() ); } getLog().info( "Found " + getFitnesseSize() + " Fitnesse configuration." ); MojoFailureException tLastFailure = null; for ( int i = 0; i < getFitnesseSize(); i++ ) { try { callFitnesse( i ); } catch ( MojoFailureException e ) { tLastFailure = e; } } if ( tLastFailure != null ) { throw tLastFailure; } } /** * Call a Fitnesse server page. * * @param pServerConfPosition The number of the Fitnesse configuration. * @throws MojoFailureException * @throws MojoExecutionException */ void callFitnesse( int pServerConfPosition ) throws MojoFailureException, MojoExecutionException { Fitnesse tServer = getFitnesse( pServerConfPosition ); File tResultFile = new File( this.getFinalFileName( tServer ) ); if ( tResultFile.exists() ) { tResultFile.delete(); } File tOutput = new File( this.getOutputFileName( tServer ) ); if ( tOutput.exists() ) { tOutput.delete(); } try { FileOutputStream tOutputStream = new FileOutputStream( tOutput ); tResultFile.createNewFile(); ByteArrayOutputStream tOut = new ByteArrayOutputStream(); String tUrl = "http://" + tServer.getHostName() + ":" + tServer.getPort() + "/" + tServer.getPageName() + "?responder=" + tServer.getType(); if ( tServer.getSuiteFilter() != null && tServer.getSuiteFilter().length() > 0 ) { if ( Fitnesse.PAGE_TYPE_SUITE.equals( tServer.getType() ) ) { tUrl = tUrl + "&testFilter=" + tServer.getType(); } else { getLog().error( "The FitNesse parameter testFilter is only supported with Suite page (not Test page), it has be ignored..." ); } } getRemoteResource( tUrl, tOut, tServer ); String tOutAsString = tOut.toString(); FitnessePage tFitnessePage = new FitnessePage( tOutAsString ); transformHtml( new ByteArrayInputStream( tOut.toByteArray() ), new FileWriter( tResultFile ), getOutputUrl( tServer ), tFitnessePage.getStatus() ); getRemoteResource( "http://" + tServer.getHostName() + ":" + tServer.getPort() + "/ErrorLogs." + tServer.getPageName(), tOutputStream, tServer ); transformOutputPage( new File( this.getOutputFileName( tServer ) ) ); checkFailure( tOutAsString, tResultFile.getAbsolutePath() ); } catch ( IOException e ) { throw new MojoExecutionException( "Unable to create File [" + tResultFile.getAbsolutePath() + "].", e ); } } void transformOutputPage( File pFinalOutputName ) throws IOException, MojoExecutionException { String tSrcAsString = FileUtil.getString( pFinalOutputName ); tSrcAsString = tSrcAsString.replaceAll( "/files/css/", "" ); tSrcAsString = tSrcAsString.replaceAll( "fitnesse.css", "fitnesse_base.css" ); tSrcAsString = tSrcAsString.replaceAll( "/files/javascript/", "" ); StringBuffer tFinal = new StringBuffer(); int tStartIndex = tSrcAsString.indexOf( "<div class=\"sidebar\">" ); if ( tStartIndex != -1 ) { int tEndIndex = tSrcAsString.indexOf( "<div class=\"mainbar\">" ); tFinal.append( tSrcAsString.substring( 0, tStartIndex ) ); tFinal.append( tSrcAsString.substring( tEndIndex, tSrcAsString.length() ) ); tSrcAsString = tFinal.toString(); } tStartIndex = tSrcAsString.indexOf( "<div class=\"header\">" ); if ( tStartIndex != -1 ) { tFinal = new StringBuffer(); int tEndIndex = tSrcAsString.indexOf( "</div>\r\n" ) + "</div>\r\n".length(); tFinal.append( tSrcAsString.substring( 0, tStartIndex ) ); tFinal.append( tSrcAsString.substring( tEndIndex, tSrcAsString.length() ) ); tSrcAsString = tFinal.toString(); } if ( !pFinalOutputName.delete() ) { throw new MojoExecutionException( "Unable to delete output file" ); } FileWriter tWriter = null; try { tWriter = new FileWriter( pFinalOutputName ); tWriter.write( tSrcAsString ); } finally { if ( tWriter != null ) { tWriter.close(); } } } void checkFailure( String pFileContent, String pFileName ) throws MojoFailureException, MojoExecutionException { if ( isFailOnError() ) { int tIndexOk = pFileContent.indexOf( START_REPORT_TAG_OK ); int tIndexKo = pFileContent.indexOf( START_REPORT_TAG_KO ); int tIndexKo2 = pFileContent.indexOf( START_REPORT_TAG_KO2 ); if ( tIndexOk == -1 ) { if ( ( tIndexKo == -1 ) && ( tIndexKo2 == -1 ) ) { throw new MojoExecutionException( "Unable to find failure result into FitNesse page, resultFile=[" + pFileName + "]." ); } else { throw new MojoFailureException( "FitNesse page fail, resultFile=[" + pFileName + "]." ); } } else { if ( ( tIndexKo != -1 ) || ( tIndexKo2 != -1 ) ) { throw new MojoExecutionException( "Find both success and fail result into FitNesse page , resultFile=[" + pFileName + "]." ); } } } } void getRemoteResource( String pUrl, OutputStream pOutStream, Fitnesse pServer ) throws MojoExecutionException { try { HttpClient tClient = new HttpClient(); getLog().info( "Request resources from [" + pUrl + "]" ); if ( pServer.getServerId() != null ) { tClient.getParams().setAuthenticationPreemptive( true ); Credentials defaultcreds = getCredential( pServer.getServerId() ); AuthScope tAuthScope = new AuthScope( pServer.getHostName(), pServer.getPort(), AuthScope.ANY_REALM ); tClient.getState().setCredentials( tAuthScope, defaultcreds ); getLog().info( "Use credential for remote connection" ); } HttpMethod tMethod = new GetMethod( pUrl ); int tStatusCode = tClient.executeMethod( tMethod ); if ( tStatusCode != 200 ) { throw new MojoExecutionException( "Bad response code from resource [" + pUrl + "], return code=[" + tStatusCode + "]" ); } InputStream tResponseStream = tMethod.getResponseBodyAsStream(); byte[] tbytes = new byte[512]; int tReadBytes = tResponseStream.read( tbytes ); while ( tReadBytes >= 0 ) { pOutStream.write( tbytes, 0, tReadBytes ); tReadBytes = tResponseStream.read( tbytes ); } pOutStream.flush(); tMethod.releaseConnection(); } catch ( IOException e ) { throw new MojoExecutionException( "Unable to read FitNesse server response.", e ); } finally { try { pOutStream.close(); } catch ( IOException e ) { getLog().error( "Unable to close Stream." ); } } } public void setWorkingDir( String pWorkingDir ) { workingDir = pWorkingDir; } String getOutputFileName( Fitnesse pServer ) { return getResultFileName( pServer, FitnesseAbstractMojo.OUTPUT_EXTENSION, "html" ); } String getOutputUrl( Fitnesse pServer ) { return FITNESSE_RESULT_PREFIX + "_" + pServer.getHostName() + "_" + pServer.getPageName() + "_output.html"; } }