001    /*
002     * Copyright 1999-2002,2004 The Apache Software Foundation.
003     * 
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.apache.commons.latka.validators;
018    
019    import java.io.ByteArrayOutputStream;
020    import java.io.File;
021    import java.io.FileInputStream;
022    import java.io.FileReader;
023    import java.io.InputStream;
024    import java.io.IOException;
025    
026    import java.util.StringTokenizer;
027    
028    import org.apache.commons.latka.Validator;
029    import org.apache.commons.latka.ValidationException;
030    import org.apache.commons.latka.http.Response;
031    
032    /** Compare the response with a golden
033        file.  Right now this is a proof
034        of concept class; we should extend it to support
035        more than just files, I think.  Also, maybe
036        golden files should be more than just text.
037    */
038    public class GoldenFileValidator extends BaseValidator 
039    implements Validator {
040    
041        protected File _goldFile = null;
042        protected boolean _ignoreWhitespace=false;
043        protected static String TRUE_MESSAGE = "EXPECTED TO MATCH GOLDEN FILE: ";
044        protected StringBuffer _matchLog = new StringBuffer();
045    
046        public GoldenFileValidator(File goldenFile) {
047            this(null,goldenFile);
048        }
049    
050        public GoldenFileValidator(String label, File goldenFile) {
051            super(label);
052            _goldFile = goldenFile;
053        }
054    
055        public void setIgnoreWhitespace(boolean ignoreWhitespace) {
056            _ignoreWhitespace = ignoreWhitespace;
057        }
058    
059        public void validate(Response response)
060        throws ValidationException {
061    
062            // Compare the results and set the status
063            boolean cmp=true;
064    
065            if (_ignoreWhitespace) {
066                String goldFileString = null;
067    
068                try {
069                    FileReader reader = new FileReader(_goldFile);
070    
071                    StringBuffer buf = new StringBuffer();
072    
073                    while (true) {
074                        int ch = reader.read();
075                        if (ch < 0) {
076                            break;
077                        }
078                        buf.append((char) ch);
079                    }
080    
081                    goldFileString = buf.toString();
082                } catch (IOException e) {
083                    fail(e.toString());
084                }
085    
086                cmp=compareWeak(response.getResource(), goldFileString );
087            } else {
088                try {
089                    InputStream responseStream = response.getStream();
090                    ByteArrayOutputStream responseBytes = new ByteArrayOutputStream();
091                    while (true) {
092                        int ch = responseStream.read();
093                        if (ch < 0) {
094                            break;
095                        }
096                        responseBytes.write(ch);
097                    }
098    
099                    FileInputStream fileStream = new FileInputStream(_goldFile);
100                    ByteArrayOutputStream fileBytes = new ByteArrayOutputStream();
101                    while (true) {
102                        int ch = fileStream.read();
103                        if (ch < 0) {
104                            break;
105                        }
106                        fileBytes.write(ch);
107                    }
108    
109                    cmp=compare(new String(responseBytes.toByteArray()).getBytes(), 
110                                new String(fileBytes.toByteArray()).getBytes() );
111                } catch (IOException e) {
112                    fail(e.toString());
113                }
114            }
115    
116            if (cmp == false) {
117                StringBuffer buf = new StringBuffer();
118                buf.append(TRUE_MESSAGE);
119                buf.append(_goldFile);
120                buf.append("\n");
121                buf.append(_matchLog);
122                fail(buf.toString());
123            }
124    
125    
126        }
127    
128        // Compare the actual result and the expected result.
129        protected boolean compare(byte[] array1, byte[] array2) {
130            if ( array1==null || array2==null) return false;
131            if ( array1.length != array2.length ) {
132                log("Wrong size " + array1.length + " " + array2.length );
133                log("char 1:" + array1[array2.length - 1]);
134                log("char 2:" + array2[array2.length - 1]);
135                return false;
136            }
137    
138            for (int i=0; i<array1.length ; i++ ) {
139                if (array1[i] != array2[i] ) {
140                    log("Error at " + i  + "comparing '" + array1[i] +
141                        "' to '" + array2[i] + "'");
142                    return false;
143                }
144            }
145            return true;
146        }
147    
148        // Compare the actual result and the expected result.
149        // Original compare - ignores whitespace ( because most
150        // golden files are wrong !)
151        protected boolean compareWeak(String str1, String str2) {
152            if ( str1==null || str2==null) return false;
153    
154            StringTokenizer st1=new StringTokenizer(str1);
155            StringTokenizer st2=new StringTokenizer(str2);
156    
157            while (st1.hasMoreTokens() && st2.hasMoreTokens()) {
158                String tok1 = st1.nextToken();
159                String tok2 = st2.nextToken();
160                if (!tok1.equals(tok2)) {
161                    log("\tFAIL*** : Live token = " + tok1 
162                        + ", did not match golden file token = " + tok2);
163                    return false;
164                }
165            }
166    
167            if (st1.hasMoreTokens() || st2.hasMoreTokens()) {
168                return false;
169            } else {
170                return true;
171            }
172        }
173    
174        protected void log(String message) {
175            _matchLog.append(message);
176        }
177    
178    }