001    /**
002     * Copyright (c) 2000-2013 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.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.exception.SystemException;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.util.GetterUtil;
026    import com.liferay.portal.kernel.util.InstanceFactory;
027    import com.liferay.portal.kernel.util.ListUtil;
028    import com.liferay.portal.kernel.util.PropsKeys;
029    import com.liferay.portal.kernel.util.StringBundler;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.workflow.WorkflowConstants;
032    import com.liferay.portal.model.Image;
033    import com.liferay.portal.service.ClassNameLocalServiceUtil;
034    import com.liferay.portal.service.ImageLocalServiceUtil;
035    import com.liferay.portal.service.persistence.ImageActionableDynamicQuery;
036    import com.liferay.portal.util.ClassLoaderUtil;
037    import com.liferay.portal.util.MaintenanceUtil;
038    import com.liferay.portal.util.PropsValues;
039    import com.liferay.portlet.documentlibrary.model.DLFileEntry;
040    import com.liferay.portlet.documentlibrary.model.DLFileVersion;
041    import com.liferay.portlet.documentlibrary.model.DLFolderConstants;
042    import com.liferay.portlet.documentlibrary.service.DLFileEntryLocalServiceUtil;
043    import com.liferay.portlet.documentlibrary.service.persistence.DLFileEntryActionableDynamicQuery;
044    import com.liferay.portlet.documentlibrary.store.AdvancedFileSystemStore;
045    import com.liferay.portlet.documentlibrary.store.CMISStore;
046    import com.liferay.portlet.documentlibrary.store.DBStore;
047    import com.liferay.portlet.documentlibrary.store.FileSystemStore;
048    import com.liferay.portlet.documentlibrary.store.JCRStore;
049    import com.liferay.portlet.documentlibrary.store.S3Store;
050    import com.liferay.portlet.documentlibrary.store.Store;
051    import com.liferay.portlet.documentlibrary.store.StoreFactory;
052    import com.liferay.portlet.documentlibrary.util.DLPreviewableProcessor;
053    import com.liferay.portlet.documentlibrary.util.comparator.FileVersionVersionComparator;
054    
055    import java.io.InputStream;
056    
057    import java.util.List;
058    
059    /**
060     * @author Minhchau Dang
061     * @author Alexander Chow
062     */
063    public class ConvertDocumentLibrary extends ConvertProcess {
064    
065            @Override
066            public String getDescription() {
067                    return "migrate-documents-from-one-repository-to-another";
068            }
069    
070            @Override
071            public String getParameterDescription() {
072                    return "please-select-a-new-repository-hook";
073            }
074    
075            @Override
076            public String[] getParameterNames() {
077                    StringBundler sb = new StringBundler(_HOOKS.length * 2 + 2);
078    
079                    sb.append(PropsKeys.DL_STORE_IMPL);
080                    sb.append(StringPool.EQUAL);
081    
082                    for (String hook : _HOOKS) {
083                            if (!hook.equals(PropsValues.DL_STORE_IMPL)) {
084                                    sb.append(hook);
085                                    sb.append(StringPool.SEMICOLON);
086                            }
087                    }
088    
089                    return new String[] {
090                            sb.toString(), "delete-files-from-previous-repository=checkbox"
091                    };
092            }
093    
094            @Override
095            public boolean isEnabled() {
096                    return true;
097            }
098    
099            @Override
100            protected void doConvert() throws Exception {
101                    _sourceStore = StoreFactory.getInstance();
102    
103                    String[] values = getParameterValues();
104    
105                    String targetStoreClassName = values[0];
106    
107                    _targetStore = (Store)InstanceFactory.newInstance(
108                            ClassLoaderUtil.getPortalClassLoader(), targetStoreClassName);
109    
110                    migratePortlets();
111    
112                    StoreFactory.setInstance(_targetStore);
113    
114                    MaintenanceUtil.appendStatus(
115                            "Please set " + PropsKeys.DL_STORE_IMPL +
116                                    " in your portal-ext.properties to use " +
117                                            targetStoreClassName);
118    
119                    PropsValues.DL_STORE_IMPL = targetStoreClassName;
120            }
121    
122            protected List<DLFileVersion> getDLFileVersions(DLFileEntry dlFileEntry)
123                    throws SystemException {
124    
125                    List<DLFileVersion> dlFileVersions = dlFileEntry.getFileVersions(
126                            WorkflowConstants.STATUS_ANY);
127    
128                    return ListUtil.sort(
129                            dlFileVersions, new FileVersionVersionComparator(true));
130            }
131    
132            protected boolean isDeleteFilesFromSourceStore() {
133                    String[] values = getParameterValues();
134    
135                    return GetterUtil.getBoolean(values[1]);
136            }
137    
138            protected void migrateDL() throws PortalException, SystemException {
139                    int count = DLFileEntryLocalServiceUtil.getFileEntriesCount();
140    
141                    final long backgroundTaskClassNameId =
142                            ClassNameLocalServiceUtil.getClassNameId(
143                                    "com.liferay.portal.model.BackgroundTask");
144                    final long mbAttachmentClassNameId =
145                            ClassNameLocalServiceUtil.getClassNameId(
146                                    "com.liferay.portlet.messageboards.model.MBMessage");
147                    final long wikiAttachmentClassNameId =
148                            ClassNameLocalServiceUtil.getClassNameId(
149                                    "com.liferay.portlet.wiki.model.WikiPage");
150    
151                    MaintenanceUtil.appendStatus(
152                            "Migrating " + count + " documents and media files");
153    
154                    ActionableDynamicQuery actionableDynamicQuery =
155                            new DLFileEntryActionableDynamicQuery() {
156    
157                            @Override
158                            protected void addCriteria(DynamicQuery dynamicQuery) {
159                                    Property classNameIdProperty = PropertyFactoryUtil.forName(
160                                            "classNameId");
161    
162                                    dynamicQuery.add(
163                                            classNameIdProperty.ne(backgroundTaskClassNameId));
164                            }
165    
166                            @Override
167                            protected void performAction(Object object) throws SystemException {
168                                    DLFileEntry dlFileEntry = (DLFileEntry)object;
169    
170                                    long dataRepositoryId = 0;
171    
172                                    long classNameId = dlFileEntry.getClassNameId();
173    
174                                    if ((classNameId == mbAttachmentClassNameId) ||
175                                            (classNameId == wikiAttachmentClassNameId)) {
176    
177                                            dataRepositoryId = DLFolderConstants.getDataRepositoryId(
178                                                    dlFileEntry.getRepositoryId(),
179                                                    dlFileEntry.getFolderId());
180                                    }
181                                    else {
182                                            dataRepositoryId = dlFileEntry.getDataRepositoryId();
183                                    }
184    
185                                    migrateDLFileEntry(
186                                            dlFileEntry.getCompanyId(), dataRepositoryId, dlFileEntry);
187                            }
188    
189                    };
190    
191                    actionableDynamicQuery.performActions();
192    
193                    if (isDeleteFilesFromSourceStore()) {
194                            DLPreviewableProcessor.deleteFiles();
195                    }
196            }
197    
198            protected void migrateDLFileEntry(
199                            long companyId, long repositoryId, DLFileEntry dlFileEntry)
200                    throws SystemException {
201    
202                    String fileName = dlFileEntry.getName();
203    
204                    List<DLFileVersion> dlFileVersions = getDLFileVersions(dlFileEntry);
205    
206                    if (dlFileVersions.isEmpty()) {
207                            String versionNumber = Store.VERSION_DEFAULT;
208    
209                            migrateFile(companyId, repositoryId, fileName, versionNumber);
210    
211                            return;
212                    }
213    
214                    for (DLFileVersion dlFileVersion : dlFileVersions) {
215                            String versionNumber = dlFileVersion.getVersion();
216    
217                            migrateFile(companyId, repositoryId, fileName, versionNumber);
218                    }
219            }
220    
221            protected void migrateFile(
222                    long companyId, long repositoryId, String fileName,
223                    String versionNumber) {
224    
225                    try {
226                            InputStream is = _sourceStore.getFileAsStream(
227                                    companyId, repositoryId, fileName, versionNumber);
228    
229                            if (versionNumber.equals(Store.VERSION_DEFAULT)) {
230                                    _targetStore.addFile(companyId, repositoryId, fileName, is);
231                            }
232                            else {
233                                    _targetStore.updateFile(
234                                            companyId, repositoryId, fileName, versionNumber, is);
235                            }
236    
237                            if (isDeleteFilesFromSourceStore()) {
238                                    _sourceStore.deleteFile(
239                                            companyId, repositoryId, fileName, versionNumber);
240                            }
241                    }
242                    catch (Exception e) {
243                            _log.error("Migration failed for " + fileName, e);
244                    }
245            }
246    
247            protected void migrateImages() throws PortalException, SystemException {
248                    int count = ImageLocalServiceUtil.getImagesCount();
249    
250                    MaintenanceUtil.appendStatus("Migrating " + count + " images");
251    
252                    ActionableDynamicQuery actionableDynamicQuery =
253                            new ImageActionableDynamicQuery() {
254    
255                            @Override
256                            protected void performAction(Object object) {
257                                    Image image = (Image)object;
258    
259                                    String fileName =
260                                            image.getImageId() + StringPool.PERIOD + image.getType();
261    
262                                    migrateFile(0, 0, fileName, Store.VERSION_DEFAULT);
263                            }
264    
265                    };
266    
267                    actionableDynamicQuery.performActions();
268            }
269    
270            protected void migratePortlets() throws Exception {
271                    migrateImages();
272                    migrateDL();
273            }
274    
275            private static final String[] _HOOKS = new String[] {
276                    AdvancedFileSystemStore.class.getName(), CMISStore.class.getName(),
277                    DBStore.class.getName(), FileSystemStore.class.getName(),
278                    JCRStore.class.getName(), S3Store.class.getName()
279            };
280    
281            private static Log _log = LogFactoryUtil.getLog(
282                    ConvertDocumentLibrary.class);
283    
284            private Store _sourceStore;
285            private Store _targetStore;
286    
287    }