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) {
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 fileName = arguments.get("db.file.name");
090    
091                    new DBLoader(databaseName, databaseType, sqlDir, fileName);
092            }
093    
094            public DBLoader(
095                    String databaseName, String databaseType, String sqlDir,
096                    String fileName) {
097    
098                    try {
099                            _databaseName = databaseName;
100                            _databaseType = databaseType;
101                            _sqlDir = sqlDir;
102                            _fileName = fileName;
103    
104                            if (_databaseType.equals("derby")) {
105                                    _loadDerby();
106                            }
107                            else if (_databaseType.equals("hypersonic")) {
108                                    _loadHypersonic();
109                            }
110                    }
111                    catch (Exception e) {
112                            e.printStackTrace();
113                    }
114            }
115    
116            private void _loadDerby() throws Exception {
117                    Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
118    
119                    Connection con = null;
120    
121                    try {
122                            con = DriverManager.getConnection(
123                                    "jdbc:derby:" + _sqlDir + "/" + _databaseName + ";create=true",
124                                    "", "");
125    
126                            if (Validator.isNull(_fileName)) {
127                                    _loadDerby(con, _sqlDir + "/portal/portal-derby.sql");
128                                    _loadDerby(con, _sqlDir + "/indexes.sql");
129                            }
130                            else {
131                                    _loadDerby(con, _sqlDir + "/" + _fileName);
132                            }
133                    }
134                    finally {
135                            if (con != null) {
136                                    con.close();
137                            }
138                    }
139    
140                    try {
141                            con = DriverManager.getConnection(
142                                    "jdbc:derby:" + _sqlDir + "/" + _databaseName +
143                                            ";shutdown=true",
144                                    "", "");
145                    }
146                    catch (SQLException sqle) {
147                            String sqlState = sqle.getSQLState();
148    
149                            if (!sqlState.equals("08006")) {
150                                    throw sqle;
151                            }
152                    }
153                    finally {
154                            if (con != null) {
155                                    con.close();
156                            }
157                    }
158            }
159    
160            private void _loadDerby(Connection con, String fileName) throws Exception {
161                    try (UnsyncBufferedReader unsyncBufferedReader =
162                                    new UnsyncBufferedReader(
163                                            new UnsyncStringReader(_fileUtil.read(fileName)))) {
164    
165                            StringBundler sb = new StringBundler();
166    
167                            String line = null;
168    
169                            while ((line = unsyncBufferedReader.readLine()) != null) {
170                                    if (line.startsWith("--")) {
171                                            continue;
172                                    }
173    
174                                    sb.append(line);
175    
176                                    if (line.endsWith(";")) {
177                                            String sql = sb.toString();
178    
179                                            sql = StringUtil.replace(
180                                                    sql,
181                                                    new String[] {"\\'", "\\\"", "\\\\", "\\n", "\\r"},
182                                                    new String[] {"''", "\"", "\\", "\n", "\r"});
183    
184                                            sql = sql.substring(0, sql.length() - 1);
185    
186                                            sb.setIndex(0);
187    
188                                            if (sql.startsWith("commit")) {
189                                                    continue;
190                                            }
191    
192                                            ij.runScript(
193                                                    con,
194                                                    new UnsyncByteArrayInputStream(
195                                                            sql.getBytes(StringPool.UTF8)),
196                                                    StringPool.UTF8, new DummyOutputStream(),
197                                                    StringPool.UTF8);
198                                    }
199                            }
200                    }
201            }
202    
203            private void _loadHypersonic() throws Exception {
204                    Class.forName("org.hsqldb.jdbcDriver");
205    
206                    // See LEP-2927. Appending ;shutdown=true to the database connection URL
207                    // guarantees that ${_databaseName}.log is purged.
208    
209                    try (Connection con = DriverManager.getConnection(
210                                    "jdbc:hsqldb:" + _sqlDir + "/" + _databaseName +
211                                            ";shutdown=true",
212                                    "sa", "")) {
213    
214                            if (Validator.isNull(_fileName)) {
215                                    loadHypersonic(con, _sqlDir + "/portal/portal-hypersonic.sql");
216                                    loadHypersonic(con, _sqlDir + "/indexes.sql");
217                            }
218                            else {
219                                    loadHypersonic(con, _sqlDir + "/" + _fileName);
220                            }
221    
222                            // Shutdown Hypersonic
223    
224                            try (Statement statement = con.createStatement()) {
225                                    statement.execute("SHUTDOWN COMPACT");
226                            }
227                    }
228    
229                    // Hypersonic will encode unicode characters twice, this will undo it
230    
231                    String content = _fileUtil.read(
232                            _sqlDir + "/" + _databaseName + ".script");
233    
234                    content = StringUtil.replace(content, "\\u005cu", "\\u");
235    
236                    _fileUtil.write(_sqlDir + "/" + _databaseName + ".script", content);
237            }
238    
239            private static FileImpl _fileUtil = FileImpl.getInstance();
240    
241            private String _databaseName;
242            private String _databaseType;
243            private String _fileName;
244            private String _sqlDir;
245    
246    }