1 16 17 package org.apache.commons.latka.validators; 18 19 import java.io.IOException ; 20 21 import org.apache.commons.latka.ValidationException; 22 import org.apache.commons.latka.http.Response; 23 24 import org.jdom.Document; 25 import org.jdom.Element; 26 import org.jdom.JDOMException; 27 import org.jdom.input.SAXBuilder; 28 import org.jaxen.jdom.JDOMXPath; 29 import org.jaxen.JaxenException; 30 31 76 public class XPathValidator extends BaseConditionalValidator { 77 78 82 protected String _select = null; 83 protected String _value = null; 84 protected Object _lastSelected = null; 86 87 89 public XPathValidator() { 90 this(null,null,true,null); 91 } 92 93 public XPathValidator(String label) { 94 this(label,null,true,null); 95 } 96 97 public XPathValidator(String label, String select, boolean cond, String value) { 98 super(label,cond); 99 _select = select; 100 _value = value; 101 } 102 103 105 public void setSelect(String select) { 106 _select = select; 107 } 108 109 public void setValue(String value) { 110 _value = value; 111 } 112 113 public boolean assertTrue(Response response) 114 throws ValidationException { 115 116 JDOMXPath xpath = getJDOMXPath(_select); Document doc = getDocument(response); Object selected = getSelectedNode(xpath, doc); _lastSelected = selected; 120 121 if (selected == null) { 122 return false; 123 } 124 125 131 if (selected instanceof Boolean ) { 132 _log.debug("Boolean XPath expression evaluated to "+selected); 134 if (_value != null) { 135 _log.warn("Ignoring unused value '"+_value+"'."); 136 } 137 boolean matched = ((Boolean )selected).booleanValue(); 138 139 return matched; 140 141 } else if (selected instanceof String ) { 142 _log.debug("XPath selected string '"+selected+"'."); 143 if (_value != null) { 144 boolean matched = selected.equals(_value); 145 146 return matched; 147 } else { 148 return true; 150 } 151 } else if (selected instanceof Element) { 152 if (_log.isDebugEnabled()) { 153 _log.debug("XPath matched element: "); 154 _log.debug(printElement((Element)selected)); 155 } 156 if (_value != null) { 157 _log.warn("Ignoring unused value '"+_value+"'."); 158 } 159 160 return true; 162 } else { 163 if (_value != null) { 165 boolean matched = selected.equals(_value); 167 168 return matched; 169 170 } else { 171 _log.warn("Selected unknown type "+selected.getClass().getName()); 172 return true; 174 } 175 } 176 } 177 178 public String generateBareExceptionMessage() { 179 180 if (_lastSelected == null) { 181 return " THAT BOOLEAN XPATH '"+_select+"' WOULD SELECT SOME NODE."; 182 } 183 184 if (_lastSelected instanceof Boolean ) { 185 return " THAT BOOLEAN XPATH '"+_select+"' WOULD RETURN '" + getCondition() + "'."; 186 } else if (_lastSelected instanceof String ) { 187 if (_value != null) { 188 StringBuffer buf = new StringBuffer (); 189 buf.append(" THAT XPATH '"); 190 buf.append(_select); 191 buf.append("' WOULD SELECT '"); 192 buf.append(_value); 193 buf.append("', RECEIVED '"); 194 buf.append(_lastSelected); 195 buf.append("'."); 196 return buf.toString(); 197 } else { 198 return " THAT XPATH '" + _select + "' WOULD SELECT SOMETHING."; 200 } 201 } else if (_lastSelected instanceof Element) { 202 return " THAT XPATH '" + _select + "' WOULD SELECT SOMETHING."; 204 } else { 205 if (_value != null) { 207 return " THAT XPATH EXPRESSION '"+_select+"' WOULD RETURN '" + _value + 208 "', RETURNED UNKNOWN TYPE "+_lastSelected.getClass().getName()+ "."; 209 } else { 210 _log.warn("Selected unknown type "+_lastSelected.getClass().getName()); 211 return " THAT XPATH '" + _select + "' WOULD SELECT SOMETHING."; 213 } 214 } 215 } 216 217 219 225 private JDOMXPath getJDOMXPath(final String xpathExpr) 226 throws ValidationException 227 { 228 JDOMXPath xpath = null; 229 try { 230 xpath = new JDOMXPath(xpathExpr); 231 } catch (JaxenException e) { 232 fail("Couldn't compile JDOMXPath xpathExpr "+xpathExpr+": "+e.toString()); 233 } 234 235 if (xpath == null) { fail("Null compiled XPath object"); 237 } 238 239 if (_log.isDebugEnabled()) { 240 _log.debug("Using XPath expression: "+xpathExpr); 241 } 242 return xpath; 243 } 244 245 253 private Document getDocument(Response response) 254 throws ValidationException 255 { 256 Document doc = null; 257 SAXBuilder builder = new SAXBuilder(); 258 try { 259 doc = builder.build(response.getStream()); 260 } catch (Exception e) { 261 if (e instanceof IOException || e instanceof JDOMException) { 262 fail(e.toString()); 263 } else { 264 fail("Unknown exception caught: " + e.toString()); 265 } 266 } 267 if (doc == null) { fail("Null document"); 269 } 270 if (_log.isDebugEnabled()) { 271 _log.debug("Processing doc: "+printDoc(doc)); 272 } 273 return doc; 274 } 275 276 290 private Object getSelectedNode(JDOMXPath xpath, Document doc) 291 throws ValidationException 292 { 293 Object selected = null; 294 try { 295 selected = xpath.selectSingleNode(doc); 296 } catch (JaxenException e) { 297 fail("XPath expression '"+_select+"' didn't match any node. "+e.toString()); 298 } 299 300 return selected; 301 } 302 303 308 private String printDoc(final Document doc) { 309 java.io.StringWriter sw = new java.io.StringWriter (); 310 try { 311 new org.jdom.output.XMLOutputter().output(doc, sw); 312 } catch (java.io.IOException ioe) { 313 _log.error("Could not print XML document.", ioe); 314 } 315 return sw.toString(); 316 } 317 318 323 private String printElement(final Element elem) { 324 java.io.StringWriter sw = new java.io.StringWriter (); 325 Element clone = (Element)((Element)elem).clone(); 326 org.jdom.output.XMLOutputter xmlOut = new org.jdom.output.XMLOutputter(); 327 try { 328 xmlOut.output(new org.jdom.Document(clone), sw); 329 } catch (java.io.IOException ioe) { 330 _log.error("Could not print XML element.", ioe); 331 } 332 return sw.toString(); 333 } 334 } 335 | Popular Tags |