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