0001: package net.sourceforge.squirrel_sql.client.session.schemainfo;
0002:
0003: /*
0004: * Copyright (C) 2001-2003 Colin Bell
0005: * colbell@users.sourceforge.net
0006: *
0007: * Copyright (C) 2001 Johan Compagner
0008: * jcompagner@j-com.nl
0009: *
0010: * This library is free software; you can redistribute it and/or
0011: * modify it under the terms of the GNU Lesser General Public
0012: * License as published by the Free Software Foundation; either
0013: * version 2.1 of the License, or (at your option) any later version.
0014: *
0015: * This library is distributed in the hope that it will be useful,
0016: * but WITHOUT ANY WARRANTY; without even the implied warranty of
0017: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
0018: * Lesser General Public License for more details.
0019: *
0020: * You should have received a copy of the GNU Lesser General Public
0021: * License along with this library; if not, write to the Free Software
0022: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0023: */
0024: import java.sql.DatabaseMetaData;
0025: import java.sql.SQLException;
0026: import java.util.ArrayList;
0027: import java.util.Arrays;
0028: import java.util.HashMap;
0029: import java.util.Hashtable;
0030: import java.util.Iterator;
0031: import java.util.List;
0032: import java.util.Vector;
0033:
0034: import javax.swing.SwingUtilities;
0035:
0036: import net.sourceforge.squirrel_sql.client.IApplication;
0037: import net.sourceforge.squirrel_sql.client.gui.db.SQLAliasSchemaProperties;
0038: import net.sourceforge.squirrel_sql.client.gui.db.SchemaLoadInfo;
0039: import net.sourceforge.squirrel_sql.client.gui.db.SchemaNameLoadInfo;
0040: import net.sourceforge.squirrel_sql.client.session.ExtendedColumnInfo;
0041: import net.sourceforge.squirrel_sql.client.session.ISession;
0042: import net.sourceforge.squirrel_sql.client.session.event.SessionAdapter;
0043: import net.sourceforge.squirrel_sql.client.session.event.SessionEvent;
0044: import net.sourceforge.squirrel_sql.fw.sql.DataTypeInfo;
0045: import net.sourceforge.squirrel_sql.fw.sql.DatabaseObjectType;
0046: import net.sourceforge.squirrel_sql.fw.sql.IDatabaseObjectInfo;
0047: import net.sourceforge.squirrel_sql.fw.sql.IProcedureInfo;
0048: import net.sourceforge.squirrel_sql.fw.sql.ISQLConnection;
0049: import net.sourceforge.squirrel_sql.fw.sql.ITableInfo;
0050: import net.sourceforge.squirrel_sql.fw.sql.ProcedureInfo;
0051: import net.sourceforge.squirrel_sql.fw.sql.ProgressCallBack;
0052: import net.sourceforge.squirrel_sql.fw.sql.SQLDatabaseMetaData;
0053: import net.sourceforge.squirrel_sql.fw.sql.TableColumnInfo;
0054: import net.sourceforge.squirrel_sql.fw.sql.TableInfo;
0055: import net.sourceforge.squirrel_sql.fw.util.StringManager;
0056: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
0057: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
0058: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
0059:
0060: public class SchemaInfo {
0061: public static final int TABLE_EXT_NOT_A_TABLE = 0;
0062: public static final int TABLE_EXT_COLS_LOADED_IN_THIS_CALL = 1;
0063: public static final int TABLE_EXT_COLS_LOADED_BEFORE = 2;
0064:
0065: private static final StringManager s_stringMgr = StringManagerFactory
0066: .getStringManager(SchemaInfo.class);
0067:
0068: private boolean _loading = false;
0069: private boolean _loaded = false;
0070:
0071: private SQLDatabaseMetaData _dmd;
0072: ISession _session = null;
0073:
0074: private static final ILogger s_log = LoggerController
0075: .createLogger(SchemaInfo.class);
0076: private SessionAdapter _sessionListener;
0077:
0078: /**
0079: * The number of load methods
0080: */
0081: private static final int LOAD_METHODS_COUNT = 7;
0082:
0083: private static final int MAX_PROGRESS = 100;
0084:
0085: static interface i18n {
0086: // i18n[SchemaInfo.loadingCatalogs=Loading catalogs]
0087: String LOADING_CATALOGS_MSG = s_stringMgr
0088: .getString("SchemaInfo.loadingCatalogs");
0089:
0090: // i18n[SchemaInfo.loadingKeywords=Loading keywords]
0091: String LOADING_KEYWORDS_MSG = s_stringMgr
0092: .getString("SchemaInfo.loadingKeywords");
0093:
0094: // i18n[SchemaInfo.loadingDataTypes=Loading data types]
0095: String LOADING_DATATYPES_MSG = s_stringMgr
0096: .getString("SchemaInfo.loadingDataTypes");
0097:
0098: // i18n[SchemaInfo.loadingFunctions=Loading functions]
0099: String LOADING_FUNCTIONS_MSG = s_stringMgr
0100: .getString("SchemaInfo.loadingFunctions");
0101:
0102: // i18n[SchemaInfo.loadingTables=Loading tables]
0103: String LOADING_TABLES_MSG = s_stringMgr
0104: .getString("SchemaInfo.loadingTables");
0105:
0106: // i18n[SchemaInfo.loadingStoredProcedures=Loading stored procedures]
0107: String LOADING_PROCS_MSG = s_stringMgr
0108: .getString("SchemaInfo.loadingStoredProcedures");
0109:
0110: // i18n[SchemaInfo.loadingSchemas=Loading schemas]
0111: String LOADING_SCHEMAS_MSG = s_stringMgr
0112: .getString("SchemaInfo.loadingSchemas");
0113:
0114: }
0115:
0116: final HashMap<CaseInsensitiveString, CaseInsensitiveString> _tablesLoadingColsInBackground = new HashMap<CaseInsensitiveString, CaseInsensitiveString>();
0117:
0118: private SchemaInfoCache _schemaInfoCache;
0119:
0120: private Vector<SchemaInfoUpdateListener> _listeners = new Vector<SchemaInfoUpdateListener>();
0121: private boolean _inInitialLoad;
0122: private long _initalLoadBeginTime;
0123: private boolean _sessionStartupTimeHintShown;
0124:
0125: private boolean _schemasAndCatalogsLoaded;
0126: private boolean _tablesLoaded;
0127: private boolean _storedProceduresLoaded;
0128:
0129: public SchemaInfo(IApplication app) {
0130: _sessionListener = new SessionAdapter() {
0131: public void connectionClosedForReconnect(SessionEvent evt) {
0132: if (null != _session
0133: && _session.getIdentifier().equals(
0134: evt.getSession().getIdentifier())) {
0135: _dmd = null;
0136: }
0137: }
0138:
0139: public void reconnected(SessionEvent evt) {
0140: if (null != _session
0141: && _session.getIdentifier().equals(
0142: evt.getSession().getIdentifier())) {
0143: _dmd = _session.getSQLConnection().getSQLMetaData();
0144: if (null != _dmd) {
0145: s_log
0146: .info(s_stringMgr
0147: .getString("SchemaInfo.SuccessfullyRestoredDatabaseMetaData"));
0148: }
0149: }
0150: }
0151:
0152: public void sessionClosing(SessionEvent evt) {
0153: SchemaInfoCacheSerializer.store(_session,
0154: _schemaInfoCache);
0155: }
0156: };
0157:
0158: if (app != null) {
0159: app.getSessionManager()
0160: .addSessionListener(_sessionListener);
0161: }
0162: }
0163:
0164: public void initialLoad(ISession session) {
0165: _session = session;
0166:
0167: breathing();
0168: _schemaInfoCache = SchemaInfoCacheSerializer.load(_session);
0169:
0170: try {
0171: _inInitialLoad = true;
0172: _initalLoadBeginTime = System.currentTimeMillis();
0173: privateLoadAll();
0174: } finally {
0175: _inInitialLoad = false;
0176: _schemaInfoCache.initialLoadDone();
0177: }
0178: }
0179:
0180: public void reloadAll() {
0181: reloadAll(true);
0182: }
0183:
0184: /**
0185: * @param fireSchemaInfoUpdate Should only be false when the caller makes sure fireSchemaInfoUpdate() is called later.
0186: */
0187: void reloadAll(boolean fireSchemaInfoUpdate) {
0188: _schemaInfoCache.clearAll();
0189: privateLoadAll();
0190:
0191: if (fireSchemaInfoUpdate) {
0192: fireSchemaInfoUpdate();
0193: }
0194: }
0195:
0196: private void privateLoadAll() {
0197: synchronized (this ) {
0198: if (_loading) {
0199: return;
0200: }
0201:
0202: _loading = true;
0203:
0204: _schemasAndCatalogsLoaded = false;
0205: _tablesLoaded = false;
0206: _storedProceduresLoaded = false;
0207: }
0208:
0209: breathing();
0210:
0211: long mstart = System.currentTimeMillis();
0212: long mfinish = 0;
0213:
0214: try {
0215: ISQLConnection conn = _session.getSQLConnection();
0216: _dmd = conn.getSQLMetaData();
0217:
0218: _dmd.clearCache();
0219:
0220: int progress = 0;
0221:
0222: progress = loadCatalogs(progress);
0223:
0224: progress = loadSchemas(progress);
0225:
0226: notifySchemasAndCatalogsLoad();
0227:
0228: long start = 0, finish = 0;
0229: try {
0230: if (s_log.isDebugEnabled()) {
0231: s_log.debug(i18n.LOADING_KEYWORDS_MSG);
0232: start = System.currentTimeMillis();
0233: }
0234:
0235: int beginProgress = getLoadMethodProgress(progress++);
0236: setProgress(i18n.LOADING_KEYWORDS_MSG, beginProgress);
0237: loadKeywords(i18n.LOADING_KEYWORDS_MSG, beginProgress);
0238:
0239: if (s_log.isDebugEnabled()) {
0240: finish = System.currentTimeMillis();
0241: s_log.debug("Keywords loaded in "
0242: + (finish - start) + " ms");
0243: }
0244: } catch (Exception ex) {
0245: s_log.error("Error loading keywords", ex);
0246: }
0247:
0248: try {
0249: if (s_log.isDebugEnabled()) {
0250: s_log.debug(i18n.LOADING_DATATYPES_MSG);
0251: start = System.currentTimeMillis();
0252: }
0253: int beginProgress = getLoadMethodProgress(progress++);
0254: setProgress(i18n.LOADING_DATATYPES_MSG, beginProgress);
0255: loadDataTypes(i18n.LOADING_DATATYPES_MSG, beginProgress);
0256:
0257: if (s_log.isDebugEnabled()) {
0258: finish = System.currentTimeMillis();
0259: s_log.debug("Data types loaded in "
0260: + (finish - start) + " ms");
0261: }
0262: } catch (Exception ex) {
0263: s_log.error("Error loading data types", ex);
0264: }
0265:
0266: try {
0267: if (s_log.isDebugEnabled()) {
0268: s_log.debug(i18n.LOADING_FUNCTIONS_MSG);
0269: start = System.currentTimeMillis();
0270: }
0271:
0272: int beginProgress = getLoadMethodProgress(progress++);
0273: setProgress(i18n.LOADING_FUNCTIONS_MSG, beginProgress);
0274: loadGlobalFunctions(i18n.LOADING_FUNCTIONS_MSG,
0275: beginProgress);
0276:
0277: if (s_log.isDebugEnabled()) {
0278: finish = System.currentTimeMillis();
0279: s_log.debug("Functions loaded in "
0280: + (finish - start) + " ms");
0281: }
0282: } catch (Exception ex) {
0283: s_log.error("Error loading functions", ex);
0284: }
0285:
0286: progress = loadTables(null, null, null, null, progress);
0287: notifyTablesLoaded();
0288:
0289: progress = loadStoredProcedures(null, null, null, progress);
0290: notifyStoredProceduresLoaded();
0291:
0292: } finally {
0293: if (_session != null && _session.getSessionSheet() != null) {
0294: _session.getSessionSheet()
0295: .setStatusBarProgressFinished();
0296: }
0297:
0298: _loading = false;
0299: _loaded = true;
0300: }
0301: if (s_log.isDebugEnabled()) {
0302: mfinish = System.currentTimeMillis();
0303: s_log.debug("SchemaInfo.load took " + (mfinish - mstart)
0304: + " ms");
0305: }
0306: }
0307:
0308: private void notifyStoredProceduresLoaded() {
0309: synchronized (this ) {
0310: _storedProceduresLoaded = true;
0311: this .notifyAll();
0312: }
0313: }
0314:
0315: private void notifyTablesLoaded() {
0316: synchronized (this ) {
0317: _tablesLoaded = true;
0318: this .notifyAll();
0319: }
0320: }
0321:
0322: private void notifySchemasAndCatalogsLoad() {
0323: synchronized (this ) {
0324: _schemasAndCatalogsLoaded = true;
0325: this .notifyAll();
0326: }
0327: }
0328:
0329: private int loadStoredProcedures(String catalog, String schema,
0330: String procNamePattern, int progress) {
0331:
0332: long start = 0, finish = 0;
0333: try {
0334: if (s_log.isDebugEnabled()) {
0335: s_log.debug(i18n.LOADING_PROCS_MSG);
0336: start = System.currentTimeMillis();
0337: }
0338:
0339: int beginProgress = getLoadMethodProgress(progress++);
0340: setProgress(i18n.LOADING_PROCS_MSG, beginProgress);
0341: privateLoadStoredProcedures(catalog, schema,
0342: procNamePattern, i18n.LOADING_PROCS_MSG,
0343: beginProgress);
0344:
0345: if (s_log.isDebugEnabled()) {
0346: finish = System.currentTimeMillis();
0347: s_log.debug("stored procedures loaded in "
0348: + (finish - start) + " ms");
0349: }
0350: } catch (Exception ex) {
0351: s_log.error("Error loading stored procedures", ex);
0352: }
0353: return progress;
0354: }
0355:
0356: private int loadTables(String catalog, String schema,
0357: String tableNamePattern, String[] types, int progress) {
0358: long start = 0, finish = 0;
0359: try {
0360:
0361: if (s_log.isDebugEnabled()) {
0362: s_log.debug(i18n.LOADING_TABLES_MSG);
0363: start = System.currentTimeMillis();
0364: }
0365: int beginProgress = getLoadMethodProgress(progress++);
0366: setProgress(i18n.LOADING_TABLES_MSG, beginProgress);
0367: privateLoadTables(catalog, schema, tableNamePattern, types,
0368: i18n.LOADING_TABLES_MSG, beginProgress);
0369: if (s_log.isDebugEnabled()) {
0370: finish = System.currentTimeMillis();
0371: s_log.debug("Tables loaded in " + (finish - start)
0372: + " ms");
0373: }
0374: } catch (Exception ex) {
0375: s_log.error("Error loading tables", ex);
0376: }
0377: return progress;
0378: }
0379:
0380: private int loadSchemas(int progress) {
0381: long start = 0, finish = 0;
0382: try {
0383: if (s_log.isDebugEnabled()) {
0384: s_log.debug(i18n.LOADING_SCHEMAS_MSG);
0385: start = System.currentTimeMillis();
0386: }
0387:
0388: int beginProgress = getLoadMethodProgress(progress++);
0389: setProgress(i18n.LOADING_SCHEMAS_MSG, beginProgress);
0390: privateLoadSchemas();
0391:
0392: if (s_log.isDebugEnabled()) {
0393: finish = System.currentTimeMillis();
0394: s_log.debug("Schemas loaded in " + (finish - start)
0395: + " ms");
0396: }
0397: } catch (Exception ex) {
0398: s_log.error("Error loading schemas", ex);
0399: }
0400: return progress;
0401: }
0402:
0403: private int loadCatalogs(int progress) {
0404: long start = 0, finish = 0;
0405: try {
0406: if (s_log.isDebugEnabled()) {
0407: s_log.debug(i18n.LOADING_CATALOGS_MSG);
0408: start = System.currentTimeMillis();
0409: }
0410:
0411: int beginProgress = getLoadMethodProgress(progress++);
0412: setProgress(i18n.LOADING_CATALOGS_MSG, beginProgress);
0413: privateLoadCatalogs();
0414:
0415: if (s_log.isDebugEnabled()) {
0416: finish = System.currentTimeMillis();
0417: s_log.debug("Catalogs loaded in " + (finish - start)
0418: + " ms");
0419: }
0420: } catch (Exception ex) {
0421: s_log.error("Error loading catalogs", ex);
0422: }
0423: return progress;
0424: }
0425:
0426: private int getLoadMethodProgress(int progress) {
0427: return (int) (((double) progress)
0428: / ((double) LOAD_METHODS_COUNT) * (MAX_PROGRESS));
0429: }
0430:
0431: private void setProgress(final String note, final int value) {
0432: breathing();
0433:
0434: if (_session == null || _session.getSessionSheet() == null) {
0435: return;
0436: }
0437:
0438: _session.getSessionSheet().setStatusBarProgress(note, 0,
0439: MAX_PROGRESS, value);
0440:
0441: if (_inInitialLoad
0442: && false == _sessionStartupTimeHintShown
0443: && false == _session.getAlias().getSchemaProperties()
0444: .isCacheSchemaIndependentMetaData()
0445: && SQLAliasSchemaProperties.GLOBAL_STATE_LOAD_ALL_CACHE_NONE == _session
0446: .getAlias().getSchemaProperties()
0447: .getGlobalState()
0448: && _session.getApplication().getSquirrelPreferences()
0449: .getShowSessionStartupTimeHint()
0450: && System.currentTimeMillis() - _initalLoadBeginTime > 3000) {
0451: _sessionStartupTimeHintShown = true;
0452: SwingUtilities.invokeLater(new Runnable() {
0453: public void run() {
0454: new SessionStartupTimeHintController(_session);
0455: }
0456: });
0457: }
0458: }
0459:
0460: /**
0461: * We found that the UI behaves much nicer at startup if
0462: * loading schema info interupted for little moments.
0463: */
0464: private void breathing() {
0465: synchronized (this ) {
0466: try {
0467: wait(50);
0468: } catch (InterruptedException e) {
0469: s_log.info("Interrupted", e);
0470: }
0471: }
0472: }
0473:
0474: private void privateLoadStoredProcedures(String catalog,
0475: String schema, String procNamePattern, final String msg,
0476: final int beginProgress) {
0477: try {
0478:
0479: ProgressCallBack pcb = new ProgressCallBack() {
0480: public void currentlyLoading(String simpleName) {
0481: setProgress(msg + " (" + simpleName + ")",
0482: beginProgress);
0483: }
0484: };
0485:
0486: SchemaLoadInfo[] schemaLoadInfos = _schemaInfoCache
0487: .getMatchingSchemaLoadInfos(schema);
0488:
0489: for (int i = 0; i < schemaLoadInfos.length; i++) {
0490: if (schemaLoadInfos[i].loadProcedures) {
0491: IProcedureInfo[] procedures = _dmd.getProcedures(
0492: catalog, schemaLoadInfos[i].schemaName,
0493: procNamePattern, pcb);
0494:
0495: for (int j = 0; j < procedures.length; j++) {
0496: _schemaInfoCache
0497: .writeToProcedureCache(procedures[j]);
0498: }
0499: }
0500: }
0501: } catch (Throwable th) {
0502: s_log.error("Failed to load stored procedures", th);
0503: }
0504:
0505: }
0506:
0507: private void privateLoadCatalogs() {
0508: try {
0509: if (false == _schemaInfoCache
0510: .loadSchemaIndependentMetaData()) {
0511: return;
0512: }
0513:
0514: _schemaInfoCache.writeCatalogs(_dmd.getCatalogs());
0515: } catch (Throwable th) {
0516: s_log.error("failed to load catalog names", th);
0517: }
0518: }
0519:
0520: private void privateLoadSchemas() {
0521: try {
0522:
0523: _session.getApplication().getSessionManager()
0524: .clearAllowedSchemaCache(_session);
0525:
0526: SchemaNameLoadInfo schemaNameLoadInfo = _schemaInfoCache
0527: .getSchemaNameLoadInfo();
0528:
0529: if (SchemaNameLoadInfo.STATE_DONT_REFERESH_SCHEMA_NAMES == schemaNameLoadInfo.state) {
0530: return;
0531: }
0532:
0533: String[] schemasToWrite;
0534: if (SchemaNameLoadInfo.STATE_REFERESH_SCHEMA_NAMES_FROM_DB == schemaNameLoadInfo.state) {
0535: schemasToWrite = _session.getApplication()
0536: .getSessionManager()
0537: .getAllowedSchemas(_session);
0538: } else if (SchemaNameLoadInfo.STATE_USES_PROVIDED_SCHEMA_NAMES == schemaNameLoadInfo.state) {
0539: schemasToWrite = schemaNameLoadInfo.schemaNames;
0540: } else {
0541: throw new IllegalArgumentException(
0542: "Unknown SchemaNameLoadInfo.state = "
0543: + schemaNameLoadInfo.state);
0544: }
0545:
0546: _schemaInfoCache.writeSchemas(schemasToWrite);
0547: } catch (Throwable th) {
0548: s_log.error("failed to load schema names", th);
0549: }
0550: }
0551:
0552: public boolean isKeyword(String data) {
0553: return isKeyword(new CaseInsensitiveString(data));
0554: }
0555:
0556: /**
0557: * Retrieve whether the passed string is a keyword.
0558: *
0559: * @param keyword String to check.
0560: *
0561: * @return <TT>true</TT> if a keyword.
0562: */
0563: public boolean isKeyword(CaseInsensitiveString data) {
0564: if (!_loading && data != null) {
0565: return _schemaInfoCache.getKeywordsForReadOnly()
0566: .containsKey(data);
0567: }
0568: return false;
0569: }
0570:
0571: public boolean isDataType(String data) {
0572: return isDataType(new CaseInsensitiveString(data));
0573: }
0574:
0575: /**
0576: * Retrieve whether the passed string is a data type.
0577: *
0578: * @param keyword String to check.
0579: *
0580: * @return <TT>true</TT> if a data type.
0581: */
0582: public boolean isDataType(CaseInsensitiveString data) {
0583: if (!_loading && data != null) {
0584: return _schemaInfoCache.getDataTypesForReadOnly()
0585: .containsKey(data);
0586: }
0587: return false;
0588: }
0589:
0590: public boolean isFunction(String data) {
0591: return isFunction(new CaseInsensitiveString(data));
0592: }
0593:
0594: /**
0595: * Retrieve whether the passed string is a function.
0596: *
0597: * @param keyword String to check.
0598: *
0599: * @return <TT>true</TT> if a function.
0600: */
0601: public boolean isFunction(CaseInsensitiveString data) {
0602: if (!_loading && data != null) {
0603: return _schemaInfoCache.getFunctionsForReadOnly()
0604: .containsKey(data);
0605: }
0606: return false;
0607: }
0608:
0609: public boolean isTable(String data) {
0610: return isTable(new CaseInsensitiveString(data));
0611: }
0612:
0613: public boolean isTable(CaseInsensitiveString data) {
0614: int tableExtRes = isTableExt(data);
0615: return TABLE_EXT_COLS_LOADED_IN_THIS_CALL == tableExtRes
0616: || TABLE_EXT_COLS_LOADED_BEFORE == tableExtRes;
0617:
0618: }
0619:
0620: /**
0621: * Retrieve whether the passed string is a table and wether this table's colums where loaded before this call.
0622: *
0623: * @param keyword String to check.
0624: *
0625: * @return <TT>true</TT> if a table.
0626: */
0627: public int isTableExt(CaseInsensitiveString data) {
0628: if (!_loading && data != null) {
0629: if (_schemaInfoCache.getTableNamesForReadOnly()
0630: .containsKey(data)) {
0631: if (loadColumns(data)) {
0632: return TABLE_EXT_COLS_LOADED_IN_THIS_CALL;
0633: } else {
0634: return TABLE_EXT_COLS_LOADED_BEFORE;
0635: }
0636: }
0637: }
0638: return TABLE_EXT_NOT_A_TABLE;
0639: }
0640:
0641: public boolean isColumn(String data) {
0642: return isColumn(new CaseInsensitiveString(data));
0643: }
0644:
0645: /**
0646: * Retrieve whether the passed string is a column.
0647: *
0648: * @param keyword String to check.
0649: *
0650: * @return <TT>true</TT> if a column.
0651: */
0652: public boolean isColumn(CaseInsensitiveString data) {
0653: if (!_loading && data != null) {
0654: return _schemaInfoCache
0655: .getExtColumnInfosByColumnNameForReadOnly()
0656: .containsKey(data);
0657: }
0658: return false;
0659: }
0660:
0661: /**
0662: * This method returns the case sensitive name of a table as it is stored
0663: * in the database.
0664: * The case sensitive name is needed for example if you want to retrieve
0665: * a table's meta data. Quote from the API doc of DataBaseMetaData.getTables():
0666: * Parameters:
0667: * ...
0668: * tableNamePattern - a table name pattern; must match the table name as it is stored in the database
0669: *
0670: *
0671: * @param data The tables name in arbitrary case.
0672: * @return the table name as it is stored in the database
0673: */
0674: public String getCaseSensitiveTableName(String data) {
0675: if (!_loading && data != null) {
0676: return _schemaInfoCache.getTableNamesForReadOnly().get(
0677: new CaseInsensitiveString(data));
0678: }
0679: return null;
0680: }
0681:
0682: public String getCaseSensitiveProcedureName(String data) {
0683: if (!_loading && data != null) {
0684: return _schemaInfoCache.getProcedureNamesForReadOnly().get(
0685: new CaseInsensitiveString(data));
0686: }
0687: return null;
0688: }
0689:
0690: private void loadKeywords(String msg, int beginProgress) {
0691: try {
0692: if (false == _schemaInfoCache
0693: .loadSchemaIndependentMetaData()) {
0694: return;
0695: }
0696:
0697: setProgress(msg + " (default keywords)", beginProgress);
0698:
0699: Hashtable<CaseInsensitiveString, String> keywordsBuf = new Hashtable<CaseInsensitiveString, String>();
0700:
0701: for (int i = 0; i < DefaultKeywords.KEY_WORDS.length; i++) {
0702: String kw = DefaultKeywords.KEY_WORDS[i];
0703: keywordsBuf.put(new CaseInsensitiveString(kw), kw);
0704: }
0705:
0706: // Extra keywords that this DBMS supports.
0707: if (_dmd != null) {
0708:
0709: setProgress(msg + " (DB specific keywords)",
0710: beginProgress);
0711:
0712: String[] sqlKeywords = _dmd.getSQLKeywords();
0713:
0714: for (int i = 0; i < sqlKeywords.length; i++) {
0715: _schemaInfoCache.getKeywordsForReadOnly().put(
0716: new CaseInsensitiveString(sqlKeywords[i]),
0717: sqlKeywords[i]);
0718: }
0719:
0720: String catalogTerm = _dmd.getCatalogTerm();
0721: if (catalogTerm != null) {
0722: keywordsBuf.put(new CaseInsensitiveString(
0723: catalogTerm), catalogTerm);
0724: }
0725:
0726: String schemaTerm = _dmd.getSchemaTerm();
0727: if (schemaTerm != null) {
0728: keywordsBuf.put(new CaseInsensitiveString(
0729: schemaTerm), schemaTerm);
0730: }
0731:
0732: String procedureTerm = _dmd.getProcedureTerm();
0733: if (procedureTerm != null) {
0734: keywordsBuf.put(new CaseInsensitiveString(
0735: procedureTerm), procedureTerm);
0736: }
0737: }
0738:
0739: _schemaInfoCache.writeKeywords(keywordsBuf);
0740: } catch (Throwable ex) {
0741: s_log
0742: .error("Error occured creating keyword collection",
0743: ex);
0744: }
0745: }
0746:
0747: private void loadDataTypes(String msg, int beginProgress) {
0748: try {
0749: if (false == _schemaInfoCache
0750: .loadSchemaIndependentMetaData()) {
0751: return;
0752: }
0753:
0754: Hashtable<CaseInsensitiveString, String> dataTypesBuf = new Hashtable<CaseInsensitiveString, String>();
0755:
0756: DataTypeInfo[] infos = _dmd.getDataTypes();
0757: for (int i = 0; i < infos.length; i++) {
0758: String typeName = infos[i].getSimpleName();
0759: dataTypesBuf.put(new CaseInsensitiveString(typeName),
0760: typeName);
0761:
0762: if (0 == i % 100) {
0763: setProgress(msg + " (" + typeName + ")",
0764: beginProgress);
0765: }
0766:
0767: }
0768:
0769: _schemaInfoCache.writeDataTypes(dataTypesBuf);
0770: } catch (Throwable ex) {
0771: s_log.error("Error occured creating data types collection",
0772: ex);
0773: }
0774: }
0775:
0776: private void loadGlobalFunctions(String msg, int beginProgress) {
0777: if (false == _schemaInfoCache.loadSchemaIndependentMetaData()) {
0778: return;
0779: }
0780:
0781: ArrayList<String> buf = new ArrayList<String>();
0782:
0783: try {
0784: setProgress(msg + " (numeric functions)", beginProgress);
0785: buf.addAll(Arrays.asList(_dmd.getNumericFunctions()));
0786: } catch (Throwable ex) {
0787: s_log.error("Error", ex);
0788: }
0789:
0790: try {
0791: setProgress(msg + " (string functions)", beginProgress);
0792: buf.addAll(Arrays.asList((_dmd.getStringFunctions())));
0793: } catch (Throwable ex) {
0794: s_log.error("Error", ex);
0795: }
0796:
0797: try {
0798: setProgress(msg + " (time/date functions)", beginProgress);
0799: buf.addAll(Arrays.asList(_dmd.getTimeDateFunctions()));
0800: } catch (Throwable ex) {
0801: s_log.error("Error", ex);
0802: }
0803:
0804: Hashtable<CaseInsensitiveString, String> functionsBuf = new Hashtable<CaseInsensitiveString, String>();
0805: for (int i = 0; i < buf.size(); i++) {
0806: String func = buf.get(i);
0807: if (func.length() > 0) {
0808: functionsBuf.put(new CaseInsensitiveString(func), func);
0809: }
0810:
0811: }
0812:
0813: _schemaInfoCache.writeFunctions(functionsBuf);
0814: }
0815:
0816: public String[] getKeywords() {
0817: return _schemaInfoCache.getKeywordsForReadOnly().values()
0818: .toArray(
0819: new String[_schemaInfoCache
0820: .getKeywordsForReadOnly().size()]);
0821: }
0822:
0823: public String[] getDataTypes() {
0824: return _schemaInfoCache.getDataTypesForReadOnly().values()
0825: .toArray(
0826: new String[_schemaInfoCache
0827: .getDataTypesForReadOnly().size()]);
0828: }
0829:
0830: public String[] getFunctions() {
0831: return _schemaInfoCache.getFunctionsForReadOnly().values()
0832: .toArray(
0833: new String[_schemaInfoCache
0834: .getFunctionsForReadOnly().size()]);
0835: }
0836:
0837: public String[] getTables() {
0838: return _schemaInfoCache.getTableNamesForReadOnly().values()
0839: .toArray(
0840: new String[_schemaInfoCache
0841: .getTableNamesForReadOnly().size()]);
0842: }
0843:
0844: public String[] getCatalogs() {
0845: return _schemaInfoCache.getCatalogsForReadOnly().toArray(
0846: new String[_schemaInfoCache.getCatalogsForReadOnly()
0847: .size()]);
0848: }
0849:
0850: public String[] getSchemas() {
0851: return _schemaInfoCache.getSchemasForReadOnly().toArray(
0852: new String[_schemaInfoCache.getSchemasForReadOnly()
0853: .size()]);
0854: }
0855:
0856: public ITableInfo[] getITableInfos() {
0857: return getITableInfos(null, null);
0858: }
0859:
0860: public ITableInfo[] getITableInfos(String catalog, String schema) {
0861: return getITableInfos(catalog, schema, null);
0862: }
0863:
0864: public ITableInfo[] getITableInfos(String catalog, String schema,
0865: String simpleName) {
0866: return getITableInfos(catalog, schema, simpleName, null);
0867: }
0868:
0869: public ITableInfo[] getITableInfos(String catalog, String schema,
0870: String tableNamePattern, String[] types) {
0871: ArrayList<ITableInfo> ret = new ArrayList<ITableInfo>();
0872: if (null != types) {
0873: // By default null == types we return only cached types
0874: ITableInfo[] tableInfosForUncachedTypes = getTableInfosForUncachedTypes(
0875: catalog, schema, tableNamePattern, types);
0876: ret.addAll(Arrays.asList(tableInfosForUncachedTypes));
0877: }
0878:
0879: List<ITableInfo> tis = _schemaInfoCache
0880: .getITableInfosForReadOnly();
0881: for (ITableInfo iTableInfo : tis) {
0882: if (null != catalog
0883: && false == catalog.equalsIgnoreCase(iTableInfo
0884: .getCatalogName())
0885: && false == fulfillsPlatformDependendMatches(
0886: iTableInfo, catalog)) {
0887: continue;
0888: }
0889:
0890: if (null != schema
0891: && false == schema.equalsIgnoreCase(iTableInfo
0892: .getSchemaName())) {
0893: continue;
0894: }
0895:
0896: if (false == SchemaInfoCache.containsType(types, iTableInfo
0897: .getType())) {
0898: continue;
0899: }
0900:
0901: if (null != tableNamePattern
0902: && false == tableNamePattern.endsWith("%")
0903: && false == iTableInfo.getSimpleName().equals(
0904: tableNamePattern)) {
0905: continue;
0906: }
0907:
0908: if (null != tableNamePattern
0909: && tableNamePattern.endsWith("%")) {
0910: String tableNameBegin = tableNamePattern.substring(0,
0911: tableNamePattern.length() - 1);
0912: if (false == iTableInfo.getSimpleName().startsWith(
0913: tableNameBegin)) {
0914: continue;
0915: }
0916: }
0917:
0918: ret.add(iTableInfo);
0919: }
0920:
0921: return ret.toArray(new ITableInfo[ret.size()]);
0922: }
0923:
0924: private boolean fulfillsPlatformDependendMatches(
0925: ITableInfo iTableInfo, String catalog) {
0926: if (SQLDatabaseMetaData.DriverMatch.isComHttxDriver(_session
0927: .getSQLConnection())) {
0928: return (iTableInfo.getCatalogName() == null && "\".\""
0929: .equals(catalog));
0930: } else {
0931: return false;
0932: }
0933:
0934: }
0935:
0936: private ITableInfo[] getTableInfosForUncachedTypes(String catalog,
0937: String schema, String tableNamePattern, String[] types) {
0938: try {
0939: ArrayList<String> missingTypes = new ArrayList<String>();
0940: for (int i = 0; i < types.length; i++) {
0941: if (false == _schemaInfoCache
0942: .isCachedTableType(types[i])) {
0943: missingTypes.add(types[i]);
0944: }
0945: }
0946:
0947: if (0 < missingTypes.size()) {
0948: try {
0949: String[] buf = missingTypes
0950: .toArray(new String[missingTypes.size()]);
0951: ProgressCallBack pcb = new ProgressCallBack() {
0952: public void currentlyLoading(String simpleName) {
0953: StringBuilder tmp = new StringBuilder(
0954: i18n.LOADING_TABLES_MSG);
0955: tmp.append(" (");
0956: tmp.append(simpleName);
0957: tmp.append(")");
0958: setProgress(tmp.toString(), 1);
0959: }
0960: };
0961: return _dmd.getTables(catalog, schema,
0962: tableNamePattern, buf, pcb);
0963: } finally {
0964: _session.getSessionSheet()
0965: .setStatusBarProgressFinished();
0966: }
0967: }
0968:
0969: } catch (SQLException e) {
0970: s_log.error("Error loading uncached tables", e);
0971: }
0972:
0973: return new ITableInfo[0];
0974: }
0975:
0976: public IProcedureInfo[] getStoredProceduresInfos(String catalog,
0977: String schema) {
0978: return getStoredProceduresInfos(catalog, schema, null);
0979: }
0980:
0981: public IProcedureInfo[] getStoredProceduresInfos(String catalog,
0982: String schema, String procNamePattern) {
0983: ArrayList<IProcedureInfo> ret = new ArrayList<IProcedureInfo>();
0984:
0985: for (Iterator<IProcedureInfo> i = _schemaInfoCache
0986: .getIProcedureInfosForReadOnly().keySet().iterator(); i
0987: .hasNext();) {
0988:
0989: IProcedureInfo iProcInfo = i.next();
0990: boolean toAdd = true;
0991: if (null != catalog
0992: && false == catalog.equalsIgnoreCase(iProcInfo
0993: .getCatalogName())) {
0994: toAdd = false;
0995: }
0996:
0997: if (null != schema
0998: && false == schema.equalsIgnoreCase(iProcInfo
0999: .getSchemaName())) {
1000: toAdd = false;
1001: }
1002:
1003: if (null != procNamePattern
1004: && false == procNamePattern.endsWith("%")
1005: && false == iProcInfo.getSimpleName().equals(
1006: procNamePattern)) {
1007: toAdd = false;
1008: }
1009:
1010: if (null != procNamePattern
1011: && procNamePattern.endsWith("%")) {
1012: String tableNameBegin = procNamePattern.substring(0,
1013: procNamePattern.length() - 1);
1014: if (false == iProcInfo.getSimpleName().startsWith(
1015: tableNameBegin)) {
1016: toAdd = false;
1017: }
1018: }
1019:
1020: if (toAdd) {
1021: ret.add(iProcInfo);
1022: }
1023: }
1024:
1025: return ret.toArray(new IProcedureInfo[ret.size()]);
1026: }
1027:
1028: public boolean isLoaded() {
1029: return _loaded;
1030: }
1031:
1032: private void privateLoadTables(String catalog, String schema,
1033: String tableNamePattern, String[] types, final String msg,
1034: final int beginProgress) {
1035: try {
1036: ProgressCallBack pcb = new ProgressCallBack() {
1037: public void currentlyLoading(String simpleName) {
1038: setProgress(msg + " (" + simpleName + ")",
1039: beginProgress);
1040: }
1041: };
1042: SchemaLoadInfo[] schemaLoadInfos = _schemaInfoCache
1043: .getMatchingSchemaLoadInfos(schema, types);
1044:
1045: for (int i = 0; i < schemaLoadInfos.length; i++) {
1046: ITableInfo[] infos = _dmd.getTables(catalog,
1047: schemaLoadInfos[i].schemaName,
1048: tableNamePattern,
1049: schemaLoadInfos[i].tableTypes, pcb);
1050: _schemaInfoCache.writeToTableCache(infos);
1051: }
1052: } catch (Throwable th) {
1053: s_log.error("failed to load table names", th);
1054: }
1055: }
1056:
1057: /**
1058: *
1059: * @return true only when the table's columns are loaded within this call.
1060: */
1061: private boolean loadColumns(final CaseInsensitiveString tableName) {
1062: try {
1063: if (_schemaInfoCache
1064: .getExtendedColumnInfosByTableNameForReadOnly()
1065: .containsKey(tableName)) {
1066: return false;
1067: }
1068:
1069: if (_session.getProperties().getLoadColumnsInBackground()) {
1070: if (_tablesLoadingColsInBackground
1071: .containsKey(tableName)) {
1072: return false;
1073: }
1074:
1075: // Note: A CaseInsensitiveString can be a mutable string.
1076: // In fact it is a mutable string here because this is usually called from
1077: // within Syntax coloring which uses a mutable string.
1078: final CaseInsensitiveString imutableString = new CaseInsensitiveString(
1079: tableName.toString());
1080: _tablesLoadingColsInBackground.put(imutableString,
1081: imutableString);
1082: _session.getApplication().getThreadPool().addTask(
1083: new Runnable() {
1084: public void run() {
1085: try {
1086: accessDbToLoadColumns(imutableString);
1087: _tablesLoadingColsInBackground
1088: .remove(imutableString);
1089: } catch (SQLException e) {
1090: throw new RuntimeException(e);
1091: }
1092: }
1093: });
1094: } else {
1095: accessDbToLoadColumns(tableName);
1096: }
1097: } catch (Throwable th) {
1098: s_log.error("failed to load table names", th);
1099: }
1100:
1101: return true;
1102: }
1103:
1104: private void accessDbToLoadColumns(CaseInsensitiveString tableName)
1105: throws SQLException {
1106: if (null == _dmd) {
1107: s_log.warn(s_stringMgr.getString(
1108: "SchemaInfo.UnableToLoadColumns", tableName));
1109: return;
1110: }
1111: String name = getCaseSensitiveTableName(tableName.toString());
1112: TableInfo ti = new TableInfo(null, null, name, "TABLE", null,
1113: _dmd);
1114: TableColumnInfo[] infos = _dmd.getColumnInfo(ti);
1115: _schemaInfoCache.writeColumsToCache(infos, tableName);
1116: }
1117:
1118: public ExtendedColumnInfo[] getExtendedColumnInfos(String tableName) {
1119: return getExtendedColumnInfos(null, null, tableName);
1120: }
1121:
1122: public ExtendedColumnInfo[] getExtendedColumnInfos(String catalog,
1123: String schema, String tableName) {
1124: CaseInsensitiveString cissTableName = new CaseInsensitiveString(
1125: tableName);
1126: loadColumns(cissTableName);
1127: List<ExtendedColumnInfo> extColInfo = _schemaInfoCache
1128: .getExtendedColumnInfosByTableNameForReadOnly().get(
1129: cissTableName);
1130:
1131: if (null == extColInfo) {
1132: return new ExtendedColumnInfo[0];
1133: }
1134:
1135: if (null == catalog && null == schema) {
1136: return extColInfo.toArray(new ExtendedColumnInfo[extColInfo
1137: .size()]);
1138: } else {
1139: ArrayList<ExtendedColumnInfo> ret = new ArrayList<ExtendedColumnInfo>();
1140:
1141: for (int i = 0; i < extColInfo.size(); i++) {
1142: ExtendedColumnInfo extendedColumnInfo = extColInfo
1143: .get(i);
1144: boolean toAdd = true;
1145: if (null != catalog
1146: && false == catalog
1147: .equalsIgnoreCase(extendedColumnInfo
1148: .getCatalog())) {
1149: toAdd = false;
1150: }
1151:
1152: if (null != schema
1153: && false == schema
1154: .equalsIgnoreCase(extendedColumnInfo
1155: .getSchema())) {
1156: toAdd = false;
1157: }
1158:
1159: if (toAdd) {
1160: ret.add(extendedColumnInfo);
1161: }
1162: }
1163:
1164: return ret.toArray(new ExtendedColumnInfo[ret.size()]);
1165: }
1166: }
1167:
1168: public void dispose() {
1169: // The SessionManager is global to SQuirreL.
1170: // If we don't remove the listeners the
1171: // Session won't get Garbeage Collected.
1172: _session.getApplication().getSessionManager()
1173: .removeSessionListener(_sessionListener);
1174: }
1175:
1176: public boolean isProcedure(CaseInsensitiveString data) {
1177: return _schemaInfoCache.getProcedureNamesForReadOnly()
1178: .containsKey(data);
1179: }
1180:
1181: public void reload(IDatabaseObjectInfo doi) {
1182: reload(doi, true);
1183: }
1184:
1185: /**
1186: * @param fireSchemaInfoUpdate Should only be false when the caller makes sure fireSchemaInfoUpdate() is called later.
1187: */
1188: void reload(IDatabaseObjectInfo doi, boolean fireSchemaInfoUpdate) {
1189: boolean doReloadAll = false;
1190:
1191: try {
1192: synchronized (this ) {
1193: if (_loading) {
1194: return;
1195: }
1196: _loading = true;
1197: _schemasAndCatalogsLoaded = false;
1198: _tablesLoaded = false;
1199: _storedProceduresLoaded = false;
1200:
1201: }
1202:
1203: if (doi instanceof ITableInfo) {
1204: ITableInfo ti = (ITableInfo) doi;
1205: DatabaseObjectType dot = ti.getDatabaseObjectType();
1206:
1207: String[] types = null;
1208: if (DatabaseObjectType.TABLE == dot) {
1209: types = new String[] { "TABLE" };
1210: } else if (DatabaseObjectType.VIEW == dot) {
1211: types = new String[] { "VIEW" };
1212: }
1213:
1214: _schemaInfoCache.clearTables(ti.getCatalogName(), ti
1215: .getSchemaName(), ti.getSimpleName(), types);
1216: loadTables(ti.getCatalogName(), ti.getSchemaName(), ti
1217: .getSimpleName(), types, 1);
1218: } else if (doi instanceof IProcedureInfo) {
1219: IProcedureInfo pi = (IProcedureInfo) doi;
1220: _schemaInfoCache.clearStoredProcedures(pi
1221: .getCatalogName(), pi.getSchemaName(), pi
1222: .getSimpleName());
1223: loadStoredProcedures(pi.getCatalogName(), pi
1224: .getSchemaName(), pi.getSimpleName(), 1);
1225: } else if (DatabaseObjectType.TABLE_TYPE_DBO == doi
1226: .getDatabaseObjectType()) {
1227: // load all table types with catalog = doi.getCatalog() and schema = doi.getSchema()
1228: _schemaInfoCache.clearTables(doi.getCatalogName(), doi
1229: .getSchemaName(), null, null);
1230: loadTables(doi.getCatalogName(), doi.getSchemaName(),
1231: null, null, 0);
1232: } else if (DatabaseObjectType.TABLE == doi
1233: .getDatabaseObjectType()) {
1234: // load tables with catalog = doi.getCatalog() and schema = doi.getSchema()
1235: _schemaInfoCache.clearTables(doi.getCatalogName(), doi
1236: .getSchemaName(), null,
1237: new String[] { "TABLE" });
1238: loadTables(doi.getCatalogName(), doi.getSchemaName(),
1239: null, new String[] { "TABLE" }, 1);
1240: } else if (DatabaseObjectType.VIEW == doi
1241: .getDatabaseObjectType()) {
1242: // load views with catalog = doi.getCatalog() and schema = doi.getSchema()
1243: _schemaInfoCache
1244: .clearTables(doi.getCatalogName(), doi
1245: .getSchemaName(), null,
1246: new String[] { "VIEW" });
1247: loadTables(doi.getCatalogName(), doi.getSchemaName(),
1248: null, new String[] { "VIEW" }, 1);
1249: } else if (DatabaseObjectType.PROCEDURE == doi
1250: .getDatabaseObjectType()
1251: || DatabaseObjectType.PROC_TYPE_DBO == doi
1252: .getDatabaseObjectType()) {
1253: _schemaInfoCache.clearStoredProcedures(doi
1254: .getCatalogName(), doi.getSchemaName(), null);
1255: loadStoredProcedures(doi.getCatalogName(), doi
1256: .getSchemaName(), null, 1);
1257: } else if (DatabaseObjectType.SCHEMA == doi
1258: .getDatabaseObjectType()) {
1259: //int progress = loadSchemas(1);
1260: // load tables with catalog = null
1261: _schemaInfoCache.clearTables(null, doi.getSchemaName(),
1262: null, null);
1263: int progress = loadTables(null, doi.getSchemaName(),
1264: null, null, 1);
1265:
1266: // load procedures with catalog = null
1267: _schemaInfoCache.clearStoredProcedures(null, doi
1268: .getSchemaName(), null);
1269: loadStoredProcedures(null, doi.getSchemaName(), null,
1270: progress);
1271: } else if (DatabaseObjectType.CATALOG == doi
1272: .getDatabaseObjectType()) {
1273: //int progress = loadCatalogs(1);
1274: // load tables with schema = null
1275: _schemaInfoCache.clearTables(doi.getCatalogName(),
1276: null, null, null);
1277: int progress = loadTables(doi.getCatalogName(), null,
1278: null, null, 1);
1279:
1280: // load procedures with schema = null
1281: _schemaInfoCache.clearStoredProcedures(doi
1282: .getCatalogName(), null, null);
1283: loadStoredProcedures(doi.getCatalogName(), null, null,
1284: progress);
1285: } else if (DatabaseObjectType.SESSION == doi
1286: .getDatabaseObjectType()) {
1287: doReloadAll = true;
1288: }
1289:
1290: // If called here it is called far to often and restoring selection in the
1291: // Object tree doesn't work.
1292: //fireSchemaInfoUpdate();
1293: } finally {
1294: _session.getSessionSheet().setStatusBarProgressFinished();
1295: _loading = false;
1296: _schemasAndCatalogsLoaded = true;
1297: _tablesLoaded = true;
1298: _storedProceduresLoaded = true;
1299: notifySchemasAndCatalogsLoad();
1300: notifyTablesLoaded();
1301: notifyStoredProceduresLoaded();
1302:
1303: if (doReloadAll) {
1304: reloadAll(fireSchemaInfoUpdate);
1305: } else {
1306: if (fireSchemaInfoUpdate) {
1307: fireSchemaInfoUpdate();
1308: }
1309: }
1310: }
1311: }
1312:
1313: public void fireSchemaInfoUpdate() {
1314: SwingUtilities.invokeLater(new Runnable() {
1315: public void run() {
1316: SchemaInfoUpdateListener[] listeners = _listeners
1317: .toArray(new SchemaInfoUpdateListener[0]);
1318:
1319: for (int i = 0; i < listeners.length; i++) {
1320: listeners[i].schemaInfoUpdated();
1321: }
1322: }
1323: });
1324:
1325: }
1326:
1327: public void addSchemaInfoUpdateListener(SchemaInfoUpdateListener l) {
1328: _listeners.remove(l);
1329: _listeners.add(l);
1330: }
1331:
1332: public void removeSchemaInfoUpdateListener(
1333: SchemaInfoUpdateListener l) {
1334: _listeners.remove(l);
1335: }
1336:
1337: public void refershCacheForSimpleTableName(String simpleTableName) {
1338: refershCacheForSimpleTableName(simpleTableName, true);
1339: }
1340:
1341: /**
1342: * @param fireSchemaInfoUpdate Should only be false when the caller makes sure fireSchemaInfoUpdate() is called later.
1343: */
1344: void refershCacheForSimpleTableName(String simpleTableName,
1345: boolean fireSchemaInfoUpdate) {
1346: HashMap<String, String> caseSensitiveTableNames = new HashMap<String, String>();
1347:
1348: CaseInsensitiveString caseInsensitiveTableName = new CaseInsensitiveString(
1349: simpleTableName);
1350: String caseSensitiveTableName = _schemaInfoCache
1351: .getTableNamesForReadOnly().get(
1352: caseInsensitiveTableName);
1353:
1354: caseSensitiveTableNames.put(caseSensitiveTableName,
1355: caseSensitiveTableName);
1356:
1357: ////////////////////////////////////////////////////////////////////////
1358: // Reload all matching table types
1359: for (Iterator<String> i = caseSensitiveTableNames.keySet()
1360: .iterator(); i.hasNext();) {
1361: String buf = i.next();
1362: TableInfo ti = new TableInfo(null, null, buf, null, null,
1363: _dmd);
1364: reload(ti, fireSchemaInfoUpdate);
1365: }
1366: //
1367: ////////////////////////////////////////////////////////////////////////
1368:
1369: // is done in reload
1370: // if(fireSchemaInfoUpdate)
1371: // {
1372: // fireSchemaInfoUpdate();
1373: // }
1374: }
1375:
1376: public void refreshCacheForSimpleProcedureName(String simpleProcName) {
1377: refreshCacheForSimpleProcedureName(simpleProcName, true);
1378: }
1379:
1380: /**
1381: * @param fireSchemaInfoUpdate Should only be false when the caller makes sure fireSchemaInfoUpdate() is called later.
1382: */
1383: void refreshCacheForSimpleProcedureName(String simpleProcName,
1384: boolean fireSchemaInfoUpdate) {
1385: HashMap<String, String> caseSensitiveProcNames = new HashMap<String, String>();
1386:
1387: CaseInsensitiveString caseInsensitiveProcName = new CaseInsensitiveString(
1388: simpleProcName);
1389: String caseSensitiveProcName = _schemaInfoCache
1390: .getProcedureNamesForReadOnly().remove(
1391: caseInsensitiveProcName);
1392:
1393: caseSensitiveProcNames.put(caseSensitiveProcName,
1394: caseSensitiveProcName);
1395:
1396: ////////////////////////////////////////////////////////////////////////
1397: // Reload all matching procedure types
1398: for (Iterator<String> i = caseSensitiveProcNames.keySet()
1399: .iterator(); i.hasNext();) {
1400: String buf = i.next();
1401: ProcedureInfo pi = new ProcedureInfo(null, null, buf, null,
1402: DatabaseMetaData.procedureResultUnknown, _dmd);
1403: reload(pi, fireSchemaInfoUpdate);
1404: }
1405: //
1406: ////////////////////////////////////////////////////////////////////////
1407:
1408: // is done in reload
1409: // if(fireSchemaInfoUpdate)
1410: // {
1411: // fireSchemaInfoUpdate();
1412: // }
1413: }
1414:
1415: public void waitTillSchemasAndCatalogsLoaded() {
1416: try {
1417: synchronized (this ) {
1418: while (false == _schemasAndCatalogsLoaded) {
1419: this .wait();
1420: }
1421: }
1422: } catch (InterruptedException e) {
1423: throw new RuntimeException(e);
1424: }
1425: }
1426:
1427: public void waitTillTablesLoaded() {
1428: try {
1429: synchronized (this ) {
1430: while (false == _tablesLoaded) {
1431: this .wait();
1432: }
1433: }
1434: } catch (InterruptedException e) {
1435: throw new RuntimeException(e);
1436: }
1437: }
1438:
1439: public void waitTillStoredProceduresLoaded() {
1440: try {
1441: synchronized (this ) {
1442: while (false == _storedProceduresLoaded) {
1443: this .wait();
1444: }
1445: }
1446: } catch (InterruptedException e) {
1447: throw new RuntimeException(e);
1448: }
1449: }
1450:
1451: }
|