001/* 002 * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the Eclipse Public License v1.0 006 * which accompanies this distribution, and is available at 007 * http://www.eclipse.org/legal/epl-v10.html 008 * 009 * Contributors: 010 * Florent Guillaume 011 */ 012package org.nuxeo.ecm.core.opencmis.tests; 013 014import java.io.ByteArrayOutputStream; 015import java.io.IOException; 016import java.io.InputStream; 017import java.io.Serializable; 018import java.util.Calendar; 019import java.util.GregorianCalendar; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.TimeZone; 023 024import org.apache.commons.codec.digest.DigestUtils; 025import org.nuxeo.common.utils.ExceptionUtils; 026import org.nuxeo.ecm.core.api.Blob; 027import org.nuxeo.ecm.core.api.Blobs; 028import org.nuxeo.ecm.core.api.CoreSession; 029import org.nuxeo.ecm.core.api.DocumentModel; 030import org.nuxeo.ecm.core.api.DocumentRef; 031import org.nuxeo.ecm.core.api.PathRef; 032import org.nuxeo.ecm.core.api.impl.DocumentModelImpl; 033import org.nuxeo.ecm.core.api.security.ACE; 034import org.nuxeo.ecm.core.api.security.ACL; 035import org.nuxeo.ecm.core.api.security.ACP; 036import org.nuxeo.ecm.core.api.security.SecurityConstants; 037import org.nuxeo.ecm.core.api.security.impl.ACLImpl; 038import org.nuxeo.ecm.core.api.security.impl.ACPImpl; 039import org.nuxeo.ecm.core.event.EventService; 040import org.nuxeo.ecm.platform.thumbnail.ThumbnailConstants; 041import org.nuxeo.runtime.api.Framework; 042import org.nuxeo.runtime.transaction.TransactionHelper; 043 044/** 045 * Various static methods used in several test cases. 046 */ 047public class Helper { 048 049 public static final String DELETE_TRANSITION = "delete"; 050 051 public static final String FILE1_CONTENT = "Noodles with rice"; 052 053 /** 054 * Reads a stream into a string. 055 */ 056 public static String read(InputStream in, String charset) throws IOException { 057 ByteArrayOutputStream os = new ByteArrayOutputStream(); 058 byte[] buf = new byte[256]; 059 try { 060 int n; 061 while ((n = in.read(buf)) != -1) { 062 os.write(buf, 0, n); 063 } 064 } finally { 065 in.close(); 066 } 067 return os.toString(charset); 068 } 069 070 /** 071 * Gets a Calendar object. 072 */ 073 public static GregorianCalendar getCalendar(int year, int month, int day, int hours, int minutes, int seconds) { 074 TimeZone tz = TimeZone.getTimeZone("GMT-02:00"); // in the Atlantic 075 return getCalendar(year, month, day, hours, minutes, seconds, tz); 076 } 077 078 /** 079 * Gets a Calendar object with a specific timezone 080 */ 081 public static GregorianCalendar getCalendar(int year, int month, int day, int hours, int minutes, int seconds, 082 TimeZone tz) { 083 GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance(tz); 084 cal.set(Calendar.YEAR, year); 085 cal.set(Calendar.MONTH, month - 1); // 0-based 086 cal.set(Calendar.DAY_OF_MONTH, day); 087 cal.set(Calendar.HOUR_OF_DAY, hours); 088 cal.set(Calendar.MINUTE, minutes); 089 cal.set(Calendar.SECOND, seconds); 090 cal.set(Calendar.MILLISECOND, 0); 091 return cal; 092 } 093 094 /** 095 * Creates data in the repository using the Nuxeo API. This is then used as a starting point by unit tests. 096 */ 097 public static Map<String, String> makeNuxeoRepository(CoreSession session) { 098 // remove default-domain 099 DocumentRef defaultDomain = new PathRef("/default-domain"); 100 if (session.exists(defaultDomain)) { 101 session.removeDocument(defaultDomain); 102 } 103 104 Map<String, String> info = new HashMap<String, String>(); 105 106 DocumentModel folder1 = new DocumentModelImpl("/", "testfolder1", "Folder"); 107 folder1.setPropertyValue("dc:title", "testfolder1_Title"); 108 folder1 = createDocument(session, folder1); 109 110 DocumentModel file1 = new DocumentModelImpl("/testfolder1", "testfile1", "File"); 111 file1.setPropertyValue("dc:title", "testfile1_Title"); 112 file1.setPropertyValue("dc:description", "testfile1_description"); 113 String content = FILE1_CONTENT; 114 String filename = "testfile.txt"; 115 Blob blob1 = Blobs.createBlob(content); 116 blob1.setDigest(DigestUtils.md5Hex(content)); 117 blob1.setFilename(filename); 118 file1.setPropertyValue("content", (Serializable) blob1); 119 Calendar cal1 = getCalendar(2007, 3, 1, 12, 0, 0); 120 file1.setPropertyValue("dc:created", cal1); 121 file1.setPropertyValue("dc:modified", cal1); 122 file1.setPropertyValue("dc:creator", "michael"); 123 file1.setPropertyValue("dc:lastContributor", "john"); 124 file1.setPropertyValue("dc:coverage", "foo/bar"); 125 file1.setPropertyValue("dc:subjects", new String[] { "foo", "gee/moo" }); 126 file1.addFacet(ThumbnailConstants.THUMBNAIL_FACET); 127 Blob thumbnailBlob; 128 String digest; 129 try { 130 thumbnailBlob = Blobs.createBlob(Helper.class.getResource("/text.png").openStream(), "image/png"); 131 digest = DigestUtils.md5Hex(thumbnailBlob.getStream()); 132 } catch (IOException e) { 133 throw new RuntimeException(e); 134 } 135 thumbnailBlob.setDigest(digest); 136 thumbnailBlob.setFilename("test.png"); 137 file1.setPropertyValue(ThumbnailConstants.THUMBNAIL_PROPERTY_NAME, (Serializable) thumbnailBlob); 138 file1 = createDocument(session, file1); 139 140 ACPImpl acp; 141 ACL acl; 142 acl = new ACLImpl(); 143 acl.add(new ACE("bob", SecurityConstants.BROWSE, true)); 144 acp = new ACPImpl(); 145 acp.addACL(acl); 146 file1.setACP(acp, true); 147 148 DocumentModel file2 = new DocumentModelImpl("/testfolder1", "testfile2", "File"); 149 file2.setPropertyValue("dc:title", "testfile2_Title"); 150 file2.setPropertyValue("dc:description", "something"); 151 Calendar cal2 = getCalendar(2007, 4, 1, 12, 0, 0); 152 file2.setPropertyValue("dc:created", cal2); 153 file2.setPropertyValue("dc:creator", "pete"); 154 file2.setPropertyValue("dc:contributors", new String[] { "pete", "bob" }); 155 file2.setPropertyValue("dc:lastContributor", "bob"); 156 file2.setPropertyValue("dc:coverage", "football"); 157 file2 = createDocument(session, file2); 158 159 acl = new ACLImpl(); 160 acl.add(new ACE("bob", SecurityConstants.BROWSE, true)); 161 acp = new ACPImpl(); 162 acp.addACL(acl); 163 file2.setACP(acp, true); 164 165 DocumentModel file3 = new DocumentModelImpl("/testfolder1", "testfile3", "Note"); 166 file3.setPropertyValue("note", "this is a note"); 167 file3.setPropertyValue("dc:title", "testfile3_Title"); 168 file3.setPropertyValue("dc:description", "testfile3_desc1 testfile3_desc2, testfile3_desc3"); 169 file3.setPropertyValue("dc:contributors", new String[] { "bob", "john" }); 170 file3.setPropertyValue("dc:lastContributor", "john"); 171 file3 = createDocument(session, file3); 172 173 DocumentModel folder2 = new DocumentModelImpl("/", "testfolder2", "Folder"); 174 folder2.setPropertyValue("dc:title", "testfolder2_Title"); 175 folder2 = createDocument(session, folder2); 176 177 DocumentModel folder3 = new DocumentModelImpl("/testfolder2", "testfolder3", "Folder"); 178 folder3.setPropertyValue("dc:title", "testfolder3_Title"); 179 folder3 = createDocument(session, folder3); 180 181 DocumentModel folder4 = new DocumentModelImpl("/testfolder2", "testfolder4", "Folder"); 182 folder4.setPropertyValue("dc:title", "testfolder4_Title"); 183 folder4 = createDocument(session, folder4); 184 185 DocumentModel file4 = new DocumentModelImpl("/testfolder2/testfolder3", "testfile4", "File"); 186 file4.setPropertyValue("dc:title", "testfile4_Title"); 187 file4.setPropertyValue("dc:description", "something"); 188 file4 = createDocument(session, file4); 189 190 DocumentModel file5 = new DocumentModelImpl("/testfolder1", "testfile5", "File"); 191 file5.setPropertyValue("dc:title", "title5"); 192 file5 = createDocument(session, file5); 193 file5.followTransition(DELETE_TRANSITION); 194 file5 = saveDocument(session, file5); 195 info.put("file5id", file5.getId()); 196 197 session.save(); 198 if (TransactionHelper.isTransactionActive()) { 199 TransactionHelper.commitOrRollbackTransaction(); 200 TransactionHelper.startTransaction(); 201 } 202 203 Framework.getLocalService(EventService.class).waitForAsyncCompletion(); 204 205 return info; 206 } 207 208 /** 209 * For audit, make sure event dates don't have the same millisecond. 210 */ 211 public static void sleepForAuditGranularity() { 212 try { 213 Thread.sleep(2); 214 } catch (InterruptedException e) { 215 ExceptionUtils.checkInterrupt(e); 216 } 217 } 218 219 public static DocumentModel createDocument(CoreSession session, DocumentModel doc) { 220 sleepForAuditGranularity(); 221 // avoid changes in last contributor in these tests 222 doc.putContextData("disableDublinCoreListener", Boolean.TRUE); 223 return session.createDocument(doc); 224 } 225 226 public static DocumentModel saveDocument(CoreSession session, DocumentModel doc) { 227 sleepForAuditGranularity(); 228 return session.saveDocument(doc); 229 } 230 231 public static String createUserWorkspace(CoreSession repo, String username) { 232 233 DocumentModel container = new DocumentModelImpl("/", "UserWorkspaceRoot", "UserWorkspaceRoot"); 234 container = repo.createDocument(container); 235 { 236 ACP acp = new ACPImpl(); 237 ACL acl = new ACLImpl(); 238 acl.setACEs(new ACE[] { new ACE(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, false) }); 239 acp.addACL(acl); 240 container.setACP(acp, true); 241 } 242 243 DocumentModel ws = new DocumentModelImpl(container.getPathAsString(), username, "Workspace"); 244 ws = repo.createDocument(ws); 245 ACP acp = new ACPImpl(); 246 { 247 ACL acl = new ACLImpl(); 248 acl.setACEs(new ACE[] { new ACE(username, SecurityConstants.EVERYTHING, true) }); 249 acp.addACL(acl); 250 ws.setACP(acp, true); 251 } 252 253 repo.save(); 254 if (TransactionHelper.isTransactionActive()) { 255 TransactionHelper.commitOrRollbackTransaction(); 256 TransactionHelper.startTransaction(); 257 } 258 return ws.getPathAsString(); 259 } 260}