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.rule.callback;
016    
017    import com.liferay.portal.kernel.io.unsync.UnsyncPrintWriter;
018    import com.liferay.portal.kernel.test.rule.callback.BaseTestCallback;
019    import com.liferay.portal.kernel.util.ReflectionUtil;
020    import com.liferay.portal.util.PropsValues;
021    
022    import java.io.File;
023    import java.io.IOException;
024    import java.io.PrintWriter;
025    
026    import java.nio.file.FileVisitResult;
027    import java.nio.file.Files;
028    import java.nio.file.Path;
029    import java.nio.file.Paths;
030    import java.nio.file.SimpleFileVisitor;
031    import java.nio.file.attribute.BasicFileAttributes;
032    
033    import java.sql.Connection;
034    import java.sql.DriverManager;
035    import java.sql.Statement;
036    
037    import java.util.concurrent.CountDownLatch;
038    import java.util.concurrent.TimeUnit;
039    
040    import org.hsqldb.server.Server;
041    import org.hsqldb.server.ServerConstants;
042    
043    import org.junit.runner.Description;
044    
045    /**
046     * @author William Newbury
047     * @author Shuyang Zhou
048     */
049    public class HypersonicServerTestCallback
050            extends BaseTestCallback<Server, Object> {
051    
052            public static final String DATABASE_URL_BASE =
053                    "jdbc:hsqldb:hsql://localhost/";
054    
055            public HypersonicServerTestCallback(String databaseName) {
056                    _databaseName = databaseName;
057            }
058    
059            @Override
060            public void afterClass(Description description, Server server)
061                    throws Exception {
062    
063                    try (Connection connection = DriverManager.getConnection(
064                                    DATABASE_URL_BASE + _databaseName, "sa", "");
065                            Statement statement = connection.createStatement()) {
066    
067                            statement.execute("SHUTDOWN COMPACT");
068                    }
069    
070                    server.stop();
071    
072                    deleteFolder(Paths.get(_HYPERSONIC_TEMP_DIR_NAME));
073            }
074    
075            @Override
076            public Server beforeClass(Description description) throws Exception {
077                    final CountDownLatch startCountDownLatch = new CountDownLatch(1);
078    
079                    Server server = new Server() {
080    
081                            @Override
082                            public int stop() {
083                                    try (PrintWriter logPrintWriter = getLogWriter();
084                                                    PrintWriter errPrintWriter = getErrWriter()) {
085    
086                                            int state = super.stop();
087    
088                                            if (!_shutdownCountDownLatch.await(1, TimeUnit.MINUTES)) {
089                                                    throw new IllegalStateException(
090                                                            "Unable to shut down Hypersonic " + _databaseName);
091                                            }
092    
093                                            return state;
094                                    }
095                                    catch (InterruptedException ie) {
096                                            return ReflectionUtil.throwException(ie);
097                                    }
098                            }
099    
100                            @Override
101                            protected synchronized void setState(int state) {
102                                    super.setState(state);
103    
104                                    if (state == ServerConstants.SERVER_STATE_ONLINE) {
105                                            startCountDownLatch.countDown();
106                                    }
107                                    else if (state == ServerConstants.SERVER_STATE_SHUTDOWN) {
108                                            _shutdownCountDownLatch.countDown();
109                                    }
110                            }
111    
112                            private final CountDownLatch _shutdownCountDownLatch =
113                                    new CountDownLatch(1);
114    
115                    };
116    
117                    try (Connection connection = DriverManager.getConnection(
118                                    PropsValues.JDBC_DEFAULT_URL, "sa", "");
119                            Statement statement = connection.createStatement()) {
120    
121                            statement.execute(
122                                    "BACKUP DATABASE TO '" + _HYPERSONIC_TEMP_DIR_NAME +
123                                            "' BLOCKING AS FILES");
124                    }
125    
126                    server.setErrWriter(
127                            new UnsyncPrintWriter(
128                                    new File(
129                                            _HYPERSONIC_TEMP_DIR_NAME, _databaseName + ".err.log")));
130                    server.setLogWriter(
131                            new UnsyncPrintWriter(
132                                    new File(
133                                            _HYPERSONIC_TEMP_DIR_NAME, _databaseName + ".std.log")));
134    
135                    server.setDatabaseName(0, _databaseName);
136                    server.setDatabasePath(0, _HYPERSONIC_TEMP_DIR_NAME + _databaseName);
137    
138                    server.start();
139    
140                    if (!startCountDownLatch.await(1, TimeUnit.MINUTES)) {
141                            throw new IllegalStateException(
142                                    "Unable to start up Hypersonic " + _databaseName);
143                    }
144    
145                    return server;
146            }
147    
148            protected void copyFile(
149                            String fileName, Path fromFolderPath, Path toFolderPath)
150                    throws IOException {
151    
152                    Path filePath = fromFolderPath.resolve(fileName);
153    
154                    if (Files.exists(filePath)) {
155                            Files.createDirectories(toFolderPath);
156    
157                            Files.copy(filePath, toFolderPath.resolve(fileName));
158                    }
159            }
160    
161            protected void deleteFolder(Path folderPath) throws IOException {
162                    if (!Files.exists(folderPath)) {
163                            return;
164                    }
165    
166                    Files.walkFileTree(
167                            folderPath,
168                            new SimpleFileVisitor<Path>() {
169    
170                                    @Override
171                                    public FileVisitResult postVisitDirectory(
172                                                    Path dirPath, IOException ioe)
173                                            throws IOException {
174    
175                                            if (ioe != null) {
176                                                    throw ioe;
177                                            }
178    
179                                            Files.delete(dirPath);
180    
181                                            return FileVisitResult.CONTINUE;
182                                    }
183    
184                                    @Override
185                                    public FileVisitResult visitFile(
186                                                    Path filePath, BasicFileAttributes basicFileAttributes)
187                                            throws IOException {
188    
189                                            Files.delete(filePath);
190    
191                                            return FileVisitResult.CONTINUE;
192                                    }
193    
194                            });
195            }
196    
197            private static final String _HYPERSONIC_TEMP_DIR_NAME =
198                    PropsValues.LIFERAY_HOME + "/data/hypersonic_temp/";
199    
200            private final String _databaseName;
201    
202    }