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(_HSQL_TEMP));
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                    Path hsqlHomePath = Paths.get(_HSQL_HOME);
118    
119                    Files.createDirectories(hsqlHomePath);
120    
121                    Path hsqlHomeTempPath = Paths.get(_HSQL_TEMP);
122    
123                    deleteFolder(hsqlHomeTempPath);
124    
125                    copyFile(_databaseName.concat(".log"), hsqlHomePath, hsqlHomeTempPath);
126                    copyFile(
127                            _databaseName.concat(".properties"), hsqlHomePath,
128                            hsqlHomeTempPath);
129                    copyFile(
130                            _databaseName.concat(".script"), hsqlHomePath, hsqlHomeTempPath);
131    
132                    server.setErrWriter(
133                            new UnsyncPrintWriter(
134                                    new File(_HSQL_TEMP, _databaseName + ".err.log")));
135                    server.setLogWriter(
136                            new UnsyncPrintWriter(
137                                    new File(_HSQL_TEMP, _databaseName + ".std.log")));
138    
139                    server.setDatabaseName(0, _databaseName);
140                    server.setDatabasePath(0, _HSQL_TEMP + _databaseName);
141    
142                    server.start();
143    
144                    if (!startCountDownLatch.await(1, TimeUnit.MINUTES)) {
145                            throw new IllegalStateException(
146                                    "Unable to start up Hypersonic " + _databaseName);
147                    }
148    
149                    return server;
150            }
151    
152            protected void copyFile(
153                            String fileName, Path fromFolderPath, Path toFolderPath)
154                    throws IOException {
155    
156                    Path filePath = fromFolderPath.resolve(fileName);
157    
158                    if (Files.exists(filePath)) {
159                            Files.createDirectories(toFolderPath);
160    
161                            Files.copy(filePath, toFolderPath.resolve(fileName));
162                    }
163            }
164    
165            protected void deleteFolder(Path folderPath) throws IOException {
166                    if (!Files.exists(folderPath)) {
167                            return;
168                    }
169    
170                    Files.walkFileTree(
171                            folderPath,
172                            new SimpleFileVisitor<Path>() {
173    
174                                    @Override
175                                    public FileVisitResult postVisitDirectory(
176                                                    Path dirPath, IOException ioe)
177                                            throws IOException {
178    
179                                            if (ioe != null) {
180                                                    throw ioe;
181                                            }
182    
183                                            Files.delete(dirPath);
184    
185                                            return FileVisitResult.CONTINUE;
186                                    }
187    
188                                    @Override
189                                    public FileVisitResult visitFile(
190                                                    Path filePath, BasicFileAttributes basicFileAttributes)
191                                            throws IOException {
192    
193                                            Files.delete(filePath);
194    
195                                            return FileVisitResult.CONTINUE;
196                                    }
197    
198                            });
199            }
200    
201            private static final String _HSQL_HOME =
202                    PropsValues.LIFERAY_HOME + "/data/hypersonic/";
203    
204            private static final String _HSQL_TEMP =
205                    PropsValues.LIFERAY_HOME + "/data/hypersonic_temp/";
206    
207            private final String _databaseName;
208    
209    }