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