001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portlet.documentlibrary.store;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.util.CharPool;
019    import com.liferay.portal.kernel.util.ContentTypes;
020    import com.liferay.portal.kernel.util.LocaleUtil;
021    import com.liferay.portal.kernel.util.StringPool;
022    import com.liferay.portal.kernel.util.StringUtil;
023    import com.liferay.portal.kernel.util.Validator;
024    import com.liferay.portal.repository.cmis.CMISRepositoryUtil;
025    import com.liferay.portal.util.PropsValues;
026    import com.liferay.portlet.documentlibrary.DuplicateFileException;
027    import com.liferay.portlet.documentlibrary.NoSuchFileException;
028    import com.liferay.portlet.documentlibrary.util.DLUtil;
029    
030    import java.io.InputStream;
031    
032    import java.util.ArrayList;
033    import java.util.HashMap;
034    import java.util.Iterator;
035    import java.util.List;
036    import java.util.Locale;
037    import java.util.Map;
038    
039    import org.apache.chemistry.opencmis.client.api.CmisObject;
040    import org.apache.chemistry.opencmis.client.api.Document;
041    import org.apache.chemistry.opencmis.client.api.Folder;
042    import org.apache.chemistry.opencmis.client.api.ItemIterable;
043    import org.apache.chemistry.opencmis.client.api.ObjectId;
044    import org.apache.chemistry.opencmis.client.api.Repository;
045    import org.apache.chemistry.opencmis.client.api.Session;
046    import org.apache.chemistry.opencmis.client.api.SessionFactory;
047    import org.apache.chemistry.opencmis.client.runtime.ObjectIdImpl;
048    import org.apache.chemistry.opencmis.commons.PropertyIds;
049    import org.apache.chemistry.opencmis.commons.SessionParameter;
050    import org.apache.chemistry.opencmis.commons.data.ContentStream;
051    import org.apache.chemistry.opencmis.commons.enums.BaseTypeId;
052    import org.apache.chemistry.opencmis.commons.enums.BindingType;
053    import org.apache.chemistry.opencmis.commons.enums.UnfileObject;
054    import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl;
055    
056    /**
057     * @author Alexander Chow
058     * @author Edward Han
059     */
060    public class CMISStore extends BaseStore {
061    
062            public CMISStore() {
063                    _systemRootDir = getFolder(
064                            _session.getRootFolder(),
065                            PropsValues.DL_STORE_CMIS_SYSTEM_ROOT_DIR);
066    
067                    if (_systemRootDir == null) {
068                            _systemRootDir = createFolder(
069                                    _session.getRootFolder(),
070                                    PropsValues.DL_STORE_CMIS_SYSTEM_ROOT_DIR);
071                    }
072            }
073    
074            @Override
075            public void addDirectory(
076                    long companyId, long repositoryId, String dirName) {
077    
078                    Folder folder = getRepositoryFolder(companyId, repositoryId);
079    
080                    String[] dirNames = StringUtil.split(dirName, CharPool.SLASH);
081    
082                    for (String curDirName : dirNames) {
083                            Folder subFolder = getFolder(folder, curDirName);
084    
085                            if (subFolder == null) {
086                                    subFolder = createFolder(folder, curDirName);
087                            }
088    
089                            folder = subFolder;
090                    }
091            }
092    
093            @Override
094            public void addFile(
095                            long companyId, long repositoryId, String fileName, InputStream is)
096                    throws PortalException {
097    
098                    updateFile(
099                            companyId, repositoryId, fileName, VERSION_DEFAULT, is);
100            }
101    
102            @Override
103            public void checkRoot(long companyId) {
104            }
105    
106            @Override
107            public void copyFileVersion(
108                            long companyId, long repositoryId, String fileName,
109                            String fromVersionLabel, String toVersionLabel)
110                    throws PortalException {
111    
112                    Folder versioningFolder = getVersioningFolder(
113                            companyId, repositoryId, fileName, false);
114    
115                    ObjectId versioningFolderObjectId = new ObjectIdImpl(
116                            versioningFolder.getId());
117    
118                    Map<String, Object> documentProperties = new HashMap<String, Object>();
119    
120                    String title = String.valueOf(toVersionLabel);
121    
122                    documentProperties.put(PropertyIds.NAME, title);
123    
124                    documentProperties.put(
125                            PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value());
126    
127                    Document document = getVersionedDocument(
128                            companyId, repositoryId, fileName, fromVersionLabel);
129    
130                    document.copy(
131                            versioningFolderObjectId, documentProperties, null,
132                            document.getPolicies(), null, null, null);
133            }
134    
135            @Override
136            public void deleteDirectory(
137                    long companyId, long repositoryId, String dirName) {
138    
139                    Folder repositoryFolder = getRepositoryFolder(companyId, repositoryId);
140    
141                    Folder directory = getFolder(repositoryFolder, dirName);
142    
143                    if (directory != null) {
144                            directory.deleteTree(true, UnfileObject.DELETE, false);
145                    }
146            }
147    
148            @Override
149            public void deleteFile(long companyId, long repositoryId, String fileName)
150                    throws PortalException {
151    
152                    Folder versioningFolder = getVersioningFolder(
153                            companyId, repositoryId, fileName, false);
154    
155                    if (versioningFolder == null) {
156                            throw new NoSuchFileException();
157                    }
158    
159                    versioningFolder.deleteTree(true, UnfileObject.DELETE, false);
160            }
161    
162            @Override
163            public void deleteFile(
164                            long companyId, long repositoryId, String fileName,
165                            String versionLabel)
166                    throws PortalException {
167    
168                    Document document = getVersionedDocument(
169                            companyId, repositoryId, fileName, versionLabel);
170    
171                    document.delete(true);
172            }
173    
174            @Override
175            public InputStream getFileAsStream(
176                            long companyId, long repositoryId, String fileName,
177                            String versionLabel)
178                    throws PortalException {
179    
180                    if (Validator.isNull(versionLabel)) {
181                            versionLabel = getHeadVersionLabel(
182                                    companyId, repositoryId, fileName);
183                    }
184    
185                    Document document = getVersionedDocument(
186                            companyId, repositoryId, fileName, versionLabel);
187    
188                    return document.getContentStream().getStream();
189            }
190    
191            public String[] getFileNames(long companyId, long repositoryId) {
192                    Folder folder = getRepositoryFolder(companyId, repositoryId);
193    
194                    List<Folder> folders = getFolders(folder);
195    
196                    String[] fileNames = new String[folders.size()];
197    
198                    for (int i = 0; i < folders.size(); i++) {
199                            Folder curFolder = folders.get(i);
200    
201                            fileNames[i] = curFolder.getName();
202                    }
203    
204                    return fileNames;
205            }
206    
207            @Override
208            public String[] getFileNames(
209                    long companyId, long repositoryId, String dirName) {
210    
211                    Folder folder = getRepositoryFolder(companyId, repositoryId);
212    
213                    String[] dirNames = StringUtil.split(dirName, CharPool.SLASH);
214    
215                    for (String curDirName : dirNames) {
216                            Folder subFolder = getFolder(folder, curDirName);
217    
218                            if (subFolder == null) {
219                                    subFolder = createFolder(folder, curDirName);
220                            }
221    
222                            folder = subFolder;
223                    }
224    
225                    List<Folder> folders = getFolders(folder);
226    
227                    String[] fileNames = new String[folders.size()];
228    
229                    for (int i = 0; i < folders.size(); i++) {
230                            Folder curFolder = folders.get(i);
231    
232                            String fileName = curFolder.getName();
233    
234                            fileNames[i] = dirName.concat(StringPool.SLASH).concat(fileName);
235                    }
236    
237                    return fileNames;
238            }
239    
240            @Override
241            public long getFileSize(long companyId, long repositoryId, String fileName)
242                    throws PortalException {
243    
244                    String versionLabel = getHeadVersionLabel(
245                            companyId, repositoryId, fileName);
246    
247                    Document document = getVersionedDocument(
248                            companyId, repositoryId, fileName, versionLabel);
249    
250                    return document.getContentStreamLength();
251            }
252    
253            @Override
254            public boolean hasDirectory(
255                    long companyId, long repositoryId, String dirName) {
256    
257                    Folder folder = getRepositoryFolder(companyId, repositoryId);
258    
259                    String[] dirNames = StringUtil.split(dirName, CharPool.SLASH);
260    
261                    for (String subdirName : dirNames) {
262                            Folder subfolder = getFolder(folder, subdirName);
263    
264                            if (subfolder == null) {
265                                    return false;
266                            }
267                    }
268    
269                    return true;
270            }
271    
272            public String getHeadVersionLabel(
273                            long companyId, long repositoryId, String dirName)
274                    throws NoSuchFileException {
275    
276                    Folder versioningFolder = getVersioningFolder(
277                            companyId, repositoryId, dirName, false);
278    
279                    if (versioningFolder == null) {
280                            throw new NoSuchFileException();
281                    }
282    
283                    List<Folder> folders = getFolders(versioningFolder);
284    
285                    String headVersionLabel = VERSION_DEFAULT;
286    
287                    for (Folder folder : folders) {
288                            String versionLabel = folder.getName();
289    
290                            if (DLUtil.compareVersions(versionLabel, headVersionLabel) > 0) {
291                                    headVersionLabel = versionLabel;
292                            }
293                    }
294    
295                    return headVersionLabel;
296            }
297    
298            @Override
299            public boolean hasFile(
300                    long companyId, long repositoryId, String fileName,
301                    String versionLabel) {
302    
303                    Folder versioningFolder = getVersioningFolder(
304                            companyId, repositoryId, fileName, true);
305    
306                    Document document = getDocument(versioningFolder, versionLabel);
307    
308                    if (document == null) {
309                            return false;
310                    }
311                    else {
312                            return true;
313                    }
314            }
315    
316            @Override
317            public void move(String srcDir, String destDir) {
318            }
319    
320            @Override
321            public void updateFile(
322                    long companyId, long repositoryId, long newRepositoryId,
323                    String fileName) {
324    
325                    Folder oldVersioningFolderEntry = getVersioningFolder(
326                            companyId, repositoryId, fileName, true);
327                    Folder newVersioningFolderEntry = getVersioningFolder(
328                            companyId, newRepositoryId, fileName, true);
329    
330                    List<Folder> folders = getFolders(oldVersioningFolderEntry);
331    
332                    for (Folder folder : folders) {
333                            String curFileName = folder.getName();
334    
335                            Document document = getDocument(
336                                    oldVersioningFolderEntry, curFileName);
337    
338                            InputStream is = document.getContentStream().getStream();
339    
340                            createDocument(newVersioningFolderEntry, curFileName, is);
341                    }
342    
343                    oldVersioningFolderEntry.deleteTree(true, UnfileObject.DELETE, false);
344            }
345    
346            public void updateFile(
347                    long companyId, long repositoryId, String fileName,
348                    String newFileName) {
349    
350                    Folder oldVersioningFolderEntry = getVersioningFolder(
351                            companyId, repositoryId, fileName, true);
352                    Folder newVersioningFolderEntry = getVersioningFolder(
353                            companyId, repositoryId, newFileName, true);
354    
355                    List<Folder> folders = getFolders(oldVersioningFolderEntry);
356    
357                    for (Folder folder : folders) {
358                            String curFileName = folder.getName();
359    
360                            Document document = getDocument(
361                                    oldVersioningFolderEntry, curFileName);
362    
363                            InputStream is = document.getContentStream().getStream();
364    
365                            createDocument(newVersioningFolderEntry, curFileName, is);
366                    }
367    
368                    oldVersioningFolderEntry.deleteTree(true, UnfileObject.DELETE, false);
369            }
370    
371            @Override
372            public void updateFile(
373                            long companyId, long repositoryId, String fileName,
374                            String versionLabel, InputStream is)
375                    throws PortalException {
376    
377                    Folder versioningFolder = getVersioningFolder(
378                            companyId, repositoryId, fileName, true);
379    
380                    String title = String.valueOf(versionLabel);
381    
382                    Document document = getDocument(versioningFolder, title);
383    
384                    if (document != null) {
385                            throw new DuplicateFileException();
386                    }
387    
388                    createDocument(versioningFolder, title, is);
389            }
390    
391            @Override
392            public void updateFileVersion(
393                            long companyId, long repositoryId, String fileName,
394                            String fromVersionLabel, String toVersionLabel)
395                    throws PortalException {
396    
397                    Folder versioningFolder = getVersioningFolder(
398                            companyId, repositoryId, fileName, false);
399    
400                    String title = String.valueOf(toVersionLabel);
401    
402                    Document document = getDocument(versioningFolder, title);
403    
404                    if (document != null) {
405                            throw new DuplicateFileException();
406                    }
407    
408                    document = getVersionedDocument(
409                            companyId, repositoryId, fileName, fromVersionLabel);
410    
411                    Map<String, Object> documentProperties = new HashMap<String, Object>();
412    
413                    documentProperties.put(PropertyIds.NAME, title);
414    
415                    document.updateProperties(documentProperties);
416            }
417    
418            protected Document createDocument(
419                    Folder versioningFolder, String title, InputStream is) {
420    
421                    Map<String, Object> documentProperties = new HashMap<String, Object>();
422    
423                    documentProperties.put(PropertyIds.NAME, title);
424                    documentProperties.put(
425                            PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_DOCUMENT.value());
426    
427                    ContentStream contentStream = new ContentStreamImpl(
428                            null, null, ContentTypes.APPLICATION_OCTET_STREAM, is);
429    
430                    return versioningFolder.createDocument(
431                            documentProperties, contentStream, null);
432            }
433    
434            protected Folder createFolder(ObjectId parentFolderId, String name) {
435                    Map<String, Object> properties = new HashMap<String, Object>();
436    
437                    properties.put(PropertyIds.NAME, name);
438                    properties.put(
439                            PropertyIds.OBJECT_TYPE_ID, BaseTypeId.CMIS_FOLDER.value());
440    
441                    ObjectId objectId = _session.createFolder(properties, parentFolderId);
442    
443                    return (Folder)_session.getObject(objectId);
444            }
445    
446            protected Folder getCompanyFolder(long companyId) {
447                    String name = String.valueOf(companyId);
448    
449                    Folder companyFolder = getFolder(_systemRootDir, name);
450    
451                    if (companyFolder == null) {
452                            companyFolder = createFolder(_systemRootDir, name);
453                    }
454    
455                    return companyFolder;
456            }
457    
458            protected Document getDocument(Folder parentFolder, String name) {
459                    ItemIterable<CmisObject> cmisObjects = parentFolder.getChildren();
460    
461                    Iterator<CmisObject> itr = cmisObjects.iterator();
462    
463                    while (itr.hasNext()) {
464                            CmisObject cmisObject = itr.next();
465    
466                            if (name.equals(cmisObject.getName()) &&
467                                    cmisObject instanceof Document) {
468    
469                                    return (Document)cmisObject;
470                            }
471                    }
472    
473                    return null;
474            }
475    
476            protected Folder getFolder(Folder parentFolder, String name) {
477                    ItemIterable<CmisObject> cmisObjects = parentFolder.getChildren();
478    
479                    Iterator<CmisObject> itr = cmisObjects.iterator();
480    
481                    while (itr.hasNext()) {
482                            CmisObject cmisObject = itr.next();
483    
484                            if (name.equals(cmisObject.getName()) &&
485                                    cmisObject instanceof Folder) {
486    
487                                    return (Folder)cmisObject;
488                            }
489                    }
490    
491                    return null;
492            }
493    
494            protected List<Folder> getFolders(Folder folder) {
495                    List<Folder> folders = new ArrayList<Folder>();
496    
497                    ItemIterable<CmisObject> cmisObjects = folder.getChildren();
498    
499                    Iterator<CmisObject> itr = cmisObjects.iterator();
500    
501                    while (itr.hasNext()) {
502                            CmisObject cmisObject = itr.next();
503    
504                            if (cmisObject instanceof Folder) {
505                                    folders.add((Folder)cmisObject);
506                            }
507                    }
508    
509                    return folders;
510            }
511    
512            protected Folder getRepositoryFolder(long companyId, long repositoryId) {
513                    Folder companyFolder = getCompanyFolder(companyId);
514    
515                    String name = String.valueOf(repositoryId);
516    
517                    Folder repositoryFolder = getFolder(companyFolder, name);
518    
519                    if (repositoryFolder == null) {
520                            repositoryFolder = createFolder(companyFolder, name);
521                    }
522    
523                    return repositoryFolder;
524            }
525    
526            protected Document getVersionedDocument(
527                            long companyId, long repositoryId, String fileName,
528                            String versionLabel)
529                    throws NoSuchFileException {
530    
531                    Folder versioningFolder = getVersioningFolder(
532                            companyId, repositoryId, fileName, false);
533    
534                    if (versioningFolder == null) {
535                            throw new NoSuchFileException();
536                    }
537    
538                    Document document = getDocument(versioningFolder, versionLabel);
539    
540                    if (document == null) {
541                            throw new NoSuchFileException();
542                    }
543    
544                    return document;
545            }
546    
547            protected Folder getVersioningFolder(
548                    long companyId, long repositoryId, String fileName, boolean create) {
549    
550                    Folder repositoryFolder = getRepositoryFolder(companyId, repositoryId);
551    
552                    Folder versioningFolder = repositoryFolder;
553    
554                    String[] dirNames = StringUtil.split(fileName, CharPool.SLASH);
555    
556                    for (String dirName : dirNames) {
557                            Folder subFolder = getFolder(versioningFolder, dirName);
558    
559                            if (create && (subFolder == null)) {
560                                    subFolder = createFolder(versioningFolder, dirName);
561                            }
562    
563                            versioningFolder = subFolder;
564                    }
565    
566                    return versioningFolder;
567            }
568    
569            private static Session _session;
570            private static Folder _systemRootDir;
571    
572            static {
573                    Map<String, String> parameters = new HashMap<String, String>();
574    
575                    parameters.put(
576                            SessionParameter.ATOMPUB_URL,
577                            PropsValues.DL_STORE_CMIS_REPOSITORY_URL);
578                    parameters.put(
579                            SessionParameter.BINDING_TYPE, BindingType.ATOMPUB.value());
580                    parameters.put(
581                            SessionParameter.COMPRESSION, Boolean.TRUE.toString());
582    
583                    Locale locale = LocaleUtil.getDefault();
584    
585                    parameters.put(
586                            SessionParameter.LOCALE_ISO3166_COUNTRY,
587                            locale.getCountry());
588                    parameters.put(
589                            SessionParameter.LOCALE_ISO639_LANGUAGE, locale.getLanguage());
590                    parameters.put(
591                            SessionParameter.PASSWORD,
592                            PropsValues.DL_STORE_CMIS_CREDENTIALS_PASSWORD);
593                    parameters.put(
594                            SessionParameter.USER,
595                            PropsValues.DL_STORE_CMIS_CREDENTIALS_USERNAME);
596    
597                    SessionFactory sessionFactory = CMISRepositoryUtil.getSessionFactory();
598    
599                    Repository repository =
600                            sessionFactory.getRepositories(parameters).get(0);
601    
602                    _session = repository.createSession();
603    
604                    _session.setDefaultContext(CMISRepositoryUtil.getOperationContext());
605            }
606    
607    }