1 package org.codehaus.mojo.fitnesse;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 import java.io.ByteArrayInputStream;
18 import java.io.ByteArrayOutputStream;
19 import java.io.File;
20 import java.io.FileOutputStream;
21 import java.io.FileWriter;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.io.OutputStream;
25
26 import org.apache.commons.httpclient.Credentials;
27 import org.apache.commons.httpclient.HttpClient;
28 import org.apache.commons.httpclient.HttpMethod;
29 import org.apache.commons.httpclient.auth.AuthScope;
30 import org.apache.commons.httpclient.methods.GetMethod;
31 import org.apache.maven.plugin.MojoExecutionException;
32 import org.apache.maven.plugin.MojoFailureException;
33 import org.apache.maven.reporting.MavenReportException;
34
35
36
37
38
39
40
41
42
43 public class FitnesseRemoteRunnerMojo
44 extends FitnesseAbstractMojo
45 {
46
47 public static final String START_REPORT_TAG_KO = "document.getElementById(\"test-summary\").className = \"fail\"";
48
49 public static final String START_REPORT_TAG_KO2 = "document.getElementById(\"test-summary\").className = \"error\"";
50
51 public static final String START_REPORT_TAG_OK = "document.getElementById(\"test-summary\").className = \"pass\"";
52
53 public void execute()
54 throws MojoExecutionException, MojoFailureException
55 {
56 new File( this.workingDir ).mkdirs();
57 checkConfiguration();
58
59 try
60 {
61 FitnesseReportMojo.copyAllResources( new File( this.workingDir ), getLog(), getClass().getClassLoader() );
62 }
63 catch ( MavenReportException e )
64 {
65 throw new MojoExecutionException( "Unable to copy resources", e.getCause() );
66 }
67
68 getLog().info( "Found " + getFitnesseSize() + " Fitnesse configuration." );
69 MojoFailureException tLastFailure = null;
70 for ( int i = 0; i < getFitnesseSize(); i++ )
71 {
72 try
73 {
74 callFitnesse( i );
75 }
76 catch ( MojoFailureException e )
77 {
78 tLastFailure = e;
79 }
80 }
81 if ( tLastFailure != null )
82 {
83 throw tLastFailure;
84 }
85 }
86
87
88
89
90
91
92
93
94 void callFitnesse( int pServerConfPosition )
95 throws MojoFailureException, MojoExecutionException
96 {
97 Fitnesse tServer = getFitnesse( pServerConfPosition );
98
99 File tResultFile = new File( this.getFinalFileName( tServer ) );
100 if ( tResultFile.exists() )
101 {
102 tResultFile.delete();
103 }
104 File tOutput = new File( this.getOutputFileName( tServer ) );
105 if ( tOutput.exists() )
106 {
107 tOutput.delete();
108 }
109 try
110 {
111 FileOutputStream tOutputStream = new FileOutputStream( tOutput );
112
113 tResultFile.createNewFile();
114 ByteArrayOutputStream tOut = new ByteArrayOutputStream();
115 getRemoteResource( "http://" + tServer.getHostName() + ":" + tServer.getPort() + "/"
116 + tServer.getPageName() + "?" + tServer.getType(), tOut, tServer );
117
118 String tOutAsString = tOut.toString();
119 FitnessePage tFitnessePage = new FitnessePage( tOutAsString );
120 transformHtml( new ByteArrayInputStream( tOut.toByteArray() ), new FileWriter( tResultFile ),
121 getOutputUrl( tServer ), tFitnessePage.getStatus() );
122
123 getRemoteResource( "http://" + tServer.getHostName() + ":" + tServer.getPort() + "/ErrorLogs."
124 + tServer.getPageName(), tOutputStream, tServer );
125 transformOutputPage( this.getOutputFileName( tServer ) );
126
127 checkFailure( tOutAsString, tResultFile.getAbsolutePath() );
128
129 }
130 catch ( IOException e )
131 {
132 throw new MojoExecutionException( "Unable to create File [" + tResultFile.getAbsolutePath() + "].", e );
133 }
134
135 }
136
137 void transformOutputPage( String pFinalOutputName )
138 throws IOException, MojoExecutionException
139 {
140 String tSrcAsString = FileUtil.getString( new File( pFinalOutputName ) );
141 tSrcAsString = tSrcAsString.replaceAll( "/files/css/", "" );
142 tSrcAsString = tSrcAsString.replaceAll( "fitnesse.css", "fitnesse_base.css" );
143 tSrcAsString = tSrcAsString.replaceAll( "/files/javascript/", "" );
144 StringBuffer tFinal = new StringBuffer();
145
146 int tStartIndex = tSrcAsString.indexOf( "<div class=\"sidebar\">" );
147 if ( tStartIndex != -1 )
148 {
149 int tEndIndex = tSrcAsString.indexOf( "<div class=\"mainbar\">" );
150 tFinal.append( tSrcAsString.substring( 0, tStartIndex ) );
151 tFinal.append( tSrcAsString.substring( tEndIndex, tSrcAsString.length() ) );
152 tSrcAsString = tFinal.toString();
153 }
154
155 tStartIndex = tSrcAsString.indexOf( "<div class=\"header\">" );
156 if ( tStartIndex != -1 )
157 {
158 tFinal = new StringBuffer();
159 int tEndIndex = tSrcAsString.indexOf( "</div>\r\n" ) + "</div>\r\n".length();
160 tFinal.append( tSrcAsString.substring( 0, tStartIndex ) );
161 tFinal.append( tSrcAsString.substring( tEndIndex, tSrcAsString.length() ) );
162 tSrcAsString = tFinal.toString();
163 }
164
165 if ( !new File( pFinalOutputName ).delete() )
166 {
167 throw new MojoExecutionException( "Unable to delete output file" );
168 }
169 FileWriter tWriter = null;
170 try
171 {
172 tWriter = new FileWriter( pFinalOutputName );
173 tWriter.write( tSrcAsString );
174 }
175 finally
176 {
177 if ( tWriter != null )
178 {
179 tWriter.close();
180 }
181 }
182 }
183
184 void checkFailure( String pFileContent, String pFileName )
185 throws MojoFailureException, MojoExecutionException
186 {
187 if ( isFailOnError() )
188 {
189 int tIndexOk = pFileContent.indexOf( START_REPORT_TAG_OK );
190 int tIndexKo = pFileContent.indexOf( START_REPORT_TAG_KO );
191 int tIndexKo2 = pFileContent.indexOf( START_REPORT_TAG_KO2 );
192 if ( tIndexOk == -1 )
193 {
194 if ( ( tIndexKo == -1 ) && ( tIndexKo2 == -1 ) )
195 {
196 throw new MojoExecutionException( "Unable to find failure result into FitNesse page, resultFile=["
197 + pFileName + "]." );
198 }
199 else
200 {
201 throw new MojoFailureException( "FitNesse page fail, resultFile=[" + pFileName + "]." );
202 }
203 }
204 else
205 {
206 if ( ( tIndexKo != -1 ) || ( tIndexKo2 != -1 ) )
207 {
208 throw new MojoExecutionException(
209 "Find both success and fail result into FitNesse page , resultFile=["
210 + pFileName + "]." );
211 }
212 }
213 }
214
215 }
216
217 void getRemoteResource( String pUrl, OutputStream pOutStream, Fitnesse pServer )
218 throws MojoExecutionException
219 {
220 try
221 {
222 HttpClient tClient = new HttpClient();
223 getLog().info( "Request resources from [" + pUrl + "]" );
224 if ( pServer.getServerId() != null )
225 {
226 tClient.getParams().setAuthenticationPreemptive( true );
227 Credentials defaultcreds = getCredential( pServer.getServerId() );
228 AuthScope tAuthScope = new AuthScope( pServer.getHostName(), pServer.getPort(), AuthScope.ANY_REALM );
229 tClient.getState().setCredentials( tAuthScope, defaultcreds );
230 getLog().info( "Use credential for remote connection" );
231 }
232 HttpMethod tMethod = new GetMethod( pUrl );
233 int tStatusCode = tClient.executeMethod( tMethod );
234 if ( tStatusCode != 200 )
235 {
236 throw new MojoExecutionException( "Bad response code from resource [" + pUrl + "], return code=["
237 + tStatusCode + "]" );
238 }
239
240 InputStream tResponseStream = tMethod.getResponseBodyAsStream();
241 byte[] tbytes = new byte[512];
242 int tReadBytes = tResponseStream.read( tbytes );
243 while ( tReadBytes >= 0 )
244 {
245 pOutStream.write( tbytes, 0, tReadBytes );
246 tReadBytes = tResponseStream.read( tbytes );
247 }
248 pOutStream.flush();
249 tMethod.releaseConnection();
250 }
251 catch ( IOException e )
252 {
253 throw new MojoExecutionException( "Unable to read FitNesse server response.", e );
254 }
255 finally
256 {
257 try
258 {
259 pOutStream.close();
260 }
261 catch ( IOException e )
262 {
263 getLog().error( "Unable to close Stream." );
264 }
265 }
266 }
267
268 public void setWorkingDir( String pWorkingDir )
269 {
270 workingDir = pWorkingDir;
271 }
272
273 String getOutputFileName( Fitnesse pServer )
274 {
275 return getResultFileName( pServer, FitnesseAbstractMojo.OUTPUT_EXTENSION, "html" );
276 }
277
278 String getOutputUrl( Fitnesse pServer )
279 {
280 return FITNESSE_RESULT_PREFIX + "_" + pServer.getHostName() + "_" + pServer.getPageName() + "_output.html";
281 }
282
283 }