001: /*
002: * $Id: Console.java,v 1.16 2006/01/10 21:02:37 ahimanikya Exp $
003: * =======================================================================
004: * Copyright (c) 2002-2003 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.tools;
042:
043: import java.io.BufferedReader;
044: import java.io.File;
045: import java.io.FileReader;
046: import java.io.FileWriter;
047: import java.io.IOException;
048: import java.io.InputStreamReader;
049: import java.io.PrintWriter;
050: import java.sql.Connection;
051: import java.sql.DriverManager;
052: import java.sql.ResultSet;
053: import java.sql.SQLException;
054: import java.sql.Statement;
055: import java.util.StringTokenizer;
056:
057: import org.axiondb.jdbc.ConnectionFactory;
058:
059: /**
060: * Simple console-based Axion client application.
061: * <p>
062: * Invoke via <code>java org.axiondb.tools.Console <i>dbname</i>
063: * [<i>location</i>]</code>.
064: * </p>
065: *
066: * @version $Revision: 1.16 $ $Date: 2006/01/10 21:02:37 $
067: * @author Chuck Burdick
068: * @author Ahimanikya Satapathy
069: * @author Jonathan Giron
070: */
071: public class Console {
072: public Console(String dbName, PrintWriter writer)
073: throws SQLException {
074: this (dbName, null, writer);
075: }
076:
077: public Console(String dbName, String dbLoc, PrintWriter writer)
078: throws SQLException {
079: if (writer == null) {
080: throw new NullPointerException(
081: "Must provide PrintWriter for output");
082: }
083: _writer = writer;
084: _dbLoc = dbLoc;
085: _dbName = dbName;
086: connect();
087:
088: _report = new BaseReport(_writer);
089: }
090:
091: private void connect() throws SQLException {
092: if (_dbName == null) {
093: throw new NullPointerException("Must provide database name");
094: }
095: StringBuffer buf = new StringBuffer();
096: buf.append(ConnectionFactory.URL_PREFIX);
097: buf.append(_dbName);
098: if (_dbLoc != null) {
099: buf.append(":");
100: buf.append(_dbLoc);
101: }
102: try {
103: _conn = DriverManager.getConnection(buf.toString());
104: _stmt = _conn.createStatement();
105: } catch (SQLException e) {
106: cleanUp();
107: throw e;
108: }
109: }
110:
111: public Connection getConnection() {
112: return _conn;
113: }
114:
115: public void execute(String input) throws SQLException {
116: if (input != null) {
117: input = input.trim();
118: if (input.length() != 0) {
119: while (input.endsWith(";")) {
120: input = input.substring(0, input.length() - 1)
121: .trim();
122: }
123:
124: StringTokenizer tokens = new StringTokenizer(input);
125:
126: String token = null;
127: if (tokens.hasMoreTokens()) {
128: token = tokens.nextToken().toUpperCase();
129: }
130:
131: if (token.equals("DESCRIBE") || token.equals("DESC")) {
132: consumeToken(tokens, "TABLE");
133: describeTable(getToken(tokens, true));
134:
135: } else if (token.equals("LIST")) {
136: listTables(getToken(tokens, false));
137: } else if (token.equals("SHOW")) {
138: if (tokens.hasMoreTokens()) {
139: token = tokens.nextToken().toUpperCase();
140: } else {
141: throw new IllegalArgumentException(
142: "Parser Error: Expected TABLES, DBLINKS, INDICES, INDEXES found EOF");
143: }
144:
145: if (token.equals("TABLE")) {
146: consumeToken(tokens, "PROPERTIES");
147: showTableProperties(getToken(tokens, false));
148: } else if (token.equals("DBLINKS")) {
149: showLinks(getToken(tokens, false));
150: } else if (token.equals("INDICES")
151: || token.equals("INDEXES")) {
152: showIndices(getToken(tokens, false));
153: }
154: } else if (token.equals("SET")) {
155: consumeToken(tokens, "AUTOCOMMIT");
156: if (tokens.hasMoreTokens()) {
157: token = tokens.nextToken().toUpperCase();
158: } else {
159: throw new IllegalArgumentException(
160: "Parser Error: Expected AUTOCIMMIT [ON|OFF]");
161: }
162:
163: if (token.equals("ON")) {
164: _conn.setAutoCommit(true);
165: } else if (token.equals("OFF")) {
166: _conn.setAutoCommit(false);
167: }
168: } else if (token.equals("COMMIT")) {
169: if (_conn.getAutoCommit() == false) {
170: _conn.commit();
171: }
172: } else if (token.equals("ROLLBACK")) {
173: if (_conn.getAutoCommit() == false) {
174: _conn.rollback();
175: }
176: } else if (token.equals("RESET")) {
177: if (_conn.isClosed() == false) {
178: cleanUp();
179: connect();
180: }
181: } else if (input.startsWith("@")) {
182: String filename = input.substring(1);
183: File batch = null;
184: BufferedReader reader = null;
185: try {
186: batch = new File(filename);
187: reader = new BufferedReader(new FileReader(
188: batch));
189: BatchSqlCommandRunner runner = new BatchSqlCommandRunner(
190: getConnection(), _writer);
191: runner.runCommands(reader);
192: _writer.println("Successfully loaded file "
193: + batch);
194: } catch (IOException e) {
195: _writer.println("Error reading file "
196: + filename);
197: _report.reportException(e);
198: } catch (SQLException e) {
199: _report.reportException(e);
200: } finally {
201: try {
202: reader.close();
203: } catch (Exception e) {
204: }
205: reader = null;
206: batch = null;
207: }
208: } else {
209: executeSql(input);
210: }
211: }
212: }
213: }
214:
215: private String getToken(StringTokenizer tokens, boolean throwErr)
216: throws SQLException {
217: if (tokens.hasMoreTokens()) {
218: return tokens.nextToken();
219: }
220: if (throwErr) {
221: throw new SQLException("Parser Error: found EOF");
222: }
223: return "";
224: }
225:
226: private void consumeToken(StringTokenizer tokens, String keyword)
227: throws SQLException {
228: String token;
229: if (tokens.hasMoreTokens()) {
230: token = tokens.nextToken().toUpperCase();
231: if (!token.equals(keyword)) {
232: throw new SQLException(
233: "Parser Error: Unrecognized Token");
234: }
235: } else {
236: throw new SQLException("Parser Error: Expected " + keyword
237: + " found EOF");
238: }
239: }
240:
241: private void showLinks(String linkname) {
242: StringBuffer query = new StringBuffer(
243: "select LINK_NAME, LINK_URL, LINK_USERNAME from AXION_DB_LINKS");
244: if (linkname != null && linkname.trim().length() != 0) {
245: query.append(" where LINK_NAME ");
246: query.append((linkname.indexOf("%") == -1) ? "= '"
247: : "like '");
248: query.append(linkname.toUpperCase()).append("'");
249: }
250: executeSql(query.toString());
251: }
252:
253: private void showTableProperties(String tablename) {
254: String query = "select PROPERTY_NAME, PROPERTY_VALUE from AXION_TABLE_PROPERTIES "
255: + "where TABLE_NAME = '"
256: + tablename.toUpperCase()
257: + "' ORDER BY PROPERTY_NAME";
258: executeSql(query);
259: }
260:
261: private void describeTable(String table) {
262: // here's the axion-centric but terse form
263: String query = "select COLUMN_NAME, TYPE_NAME, COLUMN_SIZE, DECIMAL_DIGITS, "
264: + "IS_NULLABLE from AXION_COLUMNS where TABLE_NAME = '"
265: + table.toUpperCase() + "' order by ORDINAL_POSITION";
266: executeSql(query);
267: }
268:
269: private void listTables(String type) {
270: // here's the axion-centric but terse form
271: String query = "select TABLE_NAME, TABLE_TYPE from AXION_TABLES "
272: + "where TABLE_TYPE LIKE '%"
273: + type.toUpperCase()
274: + "%' " + "order by TABLE_NAME";
275: executeSql(query);
276: }
277:
278: private void showIndices(String indexName) {
279: StringBuffer query = new StringBuffer(
280: "select index_name, table_name, column_name, "
281: + "index_type from AXION_INDEX_INFO order by INDEX_NAME");
282:
283: if (indexName != null && indexName.trim().length() != 0) {
284: query.append(" where index_name ");
285: query.append((indexName.indexOf("%") == -1) ? "= '"
286: : "like '");
287: query.append(indexName.toUpperCase()).append("'");
288: }
289: executeSql(query.toString());
290: }
291:
292: private void executeSql(String sql) {
293: try {
294: long startTime = System.currentTimeMillis();
295: boolean hasResultSet = _stmt.execute(sql);
296: long endTime = System.currentTimeMillis();
297: if (hasResultSet) {
298: ResultSet rset = _stmt.getResultSet();
299: _report.reportResultSet(rset);
300: rset.close();
301: } else {
302: int ct = _stmt.getUpdateCount();
303: _report.reportUpdateCount(ct);
304: }
305: _writer.println("Execution time: " + (endTime - startTime)
306: + " ms.");
307: } catch (SQLException e) {
308: _report.reportException(e);
309: }
310: }
311:
312: public void cleanUp() {
313: try {
314: _stmt.close();
315: } catch (Exception e) {
316: }
317: try {
318: _conn.close();
319: } catch (Exception e) {
320: }
321: }
322:
323: public static void main(String[] args) {
324: String input = null;
325: boolean quit = false;
326:
327: if (args.length < 1) {
328: System.out
329: .println("Usage: java org.axiondb.tools.Console dbName");
330: System.out
331: .println(" or java org.axiondb.tools.Console dbName location");
332: System.out
333: .println(" or java org.axiondb.tools.Console dbName location outputFilePath");
334: } else {
335: Console axion = null;
336: BufferedReader in = new BufferedReader(
337: new InputStreamReader(System.in));
338: try {
339: PrintWriter out = new PrintWriter(System.out, true);
340: switch (args.length) {
341: case 3:
342: try {
343: PrintWriter fw = new PrintWriter(
344: new FileWriter(new File(args[2])), true);
345: out = fw;
346: } catch (Exception ex) {
347: // output will be written by default to System.out
348: }
349: axion = new Console(args[0], args[1], out);
350: break;
351:
352: case 2:
353: axion = new Console(args[0], args[1], out);
354: break;
355:
356: case 1:
357: axion = new Console(args[0], out);
358: break;
359:
360: default:
361: break;
362: }
363:
364: System.out.println();
365: System.out.println("Type 'quit' to quit the program.");
366: while (!quit) {
367: System.out.print(_PROMPT);
368: input = in.readLine();
369: quit = ("quit".equalsIgnoreCase(input) || "exit"
370: .equalsIgnoreCase(input));
371: if (!quit && input != null
372: && !"".equals(input.trim())) {
373: try {
374: axion.execute(input);
375: } catch (SQLException sqle) {
376: sqle.printStackTrace();
377: }
378: }
379: }
380: } catch (SQLException sqle) {
381: System.out.println("Unable to connect to database");
382: sqle.printStackTrace();
383: } catch (IOException ioe) {
384: System.out.println("Error while reading input");
385: ioe.printStackTrace();
386: } finally {
387: try {
388: axion.cleanUp();
389: } catch (Exception e) {
390: }
391: }
392: }
393: }
394:
395: private Connection _conn = null;
396: private Statement _stmt = null;
397: private PrintWriter _writer = null;
398: private BaseReport _report = null;
399: private String _dbName = null;
400: private String _dbLoc = null;
401:
402: private static final String _PROMPT = "axion> ";
403: static {
404: try {
405: Class.forName("org.axiondb.jdbc.AxionDriver");
406: } catch (ClassNotFoundException e) {
407: }
408: }
409: }
|