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.tools;
016    
017    import com.liferay.portal.kernel.io.DummyOutputStream;
018    import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
019    import com.liferay.portal.kernel.io.unsync.UnsyncByteArrayInputStream;
020    import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
021    import com.liferay.portal.kernel.util.StringBundler;
022    import com.liferay.portal.kernel.util.StringPool;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.util.FileImpl;
026    
027    import java.io.FileReader;
028    
029    import java.sql.Connection;
030    import java.sql.DriverManager;
031    import java.sql.PreparedStatement;
032    import java.sql.SQLException;
033    import java.sql.Statement;
034    
035    import java.util.Map;
036    
037    import org.apache.derby.tools.ij;
038    
039    /**
040     * @author Brian Wing Shun Chan
041     */
042    public class DBLoader {
043    
044            public static void loadHypersonic(Connection con, String fileName)
045                    throws Exception {
046    
047                    try (UnsyncBufferedReader unsyncBufferedReader =
048                                    new UnsyncBufferedReader(new FileReader(fileName))) {
049    
050                            StringBundler sb = new StringBundler();
051    
052                            String line = null;
053    
054                            while ((line = unsyncBufferedReader.readLine()) != null) {
055                                    if (line.startsWith("//")) {
056                                            continue;
057                                    }
058    
059                                    sb.append(line);
060    
061                                    if (line.endsWith(";")) {
062                                            String sql = sb.toString();
063    
064                                            sql = StringUtil.replace(
065                                                    sql, new String[] {"\\\"", "\\\\", "\\n", "\\r"},
066                                                    new String[] {"\"", "\\", "\\u000a", "\\u000a"});
067    
068                                            sb.setIndex(0);
069    
070                                            try (PreparedStatement ps = con.prepareStatement(sql)) {
071                                                    ps.executeUpdate();
072                                            }
073                                            catch (Exception e) {
074                                                    System.out.println(sql);
075    
076                                                    throw e;
077                                            }
078                                    }
079                            }
080                    }
081            }
082    
083            public static void main(String[] args) throws Exception {
084                    Map<String, String> arguments = ArgumentsUtil.parseArguments(args);
085    
086                    String databaseName = arguments.get("db.database.name");
087                    String databaseType = arguments.get("db.database.type");
088                    String sqlDir = arguments.get("db.sql.dir");
089                    String fileNames = arguments.get("db.file.names");
090    
091                    try {
092                            new DBLoader(databaseName, databaseType, sqlDir, fileNames);
093                    }
094                    catch (Exception e) {
095                            ArgumentsUtil.processMainException(arguments, e);
096                    }
097            }
098    
099            public DBLoader(
100                            String databaseName, String databaseType, String sqlDir,
101                            String fileNames)
102                    throws Exception {
103    
104                    _databaseName = databaseName;
105                    _databaseType = databaseType;
106                    _sqlDir = sqlDir;
107                    _fileNames = fileNames;
108    
109                    if (_databaseType.equals("derby")) {
110                            _loadDerby();
111                    }
112                    else if (_databaseType.equals("hypersonic")) {
113                            _loadHypersonic();
114                    }
115            }
116    
117            private void _loadDerby() throws Exception {
118                    Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
119    
120                    Connection con = null;
121    
122                    try {
123                            con = DriverManager.getConnection(
124                                    "jdbc:derby:" + _sqlDir + "/" + _databaseName + ";create=true",
125                                    "", "");
126    
127                            if (Validator.isNull(_fileNames)) {
128                                    _loadDerby(con, _sqlDir + "/portal/portal-derby.sql");
129                                    _loadDerby(con, _sqlDir + "/indexes.sql");
130                            }
131                            else {
132                                    for (String fileName : StringUtil.split(_fileNames)) {
133                                            _loadDerby(con, _sqlDir + "/" + fileName);
134                                    }
135                            }
136                    }
137                    finally {
138                            if (con != null) {
139                                    con.close();
140                            }
141                    }
142    
143                    try {
144                            con = DriverManager.getConnection(
145                                    "jdbc:derby:" + _sqlDir + "/" + _databaseName +
146                                            ";shutdown=true",
147                                    "", "");
148                    }
149                    catch (SQLException sqle) {
150                            String sqlState = sqle.getSQLState();
151    
152                            if (!sqlState.equals("08006")) {
153                                    throw sqle;
154                            }
155                    }
156                    finally {
157                            if (con != null) {
158                                    con.close();
159                            }
160                    }
161            }
162    
163            private void _loadDerby(Connection con, String fileName) throws Exception {
164                    try (UnsyncBufferedReader unsyncBufferedReader =
165                                    new UnsyncBufferedReader(
166                                            new UnsyncStringReader(_fileUtil.read(fileName)))) {
167    
168                            StringBundler sb = new StringBundler();
169    
170                            String line = null;
171    
172                            while ((line = unsyncBufferedReader.readLine()) != null) {
173                                    if (line.startsWith("--")) {
174                                            continue;
175                                    }
176    
177                                    sb.append(line);
178    
179                                    if (line.endsWith(";")) {
180                                            String sql = sb.toString();
181    
182                                            sql = StringUtil.replace(
183                                                    sql,
184                                                    new String[] {"\\'", "\\\"", "\\\\", "\\n", "\\r"},
185                                                    new String[] {"''", "\"", "\\", "\n", "\r"});
186    
187                                            sql = sql.substring(0, sql.length() - 1);
188    
189                                            sb.setIndex(0);
190    
191                                            if (sql.startsWith("commit")) {
192                                                    continue;
193                                            }
194    
195                                            ij.runScript(
196                                                    con,
197                                                    new UnsyncByteArrayInputStream(
198                                                            sql.getBytes(StringPool.UTF8)),
199                                                    StringPool.UTF8, new DummyOutputStream(),
200                                                    StringPool.UTF8);
201                                    }
202                            }
203                    }
204            }
205    
206            private void _loadHypersonic() throws Exception {
207                    Class.forName("org.hsqldb.jdbcDriver");
208    
209                    // See LEP-2927. Appending ;shutdown=true to the database connection URL
210                    // guarantees that ${_databaseName}.log is purged.
211    
212                    try (Connection con = DriverManager.getConnection(
213                                    "jdbc:hsqldb:" + _sqlDir + "/" + _databaseName +
214                                            ";shutdown=true",
215                                    "sa", "")) {
216    
217                            if (Validator.isNull(_fileNames)) {
218                                    loadHypersonic(con, _sqlDir + "/portal/portal-hypersonic.sql");
219                                    loadHypersonic(con, _sqlDir + "/indexes.sql");
220                            }
221                            else {
222                                    for (String fileName : StringUtil.split(_fileNames)) {
223                                            loadHypersonic(con, _sqlDir + "/" + fileName);
224                                    }
225                            }
226    
227                            // Shutdown Hypersonic
228    
229                            try (Statement statement = con.createStatement()) {
230                                    statement.execute("SHUTDOWN COMPACT");
231                            }
232                    }
233    
234                    // Hypersonic will encode unicode characters twice, this will undo it
235    
236                    String content = _fileUtil.read(
237                            _sqlDir + "/" + _databaseName + ".script");
238    
239                    content = StringUtil.replace(content, "\\u005cu", "\\u");
240    
241                    _fileUtil.write(_sqlDir + "/" + _databaseName + ".script", content);
242            }
243    
244            private static final FileImpl _fileUtil = FileImpl.getInstance();
245    
246            private final String _databaseName;
247            private final String _databaseType;
248            private final String _fileNames;
249            private final String _sqlDir;
250    
251    }