001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.test;
016    
017    import com.liferay.portal.kernel.cache.CacheRegistryUtil;
018    import com.liferay.portal.kernel.cache.Lifecycle;
019    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
020    import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
021    import com.liferay.portal.kernel.cache.ThreadLocalCacheManager;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.search.SearchEngineUtil;
025    import com.liferay.portal.kernel.search.SearchException;
026    import com.liferay.portal.kernel.test.BaseTestRule;
027    import com.liferay.portal.kernel.util.FileUtil;
028    import com.liferay.portal.kernel.util.PropsKeys;
029    import com.liferay.portal.kernel.util.SystemProperties;
030    import com.liferay.portal.log.Log4JLoggerTestUtil;
031    import com.liferay.portal.test.jdbc.ResetDatabaseUtil;
032    import com.liferay.portal.upgrade.util.Table;
033    import com.liferay.portal.util.PortalInstances;
034    import com.liferay.portal.util.PropsUtil;
035    import com.liferay.portal.util.PropsValues;
036    
037    import java.io.File;
038    import java.io.IOException;
039    
040    import java.util.Arrays;
041    import java.util.HashMap;
042    import java.util.LinkedList;
043    import java.util.Map;
044    import java.util.Queue;
045    
046    import org.apache.log4j.Level;
047    
048    import org.junit.runner.Description;
049    
050    /**
051     * @author Shuyang Zhou
052     */
053    public class ResetDatabaseTestRule extends BaseTestRule<Object, Level> {
054    
055            public static final ResetDatabaseTestRule INSTANCE =
056                    new ResetDatabaseTestRule();
057    
058            @Override
059            protected void afterMethod(Description description, Level level) {
060                    restoreDLStores(false);
061                    restoreSearchIndices(false);
062    
063                    ResetDatabaseUtil.resetModifiedTables();
064    
065                    Log4JLoggerTestUtil.setLoggerLevel(Table.class.getName(), level);
066    
067                    CacheRegistryUtil.clear();
068                    SingleVMPoolUtil.clear();
069                    MultiVMPoolUtil.clear();
070    
071                    ThreadLocalCacheManager.clearAll(Lifecycle.REQUEST);
072            }
073    
074            protected void backupDLStores(boolean initialize) {
075                    String dlFileSystemStoreDirName = null;
076    
077                    if (initialize) {
078                            dlFileSystemStoreDirName =
079                                    SystemProperties.get(SystemProperties.TMP_DIR) +
080                                            "/temp-init-dl-file-system-" + System.currentTimeMillis();
081    
082                            _initializedDLFileSystemStoreDirName = dlFileSystemStoreDirName;
083    
084                            Runtime runtime = Runtime.getRuntime();
085    
086                            runtime.addShutdownHook(
087                                    new DeleteFileShutdownHook(dlFileSystemStoreDirName));
088                    }
089                    else {
090                            dlFileSystemStoreDirName =
091                                    SystemProperties.get(SystemProperties.TMP_DIR) +
092                                            "/temp-dl-file-system-" + System.currentTimeMillis();
093    
094                            _dlFileSystemStoreDirName = dlFileSystemStoreDirName;
095                    }
096    
097                    try {
098                            FileUtil.copyDirectory(
099                                    new File(PropsValues.DL_STORE_FILE_SYSTEM_ROOT_DIR),
100                                    new File(dlFileSystemStoreDirName));
101                    }
102                    catch (IOException ioe) {
103                            throw new RuntimeException(ioe);
104                    }
105    
106                    String dlJCRStoreDirName = null;
107    
108                    if (initialize) {
109                            dlJCRStoreDirName =
110                                    SystemProperties.get(SystemProperties.TMP_DIR) +
111                                            "/temp-init-dl-jcr-" + System.currentTimeMillis();
112    
113                            _initializedDLJCRStoreDirName = dlJCRStoreDirName;
114    
115                            Runtime runtime = Runtime.getRuntime();
116    
117                            runtime.addShutdownHook(
118                                    new DeleteFileShutdownHook(dlJCRStoreDirName));
119                    }
120                    else {
121                            dlJCRStoreDirName =
122                                    SystemProperties.get(SystemProperties.TMP_DIR) +
123                                            "/temp-dl-jcr-" + System.currentTimeMillis();
124    
125                            _dlJCRStoreDirName = dlJCRStoreDirName;
126                    }
127    
128                    try {
129                            FileUtil.copyDirectory(
130                                    new File(
131                                            PropsUtil.get(PropsKeys.JCR_JACKRABBIT_REPOSITORY_ROOT)),
132                                    new File(dlJCRStoreDirName));
133                    }
134                    catch (IOException ioe) {
135                            throw new RuntimeException(ioe);
136                    }
137            }
138    
139            protected void backupSearchIndices(boolean initialize) {
140                    for (long companyId : PortalInstances.getCompanyIds()) {
141                            String backupName = null;
142    
143                            if (initialize) {
144                                    backupName =
145                                            "temp-init-search-" + companyId + "-" +
146                                                    System.currentTimeMillis();
147                            }
148                            else {
149                                    backupName =
150                                            "temp-search-" + companyId + "-" +
151                                                    System.currentTimeMillis();
152                            }
153    
154                            try {
155                                    String backupFileName = SearchEngineUtil.backup(
156                                            companyId, SearchEngineUtil.SYSTEM_ENGINE_ID, backupName);
157    
158                                    if (initialize) {
159                                            Runtime runtime = Runtime.getRuntime();
160    
161                                            runtime.addShutdownHook(
162                                                    new DeleteFileShutdownHook(backupFileName));
163                                    }
164                            }
165                            catch (Exception e) {
166                                    throw new RuntimeException(e);
167                            }
168                            finally {
169                                    if (initialize) {
170                                            _initializedIndexNames.put(companyId, backupName);
171                                    }
172                                    else {
173                                            _indexNames.put(companyId, backupName);
174                                    }
175                            }
176                    }
177            }
178    
179            @Override
180            protected Object beforeClass(Description description) {
181                    Level level = Log4JLoggerTestUtil.setLoggerLevel(
182                            Table.class.getName(), Level.WARN);
183    
184                    try {
185                            if (ResetDatabaseUtil.initialize()) {
186                                    backupDLStores(true);
187                                    backupSearchIndices(true);
188                            }
189                            else {
190                                    restoreDLStores(true);
191                                    restoreSearchIndices(true);
192                            }
193                    }
194                    finally {
195                            Log4JLoggerTestUtil.setLoggerLevel(Table.class.getName(), level);
196                    }
197    
198                    return null;
199            }
200    
201            @Override
202            protected Level beforeMethod(Description description) {
203                    Level level = Log4JLoggerTestUtil.setLoggerLevel(
204                            Table.class.getName(), Level.WARN);
205    
206                    ResetDatabaseUtil.startRecording();
207    
208                    backupDLStores(false);
209                    backupSearchIndices(false);
210    
211                    return level;
212            }
213    
214            protected void restoreDLStores(boolean initialize) {
215                    FileUtil.deltree(PropsValues.DL_STORE_FILE_SYSTEM_ROOT_DIR);
216    
217                    String dlFileSystemStoreDirName = _initializedDLFileSystemStoreDirName;
218    
219                    if (!initialize) {
220                            dlFileSystemStoreDirName = _dlFileSystemStoreDirName;
221    
222                            _dlFileSystemStoreDirName = null;
223                    }
224    
225                    FileUtil.move(
226                            new File(dlFileSystemStoreDirName),
227                            new File(PropsValues.DL_STORE_FILE_SYSTEM_ROOT_DIR));
228    
229                    FileUtil.deltree(
230                            PropsUtil.get(PropsKeys.JCR_JACKRABBIT_REPOSITORY_ROOT));
231    
232                    String dlJCRStoreDirName = _initializedDLJCRStoreDirName;
233    
234                    if (!initialize) {
235                            dlJCRStoreDirName = _dlJCRStoreDirName;
236    
237                            _dlJCRStoreDirName = null;
238                    }
239    
240                    FileUtil.move(
241                            new File(dlJCRStoreDirName),
242                            new File(PropsUtil.get(PropsKeys.JCR_JACKRABBIT_REPOSITORY_ROOT)));
243            }
244    
245            protected void restoreSearchIndices(boolean initialize) {
246                    Map<Long, String> backupFileNames = _indexNames;
247    
248                    if (initialize) {
249                            backupFileNames = _initializedIndexNames;
250                    }
251    
252                    for (Map.Entry<Long, String> entry : backupFileNames.entrySet()) {
253                            String backupFileName = entry.getValue();
254    
255                            try {
256                                    SearchEngineUtil.restore(entry.getKey(), backupFileName);
257                            }
258                            catch (Exception e) {
259                                    throw new RuntimeException(e);
260                            }
261                            finally {
262                                    if (!initialize) {
263                                            try {
264                                                    SearchEngineUtil.removeBackup(
265                                                            entry.getKey(), backupFileName);
266                                            }
267                                            catch (SearchException e) {
268                                                    if (_log.isInfoEnabled()) {
269                                                            _log.info("Unable to remove backup", e);
270                                                    }
271                                            }
272                                    }
273                            }
274                    }
275    
276                    if (!initialize) {
277                            backupFileNames.clear();
278                    }
279            }
280    
281            private ResetDatabaseTestRule() {
282            }
283    
284            private static final Log _log = LogFactoryUtil.getLog(
285                    ResetDatabaseTestRule.class);
286    
287            private static String _initializedDLFileSystemStoreDirName;
288            private static String _initializedDLJCRStoreDirName;
289            private static final Map<Long, String> _initializedIndexNames =
290                    new HashMap<Long, String>();
291    
292            private String _dlFileSystemStoreDirName;
293            private String _dlJCRStoreDirName;
294            private final Map<Long, String> _indexNames = new HashMap<Long, String>();
295    
296            private class DeleteFileShutdownHook extends Thread {
297    
298                    public DeleteFileShutdownHook(String fileName) {
299                            _fileName = fileName;
300                    }
301    
302                    @Override
303                    public void run() {
304                            File file = new File(_fileName);
305    
306                            Queue<File> queue = new LinkedList<File>();
307    
308                            queue.offer(file);
309    
310                            while ((file = queue.poll()) != null) {
311                                    if (file.isFile()) {
312                                            file.delete();
313                                    }
314                                    else if (file.isDirectory()) {
315                                            File[] files = file.listFiles();
316    
317                                            if (files.length == 0) {
318                                                    file.delete();
319                                            }
320                                            else {
321                                                    queue.addAll(Arrays.asList(files));
322                                                    queue.add(file);
323                                            }
324                                    }
325                            }
326                    }
327    
328                    private final String _fileName;
329    
330            }
331    
332    }