You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by fg...@apache.org on 2009/10/30 19:46:24 UTC

svn commit: r831421 - in /incubator/chemistry/trunk/chemistry: chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/ chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ chemistry-atompub-server/src/mai...

Author: fguillaume
Date: Fri Oct 30 18:46:23 2009
New Revision: 831421

URL: http://svn.apache.org/viewvc?rev=831421&view=rev
Log:
Implement update for Simple and AtomPub client/server

Modified:
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ObjectEntryWriter.java
    incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java
    incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java
    incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java?rev=831421&r1=831420&r2=831421&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/APPConnection.java Fri Oct 30 18:46:23 2009
@@ -60,6 +60,7 @@
 import org.apache.chemistry.atompub.client.connector.Response;
 import org.apache.chemistry.atompub.client.stax.ReadContext;
 import org.apache.chemistry.atompub.client.stax.XmlProperty;
+import org.apache.chemistry.impl.simple.SimpleObjectId;
 
 /**
  *
@@ -167,8 +168,7 @@
     }
 
     public ObjectId newObjectId(String id) {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException();
+        return new SimpleObjectId(id);
     }
 
     /*
@@ -422,8 +422,20 @@
 
     public ObjectEntry getProperties(ObjectId object, String filter,
             boolean includeAllowableActions, boolean includeRelationships) {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException();
+        APPObjectEntry current = getObjectEntry(object);
+        String href = current.getLink(AtomPub.LINK_SELF);
+        Response resp = connector.get(new Request(href));
+        if (!resp.isOk()) {
+            if (resp.getStatusCode() == 404) {
+                // object not found, signature says return null
+                return null;
+            }
+            throw new ContentManagerException(
+                    "Remote server returned error code: "
+                            + resp.getStatusCode());
+        }
+        // TODO fill current
+        return (APPObjectEntry) resp.getObject(new ReadContext(this));
     }
 
     public ObjectEntry getObjectByPath(String path, String filter,
@@ -480,6 +492,7 @@
 
     public ObjectId setContentStream(ObjectId document, boolean overwrite,
             ContentStream contentStream) {
+        // LINK_EDIT_MEDIA
         // TODO Auto-generated method stub
         throw new UnsupportedOperationException();
     }
@@ -491,8 +504,26 @@
 
     public ObjectId updateProperties(ObjectId object, String changeToken,
             Map<String, Serializable> properties) {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException();
+        // make properties into an entry for putObject
+        APPObjectEntry current = getObjectEntry(object);
+        APPObjectEntry update = newObjectEntry(current.getTypeId());
+        for (String key : properties.keySet()) {
+            update._setValue(key, properties.get(key));
+        }
+        update._setValue(Property.ID, object.getId());
+        // TODO proper title
+        update._setValue(Property.NAME, current.getValue(Property.NAME));
+
+        String href = current.getLink(AtomPub.LINK_EDIT);
+        Request req = new Request(href);
+        req.setHeader("Content-Type", AtomPub.MEDIA_TYPE_ATOM_ENTRY);
+        Response resp = connector.putObject(req, update);
+        if (!resp.isOk()) {
+            throw new ContentManagerException(
+                    "Remote server returned error code: "
+                            + resp.getStatusCode());
+        }
+        return (APPObjectEntry) resp.getObject(new ReadContext(this));
     }
 
     public ObjectId moveObject(ObjectId object, ObjectId targetFolder,

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ObjectEntryWriter.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ObjectEntryWriter.java?rev=831421&r1=831420&r2=831421&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ObjectEntryWriter.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-client/src/main/java/org/apache/chemistry/atompub/client/stax/ObjectEntryWriter.java Fri Oct 30 18:46:23 2009
@@ -48,15 +48,7 @@
             xw.start();
             // atom requires an ID to be set even on new created entries ..
             xw.element("id").content("urn:uuid:" + object.getId());
-            // TODO hardcoded title properties...
-            String title = (String) object.getValue("title");
-            if (title == null) {
-                title = (String) object.getValue("dc:title");
-            }
-            if (title == null) {
-                title = (String) object.getValue(Property.NAME);
-            }
-            xw.element("title").content(title);
+            xw.element("title").content((String) object.getValue(Property.NAME));
             xw.element("updated").content(new Date());
             writeContent(object, xw);
             writeCmisObject(object, xw);

Modified: incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java?rev=831421&r1=831420&r2=831421&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-atompub-server/src/main/java/org/apache/chemistry/atompub/server/CMISObjectsCollection.java Fri Oct 30 18:46:23 2009
@@ -52,7 +52,6 @@
 import org.apache.chemistry.ObjectEntry;
 import org.apache.chemistry.ObjectId;
 import org.apache.chemistry.Property;
-import org.apache.chemistry.PropertyDefinition;
 import org.apache.chemistry.Repository;
 import org.apache.chemistry.SPI;
 import org.apache.chemistry.Type;
@@ -172,9 +171,10 @@
                 entry.addLink(getObjectLink(pid, request), AtomPub.LINK_UP,
                         AtomPub.MEDIA_TYPE_ATOM_ENTRY, null, null, -1);
             }
-            // TODO don't add links if no children/decendants
+            // down link always present to be able to add children
             entry.addLink(getChildrenLink(oid, request), AtomPub.LINK_DOWN,
                     AtomPub.MEDIA_TYPE_ATOM_FEED, null, null, -1);
+            // TODO don't add descendants links if no children
             entry.addLink(getDescendantsLink(oid, request), AtomPub.LINK_DOWN,
                     AtomPubCMIS.MEDIA_TYPE_CMIS_TREE, null, null, -1);
         } else if (baseType == BaseType.DOCUMENT) {
@@ -191,41 +191,76 @@
         return link;
     }
 
-    protected static String bool(boolean bool) {
-        return bool ? "true" : "false";
+    // getEntries is abstract, must be implemented
+
+    protected static class PropertiesAndStream {
+        public Map<String, Serializable> properties;
+
+        public InputStream stream;
+
+        public String mimeType;
     }
 
-    // getEntries is abstract, must be implemented
+    /**
+     * Finds properties and stream from entry.
+     *
+     * @param typeId is null for a POST, existing type for a PUT
+     */
+    protected PropertiesAndStream extractCMISProperties(RequestContext request,
+            String typeId) throws ResponseContextException {
+        boolean isNew = typeId == null;
+        Entry entry = getEntryFromRequest(request);
+        if (entry == null || !ProviderHelper.isValidEntry(entry)) {
+            throw new ResponseContextException(400);
+        }
 
-    @Override
-    public ResponseContext postEntry(RequestContext request) {
-        // TODO parameter sourceFolderId
-        // TODO parameter versioningState
-        Entry entry;
-        try {
-            entry = getEntryFromRequest(request);
-        } catch (ResponseContextException e) {
-            return createErrorResponse(e);
+        // get properties and type from entry
+        Map<String, Serializable> properties;
+        Element obb = entry.getFirstChild(AtomPubCMIS.OBJECT);
+        if (obb == null) {
+            // no CMIS object, basic AtomPub post/put
+            properties = new HashMap<String, Serializable>();
+            if (isNew) {
+                typeId = BaseType.DOCUMENT.getId();
+                properties.put(Property.TYPE_ID, typeId);
+            }
+        } else {
+            ObjectElement objectElement = new ObjectElement(obb, repository);
+            try {
+                properties = objectElement.getProperties();
+            } catch (Exception e) { // TODO proper exception
+                throw new ResponseContextException(500, e);
+            }
+            // type
+            String tid = (String) properties.get(Property.TYPE_ID);
+            if (isNew) {
+                // post
+                typeId = tid;
+            } else if (!typeId.equals(tid)) {
+                // mismatched types during put
+                throw new ResponseContextException("Invalid type: " + tid, 500);
+            }
         }
-        if (entry == null /* || !ProviderHelper.isValidEntry(entry) TODO XXX TCK */) {
-            return new EmptyResponseContext(400);
+        Type type = repository.getType(typeId);
+        if (type == null) {
+            throw new ResponseContextException("Unknown type: " + typeId, 500);
         }
 
+        // get stream and its mime type from entry
         InputStream stream;
         String mimeType;
-
         Element cmisContent = entry.getFirstChild(AtomPubCMIS.CONTENT);
         if (cmisContent != null) {
+            // cmisra:content has precedence over atom:content
             Element el = cmisContent.getFirstChild(AtomPubCMIS.MEDIA_TYPE);
             if (el == null) {
-                return createErrorResponse(new ResponseContextException(
-                        "missing cmisra:mediatype", 500));
+                throw new ResponseContextException("missing cmisra:mediatype",
+                        500);
             }
             mimeType = el.getText();
             el = cmisContent.getFirstChild(AtomPubCMIS.BASE64);
             if (el == null) {
-                return createErrorResponse(new ResponseContextException(
-                        "missing cmisra:base64", 500));
+                throw new ResponseContextException("missing cmisra:base64", 500);
             }
             byte[] b64 = el.getText().getBytes(); // no charset, pure ASCII
             stream = new ByteArrayInputStream(Base64.decodeBase64(b64));
@@ -260,8 +295,7 @@
                                 content.getValue().getBytes("UTF-8"));
                     }
                 } catch (IOException e1) {
-                    return createErrorResponse(new ResponseContextException(
-                            "cannot get stream", 500));
+                    throw new ResponseContextException("cannot get stream", 500);
                 }
             } else {
                 stream = null;
@@ -269,99 +303,78 @@
             }
         }
 
-        Map<String, Serializable> properties;
-        Type type;
-        Element obb = entry.getFirstChild(AtomPubCMIS.OBJECT);
-        if (obb != null) {
-            ObjectElement objectElement = new ObjectElement(obb, repository);
-            try {
-                properties = objectElement.getProperties();
-            } catch (Exception e) { // TODO proper exception
-                return createErrorResponse(new ResponseContextException(500, e));
-            }
-            String typeId = (String) properties.get(Property.TYPE_ID);
-            type = repository.getType(typeId);
-            if (type == null) {
-                return createErrorResponse(new ResponseContextException(
-                        "Unknown type: " + typeId, 500));
-            }
-        } else {
-            properties = new HashMap<String, Serializable>();
-            type = repository.getType(BaseType.DOCUMENT.getId());
-        }
-
-        // set Atom-defined properties into entry
-        // TODO hardcoded title properties...
-        PropertyDefinition pdt = type.getPropertyDefinition("title");
-        if (pdt == null) {
-            pdt = type.getPropertyDefinition("dc:title");
-        }
-        if (pdt == null) {
-            pdt = type.getPropertyDefinition(Property.NAME); // mandatory
-        }
+        // set Atom-defined properties into properties
+        // title
         String title = entry.getTitle(); // Atom MUST
-        properties.put(pdt.getId(), title);
+        properties.put(Property.NAME, title);
         // TODO summary
-        // parse the date ourselves, as Abdera's AtomDate loses the timezone
-        Calendar updated;
-        DateTime updatedElement = entry.getUpdatedElement(); // Atom MUST
-        if (updatedElement == null) { // TODO XXX TCK
-            updated = null;
-        } else {
-            updated = GregorianCalendar.fromAtomPub(updatedElement.getText());
-            properties.put(Property.LAST_MODIFICATION_DATE, updated);
+        if (isNew) {
+            // updated
+            // parse the date ourselves, as Abdera's AtomDate loses the timezone
+            DateTime updatedElement = entry.getUpdatedElement(); // Atom MUST
+            if (updatedElement != null) { // TODO XXX TCK
+                Calendar updated = GregorianCalendar.fromAtomPub(updatedElement.getText());
+                properties.put(Property.LAST_MODIFICATION_DATE, updated);
+            }
         }
 
-        SPI spi = repository.getSPI(); // TODO XXX connection leak
-        ObjectId folderId = spi.newObjectId(id);
-        ObjectId objectId;
-        switch (type.getBaseType()) {
-        case DOCUMENT:
-            String filename = (String) properties.get(Property.CONTENT_STREAM_FILE_NAME);
-            ContentStream contentStream;
-            if (stream == null) {
-                contentStream = null;
-            } else {
+        PropertiesAndStream res = new PropertiesAndStream();
+        res.properties = properties;
+        res.stream = stream;
+        res.mimeType = mimeType;
+        return res;
+    }
+
+    @Override
+    public ResponseContext postEntry(RequestContext request) {
+        // TODO parameter sourceFolderId
+        // TODO parameter versioningState
+        try {
+            PropertiesAndStream posted = extractCMISProperties(request, null);
+
+            SPI spi = repository.getSPI(); // TODO XXX connection leak
+            ObjectId folderId = spi.newObjectId(id);
+            ObjectId objectId;
+            String typeId = (String) posted.properties.get(Property.TYPE_ID);
+            BaseType baseType = repository.getType(typeId).getBaseType();
+            switch (baseType) {
+            case DOCUMENT:
+                String filename = (String) posted.properties.get(Property.CONTENT_STREAM_FILE_NAME);
+                ContentStream contentStream;
                 try {
-                    contentStream = new SimpleContentStream(stream, mimeType,
-                            filename);
+                    contentStream = new SimpleContentStream(posted.stream,
+                            posted.mimeType, filename);
                 } catch (IOException e) {
-                    return createErrorResponse(new ResponseContextException(
-                            500, e));
+                    throw new ResponseContextException(500, e);
                 }
-            }
-            VersioningState versioningState = null; // TODO
-            objectId = spi.createDocument(properties, folderId, contentStream,
-                    versioningState);
-            break;
-        case FOLDER:
-            objectId = spi.createFolder(properties, folderId);
-            break;
-        default:
-            throw new UnsupportedOperationException("not implemented: "
-                    + type.getBaseType());
-        }
-
-        ObjectEntry object = spi.getProperties(objectId, null, false, false);
-
-        // prepare the updated entry to return in the response
-        // AbstractEntityCollectionAdapter#getEntryFromCollectionProvider is
-        // package-private...
-        entry = request.getAbdera().getFactory().newEntry();
-        try {
-            // AbstractEntityCollectionAdapter#buildEntry is private...
+                VersioningState versioningState = null; // TODO
+                objectId = spi.createDocument(posted.properties, folderId,
+                        contentStream, versioningState);
+                break;
+            case FOLDER:
+                objectId = spi.createFolder(posted.properties, folderId);
+                break;
+            default:
+                throw new UnsupportedOperationException("not implemented: "
+                        + baseType);
+            }
+
+            // prepare the updated entry to return in the response
+            // AbstractEntityCollectionAdapter#getEntryFromCollectionProvider is
+            // package-private...
+            Entry entry = request.getAbdera().getFactory().newEntry();
+            ObjectEntry object = spi.getProperties(objectId, null, false, false);
             addEntryDetails(request, entry, null, object);
             if (isMediaEntry(object)) {
-                IRI feedIri = null;
-                addMediaContent(feedIri, entry, object, request);
+                addMediaContent(null, entry, object, request);
             } else {
                 addContent(entry, object, request);
             }
+            String link = getObjectLink(object.getId(), request);
+            return buildCreateEntryResponse(link, entry);
         } catch (ResponseContextException e) {
             return createErrorResponse(e);
         }
-        String link = getObjectLink(object.getId(), request);
-        return buildCreateEntryResponse(link, entry);
     }
 
     // unused but abstract in parent...
@@ -373,6 +386,57 @@
     }
 
     @Override
+    public ResponseContext putEntry(RequestContext request) {
+        try {
+            // existing object
+            String id = getResourceName(request);
+            SPI spi = repository.getSPI(); // TODO XXX connection leak
+            ObjectEntry object = spi.getProperties(spi.newObjectId(id), null,
+                    false, false);
+            if (object == null) {
+                return new EmptyResponseContext(404);
+            }
+
+            PropertiesAndStream put = extractCMISProperties(request,
+                    object.getTypeId());
+
+            // update entry
+            String changeToken = null; // TODO
+            spi.updateProperties(object, changeToken, put.properties);
+            if (put.stream != null) {
+                String filename = (String) put.properties.get(Property.CONTENT_STREAM_FILE_NAME);
+                if (filename == null) {
+                    filename = (String) object.getValue(Property.CONTENT_STREAM_FILE_NAME);
+                }
+                ContentStream contentStream;
+                try {
+                    contentStream = new SimpleContentStream(put.stream,
+                            put.mimeType, filename);
+                } catch (IOException e) {
+                    throw new ResponseContextException(500, e);
+                }
+                spi.setContentStream(object, true, contentStream);
+            }
+
+            // build response
+            Entry entry = request.getAbdera().getFactory().newEntry();
+            // refetch full object
+            object = spi.getProperties(object, null, false, false);
+            addEntryDetails(request, entry, null, object);
+            if (isMediaEntry(object)) {
+                addMediaContent(null, entry, object, request);
+            } else {
+                addContent(entry, object, request);
+            }
+            return buildGetEntryResponse(request, entry);
+
+        } catch (ResponseContextException e) {
+            return createErrorResponse(e);
+        }
+    }
+
+    // unused but abstract in parent...
+    @Override
     public void putEntry(ObjectEntry object, String title, Date updated,
             List<Person> authors, String summary, Content content,
             RequestContext request) throws ResponseContextException {
@@ -524,16 +588,7 @@
 
     @Override
     public String getTitle(ObjectEntry object) {
-        String title = null;
-        try {
-            title = (String) object.getValue("title"); // TODO improve
-        } catch (Exception e) {
-            // no such property or bad type
-        }
-        if (title == null) {
-            title = (String) object.getValue(Property.NAME);
-        }
-        return title;
+        return (String) object.getValue(Property.NAME);
     }
 
     @Override
@@ -562,8 +617,9 @@
             // no such property or bad type
         }
         if (summary == null) {
-            return null;
+            summary = (String) object.getValue(Property.NAME);
         }
+        // TODO summary not needed if there's a non-base64 inline content
         Text text = request.getAbdera().getFactory().newSummary();
         text.setValue(summary);
         return text;

Modified: incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java?rev=831421&r1=831420&r2=831421&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-commons/src/main/java/org/apache/chemistry/impl/simple/SimpleConnection.java Fri Oct 30 18:46:23 2009
@@ -59,6 +59,7 @@
 import org.apache.chemistry.SPI;
 import org.apache.chemistry.Type;
 import org.apache.chemistry.Unfiling;
+import org.apache.chemistry.Updatability;
 import org.apache.chemistry.VersioningState;
 import org.apache.chemistry.cmissql.CmisSqlLexer;
 import org.apache.chemistry.cmissql.CmisSqlParser;
@@ -577,8 +578,36 @@
 
     public ObjectId setContentStream(ObjectId document, boolean overwrite,
             ContentStream contentStream) {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException();
+        SimpleData data = repository.datas.get(document.getId());
+        if (contentStream == null) {
+            data.remove(SimpleProperty.CONTENT_BYTES_KEY);
+            data.remove(Property.CONTENT_STREAM_MIME_TYPE);
+            data.remove(Property.CONTENT_STREAM_FILE_NAME);
+            data.remove(Property.CONTENT_STREAM_LENGTH);
+        } else {
+            byte[] bytes;
+            try {
+                bytes = SimpleContentStream.getBytes(contentStream.getStream());
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+            data.put(SimpleProperty.CONTENT_BYTES_KEY, bytes);
+            data.put(Property.CONTENT_STREAM_LENGTH,
+                    Integer.valueOf(bytes.length)); // TODO-Long
+            String mt = contentStream.getMimeType();
+            if (mt == null) {
+                data.remove(Property.CONTENT_STREAM_MIME_TYPE);
+            } else {
+                data.put(Property.CONTENT_STREAM_MIME_TYPE, mt);
+            }
+            String fn = contentStream.getFileName();
+            if (fn == null) {
+                data.remove(Property.CONTENT_STREAM_FILE_NAME);
+            } else {
+                data.put(Property.CONTENT_STREAM_FILE_NAME, fn);
+            }
+        }
+        return document;
     }
 
     public ObjectId deleteContentStream(ObjectId document) {
@@ -588,8 +617,35 @@
 
     public ObjectId updateProperties(ObjectId object, String changeToken,
             Map<String, Serializable> properties) {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException();
+        // TODO changeToken
+        SimpleData data = repository.datas.get(object.getId());
+        String typeId = (String) data.get(Property.TYPE_ID);
+        Type type = repository.getType(typeId);
+        for (String key : properties.keySet()) {
+            if (key.equals(Property.ID) || key.equals(Property.TYPE_ID)) {
+                continue;
+            }
+            PropertyDefinition pd = type.getPropertyDefinition(key);
+            Updatability updatability = pd.getUpdatability();
+            if (updatability == Updatability.ON_CREATE
+                    || updatability == Updatability.READ_ONLY) {
+                // ignore attempts to write a read-only prop, as clients
+                // may want to take an existing entry, change a few values,
+                // and write the new one
+                continue;
+                // throw new RuntimeException("Read-only property: " + key);
+            }
+            Serializable value = properties.get(key);
+            if (value == null) {
+                if (pd.isRequired()) {
+                    throw new RuntimeException("Required property: " + key); // TODO
+                }
+                data.remove(key);
+            } else {
+                data.put(key, value);
+            }
+        }
+        return object;
     }
 
     public ObjectId moveObject(ObjectId object, ObjectId targetFolder,

Modified: incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java?rev=831421&r1=831420&r2=831421&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-jcr/src/main/java/org/apache/chemistry/jcr/JcrConnection.java Fri Oct 30 18:46:23 2009
@@ -151,8 +151,7 @@
     }
 
     public ObjectId newObjectId(String id) {
-        // TODO Auto-generated method stub
-        throw new UnsupportedOperationException();
+        return new SimpleObjectId(id);
     }
 
     // ----------------------------------------------------------------------

Modified: incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java
URL: http://svn.apache.org/viewvc/incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java?rev=831421&r1=831420&r2=831421&view=diff
==============================================================================
--- incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java (original)
+++ incubator/chemistry/trunk/chemistry/chemistry-tests/src/main/java/org/apache/chemistry/test/BasicTestCase.java Fri Oct 30 18:46:23 2009
@@ -18,9 +18,11 @@
 package org.apache.chemistry.test;
 
 import java.io.InputStream;
+import java.io.Serializable;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -381,4 +383,19 @@
         assertEquals("mytitle", fold.getString("title"));
     }
 
+    public void testUpdateSPI() {
+        ObjectEntry ob = spi.getObjectByPath("/folder 1/doc 1", null, false,
+                false);
+        assertEquals("doc 1 title", ob.getValue("title"));
+        assertEquals("The doc 1 descr", ob.getValue("description"));
+        // update
+        Map<String, Serializable> properties = new HashMap<String, Serializable>();
+        properties.put("description", "new descr");
+        spi.updateProperties(ob, null, properties);
+        // refetch
+        ob = spi.getProperties(ob, null, false, false);
+        assertEquals("doc 1 title", ob.getValue("title"));
+        assertEquals("new descr", ob.getValue("description"));
+    }
+
 }