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