KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > tools > testrecorder > client > PlaybackExecutor


1 /*
2  * Copyright 2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  * $Header:$
17  */

18
19 package org.apache.beehive.netui.tools.testrecorder.client;
20
21 import org.apache.beehive.netui.tools.testrecorder.shared.Logger;
22 import org.apache.beehive.netui.tools.testrecorder.shared.RecordSessionBean;
23 import org.apache.beehive.netui.tools.testrecorder.shared.Constants;
24 import org.apache.beehive.netui.tools.testrecorder.shared.RequestData;
25 import org.apache.beehive.netui.tools.testrecorder.shared.NVPair;
26 import org.apache.beehive.netui.tools.testrecorder.shared.ResponseData;
27 import org.apache.beehive.netui.tools.testrecorder.shared.xmlbeans.XMLHelper;
28 import org.apache.beehive.netui.tools.testrecorder.shared.config.TestDefinition;
29 import org.apache.commons.httpclient.HttpClient;
30 import org.apache.commons.httpclient.HttpMethod;
31 import org.apache.commons.httpclient.NameValuePair;
32 import org.apache.commons.httpclient.HttpRecoverableException;
33 import org.apache.commons.httpclient.Header;
34 import org.apache.commons.httpclient.methods.PostMethod;
35 import org.apache.commons.httpclient.methods.GetMethod;
36
37 import java.text.DecimalFormat JavaDoc;
38 import java.text.NumberFormat JavaDoc;
39 import java.util.Locale JavaDoc;
40 import java.util.List JavaDoc;
41 import java.io.File JavaDoc;
42 import java.io.IOException JavaDoc;
43
44 /**
45  * User: ozzy
46  * Date: Jun 29, 2004
47  * Time: 2:26:39 PM
48  */

49 public class PlaybackExecutor {
50
51     private static final Logger log = Logger.getInstance( PlaybackExecutor.class );
52
53     private static HttpClient controlClient = new HttpClient();
54     private static HttpClient testClient = new HttpClient();
55
56     private static final DecimalFormat JavaDoc format = (DecimalFormat JavaDoc)
57             NumberFormat.getInstance( Locale.US );
58
59     static {
60         // we just want the integer portion
61
format.setDecimalSeparatorAlwaysShown( false );
62         format.setGroupingSize( 0 );
63     }
64
65     private TestDefinition test;
66     private String JavaDoc description;
67     private String JavaDoc testUser;
68     private File JavaDoc recordFile;
69     private File JavaDoc resultsFile;
70     private File JavaDoc diffFile;
71
72     private NameValuePair[] startParams;
73     private NameValuePair[] stopParams;
74
75     private String JavaDoc testId;
76     private RecordSessionBean session;
77
78
79     public PlaybackExecutor( TestDefinition test,
80             String JavaDoc description, String JavaDoc testUser ) {
81         this.test = test;
82         assert test != null : "the test definition name may not be null";
83         this.description = description;
84         if ( description == null ) {
85             description = "No Description.";
86         }
87         this.testUser = testUser;
88         setControlParams();
89     }
90
91     protected void setControlParams() {
92         startParams = new NameValuePair[6];
93         stopParams = new NameValuePair[4];
94
95         startParams[0] = new NameValuePair( Constants.MODE, Constants.PLAYBACK );
96         startParams[1] = new NameValuePair( Constants.CMD, Constants.START );
97         startParams[2] = new NameValuePair( Constants.FILTER_SKIP_PARAM, Boolean.TRUE.toString() );
98         startParams[3] = new NameValuePair( Constants.TEST_NAME, getTest().getName() );
99         startParams[4] = new NameValuePair( Constants.DESCRIPTION, getDescription() );
100         startParams[5] = new NameValuePair( Constants.TEST_USER, getTestUser() );
101
102         stopParams[0] = new NameValuePair( Constants.MODE, Constants.PLAYBACK );
103         stopParams[1] = new NameValuePair( Constants.CMD, Constants.STOP );
104         stopParams[2] = new NameValuePair( Constants.FILTER_SKIP_PARAM, Boolean.TRUE.toString() );
105     }
106
107     public boolean run() throws PlaybackException {
108         boolean rtnVal = false;
109         // start playback
110
Throwable JavaDoc exception = null;
111         try {
112             startPlayback();
113             executeRequests();
114         }
115         catch ( Throwable JavaDoc e ) {
116             log.error( "start failure", e );
117             exception = e;
118         }
119         finally {
120             if ( getTestId() != null ) {
121                 // we successfully started, so stop
122
try {
123                     rtnVal = stopPlayback();
124                 }
125                 catch ( Throwable JavaDoc e ) {
126                     if ( exception == null ) {
127                         exception = e;
128                     }
129                     else {
130                         log.error( "ERROR: possible spurious failure, failed to stop playback, exception( " +
131                                 e.getMessage() + " )", e );
132                     }
133                 }
134             }
135             if ( exception != null ) {
136                 String JavaDoc msg = "ERROR: playback failed, exception( " + exception.getMessage() + " )";
137                 log.error( msg, exception );
138                 if ( exception instanceof PlaybackException ) {
139                     throw (PlaybackException) exception;
140                 }
141                 throw new PlaybackException( msg, exception );
142             }
143         }
144         return rtnVal;
145     }
146
147     protected void startPlayback() throws PlaybackException {
148         HttpMethod method = new GetMethod( RequestData.genUri( "http",
149                 getTest().getWebapp().getServer().getHostname(), getTest().getWebapp().getServer().getPort(),
150                 getTest().getWebapp().getServletURI() ) );
151         method.setQueryString( getStartParams() );
152         ResponseData response = null;
153         try {
154             response = execute( getControlClient(), method );
155         }
156         catch ( Exception JavaDoc e ) {
157             String JavaDoc msg = "Failed to execute start playback request, exception( " + e.getMessage() + " )";
158             log.error( msg, e );
159             if ( e instanceof PlaybackException ) {
160                 throw (PlaybackException) e;
161             }
162             throw new PlaybackException( msg, e );
163         }
164         String JavaDoc outcome = response.getHeader( Constants.OUTCOME_HEADER );
165         String JavaDoc testId = response.getHeader( Constants.TEST_ID_HEADER );
166         String JavaDoc testFileName = response.getHeader( Constants.RECORD_FILE_HEADER );
167         String JavaDoc startMsg = response.getHeader( Constants.MSG_ATTRIBUTE );
168         // config the playback stop params
169
setStopParam( 3, new NameValuePair( Constants.TEST_ID_HEADER, testId ) );
170         setTestId( testId );
171         if ( log.isInfoEnabled() ) {
172             log.info( "outcome( " + outcome + " )" );
173             log.info( "testId( " + getTestId() + " )" );
174             log.info( "testFileName( " + testFileName + " )" );
175         }
176         // failed
177
if ( outcome == null || !outcome.equals( Constants.PASS ) ) {
178             throw new PlaybackException(
179                     "ERROR: failed to start playback, server error message( " + startMsg + " )" );
180         }
181         this.recordFile = new File JavaDoc( testFileName );
182         if ( !getRecordFile().canRead() ) {
183             String JavaDoc msg = "ERROR: failed to start playback, lacking permissions to read record file( " +
184                     getRecordFile() + " )";
185             System.out.println( msg );
186             log.error( msg );
187             throw new PlaybackException( msg );
188         }
189         RecordSessionBean session = createSession();
190         setSession( session );
191         if ( log.isInfoEnabled() ) {
192             log.info( "playback started for test( " + getTest().getName() + " )" );
193         }
194     }
195
196     protected boolean stopPlayback() throws PlaybackException {
197         boolean rtnVal = false;
198         HttpMethod method = new GetMethod( RequestData.genUri( "http",
199                 getTest().getWebapp().getServer().getHostname(), getTest().getWebapp().getServer().getPort(),
200                 getTest().getWebapp().getServletURI() ) );
201         method.setQueryString( getStopParams() );
202         ResponseData response = null;
203         try {
204             response = execute( getControlClient(), method );
205         }
206         catch ( Exception JavaDoc e ) {
207             String JavaDoc msg = "Failed to execute stop playback request, exception( " + e.getMessage() + " )";
208             log.error( msg, e );
209             if ( e instanceof PlaybackException ) {
210                 throw (PlaybackException) e;
211             }
212             throw new PlaybackException( msg, e );
213         }
214         String JavaDoc outcome = response.getHeader( Constants.OUTCOME_HEADER );
215         String JavaDoc resultsFileName = response.getHeader( Constants.RESULTS_FILE_HEADER );
216         String JavaDoc diffFileName = response.getHeader( Constants.RESULTS_DIFF_HEADER );
217         String JavaDoc stopMsg = response.getHeader( Constants.MSG_ATTRIBUTE );
218         if ( log.isDebugEnabled() ) {
219             log.debug( "stop outcome( " + outcome + " )" );
220             log.debug( "stopMsg( " + stopMsg + " )" );
221         }
222         if ( outcome != null && !outcome.equals( Constants.ERROR ) ) {
223             // requests successfully executed
224
if ( log.isInfoEnabled() ) {
225                 log.info( "Results are stored in file( " + resultsFileName + " )" );
226             }
227             setResultsFile( new File JavaDoc( resultsFileName ) );
228             // if there were errors then report them...
229
if ( outcome.equals( Constants.FAIL ) ) {
230                 if ( log.isInfoEnabled() ) {
231                     log.info( "Diff results are stored in file( " + diffFileName + " )" );
232                 }
233                 setDiffFile( new File JavaDoc( diffFileName ) );
234                 rtnVal = false;
235             }
236             else {
237                 rtnVal = true;
238             }
239         }
240         else {
241             String JavaDoc msg = "ERROR: error encountered executing test( " + getTest().getName() + " ), server msg( " +
242                     stopMsg + " )";
243             log.error( msg );
244             throw new PlaybackException( msg );
245         }
246         return rtnVal;
247     }
248
249     private RecordSessionBean createSession() throws PlaybackException {
250         RecordSessionBean session = null;
251         try {
252             session = XMLHelper.getRecordSessionBean( getRecordFile() );
253             if ( log.isDebugEnabled() ) {
254                 log.debug( "test( " + getTest().getName() + " ), testCount( " + session.getTestCount() + " )" );
255             }
256         }
257         catch ( Exception JavaDoc e ) {
258             String JavaDoc msg = "ERROR: failed to process session file( " + getRecordFile().getAbsolutePath() + " )";
259             log.error( msg, e );
260             throw new PlaybackException( msg, e );
261         }
262         return session;
263     }
264
265     private void executeRequests() throws PlaybackException {
266         RequestData request = null;
267         int testNumber = 0;
268         try {
269             List JavaDoc requestList = getSession().getRequestData();
270             if ( log.isDebugEnabled() ) {
271                 log.debug( "beginning test execution" );
272             }
273             for ( testNumber = 0; testNumber < requestList.size(); testNumber++ ) {
274                 request = (RequestData) requestList.get( testNumber );
275                 if ( log.isDebugEnabled() ) {
276                     log.debug( "beginning execution for test number( " + ( testNumber + 1 ) + " )" );
277                 }
278                 HttpMethod method = createPlaybackMethod( request, getTest() );
279                 if ( log.isDebugEnabled() ) {
280                     log.debug( "playback URI( " + method.getURI() + " )" );
281                 }
282                 ResponseData response = execute( getTestClient(), method );
283                 if ( log.isDebugEnabled() ) {
284                     log.debug( "playback response, status code( " + response.getStatusCode() + " )" );
285                     log.debug( "playback response, body(\n" + response.getBody() + " )" );
286                 }
287                 String JavaDoc outcome = response.getHeader( Constants.OUTCOME_HEADER );
288                 if ( log.isDebugEnabled() ) {
289                     log.debug( "outcome( " + outcome + " )" );
290                 }
291                 if ( response.getStatusCode() >= 400 ) {
292                     String JavaDoc msg = "WARNING: unable to access URI( " + method.getURI() +
293                             " ), status code( " + response.getStatusCode() + " ) returned";
294                     System.out.println( msg );
295                     if ( log.isWarnEnabled() ) {
296                         log.warn( msg );
297                     }
298                 }
299             }
300         }
301         catch ( Exception JavaDoc e ) {
302             String JavaDoc msg = "ERROR: failed executing request for test( " + getTest().getName() +
303                     " ), testNumber( " + testNumber + " ), path( " + request.getPath() + " ), exception( "
304                     + e.getMessage() + " )";
305             log.error( msg, e );
306             if ( e instanceof PlaybackException ) {
307                 throw (PlaybackException) e;
308             }
309             throw new PlaybackException( msg, e );
310         }
311     }
312
313     protected ResponseData execute( HttpClient client, HttpMethod method ) throws PlaybackException, IOException JavaDoc {
314         ResponseData response = new ResponseData( method.getHostConfiguration().getHost(),
315                 method.getHostConfiguration().getPort() );
316         int statusCode = -1;
317         // retry up to 3 times.
318
for ( int attempt = 0; statusCode == -1 && attempt < 3; attempt++ ) {
319             try {
320                 statusCode = client.executeMethod( method );
321             }
322             catch ( HttpRecoverableException e ) {
323                 if ( log.isWarnEnabled() ) {
324                     String JavaDoc msg = "A recoverable exception occurred calling URI( " + method.getURI() +
325                             " ), retrying. exception( " + e.getMessage() + " )";
326                     log.error( msg, e );
327                 }
328             }
329             catch ( IOException JavaDoc e ) {
330                 String JavaDoc msg = "Failed executing request( " + method.getURI() + " ), exception( " + e.getMessage() +
331                         " )";
332                 log.error( msg, e );
333                 throw e;
334             }
335         }
336         // Retries failed
337
if ( statusCode == -1 ) {
338             String JavaDoc msg = "Failed to execute request( " + method.getURI() + " )";
339             log.error( msg );
340             throw new PlaybackException( msg );
341         }
342         response.setStatusCode( statusCode );
343         byte[] responseBody = method.getResponseBody();
344         response.setBody( new String JavaDoc( responseBody ) );
345         if ( log.isDebugEnabled() ) {
346             log.debug( "statusCode( " + statusCode + " )" );
347 // log.debug( "response body:\n" + response.getBody() + "\n" );
348
}
349         response.setHeaders( convertHeaders( method.getResponseHeaders() ) );
350         method.releaseConnection();
351         return response;
352     }
353
354     protected HttpMethod createPlaybackMethod( RequestData request, TestDefinition test ) {
355         HttpMethod method = null;
356         if ( request.getMethod().equalsIgnoreCase( "POST" ) ) {
357             method = new PostMethod( request.getUri( getTest().getWebapp().getServer().getHostname(),
358                     getTest().getWebapp().getServer().getPort() ) );
359             populatePlaybackPostMethod( (PostMethod) method, request );
360         }
361         else if ( request.getMethod().equalsIgnoreCase( "GET" ) ) {
362             method = new GetMethod( request.getUri( getTest().getWebapp().getServer().getHostname(),
363                     getTest().getWebapp().getServer().getPort() ) );
364             populatePlaybackGetMethod( (GetMethod) method, request );
365         }
366         else {
367             throw new RuntimeException JavaDoc( "ERROR: unhandled HTTP method( " + request.getMethod() + " )" );
368         }
369         return method;
370     }
371
372     protected HttpMethod populatePlaybackPostMethod( final PostMethod method, final RequestData request ) {
373         log.debug( "calling setRequestBody()" );
374         method.setRequestBody( convertNVPairs( request.getParameters() ) );
375         populatePlaybackMethod( method, request );
376         debugNameValuePairs( method.getParameters() );
377         return method;
378     }
379
380     protected HttpMethod populatePlaybackGetMethod( final GetMethod method, final RequestData request ) {
381         populatePlaybackMethod( method, request );
382         method.setQueryString( convertNVPairs( request.getParameters() ) );
383         return method;
384     }
385
386     protected HttpMethod populatePlaybackMethod( final HttpMethod method, RequestData request ) {
387         addRequestHeaders( method, request );
388         addTestIdHeader( method );
389         return method;
390     }
391
392     protected HttpMethod addRequestHeaders( HttpMethod method, RequestData request ) {
393         for ( int i = 0; i < request.getHeaderCount(); i++ ) {
394             if ( skipPlaybackHeader( request.getHeaderName( i ) ) ) {
395                 continue;
396             }
397             method.addRequestHeader( request.getHeaderName( i ), request.getHeaderValue( i ) );
398         }
399         return method;
400     }
401
402     /**
403      * if this method returns true the header specified by the name parameter should not be sent to the
404      * client during playback
405      *
406      * @param name
407      * @return
408      */

409     protected boolean skipPlaybackHeader( String JavaDoc name ) {
410         // fail mode header is for legacy record files
411
if ( name.equalsIgnoreCase( "host" ) ||
412                 name.equalsIgnoreCase( "referer" ) ||
413                 name.equalsIgnoreCase( "Content-length" ) ||
414                 name.equalsIgnoreCase( "Host" ) ||
415                 name.equals( Constants.TEST_ID_HEADER ) ||
416                 name.equals( Constants.FAIL_MODE_HEADER ) ||
417                 name.equals( Constants.TEST_NUMBER_HEADER ) ) {
418             // skip
419
return true;
420         }
421         return false;
422     }
423
424     public NameValuePair[] getStartParams() {
425         return startParams;
426     }
427
428     protected void setStartParams( NameValuePair[] startParams ) {
429         this.startParams = startParams;
430     }
431
432     protected void setStartParam( int index, NameValuePair param ) {
433         if ( index >= startParams.length ) {
434             throw new IndexOutOfBoundsException JavaDoc( "Invalid start parameter index( " + index +
435                     " ), start parameter size is (" + startParams.length + ")" );
436         }
437         stopParams[index] = param;
438     }
439
440     public NameValuePair[] getStopParams() {
441         return stopParams;
442     }
443
444     protected void setStopParams( NameValuePair[] stopParams ) {
445         this.stopParams = stopParams;
446     }
447
448     protected void setStopParam( int index, NameValuePair param ) {
449         if ( index >= stopParams.length ) {
450             throw new IndexOutOfBoundsException JavaDoc( "Invalid stop parameter index( " + index +
451                     " ), stop parameter size is (" + stopParams.length + ")" );
452         }
453         stopParams[index] = param;
454     }
455
456     protected HttpMethod addTestIdHeader( HttpMethod method ) {
457         if ( getTestId() != null ) {
458             method.setRequestHeader( Constants.TEST_ID_HEADER, getTestId() );
459         }
460         return method;
461     }
462
463     public RecordSessionBean getSession() {
464         return session;
465     }
466
467     protected void setSession( RecordSessionBean session ) {
468         this.session = session;
469     }
470
471     protected HttpClient getTestClient() {
472         return testClient;
473     }
474
475     protected HttpClient getControlClient() {
476         return controlClient;
477     }
478
479     public TestDefinition getTest() {
480         return test;
481     }
482
483     public String JavaDoc getDescription() {
484         return description;
485     }
486
487     public String JavaDoc getTestUser() {
488         return testUser;
489     }
490
491     public String JavaDoc getTestId() {
492         return testId;
493     }
494
495     protected void setTestId( String JavaDoc testId ) {
496         this.testId = testId;
497     }
498
499     public File JavaDoc getRecordFile() {
500         return recordFile;
501     }
502
503     public File JavaDoc getResultsFile() {
504         return resultsFile;
505     }
506
507     protected void setResultsFile( File JavaDoc resultsFile ) {
508         this.resultsFile = resultsFile;
509     }
510
511     public File JavaDoc getDiffFile() {
512         return diffFile;
513     }
514
515     protected void setDiffFile( File JavaDoc diffFile ) {
516         this.diffFile = diffFile;
517     }
518
519     private static NVPair[] convertHeaders( Header[] headers ) {
520         if ( headers == null ) {
521             return null;
522         }
523         NVPair[] newPairs = new NVPair[headers.length];
524         NVPair newPair = null;
525         for ( int i = 0; i < headers.length; i++ ) {
526             newPair = convertHeader( headers[i] );
527             newPairs[i] = newPair;
528         }
529         return newPairs;
530     }
531
532     private static NVPair convertHeader( Header header ) {
533         if ( log.isDebugEnabled() ) {
534             log.debug( "header, name( " + header.getName() + " ), value( " + header.getValue() + " )" );
535         }
536         return new NVPair( header.getName(), header.getValue() );
537     }
538
539     private static NameValuePair[] convertNVPairs( NVPair[] pairs ) {
540         if ( pairs == null ) {
541             return null;
542         }
543         NameValuePair[] newPairs = new NameValuePair[pairs.length];
544         NameValuePair newPair = null;
545         for ( int i = 0; i < pairs.length; i++ ) {
546             newPair = convertNVPair( pairs[i] );
547             newPairs[i] = newPair;
548         }
549         return newPairs;
550     }
551
552     private static NameValuePair convertNVPair( NVPair pair ) {
553         if ( log.isDebugEnabled() ) {
554             log.debug( "pair, name( " + pair.getName() + " ), value( " + pair.getValue() + " )" );
555         }
556         return new NameValuePair( pair.getName(), pair.getValue() );
557     }
558
559     private static void debugNameValuePairs( NameValuePair[] pairs ) {
560         if ( pairs == null ) {
561             log.debug( "pairs( " + pairs + " )" );
562             return;
563         }
564         for ( int i = 0; i < pairs.length; i++ ) {
565             log.debug(
566                     "pair(" + i + ")[ name( " + pairs[i].getName() + " ), value( " + pairs[i].getValue() + " )" );
567         }
568         return;
569     }
570
571 }
572
Popular Tags