001
014
015 package com.liferay.portal.convert.documentlibrary;
016
017 import com.liferay.portal.convert.BaseConvertProcess;
018 import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
019 import com.liferay.portal.kernel.dao.orm.DynamicQuery;
020 import com.liferay.portal.kernel.dao.orm.Property;
021 import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
022 import com.liferay.portal.kernel.exception.PortalException;
023 import com.liferay.portal.kernel.exception.SystemException;
024 import com.liferay.portal.kernel.log.Log;
025 import com.liferay.portal.kernel.log.LogFactoryUtil;
026 import com.liferay.portal.kernel.repository.model.FileEntry;
027 import com.liferay.portal.kernel.repository.model.FileVersion;
028 import com.liferay.portal.kernel.util.GetterUtil;
029 import com.liferay.portal.kernel.util.ListUtil;
030 import com.liferay.portal.kernel.util.PropsKeys;
031 import com.liferay.portal.kernel.util.StringBundler;
032 import com.liferay.portal.kernel.util.StringPool;
033 import com.liferay.portal.kernel.workflow.WorkflowConstants;
034 import com.liferay.portal.model.Image;
035 import com.liferay.portal.repository.liferayrepository.model.LiferayFileEntry;
036 import com.liferay.portal.service.ImageLocalServiceUtil;
037 import com.liferay.portal.util.MaintenanceUtil;
038 import com.liferay.portal.util.PropsValues;
039 import com.liferay.portlet.documentlibrary.model.DLFileEntry;
040 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
041 import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
042 import com.liferay.portlet.documentlibrary.store.Store;
043 import com.liferay.portlet.documentlibrary.store.StoreFactory;
044 import com.liferay.portlet.documentlibrary.util.DLPreviewableProcessor;
045 import com.liferay.portlet.documentlibrary.util.comparator.FileVersionVersionComparator;
046 import com.liferay.portlet.messageboards.model.MBMessage;
047 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
048 import com.liferay.registry.Registry;
049 import com.liferay.registry.RegistryUtil;
050
051 import java.io.InputStream;
052
053 import java.util.Collection;
054 import java.util.List;
055
056
061 public class DocumentLibraryConvertProcess
062 extends BaseConvertProcess implements DLStoreConverter {
063
064 @Override
065 public String getConfigurationErrorMessage() {
066 return "there-are-no-stores-configured";
067 }
068
069 @Override
070 public String getDescription() {
071 return "migrate-documents-from-one-repository-to-another";
072 }
073
074 @Override
075 public String getParameterDescription() {
076 return "please-select-a-new-repository-hook";
077 }
078
079 @Override
080 public String[] getParameterNames() {
081 StoreFactory storeFactory = StoreFactory.getInstance();
082
083 Store store = storeFactory.getStore();
084
085 if (store == null) {
086 return null;
087 }
088
089 String[] storeTypes = storeFactory.getStoreTypes();
090
091 StringBundler sb = new StringBundler(storeTypes.length * 2 + 2);
092
093 sb.append(PropsKeys.DL_STORE_IMPL);
094 sb.append(StringPool.EQUAL);
095
096 for (String storeType : storeTypes) {
097 Class<?> clazz = store.getClass();
098
099 if (!storeType.equals(clazz.getName())) {
100 sb.append(storeType);
101 sb.append(StringPool.SEMICOLON);
102 }
103 }
104
105 return new String[] {
106 sb.toString(), "delete-files-from-previous-repository=checkbox"
107 };
108 }
109
110 @Override
111 public boolean isEnabled() {
112 return true;
113 }
114
115 @Override
116 public void migrateDLFileEntry(
117 long companyId, long repositoryId, FileEntry fileEntry) {
118
119 Object model = fileEntry.getModel();
120
121 if (!(model instanceof DLFileEntry)) {
122 throw new IllegalArgumentException(
123 "Unsupported file entry model " + model.getClass());
124 }
125
126 String fileName = ((DLFileEntry)model).getName();
127
128 List<FileVersion> fileVersions = getFileVersions(fileEntry);
129
130 if (fileVersions.isEmpty()) {
131 String versionNumber = Store.VERSION_DEFAULT;
132
133 migrateFile(companyId, repositoryId, fileName, versionNumber);
134
135 return;
136 }
137
138 for (FileVersion fileVersion : fileVersions) {
139 String versionNumber = fileVersion.getVersion();
140
141 migrateFile(companyId, repositoryId, fileName, versionNumber);
142 }
143 }
144
145 @Override
146 public void validate() {
147 String sourceStoreClassName = getSourceStoreClassName();
148
149 if (!sourceStoreClassName.endsWith(_FILE_SYSTEM_STORE_SUFFIX)) {
150 return;
151 }
152
153 String targetStoreClassName = getTargetStoreClassName();
154
155 if (!targetStoreClassName.endsWith(_FILE_SYSTEM_STORE_SUFFIX)) {
156 return;
157 }
158 }
159
160 @Override
161 protected void doConvert() throws Exception {
162 StoreFactory storeFactory = StoreFactory.getInstance();
163
164 _sourceStore = storeFactory.getStore();
165
166 String targetStoreClassName = getTargetStoreClassName();
167
168 _targetStore = storeFactory.getStore(targetStoreClassName);
169
170 migratePortlets();
171
172 storeFactory.setStore(targetStoreClassName);
173
174 MaintenanceUtil.appendStatus(
175 "Please set " + PropsKeys.DL_STORE_IMPL +
176 " in your portal-ext.properties to use " +
177 targetStoreClassName);
178
179 PropsValues.DL_STORE_IMPL = targetStoreClassName;
180 }
181
182 protected List<FileVersion> getFileVersions(FileEntry fileEntry) {
183 List<FileVersion> fileVersions = fileEntry.getFileVersions(
184 WorkflowConstants.STATUS_ANY);
185
186 return ListUtil.sort(
187 fileVersions, new FileVersionVersionComparator(true));
188 }
189
190 protected String getSourceStoreClassName() {
191 StoreFactory storeFactory = StoreFactory.getInstance();
192
193 Store sourceStore = storeFactory.getStore();
194
195 Class<?> clazz = sourceStore.getClass();
196
197 return clazz.getName();
198 }
199
200 protected String getTargetStoreClassName() {
201 String[] values = getParameterValues();
202
203 return values[0];
204 }
205
206 protected boolean isDeleteFilesFromSourceStore() {
207 String[] values = getParameterValues();
208
209 return GetterUtil.getBoolean(values[1]);
210 }
211
212 protected void migrateDL() throws PortalException {
213 int count = DLFileEntryLocalServiceUtil.getFileEntriesCount();
214
215 MaintenanceUtil.appendStatus(
216 "Migrating " + count + " documents and media files");
217
218 ActionableDynamicQuery actionableDynamicQuery =
219 DLFileEntryLocalServiceUtil.getActionableDynamicQuery();
220
221 actionableDynamicQuery.setAddCriteriaMethod(
222 new ActionableDynamicQuery.AddCriteriaMethod() {
223
224 @Override
225 public void addCriteria(DynamicQuery dynamicQuery) {
226 Property classNameIdProperty = PropertyFactoryUtil.forName(
227 "classNameId");
228
229 dynamicQuery.add(classNameIdProperty.eq(0L));
230 }
231
232 });
233 actionableDynamicQuery.setPerformActionMethod(
234 new ActionableDynamicQuery.PerformActionMethod<DLFileEntry>() {
235
236 @Override
237 public void performAction(DLFileEntry dlFileEntry) {
238 migrateDLFileEntry(
239 dlFileEntry.getCompanyId(),
240 dlFileEntry.getDataRepositoryId(),
241 new LiferayFileEntry(dlFileEntry));
242 }
243
244 });
245
246 actionableDynamicQuery.performActions();
247
248 if (isDeleteFilesFromSourceStore()) {
249 DLPreviewableProcessor.deleteFiles();
250 }
251 }
252
253 protected void migrateFile(
254 long companyId, long repositoryId, String fileName,
255 String versionNumber) {
256
257 try {
258 InputStream is = _sourceStore.getFileAsStream(
259 companyId, repositoryId, fileName, versionNumber);
260
261 if (versionNumber.equals(Store.VERSION_DEFAULT)) {
262 _targetStore.addFile(companyId, repositoryId, fileName, is);
263 }
264 else {
265 _targetStore.updateFile(
266 companyId, repositoryId, fileName, versionNumber, is);
267 }
268
269 if (isDeleteFilesFromSourceStore()) {
270 _sourceStore.deleteFile(
271 companyId, repositoryId, fileName, versionNumber);
272 }
273 }
274 catch (Exception e) {
275 _log.error("Migration failed for " + fileName, e);
276 }
277 }
278
279 protected void migrateImages() throws PortalException {
280 int count = ImageLocalServiceUtil.getImagesCount();
281
282 MaintenanceUtil.appendStatus("Migrating " + count + " images");
283
284 ActionableDynamicQuery actionableDynamicQuery =
285 ImageLocalServiceUtil.getActionableDynamicQuery();
286
287 actionableDynamicQuery.setPerformActionMethod(
288 new ActionableDynamicQuery.PerformActionMethod<Image>() {
289
290 @Override
291 public void performAction(Image image) {
292 String fileName =
293 image.getImageId() + StringPool.PERIOD +
294 image.getType();
295
296 migrateFile(0, 0, fileName, Store.VERSION_DEFAULT);
297 }
298
299 });
300
301 actionableDynamicQuery.performActions();
302 }
303
304 protected void migrateMB() throws PortalException {
305 int count = MBMessageLocalServiceUtil.getMBMessagesCount();
306
307 MaintenanceUtil.appendStatus(
308 "Migrating message boards attachments in " + count + " messages");
309
310 ActionableDynamicQuery actionableDynamicQuery =
311 MBMessageLocalServiceUtil.getActionableDynamicQuery();
312
313 actionableDynamicQuery.setPerformActionMethod(
314 new ActionableDynamicQuery.PerformActionMethod<MBMessage>() {
315
316 @Override
317 public void performAction(MBMessage mbMessage)
318 throws PortalException {
319
320 for (FileEntry fileEntry :
321 mbMessage.getAttachmentsFileEntries()) {
322
323 DLFileEntry dlFileEntry =
324 (DLFileEntry)fileEntry.getModel();
325
326 migrateDLFileEntry(
327 mbMessage.getCompanyId(),
328 DLFolderConstants.getDataRepositoryId(
329 dlFileEntry.getRepositoryId(),
330 dlFileEntry.getFolderId()),
331 new LiferayFileEntry(dlFileEntry));
332 }
333 }
334
335 });
336
337 actionableDynamicQuery.performActions();
338 }
339
340 protected void migratePortlets() throws Exception {
341 migrateImages();
342 migrateDL();
343 migrateMB();
344
345 Collection<DLStoreConvertProcess> dlStoreConvertProcesses =
346 _getDLStoreConvertProcesses();
347
348 for (DLStoreConvertProcess dlStoreConvertProcess :
349 dlStoreConvertProcesses) {
350
351 dlStoreConvertProcess.migrate(this);
352 }
353 }
354
355 private Collection<DLStoreConvertProcess> _getDLStoreConvertProcesses() {
356 try {
357 Registry registry = RegistryUtil.getRegistry();
358
359 return registry.getServices(DLStoreConvertProcess.class, null);
360 }
361 catch (Exception e) {
362 throw new SystemException(e);
363 }
364 }
365
366 private static final String _FILE_SYSTEM_STORE_SUFFIX = "FileSystemStore";
367
368 private static final Log _log = LogFactoryUtil.getLog(
369 DocumentLibraryConvertProcess.class);
370
371 private Store _sourceStore;
372 private Store _targetStore;
373
374 }