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