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.sql.Connection; 24 import java.sql.SQLException; 25 import java.util.ArrayList; 26 import java.util.HashMap; 27 import java.util.Iterator; 28 import java.util.List; 29 import java.util.Map; 30 31 import org.apache.log4j.Logger; 32 import org.enableit.db.ConnFactory; 33 import org.enableit.db.DBException; 34 import org.enableit.db.DatabaseProxy; 35 import org.enableit.db.beans.Provider; 36 import org.enableit.db.darrt.beans.DiffData; 37 import org.enableit.db.darrt.ext.DeclarativeDDLGenerator; 38 39 40 /*** 41 * Utility Singleton for creating Data Definition Language. 42 * @author Tim Stephenson 43 */ 44 public class DDLFactory { 45 /*** 46 * Internal cache of <code>DDLGenerator</code>s for various RDBMS. 47 */ 48 private static Map generators = new HashMap(); 49 50 /*** 51 * Singleton instance. 52 */ 53 private static DDLFactory me; 54 55 /*** 56 * The Log4J <code>Logger</code> doing the logging. 57 */ 58 protected static Logger logger = Logger.getLogger(DDLFactory.class); 59 60 /*** 61 * Constructor to preserve singleton status. 62 */ 63 private DDLFactory() { 64 65 } 66 67 /*** 68 * Factory method. 69 */ 70 public static synchronized DDLFactory getInstance() { 71 if (me == null) { 72 me = new DDLFactory(); 73 } 74 75 return me; 76 } 77 78 /*** 79 * Create a database object that does not currently exist. 80 * 81 * @param provider 82 * @param table 83 * @return <code>List</code> of DDL statements (<code>String</code> type). 84 * @deprecated Use <code>getGenerator(provider).getCreate(dataObject)</code>. 85 */ 86 public List getCreate(Provider provider, Object dataObject) 87 throws ConfigurationException { 88 logger.info("METHOD_ENTRY: getCreate"); 89 90 DDLGenerator generator = getGenerator(provider); 91 List ddl = generator.getCreate(dataObject); 92 93 logger.info("METHOD_EXIT: getCreate"); 94 95 return ddl; 96 } 97 98 /*** 99 * @param provider 100 * @param diff 101 * @return <code>List</code> of DDL statements (<code>String</code> type). 102 * @deprecated Use <code>getGenerator(provider).getModify(diff)</code>. 103 */ 104 public List getModify(Provider provider, DiffData diff) 105 throws ConfigurationException { 106 logger.info("METHOD_ENTRY: getModify"); 107 108 DDLGenerator generator = getGenerator(provider); 109 List ddl = generator.getModify(diff); 110 111 logger.info("METHOD_EXIT: getModify"); 112 113 return ddl; 114 } 115 116 /*** 117 * Install the schema specified in the location specified. 118 * <p> 119 * It is critically important that error handling is such that either 120 * all changes are applied or none. In the latter case reasons should be 121 * provided. 122 * 123 * @param provider Specifies the location to create schema. 124 * @param database Specifies the schema to create (embedded provider details will be ignored). 125 */ 126 127 /* public void install(Provider provider, Database database) 128 throws SchemaHandlingException { 129 logger.info("METHOD_ENTRY: install"); 130 131 try { 132 133 } catch (Exception e) { 134 logger.debug(e); 135 throw new SchemaHandlingException("Error during alteration, all changes have been undone."); 136 } 137 138 logger.info("METHOD_EXIT: install"); 139 } */ 140 141 /*** 142 * Install the necessary changes in the provider database to 143 * eliminate the differences in the <code>diffs</code> parameter. 144 * <p> 145 * It is critically important that error handling is such that either 146 * all changes are applied or none. In the latter case reasons should be 147 * provided. 148 * 149 * @param provider Specifies the location to create schema. 150 * @param database Specifies the schema to create (embedded provider details will be ignored). 151 */ 152 public void install(Connection conn, DiffData diff) 153 throws SchemaHandlingException { 154 logger.info("METHOD_ENTRY: install"); 155 156 if (conn == null) { 157 throw new SchemaHandlingException("Database connection was null"); 158 } 159 160 List deferredDDL = new ArrayList() ; 161 try { 162 DDLGenerator generator = getGenerator(conn.getMetaData() 163 .getDatabaseProductName()); 164 165 // get the ddl 166 List ddlList = null; 167 168 if (diff.isMissingFromTarget()) { 169 logger.debug("Requesting ddl from " 170 + generator.getClass().getName() + generator.getName()); 171 ddlList = generator.getCreate(diff.getRefObj()); 172 } else { 173 ddlList = generator.getModify(diff); 174 } 175 176 for (Iterator j = ddlList.iterator(); j.hasNext();) { 177 // execute it on the connection 178 String ddl = (String) j.next(); 179 180 if (!DDLGenerator.NO_DEFINITION_AVAILABLE.equals(ddl)) { 181 try { 182 int result = DatabaseProxy.executeUpdate(conn, ddl); 183 } catch (DBException e) { 184 // Probably a foreign key constraint, try to defer 185 deferredDDL.add(ddl) ; 186 } 187 } 188 } 189 190 if (deferredDDL.size() > 0) { 191 String msg = "Could not add these items: " ; 192 logger.warn(msg + deferredDDL) ; 193 throw new TempSchemaHandlingException(msg, deferredDDL); 194 } 195 } catch (TempSchemaHandlingException e) { 196 throw e ; // just bubble this up 197 } catch (Exception e) { 198 // typed exceptions: SQLException and DBException 199 logger.error(e.getClass().getName() + ":" + e.getMessage()); 200 201 try { 202 logger.error("Attempting rollback...") ; 203 conn.rollback(); 204 } catch (Exception e2) { 205 logger.error(e2.getClass().getName() + ":" + e2.getMessage()); 206 } 207 208 throw new SchemaHandlingException( 209 "Error during alteration, all changes have been undone."); 210 } 211 212 logger.info("METHOD_EXIT: install"); 213 } 214 215 /*** 216 * Returns the appropriate generator for the provider specified. 217 * 218 * @param provider Defines database <code>DDLGenerator</code> 219 * is required for. May be <code>null</code>. 220 * @return <code>DDLGenerator</code>. 221 */ 222 public DDLGenerator getGenerator(Provider provider) 223 throws ConfigurationException { 224 logger.info("METHOD_ENTRY: getGenerator"); 225 226 DDLGenerator generator = null; 227 228 if (provider == null) { 229 logger.error("Provider is null."); 230 throw new ConfigurationException("Unable to identify database") ; 231 } else if (provider.getProductName() == null) { 232 Connection conn = null; 233 234 try { 235 conn = ConnFactory.getConnection(provider); 236 237 String prodName = removeWhitespace(conn.getMetaData() 238 .getDatabaseProductName()); 239 240 provider.setProductName(prodName); 241 logger.warn("Assigning product name: " + prodName); 242 } catch (DBException e) { 243 logger.error("Unable to identify database"); 244 throw new ConfigurationException("Unable to identify database") ; 245 } catch (SQLException e) { 246 logger.error("Unable to identify database"); 247 throw new ConfigurationException("Unable to identify database") ; 248 } finally { 249 try { 250 conn.close(); 251 } catch (SQLException e2) { 252 ; 253 } 254 } 255 256 generator = getGenerator(provider); 257 } else { 258 String productName = provider.getProductName(); 259 260 try { 261 if (provider.getVersion() == null) { 262 throw new ConfigurationException() ; 263 } else { 264 generator = getGenerator(productName + provider.getVersion()); 265 } 266 } catch (ConfigurationException e) { 267 generator = getGenerator(productName); 268 // If this throws config ex, then too bad 269 } 270 } 271 272 logger.info("METHOD_EXIT: getGenerator, generator=" 273 + generator.getName()); 274 275 return generator; 276 } 277 278 /*** 279 * Returns the appropriate generator for the provider specified. 280 * 281 * @param productName Defines database <code>DDLGenerator</code> 282 * is required for. May be <code>null</code>. 283 * @return <code>DDLGenerator</code>. 284 */ 285 public DDLGenerator getGenerator(String productName) 286 throws ConfigurationException { 287 logger.info("METHOD_ENTRY: getGenerator(String), " + "productName:" 288 + productName); 289 290 DDLGenerator generator = null; 291 292 productName = removeWhitespace(productName); 293 generator = (DDLGenerator) generators.get(productName); 294 295 if (generator == null) { 296 generator = new DeclarativeDDLGenerator(productName); 297 298 synchronized (DDLFactory.class) { 299 generators.put(generator.getName(), generator); 300 } 301 } 302 303 logger.info("METHOD_EXIT: getGenerator(String), generator=" 304 + generator.getName()); 305 306 return generator; 307 } 308 309 /*** 310 * Removes embedded whitespace from the string parameter. 311 */ 312 private String removeWhitespace(String s) { 313 logger.info("METHOD_ENTRY: removeWhitespace, s=" + s); 314 315 StringBuffer sb = new StringBuffer(); 316 317 for (int i = 0; i < s.length(); i++) { 318 char c = s.charAt(i); 319 320 if (!Character.isWhitespace(c)) { 321 sb.append(c); 322 } 323 } 324 325 logger.info("METHOD_EXIT: removeWhitespace, returning=" + sb); 326 327 return sb.toString(); 328 } 329 }

This page was automatically generated by Maven