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