1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.convert;
16  
17  import com.liferay.documentlibrary.DuplicateDirectoryException;
18  import com.liferay.documentlibrary.util.Hook;
19  import com.liferay.documentlibrary.util.HookFactory;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.search.Indexer;
23  import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
24  import com.liferay.portal.kernel.util.PropsKeys;
25  import com.liferay.portal.kernel.util.StringBundler;
26  import com.liferay.portal.kernel.util.StringPool;
27  import com.liferay.portal.kernel.workflow.StatusConstants;
28  import com.liferay.portal.model.CompanyConstants;
29  import com.liferay.portal.model.GroupConstants;
30  import com.liferay.portal.service.ServiceContext;
31  import com.liferay.portal.util.MaintenanceUtil;
32  import com.liferay.portal.util.PortletKeys;
33  import com.liferay.portal.util.PropsValues;
34  import com.liferay.portlet.documentlibrary.model.DLFileEntry;
35  import com.liferay.portlet.documentlibrary.model.DLFileVersion;
36  import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
37  import com.liferay.portlet.documentlibrary.service.DLFileVersionLocalServiceUtil;
38  import com.liferay.portlet.messageboards.model.MBMessage;
39  import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
40  import com.liferay.portlet.wiki.model.WikiPage;
41  import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
42  
43  import java.io.InputStream;
44  
45  import java.util.Date;
46  import java.util.List;
47  
48  /**
49   * <a href="ConvertDocumentLibrary.java.html"><b><i>View Source</i></b></a>
50   *
51   * @author Minhchau Dang
52   * @author Alexander Chow
53   */
54  public class ConvertDocumentLibrary extends ConvertProcess {
55  
56      public String getDescription() {
57          return "migrate-documents-from-one-repository-to-another";
58      }
59  
60      public String getParameterDescription() {
61          return "please-select-a-new-repository-hook";
62      }
63  
64      public String[] getParameterNames() {
65          StringBundler sb = new StringBundler(_HOOKS.length * 2 + 2);
66  
67          sb.append(PropsKeys.DL_HOOK_IMPL);
68          sb.append(StringPool.EQUAL);
69  
70          for (String hook : _HOOKS) {
71              if (!hook.equals(PropsValues.DL_HOOK_IMPL)) {
72                  sb.append(hook);
73                  sb.append(StringPool.SEMICOLON);
74              }
75          }
76  
77          return new String[] {sb.toString()};
78      }
79  
80      public boolean isEnabled() {
81          return true;
82      }
83  
84      protected void doConvert() throws Exception {
85          _sourceHook = HookFactory.getInstance();
86  
87          String[] values = getParameterValues();
88  
89          String targetHookClassName = values[0];
90  
91          ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
92  
93          _targetHook = (Hook)classLoader.loadClass(
94              targetHookClassName).newInstance();
95  
96          migratePortlets();
97  
98          HookFactory.setInstance(_targetHook);
99  
100         MaintenanceUtil.appendStatus(
101             "Please set " + PropsKeys.DL_HOOK_IMPL +
102                 " in your portal-ext.properties to use " + targetHookClassName);
103 
104         PropsValues.DL_HOOK_IMPL = targetHookClassName;
105     }
106 
107     protected void migrateDL() throws Exception {
108         int count = DLFileEntryLocalServiceUtil.getDLFileEntriesCount();
109         int pages = count / Indexer.DEFAULT_INTERVAL;
110 
111         MaintenanceUtil.appendStatus(
112             "Migrating " + count + " document library files");
113 
114         for (int i = 0; i <= pages; i++) {
115             int start = (i * Indexer.DEFAULT_INTERVAL);
116             int end = start + Indexer.DEFAULT_INTERVAL;
117 
118             List<DLFileEntry> dlFileEntries =
119                 DLFileEntryLocalServiceUtil.getDLFileEntries(start, end);
120 
121             String portletId = PortletKeys.DOCUMENT_LIBRARY;
122 
123             for (DLFileEntry dlFileEntry : dlFileEntries) {
124                 long companyId = dlFileEntry.getCompanyId();
125                 long groupId = dlFileEntry.getGroupId();
126                 long repositoryId = dlFileEntry.getRepositoryId();
127 
128                 migrateDLFileEntry(
129                     companyId, portletId, groupId, repositoryId, dlFileEntry);
130             }
131         }
132     }
133 
134     protected void migrateDLFileEntry(
135             long companyId, String portletId, long groupId, long repositoryId,
136             DLFileEntry fileEntry)
137         throws Exception {
138 
139         String fileName = fileEntry.getName();
140         long fileEntryId = fileEntry.getFileEntryId();
141         String properties = fileEntry.getLuceneProperties();
142 
143         List<DLFileVersion> dlFileVersions =
144             DLFileVersionLocalServiceUtil.getFileVersions(
145                 groupId, repositoryId, fileName, StatusConstants.ANY);
146 
147         if (dlFileVersions.isEmpty()) {
148             String versionNumber = Hook.DEFAULT_VERSION;
149             Date modifiedDate = fileEntry.getModifiedDate();
150 
151             migrateFile(
152                 companyId, portletId, groupId, repositoryId, fileName,
153                 versionNumber, fileEntryId, properties, modifiedDate);
154 
155             return;
156         }
157 
158         for (DLFileVersion dlFileVersion : dlFileVersions) {
159             String versionNumber = dlFileVersion.getVersion();
160             Date modifiedDate = dlFileVersion.getCreateDate();
161 
162             migrateFile(
163                 companyId, portletId, groupId, repositoryId, fileName,
164                 versionNumber, fileEntryId, properties, modifiedDate);
165         }
166     }
167 
168     protected void migrateFile(
169         long companyId, String portletId, long groupId, long repositoryId,
170         String fileName, String versionNumber, long fileEntryId,
171         String properties, Date modifiedDate) {
172 
173         try {
174             InputStream is = _sourceHook.getFileAsStream(
175                 companyId, repositoryId, fileName, versionNumber);
176 
177             if (versionNumber.equals(Hook.DEFAULT_VERSION)) {
178                 _targetHook.addFile(
179                     companyId, portletId, groupId, repositoryId, fileName,
180                     fileEntryId, properties, modifiedDate, _serviceContext,
181                     is);
182             }
183             else {
184                 _targetHook.updateFile(
185                     companyId, portletId, groupId, repositoryId, fileName,
186                     versionNumber, fileName, fileEntryId, properties,
187                     modifiedDate, _serviceContext, is);
188             }
189         }
190         catch (Exception e) {
191             _log.error("Migration failed for " + fileName, e);
192         }
193     }
194     protected void migrateFiles(
195             long companyId, String dirName, String[] fileNames)
196         throws Exception {
197 
198         String portletId = CompanyConstants.SYSTEM_STRING;
199         long groupId = GroupConstants.DEFAULT_PARENT_GROUP_ID;
200         long repositoryId = CompanyConstants.SYSTEM;
201         String versionNumber = Hook.DEFAULT_VERSION;
202         long fileEntryId = 0;
203         String properties = StringPool.BLANK;
204         Date modifiedDate = new Date();
205 
206         try {
207             _targetHook.addDirectory(companyId, repositoryId, dirName);
208         }
209         catch (DuplicateDirectoryException dde) {
210         }
211 
212         for (String fileName : fileNames) {
213             if (fileName.startsWith(StringPool.SLASH)) {
214                 fileName = fileName.substring(1);
215             }
216 
217             migrateFile(
218                 companyId, portletId, groupId, repositoryId, fileName,
219                 versionNumber, fileEntryId, properties, modifiedDate);
220         }
221     }
222 
223     protected void migrateMB() throws Exception {
224         int count = MBMessageLocalServiceUtil.getMBMessagesCount();
225         int pages = count / Indexer.DEFAULT_INTERVAL;
226 
227         MaintenanceUtil.appendStatus(
228             "Migrating message boards attachments in " + count + " messages");
229 
230         for (int i = 0; i <= pages; i++) {
231             int start = (i * Indexer.DEFAULT_INTERVAL);
232             int end = start + Indexer.DEFAULT_INTERVAL;
233 
234             List<MBMessage> messages =
235                 MBMessageLocalServiceUtil.getMBMessages(start, end);
236 
237             for (MBMessage message : messages) {
238                 migrateFiles(
239                     message.getCompanyId(), message.getAttachmentsDir(),
240                     message.getAttachmentsFiles());
241             }
242         }
243     }
244 
245     protected void migratePortlets() throws Exception {
246         migrateDL();
247         migrateMB();
248         migrateWiki();
249     }
250 
251     protected void migrateWiki() throws Exception {
252         int count = WikiPageLocalServiceUtil.getWikiPagesCount();
253         int pages = count / Indexer.DEFAULT_INTERVAL;
254 
255         MaintenanceUtil.appendStatus(
256             "Migrating wiki page attachments in " + count + " pages");
257 
258         for (int i = 0; i <= pages; i++) {
259             int start = (i * Indexer.DEFAULT_INTERVAL);
260             int end = start + Indexer.DEFAULT_INTERVAL;
261 
262             List<WikiPage> wikiPages =
263                 WikiPageLocalServiceUtil.getWikiPages(start, end);
264 
265             for (WikiPage wikiPage : wikiPages) {
266                 if (!wikiPage.isHead()) {
267                     continue;
268                 }
269 
270                 migrateFiles(
271                     wikiPage.getCompanyId(), wikiPage.getAttachmentsDir(),
272                     wikiPage.getAttachmentsFiles());
273             }
274         }
275     }
276 
277     private static final String[] _HOOKS = new String[] {
278         "com.liferay.documentlibrary.util.AdvancedFileSystemHook",
279         "com.liferay.documentlibrary.util.CMISHook",
280         "com.liferay.documentlibrary.util.FileSystemHook",
281         "com.liferay.documentlibrary.util.JCRHook",
282         "com.liferay.documentlibrary.util.S3Hook"
283     };
284 
285     private static Log _log = LogFactoryUtil.getLog(
286         ConvertDocumentLibrary.class);
287 
288     private ServiceContext _serviceContext = new ServiceContext();
289     private Hook _sourceHook;
290     private Hook _targetHook;
291 
292 }