All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.chemistry.opencmis.tck.tests.crud.ChangeTokenTest Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.chemistry.opencmis.tck.tests.crud;

import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.FAILURE;
import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.INFO;
import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.SKIPPED;
import static org.apache.chemistry.opencmis.tck.CmisTestResultStatus.WARNING;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.chemistry.opencmis.client.api.Document;
import org.apache.chemistry.opencmis.client.api.Folder;
import org.apache.chemistry.opencmis.client.api.ObjectId;
import org.apache.chemistry.opencmis.client.api.Session;
import org.apache.chemistry.opencmis.commons.PropertyIds;
import org.apache.chemistry.opencmis.commons.data.ContentStream;
import org.apache.chemistry.opencmis.commons.definitions.DocumentTypeDefinition;
import org.apache.chemistry.opencmis.commons.definitions.PropertyDefinition;
import org.apache.chemistry.opencmis.commons.enums.Action;
import org.apache.chemistry.opencmis.commons.enums.CapabilityContentStreamUpdates;
import org.apache.chemistry.opencmis.commons.enums.Updatability;
import org.apache.chemistry.opencmis.commons.exceptions.CmisUpdateConflictException;
import org.apache.chemistry.opencmis.commons.impl.IOUtils;
import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
import org.apache.chemistry.opencmis.tck.impl.AbstractSessionTest;

public class ChangeTokenTest extends AbstractSessionTest {

    @Override
    public void init(Map parameters) {
        super.init(parameters);
        setName("Change Token Test");
        setDescription("Creates a document and a folder and updates them with an outdated change token.");
    }

    @Override
    public void run(Session session) {
        // create a test folder
        Folder testFolder = createTestFolder(session);

        try {
            // update document properties test
            runUpdateDocumentTest(session, testFolder);

            // content update test
            runContentTest(session, testFolder);

            // update folder properties test
            runUpdateFolderTest(session, testFolder);

            // add child and update folder properties test
            runAddChildFolderTest(session, testFolder);
        } finally {
            // delete the test folder
            deleteTestFolder();
        }
    }

    private void runUpdateDocumentTest(Session session, Folder testFolder) {
        Document doc = createDocument(session, testFolder, "update1.txt", "Hello World!");

        try {
            if (doc.getChangeToken() == null) {
                addResult(createResult(SKIPPED,
                        "Repository does not provide change tokens for documents. Test skipped!"));
                return;
            }

            DocumentTypeDefinition type = (DocumentTypeDefinition) doc.getType();
            PropertyDefinition namePropDef = type.getPropertyDefinitions().get(PropertyIds.NAME);
            if (namePropDef.getUpdatability() == Updatability.WHENCHECKEDOUT
                    || !doc.getAllowableActions().getAllowableActions().contains(Action.CAN_UPDATE_PROPERTIES)) {
                addResult(createResult(SKIPPED, "Document name can't be changed. Test skipped!"));
                return;
            }

            // the first update should succeed
            Map properties2 = new HashMap();
            properties2.put(PropertyIds.NAME, "update2.txt");
            ObjectId newId = doc.updateProperties(properties2, false);

            if (!doc.getId().equals(newId.getId())) {
                // the repository created a new version
                // -> a change token test does not make sense
                addResult(createResult(INFO,
                        "The repository created a new version. Change tokens are not relevant here."));
            } else {
                try {
                    Map properties3 = new HashMap();
                    properties3.put(PropertyIds.NAME, "update3.txt");
                    doc.updateProperties(properties3, false);

                    addResult(createResult(FAILURE, "Updating properties a second time with the same change token "
                            + "should result in an UpdateConflict exception!"));
                } catch (CmisUpdateConflictException e) {
                    // expected exception
                }
            }
        } finally {
            deleteObject(doc);
        }
    }

    private void runContentTest(Session session, Folder testFolder) {
        if (session.getRepositoryInfo().getCapabilities().getContentStreamUpdatesCapability() != CapabilityContentStreamUpdates.ANYTIME) {
            addResult(createResult(SKIPPED, "Repository doesn't allow to replace content. Test skipped!"));
            return;
        }

        Document doc = createDocument(session, testFolder, "content1.txt", "Hello World!");

        try {
            if (doc.getChangeToken() == null) {
                addResult(createResult(SKIPPED,
                        "Repository does not provide change tokens for documents. Test skipped!"));
                return;
            }

            if (!doc.getAllowableActions().getAllowableActions().contains(Action.CAN_SET_CONTENT_STREAM)) {
                addResult(createResult(SKIPPED, "Document content can't be changed. Test skipped!"));
                return;
            }

            byte[] contentBytes = IOUtils.toUTF8Bytes("New content");
            ContentStream contentStream = new ContentStreamImpl("content2.txt",
                    BigInteger.valueOf(contentBytes.length), "text/plain", new ByteArrayInputStream(contentBytes));

            ObjectId newId = doc.setContentStream(contentStream, true, false);

            if (newId == null) {
                // the AtomPub binding does not return an id here
                // -> get the latest id from the version series
                if (Boolean.TRUE.equals(((DocumentTypeDefinition) doc.getType()).isVersionable())) {
                    List versions = doc.getAllVersions();
                    if (versions == null || versions.size() < 1) {
                        addResult(createResult(FAILURE, "Repository returned an empty list of document versions!"));
                    } else {
                        // the latest document is at the top of the list
                        newId = versions.get(0);
                    }
                } else {
                    // the document type is not versionable
                    // -> the repository couldn't create a new version
                    newId = doc;
                }
            }

            if (newId != null) {
                if (!doc.getId().equals(newId.getId())) {
                    // the repository created a new version
                    // -> a change token test does not make sense
                    addResult(createResult(INFO,
                            "The repository created a new version. Change tokens are not relevant here."));
                } else {
                    try {
                        doc.setContentStream(contentStream, true, false);

                        addResult(createResult(FAILURE, "Updating content a second time with the same change token "
                                + "should result in an UpdateConflict exception!"));
                    } catch (CmisUpdateConflictException uce) {
                        // expected exception
                    }
                }
            }
        } finally {
            deleteObject(doc);
        }
    }

    private void runUpdateFolderTest(Session session, Folder testFolder) {
        Folder folder = createFolder(session, testFolder, "folder1");

        try {
            if (folder.getChangeToken() == null) {
                addResult(createResult(SKIPPED, "Repository does not provide change tokens for folders. Test skipped!"));
                return;
            }

            if (!folder.getAllowableActions().getAllowableActions().contains(Action.CAN_UPDATE_PROPERTIES)) {
                addResult(createResult(SKIPPED, "Folder name can't be changed. Test skipped!"));
                return;
            }

            // the first update should succeed
            Map properties2 = new HashMap();
            properties2.put(PropertyIds.NAME, "folder2");
            folder.updateProperties(properties2, false);

            try {
                Map properties3 = new HashMap();
                properties3.put(PropertyIds.NAME, "folder3");
                folder.updateProperties(properties3, false);

                addResult(createResult(FAILURE, "Updating properties a second time with the same change token "
                        + "should result in an UpdateConflict exception!"));
            } catch (CmisUpdateConflictException e) {
                // expected exception
            }

        } finally {
            deleteObject(folder);
        }
    }

    private void runAddChildFolderTest(Session session, Folder testFolder) {
        Folder folder = createFolder(session, testFolder, "folder1");

        try {
            if (folder.getChangeToken() == null) {
                addResult(createResult(SKIPPED, "Repository does not provide change tokens for folders. Test skipped!"));
                return;
            }

            if (!folder.getAllowableActions().getAllowableActions().contains(Action.CAN_UPDATE_PROPERTIES)) {
                addResult(createResult(SKIPPED, "Folder name can't be changed. Test skipped!"));
                return;
            }

            createDocument(session, folder, "doc1", "content");

            try {
                Map properties2 = new HashMap();
                properties2.put(PropertyIds.NAME, "folder2");
                folder.updateProperties(properties2, false);
            } catch (CmisUpdateConflictException e) {
                addResult(createResult(WARNING, "Adding a child to a folder changes the change token of the folder. "
                        + "CMIS clients might not expect that."));
            }

        } finally {
            deleteObject(folder);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy