| 1 10 11 package org.mmbase.applications.dove; 12 13 import java.util.*; 14 import java.util.regex.Pattern ; 15 import org.w3c.dom.*; 16 import org.mmbase.bridge.*; 17 import org.mmbase.bridge.util.Queries; 18 import org.mmbase.datatypes.*; 19 import org.mmbase.module.builders.*; 20 import org.mmbase.storage.search.RelationStep; 21 import org.mmbase.util.Casting; 22 import org.mmbase.util.Encode; 23 import org.mmbase.util.xml.UtilReader; 24 import org.mmbase.util.logging.*; 25 26 59 60 public class Dove extends AbstractDove { 61 62 private static final Logger log = Logging.getLoggerInstance(Dove.class); 63 64 65 68 private static final UtilReader properties = new UtilReader("dove.xml"); 69 private static final String PROP_CHANGES = "changes"; 70 private static final String CHANGES_IGNORE = "ignore"; 71 private static final String CHANGES_WARN = "warn"; 72 private static final String CHANGES_EXCEPTION = "exception"; 73 74 80 public Dove(Document doc) { 81 super(doc); 82 } 83 84 93 private boolean isDataField(NodeManager nodeManager, Field f) { 94 String fname = f.getName(); 95 return (nodeManager.hasField(fname)) && (!"owner".equals(fname)) && (!"otype".equals(fname)) && 98 (!"number".equals(fname)) && 99 (!"snumber".equals(fname)) && 100 (!"dnumber".equals(fname)) && 101 (!"rnumber".equals(fname)) && 102 (!"dir".equals(fname)); 103 } 104 105 114 private boolean isDataField(NodeManager nodeManager, String fname) { 115 return nodeManager.hasField(fname); 116 } 117 118 private boolean isEditableField(NodeManager nodeManager, String fname) { 119 return isDataField(nodeManager, fname) && nodeManager.getField(fname).getState() == Field.STATE_PERSISTENT; 120 } 121 122 144 public void getDataNode(Element in, Element out, org.mmbase.bridge.Node node) { 145 NodeManager nm = node.getNodeManager(); 146 out.setAttribute(ELM_TYPE, nm.getName()); 147 out.setAttribute(ELM_MAYWRITE, "" + node.mayWrite()); 148 out.setAttribute(ELM_MAYDELETE, "" + node.mayDelete()); 149 Element field = getFirstElement(in, FIELD); 151 if (field == null) { 152 for (FieldIterator i = nm.getFields(NodeManager.ORDER_CREATE).fieldIterator(); i.hasNext(); ) { 153 Field f = i.nextField(); 154 String fname = f.getName(); 155 if (isDataField(nm,f)) { 156 Element fel; 157 DataType dataType = f.getDataType(); 158 if (dataType instanceof BinaryDataType) { 159 fel = addContentElement(FIELD, "", out); 160 161 int byteLength = 0; 162 if (nm.hasField(AbstractImages.FIELD_FILESIZE)) { 163 byteLength = node.getIntValue(AbstractImages.FIELD_FILESIZE); 164 } 165 else { 166 if (nm.hasField(Attachments.FIELD_SIZE)) { 167 byteLength = node.getIntValue(Attachments.FIELD_SIZE); 168 } 169 else { 170 byte[] bytes = node.getByteValue(fname); 171 byteLength = bytes != null ? bytes.length : 0; 172 } 173 } 174 fel.setAttribute(ELM_SIZE, "" + byteLength); 175 } else if (dataType instanceof DateTimeDataType || 176 dataType instanceof IntegerDataType || 177 dataType instanceof LongDataType 178 ) { 179 fel = addContentElement(FIELD, "" + node.getLongValue(fname), out); 181 } else { 182 fel = addContentElement(FIELD, node.isNull(fname) ? null : node.getStringValue(fname), out); 183 } 184 fel.setAttribute(ELM_TYPE, dataType.getBaseTypeIdentifier()); 185 fel.setAttribute(ELM_NAME, fname); 186 } 187 } 188 } else { 189 while (field != null) { String fname = field.getAttribute(ELM_NAME); 191 if ((fname == null) || (fname.equals(""))) { 192 Element err = addContentElement(ERROR, "name required for field",out); 193 err.setAttribute(ELM_TYPE, IS_PARSER); 194 } else if (isDataField(nm,fname)) { 195 Element fel; 196 Field f = nm.getField(fname); 197 DataType dataType = f.getDataType(); 198 if (dataType instanceof BinaryDataType) { 199 fel = addContentElement(FIELD, "", out); 200 byte[] bytes = node.getByteValue(fname); 201 fel.setAttribute(ELM_SIZE, "" + (bytes != null ? bytes.length : 0)); 202 } else if (dataType instanceof DateTimeDataType || 203 dataType instanceof IntegerDataType || 204 dataType instanceof LongDataType 205 ) { 206 fel = addContentElement(FIELD, "" + node.getLongValue(fname), out); 208 } else { 209 fel = addContentElement(FIELD, node.getStringValue(fname), out); 210 } 211 fel.setAttribute(ELM_TYPE, dataType.getBaseTypeIdentifier()); 212 fel.setAttribute(ELM_NAME, fname); 213 } else { 214 Element err = addContentElement(ERROR, "field with name " + fname + " does not exist", out); 215 err.setAttribute(ELM_TYPE, IS_PARSER); 216 } 217 field = getNextElement(field,FIELD); 218 } 219 } 220 Element relation = getFirstElement(in, RELATION); 222 while (relation != null) { addRelationNodes(relation, out, node); 224 relation = getNextElement(relation, RELATION); 225 } 226 } 227 228 248 public void getDataNode(Element in, Element out, Cloud cloud) { 249 String alias = in.getAttribute(ELM_NUMBER); 250 try { 251 org.mmbase.bridge.Node nd = cloud.getNode(alias); 252 getDataNode(in,out,nd); 253 } catch (RuntimeException e) { 254 Element err = addContentElement(ERROR,"node not found",out); 255 err.setAttribute(ELM_TYPE, IS_SERVER); 256 } 257 } 258 259 271 protected void addRelationNodes(Element relation, Element out, org.mmbase.bridge.Node nd) { 272 int thisNumber=nd.getNumber(); 273 String role=relation.getAttribute(ELM_ROLE); 274 if ("".equals(role)) role=null; 275 String destinationType = relation.getAttribute(ELM_DESTINATIONTYPE); 276 if (("".equals(destinationType)) || (destinationType==null)) { 277 destinationType = relation.getAttribute(ELM_DESTINATION); 278 } 279 if ("".equals(destinationType)) destinationType=null; 280 int searchDir=0; 281 String searchDirs = relation.getAttribute(ELM_SEARCHDIR).toLowerCase(); 282 if("destination".equals(searchDirs)) { 283 searchDir=1; 284 } else if("source".equals(searchDirs)) { 285 searchDir=2; 286 } 287 288 Element objectDef = getFirstElement(relation,OBJECT); 290 try { 291 for (RelationIterator i = nd.getRelations(role,destinationType).relationIterator(); i.hasNext(); ) { 292 Relation nrel=i.nextRelation(); 293 if (searchDir==1) { 294 if (thisNumber!=nrel.getIntValue("snumber")) continue; 295 } 296 if (searchDir==2) { 297 if (thisNumber!=nrel.getIntValue("dnumber")) continue; 298 } 299 Element data=doc.createElement(RELATION); 300 if (role!=null) { 301 data.setAttribute(ELM_ROLE, role); 302 } else { 303 data.setAttribute(ELM_ROLE,nrel.getRelationManager().getForwardRole()); 304 } 305 data.setAttribute(ELM_SOURCE, "" + nrel.getIntValue("snumber")); 306 data.setAttribute(ELM_DESTINATION, "" + nrel.getIntValue("dnumber")); 307 308 int otherNumber; 309 if (thisNumber == nrel.getIntValue("snumber")) { 310 otherNumber = nrel.getIntValue("dnumber"); 311 } else { 312 otherNumber = nrel.getIntValue("snumber"); 313 } 314 data.setAttribute(ELM_NUMBER, ""+nrel.getNumber()); 315 out.appendChild(data); 316 getDataNode(relation,data,nrel); 317 if (objectDef!=null) { 318 Element nodeData=doc.createElement(OBJECT); 319 nodeData.setAttribute(ELM_NUMBER, ""+otherNumber); 320 data.appendChild(nodeData); 321 getDataNode(objectDef, nodeData,nd.getCloud().getNode(otherNumber)); 322 } 323 } 324 } catch (RuntimeException e) { 325 Element err = addContentElement(ERROR,"role or nodetype for relation invalid ("+e.getMessage()+")",out); 326 err.setAttribute(ELM_TYPE, IS_CLIENT); 327 } 328 } 329 330 344 public void getRelationsNodes(Element in, Element out, Cloud cloud) { 345 String alias = in.getAttribute(ELM_NUMBER); 346 try { 347 org.mmbase.bridge.Node nd = cloud.getNode(alias); 348 NodeManager nm=nd.getNodeManager(); 349 out.setAttribute(ELM_TYPE,nm.getName()); 350 351 Element relation=getFirstElement(in,RELATION); 352 if (relation==null) { 353 int thisNumber=nd.getNumber(); 354 for (RelationIterator i=nd.getRelations().relationIterator(); i.hasNext(); ) { 355 Relation nrel=i.nextRelation(); 356 Element data=doc.createElement(RELATION); 357 data.setAttribute(ELM_NUMBER, ""+nrel.getNumber()); 358 data.setAttribute(ELM_ROLE, nrel.getRelationManager().getForwardRole()); 359 if (thisNumber==nrel.getIntValue("snumber")) { 360 data.setAttribute(ELM_SOURCE, ""+nrel.getIntValue("snumber")); 361 data.setAttribute(ELM_DESTINATION, ""+nrel.getIntValue("dnumber")); 362 } else { 363 data.setAttribute(ELM_SOURCE, ""+nrel.getIntValue("dnumber")); 364 data.setAttribute(ELM_DESTINATION, ""+nrel.getIntValue("snumber")); 365 } 366 out.appendChild(data); 367 getDataNode(null,data,nrel); 368 } 369 } else { 370 while (relation!=null) { addRelationNodes(relation,out,nd); 372 relation=getNextElement(relation,RELATION); 373 } 374 } 375 } catch (RuntimeException e) { 376 Element err = addContentElement(ERROR,"node not found",out); 377 err.setAttribute(ELM_TYPE, IS_SERVER); 378 } 379 } 380 381 397 public void getData(Element in, Element out, Cloud cloud) { 398 Element node=getFirstElement(in); 399 while (node!=null) { if (node.getTagName().equals(OBJECT)) { 401 String number = node.getAttribute(ELM_NUMBER); if (number.equals("")) { 403 Element err = addContentElement(ERROR,"number required for node",out); 404 err.setAttribute(ELM_TYPE, IS_PARSER); 405 } else { 406 Element data=doc.createElement(OBJECT); 407 data.setAttribute(ELM_NUMBER, number); 408 out.appendChild(data); 409 getDataNode(node,data,cloud); 410 } 411 } else { 412 Element err = addContentElement(ERROR,"Unknown subtag in getdata: "+node.getTagName(),out); 413 err.setAttribute(ELM_TYPE, IS_PARSER); 414 } 415 node=getNextElement(node); 416 } 417 } 418 419 431 public void getNew(Element in, Element out, Cloud cloud) { 432 String nodemanagername = in.getAttribute(ELM_TYPE); if (nodemanagername.equals("")) { 434 Element err = addContentElement(ERROR,"type required for getnew",out); 435 err.setAttribute(ELM_TYPE, IS_PARSER); 436 } else { 437 try { 438 out.setAttribute(ELM_TYPE,nodemanagername); 439 NodeManager nm =cloud.getNodeManager(nodemanagername); 440 org.mmbase.bridge.Node n = nm.createNode(); 441 try { 442 Element data=doc.createElement(OBJECT); 443 int number=java.lang.Math.abs(n.getNumber()); 444 data.setAttribute(ELM_NUMBER, "n"+number); 445 out.appendChild(data); 446 getDataNode(null,data,n); 447 } finally { 448 n.cancel(); } 450 } catch (RuntimeException e) { 451 Element err = addContentElement(ERROR,"node type " + nodemanagername + " does not exist(" + e.toString() + ")",out); 452 log.warn(Logging.stackTrace(e)); 453 err.setAttribute(ELM_TYPE, IS_CLIENT); 454 } 455 } 456 } 457 458 470 public void getNewRelation(Element in, Element out, Cloud cloud) { 471 String rolename = in.getAttribute(ELM_ROLE); String destination = in.getAttribute(ELM_DESTINATION); String source = in.getAttribute(ELM_SOURCE); String destinationType = in.getAttribute(ELM_DESTINATIONTYPE); String sourceType = in.getAttribute(ELM_SOURCETYPE); 477 int createDir = Queries.getRelationStepDirection(in.getAttribute(ELM_CREATEDIR)); 478 479 if (rolename.equals("")) { 480 Element err = addContentElement(ERROR,"role required for getrelations",out); 481 err.setAttribute(ELM_TYPE, IS_PARSER); 482 } else { 483 try { 484 out.setAttribute(ELM_ROLE,rolename); 485 out.setAttribute(ELM_DESTINATION, destination); 486 out.setAttribute(ELM_SOURCE, source); 487 RelationManager nm; 489 if (destinationType.equals("") || sourceType.equals("") ) { 490 nm =cloud.getRelationManager(rolename); 491 } else { 492 nm =cloud.getRelationManager(sourceType,destinationType,rolename); 493 } 494 org.mmbase.bridge.Node n = nm.createNode(); 495 try { 496 Element data=doc.createElement(RELATION); 497 int number=java.lang.Math.abs(n.getNumber()); 498 data.setAttribute(ELM_NUMBER, "n"+number); 499 if (createDir == RelationStep.DIRECTIONS_SOURCE) { 500 log.debug("Creating relation in the INVERSE direction"); 501 data.setAttribute(ELM_DESTINATION, source); 502 data.setAttribute(ELM_SOURCE, destination); 503 } else { 504 log.debug("Creating relation in the NORMAL direction"); 505 data.setAttribute(ELM_DESTINATION, destination); 506 data.setAttribute(ELM_SOURCE, source); 507 } 508 data.setAttribute(ELM_ROLE,rolename); 509 out.appendChild(data); 510 getDataNode(null, data, n); 511 } finally { 512 n.cancel(); } 514 } catch (RuntimeException e) { 515 if (destinationType.equals("") || sourceType.equals("") ) { 516 Element err = addContentElement(ERROR,"role ("+rolename+") does not exist",out); 517 err.setAttribute(ELM_TYPE, IS_CLIENT); 518 } else { 519 Element err = addContentElement(ERROR,"relation ("+sourceType+"-"+rolename+"->"+destinationType+") constraint does not exist",out); 520 err.setAttribute(ELM_TYPE, IS_CLIENT); 521 } 522 } 523 } 524 } 525 526 543 public void getRelations(Element in, Element out, Cloud cloud) { 544 Element node = getFirstElement(in); 545 while (node != null) { if (node.getTagName().equals(OBJECT)) { 547 String number = node.getAttribute(ELM_NUMBER); if (number.equals("")) { 549 Element err = addContentElement(ERROR,"number required for node", out); 550 err.setAttribute(ELM_TYPE, IS_PARSER); 551 } else { 552 Element data = doc.createElement(OBJECT); 553 data.setAttribute(ELM_NUMBER, number); 554 out.appendChild(data); 555 getRelationsNodes(node,data,cloud); 556 } 557 } else { 558 Element err = addContentElement(ERROR,"Unknown subtag in getrelations: " + node.getTagName(), out); 559 err.setAttribute(ELM_TYPE, IS_PARSER); 560 } 561 node = getNextElement(node); 562 } 563 } 564 565 574 public void getConstraints(Element in, Element out, Cloud cloud) { 575 String nodeManagerName = in.getAttribute(ELM_TYPE); if (nodeManagerName.equals("")) { 577 Element err = addContentElement(ERROR,"type required for getconstraints",out); 578 err.setAttribute(ELM_TYPE, IS_PARSER); 579 } else { 580 try { 581 out.setAttribute(ELM_TYPE,nodeManagerName); 582 NodeManager nm =cloud.getNodeManager(nodeManagerName); 583 584 Locale locale = cloud.getLocale(); 585 String lang= in.getAttribute(ELM_LANG); 586 if (!"".equals(lang)) { 587 out.setAttribute(ELM_LANG,lang); 588 locale = new Locale(lang); 589 } 590 591 Element elm=addContentElement(SINGULARNAME,nm.getGUIName(NodeManager.GUI_SINGULAR,locale),out); 593 if (lang!=null) elm.setAttribute(ELM_LANG,lang); 594 595 elm=addContentElement(PLURALNAME,nm.getGUIName(NodeManager.GUI_PLURAL,locale),out); 597 if (lang!=null) elm.setAttribute(ELM_LANG,lang); 598 599 elm=addContentElement(DESCRIPTION,nm.getDescription(locale),out); 601 if (lang!=null) elm.setAttribute(ELM_LANG,lang); 602 603 try { 605 NodeManager nmparent = nm.getParent(); 606 Element parent = doc.createElement(PARENT); 607 out.appendChild(parent); 608 parent.setAttribute(ELM_TYPE,nmparent.getName()); 609 } catch (NotFoundException nfe) { 610 log.debug("no parent available"); 611 } 612 613 NodeManagerList nmdesclist = nm.getDescendants(); 615 if (nmdesclist.size()>0) { 616 Element descendants = doc.createElement(DESCENDANTS); 617 out.appendChild(descendants); 618 for (NodeManagerIterator i = nmdesclist.nodeManagerIterator(); i.hasNext();) { 619 Element descendant=doc.createElement(DESCENDANT); 620 descendants.appendChild(descendant); 621 descendant.setAttribute(ELM_TYPE,i.nextNodeManager().getName()); 622 } 623 } 624 625 Element fields=doc.createElement(FIELDS); 627 out.appendChild(fields); 628 for(FieldIterator i = nm.getFields(NodeManager.ORDER_CREATE).fieldIterator(); i.hasNext(); ) { 629 Field fielddef=i.nextField(); 630 String fname=fielddef.getName(); 631 if (isDataField(nm,fielddef)) { 634 Element field=doc.createElement(FIELD); 635 field.setAttribute(ELM_NAME,fname); 636 fields.appendChild(field); 637 elm = addContentElement(GUINAME, fielddef.getGUIName(locale),field); 639 elm = addContentElement(DESCRIPTION, fielddef.getDescription(locale),field); 640 if (lang != null) elm.setAttribute(ELM_LANG, lang); 641 DataType dataType = fielddef.getDataType(); 643 String baseType = dataType.getBaseTypeIdentifier(); 644 String specialization = dataType.getName(); 645 if ("".equals(specialization)) { 646 DataType origin = dataType.getOrigin(); 647 if (origin != null) { 648 specialization = origin.getName(); 649 } 650 } 651 if (specialization.equals("field")) { 653 specialization = "text"; 654 } else if (specialization.equals("eventtime")) { 655 baseType = "datetime"; 656 specialization = "datetime"; 657 } else if (specialization.equals("newimage")) { 658 specialization = "image"; 659 } else if (specialization.equals("newfile")) { 660 specialization = "file"; 661 } else { 662 if (dataType instanceof NodeDataType) { 665 baseType = "int"; 666 } else if (dataType instanceof XmlDataType) { 667 baseType = "string"; 668 } else if (dataType instanceof BinaryDataType) { 669 Pattern p = ((BinaryDataType) dataType).getValidMimeTypes(); 670 if (p.matcher("image/someimageformat").matches()) { 671 specialization = "image"; 672 } else { 673 specialization = "file"; 674 } 675 } 676 } 677 String guiType = baseType + "/" + specialization; 678 679 addContentElement(GUITYPE, guiType, field); 680 int maxLength = fielddef.getMaxLength(); 681 if (maxLength>0) { 682 addContentElement(MAXLENGTH, "" + maxLength, field); 683 } 684 685 if (fielddef.isRequired()) { 686 addContentElement(REQUIRED, IS_TRUE, field); 687 } else { 688 addContentElement(REQUIRED, IS_FALSE, field); 689 } 690 } 691 } 692 Element relations = doc.createElement(RELATIONS); 694 out.appendChild(relations); 695 } catch (RuntimeException e) { 698 Element err = addContentElement(ERROR, "node type " + nodeManagerName + " does not exist(" + e.toString() + ")",out); 699 log.warn(Logging.stackTrace(e)); 700 err.setAttribute(ELM_TYPE, IS_CLIENT); 701 } 702 } 703 } 704 705 721 public void getList(Element in, Element out, Cloud cloud) { 722 Element query=getFirstElement(in); 723 while (query!=null) { if (query.getTagName().equals(QUERY)) { 725 String xpath = query.getAttribute(ELM_XPATH); String where = query.getAttribute(ELM_WHERE); String orderby = query.getAttribute(ELM_ORDERBY); if ("".equals(orderby)) orderby=null; 729 String directions = query.getAttribute(ELM_DIRECTIONS); if ("".equals(directions)) directions=null; 731 if (xpath.equals("")) { 732 Element err = addContentElement(ERROR,"xpath required for query",out); 733 err.setAttribute(ELM_TYPE, IS_PARSER); 734 } else { 735 Element querydata=doc.createElement(QUERY); 736 querydata.setAttribute(ELM_XPATH, xpath); 737 if (!where.equals("")) { 738 querydata.setAttribute(ELM_WHERE, where); 739 } 740 if (orderby!=null) { 741 querydata.setAttribute(ELM_ORDERBY, orderby); 742 } 743 if (directions!=null) { 744 querydata.setAttribute(ELM_DIRECTIONS, directions); 745 } 746 out.appendChild(querydata); 747 748 Element node=getFirstElement(query); 750 751 if (xpath.indexOf("/*@")!=0) { 752 Element err = addContentElement(ERROR,"invalid xpath",out); 753 err.setAttribute(ELM_TYPE, IS_CLIENT); 754 } else { 755 String nodepath = xpath.substring(3); 756 try { 757 NodeIterator i = null; 758 759 if (nodepath.indexOf("/") == -1) { 760 i = cloud.getNodeManager(xpath.substring(3)).getList(where,orderby,directions).nodeIterator(); 763 } else { 764 String fields = ""; 767 Element field = getFirstElement(node, FIELD); 768 nodepath = nodepath.replace('/', ','); 769 while (field != null) { 770 String fname = field.getAttribute(ELM_NAME); 771 if (!fields.equals("")) 772 fields += ","; 773 fields += fname; 774 field = getNextElement(field, FIELD); 775 } 776 i = cloud.getList("", nodepath, fields, where, orderby, directions, null, true).nodeIterator(); 777 } 778 779 for(; i.hasNext(); ) { 780 org.mmbase.bridge.Node n=i.nextNode(); 781 Element data=doc.createElement(OBJECT); 782 data.setAttribute(ELM_NUMBER, ""+n.getNumber()); 783 querydata.appendChild(data); 784 getDataNode(node,data,n); 785 } 786 } catch(RuntimeException e) { 787 Element err = addContentElement(ERROR,"node type " + xpath.substring(3) + " does not exist(" + e.toString() + ")",out); 788 log.warn(Logging.stackTrace(e)); 789 err.setAttribute(ELM_TYPE, IS_CLIENT); 790 } 791 } 792 } 793 } else { 794 Element err = addContentElement(ERROR,"Unknown subtag in getlist: "+query.getTagName(),out); 795 err.setAttribute(ELM_TYPE, IS_PARSER); 796 } 797 query=getNextElement(query); 798 } 799 } 800 801 813 public void put(Element in, Element out, Cloud cloud, Map repository) { 814 Map originalNodes = new HashMap(); 816 Map newNodes = new HashMap(); 817 Map originalRelations = new HashMap(); 818 Map newRelations = new HashMap(); 819 820 Element query = getFirstElement(in); 822 while (query!=null) { if (query.getTagName().equals(ORIGINAL) || query.getTagName().equals(NEW)) { 824 boolean isOriginal = query.getTagName().equals(ORIGINAL); 825 Element node = getFirstElement(query); 826 827 while (node!=null) { if (node.getTagName().equals(OBJECT) || node.getTagName().equals(RELATION)) { 829 boolean isRelation = node.getTagName().equals(RELATION); 830 831 Map values = new HashMap(); 833 if (isRelation) { 834 if (isOriginal) { 835 originalRelations.put(node.getAttribute(ELM_NUMBER), values); 836 } else { 837 newRelations.put(node.getAttribute(ELM_NUMBER), values); 838 } 839 } else { 840 if (isOriginal) { 841 originalNodes.put(node.getAttribute(ELM_NUMBER), values); 842 } else { 843 newNodes.put(node.getAttribute(ELM_NUMBER),values); 844 } 845 } 846 if (! isOriginal) { 847 values.put("_status",node.getAttribute(ELM_STATUS)); 848 } 849 850 String context = node.getAttribute(ELM_CONTEXT); 851 if (context != null && !context.equals("")) { 852 values.put("_context", context); 853 } 854 855 if (isRelation) { 856 String role = node.getAttribute(ELM_ROLE); 857 if (role!=null) values.put("_role",role); 858 859 String source = node.getAttribute(ELM_SOURCE); 860 if (source!=null) values.put("_source",source); 861 862 String destination = node.getAttribute(ELM_DESTINATION); 863 if (destination!=null) values.put("_destination", destination); 864 } else { 865 String type = node.getAttribute(ELM_TYPE); 866 if (type!=null) values.put("_otype", type); 867 } 868 Element field = getFirstElement(node); 869 while (field != null) { if (field.getTagName().equals(FIELD)) { 871 String fieldname = field.getAttribute(ELM_NAME); 872 String href = field.getAttribute(ELM_HREF); 873 String encoding = field.getAttribute(ELM_ENCODING); 874 if (!href.equals("")) { 875 Object repval = repository.get(href); 877 if (repval != null) { 878 values.put(fieldname, repval); 879 if(field.getFirstChild() != null) { 881 values.put("filename", field.getFirstChild().getNodeValue()); 882 } 883 } 884 } else if (!encoding.equals("")) { 885 if (encoding.toLowerCase().equals("base64")) { 886 values.put(fieldname, new Encode("BASE64").decodeBytes(field.getFirstChild().getNodeValue())); 887 } 888 } else { 889 if(field.getFirstChild() == null) { 890 values.put(fieldname, ""); 891 } else { 892 values.put(fieldname, field.getFirstChild().getNodeValue()); 893 } 894 } 895 } 896 field = getNextElement(field); 897 } 898 } 899 node = getNextElement(node); 900 } 901 } 902 query = getNextElement(query); 903 } 904 if (newNodes.size() > 0 || newRelations.size() > 0) { 906 Transaction trans = cloud.createTransaction(); 907 Map addedNodes = new HashMap (); 908 Map addedRelations = new HashMap(); 909 if (mergeClouds(originalNodes, newNodes, originalRelations, newRelations, addedNodes, addedRelations, out, trans) ) { 910 try { 911 trans.commit(); 912 for (Iterator i = addedNodes.entrySet().iterator(); i.hasNext(); ) { 917 Map.Entry me=(Map.Entry)i.next(); 918 org.mmbase.bridge.Node n = (org.mmbase.bridge.Node)me.getKey(); 919 Element oe = (Element)me.getValue(); 920 oe.setAttribute(ELM_NUMBER, n.getStringValue("number")); 921 } 922 for (Iterator i = addedRelations.entrySet().iterator(); i.hasNext(); ) { 924 Map.Entry me=(Map.Entry)i.next(); 925 org.mmbase.bridge.Node n = (org.mmbase.bridge.Node)me.getKey(); 926 Element re = (Element)me.getValue(); 927 re.setAttribute(ELM_NUMBER, n.getStringValue("number")); 928 re.setAttribute(ELM_SOURCE, "" + n.getIntValue("snumber")); 929 re.setAttribute(ELM_DESTINATION, "" + n.getIntValue("dnumber")); 930 } 931 } catch (RuntimeException e) { 932 Element err = addContentElement(ERROR, "Transaction failed : " + e.getMessage(), out); 933 log.error(Logging.stackTrace(e)); 934 err.setAttribute(ELM_TYPE, IS_SERVER); 935 } 936 } else { 937 trans.cancel(); 938 } 939 } 940 } 941 942 943 951 protected String getNodeReferenceFromValue(String name, Map values, Map aliases) { 952 String result=null; 953 String value=(String )values.get(name); 954 Object tmp=aliases.get(value); 955 if (tmp==null) { 956 result=value; 958 } else { 959 result=""+tmp; 960 } 961 return result; 962 } 963 964 975 protected boolean fillFields(String alias, org.mmbase.bridge.Node node, Element objectelement, Map values) { 976 return fillFields(alias, node, objectelement, values, null); 977 } 978 979 992 protected boolean fillFields(String alias, org.mmbase.bridge.Node node, Element out, Map values, Map originalValues) { 993 node.getCloud().setProperty(Cloud.PROP_XMLMODE, "flat"); 994 for (Iterator i = values.entrySet().iterator(); i.hasNext(); ) { 995 Map.Entry me = (Map.Entry)i.next(); 996 String key = (String )me.getKey(); 997 if (isEditableField(node.getNodeManager(),key)) { 998 Object value = me.getValue(); 999 DataType dt = node.getNodeManager().getField(key).getDataType(); 1000 String changes = (String ) properties.getProperties().get(PROP_CHANGES); 1001 if ((! CHANGES_IGNORE.equals(changes)) && 1002 (originalValues != null) && 1003 (!(value instanceof byte[]))) { String originalValue = (String ) originalValues.get(key); 1005 String mmbaseValue; 1006 if (dt instanceof DateTimeDataType || 1007 dt instanceof LongDataType || 1008 dt instanceof IntegerDataType) { 1009 mmbaseValue = "" + node.getLongValue(key); 1011 } else { 1012 mmbaseValue = node.isNull(key) ? null : node.getStringValue(key); 1013 } 1014 if (mmbaseValue == null) { 1015 if ("".equals(originalValue)) { 1016 originalValue = null; 1018 } 1019 if ("".equals(value)) { 1020 value = null; 1021 } 1022 } 1023 if ((originalValue != null ) && !originalValue.equals(mmbaseValue)) { 1024 String message = "Node was changed in the cloud, node number : " + alias + " field name '" + key + "' value found: '" + mmbaseValue + "' value expected '" + originalValue + "' changes: " + changes; 1025 if (CHANGES_WARN.equals(changes)) { 1027 log.warn(message); 1028 } else { 1029 log.debug(message); 1030 Element err = addContentElement(ERROR, message, out); 1031 err.setAttribute(ELM_TYPE, IS_SERVER); 1032 return false; 1033 } 1034 } 1035 } 1036 if (log.isDebugEnabled()) { 1037 log.debug("Setting field " + key + " to '" + value + "'"); 1038 } 1039 if (value instanceof byte[]) { 1040 node.setValue(key, value); 1041 } else { 1042 node.setStringValue(key, value != null ? Casting.toString(value) : null); 1043 } 1044 Element fieldElement = doc.createElement(FIELD); 1045 fieldElement.setAttribute(ELM_NAME, key); 1046 if (!(value instanceof byte[])) { 1047 Text tel = doc.createTextNode(value == null ? "" : value.toString()); 1048 fieldElement.appendChild(tel); 1049 } 1050 out.appendChild(fieldElement); 1051 } 1052 } 1053 return true; 1054 } 1055 1056 1069 protected boolean putNewNode(String alias, Map values, Map aliases, Map addedNodes, Element out, Cloud cloud) { 1070 String type = (String ) values.get("_otype"); 1071 try { 1072 NodeManager nm = cloud.getNodeManager(type); 1073 org.mmbase.bridge.Node newnode = nm.createNode(); 1074 Element objectelement = doc.createElement(OBJECT); 1075 objectelement.setAttribute(ELM_TYPE, type); 1076 fillFields(alias, newnode, objectelement, values); 1077 try { 1078 String context = (String ) values.get("_context"); 1079 if (context!=null) { 1080 newnode.setContext(context); 1081 } 1082 newnode.commit(); 1083 int number = newnode.getNumber(); 1084 if (log.isDebugEnabled()) 1085 log.debug("Created new node " + number); 1086 aliases.put(alias,new Integer (number)); 1087 objectelement.setAttribute(ELM_NUMBER,""+number); 1088 objectelement.setAttribute(ELM_OLDNUMBER, alias); 1089 addedNodes.put(newnode,objectelement); 1091 out.appendChild(objectelement); 1093 return true; 1094 } catch (RuntimeException e) { 1095 Element err = addContentElement(ERROR,"Cloud can not insert this object, alias number : "+alias + "(" + e.toString() + ")",out); 1097 err.setAttribute(ELM_TYPE, IS_SERVER); 1098 } 1099 } catch (BridgeException e) { 1100 Element err = addContentElement(ERROR, Logging.stackTrace(e), out); 1102 err.setAttribute(ELM_TYPE, IS_SERVER); 1103 } 1104 return false; 1105 } 1106 1107 1120 protected boolean putNewRelation(String alias, Map values, Map aliases, Map addedRelations, Element out, Cloud cloud) { 1121 String role=(String )values.get("_role"); 1122 try { 1123 RelationManager relman=cloud.getRelationManager(role); 1124 String sourcenumber=getNodeReferenceFromValue("_source",values, aliases); 1125 String destinationnumber=getNodeReferenceFromValue("_destination",values, aliases); 1126 if (log.isDebugEnabled()) log.debug("Creating a relations between node " + sourcenumber + " and " + destinationnumber); 1127 Relation newnode=relman.createRelation(cloud.getNode(sourcenumber), cloud.getNode(destinationnumber)); 1128 Element relationelement=doc.createElement(RELATION); 1129 relationelement.setAttribute(ELM_SOURCE,""+sourcenumber); 1132 relationelement.setAttribute(ELM_DESTINATION,""+destinationnumber); 1133 relationelement.setAttribute(ELM_ROLE,role); 1134 fillFields(alias,newnode,relationelement,values); 1135 try { 1136 String context = (String ) values.get("_context"); 1137 if (context!=null) { 1138 newnode.setContext(context); 1139 } 1140 newnode.commit(); 1141 int number = newnode.getNumber(); 1142 if (log.isServiceEnabled()) log.service("Created new relation " + number); 1143 aliases.put(alias, new Integer (number)); 1144 addedRelations.put(newnode,relationelement); 1146 relationelement.setAttribute(ELM_NUMBER,""+number); out.appendChild(relationelement); 1149 return true; 1150 } catch (RuntimeException e) { 1151 Element err = addContentElement(ERROR,"Cloud can not insert this object, alias number : " + alias + "(" + e.toString() + ")",out); 1153 err.setAttribute(ELM_TYPE, IS_SERVER); 1154 } 1155 } catch (RuntimeException e) { 1156 Element err = addContentElement(ERROR,"Error. Does the cloud support role :" + role + "?:" + e.getMessage(), out); 1158 err.setAttribute(ELM_TYPE, IS_CLIENT); 1159 } 1160 return false; 1161 } 1162 1163 1164 1174 protected boolean putDeleteNode(String alias, Map originalValues, Element out, Cloud cloud) { 1175 String type = (String )originalValues.get("_otype"); 1179 try { 1180 NodeManager nm = cloud.getNodeManager(type); 1181 try { 1182 org.mmbase.bridge.Node mmbaseNode = cloud.getNode(alias); 1183 if (mmbaseNode.getNodeManager().getName().equals(nm.getName()) ) { 1184 mmbaseNode.delete(true); 1185 return true; 1186 } else { 1187 Element err = addContentElement(ERROR,"Node not same type as in the cloud, node number : "+alias+", cloud type="+mmbaseNode.getNodeManager().getName()+", expected="+nm.getName()+")",out); 1189 err.setAttribute(ELM_TYPE, IS_SERVER); 1190 } 1191 } catch(RuntimeException e) { 1192 Element err = addContentElement(ERROR,"Node not in the cloud (anymore?), node number : "+alias + "(" + e.toString() + ")",out); 1194 err.setAttribute(ELM_TYPE, IS_SERVER); 1195 } 1196 } catch(RuntimeException e) { 1197 Element err = addContentElement(ERROR,"Cloud does not support type : "+type + "(" + e.toString() + ")",out); 1199 err.setAttribute(ELM_TYPE, IS_CLIENT); 1200 } 1201 return false; 1202 } 1203 1204 1214 protected boolean putDeleteRelation(String alias, Map originalValues, Element out, Cloud cloud) { 1215 String role = (String )originalValues.get("_role"); 1216 try { 1217 RelationManager relman = cloud.getRelationManager(role); 1218 try { 1219 org.mmbase.bridge.Node mmbaseNode = cloud.getNode(alias); 1220 if (mmbaseNode.getNodeManager().getName().equals(relman.getName()) ) { 1222 mmbaseNode.delete(true); 1223 return true; 1224 } else { 1225 Element err = addContentElement(ERROR,"Node not same type as in the cloud, node number : "+alias+", cloud type="+mmbaseNode.getNodeManager().getName()+", expected="+relman.getName()+")",out); 1226 err.setAttribute(ELM_TYPE, IS_SERVER); 1227 } 1228 } catch (RuntimeException e) { 1229 Element err = addContentElement(ERROR,"Relation not in the cloud (anymore?), relation number : "+alias,out); 1230 err.setAttribute(ELM_TYPE, IS_SERVER); 1231 } 1232 } catch (RuntimeException e) { 1233 Element err = addContentElement(ERROR,"Cloud does not support role : "+role, out); 1235 err.setAttribute(ELM_TYPE, IS_SERVER); 1236 } 1237 return false; 1238 } 1239 1240 1252 protected boolean putChangeNode(String alias, Map values, Map originalValues, Map aliases, Element out, Cloud cloud) { 1253 String type = (String )values.get("_otype"); 1257 try { 1258 NodeManager nm = cloud.getNodeManager(type); 1259 try { 1260 org.mmbase.bridge.Node mmbaseNode = cloud.getNode(alias); 1261 if (mmbaseNode.getNodeManager().getName().equals(nm.getName()) ) { 1263 Element objectElement = doc.createElement(OBJECT); 1265 objectElement.setAttribute(ELM_TYPE, type); 1266 objectElement.setAttribute(ELM_NUMBER, alias); 1267 if (!fillFields(alias, mmbaseNode, objectElement, values, originalValues)) { 1268 out.appendChild(objectElement); 1269 return false; 1270 } 1271 mmbaseNode.commit(); 1272 out.appendChild(objectElement); 1274 return true; 1275 } else { 1276 Element err = addContentElement(ERROR,"Node not same type as in the cloud, node number : " + alias + ", cloud type=" + mmbaseNode.getNodeManager().getName()+", expected=" + nm.getName() + ")", out); 1278 err.setAttribute(ELM_TYPE, IS_SERVER); 1279 } 1280 1281 } catch(RuntimeException e) { 1282 log.error(Logging.stackTrace(e)); 1284 Element err = addContentElement(ERROR,"Node not in the cloud (any more), node number : " + alias + "(" + e.toString() + ")", out); 1285 err.setAttribute(ELM_TYPE, IS_SERVER); 1286 } 1287 } catch(RuntimeException e) { 1288 Element err = addContentElement(ERROR, "Cloud does not support type : " + type + "(" + e.toString() + ")", out); 1290 err.setAttribute(ELM_TYPE, IS_CLIENT); 1291 } 1292 return false; 1293 } 1294 1295 1310 protected boolean mergeClouds(Map originalNodes, Map newNodes, Map originalRelations, Map newRelations, 1311 Map addedNodes, Map addedRelations, Element out, Cloud cloud) { 1312 Map aliases = new HashMap(); 1314 Element newElement = doc.createElement(NEW); 1316 out.appendChild(newElement); 1317 1318 for (Iterator i = newNodes.entrySet().iterator(); i.hasNext(); ) { 1320 Map.Entry me = (Map.Entry)i.next(); 1323 String alias = (String )me.getKey(); 1324 Map values = (Map)me.getValue(); 1325 String status = (String )values.get("_status"); 1326 1327 if (status != null && status.equals("new")) { 1329 if (!putNewNode(alias, values, aliases, addedNodes, newElement, cloud)) return false; 1330 } else if (status != null && status.equals("delete")) { 1331 Map originalValues = (Map) originalNodes.get(alias); 1334 if (originalValues!=null) { 1335 if (!putDeleteNode(alias, originalValues, newElement, cloud)) return false;; 1336 } 1337 } else if (status == null || status.equals("") || status.equals("change")) { 1338 Map originalValues = (Map )originalNodes.get(alias); 1340 if (originalValues != null) { 1341 if(!putChangeNode(alias, values, originalValues, aliases, newElement, cloud)) return false; 1342 } else { 1343 Element err = addContentElement(ERROR,"Node not defined in original tag, node number : " + alias, out); 1345 err.setAttribute(ELM_TYPE, IS_SERVER); 1346 return false; 1347 } 1348 } else { 1349 Element err = addContentElement(ERROR,"Invalid status "+status+" for node : "+alias,out); 1351 err.setAttribute(ELM_TYPE, IS_SERVER); 1352 return false; 1353 } 1354 } 1355 1356 for (Iterator i = newRelations.entrySet().iterator(); i.hasNext(); ) { 1358 Map.Entry me = (Map.Entry)i.next(); 1361 String alias = (String )me.getKey(); 1362 Map values = (Map)me.getValue(); 1363 String status = (String )values.get("_status"); 1364 1365 if (status != null && status.equals("new")) { 1367 if (!putNewRelation(alias, values, aliases, addedRelations, newElement, cloud)) return false; 1368 } else if (status != null && status.equals("delete")) { 1369 Map originalValues = (Map)originalRelations.get(alias); 1370 if (originalValues != null) { 1371 if(!putDeleteRelation(alias, originalValues, newElement, cloud)) return false;; 1372 } } else { 1375 Element err = addContentElement(ERROR, "Invalid status " + status + " for node : " + alias, out); 1377 err.setAttribute(ELM_TYPE, IS_SERVER); 1378 return false; 1379 } 1380 } 1381 return true; 1382 } 1383 1384 1409 public void doRequest(Element in, Element out, Cloud cloud, Map repository) { 1410 if (repository == null) repository = new HashMap(); 1412 1413 Element command = getFirstElement(in); 1414 if ((cloud == null)) { 1415 cloud = checkSecurity(command,out); 1417 if(cloud == null) { 1418 return; } 1420 command = getNextElement(command); 1421 } 1422 if (SECURITY.equals(command.getTagName())) { 1424 command = getNextElement(command); 1425 } 1426 1427 while (command!=null) { 1428 String cmd = command.getTagName(); 1429 Element data = doc.createElement(cmd); 1430 if (command.hasAttribute(ELM_ID)) { 1431 data.setAttribute(ELM_ID, command.getAttribute(ELM_ID)); 1432 } 1433 out.appendChild(data); 1434 if (cmd.equals(GETDATA)) { 1435 getData(command, data, cloud); 1436 } else if (cmd.equals(GETNEW)) { 1437 getNew(command, data, cloud); 1438 } else if (cmd.equals(GETNEWRELATION)) { 1439 getNewRelation(command, data, cloud); 1440 } else if (cmd.equals(GETRELATIONS)) { 1441 getRelations(command, data, cloud); 1442 } else if (cmd.equals(GETCONSTRAINTS)) { 1443 getConstraints(command, data, cloud); 1444 } else if (cmd.equals(GETLIST)) { 1445 getList(command, data, cloud); 1446 } else if (cmd.equals(PUT)) { 1447 put(command, data, cloud, repository); 1448 } else { 1449 Element err = addContentElement(ERROR, "Unknown command: " + cmd, data); 1450 err.setAttribute(ELM_TYPE, IS_PARSER); 1451 } 1452 command = getNextElement(command); 1453 } 1454 } 1455 1456 1460 private Cloud checkSecurity(Element command, Element out) { 1461 Element data = doc.createElement(SECURITY); 1462 out.appendChild(data); 1463 1464 if (command!=null && command.getTagName().equals(SECURITY)) { 1465 String userName = command.getAttribute(SECURITY_NAME); try { 1467 String password = command.getAttribute(SECURITY_PASSWORD); String methodName = command.getAttribute(SECURITY_METHOD ); if ((methodName == null) || (methodName.equals(""))) methodName="name/password"; 1470 String cloudName = command.getAttribute(SECURITY_CLOUD); if ((cloudName == null) || (cloudName.equals(""))) cloudName="mmbase"; 1472 Map user = new HashMap(); 1473 if ((userName!=null) && (!userName.equals(""))) { 1474 user.put("username", userName); 1475 user.put("password", password); 1476 } 1477 Cloud cloud = ContextProvider.getDefaultCloudContext().getCloud(cloudName, methodName, user); 1478 return cloud; 1479 } catch (RuntimeException e) { 1480 log.warn("Authentication error : " + e.getMessage()); 1482 Element err = addContentElement(ERROR, "Authentication error : " + e.getMessage(), data); 1483 err.setAttribute(ELM_TYPE, IS_CLIENT); 1484 } 1485 } else { 1486 log.warn("Authentication error (security info missing)"); 1487 Element err = addContentElement(ERROR, "Authentication error (security info missing).", data); 1488 err.setAttribute(ELM_TYPE, IS_CLIENT); 1489 } 1490 return null; 1491 } 1492} 1493 1494 | Popular Tags |