KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > continuent > sequoia > console > text > module > VirtualDatabaseConsole


1 /**
2  * Sequoia: Database clustering technology.
3  * Copyright (C) 2002-2004 French National Institute For Research In Computer
4  * Science And Control (INRIA).
5  * Copyright (C) 2005 AmicoSoft, Inc. dba Emic Networks
6  * Contact: sequoia@continuent.org
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  * Initial developer(s): Emmanuel Cecchet.
21  * Contributor(s): Mathieu Peltier, Nicolas Modrzyk.
22  */

23
24 package org.continuent.sequoia.console.text.module;
25
26 import java.sql.Connection JavaDoc;
27 import java.sql.DriverManager JavaDoc;
28 import java.sql.PreparedStatement JavaDoc;
29 import java.sql.ResultSet JavaDoc;
30 import java.sql.SQLException JavaDoc;
31 import java.sql.Savepoint JavaDoc;
32 import java.util.Hashtable JavaDoc;
33
34 import org.continuent.sequoia.common.i18n.ConsoleTranslate;
35 import org.continuent.sequoia.common.util.Constants;
36 import org.continuent.sequoia.console.text.Console;
37 import org.continuent.sequoia.console.text.ConsoleException;
38 import org.continuent.sequoia.console.text.ConsoleLauncher;
39 import org.continuent.sequoia.console.text.commands.ConsoleCommand;
40 import org.continuent.sequoia.console.text.formatter.ResultSetFormatter;
41
42 /**
43  * Sequoia Controller Virtual Database Console module.
44  *
45  * @author <a HREF="mailto:Emmanuel.Cecchet@inria.fr">Emmanuel Cecchet </a>
46  * @author <a HREF="mailto:Mathieu.Peltier@inrialpes.fr">Mathieu Peltier </a>
47  * @author <a HREF="mailto:Nicolas.Modrzyk@inrialpes.fr">Nicolas Modrzyk </a>
48  * @version 1.0
49  */

50 public class VirtualDatabaseConsole extends AbstractConsoleModule
51 {
52   private Connection JavaDoc connection = null;
53   /**
54    * contains a hash of <String, SavePoint> to handle savepoints (used by
55    * SetSavePoint and Rollback commands)
56    */

57   private Hashtable JavaDoc savePoints = new Hashtable JavaDoc();
58
59   /** Default query timeout. */
60   private int timeout = 60;
61
62   private int fetchsize = 0;
63
64   private int maxrows = 0;
65
66   private String JavaDoc login;
67   private String JavaDoc url;
68
69   // for backwards compatiblity, multiline statement is disabled by default
70
private boolean multilineStatementsEnabled = false;
71   // request delimiter to use when multiline statement is enabled
72
private String JavaDoc delimiter = DEFAULT_REQUEST_DELIMITER;
73   private static final String JavaDoc DEFAULT_REQUEST_DELIMITER = ";";
74   // a buffer used when multiline statement is enabled to keep in
75
// memory the statement across each handlePrompt()
76
private StringBuffer JavaDoc currentRequest = new StringBuffer JavaDoc("");
77
78   /**
79    * Creates a new <code>VirtualDatabaseAdmin</code> instance. Loads the
80    * driver
81    *
82    * @param console console console
83    */

84   public VirtualDatabaseConsole(Console console)
85   {
86     super(console);
87     try
88     {
89       Class.forName(System.getProperty("console.driver",
90           "org.continuent.sequoia.driver.Driver"));
91     }
92     catch (Exception JavaDoc e)
93     {
94       console.printError(ConsoleTranslate.get(
95           "sql.login.cannot.load.driver", ConsoleLauncher.PRODUCT_NAME), e);
96       Runtime.getRuntime().exit(1);
97     }
98     if (console.isInteractive())
99       console.println(ConsoleTranslate.get("sql.login.loaded.driver",
100           new String JavaDoc[] {ConsoleLauncher.PRODUCT_NAME, Constants.VERSION}));
101   }
102
103   /**
104    * Get the JDBC connection used by the sql console.
105    *
106    * @return a JDBC connection
107    */

108   public Connection JavaDoc getConnection()
109   {
110     return connection;
111   }
112
113   /**
114    * Create a new connection from the driver.
115    *
116    * @param url the Sequoia url
117    * @param login the login to use to open the connection
118    * @param password the password to use to open the connection
119    * @return a new connection
120    * @throws ConsoleException if login failed
121    */

122   public Connection JavaDoc createConnection(String JavaDoc url, String JavaDoc login, String JavaDoc password)
123       throws ConsoleException
124   {
125     try
126     {
127       return DriverManager.getConnection(url, login, password);
128     }
129     catch (Exception JavaDoc e)
130     {
131       throw new ConsoleException(ConsoleTranslate.get(
132           "sql.login.connection.failed", new String JavaDoc[]{url, e.getMessage()}));
133     }
134   }
135
136   /**
137    * Executes a SQL statement.
138    *
139    * @param request the SQL request to execute
140    * @param displayResult <code>true</code> if the result must be printed on
141    * the standard output
142    */

143   public synchronized void execSQL(String JavaDoc request, boolean displayResult)
144   {
145     PreparedStatement JavaDoc stmt = null;
146     try
147     {
148       stmt = connection.prepareStatement(request);
149       stmt.setQueryTimeout(timeout);
150       if (fetchsize != 0)
151         stmt.setFetchSize(fetchsize);
152       if (maxrows != 0)
153         stmt.setMaxRows(maxrows);
154
155       long start = System.currentTimeMillis();
156       long end;
157       if (request.toLowerCase().matches("^(\\(|\\s+)*select.*"))
158       {
159         ResultSet JavaDoc rs = stmt.executeQuery();
160         end = System.currentTimeMillis();
161         if (displayResult)
162           ResultSetFormatter.formatAndDisplay(rs, fetchsize, console);
163       }
164       else
165       {
166         boolean hasResult = stmt.execute();
167         end = System.currentTimeMillis();
168
169         int updatedRows;
170         do
171         {
172           updatedRows = -1;
173           if (hasResult)
174           {
175             ResultSet JavaDoc rs = stmt.getResultSet();
176             if (displayResult)
177               ResultSetFormatter.formatAndDisplay(rs, fetchsize, console);
178             rs.close();
179           }
180           else
181           {
182             updatedRows = stmt.getUpdateCount();
183             if (displayResult)
184               console.printInfo(ConsoleTranslate.get("sql.display.affected.rows",
185                   updatedRows));
186           }
187           hasResult = stmt.getMoreResults();
188           updatedRows = stmt.getUpdateCount();
189         }
190         while (hasResult || (updatedRows != -1));
191       }
192       console.printInfo(ConsoleTranslate.get("sql.display.query.time",
193           new Long JavaDoc[]{new Long JavaDoc((end - start) / 1000),
194               new Long JavaDoc((end - start) % 1000)}));
195     }
196     catch (Exception JavaDoc e)
197     {
198       console.printError(ConsoleTranslate.get("sql.command.sqlquery.error", e),
199           e);
200     }
201     finally
202     {
203       try
204       {
205         stmt.close();
206       }
207       catch (Exception JavaDoc ignore)
208       {
209       }
210     }
211   }
212
213   /**
214    * Connects to a virtual database.
215    */

216   public void handlePrompt()
217   {
218     while (!quit)
219     {
220       try
221       {
222         String JavaDoc cmd = console.readLine(this.getPromptString());
223         if (cmd == null)
224         {
225           quit();
226           break;
227         }
228
229         if (cmd.length() == 0)
230           continue;
231
232         ConsoleCommand currentCommand = findConsoleCommand(cmd,
233             getHashCommands());
234
235         if (currentCommand == null)
236         {
237           if (multilineStatementsEnabled)
238           {
239             // append a whitespace beacuse console.readLine() trim the cmd
240
currentRequest.append(" ").append(cmd);
241             if (currentRequest.toString().endsWith(delimiter))
242             {
243               String JavaDoc request = removeDelimiterAndTrim(currentRequest.toString());
244               execSQL(request, true);
245               currentRequest = new StringBuffer JavaDoc("");
246             }
247           }
248           else
249           {
250             execSQL(cmd, true);
251           }
252         }
253         else
254         {
255           currentCommand.execute(cmd.substring(
256               currentCommand.getCommandName().length()).trim());
257         }
258       }
259       catch (Exception JavaDoc e)
260       {
261         console.printError(ConsoleTranslate.get("sql.display.exception", e), e);
262         if ((e instanceof RuntimeException JavaDoc)
263             || (!console.isInteractive() && console.isExitOnError()))
264         {
265           System.exit(1);
266         }
267       }
268     }
269   }
270
271   /**
272    * Removes the delimiter at the end of the request and trims the resulting
273    * substring.
274    *
275    * @param request the SQL request
276    * @return a String representing the SQL request without its delimiter
277    * @see #delimiter
278    */

279   private String JavaDoc removeDelimiterAndTrim(String JavaDoc request)
280   {
281     if (request == null)
282     {
283       return "";
284     }
285     return request.substring(0, request.length() - delimiter.length()).trim();
286   }
287
288   /**
289    * @see org.continuent.sequoia.console.text.module.AbstractConsoleModule#getDescriptionString()
290    */

291   public String JavaDoc getDescriptionString()
292   {
293     return "SQL Console";
294   }
295
296   /**
297    * @see org.continuent.sequoia.console.text.module.AbstractConsoleModule#getModuleID()
298    */

299   protected String JavaDoc getModuleID()
300   {
301     return "sql"; //$NON-NLS-1$
302
}
303
304   /**
305    * @see org.continuent.sequoia.console.text.module.AbstractConsoleModule#getPromptString()
306    */

307   public String JavaDoc getPromptString()
308   {
309     int ind1 = url.lastIndexOf('?');
310     int ind2 = url.lastIndexOf(';');
311     if (ind1 != -1 || ind2 != -1)
312     {
313       String JavaDoc prompt;
314       prompt = (ind1 != -1) ? url.substring(0, ind1) : url;
315       prompt = (ind2 != -1) ? url.substring(0, ind2) : url;
316       return prompt + " (" + login + ")";
317     }
318     else
319       return url + " (" + login + ")";
320   }
321
322   /**
323    * Get a <code>SavePoint</code> identified by its <code>name</code>
324    *
325    * @param name name fo the <code>SavePoint</code>
326    * @return a <code>SavePoint</code> or <code>null</code> if no
327    * <code>SavePoint</code> with such a name has been previously added
328    */

329   public Savepoint JavaDoc getSavePoint(String JavaDoc name)
330   {
331     return (Savepoint JavaDoc) savePoints.get(name);
332   }
333
334   /**
335    * add a <code>SavePoint</code>
336    *
337    * @param savePoint the <code>SavePoint</code> to add
338    * @throws SQLException if the <code>savePoint</code> is unnamed
339    */

340   public void addSavePoint(Savepoint JavaDoc savePoint) throws SQLException JavaDoc
341   {
342     savePoints.put(savePoint.getSavepointName(), savePoint);
343   }
344
345   /**
346    * Get the timeout value (in seconds)
347    *
348    * @return the timeout value (in seconds)
349    */

350   public int getTimeout()
351   {
352     return timeout;
353   }
354
355   /**
356    * Set the timeout value (in seconds)
357    *
358    * @param timeout new timeout value (in seconds)
359    */

360   public void setTimeout(int timeout)
361   {
362     this.timeout = timeout;
363   }
364
365   /**
366    * Get the fetchsize value
367    *
368    * @return the fetchsize value
369    */

370   public int getFetchsize()
371   {
372     return fetchsize;
373   }
374
375   /**
376    * Set the fetchsize
377    *
378    * @param fetchsize new fetchsize value
379    */

380   public void setFetchsize(int fetchsize)
381   {
382     this.fetchsize = fetchsize;
383   }
384
385   /**
386    * Set the maxrows
387    *
388    * @param maxrows new maxrows value
389    */

390   public void setMaxrows(int maxrows)
391   {
392     this.maxrows = maxrows;
393   }
394
395   /**
396    * @see org.continuent.sequoia.console.text.module.AbstractConsoleModule#login(java.lang.String[])
397    */

398   public void login(String JavaDoc[] params) throws Exception JavaDoc
399   {
400     quit = false;
401
402     login = null;
403     url = (params.length > 0 && params[0] != null) ? params[0].trim() : null;
404     try
405     {
406       if ((url == null) || url.trim().equals(""))
407       {
408         url = console.readLine(ConsoleTranslate
409             .get("sql.login.prompt.url", ConsoleLauncher.PRODUCT_NAME));
410         if (url == null)
411           return;
412       }
413       login = console.readLine(ConsoleTranslate.get("sql.login.prompt.user"));
414       if (login == null)
415         return;
416       String JavaDoc password = console.readPassword(ConsoleTranslate
417           .get("sql.login.prompt.password"));
418       if (password == null)
419         return;
420
421       connection = createConnection(url, login, password);
422
423       // Change console reader completor
424
console.getConsoleReader().removeCompletor(
425           console.getControllerModule().getCompletor());
426       console.getConsoleReader().addCompletor(this.getCompletor());
427     }
428     catch (ConsoleException e)
429     {
430       throw e;
431     }
432     catch (Exception JavaDoc e)
433     {
434       throw new ConsoleException(ConsoleTranslate.get("sql.login.exception", e));
435     }
436   }
437
438   /**
439    * @see org.continuent.sequoia.console.text.module.AbstractConsoleModule#quit()
440    */

441   public void quit()
442   {
443     if (connection != null)
444     {
445       try
446       {
447         connection.close();
448       }
449       catch (Exception JavaDoc e)
450       {
451         // ignore
452
}
453     }
454     super.quit();
455   }
456
457   /**
458    * @see org.continuent.sequoia.console.text.module.AbstractConsoleModule#help()
459    */

460   public void help()
461   {
462     super.help();
463     console.println();
464     console.println(ConsoleTranslate.get("sql.command.description"));
465   }
466
467   /**
468    * Sets the request delimiter to use when multiline statement is enabled.
469    *
470    * @param delimiter the String to use as request delimiter
471    * @see #DEFAULT_REQUEST_DELIMITER
472    */

473   public void setRequestDelimiter(String JavaDoc delimiter)
474   {
475     this.delimiter = delimiter;
476   }
477
478   /**
479    * Returns the request delimiter
480    *
481    * @return a String representing the request delimiter
482    */

483   public String JavaDoc getRequestDelimiter()
484   {
485     return delimiter;
486   }
487
488   /**
489    * Enables multiline statements to be able to write one statement on several
490    * lines. A multiline statement is executed when the user inputs the request
491    * delimiter String at the end of a line. By default multiline statement is
492    * disabled (for backwards compatibility)
493    *
494    * @param multilineStatementsEnabled <code>true</code> if multiline
495    * statement must be enabled, <code>false</code> else
496    */

497   public void enableMultilineStatement(boolean multilineStatementsEnabled)
498   {
499     this.multilineStatementsEnabled = multilineStatementsEnabled;
500   }
501 }
502
Popular Tags