KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > tools > dblook


1 /*
2
3    Derby - Class org.apache.derby.tools.dblook
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to You under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. 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  */

21
22 package org.apache.derby.tools;
23
24 import java.io.BufferedReader JavaDoc;
25 import java.io.StringReader JavaDoc;
26
27 import java.sql.DriverManager JavaDoc;
28 import java.sql.ResultSet JavaDoc;
29 import java.sql.Connection JavaDoc;
30 import java.sql.Statement JavaDoc;
31 import java.sql.PreparedStatement JavaDoc;
32 import java.sql.SQLException JavaDoc;
33 import java.sql.SQLWarning JavaDoc;
34 import java.sql.Timestamp JavaDoc;
35
36 import java.util.HashMap JavaDoc;
37 import java.util.StringTokenizer JavaDoc;
38 import java.util.ArrayList JavaDoc;
39
40 import org.apache.derby.iapi.tools.i18n.LocalizedResource;
41
42 import org.apache.derby.impl.tools.dblook.DB_Check;
43 import org.apache.derby.impl.tools.dblook.DB_Index;
44 import org.apache.derby.impl.tools.dblook.DB_Jar;
45 import org.apache.derby.impl.tools.dblook.DB_Key;
46 import org.apache.derby.impl.tools.dblook.DB_Table;
47 import org.apache.derby.impl.tools.dblook.DB_Schema;
48 import org.apache.derby.impl.tools.dblook.DB_Alias;
49 import org.apache.derby.impl.tools.dblook.DB_Trigger;
50 import org.apache.derby.impl.tools.dblook.DB_View;
51 import org.apache.derby.impl.tools.dblook.DB_GrantRevoke;
52 import org.apache.derby.impl.tools.dblook.Logs;
53
54 public final class dblook {
55
56     // DB2 enforces a maximum of 30 tables to be specified as part of
57
// the table list.
58
private static final int DB2_MAX_NUMBER_OF_TABLES = 30;
59
60     private Connection JavaDoc conn;
61     private static PreparedStatement JavaDoc getColNameFromNumberQuery;
62
63     // Mappings from id to name for schemas and tables (for ease
64
// of reference).
65
private static HashMap JavaDoc schemaMap;
66     private static HashMap JavaDoc tableIdToNameMap;
67
68     // Command-line Parameters.
69
private static String JavaDoc sourceDBUrl;
70     private static String JavaDoc ddlFileName;
71     private static String JavaDoc stmtDelimiter;
72     private static boolean appendLogs;
73     private static ArrayList JavaDoc tableList;
74     private static String JavaDoc schemaParam;
75     private static String JavaDoc targetSchema;
76     private static boolean skipViews;
77     private static boolean verbose;
78     private static String JavaDoc sourceDBName;
79
80     private static String JavaDoc lookLogName = "dblook.log";
81
82     private static LocalizedResource langUtil;
83
84     private static boolean sqlAuthorization;
85
86     /* ************************************************
87      * main:
88      * Initialize program state by creating a dblook object,
89      * and then start the DDL generation by calling "go".
90      * ****/

91
92     public static void main(String JavaDoc[] args) {
93
94         try {
95             new dblook(args);
96         } catch (Exception JavaDoc e) {
97         // All "normal" errors are logged and printed to
98
// console according to command line arguments,
99
// so if we get here, something unexpected must
100
// have happened; print to error stream.
101
e.printStackTrace();
102         }
103
104     }
105
106     /* ************************************************
107      * Constructor:
108      * Parse the command line, initialize logs, echo program variables,
109      * and load the Derby driver.
110      * @param args Array of dblook command-line arguments.
111      * ****/

112
113     public dblook(String JavaDoc[] args) throws Exception JavaDoc {
114
115         // Adjust the application in accordance with derby.ui.locale
116
// and derby.ui.codeset
117
langUtil = LocalizedResource.getInstance();
118
119         // Initialize class variables.
120
initState();
121
122         // Parse the command line.
123
if (!parseArgs(args)) {
124             System.out.println(lookupMessage("DBLOOK_Usage"));
125             return;
126         }
127
128         showVariables();
129
130         if (!loadDriver()) {
131         // Failed when loading the driver. We already logged
132
// the exception, so just return.
133
return;
134         }
135
136         schemaMap = new HashMap JavaDoc();
137         tableIdToNameMap = new HashMap JavaDoc();
138
139         // Now run the utility.
140
go();
141
142     }
143
144     /* ************************************************
145      * initState:
146      * Initialize class variables.
147      ****/

148
149     private void initState() {
150
151         sourceDBUrl = null;
152         ddlFileName = null;
153         stmtDelimiter = null;
154         appendLogs = false;
155         tableList = null;
156         targetSchema = null;
157         schemaParam = null;
158         skipViews = false;
159         verbose= false;
160         sourceDBName = null;
161         return;
162
163     }
164
165     /* ************************************************
166      * parseArgs:
167      * Parse the command-line arguments.
168      * @param args args[0] is the url for the source database.
169      * @return true if all parameters were loaded and the output
170      * files were successfully created; false otherwise.
171      ****/

172
173     private boolean parseArgs(String JavaDoc[] args) {
174
175         if (args.length < 2)
176         // must have minimum of 2 args: "-d" and "<dbUrl>".
177
return false;
178
179         int st = 0;
180         for (int i = 0; i < args.length; i++) {
181             st = loadParam(args, i);
182             if (st == -1)
183                 return false;
184             i = st;
185         }
186
187         if (sourceDBUrl == null) {
188         // must have at least a database url.
189
return false;
190         }
191
192         // At this point, all parameters should have been read into
193
// their respective class variables. Use those
194
// variables for some further processing.
195

196         // Setup logs.
197
boolean okay = Logs.initLogs(lookLogName, ddlFileName, appendLogs,
198             verbose, (stmtDelimiter == null ? ";" : stmtDelimiter));
199
200         // Get database name.
201
sourceDBName = extractDBNameFromUrl(sourceDBUrl);
202
203         // Set up schema restriction.
204
if ((schemaParam != null) && (schemaParam.length() > 0) &&
205             (schemaParam.charAt(0) != '"'))
206         // not quoted, so upper case, then add quotes.
207
{
208             targetSchema = addQuotes(expandDoubleQuotes(
209                 schemaParam.toUpperCase(java.util.Locale.ENGLISH)));
210         }
211         else
212             targetSchema = addQuotes(expandDoubleQuotes(stripQuotes(schemaParam)));
213         return okay;
214
215     }
216
217     /* ************************************************
218      * loadParam:
219      * Read in a flag and its corresponding values from
220      * list of command line arguments, starting at
221      * the start'th argument.
222      * @return The position of the argument that was
223      * most recently processed.
224      ****/

225
226     private int loadParam(String JavaDoc [] args, int start) {
227
228         if ((args[start].length() == 0) || args[start].charAt(0) != '-')
229         // starting argument should be a flag; if it's
230
// not, ignore it.
231
return start;
232
233         boolean haveVal = (args.length > start + 1);
234         switch (args[start].charAt(1)) {
235
236             case 'd':
237                 if (!haveVal)
238                     return -1;
239                 if (args[start].length() == 2) {
240                     sourceDBUrl = stripQuotes(args[++start]);
241                     return start;
242                 }
243                 return -1;
244
245             case 'z':
246                 if (!haveVal)
247                     return -1;
248                 if (args[start].length() == 2) {
249                     schemaParam = args[++start];
250                     return start;
251                 }
252                 return -1;
253
254             case 't':
255                 if (!haveVal)
256                     return -1;
257                 if (args[start].equals("-td")) {
258                     stmtDelimiter = args[++start];
259                     return start;
260                 }
261                 else if (args[start].equals("-t"))
262                 // list of tables.
263
return extractTableNamesFromList(args, start+1);
264                 return -1;
265
266             case 'o':
267                 if (!haveVal)
268                     return -1;
269                 if ((args[start].length() == 2) && (args[start+1].length() > 0)) {
270                     ddlFileName = args[++start];
271                     return start;
272                 }
273                 return -1;
274
275             case 'a':
276                 if (args[start].equals("-append")) {
277                     appendLogs = true;
278                     return start;
279                 }
280                 return -1;
281
282             case 'n':
283                 if (args[start].equals("-noview")) {
284                     skipViews = true;
285                     return start;
286                 }
287                 return -1;
288
289             case 'v':
290                 if (args[start].equals("-verbose")) {
291                     verbose = true;
292                     return start;
293                 }
294                 return -1;
295
296             default:
297                 return -1;
298
299         }
300
301     }
302
303     /* ************************************************
304      * loadDriver:
305      * Load derby driver.
306      * @param precondition sourceDBUrl has been loaded.
307      * @return false if anything goes wrong; true otherwise.
308      ****/

309
310     private boolean loadDriver() {
311
312         String JavaDoc derbyDriver = System.getProperty("driver");
313         if (derbyDriver == null) {
314             if (sourceDBUrl.indexOf(":net://") != -1)
315                 derbyDriver = "com.ibm.db2.jcc.DB2Driver";
316             else if (sourceDBUrl.startsWith("jdbc:derby://"))
317                derbyDriver = "org.apache.derby.jdbc.ClientDriver";
318             else
319                 derbyDriver = "org.apache.derby.jdbc.EmbeddedDriver";
320         }
321
322         try {
323             Class.forName(derbyDriver).newInstance();
324         }
325         catch (Exception JavaDoc e)
326         {
327             Logs.debug(e);
328             return false;
329         }
330
331         return true;
332     }
333
334     /* ************************************************
335      * extractDBNameFromUrl:
336      * Given a database url, parse out the actual name
337      * of the database. This is required for creation
338      * the DB2JJARS directory (the database name is part
339      * of the path to the jar).
340      * @param dbUrl The database url from which to extract the
341      * the database name.
342      * @return the name of the database (including its
343      * path, if provided) that is referenced by the url.
344      ****/

345
346     private String JavaDoc extractDBNameFromUrl(String JavaDoc dbUrl) {
347
348         if (dbUrl == null)
349         // shouldn't happen; ignore it here, as an error
350
// will be thrown we try to connect.
351
return "";
352
353         int start = dbUrl.indexOf("jdbc:derby:");
354         if (start == -1)
355         // not a valid url; just ignore it (an error
356
// will be thrown when we try to connect).
357
return "";
358
359         start = dbUrl.indexOf("://");
360         if (start == -1)
361         // standard url (jdbc:derby:<dbname>). Database
362
// name starts right after "derby:". The "6" in
363
// the following line is the length of "derby:".
364
start = dbUrl.indexOf("derby:") + 6;
365         else
366         // Network Server url. Database name starts right
367
// after next slash (":net://hostname:port/<dbname>).
368
// The "3" in the following line is the length of
369
// "://".
370
start = dbUrl.indexOf("/", start+3) + 1;
371
372         int stop = -1;
373         if (dbUrl.charAt(start) == '"') {
374         // database name is quoted; end of the name is the
375
// closing quote.
376
start++;
377             stop = dbUrl.indexOf("\"", start);
378         }
379         else {
380         // Database name ends with the start of a list of connection
381
// attributes. This list can begin with either a colon
382
// or a semi-colon.
383
stop = dbUrl.indexOf(":", start);
384             if (stop != -1) {
385                 if ((dbUrl.charAt(stop+1) == '/') ||
386                         (dbUrl.charAt(stop+1) == '\\'))
387                 // then this colon is part of the path (ex. "C:"),
388
// so ignore it.
389
stop = dbUrl.indexOf(":", stop+2);
390             }
391             int stop2 = dbUrl.length();
392             if (stop == -1)
393             // no colons; see if we can find a semi-colon.
394
stop = dbUrl.indexOf(";", start);
395             else
396                 stop2 = dbUrl.indexOf(";", start);
397             stop = (stop <= stop2 ? stop : stop2);
398         }
399
400         if (stop == -1)
401         // we have a url that ends with database name (no
402
// other attributes appended).
403
stop = dbUrl.length();
404
405         return dbUrl.substring(start, stop);
406
407     }
408
409     /* ************************************************
410      * extractTableNamesFromList:
411      * Given an array of command line arguments containing
412      * a list of table names beginning at start'th position,
413      * read the list of table names and store them as
414      * our target table list. Names without quotes are
415      * turned into ALL CAPS and then double quotes are
416      * added; names whcih already have double quotes are
417      * stored exactly as they are. NOTE: DB2 enforces
418      * maximum of 30 tables, and ignores the rest; so
419      * do we.
420      * @param args Array of command line arguments.
421      * @start Position of the start of the list of tables
422      * with the args array.
423      * @return The position of the last table name in
424      * the list of table names.
425      ****/

426
427     private int extractTableNamesFromList(String JavaDoc [] args,
428         int start)
429     {
430
431         int argIndex = start;
432         int count = 0;
433         tableList = new ArrayList JavaDoc();
434         while (argIndex < args.length) {
435
436             if (((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '-')) ||
437                 (++count > DB2_MAX_NUMBER_OF_TABLES))
438             // we're done with the table list.
439
break;
440
441             if ((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '"'))
442             // it's quoted.
443
tableList.add(addQuotes(expandDoubleQuotes(
444                     stripQuotes(args[argIndex++]))));
445             else
446             // not quoted, so make it all caps, then add
447
// quotes.
448
tableList.add(addQuotes(
449                     expandDoubleQuotes(args[argIndex++].toUpperCase(
450                     java.util.Locale.ENGLISH))));
451
452         }
453
454         if (tableList.size() == 0)
455             tableList = null;
456
457         return argIndex - 1;
458
459     }
460
461     /* ************************************************
462      * showVariables:
463      * Echo primary variables to output, so user can see
464      * what s/he specified.
465      ****/

466
467     private void showVariables() {
468
469         if (ddlFileName != null) {
470             Logs.reportString("============================\n");
471             Logs.reportMessage("DBLOOK_FileCreation");
472             if (verbose)
473                 writeVerboseOutput("DBLOOK_OutputLocation",
474                     ddlFileName);
475         }
476
477         Logs.reportMessage("DBLOOK_Timestamp",
478             new Timestamp JavaDoc(System.currentTimeMillis()).toString());
479         Logs.reportMessage("DBLOOK_DBName", sourceDBName);
480         Logs.reportMessage("DBLOOK_DBUrl", sourceDBUrl);
481         if (tableList != null)
482             Logs.reportMessage("DBLOOK_TargetTables");
483         if (schemaParam != null)
484             Logs.reportMessage("DBLOOK_TargetSchema", stripQuotes(schemaParam));
485         Logs.reportString("appendLogs: " + appendLogs + "\n");
486         return;
487
488     }
489
490     /* ************************************************
491      * go:
492      * Connect to the source database, prepare statements,
493      * and load a list of table id-to-name mappings. Then,
494      * generate the DDL for the various objects in the
495      * database by making calls to static methods of helper
496      * classes (one helper class for each type of database
497      * object). If a particular object type should not be
498      * generated (because of the user-specified command-
499      * line), then we enforce that here.
500      * @precondition all user-specified parameters have
501      * been loaded.
502      * @return DDL for the source database has been
503      * generated and printed to output, subject to
504      * user-specified restrictions.
505      * ****/

506
507     private void go()
508         throws Exception JavaDoc
509     {
510
511         try
512         {
513             // Connect to the database, prepare statements,
514
// and load id-to-name mappings.
515
this.conn = DriverManager.getConnection(sourceDBUrl);
516             prepForDump();
517
518             // Generate DDL.
519

520             // Start with schemas, since we might need them to
521
// exist for jars to load properly.
522
DB_Schema.doSchemas(this.conn,
523                 (tableList != null) && (targetSchema == null));
524
525             if (tableList == null) {
526             // Don't do these if user just wants table-related objects.
527
DB_Jar.doJars(sourceDBName, this.conn);
528                 DB_Alias.doProceduresAndFunctions(this.conn);
529             }
530
531             DB_Table.doTables(this.conn, tableIdToNameMap);
532             DB_Index.doIndexes(this.conn);
533             DB_Alias.doSynonyms(this.conn);
534             DB_Key.doKeys(this.conn);
535             DB_Check.doChecks(this.conn);
536
537             if (!skipViews)
538                 DB_View.doViews(this.conn);
539
540             DB_Trigger.doTriggers(this.conn);
541
542             DB_GrantRevoke.doAuthorizations(this.conn);
543
544             // That's it; we're done.
545
if (getColNameFromNumberQuery != null)
546                 getColNameFromNumberQuery.close();
547             Logs.cleanup();
548
549         }
550         catch (SQLException JavaDoc sqlE)
551         {
552             Logs.debug(sqlE);
553             Logs.debug(Logs.unRollExceptions(sqlE), (String JavaDoc)null);
554             Logs.cleanup();
555             return;
556         }
557         catch (Exception JavaDoc e)
558         {
559             Logs.debug(e);
560             Logs.cleanup();
561             return;
562         }
563         finally {
564         // Close our connection.
565
if (conn != null) {
566                 conn.commit();
567                 conn.close();
568             }
569         }
570
571     }
572
573     /* ************************************************
574      * prepForDump:
575      * Prepare any useful statements (i.e. statements that
576      * are required by more than one helper class) and load
577      * the id-to-name mappings for the source database.
578      ****/

579
580     private void prepForDump() throws Exception JavaDoc {
581
582         // We're only SELECTing throughout all of this, so no need
583
// to commit (plus, disabling commit makes it easier to
584
// have multiple ResultSets open on the same connection).
585
this.conn.setAutoCommit(false);
586
587         // Prepare statements.
588
getColNameFromNumberQuery = conn.prepareStatement(
589             "SELECT COLUMNNAME FROM SYS.SYSCOLUMNS WHERE " +
590             "REFERENCEID = ? AND COLUMNNUMBER = ?");
591
592         // Load list of user tables and table ids, for general use.
593
Statement JavaDoc stmt = conn.createStatement();
594         ResultSet JavaDoc rs = stmt.executeQuery("SELECT T.TABLEID, T.TABLENAME, " +
595                 "S.SCHEMANAME FROM SYS.SYSTABLES T, SYS.SYSSCHEMAS S " +
596                 "WHERE T.TABLETYPE = 'T' AND T.SCHEMAID = S.SCHEMAID");
597
598         while (rs.next()) {
599             String JavaDoc tableName = addQuotes(expandDoubleQuotes(rs.getString(2)));
600             String JavaDoc schemaName = addQuotes(expandDoubleQuotes(rs.getString(3)));
601             tableIdToNameMap.put(rs.getString(1),
602                 schemaName + "." + tableName);
603         }
604
605         // Load schema id's and names.
606
rs = stmt.executeQuery("SELECT SCHEMAID, SCHEMANAME FROM " +
607             "SYS.SYSSCHEMAS");
608         while (rs.next()) {
609             schemaMap.put(rs.getString(1),
610                 addQuotes(expandDoubleQuotes(rs.getString(2))));
611         }
612
613         // Check if sqlAuthorization mode is on. If so, need to generate
614
// authorization statements.
615
rs = stmt.executeQuery("VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY" +
616                         "('derby.database.sqlAuthorization')");
617         if (rs.next())
618         {
619             String JavaDoc sqlAuth = rs.getString(1);
620             if (Boolean.valueOf(sqlAuth).booleanValue())
621                 sqlAuthorization = true;
622         }
623         stmt.close();
624
625         // Load default property values.
626
return;
627
628     }
629
630     /* ************************************************
631      * getColumnListFromDescription:
632      * Takes string description of column numbers in the
633      * form of "(2, 1, 3...)" and the id of the table
634      * having those columns, and then returns a string
635      * with the column numbers replaced by their actual
636      * names ('2' is replaced with the 2nd column in the
637      * table, '1' with the first column, etc.).
638      * @param tableId the id of the table to which the column
639      * numbers should be applied.
640      * @param description a string holding a list of column
641      * numbers, enclosed in parentheses and separated
642      * by commas.
643      * @return a new string with the column numbers in
644      * 'description' replaced by their column names;
645      * also, the parentheses have been stripped off.
646      ****/

647
648     public static String JavaDoc getColumnListFromDescription(String JavaDoc tableId,
649         String JavaDoc description) throws SQLException JavaDoc
650     {
651
652         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
653         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(
654             description.substring(description.indexOf("(") + 1,
655                 description.lastIndexOf(")")), " ,", true);
656
657         boolean firstCol = true;
658         while (tokenizer.hasMoreTokens()) {
659
660             String JavaDoc tok = tokenizer.nextToken().trim();
661             if (tok.equals(""))
662                 continue;
663             else if (tok.equals(",")) {
664                 firstCol = false;
665                 continue;
666             }
667             try {
668                 String JavaDoc colName = getColNameFromNumber(tableId,
669                     (Integer.valueOf(tok)).intValue());
670                 if (!firstCol)
671                     sb.append(", ");
672                 sb.append(colName);
673             } catch (NumberFormatException JavaDoc e) {
674             // not a number; could be "ASC" or "DESC" tag,
675
// which is okay; otherwise, something's wrong.
676
tok = tok.toUpperCase();
677                 if (tok.equals("DESC") || tok.equals("ASC"))
678                 // then this is okay; just add the token to result.
679
sb.append(" " + tok);
680                 else
681                 // shouldn't happen.
682
Logs.debug("INTERNAL ERROR: read a non-number (" +
683                         tok + ") when a column number was expected:\n" +
684                         description, (String JavaDoc)null);
685             }
686
687         }
688
689         return sb.toString();
690
691     }
692
693     /* ************************************************
694      * getColNameFromNumber:
695      * Takes a tableid and a column number colNum, and
696      * returns the name of the colNum'th column in the
697      * table with tableid.
698      * @param tableid id of the table.
699      * @param colNum number of the column for which we want
700      * the name.
701      * @return The name of the colNum'th column in the
702      * table with tableid.
703      ****/

704
705     public static String JavaDoc getColNameFromNumber(String JavaDoc tableId,
706         int colNum) throws SQLException JavaDoc
707     {
708
709         getColNameFromNumberQuery.setString(1, tableId);
710         getColNameFromNumberQuery.setInt(2, colNum);
711         ResultSet JavaDoc rs = getColNameFromNumberQuery.executeQuery();
712
713         if (!rs.next()) {
714         // shouldn't happen.
715
Logs.debug("INTERNAL ERROR: Failed column number " +
716                 "lookup for table " + lookupTableId(tableId) +
717                 ", column " + colNum, (String JavaDoc)null);
718             rs.close();
719             return "";
720         }
721         else {
722             String JavaDoc colName = addQuotes(expandDoubleQuotes(rs.getString(1)));
723             rs.close();
724             return colName;
725         }
726
727     }
728
729     /* ************************************************
730      * addQuotes:
731      * Add quotes to the received object name, and return
732      * the result.
733      * @param name the name to which to add quotes.
734      * @return the name with double quotes around it.
735      ****/

736
737     public static String JavaDoc addQuotes(String JavaDoc name) {
738
739         if (name == null)
740             return null;
741
742         return "\"" + name + "\"";
743
744     }
745
746
747     public static String JavaDoc addSingleQuotes(String JavaDoc name) {
748
749         if (name == null)
750             return null;
751
752         return "'" + name + "'";
753     }
754
755     /* ************************************************
756      * stripQuotes:
757      * Takes a name and, if the name is enclosed in
758      * quotes, strips the quotes off. This method
759      * assumes that the received String either has no quotes,
760      * or has a quote (double or single) as the very first
761      * AND very last character.
762      * @param quotedName a name with quotes as the first
763      * and last character, or else with no quotes at all.
764      * @return quotedName, without the quotes.
765      ****/

766
767     public static String JavaDoc stripQuotes(String JavaDoc quotedName) {
768
769         if (quotedName == null)
770             return null;
771
772         if (!(quotedName.startsWith("'") || quotedName.startsWith("\"")))
773         // name doesn't _start_ with a quote, so we do nothing.
774
return quotedName;
775
776         if (!(quotedName.endsWith("'") || quotedName.endsWith("\"")))
777         // name doesn't _end_ with a quote, so we do nothing.
778
return quotedName;
779
780         // Remove starting and ending quotes.
781
return quotedName.substring(1, quotedName.length() - 1);
782
783     }
784
785     /* ************************************************
786      * isExcludedTable:
787      * Takes a table name and determines whether or not
788      * the DDL for objects related to that table should be
789      * generated.
790      * @param tableName name of the table to check.
791      * @return true if 1) the user specified a table list
792      * and that list does NOT include the received name; or
793      * 2) if the user specified a schema restriction and
794      * the received name does NOT have that schema; false
795      * otherwise.
796      ****/

797
798     public static boolean isExcludedTable(String JavaDoc tableName) {
799
800         if (tableName == null)
801             return true;
802
803         int dot = tableName.indexOf(".");
804         if (dot != -1) {
805         // strip off the schema part of the name, and see if we're
806
// okay to use it.
807
if (isIgnorableSchema(tableName.substring(0, dot)))
808             // then we exclude this table.
809
return true;
810             tableName = tableName.substring(dot + 1,
811                 tableName.length());
812         }
813
814         return ((tableList != null) && !tableList.contains(tableName));
815
816     }
817
818     /* ************************************************
819      * Takes a schema name and determines whether or
820      * not the DDL for objects with that schema should
821      * be generated.
822      * @param schemaName schema name to be checked.
823      * @return true if 1) the user specified a target
824      * schema and that target is NOT the same as the
825      * received schema name, or 2) the schema is a
826      * system schema (SYS, SYSVISUAL, or SYSIBM);
827      * false otherwise;
828      ****/

829
830     private static final String JavaDoc[] ignorableSchemaNames = {
831         "SYSIBM",
832         "SYS",
833         "SYSVISUAL",
834         "SYSCAT",
835         "SYSFUN",
836         "SYSPROC",
837         "SYSSTAT",
838         "NULLID",
839         "SYSCS_ADMIN",
840         "SYSCS_DIAG",
841         "SYSCS_UTIL",
842         "SQLJ"};
843
844     public static boolean isIgnorableSchema(String JavaDoc schemaName) {
845
846         if ((targetSchema != null) && (!schemaName.equals(targetSchema)))
847             return true;
848
849         schemaName = stripQuotes(schemaName);
850
851         boolean ret = false;
852
853         for (int i = ignorableSchemaNames.length - 1; i >= 0;)
854         {
855             if ((ret = ignorableSchemaNames[i--].equalsIgnoreCase(schemaName)))
856                 break;
857         }
858
859         return(ret);
860     }
861
862     /* ************************************************
863      * Takes a string and determines whether or not that
864      * string makes reference to any of the table names
865      * in the user-specified table list.
866      * @param str The string in which to search for table names.
867      * @return true if 1) the user didn't specify a
868      * target table list, or 2) the received string
869      * contains at least one of the table names in the
870      * user-specified target list; false otherwise.
871      ****/

872
873     public static boolean stringContainsTargetTable(String JavaDoc str) {
874
875         if (str == null)
876         // if the string is null, it can't possibly contain
877
// any table names.
878
return false;
879
880         if (tableList == null)
881         // if we have no target tables, then default to true.
882
return true;
883
884         int strLen = str.length();
885         for (int i = 0; i < tableList.size(); i++) {
886
887             String JavaDoc tableName = (String JavaDoc)tableList.get(i);
888             tableName = expandDoubleQuotes(stripQuotes(tableName));
889             int nameLen = tableName.length();
890             String JavaDoc strCopy;
891             if (tableName.equals(tableName.toUpperCase(
892                 java.util.Locale.ENGLISH)))
893             // case doesn't matter.
894
strCopy = str.toUpperCase();
895             else
896                 strCopy = str;
897             int pos = strCopy.indexOf(tableName);
898             while (pos != -1) {
899
900                 // If we found it, make sure it's really a match.
901
// First, see if it's part of another word.
902
if (!partOfWord(str, pos, nameLen, strLen)) {
903
904                     // See if the match is in quotes--if so, then
905
// it should match the table name's case.
906
if ((pos >= 1) && (strCopy.charAt(pos-1) == '"') &&
907                       (pos + nameLen < strCopy.length()) &&
908                       (strCopy.charAt(pos+nameLen) == '"'))
909                     { // match is quoted; check it's case.
910
if (str.substring(pos,
911                             pos + nameLen).equals(tableName))
912                         // everything checks out.
913
return true;
914                     }
915                     else
916                     // match isn't quoted, so we're okay as is.
917
return true;
918                 }
919
920                 pos = str.indexOf(tableName, pos + nameLen);
921
922             }
923         }
924
925         // If we get here, we didn't find it.
926
return false;
927
928     }
929
930     /* ************************************************
931      * partOfWord:
932      * Returns true if the part of the string given by
933      * str.substring(pos, pos + nameLen) is part of
934      * another word.
935      * @param str The string in which we're looking.
936      * @param pos The position at which the substring in
937      * question begins.
938      * @param nameLen the length of the substring in
939      * question.
940      * @param strLen The length of the string in which
941      * we're looking.
942      * @return true if the substring from pos to
943      * pos+nameLen is part of larger word (i.e.
944      * if it has a letter/digit immediately before
945      * or after); false otherwise.
946      ****/

947
948     private static boolean partOfWord (String JavaDoc str,
949         int pos, int nameLen, int strLen)
950     {
951
952         boolean somethingBefore = false;
953         if (pos > 0) {
954             char c = str.charAt(pos-1);
955             somethingBefore = ((c == '_') ||
956                 Character.isLetterOrDigit(c));
957         }
958
959         boolean somethingAfter = false;
960         if (pos + nameLen < strLen) {
961             char c = str.charAt(pos + nameLen);
962             somethingAfter = ((c == '_') ||
963                 Character.isLetterOrDigit(c));
964         }
965
966         return (somethingBefore || somethingAfter);
967
968     }
969
970     /* ************************************************
971      * expandDoubleQuotes:
972      * If the received SQL id contains a quote, we have
973      * to expand it into TWO quotes so that it can be
974      * treated correctly at parse time.
975      * @param name Id that we want to print.
976      ****/

977
978     public static String JavaDoc expandDoubleQuotes(String JavaDoc name) {
979
980         if ((name == null) || (name.indexOf("\"") < 0))
981         // nothing to do.
982
return name;
983
984         char [] cA = name.toCharArray();
985
986         // Worst (and extremely unlikely) case is every
987
// character is a double quote, which means the
988
// escaped string would need to be 2 times as long.
989
char [] result = new char[2*cA.length];
990
991         int j = 0;
992         for (int i = 0; i < cA.length; i++) {
993
994             if (cA[i] == '"') {
995                 result[j++] = '"';
996                 result[j++] = '"';
997             }
998             else
999                 result[j++] = cA[i];
1000
1001        }
1002
1003        return new String JavaDoc(result, 0, j);
1004
1005    }
1006
1007    /* ************************************************
1008     * lookupSchemaId:
1009     * Return the schema name corresponding to the
1010     * received schema id.
1011     * @param schemaId The id to look up.
1012     * @return the schema name.
1013     ****/

1014
1015    public static String JavaDoc lookupSchemaId(String JavaDoc schemaId) {
1016
1017        return (String JavaDoc)(schemaMap.get(schemaId));
1018
1019    }
1020
1021    /* ************************************************
1022     * lookupTableId:
1023     * Return the table name corresponding to the
1024     * received table id.
1025     * @param tableId The id to look up.
1026     * @return the table name.
1027     ****/

1028
1029    public static String JavaDoc lookupTableId(String JavaDoc tableId) {
1030
1031        return (String JavaDoc)(tableIdToNameMap.get(tableId));
1032
1033    }
1034
1035    /* ************************************************
1036     * writeVerboseOutput:
1037     * Writes the received string as "verbose" output,
1038     * meaning that we write it to System.err. We
1039     * choose System.err so that the string doesn't
1040     * show up if the user pipes dblook output to
1041     * a file (unless s/he explicitly pipes System.err
1042     * output to that file, as well).
1043     * @param key Key for the message to be printed as
1044     * verbose output.
1045     * @param value Value to be substituted into the
1046     * message.
1047     * @return message for received key has been printed
1048     * to System.err.
1049     ****/

1050
1051    public static void writeVerboseOutput(String JavaDoc key,
1052        String JavaDoc value) {
1053
1054        if (value == null)
1055            System.err.println(lookupMessage(key));
1056        else
1057            System.err.println(lookupMessage(key,
1058                new String JavaDoc [] {value}));
1059        return;
1060
1061    }
1062
1063    /* ************************************************
1064     * lookupMessage:
1065     * Retrieve a localized message.
1066     * @param key The key for the localized message.
1067     * @return the message corresponding to the received
1068     * key.
1069     ****/

1070
1071    public static String JavaDoc lookupMessage(String JavaDoc key) {
1072
1073        return lookupMessage(key, null);
1074
1075    }
1076
1077    /* ************************************************
1078     * lookupMessage:
1079     * Retreive a localized message.
1080     * @param key The key for the localized message.
1081     * @param vals Array of values to be used in the
1082     * message.
1083     * @return the message corresponding to the received
1084     * key, with the received values substituted where
1085     * appropriate.
1086     ****/

1087
1088    public static String JavaDoc lookupMessage(String JavaDoc key, String JavaDoc[] vals) {
1089    
1090        String JavaDoc msg = "";
1091        if (vals == null)
1092            msg = langUtil.getTextMessage(key);
1093        else {
1094            switch (vals.length) {
1095                case 1: msg = langUtil.getTextMessage(
1096                            key, vals[0]);
1097                        break;
1098                case 2: msg = langUtil.getTextMessage(
1099                            key, vals[0], vals[1]);
1100                        break;
1101                default: /* shouldn't happen */
1102                        break;
1103            }
1104        }
1105
1106        return msg;
1107
1108    }
1109
1110    /* ************************************************
1111     * removeNewlines:
1112     * Remove any newline characters from the received
1113     * string (replace them with spaces).
1114     * @param str The string from which we are removing
1115     * all newline characters.
1116     * @return The string, with all newline characters
1117     * replaced with spaces.
1118     ****/

1119
1120    public static String JavaDoc removeNewlines(String JavaDoc str) {
1121
1122        if (str == null)
1123        // don't do anything.
1124
return null;
1125
1126        StringBuffer JavaDoc result = null;
1127        try {
1128
1129            BufferedReader JavaDoc strVal = new BufferedReader JavaDoc (new StringReader JavaDoc(str));
1130            for (String JavaDoc txt = strVal.readLine(); txt != null;
1131                txt = strVal.readLine())
1132            {
1133                if (result == null)
1134                    result = new StringBuffer JavaDoc(txt);
1135                else {
1136                    result.append(" ");
1137                    result.append(txt);
1138                }
1139            }
1140
1141            return result.toString();
1142
1143        } catch (Exception JavaDoc e) {
1144        // if something went wrong, just return the string as is--
1145
// worst case is that the generated DDL is correct, it just
1146
// can't be run in some SQL script apps (because of the newline
1147
// characters).
1148
return str;
1149        }
1150
1151    }
1152
1153}
1154
1155
Popular Tags