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 return sourceStore.getClass().getName();
196 }
197
198 protected String getTargetStoreClassName() {
199 String[] values = getParameterValues();
200
201 return values[0];
202 }
203
204 protected boolean isDeleteFilesFromSourceStore() {
205 String[] values = getParameterValues();
206
207 return GetterUtil.getBoolean(values[1]);
208 }
209
210 protected void migrateDL() throws PortalException {
211 int count = DLFileEntryLocalServiceUtil.getFileEntriesCount();
212
213 MaintenanceUtil.appendStatus(
214 "Migrating " + count + " documents and media files");
215
216 ActionableDynamicQuery actionableDynamicQuery =
217 DLFileEntryLocalServiceUtil.getActionableDynamicQuery();
218
219 actionableDynamicQuery.setAddCriteriaMethod(
220 new ActionableDynamicQuery.AddCriteriaMethod() {
221
222 @Override
223 public void addCriteria(DynamicQuery dynamicQuery) {
224 Property classNameIdProperty = PropertyFactoryUtil.forName(
225 "classNameId");
226
227 dynamicQuery.add(classNameIdProperty.eq(0L));
228 }
229
230 });
231 actionableDynamicQuery.setPerformActionMethod(
232 new ActionableDynamicQuery.PerformActionMethod<DLFileEntry>() {
233
234 @Override
235 public void performAction(DLFileEntry dlFileEntry) {
236 migrateDLFileEntry(
237 dlFileEntry.getCompanyId(),
238 dlFileEntry.getDataRepositoryId(),
239 new LiferayFileEntry(dlFileEntry));
240 }
241
242 });
243
244 actionableDynamicQuery.performActions();
245
246 if (isDeleteFilesFromSourceStore()) {
247 DLPreviewableProcessor.deleteFiles();
248 }
249 }
250
251 protected void migrateFile(
252 long companyId, long repositoryId, String fileName,
253 String versionNumber) {
254
255 try {
256 InputStream is = _sourceStore.getFileAsStream(
257 companyId, repositoryId, fileName, versionNumber);
258
259 if (versionNumber.equals(Store.VERSION_DEFAULT)) {
260 _targetStore.addFile(companyId, repositoryId, fileName, is);
261 }
262 else {
263 _targetStore.updateFile(
264 companyId, repositoryId, fileName, versionNumber, is);
265 }
266
267 if (isDeleteFilesFromSourceStore()) {
268 _sourceStore.deleteFile(
269 companyId, repositoryId, fileName, versionNumber);
270 }
271 }
272 catch (Exception e) {
273 _log.error("Migration failed for " + fileName, e);
274 }
275 }
276
277 protected void migrateImages() throws PortalException {
278 int count = ImageLocalServiceUtil.getImagesCount();
279
280 MaintenanceUtil.appendStatus("Migrating " + count + " images");
281
282 ActionableDynamicQuery actionableDynamicQuery =
283 ImageLocalServiceUtil.getActionableDynamicQuery();
284
285 actionableDynamicQuery.setPerformActionMethod(
286 new ActionableDynamicQuery.PerformActionMethod<Image>() {
287
288 @Override
289 public void performAction(Image image) {
290 String fileName =
291 image.getImageId() + StringPool.PERIOD +
292 image.getType();
293
294 migrateFile(0, 0, fileName, Store.VERSION_DEFAULT);
295 }
296
297 });
298
299 actionableDynamicQuery.performActions();
300 }
301
302 protected void migrateMB() throws PortalException {
303 int count = MBMessageLocalServiceUtil.getMBMessagesCount();
304
305 MaintenanceUtil.appendStatus(
306 "Migrating message boards attachments in " + count + " messages");
307
308 ActionableDynamicQuery actionableDynamicQuery =
309 MBMessageLocalServiceUtil.getActionableDynamicQuery();
310
311 actionableDynamicQuery.setPerformActionMethod(
312 new ActionableDynamicQuery.PerformActionMethod<MBMessage>() {
313
314 @Override
315 public void performAction(MBMessage mbMessage)
316 throws PortalException {
317
318 for (FileEntry fileEntry :
319 mbMessage.getAttachmentsFileEntries()) {
320
321 DLFileEntry dlFileEntry =
322 (DLFileEntry)fileEntry.getModel();
323
324 migrateDLFileEntry(
325 mbMessage.getCompanyId(),
326 DLFolderConstants.getDataRepositoryId(
327 dlFileEntry.getRepositoryId(),
328 dlFileEntry.getFolderId()),
329 new LiferayFileEntry(dlFileEntry));
330 }
331 }
332
333 });
334
335 actionableDynamicQuery.performActions();
336 }
337
338 protected void migratePortlets() throws Exception {
339 migrateImages();
340 migrateDL();
341 migrateMB();
342
343 Collection<DLStoreConvertProcess> dlStoreConvertProcesses =
344 _getDLStoreConvertProcesses();
345
346 for (DLStoreConvertProcess dlStoreConvertProcess :
347 dlStoreConvertProcesses) {
348
349 dlStoreConvertProcess.migrate(this);
350 }
351 }
352
353 private Collection<DLStoreConvertProcess> _getDLStoreConvertProcesses() {
354 try {
355 Registry registry = RegistryUtil.getRegistry();
356
357 return registry.getServices(DLStoreConvertProcess.class, null);
358 }
359 catch (Exception e) {
360 throw new SystemException(e);
361 }
362 }
363
364 private static final String _FILE_SYSTEM_STORE_SUFFIX = "FileSystemStore";
365
366 private static final Log _log = LogFactoryUtil.getLog(
367 DocumentLibraryConvertProcess.class);
368
369 private Store _sourceStore;
370 private Store _targetStore;
371
372 }