001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/portal/owswatch/validator/AbstractValidator.java $ 002 /*---------------------------------------------------------------------------- 003 This file is part of deegree, http://deegree.org/ 004 Copyright (C) 2001-2009 by: 005 Department of Geography, University of Bonn 006 and 007 lat/lon GmbH 008 009 This library is free software; you can redistribute it and/or modify it under 010 the terms of the GNU Lesser General Public License as published by the Free 011 Software Foundation; either version 2.1 of the License, or (at your option) 012 any later version. 013 This library is distributed in the hope that it will be useful, but WITHOUT 014 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 015 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 016 details. 017 You should have received a copy of the GNU Lesser General Public License 018 along with this library; if not, write to the Free Software Foundation, Inc., 019 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 020 021 Contact information: 022 023 lat/lon GmbH 024 Aennchenstr. 19, 53177 Bonn 025 Germany 026 http://lat-lon.de/ 027 028 Department of Geography, University of Bonn 029 Prof. Dr. Klaus Greve 030 Postfach 1147, 53001 Bonn 031 Germany 032 http://www.geographie.uni-bonn.de/deegree/ 033 034 e-mail: info@deegree.org 035 ----------------------------------------------------------------------------*/ 036 037 package org.deegree.portal.owswatch.validator; 038 039 import java.io.BufferedReader; 040 import java.io.ByteArrayInputStream; 041 import java.io.ByteArrayOutputStream; 042 import java.io.IOException; 043 import java.io.InputStream; 044 import java.io.InputStreamReader; 045 046 import javax.servlet.http.HttpServletResponse; 047 import javax.xml.parsers.DocumentBuilder; 048 import javax.xml.parsers.DocumentBuilderFactory; 049 import javax.xml.parsers.ParserConfigurationException; 050 051 import org.apache.commons.httpclient.HttpMethodBase; 052 import org.deegree.framework.log.ILogger; 053 import org.deegree.framework.log.LoggerFactory; 054 import org.deegree.framework.util.StringTools; 055 import org.deegree.framework.xml.XMLParsingException; 056 import org.deegree.framework.xml.XMLTools; 057 import org.w3c.dom.Document; 058 059 import org.deegree.portal.owswatch.Status; 060 import org.deegree.portal.owswatch.ValidatorResponse; 061 062 /** 063 * Abstract class implementing the method validate. 064 * 065 * @author <a href="mailto:elmasry@lat-lon.de">Moataz Elmasry</a> 066 * @author last edited by: $Author: jmays $ 067 * 068 * @version $Revision: 20271 $, $Date: 2009-10-21 13:07:15 +0200 (Mi, 21 Okt 2009) $ 069 */ 070 public abstract class AbstractValidator implements Validator { 071 072 private static final ILogger LOG = LoggerFactory.getLogger( AbstractValidator.class ); 073 074 /* 075 * (non-Javadoc) 076 * 077 * @see org.deegree.portal.owswatch.validator.Validator#validateAnswer(org.apache.commons.httpclient.HttpMethodBase, int, 078 * int) 079 */ 080 public ValidatorResponse validateAnswer( HttpMethodBase method, int statusCode ) { 081 if ( isValidHttpResponse( statusCode ) ) { 082 return validateXml( method ); 083 } else { 084 return validateErrorHttpResponse( statusCode ); 085 } 086 } 087 088 /** 089 * Validates the HttpMethodBase and checks if the execution was successful or not 090 * 091 * @param method 092 * the httpmethod after executing it 093 * @return an instance of ValidatorResponse with the necessary information after validation 094 */ 095 protected ValidatorResponse validateXml( HttpMethodBase method ) { 096 097 String lastMessage = null; 098 Status status = null; 099 100 String contentType = method.getResponseHeader( "Content-Type" ).getValue(); 101 if ( !contentType.contains( "xml" ) ) { 102 status = Status.RESULT_STATE_UNEXPECTED_CONTENT; 103 lastMessage = StringTools.concat( 100, "Error: Response Content is ", contentType, " not xml" ); 104 return new ValidatorResponse( lastMessage, status ); 105 } 106 107 String xml = null; 108 try { 109 InputStream stream = copyStream( method.getResponseBodyAsStream() ); 110 stream.reset(); 111 xml = parseStream( stream ); 112 } catch ( IOException e ) { 113 status = Status.RESULT_STATE_BAD_RESPONSE; 114 lastMessage = status.getStatusMessage(); 115 return new ValidatorResponse( lastMessage, status ); 116 } 117 118 if ( xml.length() == 0 ) { 119 status = Status.RESULT_STATE_BAD_RESPONSE; 120 lastMessage = "Error: XML Response is empty"; 121 return new ValidatorResponse( lastMessage, status ); 122 } 123 if ( xml.contains( "ServiceException" ) ) { 124 return validateXmlServiceException( method ); 125 } 126 // If its an xml, and there's no service exception, then don't really parse the xml, 127 // we assume that its well formed, since there might be huge xmls, which would take time to be parsed 128 status = Status.RESULT_STATE_AVAILABLE; 129 lastMessage = status.getStatusMessage(); 130 return new ValidatorResponse( lastMessage, status ); 131 } 132 133 /** 134 * This method is called To read the ServiceExceptionReport from the xml file 135 * 136 * @param method 137 * the httpmethod after executing it 138 * @return an instance of ValidatorResponse with the necessary information after validation 139 */ 140 protected ValidatorResponse validateXmlServiceException( HttpMethodBase method ) { 141 142 Document doc = null; 143 String lastMessage = null; 144 Status status = null; 145 try { 146 InputStream stream = method.getResponseBodyAsStream(); 147 stream.reset(); 148 doc = instantiateParser().parse( stream ); 149 } catch ( Exception e ) { 150 status = Status.RESULT_STATE_INVALID_XML; 151 lastMessage = "Error: MalFormed XML Response"; 152 return new ValidatorResponse( lastMessage, status ); 153 } 154 try { 155 status = Status.RESULT_STATE_SERVICE_UNAVAILABLE; 156 lastMessage = XMLTools.getNodeAsString( doc.getDocumentElement(), "./ServiceException", null, 157 "Service Unavailable. Unknown error" ); 158 return new ValidatorResponse( lastMessage, status ); 159 } catch ( XMLParsingException e ) { 160 status = Status.RESULT_STATE_SERVICE_UNAVAILABLE; 161 lastMessage = status.getStatusMessage(); 162 return new ValidatorResponse( lastMessage, status ); 163 } 164 } 165 166 /** 167 * Makes sure that the HttpResponse is not a critical error 168 * 169 * @param statusCode 170 */ 171 protected boolean isValidHttpResponse( int statusCode ) { 172 173 if ( statusCode >= 100 && statusCode < 400 ) { 174 return true; 175 } 176 return false; 177 } 178 179 /** 180 * @param statusCode 181 * @return instance of the validatorresponse with the error 182 */ 183 protected ValidatorResponse validateErrorHttpResponse( int statusCode ) { 184 185 String lastMessage = null; 186 Status status = null; 187 188 if ( statusCode == HttpServletResponse.SC_REQUEST_TIMEOUT ) { 189 status = Status.RESULT_STATE_TIMEOUT; 190 lastMessage = status.getStatusMessage(); 191 } else { 192 status = Status.RESULT_STATE_PAGE_UNAVAILABLE; 193 lastMessage = status.getStatusMessage(); 194 } 195 196 return new ValidatorResponse( lastMessage, status ); 197 } 198 199 /** 200 * Parses a given InputStream to a String 201 * 202 * @param stream 203 * @return String 204 * @throws IOException 205 */ 206 protected String parseStream( InputStream stream ) 207 throws IOException { 208 stream.reset(); 209 InputStreamReader reader = new InputStreamReader( stream ); 210 BufferedReader bufReader = new BufferedReader( reader ); 211 StringBuilder builder = new StringBuilder(); 212 String line = null; 213 214 line = bufReader.readLine(); 215 while ( line != null ) { 216 builder.append( line ); 217 line = bufReader.readLine(); 218 } 219 220 String answer = builder.toString(); 221 return answer; 222 } 223 224 /** 225 * Creates a new instance of DocumentBuilder 226 * 227 * @return DocumentBuilder 228 * @throws IOException 229 */ 230 protected DocumentBuilder instantiateParser() 231 throws IOException { 232 233 DocumentBuilder parser = null; 234 235 try { 236 DocumentBuilderFactory fac = DocumentBuilderFactory.newInstance(); 237 fac.setNamespaceAware( true ); 238 fac.setValidating( false ); 239 fac.setIgnoringElementContentWhitespace( false ); 240 parser = fac.newDocumentBuilder(); 241 return parser; 242 } catch ( ParserConfigurationException e ) { 243 throw new IOException( "Unable to initialize DocumentBuilder: " + e.getMessage() ); 244 } 245 } 246 247 protected boolean closeStream( InputStream stream ) { 248 try { 249 stream.close(); 250 } catch ( IOException e ) { 251 LOG.logError( e.getLocalizedMessage() ); 252 return false; 253 } 254 return true; 255 } 256 257 /** 258 * Creates a new copy of the given InputStream 259 * 260 * @param stream 261 * @return InputStream 262 * @throws IOException 263 */ 264 protected InputStream copyStream( InputStream stream ) 265 throws IOException { 266 ByteArrayOutputStream out = new ByteArrayOutputStream(); 267 int read; 268 byte[] bs = new byte[16384]; 269 while ( ( read = stream.read( bs ) ) != -1 ) { 270 out.write( bs, 0, read ); 271 } 272 return new ByteArrayInputStream( out.toByteArray() ); 273 } 274 }