View Javadoc
1 /* 2 * PROJECT : DAR Runtime and Tools 3 * COPYRIGHT : Copyright (C) 1999-2004 tim.stephenson@enableit.org 4 * LICENSE : GNU LESSER GENERAL PUBLIC LICENSE 5 * Version 2.1, February 1999 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package org.enableit.db.darrt; 22 23 import java.io.File; 24 import java.io.FileReader; 25 import java.io.FileWriter; 26 import java.io.IOException; 27 import java.util.HashMap; 28 29 import org.apache.log4j.Logger; 30 import org.enableit.db.DBException; 31 import org.enableit.db.beans.Database; 32 import org.enableit.db.beans.Provider; 33 import org.enableit.db.beans.ProviderExt; 34 import org.enableit.db.beans.Schema; 35 import org.enableit.db.beans.Table; 36 import org.exolab.castor.xml.CastorException; 37 import org.exolab.castor.xml.Unmarshaller; 38 import org.w3c.dom.Document; 39 40 41 /*** 42 * Factory for DBMS table meta data. 43 * 44 * @author Tim Stephenson 45 */ 46 public class MetaDataFactory extends AbstractFileHandler { 47 private static MetaDataFactory me; 48 49 /*** 50 * The Log4J <code>Logger</code> doing the logging. 51 */ 52 private static Logger logger = Logger.getLogger(MetaDataFactory.class); 53 54 /*** 55 * CVS info ABOUT this class and its current version 56 */ 57 public static final String ABOUT = "$Revision: 1.4 $"; 58 59 private static HashMap databases; 60 61 // TODO Make singleton 62 63 /*** 64 * Constructor preserves singleton status. 65 */ 66 private MetaDataFactory() { 67 synchronized (MetaDataFactory.class) { 68 databases = new HashMap(); 69 } 70 } 71 72 public static MetaDataFactory getInstance() { 73 if (me == null) { 74 synchronized (MetaDataFactory.class) { 75 me = new MetaDataFactory(); 76 } 77 } 78 79 return me; 80 } 81 82 /*** 83 * @param provider Information ABOUT how to obtain connection 84 * to the database. 85 * @return Table instance describing the table, never null. 86 * @throws DBException If meta data cannot be obtained. 87 */ 88 public Database getMetaData(Provider provider) 89 throws DBException { 90 Database database = getMetaData(provider, false); 91 92 return database; 93 } 94 95 /*** 96 * @param provider Information ABOUT how to obtain connection 97 * to the database. 98 * @param refresh Should cache be refreshed? 99 * @return Table instance describing the table, never null. 100 * @throws DBException If meta data cannot be obtained. 101 */ 102 public Database getMetaData(Provider provider, boolean refresh) 103 throws DBException { 104 logger.info("METHOD_ENTRY: getMetaData, provider= " 105 + ProviderExt.toString(provider)); 106 107 Database database = null; 108 109 if (refresh) { 110 databases.remove(provider); 111 } 112 113 if (databases.containsKey(provider)) { 114 database = (Database) databases.get(provider); 115 } else { 116 try { 117 SchemaExporter se = new SchemaExporter(); 118 119 database = getMetaDataFromPersistentCache(se, provider, refresh); 120 121 if (database == null) { 122 // Go get fresh meta-data 123 //se.setTablePattern("TABLE, VIEW") ; 124 if (provider.getSchemaName() != null) { 125 se.setSchemaName(provider.getSchemaName()); 126 } 127 128 Document doc = se.exportToFile(provider, 129 SchemaConstants.OM_SINGLE_FILE_AND_FILE_PER_TABLE); 130 131 database = (Database) Unmarshaller.unmarshal(Database.class, 132 doc); 133 134 // Add to in-memory cache 135 setMetaData(provider, database) ; 136 } else { 137 logger.warn("Found from persistent cache"); 138 } 139 } catch (Exception e) { 140 logger.error(e.getMessage(), e); 141 throw new DBException(e.getMessage(), e); 142 } 143 } 144 145 logger.info("METHOD_EXIT: getMetaData"); 146 147 return database; 148 } 149 150 /*** 151 * @param se 152 * @return 153 */ 154 private Database getMetaDataFromPersistentCache(SchemaExporter se, 155 Provider provider, boolean refresh) { 156 Database database = null; 157 158 try { 159 File dbFile = new File(getOperDir(), se.getFileName(provider)); 160 161 if (refresh && dbFile.exists()) { 162 dbFile.delete(); 163 164 // remove dir that holds per-table files 165 new File(dbFile.getParent(), "schema"); 166 } else if (dbFile.exists()) { 167 database = Database.unmarshal(new FileReader(dbFile)); 168 } else { 169 // TODO: Check if we have a file in user.dir? 170 // (if user dir is different to oper dir) 171 } 172 } catch (Exception e) { 173 logger.warn("Unable to find persistently cached schema: " 174 + e.getMessage(), e); 175 } 176 177 return database; 178 } 179 180 /*** 181 * @param provider Information ABOUT how to obtain connection 182 * to the database. 183 * @param tableName Name of table whose metadata is sought. 184 * @return Table instance describing the table, never null. 185 * @throws DBException If meta data cannot be obtained. 186 */ 187 public Table getMetaData(Provider provider, String tableName) 188 throws DBException { 189 logger.info("METHOD_ENTRY: getMetaData, provider= " 190 + ProviderExt.toString(provider) + "tableName=" + tableName); 191 192 File tableHome = null ; 193 Table table = null; 194 195 try { 196 if (databases.get(provider) != null) { 197 Database db = (Database) databases.get(provider) ; 198 for (int i = 0 ; i < db.getSchemaCount() ; i++) { 199 Schema schema = db.getSchema(i) ; 200 for (int j = 0 ; j < schema.getTableCount() ; j++) { 201 Table t = schema.getTable(j) ; 202 if (tableName.equals(t.getName())) { 203 table = t ; 204 break; 205 } 206 } 207 } 208 } 209 210 // TODO: replace with perisitent cache method 211 // Try for cached table file 212 if (table == null) { 213 File darrtHome = getOperDir(); 214 SchemaExporter se = new SchemaExporter(); 215 String tableHomeName = se.getFileName(provider) ; 216 tableHome = new File(darrtHome, 217 tableHomeName.substring(0, tableHomeName.indexOf(".xml"))); 218 219 // Do we have file of this meta data in temp dir? 220 File tableFile = new File(tableHome, tableName + ".xml"); 221 222 if (tableFile.exists()) { 223 table = Table.unmarshal(new FileReader(tableFile)); 224 } 225 } 226 if (table == null) { 227 // Go get fresh meta-data 228 Database database = getMetaData(provider); 229 230 for (int j = 0; j < database.getSchemaCount(); j++) { 231 Schema schema = database.getSchema(j); 232 233 for (int i = 0; i < schema.getTableCount(); i++) { 234 // TODO: Disregard case of table name? 235 if (tableName.equals(schema.getTable(i).getName())) { 236 table = schema.getTable(i); 237 238 break; 239 } 240 } 241 } 242 243 if (table == null) { 244 throw new DBException("Unable to find meta data for " 245 + tableName); 246 } 247 248 // Save for next time 249 tableHome.mkdirs(); 250 251 FileWriter fw = new FileWriter(new File(tableHome, 252 tableName + ".xml")); 253 254 table.marshal(fw); 255 } 256 } catch (DBException e) { 257 throw e ; 258 } catch (IOException e) { 259 logger.error(e.getMessage(), e); 260 throw new DBException(e.getMessage(), e); 261 } catch (CastorException e) { 262 logger.error(e.getMessage(), e); 263 throw new DBException(e.getMessage(), e); 264 } 265 266 logger.info("METHOD_EXIT: getMetaData"); 267 268 return table; 269 } 270 271 /*** 272 * Allows an external class to specify meta-data rather than forcing it to 273 * be detected from an active connection. 274 * 275 * <p><b>Implementation Note:</p>The requirement for this method comes from 276 * <code>DarHandler</code>, as it seems 277 * JDBC meta data is not available immediately. Not sure why this is since 278 * the schema creation connection has been closed.</p> 279 * @param provider 280 * @param db 281 */ 282 protected void setMetaData(Provider provider, Database db) { 283 synchronized (MetaDataFactory.class) { 284 synchronized (databases) { 285 databases.put(provider, db); 286 } 287 } 288 } 289 }

This page was automatically generated by Maven