001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
013     */
014    
015    package com.liferay.portal.convert;
016    
017    import com.liferay.portal.kernel.log.Log;
018    import com.liferay.portal.kernel.log.LogFactoryUtil;
019    import com.liferay.portal.kernel.search.Indexer;
020    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
021    import com.liferay.portal.kernel.util.PropsKeys;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.workflow.WorkflowConstants;
025    import com.liferay.portal.model.CompanyConstants;
026    import com.liferay.portal.util.MaintenanceUtil;
027    import com.liferay.portal.util.PropsValues;
028    import com.liferay.portlet.documentlibrary.DuplicateDirectoryException;
029    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
030    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
031    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
032    import com.liferay.portlet.documentlibrary.store.AdvancedFileSystemStore;
033    import com.liferay.portlet.documentlibrary.store.CMISStore;
034    import com.liferay.portlet.documentlibrary.store.FileSystemStore;
035    import com.liferay.portlet.documentlibrary.store.JCRStore;
036    import com.liferay.portlet.documentlibrary.store.S3Store;
037    import com.liferay.portlet.documentlibrary.store.Store;
038    import com.liferay.portlet.documentlibrary.store.StoreFactory;
039    import com.liferay.portlet.messageboards.model.MBMessage;
040    import com.liferay.portlet.messageboards.service.MBMessageLocalServiceUtil;
041    import com.liferay.portlet.wiki.model.WikiPage;
042    import com.liferay.portlet.wiki.service.WikiPageLocalServiceUtil;
043    
044    import java.io.InputStream;
045    
046    import java.util.List;
047    
048    /**
049     * @author Minhchau Dang
050     * @author Alexander Chow
051     */
052    public class ConvertDocumentLibrary extends ConvertProcess {
053    
054            @Override
055            public String getDescription() {
056                    return "migrate-documents-from-one-repository-to-another";
057            }
058    
059            @Override
060            public String getParameterDescription() {
061                    return "please-select-a-new-repository-hook";
062            }
063    
064            @Override
065            public String[] getParameterNames() {
066                    StringBundler sb = new StringBundler(_HOOKS.length * 2 + 2);
067    
068                    sb.append(PropsKeys.DL_STORE_IMPL);
069                    sb.append(StringPool.EQUAL);
070    
071                    for (String hook : _HOOKS) {
072                            if (!hook.equals(PropsValues.DL_STORE_IMPL)) {
073                                    sb.append(hook);
074                                    sb.append(StringPool.SEMICOLON);
075                            }
076                    }
077    
078                    return new String[] {sb.toString()};
079            }
080    
081            @Override
082            public boolean isEnabled() {
083                    return true;
084            }
085    
086            @Override
087            protected void doConvert() throws Exception {
088                    _sourceStore = StoreFactory.getInstance();
089    
090                    String[] values = getParameterValues();
091    
092                    String targetStoreClassName = values[0];
093    
094                    ClassLoader classLoader = PortalClassLoaderUtil.getClassLoader();
095    
096                    _targetStore = (Store)classLoader.loadClass(
097                            targetStoreClassName).newInstance();
098    
099                    migratePortlets();
100    
101                    StoreFactory.setInstance(_targetStore);
102    
103                    MaintenanceUtil.appendStatus(
104                            "Please set " + PropsKeys.DL_STORE_IMPL +
105                                    " in your portal-ext.properties to use " +
106                                            targetStoreClassName);
107    
108                    PropsValues.DL_STORE_IMPL = targetStoreClassName;
109            }
110    
111            protected void migrateDL() throws Exception {
112                    int count = DLFileEntryLocalServiceUtil.getFileEntriesCount();
113                    int pages = count / Indexer.DEFAULT_INTERVAL;
114    
115                    MaintenanceUtil.appendStatus(
116                            "Migrating " + count + " document library files");
117    
118                    for (int i = 0; i <= pages; i++) {
119                            int start = (i * Indexer.DEFAULT_INTERVAL);
120                            int end = start + Indexer.DEFAULT_INTERVAL;
121    
122                            List<DLFileEntry> dlFileEntries =
123                                    DLFileEntryLocalServiceUtil.getFileEntries(start, end);
124    
125                            for (DLFileEntry dlFileEntry : dlFileEntries) {
126                                    long companyId = dlFileEntry.getCompanyId();
127                                    long repositoryId = dlFileEntry.getDataRepositoryId();
128    
129                                    migrateDLFileEntry(companyId, repositoryId, dlFileEntry);
130                            }
131                    }
132            }
133    
134            protected void migrateDLFileEntry(
135                            long companyId, long repositoryId, DLFileEntry fileEntry)
136                    throws Exception {
137    
138                    String fileName = fileEntry.getName();
139    
140                    List<DLFileVersion> dlFileVersions = fileEntry.getFileVersions(
141                            WorkflowConstants.STATUS_ANY);
142    
143                    if (dlFileVersions.isEmpty()) {
144                            String versionNumber = Store.VERSION_DEFAULT;
145    
146                            migrateFile(companyId, repositoryId, fileName, versionNumber);
147    
148                            return;
149                    }
150    
151                    for (DLFileVersion dlFileVersion : dlFileVersions) {
152                            String versionNumber = dlFileVersion.getVersion();
153    
154                            migrateFile(companyId, repositoryId, fileName, versionNumber);
155                    }
156            }
157    
158            protected void migrateFile(
159                    long companyId, long repositoryId, String fileName,
160                    String versionNumber) {
161    
162                    try {
163                            InputStream is = _sourceStore.getFileAsStream(
164                                    companyId, repositoryId, fileName, versionNumber);
165    
166                            if (versionNumber.equals(Store.VERSION_DEFAULT)) {
167                                    _targetStore.addFile(companyId, repositoryId, fileName, is);
168                            }
169                            else {
170                                    _targetStore.updateFile(
171                                            companyId, repositoryId, fileName, versionNumber, is);
172                            }
173                    }
174                    catch (Exception e) {
175                            _log.error("Migration failed for " + fileName, e);
176                    }
177            }
178    
179            protected void migrateFiles(
180                            long companyId, String dirName, String[] fileNames)
181                    throws Exception {
182    
183                    long repositoryId = CompanyConstants.SYSTEM;
184                    String versionNumber = Store.VERSION_DEFAULT;
185    
186                    try {
187                            _targetStore.addDirectory(companyId, repositoryId, dirName);
188                    }
189                    catch (DuplicateDirectoryException dde) {
190                    }
191    
192                    for (String fileName : fileNames) {
193                            if (fileName.startsWith(StringPool.SLASH)) {
194                                    fileName = fileName.substring(1);
195                            }
196    
197                            migrateFile(companyId, repositoryId, fileName, versionNumber);
198                    }
199            }
200    
201            protected void migrateMB() throws Exception {
202                    int count = MBMessageLocalServiceUtil.getMBMessagesCount();
203                    int pages = count / Indexer.DEFAULT_INTERVAL;
204    
205                    MaintenanceUtil.appendStatus(
206                            "Migrating message boards attachments in " + count + " messages");
207    
208                    for (int i = 0; i <= pages; i++) {
209                            int start = (i * Indexer.DEFAULT_INTERVAL);
210                            int end = start + Indexer.DEFAULT_INTERVAL;
211    
212                            List<MBMessage> messages =
213                                    MBMessageLocalServiceUtil.getMBMessages(start, end);
214    
215                            for (MBMessage message : messages) {
216                                    migrateFiles(
217                                            message.getCompanyId(), message.getAttachmentsDir(),
218                                            message.getAttachmentsFiles());
219                            }
220                    }
221            }
222    
223            protected void migratePortlets() throws Exception {
224                    migrateDL();
225                    migrateMB();
226                    migrateWiki();
227            }
228    
229            protected void migrateWiki() throws Exception {
230                    int count = WikiPageLocalServiceUtil.getWikiPagesCount();
231                    int pages = count / Indexer.DEFAULT_INTERVAL;
232    
233                    MaintenanceUtil.appendStatus(
234                            "Migrating wiki page attachments in " + count + " pages");
235    
236                    for (int i = 0; i <= pages; i++) {
237                            int start = (i * Indexer.DEFAULT_INTERVAL);
238                            int end = start + Indexer.DEFAULT_INTERVAL;
239    
240                            List<WikiPage> wikiPages =
241                                    WikiPageLocalServiceUtil.getWikiPages(start, end);
242    
243                            for (WikiPage wikiPage : wikiPages) {
244                                    if (!wikiPage.isHead()) {
245                                            continue;
246                                    }
247    
248                                    migrateFiles(
249                                            wikiPage.getCompanyId(), wikiPage.getAttachmentsDir(),
250                                            wikiPage.getAttachmentsFiles());
251                            }
252                    }
253            }
254    
255            private static final String[] _HOOKS = new String[] {
256                    AdvancedFileSystemStore.class.getName(), CMISStore.class.getName(),
257                    FileSystemStore.class.getName(), JCRStore.class.getName(),
258                    S3Store.class.getName()
259            };
260    
261            private static Log _log = LogFactoryUtil.getLog(
262                    ConvertDocumentLibrary.class);
263    
264            private Store _sourceStore;
265            private Store _targetStore;
266    
267    }