You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xindice-dev@xml.apache.org by vg...@apache.org on 2005/05/26 03:17:11 UTC

cvs commit: xml-xindice/java/tests/src/org/apache/xindice/integration/client/services XUpdateQueryTest.java

vgritsenko    2005/05/25 18:17:11

  Modified:    .        status.xml
               java/src/org/apache/xindice/core/xupdate XUpdateImpl.java
               java/tests/src/org/apache/xindice/integration/client/services
                        XUpdateQueryTest.java
  Log:
  apply patch from Todd Byrne, fix xupdate bug #30878
  
  Revision  Changes    Path
  1.52      +8 -1      xml-xindice/status.xml
  
  Index: status.xml
  ===================================================================
  RCS file: /home/cvs/xml-xindice/status.xml,v
  retrieving revision 1.51
  retrieving revision 1.52
  diff -u -r1.51 -r1.52
  --- status.xml	4 Mar 2005 03:38:14 -0000	1.51
  +++ status.xml	26 May 2005 01:17:11 -0000	1.52
  @@ -73,7 +73,14 @@
       </todo>
   
       <changes>
  -        <release version="1.1b5-dev" date="March 3 2005">
  +        <release version="1.1b5-dev" date="May 25 2005">
  +            <action dev="VG" type="fix" fixes-bug="30878" due-to="Todd Byrne">
  +                Make sure that XUpdate commands are run only once per document.
  +                In case XUpdate command does not complete successfully, revert
  +                all affected documents to the original state. This requires
  +                buffering of modified documents - so XUpdate on large collection
  +                might require lots of memory.
  +            </action>
               <action dev="VG" type="update" fixes-bug="33657" due-to="Dave Brosius">
                   Added support for current Xalan CVS (post 2.6.0 release).
               </action>
  
  
  
  1.13      +34 -21    xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java
  
  Index: XUpdateImpl.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/src/org/apache/xindice/core/xupdate/XUpdateImpl.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- XUpdateImpl.java	8 Feb 2004 02:50:54 -0000	1.12
  +++ XUpdateImpl.java	26 May 2005 01:17:11 -0000	1.13
  @@ -1,5 +1,5 @@
   /*
  - * Copyright 1999-2004 The Apache Software Foundation.
  + * Copyright 1999-2005 The Apache Software Foundation.
    *
    * Licensed under the Apache License, Version 2.0 (the "License");
    * you may not use this file except in compliance with the License.
  @@ -34,27 +34,30 @@
   import org.xmldb.xupdate.lexus.commands.DefaultCommand;
   
   import java.util.Enumeration;
  +import java.util.HashMap;
   import java.util.Hashtable;
  +import java.util.Iterator;
  +import java.util.Map;
   
   /**
    * Provides Collection and document based XUpdate capabilities.
    *
    * For more detail about XUpdate look at the
  - * <a href="http://www.xmldb.org/xupdate/xupdate-wd.html">XUpdate Working Draft</a>.
  + * <a href="http://xmldb-org.sourceforge.net/xupdate/xupdate-wd.html">XUpdate Working Draft</a>.
    *
    * @version CVS $Revision$, $Date$
    */
   public class XUpdateImpl extends XUpdateQueryImpl {
   
  -    protected int nodesModified = 0;
  -    protected NamespaceMap nsMap;
  -
       /**
        * If set to true, then namespaces set explicitly via an API call will take precendence.
        * If set to false, then namespaces set implicitly within query string will take precedence.
        */
       private static final boolean API_NS_PRECEDENCE = true;
   
  +    protected int nodesModified;
  +    protected NamespaceMap nsMap;
  +
       /**
        * Set the namespace map to be used when resolving queries
        */
  @@ -148,44 +151,54 @@
        * @exception Exception Description of Exception
        */
       public void execute(Collection col) throws Exception {
  -
           int attribIndex = 0;
  +
  +        // TODO: Don't cache all the documents in memory.
  +        // Need to keep updated documents in memory so that can
  +        // 'rollback' all the changes in case of failure.
  +        // Won't need this in case underlying collection supports
  +        // transaction.
  +        HashMap docsUpdated = new HashMap();
           for (int i = 0; i < super.query[0].size(); i++) {
               int cmdID = ((Integer) super.query[0].elementAt(i)).intValue();
   
               if (cmdID == CommandConstants.ATTRIBUTES) {
                   Hashtable attribs = (Hashtable) super.query[1].elementAt(attribIndex);
  -                attribIndex++;
                   String selector = (String) attribs.get("select");
  +                attribIndex++;
   
  -                // If we found an XPath selector we need to execute the commands.
  -                if (selector != null) {
  +                // If we found an XPath selector we need to execute the commands,
  +                // but we can not execute xupdate variables again.
  +                // all variables start with a '$'
  +                if (selector != null && !selector.startsWith("$")) {
                       NodeSet ns = col.queryCollection("XPath", selector, nsMap);
  -                    Document lastDoc = null;
                       while (ns != null && ns.hasMoreNodes()) {
                           DBNode node = (DBNode) ns.getNextNode();
                           Document doc = node.getOwnerDocument();
  +                        NodeSource source = node.getSource();
   
  -                        if (doc == lastDoc) {
  +                        if (docsUpdated.containsKey(source.getKey())) {
                               continue; // We only have to process it once
                           } else {
  -                            lastDoc = doc;
  +                            docsUpdated.put(source.getKey(), doc);
                           }
   
  -                        NodeSource source = node.getSource();
  -
  -                        Node contextNode = doc.getDocumentElement();
  -                        execute(contextNode);
  -
  -                        col.setDocument(source.getKey(), doc);
  +                        execute(doc.getDocumentElement());
                       }
                   }
               }
           }
  +
  +        // Update all documents at once
  +        // this way we don't get any half run xupdate commands.
  +        Iterator i = docsUpdated.entrySet().iterator();
  +        while (i.hasNext()) {
  +            Map.Entry set = (Map.Entry) i.next();
  +            col.setDocument(set.getKey(), (Document) set.getValue());
  +        }
       }
   
       public int getModifiedCount() {
           return nodesModified;
       }
   }
  -
  
  
  
  1.8       +44 -7     xml-xindice/java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java
  
  Index: XUpdateQueryTest.java
  ===================================================================
  RCS file: /home/cvs/xml-xindice/java/tests/src/org/apache/xindice/integration/client/services/XUpdateQueryTest.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- XUpdateQueryTest.java	1 Apr 2005 02:46:43 -0000	1.7
  +++ XUpdateQueryTest.java	26 May 2005 01:17:11 -0000	1.8
  @@ -22,6 +22,9 @@
   
   import org.xmldb.api.modules.XUpdateQueryService;
   import org.xmldb.api.base.Collection;
  +import org.apache.commons.logging.Log;
  +import org.apache.commons.logging.LogFactory;
  +import org.custommonkey.xmlunit.XMLAssert;
   
   /**
    * @version CVS $Revision$, $Date$
  @@ -29,7 +32,7 @@
    */
   public class XUpdateQueryTest
           extends AbstractXmlDbClientTest {
  -
  +    private static final Log log = LogFactory.getLog(XUpdateQueryTest.class);
       public void setUp() throws Exception {
           super.setUp();
   
  @@ -96,6 +99,7 @@
                   "<last>Smith</last>" +
                   "<phone type=\"work\">480-300-3003</phone>" +
                   "</person>";
  +
           String updatedDocument2 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
                   "<person status=\"divorced\">" +
                   "<first>Ben</first>" +
  @@ -103,18 +107,51 @@
                   "<phone type=\"work\">480-300-3003</phone>" +
                   "</person>";
   
  +        String query2 =
  +                "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
  +                "<xupdate:modifications version=\"1.0\" xmlns:xupdate=\"http://www.xmldb.org/xupdate\">" +
  +                "<xupdate:append select=\"/person/first\">" +
  +                "<xupdate:element name=\"test2\"/>" +
  +                "</xupdate:append>" +
  +                "<xupdate:append select=\"/person/last\">" +
  +                "<xupdate:element name=\"test1\"/>" +
  +                "</xupdate:append>" +
  +                "</xupdate:modifications>";
  +
  +        String updatedDocument3 = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
  +                "<person status=\"divorced\">" +
  +                "<first>Ben" +
  +                "<test2 />" +
  +                "</first>" +
  +                "<last>Benton"+
  +                "<test1 />" +
  +                "</last>" +
  +                "<phone type=\"work\">480-300-3003</phone>" +
  +                "</person>";
  +
           Collection col = this.client.getCollection(TEST_COLLECTION_PATH);
           XUpdateQueryService service = (XUpdateQueryService) col.getService("XUpdateQueryService", "1.0");
  -
           long count = service.update(query);
  -        assertEquals(6, count);
  +        // Fixed: was 6 should be 2. The old code would cause multiple updates.
  +        assertEquals(2, count);
   
           String doc = this.client.getDocument(TEST_COLLECTION_PATH, "doc1");
           assertNotNull(doc);
  -        assertEquals(updatedDocument1, doc);
  +        XMLAssert.assertXMLEqual(updatedDocument1, doc);
   
           doc = this.client.getDocument(TEST_COLLECTION_PATH, "doc2");
           assertNotNull(doc);
  -        assertEquals(updatedDocument2, doc);
  +        XMLAssert.assertXMLEqual(updatedDocument2, doc);
  +
  +        // test the second query should update 2 docs
  +        count = service.update(query2);
  +        assertEquals(2,count);
  +
  +        // check the second doc to make sure its correct
  +        doc = this.client.getDocument(TEST_COLLECTION_PATH, "doc2");
  +
  +        log.debug("Doc2:=\n " + doc);
  +        log.debug("UpdatedDoc3:\n " + updatedDocument3);
  +        XMLAssert.assertXMLEqual(updatedDocument3,doc);
       }
   }