1 10 package org.mmbase.module.builders; 11 12 import java.util.*; 13 import java.util.regex.*; 14 15 import org.mmbase.servlet.MMBaseServlet; 16 import org.mmbase.servlet.BridgeServlet; 17 import javax.servlet.http.HttpServletRequest ; 18 import org.mmbase.module.core.*; 19 import org.mmbase.util.*; 20 import org.mmbase.util.logging.*; 21 import org.mmbase.util.magicfile.MagicFile; 22 import org.mmbase.util.functions.*; 23 import org.mmbase.bridge.*; 24 import org.mmbase.security.Rank; 25 26 36 public abstract class AbstractServletBuilder extends MMObjectBuilder { 37 38 private static final Logger log = Logging.getLoggerInstance(AbstractServletBuilder.class); 39 40 public static final String FIELD_MIMETYPE = "mimetype"; 41 public static final String FIELD_FILENAME = "filename"; 42 public static final String FIELD_HANDLE = "handle"; 43 44 48 public final static Parameter[] GUI_PARAMETERS = { 49 new Parameter.Wrapper(MMObjectBuilder.GUI_PARAMETERS) }; 51 52 53 public final static Parameter[] FORMAT_PARAMETERS = {}; 54 public final static Parameter[] MIMETYPE_PARAMETERS = {}; 55 56 57 58 59 62 private String servletPath = null; 63 67 private boolean servletPathAbsolute; 68 69 74 protected boolean usesBridgeServlet = false; 75 76 77 private static final int FILENAME_ADD = 1; 78 private static final int FILENAME_DONTADD = 0; 79 private static final int FILENAME_IFSENSIBLE = -1; 80 private static final int FILENAME_CHECKSETTING = -2; 81 88 protected int addsFileName = FILENAME_CHECKSETTING; 89 90 91 99 abstract protected String getAssociation(); 100 101 110 abstract protected String getDefaultPath(); 111 112 116 117 private String getServletPathWithAssociation(String association, String root) { 118 if (MMBaseContext.isInitialized()) { 119 javax.servlet.ServletContext sx = MMBaseContext.getServletContext(); 120 if (sx != null) { 121 String res = sx.getInitParameter("mmbase.servlet." + association + ".url"); 122 if (res != null && ! res.equals("")) { 123 return res; 124 } 125 } 126 } 127 String result; 128 List ls = MMBaseServlet.getServletMappingsByAssociation(association); 129 if (ls.size()>0) { 130 result = (String ) ls.get(0); 131 usesBridgeServlet = MMBaseServlet.getServletByMapping(result) instanceof BridgeServlet; 132 int pos = result.lastIndexOf("*"); 134 if (pos > 0) { 135 result = result.substring(0, pos); 136 } 137 pos = result.indexOf("*"); 138 if (pos == 0) { 139 result = result.substring(pos + 1); 140 } 141 } else { 142 result = getDefaultPath(); 143 } 144 145 if (result.startsWith("/")) { 146 if (root != null) { 148 if (root.endsWith("/")) { 149 result = root + result.substring(1); 150 } else { 151 result = root + result; 152 } 153 } 154 } 155 return result; 156 } 157 158 165 166 protected String getServletPath(String root) { 167 if (servletPath == null) { 168 servletPath = getServletPathWithAssociation(getAssociation(), ""); 169 if (log.isServiceEnabled()) { 170 log.service(getAssociation() + " are served on: " + servletPath + " root: " + root); 171 } 172 servletPathAbsolute = servletPath.startsWith("http:") || servletPath.startsWith("https"); 173 } 174 175 String result; 176 if (servletPathAbsolute) { 177 result = servletPath; 178 } else if (root.endsWith("/") && servletPath.startsWith("/")) { 179 result = root + servletPath.substring(1); 180 } else { 181 result = root + servletPath; 182 } 183 184 if (! MMBaseContext.isInitialized()) { servletPath = null; } 185 if (! result.endsWith("/")) result += "?"; 187 return result; 188 } 189 190 protected String getServletPath() { 191 return getServletPath(MMBaseContext.getHtmlRootUrlPath()); 192 } 193 194 195 198 protected String getMimeType(MMObjectNode node) { 199 String mimeType = node.getStringValue(FIELD_MIMETYPE); 200 if (mimeType == null || mimeType.equals("")) { 201 if (log.isServiceEnabled()) { 202 log.service("Mimetype of attachment '" + node.getNumber() + "' was not set. Using magic to determine it automaticly."); 203 } 204 byte[] handle = node.getByteValue(FIELD_HANDLE); 205 206 String extension = null; 207 if (hasField(FIELD_FILENAME)) { 208 String filename = node.getStringValue(FIELD_FILENAME); 209 int dotIndex = filename.lastIndexOf("."); 210 if (dotIndex > -1) { 211 extension = filename.substring(dotIndex + 1); 212 } 213 } 214 215 MagicFile magic = MagicFile.getInstance(); 216 try { 217 if (extension == null) { 218 mimeType = magic.getMimeType(handle); 219 } else { 220 mimeType = magic.getMimeType(handle, extension); 221 } 222 log.service("Found mime-type: " + mimeType); 223 node.setValue(FIELD_MIMETYPE, mimeType); 224 } catch (Throwable e) { 225 log.warn("Exception in MagicFile for " + node); 226 mimeType = "application/octet-stream"; 227 node.setValue(FIELD_MIMETYPE, mimeType); 228 } 229 230 } 231 return mimeType; 232 } 233 234 238 protected void checkHandle(MMObjectNode node) { 239 if (getField(FIELD_MIMETYPE) != null) { 240 getMimeType(node); 241 } 242 243 } 244 245 248 249 abstract protected Set getHandleFields(); 250 251 public int insert(String owner, MMObjectNode node) { 252 if (log.isDebugEnabled()) { 253 log.debug("Inserting node " + node.getNumber() + " memory: " + SizeOf.getByteSize(node)); 254 } 255 checkHandle(node); 256 int result = super.insert(owner, node); 257 if (log.isDebugEnabled()) { 258 log.debug("After handle unload, memory: " + SizeOf.getByteSize(node)); 259 } 260 return result; 261 } 262 public boolean commit(MMObjectNode node) { 263 Collection changed = node.getChanged(); 264 if (log.isDebugEnabled()) { 265 log.debug("Committing node " + node.getNumber() + " memory: " + SizeOf.getByteSize(node) + " fields " + changed); 266 } 267 268 Object h; 269 if (changed.contains(FIELD_HANDLE)) { 270 Collection cp = new ArrayList(); 272 cp.addAll(getHandleFields()); 273 cp.removeAll(changed); 274 Iterator i = cp.iterator(); 275 while (i.hasNext()) { 276 String f = (String ) i.next(); 277 if (node.getBuilder().hasField(f)) { 278 node.setValue(f, null); 279 } 280 } 281 } 282 checkHandle(node); 283 boolean result = super.commit(node); 284 if (log.isDebugEnabled()) { 285 log.debug("After commit node " + node.getNumber() + " memory: " + SizeOf.getByteSize(node)); 286 } 287 return result; 288 } 289 290 291 295 296 abstract protected String getSGUIIndicator(MMObjectNode node, Parameters a); 297 298 299 303 304 final protected String getSuperGUIIndicator(String field, MMObjectNode node) { 305 return super.getGUIIndicator(field, node); 306 } 307 308 final protected String getGUIIndicator(MMObjectNode node, Parameters pars) { 309 String field = (String ) pars.get("field"); 310 if (field == null || "".equals(field) || FIELD_HANDLE.equals(field)) { 311 return getSGUIIndicator(node, pars); 312 } else { 313 return super.getGUIIndicator(node, pars); 314 } 315 316 } 317 320 321 final public String getGUIIndicator(String field, MMObjectNode node) { return getSGUIIndicator(node, new Parameters(GUI_PARAMETERS).set("field", field)); 323 } 324 325 protected static final Pattern legalizeFileName = Pattern.compile("[\\/\\:\\;\\\\ ]+"); 326 327 328 331 protected String getDefaultFileName() { 332 return getSingularName("en"); 333 } 334 337 protected StringBuffer getFileName(MMObjectNode node, StringBuffer buf) { 338 String fileName = hasField(FIELD_FILENAME) ? node.getStringValue(FIELD_FILENAME) : ""; 339 if (fileName.equals("")) { 340 String fileTitle; 341 if (hasField("title")) { 342 fileTitle = node.getStringValue("title"); 343 } else if (hasField("name")) { 344 fileTitle = node.getStringValue("name"); 345 } else { 346 fileTitle = ""; 347 } 348 if (fileTitle.equals("")) { 349 fileTitle = getDefaultFileName(); 350 } 351 fileName = fileTitle + "." + node.getFunctionValue("format", null); 352 } 353 int backSlash = fileName.lastIndexOf("\\"); 354 if (backSlash > -1) { 357 fileName = fileName.substring(backSlash + 1); 358 } 359 buf.append(legalizeFileName.matcher(fileName).replaceAll("_")); 360 return buf; 361 } 362 363 366 protected boolean addFileName(MMObjectNode node, String servlet) { 367 if (addsFileName == FILENAME_CHECKSETTING) { 368 javax.servlet.ServletContext sx = MMBaseContext.getServletContext(); 369 if (sx != null) { 370 String res = sx.getInitParameter("mmbase.servlet." + getAssociation() + ".addfilename"); 371 if (res == null) res = ""; 372 res = res.toLowerCase(); 373 log.trace("res " + res); 374 if ("no".equals(res) || "false".equals(res)) { 375 addsFileName = FILENAME_DONTADD; 376 } else if ("yes".equals(res) || "true".equals(res)) { 377 addsFileName = FILENAME_ADD; 378 } else { 379 log.debug("Found " + res + " for mmbase.servlet." + getAssociation() + ".addfilename"); 380 addsFileName = FILENAME_IFSENSIBLE; 381 } 382 } 383 } 384 log.debug("addsFileName " + addsFileName); 385 386 String fileName = hasField(FIELD_FILENAME) ? node.getStringValue(FIELD_FILENAME) : ""; 387 return addsFileName == FILENAME_ADD || 388 ( addsFileName == FILENAME_IFSENSIBLE && (!servlet.endsWith("?")) && (! "".equals(fileName))); 389 390 } 391 392 393 396 protected String getSession(Parameters a, int nodeNumber) { 397 String session = (String ) a.get("session"); 398 if (session == null) { 399 Cloud cloud = (Cloud) a.get(Parameter.CLOUD); 400 log.debug("No session given for " + cloud); 401 if(cloud != null && ! cloud.getUser().getRank().equals(Rank.ANONYMOUS)) { 402 log.debug("not anonymous"); 403 try { 410 String cloudName; 411 if (cloud instanceof Transaction) { 412 cloudName = ((Transaction) cloud).getCloudName(); 413 } 414 else { 415 cloudName = cloud.getName(); 416 } 417 Cloud anonymousCloud = cloud.getCloudContext().getCloud(cloudName); 418 if (! anonymousCloud.mayRead(nodeNumber)) { 419 session = (String ) cloud.getProperty(Cloud.PROP_SESSIONNAME); 420 log.debug("Anonymous may not read, setting session to " + session); 421 422 } 423 } catch (org.mmbase.security.SecurityException se) { 424 log.debug(se.getMessage()); 425 session = (String ) cloud.getProperty(Cloud.PROP_SESSIONNAME); 426 } 427 } 428 if ("".equals(session)) session = null; 429 } 430 431 return session; 432 } 433 434 { 435 addFunction(new NodeFunction("servletpath", 437 new Parameter[] { 438 new Parameter("session", String .class), new Parameter("field", String .class), new Parameter("context", String .class), new Parameter("argument", String .class), Parameter.REQUEST, 443 Parameter.CLOUD 444 }, 445 ReturnType.STRING) { 446 { 447 setDescription("Returns the path associated with this builder or node."); 448 } 449 450 protected StringBuffer getServletPath(Parameters a) { 451 StringBuffer servlet = new StringBuffer (); 452 String context = (String ) a.get("context"); 454 455 if (context == null) { 456 HttpServletRequest request = (HttpServletRequest ) a.get(Parameter.REQUEST); 458 if (request == null) { 459 servlet.append(AbstractServletBuilder.this.getServletPath()); } else { 462 servlet.append(AbstractServletBuilder.this.getServletPath(request.getContextPath())); 463 } 464 } else { 465 servlet.append(AbstractServletBuilder.this.getServletPath(context)); 467 } 468 return servlet; 469 } 470 471 public Object getFunctionValue(Node node, Parameters a) { 472 StringBuffer servlet = getServletPath(a); 473 474 String session = getSession(a, node.getNumber()); 475 String argument = (String ) a.get("argument"); 476 478 if (argument == null) { 479 String fieldName = (String ) a.get("field"); 480 if (fieldName == null || "".equals(fieldName)) { 481 argument = node.getStringValue("number"); 482 } else { 483 if (log.isDebugEnabled()) { 484 log.debug("Getting 'field' '" + fieldName + "'"); 485 } 486 argument = node.getStringValue(fieldName); 487 } 488 } 489 MMObjectNode mmnode = node.getNumber() > 0 ? 490 AbstractServletBuilder.this.getNode(node.getNumber()) : 491 new MMObjectNode(AbstractServletBuilder.this, new org.mmbase.bridge.util.NodeMap(node)); 492 boolean addFileName = addFileName(mmnode, servlet.toString()); 493 494 log.debug("Using session " + session); 495 496 if (usesBridgeServlet && session != null) { 497 servlet.append("session=" + session + "+"); 498 } 499 500 if (! addFileName) { 501 return servlet.append(argument).toString(); 502 } else { 503 servlet.append(argument).append('/'); 504 getFileName(mmnode, servlet); 505 return servlet.toString(); 506 } 507 } 508 509 public Object getFunctionValue(Parameters a) { 510 return getServletPath(a).toString(); 511 } 512 }); 513 514 } 515 516 517 518 { 519 522 addFunction(new NodeFunction("iconurl", 523 new Parameter[] { 524 Parameter.REQUEST, 525 new Parameter("iconroot", String .class, "/mmbase/style/icons/"), 526 new Parameter("absolute", String .class, "false") 527 }, 528 ReturnType.STRING) { 529 { 530 setDescription("Returns an URL for an icon for this blob"); 531 } 532 public Object getFunctionValue(Node n, Parameters parameters) { 533 String mimeType = AbstractServletBuilder.this.getMimeType(getCoreNode(AbstractServletBuilder.this, n)); 534 ResourceLoader webRoot = ResourceLoader.getWebRoot(); 535 HttpServletRequest request = (HttpServletRequest ) parameters.get(Parameter.REQUEST); 536 String absolute = parameters.getString("absolute"); 537 String root; 538 if (request != null) { 539 root = request.getContextPath(); 540 } else { 541 root = MMBaseContext.getHtmlRootUrlPath(); 542 } 543 544 if ("true".equals(absolute) && request != null) { 545 int port = request.getServerPort(); 546 root = request.getScheme() + "://" + request.getServerName() + (port == 80 ? "" : ":" + port) + root; 547 } 548 String iconRoot = (String ) parameters.get("iconroot"); 549 if (root.endsWith("/") && iconRoot.startsWith("/")) iconRoot = iconRoot.substring(1); 550 551 if (! iconRoot.endsWith("/")) iconRoot = iconRoot + '/'; 552 553 String resource = iconRoot + mimeType + ".gif"; 554 try { 555 if (! webRoot.getResource(resource).openConnection().getDoInput()) { 556 resource = iconRoot + "application/octet-stream.gif"; 557 } 558 } catch (java.io.IOException ioe) { 559 log.warn(ioe.getMessage(), ioe); 560 resource = iconRoot + "application/octet-stream.gif"; 561 } 562 return root + resource; 563 } 564 565 }); 566 } 567 568 569 570 577 578 protected Object executeFunction(MMObjectNode node, String function, List args) { 579 if (log.isDebugEnabled()) { 580 log.debug("executefunction of abstractservletbuilder for " + node.getNumber() + "." + function + " " + args); 581 } 582 if (function.equals("info")) { 583 List empty = new ArrayList(); 584 Map info = (Map) super.executeFunction(node, function, empty); 585 info.put("servletpathof", "(function) Returns the servletpath associated with a certain function"); 586 info.put("format", "bla bla"); 587 info.put("mimetype", "Returns the mimetype associated with this object"); 588 info.put("gui", "" + GUI_PARAMETERS + "Gui representation of this object."); 589 590 if (args == null || args.size() == 0) { 591 return info; 592 } else { 593 return info.get(args.get(0)); 594 } 595 } else if (function.equals("servletpath")) { 596 597 } else if (function.equals("servletpathof")) { 598 return getServletPathWithAssociation((String ) args.get(0), MMBaseContext.getHtmlRootUrlPath()); 600 } else if (function.equals("format")) { } else if (function.equals("mimetype")) { } else if (function.equals("gui")) { 605 if (log.isDebugEnabled()) { 606 log.debug("GUI of servlet builder with " + args); 607 } 608 if (args == null || args.size() == 0) { 609 return getGUIIndicator(node); 610 } else { 611 Parameters a; 612 if (args instanceof Parameters) { 613 a = (Parameters) args; 614 } else { 615 a = new Parameters(GUI_PARAMETERS, args); 616 } 617 618 String rtn = getSGUIIndicator(node, a); 619 if (rtn == null) return super.executeFunction(node, function, args); 620 return rtn; 621 } 622 } else { 623 return super.executeFunction(node, function, args); 624 } 625 return null; 626 } 627 628 } 629 | Popular Tags |