1 10 package org.mmbase.servlet; 11 12 import java.io.IOException ; 13 import java.util.regex.*; 14 15 import javax.servlet.ServletException ; 16 import javax.servlet.http.*; 17 18 import org.mmbase.bridge.*; 19 import org.mmbase.util.logging.*; 20 21 43 public abstract class BridgeServlet extends MMBaseServlet { 44 public static final String MESSAGE_ATTRIBUTE = "org.mmbase.servlet.error.message"; 46 51 52 public static final Pattern FILE_PATTERN = Pattern.compile(".*?\\D((?:session=.*?\\+)?\\d+(?:\\+.+?)?)(/.*)?"); 53 60 61 63 64 private static Logger log; 65 66 69 private static int contextPathLength = -1; 70 71 72 private String lastModifiedField = null; 73 74 78 protected String getCloudName() { 79 return "mmbase"; 80 } 81 82 83 84 88 protected QueryParts readQuery(HttpServletRequest req, HttpServletResponse res) throws IOException { 89 QueryParts qp = (QueryParts) req.getAttribute("org.mmbase.servlet.BridgeServlet$QueryParts"); 90 if (qp != null) { 91 log.trace("no need parsing query"); 92 if (qp.getResponse() == null && res != null) { 93 qp.setResponse(res); 94 } 95 return qp; 96 } 97 if (log.isTraceEnabled()) { 98 log.trace("parsing query "); 99 } 100 101 String q = req.getQueryString(); 102 103 String fileNamePart; 104 if (q == null || "".equals(q)) { if (contextPathLength == -1) { 107 contextPathLength = req.getContextPath().length(); 108 } 109 String reqString = req.getRequestURI().substring(contextPathLength); 111 if (req.isRequestedSessionIdFromURL()) { 113 int jsessionid = reqString.indexOf(";jsessionid="); 114 if (jsessionid != -1) { 115 reqString = reqString.substring(0, jsessionid); 116 } 117 } 118 119 if(log.isDebugEnabled()) { 120 log.debug("using servlet URI " + reqString + " to find node number"); 121 } 122 123 qp = readServletPath(reqString); 124 if (qp == null) { 125 log.debug("Did not match"); 126 if(res != null) { 127 res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Malformed URL: '" + reqString + "' does not match '" + FILE_PATTERN.pattern() + "'."); 128 req.setAttribute(MESSAGE_ATTRIBUTE, "Malformed URL: '" + reqString + "' does not match '" + FILE_PATTERN.pattern() + "'."); 129 } else { 130 log.error("Malformed URL: '" + reqString + "' does not match '" + FILE_PATTERN.pattern() + "'."); 131 } 132 } else { 133 if (log.isDebugEnabled()) { 134 log.debug("found " + qp); 135 } 136 } 137 } else { 138 if(log.isDebugEnabled()) { 139 log.debug("using query " + q + " to find node number"); 140 } 141 qp = readQuery(q); 143 if (qp == null && res != null) { 144 res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Malformed URL: No node number found after session."); 145 req.setAttribute(MESSAGE_ATTRIBUTE, "Malformed URL: No node number found after session."); 146 } 147 148 } 149 150 if (qp == null) return null; 151 152 qp.setRequest(req); 153 qp.setResponse(res); 154 155 req.setAttribute("org.mmbase.servlet.BridgeServlet$QueryParts", qp); 156 return qp; 157 } 158 159 160 164 public static QueryParts readServletPath(String servletPath) { 165 Matcher m = FILE_PATTERN.matcher(servletPath); 166 if (! m.matches()) { 167 return null; 168 } 169 QueryParts qp = readQuery(m.group(1)); 170 qp.setFileName(m.group(2)); 171 return qp; 172 } 173 174 178 public static QueryParts readQuery(String query) { 179 String sessionName = null; String nodeIdentifier; 181 if (query.startsWith("session=")) { 182 184 int plus = query.indexOf("+", 8); 185 if (plus == -1) { 186 sessionName = ""; 187 nodeIdentifier = query; 188 } else { 189 sessionName = query.substring(8, plus); 190 nodeIdentifier = query.substring(plus + 1); 191 } 192 } else { 193 nodeIdentifier = query; 194 } 195 return new QueryParts(sessionName, nodeIdentifier); 196 197 } 198 199 200 204 final protected Cloud getCloud(QueryParts qp) throws IOException { 205 log.debug("getting a cloud"); 206 Cloud cloud = null; 208 HttpSession session = qp.getRequest().getSession(false); if (session != null) { log.debug("from session"); 211 String sessionName = qp.getSessionName(); 212 if (sessionName != null) { 213 cloud = (Cloud) session.getAttribute(sessionName); 214 } else { cloud = (Cloud) session.getAttribute("cloud_" + getCloudName()); 216 } 217 } 218 return cloud; 219 } 220 221 224 final protected Cloud getAnonymousCloud() { 225 try { 226 return ContextProvider.getDefaultCloudContext().getCloud(getCloudName()); 227 } catch (org.mmbase.security.SecurityException e) { 228 log.debug("could not generate anonymous cloud"); 229 return null; 231 } 232 } 233 234 239 protected Cloud getClassCloud() { 240 try { 241 return ContextProvider.getDefaultCloudContext().getCloud(getCloudName(), "class", null); } catch (java.lang.SecurityException e) { 243 log.debug("could not generate class cloud"); 244 return null; 246 } 247 } 248 249 250 251 255 protected Cloud findCloud(Cloud c, String nodeNumber, QueryParts query) throws IOException { 256 257 if (c == null || ! (c.mayRead(nodeNumber))) { 258 c = getClassCloud(); 259 } 260 261 if (c == null || ! (c.mayRead(nodeNumber))) { 262 c = getCloud(query); 263 } 264 if (c == null || ! (c.mayRead(nodeNumber))) { HttpServletResponse res = query.getResponse(); 266 if (res != null) { 267 res.sendError(HttpServletResponse.SC_FORBIDDEN, "Permission denied to anonymous for node '" + nodeNumber + "'"); 268 } 269 return null; 270 } 271 return c; 272 } 273 274 278 279 final protected Node getNode(QueryParts query) throws IOException { 280 try { 281 if (log.isDebugEnabled()) { 282 log.debug("query : " + query); 283 } 284 285 if (query == null) { 286 return null; 287 } else { 288 Node n = query.getNode(); 289 if (n != null) { 290 return n; 291 } 292 } 293 294 Cloud c = getAnonymousCloud(); 296 String nodeNumber = java.net.URLDecoder.decode(query.getNodeNumber(), "UTF-8"); 297 298 if (c != null && ! c.hasNode(nodeNumber)) { 299 Node desperateNode = desperatelyGetNode(c, nodeNumber); 301 if (desperateNode != null) { 302 query.setNode(desperateNode); 303 return desperateNode; 304 } 305 HttpServletResponse res = query.getResponse(); 306 if (res != null) { 307 res.sendError(HttpServletResponse.SC_NOT_FOUND, "Node '" + nodeNumber + "' does not exist"); 308 query.getRequest().setAttribute(MESSAGE_ATTRIBUTE, "Node '" + nodeNumber + "' does not exist"); 309 } 310 return null; 311 } 312 313 c = findCloud(c, nodeNumber, query); 314 if (c == null) { 315 return null; 316 } 317 318 Node n = c.getNode(nodeNumber); 319 query.setNode(n); 320 return n; 321 } catch (Exception e) { 322 HttpServletResponse res = query.getResponse(); 323 if (res != null) { 324 query.getResponse().sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString()); 325 } 326 return null; 327 } 328 } 329 330 334 protected Node desperatelyGetNode(Cloud cloud, String nodeIdentifier) { 335 return null; 336 } 337 338 345 protected Node getServedNode(QueryParts qp, Node node) throws IOException { 346 return node; 347 } 348 349 357 protected long getLastModified(HttpServletRequest req) { 358 if (lastModifiedField == null) return -1; 359 try { 360 QueryParts query = readQuery(req, null); 361 Node node = getServedNode(query, getNode(query)); 362 if (node != null) { return node.getDateValue(lastModifiedField).getTime(); 364 } else { 365 return -1; 366 } 367 } catch (IOException ieo) { 368 return -1; 369 } 370 } 371 372 376 377 public void init() throws ServletException { 378 super.init(); 379 lastModifiedField = getInitParameter("lastmodifiedfield"); 380 if ("".equals(lastModifiedField)) lastModifiedField = null; 381 log = Logging.getLoggerInstance(BridgeServlet.class); 382 if (lastModifiedField != null) { 383 log.service("Field '" + lastModifiedField + "' will be used to calculate lastModified"); 384 } 385 } 386 387 390 final static public class QueryParts { 391 private String sessionName; 392 private String nodeIdentifier; 393 private HttpServletRequest req; 394 private HttpServletResponse res; 395 private Node node; 396 private Node servedNode; 397 private String fileName; 398 QueryParts(String sessionName, String nodeIdentifier) { 399 this.sessionName = sessionName; 400 this.nodeIdentifier = nodeIdentifier; 401 402 } 403 void setNode(Node node) { 404 this.node = node; 405 } 406 Node getNode() { 407 return node; 408 } 409 void setServedNode(Node node) { 410 this.servedNode = node; 411 } 412 Node getServedNode() { 413 return servedNode; 414 } 415 void setFileName(String fn) { 416 fileName = fn; 417 } 418 public String getFileName() { 419 return fileName; 420 } 421 public String getSessionName() { 422 return sessionName; 423 } 424 public String getNodeNumber() { 425 int i = nodeIdentifier.indexOf('+'); 426 if (i > 0) { 427 return nodeIdentifier.substring(0, i); 428 } else { 429 return nodeIdentifier; 430 } 431 } 432 void setRequest(HttpServletRequest req) { 433 this.req = req; 434 } 435 void setResponse(HttpServletResponse res) { 436 this.res = res; 437 } 438 439 HttpServletRequest getRequest() { 440 return req; 441 } 442 HttpServletResponse getResponse() { 443 return res; 444 } 445 446 449 public String getNodeIdentifier() { 450 return nodeIdentifier; 451 } 452 453 public String toString() { 454 return sessionName == null ? nodeIdentifier : "session=" + sessionName + "+" + nodeIdentifier; 455 } 456 457 458 } 459 460 463 public static void main(String [] argv) { 464 465 Matcher m = FILE_PATTERN.matcher(argv[0]); 466 if (! m.matches()) { 467 System.out.println("Didn't match"); 468 } else { 469 System.out.println("Found node " + m.group(1)); 470 } 471 } 472 473 } 474
| Popular Tags
|