001: /*
002: * The contents of this file are subject to the Mozilla Public License
003: * Version 1.1 (the "License"); you may not use this file except in
004: * compliance with the License. You may obtain a copy of the License at
005: * http://www.mozilla.org/MPL/
006: *
007: * Software distributed under the License is distributed on an "AS IS"
008: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
009: * License for the specific language governing rights and limitations
010: * under the License.
011: *
012: * The Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
013: *
014: * The Initial Developer of the Original Code is iSQL-Viewer, A Mutli-Platform Database Tool.
015: * Portions created by Mark A. Kobold are Copyright (C) 2000-2007. All Rights Reserved.
016: *
017: * Contributor(s):
018: * Mark A. Kobold [mkobold <at> isqlviewer <dot> com].
019: *
020: * If you didn't download this code from the following link, you should check
021: * if you aren't using an obsolete version: http://www.isqlviewer.com
022: */
023: package org.isqlviewer.model;
024:
025: import java.sql.Connection;
026: import java.sql.DatabaseMetaData;
027: import java.sql.ResultSet;
028: import java.sql.SQLException;
029: import java.sql.Types;
030: import java.util.Collection;
031: import java.util.TreeSet;
032:
033: import javax.swing.tree.DefaultTreeModel;
034:
035: import org.isqlviewer.util.LocalMessages;
036:
037: /**
038: * JDBC Schema Model that represents a Swing JTree compatible representation of JDBC structures.
039: * <p>
040: *
041: * @author Mark A. Kobold <mkobold at isqlviewer dot com>
042: * @version 1.0
043: */
044: public class JdbcSchemaTreeModel extends DefaultTreeModel {
045:
046: private static final long serialVersionUID = -3951771268602130376L;
047: private static final String RESOURCE_BUNDLE = "org.isqlviewer.model.ResourceBundle";
048: private static final LocalMessages messages = new LocalMessages(
049: RESOURCE_BUNDLE);
050:
051: private DatabaseMetaData jdbcMetadata = null;
052: private String catalog = null;
053: private String schema = null;
054:
055: private SchemaNode rootNode = null;
056: private boolean showProcedures = true;
057: private boolean metaEnabled = true;
058: private boolean showTables = true;
059:
060: public String getCurrentCatlog() {
061:
062: return catalog;
063: }
064:
065: public String getCurrentSchema() {
066:
067: return schema;
068: }
069:
070: public JdbcSchemaTreeModel() {
071:
072: super (new SchemaNode(null, true, SchemaNodeType.ROOT));
073: rootNode = (SchemaNode) getRoot();
074: }
075:
076: public void updateConnection(Connection cnx, boolean setContext)
077: throws SQLException {
078:
079: if (cnx == null && jdbcMetadata == null) {
080: rootNode.removeAllChildren();
081: return;
082: }
083:
084: if (cnx != null) {
085: jdbcMetadata = cnx.getMetaData();
086: rootNode.setUserObject("Connection");
087: rootNode.setAllowsChildren(true);
088: if (setContext) {
089: try {
090: setSchema(jdbcMetadata.getUserName(), false);
091: } catch (Throwable t) {
092: setSchema(null, false);
093: }
094:
095: try {
096: setCatalog(cnx.getCatalog(), false);
097: } catch (Throwable t) {
098: setCatalog(null, false);
099: }
100: }
101: } else {
102: clear();
103: }
104: }
105:
106: public synchronized void setCatalog(String pCatalog) {
107:
108: setCatalog(pCatalog, true);
109: }
110:
111: public synchronized void setSchema(String pSchema) {
112:
113: setSchema(pSchema, true);
114: }
115:
116: public synchronized void setCatalog(String pCatalog, boolean reload) {
117:
118: if (pCatalog != null) {
119: catalog = pCatalog;
120: } else {
121: catalog = null;
122: }
123:
124: if (reload) {
125: reload();
126: }
127: }
128:
129: public synchronized void setSchema(String pSchema, boolean reload) {
130:
131: if (pSchema != null)
132: schema = pSchema;
133: else
134: schema = null;
135: if (reload)
136: reload();
137: }
138:
139: @Override
140: public synchronized void reload() {
141:
142: rootNode.removeAllChildren();
143: if (jdbcMetadata != null) {
144: initializeDefaultNodes(metaEnabled, showTables,
145: showProcedures);
146: }
147: reload(rootNode);
148: }
149:
150: public synchronized void loadChildNodes(SchemaNode parentNode) {
151:
152: if (parentNode == null) {
153: throw new NullPointerException();
154: }
155:
156: SchemaNodeType nodeType = parentNode.getNodeType();
157: switch (nodeType) {
158: case TABLE_TYPE:
159: loadTableTypeChildren(parentNode);
160: break;
161: case PROCEDURE_SET:
162: loadProcedureChildren(parentNode);
163: break;
164: case TABLE:
165: loadTableChildren(parentNode);
166: break;
167: case COLUMN_SET:
168: loadColumnChildren(parentNode);
169: break;
170: case DATA_TYPE_SET:
171: loadDataTypeChildren(parentNode);
172: break;
173: case UDT_SET_DISTINCT:
174: loadUserDataTypeChildren(parentNode, Types.DISTINCT);
175: break;
176: case UDT_SET_JAVA_OBJECT:
177: loadUserDataTypeChildren(parentNode, Types.JAVA_OBJECT);
178: break;
179: case UDT_SET_STRUCT:
180: loadUserDataTypeChildren(parentNode, Types.STRUCT);
181: break;
182: default:
183: break;
184: }
185: }
186:
187: public boolean isMetadataEnabled() {
188:
189: return metaEnabled;
190: }
191:
192: public boolean isProceduresEnabled() {
193:
194: return showProcedures;
195: }
196:
197: public boolean isTablesEnabled() {
198:
199: return showTables;
200: }
201:
202: public void setMetadataEnabled(boolean b) {
203:
204: metaEnabled = b;
205: }
206:
207: public void setProceduresEnabled(boolean b) {
208:
209: showProcedures = b;
210: }
211:
212: public void setTablesEnabled(boolean b) {
213:
214: showTables = b;
215: }
216:
217: /**
218: * @return
219: */
220: public DatabaseMetaData getMetaData() {
221:
222: return jdbcMetadata;
223: }
224:
225: /**
226: * Clears all items from the tree.
227: * <p>
228: */
229: public void clear() {
230:
231: rootNode.setUserObject("");
232: rootNode.removeAllChildren();
233: jdbcMetadata = null;
234: catalog = null;
235: schema = null;
236: reload();
237: }
238:
239: protected void initializeDefaultNodes(boolean showDataTypes,
240: boolean showTableTypes, boolean showStoredProcedures) {
241:
242: String nodeText = null;
243: if (showDataTypes) {
244: SchemaNode schemaNode = null;
245:
246: schemaNode = new SchemaNode(messages
247: .format("schema.userdatatypes.node"), true,
248: SchemaNodeType.UDT_SET);
249: insertNodeInto(schemaNode, rootNode, 0);
250:
251: nodeText = messages
252: .format("schema.userdatatypes_distinct.node");
253: SchemaNode udt = new SchemaNode(nodeText, true,
254: SchemaNodeType.UDT_SET_DISTINCT);
255: udt.add(createNoncachedNode());
256: insertNodeInto(udt, schemaNode, 0);
257:
258: nodeText = messages
259: .format("schema.userdatatypes_java_object.node");
260: udt = new SchemaNode(nodeText, true,
261: SchemaNodeType.UDT_SET_JAVA_OBJECT);
262: udt.add(createNoncachedNode());
263: insertNodeInto(udt, schemaNode, 0);
264:
265: nodeText = messages
266: .format("schema.userdatatypes_struct.node");
267: udt = new SchemaNode(nodeText, true,
268: SchemaNodeType.UDT_SET_STRUCT);
269: udt.add(createNoncachedNode());
270: insertNodeInto(udt, schemaNode, 0);
271:
272: schemaNode = new SchemaNode(messages
273: .format("schema.datatypes.node"), true,
274: SchemaNodeType.DATA_TYPE_SET);
275: schemaNode.add(createNoncachedNode());
276: insertNodeInto(schemaNode, rootNode, 0);
277: }
278:
279: if (showTableTypes) {
280: ResultSet resultSet = null;
281: Collection<String> tableTypes = new TreeSet<String>(
282: String.CASE_INSENSITIVE_ORDER);
283: try {
284: resultSet = jdbcMetadata.getTableTypes();
285: while (resultSet.next()) {
286: tableTypes.add(resultSet.getString("TABLE_TYPE"));
287: }
288: } catch (SQLException sqle) {
289: // TODO Do Something here...
290: } finally {
291: if (resultSet != null) {
292: try {
293: resultSet.close();
294: } catch (SQLException ignored) {
295: }
296: }
297: }
298:
299: for (String type : tableTypes) {
300: String[] typeSet = new String[] { type };
301: try {
302: resultSet = jdbcMetadata.getTables(catalog, schema,
303: null, typeSet);
304: if (resultSet.next()) {
305: // Threre are tables that exist for this type in the current catalog/schema //
306: SchemaNode tabletypeNode = new SchemaNode(type
307: .trim(), true,
308: SchemaNodeType.TABLE_TYPE);
309: tabletypeNode.add(createNoncachedNode());
310: insertNodeInto(tabletypeNode, rootNode, 0);
311: }
312: } catch (SQLException sqle) {
313: } finally {
314: if (resultSet != null) {
315: try {
316: resultSet.close();
317: } catch (SQLException ignored) {
318: }
319: }
320: }
321: }
322: }
323:
324: if (showStoredProcedures) {
325: ResultSet resultSet = null;
326: try {
327: resultSet = jdbcMetadata.getProcedures(catalog, schema,
328: null);
329: if (resultSet.next()) {
330: // Threre are stored procedures that exist for this type in the current catalog/schema //
331: nodeText = messages
332: .format("schema.storedprocedures.node");
333: SchemaNode procedureNode = new SchemaNode(nodeText,
334: true, SchemaNodeType.PROCEDURE_SET);
335: procedureNode.add(new SchemaNode(
336: SchemaNodeType.NON_CACHED));
337: insertNodeInto(procedureNode, rootNode, 0);
338: }
339: } catch (SQLException sqle) {
340: nodeText = messages
341: .format("schema.storedprocedures.node");
342: SchemaNode procedureNode = new SchemaNode(nodeText,
343: false, SchemaNodeType.PROCEDURE_SET);
344: procedureNode.setHasError(true);
345: insertNodeInto(procedureNode, rootNode, 0);
346: } finally {
347: if (resultSet != null) {
348: try {
349: resultSet.close();
350: } catch (SQLException ignored) {
351: }
352: }
353: }
354: }
355: }
356:
357: private SchemaNode createNoncachedNode() {
358:
359: return new SchemaNode(messages
360: .getMessage("schema.noncached.node"), false,
361: SchemaNodeType.NON_CACHED);
362: }
363:
364: private void loadTableTypeChildren(SchemaNode tabletypeNode) {
365:
366: tabletypeNode.removeAllChildren();
367: ResultSet resultSet = null;
368: if (showTables) {
369: String tableType = tabletypeNode.getUserObject();
370: try {
371: resultSet = jdbcMetadata.getTables(catalog, schema,
372: null, new String[] { tableType });
373: while (resultSet.next()) {
374: String tableName = resultSet
375: .getString("TABLE_NAME");
376: SchemaNode tableNode = new SchemaNode(tableName
377: .trim(), true, SchemaNodeType.TABLE);
378: insertNodeInto(createNoncachedNode(), tableNode, 0);
379: insertNodeInto(tableNode, tabletypeNode, 0);
380: }
381: } catch (SQLException sqle) {
382: tabletypeNode.setHasError(true);
383: } finally {
384: if (resultSet != null) {
385: try {
386: resultSet.close();
387: } catch (SQLException ignored) {
388: }
389: }
390: reload(tabletypeNode);
391: }
392: }
393: }
394:
395: private void loadDataTypeChildren(SchemaNode typesetNode) {
396:
397: typesetNode.removeAllChildren();
398: ResultSet resultSet = null;
399: try {
400: resultSet = jdbcMetadata.getTypeInfo();
401: while (resultSet.next()) {
402: String tableName = resultSet.getString("TYPE_NAME");
403: SchemaNode tableNode = new SchemaNode(tableName.trim(),
404: true, SchemaNodeType.DATA_TYPE);
405: insertNodeInto(tableNode, typesetNode, 0);
406: }
407: } catch (SQLException sqle) {
408: typesetNode.setHasError(true);
409: } finally {
410: if (resultSet != null) {
411: try {
412: resultSet.close();
413: } catch (SQLException ignored) {
414: }
415: }
416: reload(typesetNode);
417: }
418: }
419:
420: private void loadUserDataTypeChildren(SchemaNode usertypesetNode,
421: int dataType) {
422:
423: usertypesetNode.removeAllChildren();
424: ResultSet resultSet = null;
425: int[] type = new int[] { dataType };
426: try {
427: resultSet = jdbcMetadata.getUDTs(catalog, schema, null,
428: type);
429: while (resultSet.next()) {
430: String tableName = resultSet.getString("TYPE_NAME");
431: SchemaNode tableNode = new SchemaNode(tableName.trim(),
432: true, SchemaNodeType.DATA_TYPE);
433: insertNodeInto(tableNode, usertypesetNode, 0);
434: }
435: } catch (SQLException sqle) {
436: usertypesetNode.setHasError(true);
437: } finally {
438: if (resultSet != null) {
439: try {
440: resultSet.close();
441: } catch (SQLException ignored) {
442: }
443: }
444: reload(usertypesetNode);
445: }
446: }
447:
448: private void loadProcedureChildren(SchemaNode procedureNode) {
449:
450: procedureNode.removeAllChildren();
451: ResultSet resultSet = null;
452: if (showProcedures) {
453: try {
454: resultSet = jdbcMetadata.getProcedures(catalog, schema,
455: null);
456: while (resultSet.next()) {
457: String tableName = resultSet
458: .getString("PROCEDURE_NAME");
459: SchemaNode tableNode = new SchemaNode(tableName
460: .trim(), false, SchemaNodeType.PROCEDURE);
461: insertNodeInto(tableNode, procedureNode, 0);
462: }
463: } catch (SQLException sqle) {
464: procedureNode.setHasError(true);
465: } finally {
466: if (resultSet != null) {
467: try {
468: resultSet.close();
469: } catch (SQLException ignored) {
470: }
471: }
472: reload(procedureNode);
473: }
474: }
475: }
476:
477: private void loadTableChildren(SchemaNode tableNode) {
478:
479: tableNode.removeAllChildren();
480: String nodeText = null;
481:
482: nodeText = messages.format("schema.columns.node");
483: SchemaNode columnsetNode = new SchemaNode(nodeText, true,
484: SchemaNodeType.COLUMN_SET);
485: insertNodeInto(columnsetNode, tableNode, 0);
486: insertNodeInto(createNoncachedNode(), columnsetNode, 0);
487:
488: // TODO Add a profile preference for service API level so that if a service is set to JDBC 2.x or 1.0 :-\ we
489: // won't call JDBC 3.0 functions like getSuperTables this would reduce false exceptions being logged.
490: loadJdbc10TableChildren(tableNode, tableNode.getUserObject());
491: if (Boolean.getBoolean("isql.jdbc3.enabled")) {
492: loadJdbc30TableChildren(tableNode, tableNode
493: .getUserObject());
494: }
495: reload(tableNode);
496: }
497:
498: private void loadJdbc10TableChildren(SchemaNode tableNode,
499: String table) {
500:
501: String nodeText = null;
502: SchemaNode schemaNode = null;
503: ResultSet resultSet = null;
504:
505: try {
506: resultSet = jdbcMetadata.getIndexInfo(catalog, schema,
507: table, false, false);
508: if (resultSet.next()) {
509: nodeText = messages.format("schema.indicies.node");
510: schemaNode = new SchemaNode(nodeText, false,
511: SchemaNodeType.INDEX);
512: insertNodeInto(schemaNode, tableNode, 0);
513: }
514: } catch (SQLException sqle) {
515: nodeText = messages.format("schema.indicies.node");
516: schemaNode = new SchemaNode(nodeText, false,
517: SchemaNodeType.INDEX);
518: schemaNode.setHasError(true);
519: insertNodeInto(schemaNode, tableNode, 0);
520: } finally {
521: if (resultSet != null) {
522: try {
523: resultSet.close();
524: } catch (SQLException ignored) {
525: }
526: }
527: }
528:
529: try {
530: resultSet = jdbcMetadata.getPrimaryKeys(catalog, schema,
531: table);
532: if (resultSet.next()) {
533: nodeText = messages.format("schema.primarykeys.node");
534: schemaNode = new SchemaNode(nodeText, false,
535: SchemaNodeType.PRIMARY_KEYS);
536: insertNodeInto(schemaNode, tableNode, 0);
537: }
538: } catch (SQLException sqle) {
539: nodeText = messages.format("schema.primarykeys.node");
540: schemaNode = new SchemaNode(nodeText, false,
541: SchemaNodeType.PRIMARY_KEYS);
542: schemaNode.setHasError(true);
543: insertNodeInto(schemaNode, tableNode, 0);
544: } finally {
545: if (resultSet != null) {
546: try {
547: resultSet.close();
548: } catch (SQLException ignored) {
549: }
550: }
551: }
552:
553: try {
554: resultSet = jdbcMetadata.getExportedKeys(catalog, schema,
555: table);
556: if (resultSet.next()) {
557: nodeText = messages.format("schema.foreignkeys.node");
558: schemaNode = new SchemaNode(nodeText, false,
559: SchemaNodeType.EXPORTED_KEYS);
560: insertNodeInto(schemaNode, tableNode, 0);
561: }
562: } catch (SQLException sqle) {
563: nodeText = messages.format("schema.foreignkeys.node");
564: schemaNode = new SchemaNode(nodeText, false,
565: SchemaNodeType.EXPORTED_KEYS);
566: schemaNode.setHasError(true);
567: insertNodeInto(schemaNode, tableNode, 0);
568: } finally {
569: if (resultSet != null) {
570: try {
571: resultSet.close();
572: } catch (SQLException ignored) {
573: }
574: }
575: }
576:
577: try {
578: resultSet = jdbcMetadata.getImportedKeys(catalog, schema,
579: table);
580: if (resultSet.next()) {
581: nodeText = messages
582: .format("schema.foreignkeyconstraints.node");
583: schemaNode = new SchemaNode(nodeText, false,
584: SchemaNodeType.IMPORTED_KEYS);
585: insertNodeInto(schemaNode, tableNode, 0);
586: }
587: } catch (SQLException sqle) {
588: nodeText = messages
589: .format("schema.foreignkeyconstraints.node");
590: schemaNode = new SchemaNode(nodeText, false,
591: SchemaNodeType.IMPORTED_KEYS);
592: schemaNode.setHasError(true);
593: insertNodeInto(schemaNode, tableNode, 0);
594: } finally {
595: if (resultSet != null) {
596: try {
597: resultSet.close();
598: } catch (SQLException ignored) {
599: }
600: }
601: }
602:
603: try {
604: resultSet = jdbcMetadata.getTablePrivileges(catalog,
605: schema, table);
606: if (resultSet.next()) {
607: nodeText = messages
608: .format("schema.tableprivileges.node");
609: schemaNode = new SchemaNode(nodeText, false,
610: SchemaNodeType.TABLE_PRIVILIGES);
611: insertNodeInto(schemaNode, tableNode, 0);
612: }
613: } catch (SQLException sqle) {
614: nodeText = messages.format("schema.tableprivileges.node");
615: schemaNode = new SchemaNode(nodeText, false,
616: SchemaNodeType.TABLE_PRIVILIGES);
617: schemaNode.setHasError(true);
618: insertNodeInto(schemaNode, tableNode, 0);
619: } finally {
620: if (resultSet != null) {
621: try {
622: resultSet.close();
623: } catch (SQLException ignored) {
624: }
625: }
626: }
627:
628: try {
629: resultSet = jdbcMetadata.getIndexInfo(catalog, schema,
630: table, false, false);
631: if (resultSet.next()) {
632: nodeText = messages
633: .format("schema.columnprivileges.node");
634: schemaNode = new SchemaNode(nodeText, false,
635: SchemaNodeType.COLUMN_PRIVILIGES);
636: insertNodeInto(schemaNode, tableNode, 0);
637: }
638: } catch (SQLException sqle) {
639: nodeText = messages.format("schema.columnprivileges.node");
640: schemaNode = new SchemaNode(nodeText, false,
641: SchemaNodeType.COLUMN_PRIVILIGES);
642: schemaNode.setHasError(true);
643: insertNodeInto(schemaNode, tableNode, 0);
644: } finally {
645: if (resultSet != null) {
646: try {
647: resultSet.close();
648: } catch (SQLException ignored) {
649: }
650: }
651: }
652:
653: }
654:
655: private void loadJdbc30TableChildren(SchemaNode tableNode,
656: String tableName) {
657:
658: String nodeText = null;
659: SchemaNode schemaNode = null;
660: ResultSet resultSet = null;
661:
662: try {
663: resultSet = jdbcMetadata.getSuperTables(catalog, schema,
664: tableName);
665: if (resultSet.next()) {
666: nodeText = messages.format("schema.supertables.node");
667: schemaNode = new SchemaNode(nodeText, false,
668: SchemaNodeType.SUPER_TABLES);
669: insertNodeInto(schemaNode, tableNode, 0);
670: }
671: } catch (SQLException sqle) {
672: nodeText = messages.format("schema.supertables.node");
673: schemaNode = new SchemaNode(nodeText, false,
674: SchemaNodeType.SUPER_TABLES);
675: schemaNode.setHasError(true);
676: insertNodeInto(schemaNode, tableNode, 0);
677: } finally {
678: if (resultSet != null) {
679: try {
680: resultSet.close();
681: } catch (SQLException ignored) {
682: }
683: }
684: }
685: }
686:
687: private void loadColumnChildren(SchemaNode columnNode) {
688:
689: columnNode.removeAllChildren();
690: ResultSet resultSet = null;
691: SchemaNode tableNode = (SchemaNode) columnNode.getParent();
692: if (tableNode == null) {
693: throw new IllegalArgumentException(columnNode.toString());
694: }
695:
696: String tableName = tableNode.getUserObject();
697: try {
698: resultSet = jdbcMetadata.getColumns(catalog, schema,
699: tableName, null);
700: while (resultSet.next()) {
701: String columnName = resultSet.getString("COLUMN_NAME");
702: SchemaNode columnNameNode = new SchemaNode(columnName
703: .trim(), false, SchemaNodeType.COLUMN);
704: insertNodeInto(columnNameNode, columnNode, 0);
705: }
706: } catch (SQLException sqle) {
707: columnNode.setHasError(true);
708: } finally {
709: if (resultSet != null) {
710: try {
711: resultSet.close();
712: } catch (SQLException ignored) {
713: }
714: }
715: reload(columnNode);
716: }
717: }
718: }
|