1 13 package org.jahia.services.applications; 14 15 import org.apache.log4j.Logger; 16 import org.apache.regexp.RE; 17 import org.jahia.bin.Jahia; 18 import org.jahia.data.applications.ApplicationBean; 19 import org.jahia.engines.applications.FullScreenDispatcherEngine; 20 import org.jahia.exceptions.JahiaException; 21 import org.jahia.params.ParamBean; 22 import org.jahia.registries.ServicesRegistry; 23 24 import javax.servlet.ServletContext ; 25 import javax.servlet.ServletOutputStream ; 26 import javax.servlet.http.Cookie ; 27 import javax.servlet.http.HttpServletRequest ; 28 import javax.servlet.http.HttpServletResponse ; 29 import javax.servlet.http.HttpServletResponseWrapper ; 30 import java.util.Properties ; 31 import java.io.PrintWriter ; 32 import java.io.IOException ; 33 import java.io.UnsupportedEncodingException ; 34 import java.io.File ; 35 import java.io.OutputStreamWriter ; 36 import java.net.MalformedURLException ; 37 import java.net.URL ; 38 import java.net.URLEncoder ; 39 40 41 60 public class ServletIncludeResponseWrapper extends HttpServletResponseWrapper { 61 62 private static Logger logger = Logger.getLogger (ServletIncludeResponseWrapper.class); 63 64 private PrintWriter strPrintWriter = null; 66 private StringServletOutputStream strOutputStream = null; 67 private String appUniqueIDStr; private ParamBean jahiaParams; 69 private String emulatedURL; 70 private String contentType; 71 private boolean outputStreamCalled = false; 72 private String redirectLocation = null; 73 private boolean isPassThrough = false; 74 private String encoding = "ISO-8859-1"; 75 private String forceEncoding = null; 76 private static final String APP_ID_SEPARATOR = "_"; 77 private String pageUrlKey; 78 79 80 private static String mFieldIDPart = "(^\\d+)_\\d+"; 81 82 83 84 private static org.apache.regexp.RE mRExpFieldID = null; 85 86 87 static { 88 89 try { 90 mRExpFieldID = new RE (mFieldIDPart); 91 } catch (Throwable t) { 92 logger.debug ("Error while creating regular expression ", t); 93 } 94 95 } 96 97 100 public ServletIncludeResponseWrapper (HttpServletResponse httpServletResponse, 101 boolean passThrough, String forcedEncoding) { 102 super (httpServletResponse); 103 logger.debug ("Initializing using normal mode"); 104 appUniqueIDStr = null; 105 this.isPassThrough = passThrough; 106 this.forceEncoding = forcedEncoding; 107 if (forceEncoding != null) { 108 encoding = forcedEncoding; 109 this.contentType = "text/html; charset=" + forceEncoding; 110 } 111 } 112 113 117 public ServletIncludeResponseWrapper (HttpServletResponse httpServletResponse, 118 String appUniqueID, 119 String emulURL, 120 ParamBean jParams, 121 boolean passThrough, 122 String forcedEncoding) { 123 super (httpServletResponse); 124 logger.debug ("Initializing using emulation mode. appID = [" + appUniqueID + "]"); 125 appUniqueIDStr = appUniqueID; 126 jahiaParams = jParams; 127 emulatedURL = emulURL; 128 this.isPassThrough = passThrough; 129 this.forceEncoding = forcedEncoding; 130 if (forceEncoding != null) { 131 encoding = forcedEncoding; 132 this.contentType = "text/html; charset=" + forceEncoding; 133 } 134 } 135 136 public ServletIncludeResponseWrapper( 137 HttpServletResponse httpServletResponse, String aPageUrlKey, 138 String appUniqueID, String emulURL, ParamBean jParams, 139 boolean passThrough, String forcedEncoding) { 140 super(httpServletResponse); 141 logger.debug("Initializing using emulation mode. appID = [" 142 + appUniqueID + "]"); 143 appUniqueIDStr = appUniqueID; 144 jahiaParams = jParams; 145 emulatedURL = emulURL; 146 this.pageUrlKey = aPageUrlKey; 147 this.isPassThrough = passThrough; 148 this.forceEncoding = forcedEncoding; 149 if (forceEncoding != null) { 150 encoding = forcedEncoding; 151 this.contentType = "text/html; charset=" + forceEncoding; 152 } 153 } 154 155 public PrintWriter getWriter () { 156 logger.debug ("Using a print writer for output"); 157 checkStreams (); 158 if (outputStreamCalled) { 159 logger.debug ( 160 "Servlet compliance warning, OutputStream has already been called, the response output will be reset !"); 161 } 162 return strPrintWriter; 163 } 164 165 public ServletOutputStream getOutputStream () throws IOException { 166 logger.debug ("Using an output stream for output"); 167 checkStreams (); 168 this.outputStreamCalled = true; 169 return strOutputStream; 170 } 171 172 public String getStringBuffer () throws IOException { 173 return getStringBuffer (true); 174 } 175 176 public String getStringBuffer (boolean checkWriterError) throws IOException { 177 try { 178 if (outputStreamCalled) { 179 return strOutputStream.getBuffer (); 181 } else { 182 if (strOutputStream == null) { 184 return null; 185 } else { 186 if (strPrintWriter.checkError () && checkWriterError) { 187 throw new IOException ("An error has occured while writing to output"); 188 } 189 return strOutputStream.getBuffer (); 190 } 191 } 192 } catch (UnsupportedEncodingException uee) { 193 logger.debug ("Error in encoding [" + encoding + " ], returning empty buffer", uee); 194 return ""; 195 } 196 } 197 198 public String getRedirectLocation () { 199 return redirectLocation; 200 } 201 202 public String getCharacterEncoding () { 203 return encoding; 204 } 205 206 public void flushBuffer () { 207 219 logger.debug ("flushBuffer()"); 220 } 221 222 public void resetBuffer () { 223 logger.debug ("resetBuffer()"); 224 } 225 226 public void finishResponse () { 227 logger.debug ("finishResponse()"); 228 } 229 230 public boolean isCommitted () { 231 logger.debug ("isCommitted()"); 232 return false; 233 } 234 235 private static String [][] STATIC_EXTS = { null, null, { "js" }, { "css", "gif", "ico", "jpg", "jpe", "htm", "png", "xml" }, { "jpeg", "html" } }; 241 242 private String internalEncodeURL(String url) { 243 if (url != null && url.length() != 0) { 244 if (url.indexOf("/webdav/") == -1 || url.indexOf('?') == -1) { 245 int point = url.lastIndexOf('.'); int extLen = url.length() - point - 1; 247 if (extLen > 0 && extLen < STATIC_EXTS.length) { 248 String ext = url.substring(point + 1); 249 String [] exts = STATIC_EXTS[extLen]; 250 if (exts != null) { 251 for (int j = 0; j < exts.length; j++) 252 if (ext.equalsIgnoreCase(exts[j])) 253 return url; } 255 } 256 } 257 return super.encodeURL(url); 258 } else 259 return url; 260 } 261 262 276 public String encodeURL (String url) { 277 278 if (url == null) { 279 return null; 280 } 281 282 String servletIncludeURL; 283 284 if (jahiaParams != null && appUniqueIDStr != null) { 285 if (url.toLowerCase ().indexOf (".jsp") == -1) { 286 try { 287 ApplicationBean appBean = ServicesRegistry.getInstance().getJahiaApplicationsManagerService() 290 .getApplication( 291 Integer.parseInt(appUniqueIDStr 292 .substring(appUniqueIDStr.indexOf(APP_ID_SEPARATOR) + 1))); 293 294 if (appBean == null) { 295 logger.debug ( 296 "The requested application [" + appUniqueIDStr + "] is not available"); 297 } 298 299 ServletContext dispatchedContext = Jahia.getThreadParamBean () 300 .getContext ().getContext (appBean.getContext ()); 301 if (dispatchedContext == null) { 302 logger.debug ("Error getting dispatch context [" + 303 appBean.getContext () + "]"); 304 return super.encodeURL (url); 305 } 306 try { 307 String path = url; 308 if (url.startsWith (appBean.getContext ())) { 309 path = url.substring (url.indexOf (appBean.getContext ())) 311 .substring (appBean.getContext ().length ()); 312 } 313 path = dispatchedContext.getRealPath (path); 314 File f = new File (path); 315 if (f.isFile ()) { 316 return super.encodeURL (url); 317 } 318 } catch (Throwable t) { 319 } 320 } catch (Throwable t) { 321 logger.debug ( 322 "Exception retrieving Applicatiton Context appid[" + appUniqueIDStr + "]\n", 323 t); 324 return super.encodeURL (url); 325 } 326 } 327 328 boolean fullScreenEngineOn = false; 329 if (jahiaParams.getEngine ().equals (FullScreenDispatcherEngine.ENGINE_NAME)) { 330 fullScreenEngineOn = true; 331 } 332 333 String realURL = new String (url); 334 if (realURL != null) { 337 if (realURL.startsWith ("###JAHIA###")) { 338 340 realURL = realURL.substring (11); while (realURL.indexOf ("###") >= 0) { 342 int seperatorPos = realURL.indexOf ("###"); 343 String jahiaModifier = realURL.substring (0, seperatorPos); 344 if (jahiaModifier != null) { 345 if ("fullscreen".equals (jahiaModifier.toLowerCase ())) { 346 fullScreenEngineOn = true; 347 } 348 if ("restore".equals (jahiaModifier.toLowerCase ())) { 349 fullScreenEngineOn = false; 350 } 351 } 352 realURL = realURL.substring (seperatorPos + 3); 353 } 354 } 355 } 356 357 HttpServletRequest request = jahiaParams.getRequest(); 358 String urlPort; 359 URL resolvedURL; 360 361 int serverPort = request.getServerPort(); 362 if (serverPort == 80) { 363 urlPort = ""; 364 } else { 365 urlPort = ":" + serverPort; 366 } 367 368 try { 369 URL contextURL = null; 370 if (url.startsWith ("/")) { contextURL = new URL (request.getScheme () + "://" + 373 request.getServerName () + urlPort + "/"); 374 } else { 375 URL emulURL = new URL (emulatedURL); 377 if (emulURL.getPort () != 80 && emulURL.getPort () != -1) { 378 contextURL = new URL (emulURL.getProtocol () + "://" + 379 emulURL.getHost () + ":" + 380 emulURL.getPort () + 381 emulURL.getPath ()); 382 } else { 383 contextURL = new URL (emulURL.getProtocol () + "://" + 384 emulURL.getHost () + 385 emulURL.getPath ()); 386 } 387 } 388 389 logger.debug ("encodeURL.contextURL=[" + contextURL.toString () + "]"); 390 391 resolvedURL = new URL (contextURL, realURL); 392 } catch (MalformedURLException mue) { 393 return null; 394 } 395 396 399 servletIncludeURL = super.encodeURL(resolvedURL.toString()); try { 403 servletIncludeURL = URLEncoder.encode(servletIncludeURL, 404 encoding); 405 } catch (UnsupportedEncodingException ex) { 406 logger.error(ex.getMessage(), ex); 407 } 408 409 try { 410 String anchorID = ServletIncludeResponseWrapper.getFieldIDPart (appUniqueIDStr); 412 if (anchorID != null) { 413 jahiaParams.setAnchor ("field_" + anchorID); 414 } 416 String savedCacheStatus = jahiaParams.getCacheStatus (); 419 jahiaParams.setCacheStatus (ParamBean.CACHE_BYPASS); 420 String fullScreenStr = ""; 421 String fullScreenIDStr = request.getParameter ("fullscreen"); 422 if (fullScreenIDStr == null) { 423 fullScreenIDStr = request.getParameter ("maximize"); 424 } 425 if (fullScreenIDStr != null) { 426 fullScreenStr = "&fullscreen=" + fullScreenIDStr; 427 } 428 429 if (fullScreenEngineOn) { 430 431 Properties extraParams = new Properties (); 434 extraParams.setProperty (ParamBean.PAGE_ID_PARAMETER, 435 Integer.toString (jahiaParams.getPageID ())); 436 servletIncludeURL = jahiaParams.composeEngineUrl( 437 FullScreenDispatcherEngine.ENGINE_NAME, extraParams, 438 "?appid=" + appUniqueIDStr + "&appparams=" 439 + servletIncludeURL + "&resetAppSession=true"); 440 } else { 441 if (pageUrlKey == null) 442 servletIncludeURL = jahiaParams.composeUrl("?appid=" 443 + appUniqueIDStr + fullScreenStr 444 + "&appparams=" + servletIncludeURL 445 + "&resetAppSession=true"); 446 else 447 servletIncludeURL = jahiaParams.composeUrl(pageUrlKey, 448 "?appid=" + appUniqueIDStr + fullScreenStr 449 + "&appparams=" + servletIncludeURL 450 + "&resetAppSession=true"); 451 } 452 jahiaParams.setCacheStatus (savedCacheStatus); 453 } catch (JahiaException je) { 454 servletIncludeURL = null; 455 } 456 457 } else { 458 if (url.indexOf (";jsessionid=") != -1) { 459 logger.debug ( 460 "jsessionid already in URL, ignoring call and returning unmodified URL... "); 461 servletIncludeURL = url; 462 } else { 463 servletIncludeURL = internalEncodeURL(url); } 465 } 466 467 return servletIncludeURL; 468 } 469 470 public String encodeUrl (String URL) { 471 return encodeURL (URL); 472 } 473 474 public void sendRedirect (String location) throws IOException { 475 logger.debug ("location=" + location + ""); 476 if (redirectLocation != null) { 477 logger.debug ("Multiple calls to sendRedirect, keeping only the first one."); 478 } else { 479 if (location.endsWith ("/")) { 480 redirectLocation = location.substring (0, location.length () - 1); 481 } else { 482 redirectLocation = location; 483 } 484 } 485 if (isPassThrough) { 486 logger.debug ( 487 "Pass-through active, sending redirect to wrapped response directly..."); 488 super.sendRedirect (location); 489 } else { 490 logger.debug ("redirectLocation=" + redirectLocation + ""); 491 } 492 } 493 494 495 public void setContentType (java.lang.String type) { 496 logger.debug ("Content-type set to [" + type + "]"); 497 if (contentType != null) { 498 if (!this.contentType.equals (type)) { 499 logger.debug ("Warning, content type has already been set to [" + 500 contentType + "]. Trying to set now to [" + type + 501 "]"); 502 } 503 } 504 if (forceEncoding != null) { 505 logger.debug ("Enforcing charset=[" + forceEncoding + "]"); 506 int separatorPos = type.indexOf (";"); 507 if (separatorPos > 0) { 508 type = type.substring (0, separatorPos); 509 } 510 type += ";charset=" + forceEncoding; 511 } 512 this.contentType = type; 513 int charsetPos = type.toLowerCase ().indexOf ("charset="); 514 if (charsetPos > 0) { 515 encoding = type.toUpperCase ().substring (charsetPos + "charset=".length ()).trim (); 516 } 517 if (isPassThrough) { 518 super.setContentType (this.contentType); 519 try { 520 ServletOutputStream outputStream = super.getResponse (). 521 getOutputStream (); 522 if (outputStream.getClass ().getName ().equals ( 523 "weblogic.servlet.internal.ServletOutputStreamImpl")) { 524 Object o = outputStream.getClass ().getMethod ("getOutput", 525 new Class []{}).invoke (outputStream, new Object []{}); 526 o.getClass ().getMethod ("changeToCharset", 527 new Class []{String .class, 528 Class. 529 forName ("weblogic.servlet.internal.CharsetMap")}). 530 invoke (o, new Object []{null, null}); 531 } 532 } catch (Exception e) { 533 } 534 } else { 535 logger.debug ( 536 "Not setting parent response object because this wrapper is not in pass-through mode"); 537 } 538 } 539 540 546 public String getContentType () { 547 return this.contentType; 548 } 549 550 560 public static String getFieldIDPart (String appUniqueIDStr) { 561 562 if (appUniqueIDStr == null) { 563 return null; 564 } 565 566 mRExpFieldID.match (appUniqueIDStr); 567 return mRExpFieldID.getParen (1); 568 } 569 570 public void addCookie (Cookie cookie) { 571 logger.debug ("Adding cookie name=" + cookie.getName ()); 572 super.addCookie (cookie); 573 } 574 575 private void checkStreams () { 576 if ((strOutputStream == null) && (strPrintWriter == null)) { 577 try { 578 if (isPassThrough) { 580 logger.debug ( 581 "Creating output streams for response wrapper using pass-through servlet output stream..."); 582 strOutputStream = 583 new StringServletOutputStream ( 584 super.getResponse ().getOutputStream (), encoding); 585 } else { 586 logger.debug ( 587 "Creating output streams for response wrapper using only stringbuffers and no pass-through..."); 588 strOutputStream = new StringServletOutputStream (encoding); 589 } 590 OutputStreamWriter streamWriter; 591 if (encoding != null) { 592 logger.debug ("Using PrintWriter with encoding : " + encoding); 593 streamWriter = new OutputStreamWriter (strOutputStream, encoding); 594 } else { 595 streamWriter = new OutputStreamWriter (strOutputStream); 596 } 597 strPrintWriter = new PrintWriter (streamWriter, true); 598 } catch (Exception e) { 599 logger.debug ("Error creating StringPrintWriter object !", e); 600 } 601 } 602 } 603 604 605 } 606 | Popular Tags |