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