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.exception.SystemException;
019    import com.liferay.portal.kernel.messaging.DestinationNames;
020    import com.liferay.portal.kernel.messaging.Message;
021    import com.liferay.portal.kernel.messaging.MessageBusUtil;
022    import com.liferay.portal.kernel.repository.LocalRepository;
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.RepositoryEventListener;
026    import com.liferay.portal.kernel.repository.event.RepositoryEventType;
027    import com.liferay.portal.kernel.repository.event.TrashRepositoryEventType;
028    import com.liferay.portal.kernel.repository.event.WorkflowRepositoryEventType;
029    import com.liferay.portal.kernel.repository.model.FileEntry;
030    import com.liferay.portal.kernel.repository.model.FileVersion;
031    import com.liferay.portal.kernel.repository.model.Folder;
032    import com.liferay.portal.kernel.repository.model.RepositoryModelOperation;
033    import com.liferay.portal.kernel.repository.registry.RepositoryEventRegistry;
034    import com.liferay.portal.kernel.transaction.TransactionCommitCallbackRegistryUtil;
035    import com.liferay.portal.kernel.util.MethodKey;
036    import com.liferay.portal.model.Group;
037    import com.liferay.portal.repository.liferayrepository.model.LiferayFileEntry;
038    import com.liferay.portal.repository.liferayrepository.model.LiferayFolder;
039    import com.liferay.portal.service.GroupLocalServiceUtil;
040    import com.liferay.portlet.documentlibrary.model.DLSyncConstants;
041    import com.liferay.portlet.documentlibrary.model.DLSyncEvent;
042    import com.liferay.portlet.documentlibrary.service.DLSyncEventLocalServiceUtil;
043    
044    import java.lang.reflect.InvocationTargetException;
045    import java.lang.reflect.Method;
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 implements SyncCapability {
055    
056            @Override
057            public void addFileEntry(FileEntry fileEntry) {
058                    registerDLSyncEventCallback(DLSyncConstants.EVENT_ADD, fileEntry);
059            }
060    
061            @Override
062            public void addFolder(Folder folder) {
063                    registerDLSyncEventCallback(DLSyncConstants.EVENT_ADD, folder);
064            }
065    
066            @Override
067            public void deleteFileEntry(FileEntry fileEntry) {
068                    registerDLSyncEventCallback(DLSyncConstants.EVENT_DELETE, fileEntry);
069            }
070    
071            @Override
072            public void deleteFolder(Folder folder) {
073                    registerDLSyncEventCallback(DLSyncConstants.EVENT_DELETE, folder);
074            }
075    
076            @Override
077            public void destroyLocalRepository(LocalRepository localRepository)
078                    throws PortalException {
079    
080                    if (!localRepository.isCapabilityProvided(
081                                    BulkOperationCapability.class)) {
082    
083                            return;
084                    }
085    
086                    BulkOperationCapability bulkOperationCapability =
087                            localRepository.getCapability(BulkOperationCapability.class);
088    
089                    bulkOperationCapability.execute(new DeleteRepositoryModelOperation());
090            }
091    
092            @Override
093            public void moveFileEntry(FileEntry fileEntry) {
094                    registerDLSyncEventCallback(DLSyncConstants.EVENT_MOVE, fileEntry);
095            }
096    
097            @Override
098            public void moveFolder(Folder folder) {
099                    registerDLSyncEventCallback(DLSyncConstants.EVENT_MOVE, folder);
100            }
101    
102            public void registerRepositoryEventListeners(
103                    RepositoryEventRegistry repositoryEventRegistry) {
104    
105                    registerRepositoryEventListener(
106                            repositoryEventRegistry, RepositoryEventType.Add.class,
107                            Folder.class, "addFolder");
108                    registerRepositoryEventListener(
109                            repositoryEventRegistry, RepositoryEventType.Update.class,
110                            FileEntry.class, "updateFileEntry");
111                    registerRepositoryEventListener(
112                            repositoryEventRegistry, RepositoryEventType.Update.class,
113                            Folder.class, "updateFolder");
114                    registerRepositoryEventListener(
115                            repositoryEventRegistry, RepositoryEventType.Delete.class,
116                            FileEntry.class, "deleteFileEntry");
117                    registerRepositoryEventListener(
118                            repositoryEventRegistry, RepositoryEventType.Delete.class,
119                            Folder.class, "deleteFolder");
120                    registerRepositoryEventListener(
121                            repositoryEventRegistry, RepositoryEventType.Move.class,
122                            FileEntry.class, "moveFileEntry");
123                    registerRepositoryEventListener(
124                            repositoryEventRegistry, RepositoryEventType.Move.class,
125                            Folder.class, "moveFolder");
126                    registerRepositoryEventListener(
127                            repositoryEventRegistry,
128                            TrashRepositoryEventType.EntryTrashed.class, FileEntry.class,
129                            "trashFileEntry");
130                    registerRepositoryEventListener(
131                            repositoryEventRegistry,
132                            TrashRepositoryEventType.EntryRestored.class, FileEntry.class,
133                            "restoreFileEntry");
134                    registerRepositoryEventListener(
135                            repositoryEventRegistry,
136                            TrashRepositoryEventType.EntryRestored.class, Folder.class,
137                            "restoreFolder");
138                    registerRepositoryEventListener(
139                            repositoryEventRegistry,
140                            TrashRepositoryEventType.EntryTrashed.class, Folder.class,
141                            "trashFolder");
142                    registerRepositoryEventListener(
143                            repositoryEventRegistry, WorkflowRepositoryEventType.Add.class,
144                            FileEntry.class, "addFileEntry");
145                    registerRepositoryEventListener(
146                            repositoryEventRegistry, WorkflowRepositoryEventType.Update.class,
147                            FileEntry.class, "updateFileEntry");
148            }
149    
150            @Override
151            public void restoreFileEntry(FileEntry fileEntry) {
152                    registerDLSyncEventCallback(DLSyncConstants.EVENT_RESTORE, fileEntry);
153            }
154    
155            @Override
156            public void restoreFolder(Folder folder) {
157                    registerDLSyncEventCallback(DLSyncConstants.EVENT_RESTORE, folder);
158            }
159    
160            @Override
161            public void trashFileEntry(FileEntry fileEntry) {
162                    registerDLSyncEventCallback(DLSyncConstants.EVENT_TRASH, fileEntry);
163            }
164    
165            @Override
166            public void trashFolder(Folder folder) {
167                    registerDLSyncEventCallback(DLSyncConstants.EVENT_TRASH, folder);
168            }
169    
170            @Override
171            public void updateFileEntry(FileEntry fileEntry) {
172                    registerDLSyncEventCallback(DLSyncConstants.EVENT_UPDATE, fileEntry);
173            }
174    
175            @Override
176            public void updateFolder(Folder folder) {
177                    registerDLSyncEventCallback(DLSyncConstants.EVENT_UPDATE, folder);
178            }
179    
180            protected boolean isStagingGroup(long groupId) {
181                    try {
182                            Group group = GroupLocalServiceUtil.getGroup(groupId);
183    
184                            return group.isStagingGroup();
185                    }
186                    catch (Exception e) {
187                            return false;
188                    }
189            }
190    
191            protected void registerDLSyncEventCallback(
192                    String event, FileEntry fileEntry) {
193    
194                    if (isStagingGroup(fileEntry.getGroupId()) ||
195                            !(fileEntry instanceof LiferayFileEntry)) {
196    
197                            return;
198                    }
199    
200                    registerDLSyncEventCallback(
201                            event, DLSyncConstants.TYPE_FILE, fileEntry.getFileEntryId());
202            }
203    
204            protected void registerDLSyncEventCallback(String event, Folder folder) {
205                    if (isStagingGroup(folder.getGroupId()) ||
206                            !(folder instanceof LiferayFolder)) {
207    
208                            return;
209                    }
210    
211                    registerDLSyncEventCallback(
212                            event, DLSyncConstants.TYPE_FOLDER, folder.getFolderId());
213            }
214    
215            protected void registerDLSyncEventCallback(
216                    final String event, final String type, final long typePK) {
217    
218                    DLSyncEvent dlSyncEvent = DLSyncEventLocalServiceUtil.addDLSyncEvent(
219                            event, type, typePK);
220    
221                    final long modifiedTime = dlSyncEvent.getModifiedTime();
222    
223                    TransactionCommitCallbackRegistryUtil.registerCallback(
224                            new Callable<Void>() {
225    
226                                    @Override
227                                    public Void call() throws Exception {
228                                            Message message = new Message();
229    
230                                            Map<String, Object> values = new HashMap<String, Object>(4);
231    
232                                            values.put("event", event);
233                                            values.put("modifiedTime", modifiedTime);
234                                            values.put("type", type);
235                                            values.put("typePK", typePK);
236    
237                                            message.setValues(values);
238    
239                                            MessageBusUtil.sendMessage(
240                                                    DestinationNames.DOCUMENT_LIBRARY_SYNC_EVENT_PROCESSOR,
241                                                    message);
242    
243                                            return null;
244                                    }
245    
246                            }
247                    );
248            }
249    
250            protected <S extends RepositoryEventType, T>
251                    void registerRepositoryEventListener(
252                            RepositoryEventRegistry repositoryEventRegistry,
253                            Class<S> repositoryEventTypeClass, Class<T> modelClass,
254                            String methodName) {
255    
256                    RepositoryEventListener<S, T> repositoryEventListener =
257                            new MethodKeyRepositoryEventListener<S, T>(
258                                    new MethodKey(
259                                            LiferaySyncCapability.class, methodName, modelClass));
260    
261                    repositoryEventRegistry.registerRepositoryEventListener(
262                            repositoryEventTypeClass, modelClass, repositoryEventListener);
263            }
264    
265            private class DeleteRepositoryModelOperation
266                    implements RepositoryModelOperation {
267    
268                    @Override
269                    public void execute(FileEntry fileEntry) {
270                            deleteFileEntry(fileEntry);
271                    }
272    
273                    @Override
274                    public void execute(FileVersion fileVersion) {
275                    }
276    
277                    @Override
278                    public void execute(Folder folder) {
279                            deleteFolder(folder);
280                    }
281    
282            }
283    
284            private class MethodKeyRepositoryEventListener
285                            <S extends RepositoryEventType, T>
286                    implements RepositoryEventListener<S, T> {
287    
288                    public MethodKeyRepositoryEventListener(MethodKey methodKey) {
289                            _methodKey = methodKey;
290                    }
291    
292                    @Override
293                    public void execute(T target) {
294                            try {
295                                    Method method = _methodKey.getMethod();
296    
297                                    method.invoke(LiferaySyncCapability.this, target);
298                            }
299                            catch (IllegalAccessException iae) {
300                                    throw new SystemException(iae);
301                            }
302                            catch (InvocationTargetException ite) {
303                                    throw new SystemException(ite);
304                            }
305                            catch (NoSuchMethodException nsme) {
306                                    throw new SystemException(nsme);
307                            }
308                    }
309    
310                    private final MethodKey _methodKey;
311    
312            }
313    
314    }