001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.documentlibrary.util;
016    
017    import com.liferay.documentlibrary.DuplicateFileException;
018    import com.liferay.documentlibrary.NoSuchFileException;
019    import com.liferay.documentlibrary.model.FileModel;
020    import com.liferay.portal.cmis.CMISException;
021    import com.liferay.portal.cmis.CMISUtil;
022    import com.liferay.portal.cmis.model.CMISConstants;
023    import com.liferay.portal.cmis.model.CMISObject;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.search.Document;
028    import com.liferay.portal.kernel.search.Indexer;
029    import com.liferay.portal.kernel.search.IndexerRegistryUtil;
030    import com.liferay.portal.kernel.search.SearchEngineUtil;
031    import com.liferay.portal.kernel.search.SearchException;
032    import com.liferay.portal.kernel.util.GetterUtil;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.service.ServiceContext;
035    import com.liferay.portlet.documentlibrary.util.DLUtil;
036    
037    import java.io.InputStream;
038    
039    import java.util.ArrayList;
040    import java.util.Collection;
041    import java.util.Date;
042    import java.util.List;
043    
044    import org.apache.abdera.model.Entry;
045    import org.apache.abdera.model.Link;
046    
047    /**
048     * @author Alexander Chow
049     */
050    public class CMISHook extends BaseHook {
051    
052            public CMISHook() {
053                    try {
054                            String version = CMISUtil.verifyRepository();
055    
056                            if (_log.isInfoEnabled()) {
057                                    _log.info("CMIS Service is running version " + version);
058                            }
059                    }
060                    catch (Exception e) {
061                            _log.error(e, e);
062                    }
063            }
064    
065            public void addDirectory(long companyId, long repositoryId, String dirName)
066                    throws PortalException {
067    
068                    Entry repositoryFolderEntry = getRepositoryFolderEntry(
069                            companyId, repositoryId);
070    
071                    CMISUtil.createFolder(repositoryFolderEntry, dirName);
072            }
073    
074            public void addFile(
075                            long companyId, String portletId, long groupId, long repositoryId,
076                            String fileName, long fileEntryId, String properties,
077                            Date modifiedDate, ServiceContext serviceContext, InputStream is)
078                    throws PortalException {
079    
080                    updateFile(
081                            companyId, portletId, groupId, repositoryId, fileName,
082                            DEFAULT_VERSION, null, fileEntryId, properties, modifiedDate,
083                            serviceContext, is);
084            }
085    
086            public void checkRoot(long companyId) {
087            }
088    
089            public void deleteDirectory(
090                            long companyId, String portletId, long repositoryId, String dirName)
091                    throws PortalException {
092    
093                    Entry repositoryFolderEntry = getRepositoryFolderEntry(
094                            companyId, repositoryId);
095    
096                    Entry directory = CMISUtil.getFolder(repositoryFolderEntry, dirName);
097    
098                    if (directory != null) {
099                            CMISUtil.delete(directory);
100                    }
101            }
102    
103            public void deleteFile(
104                            long companyId, String portletId, long repositoryId,
105                            String fileName)
106                    throws PortalException {
107    
108                    Entry versioningFolderEntry = getVersioningFolderEntry(
109                            companyId, repositoryId, fileName, false);
110    
111                    if (versioningFolderEntry == null) {
112                            throw new NoSuchFileException();
113                    }
114    
115                    CMISUtil.delete(versioningFolderEntry);
116    
117                    Indexer indexer = IndexerRegistryUtil.getIndexer(
118                            FileModel.class);
119    
120                    FileModel fileModel = new FileModel();
121    
122                    fileModel.setCompanyId(companyId);
123                    fileModel.setFileName(fileName);
124                    fileModel.setPortletId(portletId);
125                    fileModel.setRepositoryId(repositoryId);
126    
127                    indexer.delete(fileModel);
128            }
129    
130            public void deleteFile(
131                            long companyId, String portletId, long repositoryId,
132                            String fileName, String versionNumber)
133                    throws PortalException {
134    
135                    Entry fileEntry = getVersionedFileEntry(
136                            companyId, repositoryId, fileName, versionNumber);
137    
138                    CMISUtil.delete(fileEntry);
139    
140                    Indexer indexer = IndexerRegistryUtil.getIndexer(
141                            FileModel.class);
142    
143                    FileModel fileModel = new FileModel();
144    
145                    fileModel.setCompanyId(companyId);
146                    fileModel.setFileName(fileName);
147                    fileModel.setPortletId(portletId);
148                    fileModel.setRepositoryId(repositoryId);
149    
150                    indexer.delete(fileModel);
151            }
152    
153            public InputStream getFileAsStream(
154                            long companyId, long repositoryId, String fileName,
155                            String versionNumber)
156                    throws PortalException {
157    
158                    if (Validator.isNull(versionNumber)) {
159                            versionNumber = getHeadVersionNumber(
160                                    companyId, repositoryId, fileName);
161                    }
162    
163                    Entry fileEntry = getVersionedFileEntry(
164                            companyId, repositoryId, fileName, versionNumber);
165    
166                    return CMISUtil.getInputStream(fileEntry);
167            }
168    
169            public String[] getFileNames(
170                            long companyId, long repositoryId, String dirName)
171                    throws PortalException {
172    
173                    Entry repositoryFolderEntry = getRepositoryFolderEntry(
174                            companyId, repositoryId);
175    
176                    List<String> fileNames = CMISUtil.getFolders(repositoryFolderEntry);
177    
178                    return fileNames.toArray(new String[fileNames.size()]);
179            }
180    
181            public long getFileSize(
182                            long companyId, long repositoryId, String fileName)
183                    throws PortalException {
184    
185                    String versionNumber = getHeadVersionNumber(
186                            companyId, repositoryId, fileName);
187    
188                    Entry fileEntry = getVersionedFileEntry(
189                            companyId, repositoryId, fileName, versionNumber);
190    
191                    CMISObject cmisObject = fileEntry.getFirstChild(_cmisConstants.OBJECT);
192    
193                    return cmisObject.getContentStreamLength();
194            }
195    
196            public String getHeadVersionNumber(
197                            long companyId, long repositoryId, String dirName)
198                    throws CMISException, NoSuchFileException {
199    
200                    Entry versioningFolderEntry = getVersioningFolderEntry(
201                            companyId, repositoryId, dirName, false);
202    
203                    if (versioningFolderEntry == null) {
204                            throw new NoSuchFileException();
205                    }
206    
207                    List<String> versionNumbers = CMISUtil.getFolders(
208                            versioningFolderEntry);
209    
210                    String headVersionNumber = DEFAULT_VERSION;
211    
212                    for (String versionNumber : versionNumbers) {
213                            if (DLUtil.compareVersions(versionNumber, headVersionNumber) > 0) {
214                                    headVersionNumber = versionNumber;
215                            }
216                    }
217    
218                    return headVersionNumber;
219            }
220    
221            public boolean hasFile(
222                            long companyId, long repositoryId, String fileName,
223                            String versionNumber)
224                    throws PortalException {
225    
226                    Entry versioningFolderEntry = getVersioningFolderEntry(
227                            companyId, repositoryId, fileName, true);
228    
229                    Link link = versioningFolderEntry.getLink(
230                            _cmisConstants.LINK_DESCENDANTS);
231    
232                    String url = link.getHref().toString();
233    
234                    Entry fileEntry = CMISUtil.getEntry(
235                            url, versionNumber, _cmisConstants.BASE_TYPE_DOCUMENT);
236    
237                    if (fileEntry == null) {
238                            return false;
239                    }
240                    else {
241                            return true;
242                    }
243            }
244    
245            public void move(String srcDir, String destDir) {
246            }
247    
248            public void reindex(String[] ids) throws SearchException {
249                    long companyId = GetterUtil.getLong(ids[0]);
250                    String portletId = ids[1];
251                    long groupId = GetterUtil.getLong(ids[2]);
252                    long repositoryId = GetterUtil.getLong(ids[3]);
253    
254                    Collection<Document> documents = new ArrayList<Document>();
255    
256                    try {
257                            Entry repositoryFolderEntry = getRepositoryFolderEntry(
258                                    companyId, repositoryId);
259    
260                            List<String> fileNames = CMISUtil.getFolders(repositoryFolderEntry);
261    
262                            for (String fileName : fileNames) {
263                                    Indexer indexer = IndexerRegistryUtil.getIndexer(
264                                            FileModel.class);
265    
266                                    FileModel fileModel = new FileModel();
267    
268                                    fileModel.setCompanyId(companyId);
269                                    fileModel.setFileName(fileName);
270                                    fileModel.setGroupId(groupId);
271                                    fileModel.setPortletId(portletId);
272                                    fileModel.setRepositoryId(repositoryId);
273    
274                                    Document document = indexer.getDocument(fileModel);
275    
276                                    if (document == null) {
277                                            continue;
278                                    }
279    
280                                    documents.add(document);
281                            }
282                    }
283                    catch (CMISException cmise) {
284                            if (_log.isErrorEnabled()) {
285                                    _log.error(cmise, cmise);
286                            }
287                    }
288    
289                    SearchEngineUtil.updateDocuments(companyId, documents);
290            }
291    
292            public void updateFile(
293                            long companyId, String portletId, long groupId, long repositoryId,
294                            long newRepositoryId, String fileName, long fileEntryId)
295                    throws PortalException {
296    
297                    Entry oldVersioningFolderEntry = getVersioningFolderEntry(
298                            companyId, repositoryId, fileName, true);
299                    Entry newVersioningFolderEntry = getVersioningFolderEntry(
300                            companyId, newRepositoryId, fileName, true);
301    
302                    List<String> fileNames = CMISUtil.getFolders(oldVersioningFolderEntry);
303    
304                    for (String curFileName : fileNames) {
305                            Entry entry = CMISUtil.getDocument(
306                                    oldVersioningFolderEntry, curFileName);
307    
308                            InputStream is = CMISUtil.getInputStream(entry);
309    
310                            CMISUtil.createDocument(newVersioningFolderEntry, curFileName, is);
311                    }
312    
313                    CMISUtil.delete(oldVersioningFolderEntry);
314    
315                    Indexer indexer = IndexerRegistryUtil.getIndexer(FileModel.class);
316    
317                    FileModel fileModel = new FileModel();
318    
319                    fileModel.setCompanyId(companyId);
320                    fileModel.setFileName(fileName);
321                    fileModel.setPortletId(portletId);
322                    fileModel.setRepositoryId(repositoryId);
323    
324                    indexer.delete(fileModel);
325    
326                    fileModel.setRepositoryId(newRepositoryId);
327                    fileModel.setGroupId(groupId);
328    
329                    indexer.reindex(fileModel);
330            }
331    
332            public void updateFile(
333                            long companyId, String portletId, long groupId, long repositoryId,
334                            String fileName, String newFileName, boolean reindex)
335                    throws PortalException {
336    
337                    Entry oldVersioningFolderEntry = getVersioningFolderEntry(
338                            companyId, repositoryId, fileName, true);
339                    Entry newVersioningFolderEntry = getVersioningFolderEntry(
340                            companyId, repositoryId, newFileName, true);
341    
342                    List<String> fileNames = CMISUtil.getFolders(oldVersioningFolderEntry);
343    
344                    for (String curFileName : fileNames) {
345                            Entry entry = CMISUtil.getDocument(
346                                    oldVersioningFolderEntry, curFileName);
347    
348                            InputStream is = CMISUtil.getInputStream(entry);
349    
350                            CMISUtil.createDocument(newVersioningFolderEntry, curFileName, is);
351                    }
352    
353                    CMISUtil.delete(oldVersioningFolderEntry);
354    
355                    if (reindex) {
356                            Indexer indexer = IndexerRegistryUtil.getIndexer(FileModel.class);
357    
358                            FileModel fileModel = new FileModel();
359    
360                            fileModel.setCompanyId(companyId);
361                            fileModel.setFileName(fileName);
362                            fileModel.setPortletId(portletId);
363                            fileModel.setRepositoryId(repositoryId);
364    
365                            indexer.delete(fileModel);
366    
367                            fileModel.setFileName(newFileName);
368                            fileModel.setGroupId(groupId);
369    
370                            indexer.reindex(fileModel);
371                    }
372            }
373    
374            public void updateFile(
375                            long companyId, String portletId, long groupId, long repositoryId,
376                            String fileName, String versionNumber, String sourceFileName,
377                            long fileEntryId, String properties, Date modifiedDate,
378                            ServiceContext serviceContext, InputStream is)
379                    throws PortalException {
380    
381                    Entry versioningFolderEntry = getVersioningFolderEntry(
382                            companyId, repositoryId, fileName, true);
383    
384                    Link link = versioningFolderEntry.getLink(
385                            _cmisConstants.LINK_DESCENDANTS);
386    
387                    String url = link.getHref().toString();
388    
389                    String title = String.valueOf(versionNumber);
390    
391                    Entry fileEntry = CMISUtil.getEntry(
392                            url, title, _cmisConstants.BASE_TYPE_DOCUMENT);
393    
394                    if (fileEntry != null) {
395                            throw new DuplicateFileException();
396                    }
397    
398                    fileEntry = CMISUtil.createDocument(url, title, is);
399    
400                    Indexer indexer = IndexerRegistryUtil.getIndexer(FileModel.class);
401    
402                    FileModel fileModel = new FileModel();
403    
404                    fileModel.setAssetCategoryIds(serviceContext.getAssetCategoryIds());
405                    fileModel.setAssetTagNames(serviceContext.getAssetTagNames());
406                    fileModel.setCompanyId(companyId);
407                    fileModel.setFileEntryId(fileEntryId);
408                    fileModel.setFileName(fileName);
409                    fileModel.setGroupId(groupId);
410                    fileModel.setModifiedDate(modifiedDate);
411                    fileModel.setPortletId(portletId);
412                    fileModel.setProperties(properties);
413                    fileModel.setRepositoryId(repositoryId);
414    
415                    indexer.reindex(fileModel);
416            }
417    
418            protected Entry getCompanyFolderEntry(long companyId) throws CMISException {
419                    String title = String.valueOf(companyId);
420    
421                    Entry companyFolderEntry = CMISUtil.getFolder(title);
422    
423                    if (companyFolderEntry == null) {
424                            companyFolderEntry = CMISUtil.createFolder(title);
425                    }
426    
427                    return companyFolderEntry;
428            }
429    
430            protected Entry getRepositoryFolderEntry(long companyId, long repositoryId)
431                    throws CMISException {
432    
433                    Entry companyFolderEntry = getCompanyFolderEntry(companyId);
434    
435                    Link link = companyFolderEntry.getLink(_cmisConstants.LINK_DESCENDANTS);
436    
437                    String url = link.getHref().toString();
438    
439                    String title = String.valueOf(repositoryId);
440    
441                    Entry repositoryFolderEntry = CMISUtil.getFolder(url, title);
442    
443                    if (repositoryFolderEntry == null) {
444                            repositoryFolderEntry = CMISUtil.createFolder(url, title);
445                    }
446    
447                    return repositoryFolderEntry;
448            }
449    
450            protected Entry getVersionedFileEntry(
451                            long companyId, long repositoryId, String fileName,
452                            String versionNumber)
453                    throws CMISException, NoSuchFileException {
454    
455                    Entry versioningFolderEntry = getVersioningFolderEntry(
456                            companyId, repositoryId, fileName, false);
457    
458                    if (versioningFolderEntry == null) {
459                            throw new NoSuchFileException();
460                    }
461    
462                    Link link = versioningFolderEntry.getLink(
463                            _cmisConstants.LINK_DESCENDANTS);
464    
465                    String url = link.getHref().toString();
466    
467                    Entry fileEntry = CMISUtil.getEntry(
468                            url, String.valueOf(versionNumber),
469                            _cmisConstants.BASE_TYPE_DOCUMENT);
470    
471                    if (fileEntry == null) {
472                            throw new NoSuchFileException();
473                    }
474    
475                    return fileEntry;
476            }
477    
478            protected Entry getVersioningFolderEntry(
479                            long companyId, long repositoryId, String fileName, boolean create)
480                    throws CMISException {
481    
482                    Entry repositoryFolderEntry = getRepositoryFolderEntry(
483                            companyId, repositoryId);
484    
485                    Link link = repositoryFolderEntry.getLink(
486                            _cmisConstants.LINK_DESCENDANTS);
487    
488                    String url = link.getHref().toString();
489    
490                    Entry versioningFolderEntry = CMISUtil.getEntry(
491                            url, fileName, _cmisConstants.BASE_TYPE_FOLDER);
492    
493                    if (create && (versioningFolderEntry == null)) {
494                            versioningFolderEntry = CMISUtil.createFolder(url, fileName);
495                    }
496    
497                    return versioningFolderEntry;
498            }
499    
500            private static Log _log = LogFactoryUtil.getLog(CMISHook.class);
501    
502            private static CMISConstants _cmisConstants = CMISConstants.getInstance();
503    
504    }