1 10 package org.mmbase.bridge.jsp.taglib.pageflow; 11 12 import org.mmbase.bridge.jsp.taglib.util.Attribute; 13 import org.mmbase.bridge.jsp.taglib.util.Referids; 14 import org.mmbase.bridge.jsp.taglib.util.Notfound; 15 import org.mmbase.bridge.jsp.taglib.TaglibException; 16 import org.mmbase.bridge.jsp.taglib.ContextTag; 17 import org.mmbase.bridge.NotFoundException; 18 import java.net.*; 19 import java.io.*; 21 import javax.servlet.jsp.JspTagException ; 22 import javax.servlet.jsp.tagext.BodyContent ; 23 import javax.servlet.http.*; 24 import javax.servlet.*; 25 26 import java.util.*; 27 28 import org.mmbase.util.*; 29 import org.mmbase.util.logging.Logger; 30 import org.mmbase.util.logging.Logging; 31 32 39 40 public class IncludeTag extends UrlTag { 41 42 private static final Logger log = Logging.getLoggerInstance(IncludeTag.class); 43 private static final Logger pageLog = Logging.getLoggerInstance(Logging.PAGE_CATEGORY); 44 45 private static final int DEBUG_NONE = 0; 46 private static final int DEBUG_HTML = 1; 47 private static final int DEBUG_CSS = 2; 48 private static final int DEBUG_XML = 3; 49 50 public static final String INCLUDE_PATH_KEY = "javax.servlet.include.servlet_path"; 51 public static final String INCLUDE_LEVEL_KEY = "org.mmbase.taglib.includeLevel"; 52 53 54 protected Attribute debugType = Attribute.NULL; 55 56 private Attribute cite = Attribute.NULL; 57 58 private Attribute encodingAttribute = Attribute.NULL; 59 60 private Attribute attributes = Attribute.NULL; 61 62 protected Attribute notFound = Attribute.NULL; 63 64 protected Attribute resource = Attribute.NULL; 65 66 67 70 public void setCite(String c) throws JspTagException { 71 cite = getAttribute(c); 72 } 73 74 public void setEncoding(String e) throws JspTagException { 75 encodingAttribute = getAttribute(e); 76 } 77 78 public void setNotfound(String n) throws JspTagException { 79 notFound = getAttribute(n); 80 } 81 82 protected boolean getCite() throws JspTagException { 83 return resource != Attribute.NULL || cite.getBoolean(this, false); 84 } 85 86 public void setAttributes(String a) throws JspTagException { 87 attributes = getAttribute(a); 88 } 89 90 public void setResource(String r) throws JspTagException { 91 resource = getAttribute(r); 92 } 93 94 protected String getPage() throws JspTagException { 95 if (resource != Attribute.NULL) return resource.getString(this); 96 return super.getPage(); 97 } 98 99 public int doStartTag() throws JspTagException { 100 if (page == Attribute.NULL && resource == Attribute.NULL) { throw new JspTagException ("No attribute 'page' or 'resource' was specified"); 102 } 103 return super.doStartTag(); 104 } 105 106 protected void doAfterBodySetValue() throws JspTagException { 107 includePage(); 108 } 109 112 private void external(BodyContent bodyContent, String absoluteUrl, HttpServletRequest request, HttpServletResponse response) throws JspTagException { 113 if (log.isDebugEnabled()) { 114 log.debug("External: found url: >" + absoluteUrl + "<"); 115 } 116 try { 117 URL includeURL = new URL(absoluteUrl); 118 119 HttpURLConnection connection = (HttpURLConnection) includeURL.openConnection(); 120 121 if (request != null) { 122 Cookie[] cookies = request.getCookies(); 125 if (cookies != null) { 126 StringBuffer koekjes = new StringBuffer (); 127 for (int i=0; i < cookies.length; i++) { 128 if (log.isDebugEnabled()) { 129 log.debug("setting cookie " + i + ":" + cookies[i].getName() + "=" + cookies[i].getValue()); 130 } 131 koekjes.append((i > 0 ? ";" : "")).append(cookies[i].getName()).append("=").append(cookies[i].getValue()); 132 } 133 connection.setRequestProperty("Cookie", koekjes.toString()); 134 } 135 } 136 137 String result; 138 int responseCode; 139 try { 140 responseCode = connection.getResponseCode(); 141 if (responseCode < 300) { 143 144 String encoding = encodingAttribute.getString(this); 145 if (encoding.equals("")) { 146 encoding = connection.getContentEncoding(); 147 } 148 log.debug("Found content encoding " + encoding); 149 ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 150 InputStream inputStream = connection.getInputStream(); 151 int c = inputStream.read(); 152 while (c != -1) { 153 bytes.write(c); 154 c = inputStream.read(); 155 } 156 byte[] allBytes = bytes.toByteArray(); 157 if (encoding == null || encoding.equals("")) { 158 String contentType = connection.getContentType(); 159 if (contentType != null) { 160 encoding = GenericResponseWrapper.getEncoding(contentType); 162 } 163 164 if (encoding == null && contentType != null) { encoding = GenericResponseWrapper.getDefaultEncoding(contentType); 166 } 167 if (encoding.equals(GenericResponseWrapper.TEXT_XML_DEFAULT_CHARSET)) { encoding = GenericResponseWrapper.getXMLEncoding(allBytes); } 170 171 } 172 log.debug("Using " + encoding); 173 result = new String (allBytes, encoding) + debugEnd(absoluteUrl); 174 175 } else { 176 if (responseCode >= 500) { 177 result = "Server error " + responseCode + " during mm:include of " + includeURL + " " + connection.getResponseMessage(); 178 } else if (responseCode >= 400) { 179 result = "Client error " + responseCode + " during mm:include of " + includeURL + " " + connection.getResponseMessage(); 180 } else { result = "Redirect " + responseCode + " during mm:include of " + includeURL + " " + connection.getResponseMessage() + " " + connection.getInstanceFollowRedirects(); 182 } 183 } 184 } catch (java.net.ConnectException ce) { 185 result = "For " + includeURL + ": " + ce.getMessage(); 186 responseCode = -1; 187 } 188 189 handleResponse(responseCode, result, absoluteUrl); 190 191 if (log.isDebugEnabled()) { 192 log.debug("found string: " + helper.getValue()); 193 } 194 195 } catch (IOException e) { 196 throw new TaglibException (e.getMessage(), e); 197 } 198 } 199 200 204 private void externalRelative(BodyContent bodyContent, String relativeUrl, HttpServletRequest request, HttpServletResponse response) throws JspTagException { 205 external(bodyContent, 206 request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + relativeUrl, 207 request, response); 208 } 209 210 211 protected boolean addContext() { 212 return false; 213 } 214 215 218 protected void handleResponse(int code, String result, String url) throws JspTagException { 219 220 String page; 221 switch(code) { 222 case 200: 223 page = result; 224 break; 225 default: 226 case 404: 227 switch(Notfound.get(notFound, this)) { 228 case Notfound.SKIP: 229 case Notfound.PROVIDENULL: 230 page = ""; 231 break; 232 case Notfound.THROW: 233 if ("".equals(result)) result = "The requested resource '" + url + "' is not available"; 234 throw new JspTagException (result); 235 default: 236 case Notfound.DEFAULT: 237 case Notfound.MESSAGE: 238 if ("".equals(result)) result = "The requested resource '" + url + "' is not available"; 239 page = result; 240 } 241 break; 242 } 243 helper.setValue(debugStart(url) + page + debugEnd(url)); 244 } 245 249 private void internal(BodyContent bodyContent, String relativeUrl, HttpServletRequest req, HttpServletResponse resp) throws JspTagException { 250 if (log.isDebugEnabled()) { 251 log.debug("Internal: found url: >" + relativeUrl + "<"); 252 String targetEncoding = resp.getCharacterEncoding(); 253 log.debug("encoding: " + targetEncoding); 254 log.debug("req Parameters"); 255 Map params = req.getParameterMap(); 256 Iterator i = params.entrySet().iterator(); 257 Object o; 258 while (i.hasNext()) { 259 Map.Entry e = (Map.Entry) i.next(); 260 o = e.getValue(); 261 if (o instanceof String []) { 262 log.debug("key '" + e.getKey() + "' value '" + Arrays.asList((String []) o) + "'"); 263 } else { 264 log.debug("key '" + e.getKey() + "' value '" + o.toString() + "'"); 265 } 266 } 267 } 268 269 req.removeAttribute(ContextTag.CONTEXTTAG_KEY); 270 271 if (attributes != Attribute.NULL) { 272 Iterator i = Referids.getReferids(attributes, this).entrySet().iterator(); 273 while (i.hasNext()) { 274 Map.Entry entry = (Map.Entry) i.next(); 275 req.setAttribute((String ) entry.getKey(), entry.getValue()); 276 } 277 278 } 279 req.getParameterMap(); 281 282 HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper(req); 283 284 try { 285 ServletContext sc = pageContext.getServletContext(); 286 if (sc == null) log.error("Cannot retrieve ServletContext from PageContext"); 287 RequestDispatcher requestDispatcher = sc.getRequestDispatcher(relativeUrl); 288 if (requestDispatcher == null) { 289 throw new NotFoundException("Page \"" + relativeUrl + "\" does not exist (No request-dispatcher could be created)"); 290 } 291 292 IncludeWrapper responseWrapper; 293 String encoding = encodingAttribute.getString(this); 294 if (encoding.equals("")) { 295 responseWrapper = new IncludeWrapper(resp); 296 } else { 297 responseWrapper = new IncludeWrapper(resp, encoding); 298 } 299 requestDispatcher.include(requestWrapper, responseWrapper); 300 301 handleResponse(responseWrapper.getStatus(), responseWrapper.toString(), relativeUrl); 302 303 304 } catch (Throwable e) { 305 log.error(relativeUrl + " " + Logging.stackTrace(e)); 306 throw new TaglibException(relativeUrl + " " + e.getMessage(), e); 307 } 308 309 if (log.isDebugEnabled()) { 310 log.debug("req Parameters"); 311 Map params = req.getParameterMap(); 312 Iterator i = params.entrySet().iterator(); 313 while (i.hasNext()) { 314 Map.Entry e = (Map.Entry) i.next(); 315 log.debug("key '" + e.getKey() + "' value '" + e.getValue() + "'"); 316 } 317 } 318 } 319 320 321 322 330 private void cite(BodyContent bodyContent, String relativeUrl, HttpServletRequest request) throws JspTagException { 331 try { 332 if (log.isDebugEnabled()) log.trace("Citing " + relativeUrl); 333 if (resource == Attribute.NULL) { 334 if (relativeUrl.indexOf("..") > -1 || relativeUrl.toUpperCase().indexOf("WEB-INF") > -1) { throw new JspTagException ("Not allowed to cite " + relativeUrl); 336 } 337 } 338 339 { int j = relativeUrl.lastIndexOf(';'); 344 if (j != -1) { 345 relativeUrl = relativeUrl.substring(0, j); 346 } 347 348 } 349 350 351 String resource = relativeUrl; 352 if (log.isDebugEnabled()) log.debug("Citing " + resource); 353 354 355 Reader reader = ResourceLoader.getWebRoot().getReader(resource); 356 if (reader == null) { 357 handleResponse(404, "No such resource " + resource, resource); 358 } else { 359 StringWriter writer = new StringWriter(); 360 while (true) { 361 int c = reader.read(); 362 if (c == -1) break; 363 writer.write(c); 364 } 365 handleResponse(200, writer.toString(), resource); 366 } 367 368 } catch (IOException e) { 369 throw new TaglibException (e); 370 } 371 } 372 373 376 protected void includePage() throws JspTagException { 377 String gotUrl = null; 378 try { 379 gotUrl = getUrl(false, false); 381 if (gotUrl == null || "".equals(gotUrl)) { 382 return; } 384 385 if (pageLog.isServiceEnabled()) { 386 pageLog.service("Parsing mm:include JSP page: " + gotUrl); 387 } 388 389 String nudeUrl; String params; int paramsIndex = gotUrl.indexOf('?'); 393 if (paramsIndex != -1) { 394 nudeUrl = gotUrl.substring(0, paramsIndex); 395 params = gotUrl.substring(paramsIndex); 396 } else { 397 nudeUrl = gotUrl; 398 params = ""; 399 } 400 if (log.isDebugEnabled()) { 401 log.debug("Found nude url " + nudeUrl); 402 } 403 HttpServletRequest request = (HttpServletRequest) pageContext.getRequest(); 404 HttpServletResponse response = (HttpServletResponse) pageContext.getResponse(); 405 406 407 if (nudeUrl.indexOf(':') == -1) { Integer level = (Integer ) request.getAttribute(INCLUDE_LEVEL_KEY); 410 int includeLevel; 411 if (level == null) { 412 includeLevel = 0; 413 } else { 414 includeLevel = level.intValue(); 415 } 416 417 String includingServlet = (String ) request.getAttribute(INCLUDE_PATH_KEY); 420 if (includingServlet == null) { 421 includingServlet = request.getServletPath(); 422 } 423 if (log.isDebugEnabled()) { 424 log.debug("Including from : Level=" + includeLevel + " URI=" + includingServlet); 425 } 426 427 String includedServlet; 428 if (nudeUrl.startsWith("/")) { 429 log.debug("URL was absolute on servletcontext"); 430 includedServlet = gotUrl; 431 } else { 432 log.debug("URL was relative"); 433 URL u = new URL("http", "localhost", includingServlet); 435 URL dir = new URL(u, "."); 437 File currentDir = new File(includingServlet + "includetagpostfix"); nudeUrl = new URL(dir, nudeUrl).getFile(); 439 includedServlet = nudeUrl + params; 440 } 441 442 includeLevel++; 444 request.setAttribute(INCLUDE_LEVEL_KEY, new Integer (includeLevel)); 445 446 if (log.isDebugEnabled()) { 447 log.debug("Next Include: Level=" + includeLevel + " URI=" + includedServlet); 448 } 449 450 if (getCite()) { 451 cite(bodyContent, includedServlet, request); 452 } else { 453 internal(bodyContent, includedServlet, request, response); 454 } 455 includeLevel--; 457 if (includeLevel == 0) { 458 request.removeAttribute(INCLUDE_LEVEL_KEY); 459 } else { 460 request.setAttribute(INCLUDE_LEVEL_KEY, new Integer (includeLevel)); 461 } 462 463 } else { if (getCite()) { 465 cite(bodyContent, gotUrl, request); 466 } else { 467 external(bodyContent, gotUrl, null, response); } 470 } 471 472 } catch (IOException e) { 473 throw new TaglibException (e); 474 } 475 if (pageLog.isDebugEnabled()) { 476 pageLog.debug("END Parsing mm:include JSP page " + gotUrl); 477 } 478 } 479 480 484 public void setDebug(String p) throws JspTagException { 485 debugType = getAttribute(p); 486 } 487 488 protected int getDebug() throws JspTagException { 489 490 if (debugType == Attribute.NULL) return DEBUG_NONE; 491 492 String dtype = debugType.getString(this).toLowerCase(); 493 if (dtype.equals("none")) { 494 return DEBUG_NONE; } else if (dtype.equals("html")) { 497 return DEBUG_HTML; 498 } else if (dtype.equals("xml")) { 499 return DEBUG_XML; 500 } else if (dtype.equals("css")) { 501 return DEBUG_CSS; 502 } else { 503 throw new JspTagException ("Unknow value for debug attribute " + dtype); 504 } 505 } 506 507 510 protected String getThisName() { 511 String clazz = this.getClass().getName(); 512 return clazz.substring(clazz.lastIndexOf(".") + 1); 513 } 514 515 518 private String debugStart(String url) throws JspTagException { 519 switch(getDebug()) { 520 case DEBUG_NONE: return ""; 521 case DEBUG_HTML: 522 return "\n<!-- " + getThisName() + " page = '" + url + "' -->\n"; 523 case DEBUG_XML: 524 return "<!-- " + getThisName() + " page = '" + url + "' -->"; 525 case DEBUG_CSS: return "\n/* " + getThisName() + " page = '" + url + "' */\n"; 526 default: return ""; 527 } 528 } 529 530 533 private String debugEnd(String url) throws JspTagException { 534 switch(getDebug()) { 535 case DEBUG_NONE: return ""; 536 case DEBUG_HTML: 537 return "\n<!-- END " + getThisName() + " page = '" + url + "' -->\n"; 538 case DEBUG_XML: 539 return "<!-- END " + getThisName() + " page = '" + url + "' -->"; 540 case DEBUG_CSS: return "\n/* END " + getThisName() + " page = '" + url + "' */\n"; 541 default: return ""; 542 } 543 } 544 private static class IncludeWrapper extends GenericResponseWrapper { 545 int includeStatus = 200; 546 public IncludeWrapper(HttpServletResponse resp) { 547 super(resp); 548 } 549 public IncludeWrapper(HttpServletResponse resp, String encoding) { 550 super(resp, encoding); 551 } 552 553 public void setStatus(int status) { 555 includeStatus = status; 556 } 557 public void sendError(int sc, String mes) { 558 includeStatus = sc; 559 } 560 public void sendError(int sc) { 561 includeStatus = sc; 562 } 563 public int getStatus() { 564 return includeStatus; 565 } 566 567 } 568 } 569 | Popular Tags |