/* * (C) Copyright 2006-2016 Nuxeo SA (http://nuxeo.com/) and others. * * Licensed 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. * * Contributors: * Thierry Delprat * Florent Guillaume */ package org.nuxeo.ecm.platform.dublincore; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.nuxeo.ecm.platform.dublincore.listener.DublinCoreListener.DISABLE_DUBLINCORE_LISTENER; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; import javax.inject.Inject; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.nuxeo.ecm.core.api.CoreInstance; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.CoreSession.CopyOption; import org.nuxeo.ecm.core.api.DataModel; import org.nuxeo.ecm.core.api.DocumentModel; import org.nuxeo.ecm.core.api.PathRef; import org.nuxeo.ecm.core.api.UnrestrictedSessionRunner; import org.nuxeo.ecm.core.api.impl.DocumentModelImpl; import org.nuxeo.ecm.core.api.security.ACE; import org.nuxeo.ecm.core.api.security.ACL; import org.nuxeo.ecm.core.api.security.ACP; import org.nuxeo.ecm.core.api.security.SecurityConstants; import org.nuxeo.ecm.core.event.EventProducer; import org.nuxeo.ecm.core.event.EventService; import org.nuxeo.ecm.core.event.impl.DocumentEventContext; import org.nuxeo.ecm.core.test.CoreFeature; import org.nuxeo.ecm.core.test.StorageConfiguration; import org.nuxeo.ecm.platform.dublincore.service.DublinCoreStorageService; import org.nuxeo.ecm.platform.login.test.ClientLoginFeature; import org.nuxeo.runtime.api.Framework; import org.nuxeo.runtime.test.runner.Deploy; import org.nuxeo.runtime.test.runner.Features; import org.nuxeo.runtime.test.runner.FeaturesRunner; import org.nuxeo.runtime.test.runner.LocalDeploy; import org.nuxeo.runtime.test.runner.RuntimeHarness; import org.nuxeo.runtime.transaction.TransactionHelper; /** * DublinCoreStorage Test Case. */ @RunWith(FeaturesRunner.class) @Features({ CoreFeature.class, ClientLoginFeature.class }) @Deploy("org.nuxeo.ecm.platform.dublincore") @LocalDeploy("org.nuxeo.ecm.platform.dublincore.tests:OSGI-INF/types-contrib.xml") public class TestDublinCoreStorage { @Inject protected CoreFeature feature; protected StorageConfiguration storageConfiguration; @Inject protected CoreSession session; @Inject protected RuntimeHarness runtimeHarness; @Before public void before() { storageConfiguration = feature.getStorageConfiguration(); } @Test public void testStorageService() { DublinCoreStorageService service = NXDublinCore.getDublinCoreStorageService(); assertNotNull(service); } @Test public void testCreationDateAndCreator() { DocumentModel childFile = new DocumentModelImpl("/", "file-007", "File"); DocumentModel childFile2 = session.createDocument(childFile); assertNotNull(childFile2.getPropertyValue("dc:created")); assertEquals("Administrator", childFile2.getPropertyValue("dc:creator")); } @Test public void testModificationDate() { DocumentModel childFile = new DocumentModelImpl("/", "file-008", "File"); DocumentModel childFile2 = session.createDocument(childFile); try { Thread.sleep(100); } catch (InterruptedException e) { } childFile2.setProperty("dublincore", "title", "toto"); session.saveDocument(childFile2); DataModel dm = childFile2.getDataModel("dublincore"); Calendar created = (Calendar) dm.getData("created"); assertNotNull(created); Calendar modified = (Calendar) childFile2.getPropertyValue("dc:modified"); assertNotNull(modified); assertTrue(modified.getTime() + " !> " + created.getTime(), modified.after(created)); } // Wait until we can have a real list management @Test public void testContributors() { DocumentModel childFile = new DocumentModelImpl("/", "file-008", "File"); DocumentModel childFile2 = session.createDocument(childFile); DataModel dm = childFile2.getDataModel("dublincore"); String author = (String) dm.getData("creator"); assertEquals("Administrator", author); String[] contributorsArray = (String[]) dm.getData("contributors"); List<String> contributorsList = Arrays.asList(contributorsArray); assertTrue(contributorsList.contains("Administrator")); // modify security to test with a new user DocumentModel root = session.getRootDocument(); ACP acp = root.getACP(); ACL[] acls = acp.getACLs(); ACL theAcl = acls[0]; ACE ace = new ACE("Jacky", SecurityConstants.EVERYTHING, true); theAcl.add(ace); root.setACP(acp, true); // create a new session session.save(); try (CoreSession session2 = CoreInstance.openCoreSession(session.getRepositoryName(), "Jacky")) { DocumentModel childFile3 = session2.getDocument(childFile2.getRef()); childFile3.setProperty("dublincore", "source", "testing"); childFile3 = session2.saveDocument(childFile3); contributorsArray = (String[]) childFile3.getDataModel("dublincore").getData("contributors"); contributorsList = Arrays.asList(contributorsArray); assertTrue(contributorsList.contains("Jacky")); assertEquals("Administrator", childFile3.getProperty("dublincore", "creator")); } } @Test public void testLastContributor() { DocumentModel childFile = new DocumentModelImpl("/", "file-008", "File"); DocumentModel childFile2 = session.createDocument(childFile); DataModel dm = childFile2.getDataModel("dublincore"); String lastContributor = (String) dm.getData("lastContributor"); assertEquals("Administrator", lastContributor); String[] contributorsArray = (String[]) dm.getData("contributors"); List<String> contributorsList = Arrays.asList(contributorsArray); assertTrue(contributorsList.contains("Administrator")); // modify security to test with tow new user DocumentModel root = session.getRootDocument(); ACP acp = root.getACP(); ACL[] acls = acp.getACLs(); ACL theAcl = acls[0]; ACE ace = new ACE("Jacky", SecurityConstants.EVERYTHING, true); theAcl.add(ace); ace = new ACE("Fredo", SecurityConstants.EVERYTHING, true); theAcl.add(ace); root.setACP(acp, true); session.save(); // create a new session try (CoreSession session2 = CoreInstance.openCoreSession(session.getRepositoryName(), "Jacky")) { DocumentModel childFile3 = session2.getDocument(childFile2.getRef()); childFile3.setProperty("dublincore", "source", "testing"); childFile3 = session2.saveDocument(childFile3); contributorsArray = (String[]) childFile3.getDataModel("dublincore").getData("contributors"); contributorsList = Arrays.asList(contributorsArray); assertTrue(contributorsList.contains("Jacky")); assertEquals(1, contributorsList.indexOf("Jacky")); assertEquals("Jacky", childFile3.getProperty("dublincore", "lastContributor")); session2.save(); } // Test if a new contributor will be at the end of the list try (CoreSession session3 = CoreInstance.openCoreSession(session.getRepositoryName(), "Fredo")) { DocumentModel childFile3 = session3.getDocument(childFile2.getRef()); childFile3.setProperty("dublincore", "source", "testing2"); // make a change childFile3 = session3.saveDocument(childFile3); contributorsArray = (String[]) childFile3.getDataModel("dublincore").getData("contributors"); contributorsList = Arrays.asList(contributorsArray); assertTrue(contributorsList.contains("Fredo")); assertEquals("Fredo", childFile3.getProperty("dublincore", "lastContributor")); session3.save(); } // Test if a previously contributor will be move to the end of the list try (CoreSession session4 = CoreInstance.openCoreSession(session.getRepositoryName(), "Administrator")) { DocumentModel childFile3 = session4.getDocument(childFile2.getRef()); childFile3.setProperty("dublincore", "source", "testing"); childFile3 = session4.saveDocument(childFile3); contributorsArray = (String[]) childFile3.getDataModel("dublincore").getData("contributors"); contributorsList = Arrays.asList(contributorsArray); assertTrue(contributorsList.contains("Administrator")); assertEquals("Administrator", childFile3.getProperty("dublincore", "lastContributor")); } } @Test public void testContributorsAndModifiedDoesntChangeIfTheresNoChanges() { DocumentModel childFile = new DocumentModelImpl("/", "file-008", "File"); childFile = session.createDocument(childFile); DataModel dm = childFile.getDataModel("dublincore"); // backup the data to check Calendar modified = (Calendar) dm.getData("modified"); String lastContributor = (String) dm.getData("lastContributor"); String[] contributors = (String[]) dm.getData("contributors"); // save the document with no changes childFile = session.saveDocument(childFile); // get the data to check Calendar modified2 = (Calendar) dm.getData("modified"); String lastContributor2 = (String) dm.getData("lastContributor"); String[] contributors2 = (String[]) dm.getData("contributors"); assertEquals(modified, modified2); assertEquals(lastContributor, lastContributor2); assertArrayEquals(contributors, contributors2); } @Test public void testIssuedDate() { DocumentModel folder1 = new DocumentModelImpl("/", "testfolder1", "Folder"); folder1 = session.createDocument(folder1); DocumentModel file1 = new DocumentModelImpl("/testfolder1", "testfile1", "File"); file1 = session.createDocument(file1); DocumentModel proxyDoc = session.publishDocument(file1, folder1); getEventProducer().fireEvent( new DocumentEventContext(session, session.getPrincipal(), proxyDoc).newEvent("documentPublished")); DocumentModel version = session.getSourceDocument(proxyDoc.getRef()); Calendar issued = (Calendar) version.getPropertyValue("dc:issued"); assertNotNull(issued); } @Test public void testProxySchemas() { DocumentModel folder = new DocumentModelImpl("/", "folder", "Folder"); folder = session.createDocument(folder); DocumentModel doc = new DocumentModelImpl("/", "file", "File"); doc = session.createDocument(doc); DocumentModel proxy = session.publishDocument(doc, folder); session.save(); proxy.setPropertyValue("info:info", "proxyinfo"); proxy = session.saveDocument(proxy); session.save(); } @Test public void testProxySchemasWithComplex() { DocumentModel folder = new DocumentModelImpl("/", "folder", "Folder"); folder = session.createDocument(folder); DocumentModel doc = new DocumentModelImpl("/", "file", "File"); doc = session.createDocument(doc); DocumentModel proxy = session.publishDocument(doc, folder); session.save(); // read part of a non-initialized complex prop // should not mark it dirty which would cause problems on save proxy.getPropertyValue("file:content"); // write a modifiable proxy schema proxy.setPropertyValue("info:info", "proxyinfo"); proxy = session.saveDocument(proxy); session.save(); } /* check that creating a live proxy to a doc doesn't update the doc. */ @Test public void testProxyLive() throws Exception { // create file DocumentModel file = session.createDocumentModel("/", "file", "File"); file = session.createDocument(file); Calendar created1 = (Calendar) file.getPropertyValue("dc:created"); Thread.sleep(1000); // create proxy DocumentModel proxy = session.createProxy(file.getRef(), new PathRef("/")); proxy = session.saveDocument(proxy); // check file file = session.getDocument(file.getRef()); Calendar created2 = (Calendar) file.getPropertyValue("dc:created"); assertEquals(created1.getTimeInMillis(), created2.getTimeInMillis()); } @Test public void testDisableListener() { DocumentModel childFile = new DocumentModelImpl("/", "file-007", "File"); childFile.setPropertyValue("dc:creator", "Bender"); Date now = new Date(); childFile.setPropertyValue("dc:created", now); childFile.putContextData(DISABLE_DUBLINCORE_LISTENER, Boolean.TRUE); DocumentModel childFile2 = session.createDocument(childFile); assertEquals(now, ((Calendar) childFile2.getPropertyValue("dc:created")).getTime()); assertEquals("Bender", childFile2.getPropertyValue("dc:creator")); } private static EventProducer getEventProducer() { return Framework.getService(EventProducer.class); } @Test public void testCreatorForUnrestrictedSessionCreatedDoc() throws Exception { try (CoreSession session2 = CoreInstance.openCoreSession(session.getRepositoryName(), "Jacky")) { CreateDocumentUnrestricted runner = new CreateDocumentUnrestricted(session2); runner.runUnrestricted(); DocumentModel doc = runner.getFolder(); String creator = (String) doc.getPropertyValue("dc:creator"); assertEquals("Jacky", creator); } } public class CreateDocumentUnrestricted extends UnrestrictedSessionRunner { private DocumentModel folder; public CreateDocumentUnrestricted(CoreSession session) { super(session); } @Override public void run() { folder = new DocumentModelImpl("/", "testfolder1", "Folder"); folder = session.createDocument(folder); session.saveDocument(folder); } public DocumentModel getFolder() { return folder; } } @Test public void testCopyDocument() throws Exception { DocumentModel file = session.createDocument(session.createDocumentModel("/", "file-007", "File")); storageConfiguration.maybeSleepToNextSecond(); DocumentModel copy = session.copy(file.getRef(), file.getParentRef(), "file-008"); waitForAsyncCompletion(); assertNotNull(copy); assertEquals(file.getPropertyValue("dc:created"), copy.getPropertyValue("dc:created")); assertEquals(file.getPropertyValue("dc:modified"), copy.getPropertyValue("dc:modified")); } @Test public void testCopyDocumentWithResetCoreMetadata() throws Exception { DocumentModel file = session.createDocument(session.createDocumentModel("/", "file-007", "File")); storageConfiguration.maybeSleepToNextSecond(); DocumentModel copy = session.copy(file.getRef(), file.getParentRef(), "file-008", CopyOption.RESET_CREATOR); waitForAsyncCompletion(); assertNotNull(copy); assertNotEquals(file.getPropertyValue("dc:created"), copy.getPropertyValue("dc:created")); assertNotEquals(file.getPropertyValue("dc:modified"), copy.getPropertyValue("dc:modified")); } @Test public void testCopyDocumentWithResetCoreMetadataByConfiguration() throws Exception { runtimeHarness.deployTestContrib("org.nuxeo.ecm.platform.dublincore.test.reset-creator.contrib", "OSGI-INF/reset-creator-contrib.xml"); DocumentModel file = session.createDocument(session.createDocumentModel("/", "file-007", "File")); storageConfiguration.maybeSleepToNextSecond(); DocumentModel copy = session.copy(file.getRef(), file.getParentRef(), "file-008"); waitForAsyncCompletion(); assertNotNull(copy); assertNotEquals(file.getPropertyValue("dc:created"), copy.getPropertyValue("dc:created")); assertNotEquals(file.getPropertyValue("dc:modified"), copy.getPropertyValue("dc:modified")); } protected void waitForAsyncCompletion() { if (TransactionHelper.isTransactionActiveOrMarkedRollback()) { TransactionHelper.commitOrRollbackTransaction(); TransactionHelper.startTransaction(); } Framework.getService(EventService.class).waitForAsyncCompletion(); } }