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.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.repository.model.FileEntry;
025 import com.liferay.portal.kernel.util.InstanceFactory;
026 import com.liferay.portal.kernel.util.ListUtil;
027 import com.liferay.portal.kernel.util.PropsKeys;
028 import com.liferay.portal.kernel.util.StringBundler;
029 import com.liferay.portal.kernel.util.StringPool;
030 import com.liferay.portal.kernel.util.Validator;
031 import com.liferay.portal.kernel.workflow.WorkflowConstants;
032 import com.liferay.portal.model.Image;
033 import com.liferay.portal.service.ImageLocalServiceUtil;
034 import com.liferay.portal.util.ClassLoaderUtil;
035 import com.liferay.portal.util.MaintenanceUtil;
036 import com.liferay.portal.util.PropsValues;
037 import com.liferay.portlet.documentlibrary.model.DLFileEntry;
038 import com.liferay.portlet.documentlibrary.model.DLFileVersion;
039 import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
040 import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
041 import com.liferay.portlet.documentlibrary.store.AdvancedFileSystemStore;
042 import com.liferay.portlet.documentlibrary.store.CMISStore;
043 import com.liferay.portlet.documentlibrary.store.DBStore;
044 import com.liferay.portlet.documentlibrary.store.FileSystemStore;
045 import com.liferay.portlet.documentlibrary.store.JCRStore;
046 import com.liferay.portlet.documentlibrary.store.S3Store;
047 import com.liferay.portlet.documentlibrary.store.Store;
048 import com.liferay.portlet.documentlibrary.store.StoreFactory;
049 import com.liferay.portlet.documentlibrary.util.comparator.FileVersionVersionComparator;
050 import com.liferay.portlet.messageboards.model.MBMessage;
051 import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
052 import com.liferay.portlet.wiki.model.WikiPage;
053 import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
054
055 import java.io.InputStream;
056
057 import java.util.List;
058
059
064 public class ConvertDocumentLibrary extends BaseConvertProcess {
065
066 @Override
067 public String getDescription() {
068 return "migrate-documents-from-one-repository-to-another";
069 }
070
071 @Override
072 public String getParameterDescription() {
073 return "please-select-a-new-repository-hook";
074 }
075
076 @Override
077 public String[] getParameterNames() {
078 StringBundler sb = new StringBundler(_HOOKS.length * 2 + 2);
079
080 sb.append(PropsKeys.DL_STORE_IMPL);
081 sb.append(StringPool.EQUAL);
082
083 for (String hook : _HOOKS) {
084 if (!hook.equals(PropsValues.DL_STORE_IMPL)) {
085 sb.append(hook);
086 sb.append(StringPool.SEMICOLON);
087 }
088 }
089
090 return new String[] {sb.toString()};
091 }
092
093 @Override
094 public boolean isEnabled() {
095 return true;
096 }
097
098 @Override
099 public void validate() throws FileSystemStoreRootDirException {
100 String sourceStoreClassName = getSourceStoreClassName();
101
102 if (!sourceStoreClassName.endsWith(_FILE_SYSTEM_STORE_SUFFIX)) {
103 return;
104 }
105
106 String targetStoreClassName = getTargetStoreClassName();
107
108 if (!targetStoreClassName.endsWith(_FILE_SYSTEM_STORE_SUFFIX)) {
109 return;
110 }
111
112 if (Validator.isBlank(
113 PropsValues.DL_STORE_ADVANCED_FILE_SYSTEM_ROOT_DIR)) {
114
115 if (_log.isWarnEnabled()) {
116 _log.warn(
117 "Property \"" +
118 PropsKeys.DL_STORE_ADVANCED_FILE_SYSTEM_ROOT_DIR +
119 " is not set");
120 }
121
122 throw new FileSystemStoreRootDirException();
123 }
124
125 if (Validator.isBlank(PropsValues.DL_STORE_FILE_SYSTEM_ROOT_DIR)) {
126 if (_log.isWarnEnabled()) {
127 _log.warn(
128 "Property \"" +
129 PropsKeys.DL_STORE_FILE_SYSTEM_ROOT_DIR +
130 " is not set");
131 }
132
133 throw new FileSystemStoreRootDirException();
134 }
135
136 if (PropsValues.DL_STORE_ADVANCED_FILE_SYSTEM_ROOT_DIR.equals(
137 PropsValues.DL_STORE_FILE_SYSTEM_ROOT_DIR)) {
138
139 if (_log.isWarnEnabled()) {
140 StringBundler sb = new StringBundler(5);
141
142 sb.append("Both properties \"");
143 sb.append(PropsKeys.DL_STORE_ADVANCED_FILE_SYSTEM_ROOT_DIR);
144 sb.append("\" and \"");
145 sb.append(PropsKeys.DL_STORE_FILE_SYSTEM_ROOT_DIR);
146 sb.append("\" have the same value");
147
148 _log.warn(sb.toString());
149 }
150
151 throw new FileSystemStoreRootDirException();
152 }
153 }
154
155 @Override
156 protected void doConvert() throws Exception {
157 _sourceStore = StoreFactory.getInstance();
158
159 String targetStoreClassName = getTargetStoreClassName();
160
161 _targetStore = (Store)InstanceFactory.newInstance(
162 ClassLoaderUtil.getPortalClassLoader(), targetStoreClassName);
163
164 migratePortlets();
165
166 StoreFactory.setInstance(_targetStore);
167
168 MaintenanceUtil.appendStatus(
169 "Please set " + PropsKeys.DL_STORE_IMPL +
170 " in your portal-ext.properties to use " +
171 targetStoreClassName);
172
173 PropsValues.DL_STORE_IMPL = targetStoreClassName;
174 }
175
176 protected List<DLFileVersion> getDLFileVersions(DLFileEntry dlFileEntry) {
177 List<DLFileVersion> dlFileVersions = dlFileEntry.getFileVersions(
178 WorkflowConstants.STATUS_ANY);
179
180 return ListUtil.sort(
181 dlFileVersions, new FileVersionVersionComparator(true));
182 }
183
184 protected String getSourceStoreClassName() {
185 Store sourceStore = StoreFactory.getInstance();
186
187 return sourceStore.getClass().getName();
188 }
189
190 protected String getTargetStoreClassName() {
191 String[] values = getParameterValues();
192
193 return values[0];
194 }
195
196 protected void migrateDL() throws PortalException {
197 int count = DLFileEntryLocalServiceUtil.getFileEntriesCount();
198
199 MaintenanceUtil.appendStatus(
200 "Migrating " + count + " documents and media files");
201
202 ActionableDynamicQuery actionableDynamicQuery =
203 DLFileEntryLocalServiceUtil.getActionableDynamicQuery();
204
205 actionableDynamicQuery.setAddCriteriaMethod(
206 new ActionableDynamicQuery.AddCriteriaMethod() {
207
208 @Override
209 public void addCriteria(DynamicQuery dynamicQuery) {
210 Property classNameIdProperty = PropertyFactoryUtil.forName(
211 "classNameId");
212
213 dynamicQuery.add(classNameIdProperty.eq(0L));
214 }
215
216 });
217 actionableDynamicQuery.setPerformActionMethod(
218 new ActionableDynamicQuery.PerformActionMethod() {
219
220 @Override
221 public void performAction(Object object) {
222 DLFileEntry dlFileEntry = (DLFileEntry)object;
223
224 migrateDLFileEntry(
225 dlFileEntry.getCompanyId(),
226 dlFileEntry.getDataRepositoryId(), dlFileEntry);
227 }
228
229 });
230
231 actionableDynamicQuery.performActions();
232 }
233
234 protected void migrateDLFileEntry(
235 long companyId, long repositoryId, DLFileEntry dlFileEntry) {
236
237 String fileName = dlFileEntry.getName();
238
239 List<DLFileVersion> dlFileVersions = getDLFileVersions(dlFileEntry);
240
241 if (dlFileVersions.isEmpty()) {
242 String versionNumber = Store.VERSION_DEFAULT;
243
244 migrateFile(companyId, repositoryId, fileName, versionNumber);
245
246 return;
247 }
248
249 for (DLFileVersion dlFileVersion : dlFileVersions) {
250 String versionNumber = dlFileVersion.getVersion();
251
252 migrateFile(companyId, repositoryId, fileName, versionNumber);
253 }
254 }
255
256 protected void migrateFile(
257 long companyId, long repositoryId, String fileName,
258 String versionNumber) {
259
260 try {
261 InputStream is = _sourceStore.getFileAsStream(
262 companyId, repositoryId, fileName, versionNumber);
263
264 if (versionNumber.equals(Store.VERSION_DEFAULT)) {
265 _targetStore.addFile(companyId, repositoryId, fileName, is);
266 }
267 else {
268 _targetStore.updateFile(
269 companyId, repositoryId, fileName, versionNumber, is);
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() {
287
288 @Override
289 public void performAction(Object object) {
290 Image image = (Image)object;
291
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() {
315
316 @Override
317 public void performAction(Object object)
318 throws PortalException {
319
320 MBMessage mbMessage = (MBMessage)object;
321
322 for (FileEntry fileEntry :
323 mbMessage.getAttachmentsFileEntries()) {
324
325 DLFileEntry dlFileEntry =
326 (DLFileEntry)fileEntry.getModel();
327
328 migrateDLFileEntry(
329 mbMessage.getCompanyId(),
330 DLFolderConstants.getDataRepositoryId(
331 dlFileEntry.getRepositoryId(),
332 dlFileEntry.getFolderId()),
333 dlFileEntry);
334 }
335 }
336
337 });
338
339 actionableDynamicQuery.performActions();
340 }
341
342 protected void migratePortlets() throws Exception {
343 migrateImages();
344 migrateDL();
345 migrateMB();
346 migrateWiki();
347 }
348
349 protected void migrateWiki() throws PortalException {
350 int count = WikiPageLocalServiceUtil.getWikiPagesCount();
351
352 MaintenanceUtil.appendStatus(
353 "Migrating wiki page attachments in " + count + " pages");
354
355 ActionableDynamicQuery actionableDynamicQuery =
356 WikiPageLocalServiceUtil.getActionableDynamicQuery();
357
358 actionableDynamicQuery.setAddCriteriaMethod(
359 new ActionableDynamicQuery.AddCriteriaMethod() {
360
361 @Override
362 public void addCriteria(DynamicQuery dynamicQuery) {
363 Property property = PropertyFactoryUtil.forName("head");
364
365 dynamicQuery.add(property.eq(true));
366 }
367
368 });
369 actionableDynamicQuery.setPerformActionMethod(
370 new ActionableDynamicQuery.PerformActionMethod() {
371
372 @Override
373 public void performAction(Object object) {
374 WikiPage wikiPage = (WikiPage)object;
375
376 for (FileEntry fileEntry :
377 wikiPage.getAttachmentsFileEntries()) {
378
379 DLFileEntry dlFileEntry =
380 (DLFileEntry)fileEntry.getModel();
381
382 migrateDLFileEntry(
383 wikiPage.getCompanyId(),
384 DLFolderConstants.getDataRepositoryId(
385 dlFileEntry.getRepositoryId(),
386 dlFileEntry.getFolderId()),
387 dlFileEntry);
388 }
389 }
390
391 });
392
393 actionableDynamicQuery.performActions();
394 }
395
396 private static final String _FILE_SYSTEM_STORE_SUFFIX = "FileSystemStore";
397
398 private static final String[] _HOOKS = new String[] {
399 AdvancedFileSystemStore.class.getName(), CMISStore.class.getName(),
400 DBStore.class.getName(), FileSystemStore.class.getName(),
401 JCRStore.class.getName(), S3Store.class.getName()
402 };
403
404 private static final Log _log = LogFactoryUtil.getLog(
405 ConvertDocumentLibrary.class);
406
407 private Store _sourceStore;
408 private Store _targetStore;
409
410 }