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}