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.setFilename(filename); 117 file1.setPropertyValue("content", (Serializable) blob1); 118 Calendar cal1 = getCalendar(2007, 3, 1, 12, 0, 0); 119 file1.setPropertyValue("dc:created", cal1); 120 file1.setPropertyValue("dc:modified", cal1); 121 file1.setPropertyValue("dc:creator", "michael"); 122 file1.setPropertyValue("dc:lastContributor", "john"); 123 file1.setPropertyValue("dc:coverage", "foo/bar"); 124 file1.setPropertyValue("dc:subjects", new String[] { "foo", "gee/moo" }); 125 file1.addFacet(ThumbnailConstants.THUMBNAIL_FACET); 126 Blob thumbnailBlob; 127 String digest; 128 try { 129 thumbnailBlob = Blobs.createBlob(Helper.class.getResource("/text.png").openStream(), "image/png"); 130 digest = DigestUtils.md5Hex(thumbnailBlob.getStream()); 131 } catch (IOException e) { 132 throw new RuntimeException(e); 133 } 134 thumbnailBlob.setDigest(digest); 135 thumbnailBlob.setFilename("test.png"); 136 file1.setPropertyValue(ThumbnailConstants.THUMBNAIL_PROPERTY_NAME, (Serializable) thumbnailBlob); 137 file1 = createDocument(session, file1); 138 139 ACPImpl acp; 140 ACL acl; 141 acl = new ACLImpl(); 142 acl.add(new ACE("bob", SecurityConstants.BROWSE, true)); 143 acp = new ACPImpl(); 144 acp.addACL(acl); 145 file1.setACP(acp, true); 146 147 DocumentModel file2 = new DocumentModelImpl("/testfolder1", "testfile2", "File"); 148 file2.setPropertyValue("dc:title", "testfile2_Title"); 149 file2.setPropertyValue("dc:description", "something"); 150 Calendar cal2 = getCalendar(2007, 4, 1, 12, 0, 0); 151 file2.setPropertyValue("dc:created", cal2); 152 file2.setPropertyValue("dc:creator", "pete"); 153 file2.setPropertyValue("dc:contributors", new String[] { "pete", "bob" }); 154 file2.setPropertyValue("dc:lastContributor", "bob"); 155 file2.setPropertyValue("dc:coverage", "football"); 156 file2 = createDocument(session, file2); 157 158 acl = new ACLImpl(); 159 acl.add(new ACE("bob", SecurityConstants.BROWSE, true)); 160 acp = new ACPImpl(); 161 acp.addACL(acl); 162 file2.setACP(acp, true); 163 164 DocumentModel file3 = new DocumentModelImpl("/testfolder1", "testfile3", "Note"); 165 file3.setPropertyValue("note", "this is a note"); 166 file3.setPropertyValue("dc:title", "testfile3_Title"); 167 file3.setPropertyValue("dc:description", "testfile3_desc1 testfile3_desc2, testfile3_desc3"); 168 file3.setPropertyValue("dc:contributors", new String[] { "bob", "john" }); 169 file3.setPropertyValue("dc:lastContributor", "john"); 170 file3 = createDocument(session, file3); 171 172 DocumentModel folder2 = new DocumentModelImpl("/", "testfolder2", "Folder"); 173 folder2.setPropertyValue("dc:title", "testfolder2_Title"); 174 folder2 = createDocument(session, folder2); 175 176 DocumentModel folder3 = new DocumentModelImpl("/testfolder2", "testfolder3", "Folder"); 177 folder3.setPropertyValue("dc:title", "testfolder3_Title"); 178 folder3 = createDocument(session, folder3); 179 180 DocumentModel folder4 = new DocumentModelImpl("/testfolder2", "testfolder4", "Folder"); 181 folder4.setPropertyValue("dc:title", "testfolder4_Title"); 182 folder4 = createDocument(session, folder4); 183 184 DocumentModel file4 = new DocumentModelImpl("/testfolder2/testfolder3", "testfile4", "File"); 185 file4.setPropertyValue("dc:title", "testfile4_Title"); 186 file4.setPropertyValue("dc:description", "something"); 187 file4 = createDocument(session, file4); 188 189 DocumentModel file5 = new DocumentModelImpl("/testfolder1", "testfile5", "File"); 190 file5.setPropertyValue("dc:title", "title5"); 191 file5 = createDocument(session, file5); 192 file5.followTransition(DELETE_TRANSITION); 193 file5 = saveDocument(session, file5); 194 info.put("file5id", file5.getId()); 195 196 session.save(); 197 if (TransactionHelper.isTransactionActive()) { 198 TransactionHelper.commitOrRollbackTransaction(); 199 TransactionHelper.startTransaction(); 200 } 201 202 Framework.getLocalService(EventService.class).waitForAsyncCompletion(); 203 204 return info; 205 } 206 207 /** 208 * For audit, make sure event dates don't have the same millisecond. 209 */ 210 public static void sleepForAuditGranularity() { 211 try { 212 Thread.sleep(2); 213 } catch (InterruptedException e) { 214 ExceptionUtils.checkInterrupt(e); 215 } 216 } 217 218 public static DocumentModel createDocument(CoreSession session, DocumentModel doc) { 219 sleepForAuditGranularity(); 220 // avoid changes in last contributor in these tests 221 doc.putContextData("disableDublinCoreListener", Boolean.TRUE); 222 return session.createDocument(doc); 223 } 224 225 public static DocumentModel saveDocument(CoreSession session, DocumentModel doc) { 226 sleepForAuditGranularity(); 227 return session.saveDocument(doc); 228 } 229 230 public static String createUserWorkspace(CoreSession repo, String username) { 231 232 DocumentModel container = new DocumentModelImpl("/", "UserWorkspaceRoot", "UserWorkspaceRoot"); 233 container = repo.createDocument(container); 234 { 235 ACP acp = new ACPImpl(); 236 ACL acl = new ACLImpl(); 237 acl.setACEs(new ACE[] { new ACE(SecurityConstants.EVERYONE, SecurityConstants.EVERYTHING, false) }); 238 acp.addACL(acl); 239 container.setACP(acp, true); 240 } 241 242 DocumentModel ws = new DocumentModelImpl(container.getPathAsString(), username, "Workspace"); 243 ws = repo.createDocument(ws); 244 ACP acp = new ACPImpl(); 245 { 246 ACL acl = new ACLImpl(); 247 acl.setACEs(new ACE[] { new ACE(username, SecurityConstants.EVERYTHING, true) }); 248 acp.addACL(acl); 249 ws.setACP(acp, true); 250 } 251 252 repo.save(); 253 if (TransactionHelper.isTransactionActive()) { 254 TransactionHelper.commitOrRollbackTransaction(); 255 TransactionHelper.startTransaction(); 256 } 257 return ws.getPathAsString(); 258 } 259}