1 16 package org.apache.myfaces.renderkit.html; 17 18 import org.apache.myfaces.config.MyfacesConfig; 19 import org.apache.myfaces.renderkit.html.util.DummyFormResponseWriter; 20 import org.apache.myfaces.renderkit.html.util.DummyFormUtils; 21 import org.apache.myfaces.renderkit.html.util.HTMLEncoder; 22 import org.apache.myfaces.renderkit.html.util.JavascriptUtils; 23 import org.apache.myfaces.renderkit.html.util.UnicodeEncoder; 24 import org.apache.myfaces.renderkit.RendererUtils; 25 import org.apache.commons.logging.Log; 26 import org.apache.commons.logging.LogFactory; 27 28 import javax.faces.component.UIComponent; 29 import javax.faces.context.FacesContext; 30 import javax.faces.context.ResponseWriter; 31 import java.io.IOException ; 32 import java.io.Writer ; 33 import java.util.HashSet ; 34 import java.util.Set ; 35 36 102 public class HtmlResponseWriterImpl 103 extends ResponseWriter 104 implements DummyFormResponseWriter 105 { 106 private static final Log log = LogFactory.getLog(HtmlResponseWriterImpl.class); 107 108 private static final String DEFAULT_CONTENT_TYPE = "text/html"; 109 private static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1"; 110 111 private boolean _writeDummyForm = false; 112 private Set _dummyFormParams = null; 113 114 private Writer _writer; 115 private String _contentType; 116 private String _characterEncoding; 117 private String _startElementName; 118 private UIComponent _startElementUIComponent; 119 private boolean _startTagOpen; 120 121 private static final Set s_emptyHtmlElements = new HashSet (); 122 123 static 124 { 125 s_emptyHtmlElements.add("area"); 126 s_emptyHtmlElements.add("br"); 127 s_emptyHtmlElements.add("base"); 128 s_emptyHtmlElements.add("basefont"); 129 s_emptyHtmlElements.add("col"); 130 s_emptyHtmlElements.add("frame"); 131 s_emptyHtmlElements.add("hr"); 132 s_emptyHtmlElements.add("img"); 133 s_emptyHtmlElements.add("input"); 134 s_emptyHtmlElements.add("isindex"); 135 s_emptyHtmlElements.add("link"); 136 s_emptyHtmlElements.add("meta"); 137 s_emptyHtmlElements.add("param"); 138 } 139 140 public HtmlResponseWriterImpl(Writer writer, String contentType, String characterEncoding) 141 { 142 _writer = writer; 143 _contentType = contentType; 144 if (_contentType == null) 145 { 146 if (log.isInfoEnabled()) log.debug("No content type given, using default content type " + DEFAULT_CONTENT_TYPE); 147 _contentType = DEFAULT_CONTENT_TYPE; 148 } 149 _characterEncoding = characterEncoding; 150 if (_characterEncoding == null) 151 { 152 if (log.isInfoEnabled()) log.debug("No character encoding given, using default character encoding " + DEFAULT_CHARACTER_ENCODING); 153 _characterEncoding = DEFAULT_CHARACTER_ENCODING; 154 } 155 } 156 157 public static boolean supportsContentType(String contentType) 158 { 159 return true; 161 } 162 163 public String getContentType() 164 { 165 return _contentType; 166 } 167 168 public String getCharacterEncoding() 169 { 170 return _characterEncoding; 171 } 172 173 public void flush() throws IOException 174 { 175 closeStartTagIfNecessary(); 179 } 180 181 public void startDocument() 182 { 183 } 185 186 public void endDocument() throws IOException 187 { 188 flush(); 189 if (_writeDummyForm) 190 { 191 DummyFormUtils.writeDummyForm(this, _dummyFormParams); 192 } 193 194 FacesContext facesContext = FacesContext.getCurrentInstance(); 195 MyfacesConfig myfacesConfig = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()); 196 if (myfacesConfig.isDetectJavascript()) 197 { 198 if (! JavascriptUtils.isJavascriptDetected(facesContext.getExternalContext())) 199 { 200 write("<script type=\"text/javascript\">\n<!--\ndocument.location.replace('" + facesContext.getApplication().getViewHandler().getResourceURL(facesContext, "/_javascriptDetector_") + "?goto=" + facesContext.getApplication().getViewHandler().getActionURL(facesContext, facesContext.getViewRoot().getViewId()) +"');\n//-->\n</script>"); 201 } 202 } 203 204 if (myfacesConfig.isAutoScroll()) 205 { 206 JavascriptUtils.renderAutoScrollFunction(facesContext, this); 207 } 208 209 _writer.flush(); 210 } 211 212 public void startElement(String name, UIComponent uiComponent) throws IOException 213 { 214 if (name == null) 215 { 216 throw new NullPointerException ("elementName name must not be null"); 217 } 218 219 closeStartTagIfNecessary(); 220 _writer.write('<'); 221 _writer.write(name); 222 _startElementName = name; 223 _startElementUIComponent = uiComponent; 224 _startTagOpen = true; 225 } 226 227 private void closeStartTagIfNecessary() throws IOException 228 { 229 if (_startTagOpen) 230 { 231 if (s_emptyHtmlElements.contains(_startElementName.toLowerCase())) 232 { 233 _writer.write("/>"); 234 _startElementName = null; 237 } 238 else 239 { 240 _writer.write('>'); 241 } 242 _startTagOpen = false; 243 } 244 } 245 246 public void endElement(String name) throws IOException 247 { 248 if (name == null) 249 { 250 throw new NullPointerException ("elementName name must not be null"); 251 } 252 253 if (log.isWarnEnabled()) 254 { 255 if (_startElementName != null && 256 !name.equals(_startElementName)) 257 { 258 if (log.isWarnEnabled()) 259 log.warn("HTML nesting warning on closing " + name + ": element " + _startElementName + 260 (_startElementUIComponent==null?"":(" rendered by component : "+ 261 RendererUtils.getPathToComponent(_startElementUIComponent)))+" not explicitly closed"); 262 } 263 } 264 265 if(_startTagOpen) 266 { 267 if (s_emptyHtmlElements.contains(name.toLowerCase())) 269 { 270 _writer.write("/>"); 271 } 272 else 273 { 274 _writer.write("></"); 275 _writer.write(name); 276 _writer.write('>'); 277 } 278 _startTagOpen = false; 279 } 280 else 281 { 282 if (s_emptyHtmlElements.contains(name.toLowerCase())) 283 { 284 if (log.isWarnEnabled()) 285 log.warn("HTML nesting warning on closing " + name + ": This element must not contain nested elements or text in HTML"); 286 } 287 else 288 { 289 _writer.write("</"); 290 _writer.write(name); 291 _writer.write('>'); 292 } 293 } 294 295 _startElementName = null; 296 _startElementUIComponent = null; 297 } 298 299 public void writeAttribute(String name, Object value, String componentPropertyName) throws IOException 300 { 301 if (name == null) 302 { 303 throw new NullPointerException ("attributeName name must not be null"); 304 } 305 if (!_startTagOpen) 306 { 307 throw new IllegalStateException ("Must be called before the start element is closed (attribute '" + name + "')"); 308 } 309 310 if (value instanceof Boolean ) 311 { 312 if (((Boolean )value).booleanValue()) 313 { 314 _writer.write(' '); 316 _writer.write(name); 317 _writer.write("=\""); 318 _writer.write(name); 319 _writer.write('"'); 320 } 321 } 322 else 323 { 324 String strValue = value.toString(); _writer.write(' '); 326 _writer.write(name); 327 _writer.write("=\""); 328 _writer.write(HTMLEncoder.encode(strValue, false, false)); 329 _writer.write('"'); 330 } 331 } 332 333 public void writeURIAttribute(String name, Object value, String componentPropertyName) throws IOException 334 { 335 if (name == null) 336 { 337 throw new NullPointerException ("attributeName name must not be null"); 338 } 339 if (!_startTagOpen) 340 { 341 throw new IllegalStateException ("Must be called before the start element is closed (attribute '" + name + "')"); 342 } 343 344 String strValue = value.toString(); _writer.write(' '); 346 _writer.write(name); 347 _writer.write("=\""); 348 if (strValue.toLowerCase().startsWith("javascript:")) 349 { 350 _writer.write(HTMLEncoder.encode(strValue, false, false)); 351 } 352 else 353 { 354 378 _writer.write(strValue); 379 } 380 _writer.write('"'); 381 } 382 383 public void writeComment(Object value) throws IOException 384 { 385 if (value == null) 386 { 387 throw new NullPointerException ("comment name must not be null"); 388 } 389 390 closeStartTagIfNecessary(); 391 _writer.write("<!--"); 392 _writer.write(value.toString()); _writer.write("-->"); 394 } 395 396 public void writeText(Object value, String componentPropertyName) throws IOException 397 { 398 if (value == null) 399 { 400 throw new NullPointerException ("text name must not be null"); 401 } 402 403 closeStartTagIfNecessary(); 404 if(value == null) 405 return; 406 407 String strValue = value.toString(); 409 if (isScriptOrStyle()) 410 { 411 _writer.write(UnicodeEncoder.encode(strValue, false, false)); 412 } 413 else 414 { 415 _writer.write(HTMLEncoder.encode(strValue, false, false)); 416 } 417 } 418 419 public void writeText(char cbuf[], int off, int len) throws IOException 420 { 421 if (cbuf == null) 422 { 423 throw new NullPointerException ("cbuf name must not be null"); 424 } 425 if (cbuf.length < off + len) 426 { 427 throw new IndexOutOfBoundsException ((off + len) + " > " + cbuf.length); 428 } 429 430 closeStartTagIfNecessary(); 431 432 if (isScriptOrStyle()) 433 { 434 String strValue = new String (cbuf, off, len); 435 _writer.write(UnicodeEncoder.encode(strValue, false, false)); 436 } 437 else if (isTextarea()) 438 { 439 String strValue = new String (cbuf, off, len); 442 _writer.write(HTMLEncoder.encode(strValue, false, false)); 443 } 444 else 445 { 446 String strValue = new String (cbuf, off, len); 449 _writer.write(HTMLEncoder.encode(strValue, true, true)); 450 } 451 } 452 453 private boolean isScriptOrStyle() 454 { 455 return _startElementName != null && 456 (_startElementName.equalsIgnoreCase(HTML.SCRIPT_ELEM) || 457 _startElementName.equalsIgnoreCase(HTML.STYLE_ELEM)); 458 } 459 460 private boolean isTextarea() 461 { 462 return _startElementName != null && 463 (_startElementName.equalsIgnoreCase(HTML.TEXTAREA_ELEM)); 464 } 465 466 467 public ResponseWriter cloneWithWriter(Writer writer) 468 { 469 HtmlResponseWriterImpl newWriter 470 = new HtmlResponseWriterImpl(writer, getContentType(), getCharacterEncoding()); 471 newWriter._writeDummyForm = _writeDummyForm; 472 newWriter._dummyFormParams = _dummyFormParams; 473 return newWriter; 474 } 475 476 477 479 public void close() throws IOException 480 { 481 if (_startTagOpen) 482 { 483 _writer.write(" />"); 485 } 486 _writer.close(); 487 } 488 489 public void write(char cbuf[], int off, int len) throws IOException 490 { 491 closeStartTagIfNecessary(); 492 String strValue = new String (cbuf, off, len); 493 _writer.write(UnicodeEncoder.encode(strValue, false, false)); 494 } 495 496 public void write(int c) throws IOException 497 { 498 closeStartTagIfNecessary(); 499 _writer.write(c); 500 } 501 502 public void write(char cbuf[]) throws IOException 503 { 504 closeStartTagIfNecessary(); 505 String strValue = new String (cbuf); 506 _writer.write(UnicodeEncoder.encode(strValue, false, false)); 507 } 508 509 public void write(String str) throws IOException 510 { 511 closeStartTagIfNecessary(); 512 if (str.length() > 0) 515 { 516 _writer.write(UnicodeEncoder.encode(str, false, false)); 517 } 518 } 519 520 public void write(String str, int off, int len) throws IOException 521 { 522 closeStartTagIfNecessary(); 523 String strValue = str.substring(off, off+len); 524 _writer.write(UnicodeEncoder.encode(strValue, false, false)); 525 } 526 527 529 public void setWriteDummyForm(boolean writeDummyForm) 530 { 531 _writeDummyForm = writeDummyForm; 532 } 533 534 public String getDummyFormName() 535 { 536 return DummyFormUtils.DUMMY_FORM_NAME; 537 } 538 539 public void addDummyFormParameter(String paramName) 540 { 541 if (_dummyFormParams == null) 542 { 543 _dummyFormParams = new HashSet (); 544 } 545 _dummyFormParams.add(paramName); 546 } 547 548 public Set getDummyFormParams() 549 { 550 return _dummyFormParams; 551 } 552 } 553 | Popular Tags |