1 56 package org.objectstyle.cayenne.pref; 57 58 import java.io.File ; 59 import java.io.FileFilter ; 60 import java.io.IOException ; 61 62 import javax.sql.DataSource ; 63 64 import org.apache.log4j.Level; 65 import org.objectstyle.cayenne.CayenneRuntimeException; 66 import org.objectstyle.cayenne.access.QueryLogger; 67 import org.objectstyle.cayenne.access.util.ConnectionEventLogger; 68 import org.objectstyle.cayenne.conf.Configuration; 69 import org.objectstyle.cayenne.conf.DataSourceFactory; 70 import org.objectstyle.cayenne.conf.DefaultConfiguration; 71 import org.objectstyle.cayenne.conn.PoolManager; 72 import org.objectstyle.cayenne.query.SQLTemplate; 73 import org.objectstyle.cayenne.util.Util; 74 75 81 public class HSQLEmbeddedPreferenceService extends CayennePreferenceService { 82 83 protected File dbDirectory; 84 protected String baseName; 85 protected String masterBaseName; 86 protected String cayenneConfigPackage; 87 88 97 public HSQLEmbeddedPreferenceService(String dbLocation, String cayenneConfigPackage, 98 String defaultDomain) { 99 super(defaultDomain); 100 if (dbLocation == null) { 101 throw new PreferenceException("Null DB location."); 102 } 103 104 File file = new File (dbLocation); 105 106 this.dbDirectory = file.getParentFile(); 107 this.masterBaseName = file.getName(); 108 this.cayenneConfigPackage = cayenneConfigPackage; 109 } 110 111 115 public boolean isSecondaryDB() { 116 return !Util.nullSafeEquals(masterBaseName, baseName); 117 } 118 119 public File getMasterLock() { 120 return new File (dbDirectory, masterBaseName + ".lck"); 121 } 122 123 127 public void startService() { 128 HSQLDataSourceFactory dataSourceFactory = new HSQLDataSourceFactory(); 130 131 DefaultConfiguration config = new DefaultConfiguration(); 132 config.setDataSourceFactory(dataSourceFactory); 133 134 if (cayenneConfigPackage != null) { 135 config.addClassPath(cayenneConfigPackage); 136 } 137 138 try { 139 config.initialize(); 140 } 141 catch (Exception ex) { 142 throw new CayenneRuntimeException("Error connecting to preference DB.", ex); 143 } 144 145 config.didInitialize(); 146 dataContext = config.getDomain().createDataContext(); 147 148 if (dataSourceFactory.needSchemaUpdate) { 150 initSchema(); 151 } 152 153 initPreferences(); 155 156 startTimer(); 158 } 159 160 public void stopService() { 161 162 if (saveTimer != null) { 163 saveTimer.cancel(); 164 } 165 166 if (dataContext != null) { 167 168 savePreferences(); 170 171 dataContext.performNonSelectingQuery(new SQLTemplate( 173 Domain.class, 174 "SHUTDOWN", 175 false)); 176 177 dataContext.getParentDataDomain().shutdown(); 179 } 180 181 if (isSecondaryDB()) { 183 File lock = getMasterLock(); 184 if (!lock.exists()) { 185 186 try { 189 if (lock.createNewFile()) { 190 try { 191 moveDB(baseName, masterBaseName); 192 } 193 finally { 194 lock.delete(); 195 } 196 } 197 } 198 catch (Throwable th) { 199 throw new PreferenceException( 200 "Error shutting down database. Preferences may be in invalid state."); 201 } 202 } 203 } 204 } 205 206 210 void moveDB(String masterBaseName, String targetBaseName) throws IOException { 211 212 File [] filesToMove = dbDirectory.listFiles(new HSQLDBFileFilter(masterBaseName)); 213 if (filesToMove != null) { 214 for (int i = 0; i < filesToMove.length; i++) { 215 String ext = Util.extractFileExtension(filesToMove[i].getName()); 216 217 File target = new File (dbDirectory, targetBaseName + "." + ext); 218 if (filesToMove[i].exists()) { 219 filesToMove[i].renameTo(target); 220 } 221 else { 222 target.delete(); 223 } 224 } 225 } 226 } 227 228 232 void copyDB(String masterBaseName, String targetBaseName) throws IOException { 233 234 File [] filesToCopy = dbDirectory.listFiles(new HSQLDBFileFilter(masterBaseName)); 235 if (filesToCopy != null) { 236 for (int i = 0; i < filesToCopy.length; i++) { 237 String ext = Util.extractFileExtension(filesToCopy[i].getName()); 238 239 File target = new File (dbDirectory, targetBaseName + "." + ext); 240 if (filesToCopy[i].exists()) { 241 Util.copy(filesToCopy[i], target); 242 } 243 else { 244 target.delete(); 245 } 246 } 247 } 248 } 249 250 final class HSQLDBFileFilter implements FileFilter { 252 String baseName; 253 254 HSQLDBFileFilter(String baseName) { 255 this.baseName = baseName; 256 } 257 258 public boolean accept(File pathname) { 259 if (!pathname.isFile()) { 260 return false; 261 } 262 263 String fullName = pathname.getName(); 264 if (fullName.endsWith(".lck")) { 265 return false; 266 } 267 268 int dot = fullName.indexOf('.'); 269 String name = (dot > 0) ? fullName.substring(0, dot) : fullName; 270 271 return baseName.equals(name); 272 }; 273 }; 274 275 final class HSQLDataSourceFactory implements DataSourceFactory { 277 278 boolean needSchemaUpdate; 279 String url; 280 281 void prepareDB() throws IOException { 282 283 if (checkMainDB(masterBaseName)) { 285 return; 286 } 287 288 if (baseName != null && checkMainDB(baseName)) { 290 return; 291 } 292 293 for (int i = 1; i < 200; i++) { 296 String name = masterBaseName + i; 297 File lock = new File (dbDirectory, name + ".lck"); 298 if (!lock.exists()) { 299 300 if (!lock.createNewFile()) { 303 continue; 304 } 305 306 try { 307 copyDB(masterBaseName, name); 308 } 309 finally { 310 lock.delete(); 311 } 312 313 needSchemaUpdate = false; 314 url = "jdbc:hsqldb:file:" 315 + Util.substBackslashes(new File (dbDirectory, name) 316 .getAbsolutePath()); 317 baseName = name; 318 return; 319 } 320 } 321 322 throw new IOException ("Can't create preferences DB"); 323 } 324 325 boolean checkMainDB(String sessionBaseName) { 326 File dbFile = new File (dbDirectory, sessionBaseName + ".properties"); 327 328 if (!dbFile.exists()) { 330 needSchemaUpdate = true; 331 url = "jdbc:hsqldb:file:" 332 + Util.substBackslashes(new File (dbDirectory, sessionBaseName) 333 .getAbsolutePath()); 334 baseName = sessionBaseName; 335 return true; 336 } 337 338 File lockFile = new File (dbDirectory, sessionBaseName + ".lck"); 340 341 if (lockFile.exists() 344 && System.getProperty("os.name").toLowerCase().indexOf("windows") >= 0) { 345 lockFile.delete(); 346 } 347 348 if (!lockFile.exists()) { 349 needSchemaUpdate = false; 350 url = "jdbc:hsqldb:file:" 351 + Util.substBackslashes(new File (dbDirectory, sessionBaseName) 352 .getAbsolutePath()); 353 baseName = sessionBaseName; 354 return true; 355 } 356 357 return false; 358 } 359 360 public DataSource getDataSource(String location, Level logLevel) throws Exception { 361 try { 362 prepareDB(); 363 364 PoolManager pm = new PoolManager( 365 org.hsqldb.jdbcDriver.class.getName(), 366 url, 367 1, 368 1, 369 "sa", 370 null, 371 new ConnectionEventLogger(logLevel)); 372 373 return pm; 374 } 375 catch (Throwable th) { 376 QueryLogger.logConnectFailure(logLevel, th); 377 throw new PreferenceException("Error connecting to DB", th); 378 } 379 } 380 381 public DataSource getDataSource(String location) throws Exception { 382 return getDataSource(location, Level.INFO); 383 } 384 385 public void initializeWithParentConfiguration(Configuration conf) { 386 } 387 } 388 389 } | Popular Tags |