001    /**
002     * Copyright (c) 2000-present 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.portal.repository.capabilities;
016    
017    import com.liferay.portal.kernel.exception.PortalException;
018    import com.liferay.portal.kernel.messaging.DestinationNames;
019    import com.liferay.portal.kernel.messaging.Message;
020    import com.liferay.portal.kernel.messaging.MessageBusUtil;
021    import com.liferay.portal.kernel.repository.LocalRepository;
022    import com.liferay.portal.kernel.repository.Repository;
023    import com.liferay.portal.kernel.repository.capabilities.BulkOperationCapability;
024    import com.liferay.portal.kernel.repository.capabilities.SyncCapability;
025    import com.liferay.portal.kernel.repository.event.RepositoryEventAware;
026    import com.liferay.portal.kernel.repository.event.RepositoryEventListener;
027    import com.liferay.portal.kernel.repository.event.RepositoryEventType;
028    import com.liferay.portal.kernel.repository.event.TrashRepositoryEventType;
029    import com.liferay.portal.kernel.repository.event.WorkflowRepositoryEventType;
030    import com.liferay.portal.kernel.repository.model.FileEntry;
031    import com.liferay.portal.kernel.repository.model.FileVersion;
032    import com.liferay.portal.kernel.repository.model.Folder;
033    import com.liferay.portal.kernel.repository.model.RepositoryModelOperation;
034    import com.liferay.portal.kernel.repository.registry.RepositoryEventRegistry;
035    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
036    import com.liferay.portal.model.Group;
037    import com.liferay.portal.repository.liferayrepository.LiferaySyncLocalRepositoryWrapper;
038    import com.liferay.portal.repository.liferayrepository.LiferaySyncRepositoryWrapper;
039    import com.liferay.portal.repository.liferayrepository.model.LiferayFileEntry;
040    import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
041    import com.liferay.portal.repository.util.RepositoryWrapperAware;
042    import com.liferay.portal.service.GroupLocalServiceUtil;
043    import com.liferay.portlet.documentlibrary.model.DLSyncConstants;
044    import com.liferay.portlet.documentlibrary.model.DLSyncEvent;
045    import com.liferay.portlet.documentlibrary.service.DLSyncEventLocalServiceUtil;
046    
047    import java.util.HashMap;
048    import java.util.Map;
049    import java.util.concurrent.Callable;
050    
051    /**
052     * @author Adolfo P??rez
053     */
054    public class LiferaySyncCapability
055            implements RepositoryEventAware, RepositoryWrapperAware, SyncCapability {
056    
057            public LiferaySyncCapability(
058                    BulkOperationCapability bulkOperationCapability) {
059    
060                    _bulkOperationCapability = bulkOperationCapability;
061            }
062    
063            @Override
064            public void destroyDocumentRepository() throws PortalException {
065                    _bulkOperationCapability.execute(new DeleteRepositoryModelOperation());
066            }
067    
068            @Override
069            public void registerRepositoryEventListeners(
070                    RepositoryEventRegistry repositoryEventRegistry) {
071    
072                    repositoryEventRegistry.registerRepositoryEventListener(
073                            RepositoryEventType.Add.class, Folder.class,
074                            ADD_FOLDER_EVENT_LISTENER);
075                    repositoryEventRegistry.registerRepositoryEventListener(
076                            RepositoryEventType.Delete.class, FileEntry.class,
077                            DELETE_FILE_ENTRY_EVENT_LISTENER);
078                    repositoryEventRegistry.registerRepositoryEventListener(
079                            RepositoryEventType.Delete.class, Folder.class,
080                            DELETE_FOLDER_EVENT_LISTENER);
081                    repositoryEventRegistry.registerRepositoryEventListener(
082                            RepositoryEventType.Move.class, FileEntry.class,
083                            MOVE_FILE_ENTRY_EVENT_LISTENER);
084                    repositoryEventRegistry.registerRepositoryEventListener(
085                            RepositoryEventType.Move.class, Folder.class,
086                            MOVE_FOLDER_EVENT_LISTENER);
087                    repositoryEventRegistry.registerRepositoryEventListener(
088                            TrashRepositoryEventType.EntryRestored.class, FileEntry.class,
089                            RESTORE_FILE_ENTRY_EVENT_LISTENER);
090                    repositoryEventRegistry.registerRepositoryEventListener(
091                            TrashRepositoryEventType.EntryRestored.class, Folder.class,
092                            RESTORE_FOLDER_EVENT_LISTENER);
093                    repositoryEventRegistry.registerRepositoryEventListener(
094                            TrashRepositoryEventType.EntryTrashed.class, FileEntry.class,
095                            TRASH_FILE_ENTRY_EVENT_LISTENER);
096                    repositoryEventRegistry.registerRepositoryEventListener(
097                            TrashRepositoryEventType.EntryTrashed.class, Folder.class,
098                            TRASH_FOLDER_EVENT_LISTENER);
099                    repositoryEventRegistry.registerRepositoryEventListener(
100                            RepositoryEventType.Update.class, FileEntry.class,
101                            UPDATE_FILE_ENTRY_EVENT_LISTENER);
102                    repositoryEventRegistry.registerRepositoryEventListener(
103                            RepositoryEventType.Update.class, Folder.class,
104                            UPDATE_FOLDER_EVENT_LISTENER);
105                    repositoryEventRegistry.registerRepositoryEventListener(
106                            WorkflowRepositoryEventType.Add.class, FileEntry.class,
107                            WORKFLOW_ADD_FILE_ENTRY_EVENT_LISTENER);
108                    repositoryEventRegistry.registerRepositoryEventListener(
109                            WorkflowRepositoryEventType.Update.class, FileEntry.class,
110                            WORKFLOW_UPDATE_FILE_ENTRY_EVENT_LISTENER);
111            }
112    
113            @Override
114            public LocalRepository wrapLocalRepository(
115                    LocalRepository localRepository) {
116    
117                    return new LiferaySyncLocalRepositoryWrapper(localRepository, this);
118            }
119    
120            @Override
121            public Repository wrapRepository(Repository repository) {
122                    return new LiferaySyncRepositoryWrapper(repository, this);
123            }
124    
125            protected static boolean isStagingGroup(long groupId) {
126                    try {
127                            Group group = GroupLocalServiceUtil.getGroup(groupId);
128    
129                            return group.isStagingGroup();
130                    }
131                    catch (Exception e) {
132                            return false;
133                    }
134            }
135    
136            protected static void registerDLSyncEventCallback(
137                    String event, FileEntry fileEntry) {
138    
139                    if (isStagingGroup(fileEntry.getGroupId()) ||
140                            !(fileEntry instanceof LiferayFileEntry)) {
141    
142                            return;
143                    }
144    
145                    registerDLSyncEventCallback(
146                            event, DLSyncConstants.TYPE_FILE, fileEntry.getFileEntryId());
147            }
148    
149            protected static void registerDLSyncEventCallback(
150                    String event, Folder folder) {
151    
152                    if (isStagingGroup(folder.getGroupId()) ||
153                            !(folder instanceof LiferayFolder)) {
154    
155                            return;
156                    }
157    
158                    registerDLSyncEventCallback(
159                            event, DLSyncConstants.TYPE_FOLDER, folder.getFolderId());
160            }
161    
162            protected static void registerDLSyncEventCallback(
163                    final String event, final String type, final long typePK) {
164    
165                    DLSyncEvent dlSyncEvent = DLSyncEventLocalServiceUtil.addDLSyncEvent(
166                            event, type, typePK);
167    
168                    final long modifiedTime = dlSyncEvent.getModifiedTime();
169    
170                    TransactionCommitCallbackRegistryUtil.registerCallback(
171                            new Callable<Void>() {
172    
173                                    @Override
174                                    public Void call() throws Exception {
175                                            Message message = new Message();
176    
177                                            Map<String, Object> values = new HashMap<String, Object>(4);
178    
179                                            values.put("event", event);
180                                            values.put("modifiedTime", modifiedTime);
181                                            values.put("type", type);
182                                            values.put("typePK", typePK);
183    
184                                            message.setValues(values);
185    
186                                            MessageBusUtil.sendMessage(
187                                                    DestinationNames.DOCUMENT_LIBRARY_SYNC_EVENT_PROCESSOR,
188                                                    message);
189    
190                                            return null;
191                                    }
192    
193                            }
194                    );
195            }
196    
197            private static final RepositoryEventListener
198                    <RepositoryEventType.Add, Folder> ADD_FOLDER_EVENT_LISTENER =
199                            new SyncFolderRepositoryEventListener<>(DLSyncConstants.EVENT_ADD);
200    
201            private static final RepositoryEventListener
202                    <RepositoryEventType.Delete, FileEntry>
203                            DELETE_FILE_ENTRY_EVENT_LISTENER =
204                                    new SyncFileEntryRepositoryEventListener<>(
205                                            DLSyncConstants.EVENT_DELETE);
206    
207            private static final RepositoryEventListener
208                    <RepositoryEventType.Delete, Folder> DELETE_FOLDER_EVENT_LISTENER =
209                            new SyncFolderRepositoryEventListener<>(
210                                    DLSyncConstants.EVENT_DELETE);
211    
212            private static final RepositoryEventListener
213                    <RepositoryEventType.Move, FileEntry> MOVE_FILE_ENTRY_EVENT_LISTENER =
214                            new SyncFileEntryRepositoryEventListener<>(
215                                    DLSyncConstants.EVENT_MOVE);
216    
217            private static final RepositoryEventListener
218                    <RepositoryEventType.Move, Folder> MOVE_FOLDER_EVENT_LISTENER =
219                            new SyncFolderRepositoryEventListener<>(DLSyncConstants.EVENT_MOVE);
220    
221            private static final RepositoryEventListener
222                    <TrashRepositoryEventType.EntryRestored, FileEntry>
223                            RESTORE_FILE_ENTRY_EVENT_LISTENER =
224                                    new SyncFileEntryRepositoryEventListener<>(
225                                            DLSyncConstants.EVENT_RESTORE);
226    
227            private static final RepositoryEventListener
228                    <TrashRepositoryEventType.EntryRestored, Folder>
229                            RESTORE_FOLDER_EVENT_LISTENER =
230                                    new SyncFolderRepositoryEventListener<>(
231                                            DLSyncConstants.EVENT_RESTORE);
232    
233            private static final RepositoryEventListener
234                    <TrashRepositoryEventType.EntryTrashed, FileEntry>
235                            TRASH_FILE_ENTRY_EVENT_LISTENER =
236                                    new SyncFileEntryRepositoryEventListener<>(
237                                            DLSyncConstants.EVENT_TRASH);
238    
239            private static final RepositoryEventListener
240                    <TrashRepositoryEventType.EntryTrashed, Folder>
241                            TRASH_FOLDER_EVENT_LISTENER =
242                                    new SyncFolderRepositoryEventListener<>(
243                                            DLSyncConstants.EVENT_TRASH);
244    
245            private static final RepositoryEventListener
246                    <RepositoryEventType.Update, FileEntry>
247                            UPDATE_FILE_ENTRY_EVENT_LISTENER =
248                                    new SyncFileEntryRepositoryEventListener<>(
249                                            DLSyncConstants.EVENT_UPDATE);
250    
251            private static final RepositoryEventListener
252                    <RepositoryEventType.Update, Folder> UPDATE_FOLDER_EVENT_LISTENER =
253                            new SyncFolderRepositoryEventListener<>(
254                                    DLSyncConstants.EVENT_UPDATE);
255    
256            private static final RepositoryEventListener
257                    <WorkflowRepositoryEventType.Add, FileEntry>
258                            WORKFLOW_ADD_FILE_ENTRY_EVENT_LISTENER =
259                                    new SyncFileEntryRepositoryEventListener<>(
260                                            DLSyncConstants.EVENT_ADD);
261    
262            private static final RepositoryEventListener
263                    <WorkflowRepositoryEventType.Update, FileEntry>
264                            WORKFLOW_UPDATE_FILE_ENTRY_EVENT_LISTENER =
265                                    new SyncFileEntryRepositoryEventListener<>(
266                                            DLSyncConstants.EVENT_UPDATE);
267    
268            private final BulkOperationCapability _bulkOperationCapability;
269    
270            private static class SyncFileEntryRepositoryEventListener
271                            <S extends RepositoryEventType>
272                    implements RepositoryEventListener<S, FileEntry> {
273    
274                    public SyncFileEntryRepositoryEventListener(String syncEvent) {
275                            _syncEvent = syncEvent;
276                    }
277    
278                    @Override
279                    public void execute(FileEntry fileEntry) {
280                            registerDLSyncEventCallback(_syncEvent, fileEntry);
281                    }
282    
283                    private final String _syncEvent;
284    
285            }
286    
287            private static class SyncFolderRepositoryEventListener
288                            <S extends RepositoryEventType>
289                    implements RepositoryEventListener<S, Folder> {
290    
291                    public SyncFolderRepositoryEventListener(String syncEvent) {
292                            _syncEvent = syncEvent;
293                    }
294    
295                    @Override
296                    public void execute(Folder folder) {
297                            registerDLSyncEventCallback(_syncEvent, folder);
298                    }
299    
300                    private final String _syncEvent;
301    
302            }
303    
304            private class DeleteRepositoryModelOperation
305                    implements RepositoryModelOperation {
306    
307                    @Override
308                    public void execute(FileEntry fileEntry) {
309                            registerDLSyncEventCallback(
310                                    DLSyncConstants.EVENT_DELETE, fileEntry);
311                    }
312    
313                    @Override
314                    public void execute(FileVersion fileVersion) {
315                    }
316    
317                    @Override
318                    public void execute(Folder folder) {
319                            registerDLSyncEventCallback(DLSyncConstants.EVENT_DELETE, folder);
320                    }
321    
322            }
323    
324    }