1 package com.sslexplorer.jdbc; 2 3 import java.io.ByteArrayOutputStream ; 4 import java.io.File ; 5 import java.io.ObjectOutputStream ; 6 import java.io.Serializable ; 7 import java.sql.ResultSet ; 8 import java.sql.SQLException ; 9 import java.sql.Timestamp ; 10 import java.util.ArrayList ; 11 import java.util.Calendar ; 12 import java.util.HashSet ; 13 import java.util.List ; 14 import java.util.Set ; 15 16 import org.apache.commons.cache.Cache; 17 import org.apache.commons.cache.CacheStat; 18 import org.apache.commons.cache.MemoryStash; 19 import org.apache.commons.cache.SimpleCache; 20 import org.apache.commons.logging.Log; 21 import org.apache.commons.logging.LogFactory; 22 23 import com.sslexplorer.boot.ContextHolder; 24 import com.sslexplorer.boot.PropertyClass; 25 import com.sslexplorer.boot.PropertyClassManager; 26 import com.sslexplorer.boot.PropertyDefinition; 27 import com.sslexplorer.core.CoreServlet; 28 import com.sslexplorer.properties.DefaultPropertyProfile; 29 import com.sslexplorer.properties.Property; 30 import com.sslexplorer.properties.PropertyDatabase; 31 import com.sslexplorer.properties.PropertyProfile; 32 import com.sslexplorer.properties.attributes.AbstractAttributeKey; 33 import com.sslexplorer.properties.attributes.AttributeDefinition; 34 import com.sslexplorer.properties.attributes.DefaultAttributeDefinition; 35 import com.sslexplorer.properties.impl.profile.ProfileProperties; 36 import com.sslexplorer.properties.impl.profile.ProfilePropertyKey; 37 38 51 52 public class JDBCPropertyDatabase implements PropertyDatabase { 53 54 static Log log = LogFactory.getLog(JDBCPropertyDatabase.class); 55 56 final static Long CACHE_TTL = new Long (System.getProperty("sslexplorer.jdbcPropertyDatabase.cacheTTL", "180000")); 57 final static Integer CACHE_MAXOBJS = new Integer (System.getProperty("sslexplorer.jdbcPropertyDatabase.cacheMaxObjs", "2000")); 58 final static Long CACHE_COST = new Long (1); 59 60 private Cache propertyCache; 62 private JDBCDatabaseEngine db; 63 64 69 public void open(CoreServlet controllingServlet) throws Exception { 70 String dbName = System.getProperty("sslexplorer.propertyDatabase.jdbc.dbName", "explorer_configuration"); 71 controllingServlet.addDatabase(dbName, ContextHolder.getContext().getDBDirectory()); 72 String jdbcUser = System.getProperty("sslexplorer.jdbc.username", "sa"); 73 String jdbcPassword = System.getProperty("sslexplorer.jdbc.password", ""); 74 String vendorDB = System.getProperty("sslexplorer.jdbc.vendorClass", "com.sslexplorer.jdbc.hsqldb.HSQLDBDatabaseEngine"); 75 76 if (log.isInfoEnabled()) { 77 log.info("Property database is being opened..."); 78 log.info("JDBC vendor class implementation is " + vendorDB); 79 } 80 81 db = (JDBCDatabaseEngine) Class.forName(vendorDB).newInstance(); 82 db.init("propertyDatabase", dbName, jdbcUser, jdbcPassword, null); 83 84 File upgradeDir = new File ("install/upgrade"); 85 DBUpgrader upgrader = new DBUpgrader(ContextHolder.getContext().getVersion(), db, ContextHolder.getContext() 86 .getDBDirectory(), upgradeDir); 87 upgrader.upgrade(); 88 89 int maxObjs = CACHE_MAXOBJS.intValue(); 90 propertyCache = new SimpleCache(new MemoryStash(maxObjs)); 91 loadAttributeDefinitions(); 92 } 93 94 99 public void close() throws Exception { 100 if(propertyCache != null) 101 propertyCache.clear(); 102 } 103 104 public String retrieveGenericProperty(String key1, String key2, String key3, String key4, String key5) throws Exception { 105 String cacheKey = key1 + "_" + key2 + "_" + key3 + "_" + key4 + "_" + key5; 106 String val = (String ) propertyCache.retrieve(cacheKey); 107 if (val == null) { 108 109 JDBCPreparedStatement ps = db.getStatement("select.property"); 110 ps.setString(1, key1); 111 ps.setString(2, key2); 112 ps.setString(3, key3); 113 ps.setString(4, key4); 114 ps.setString(5, key5); 115 ResultSet rs = ps.executeQuery(); 116 try { 117 val = rs.next() ? rs.getString("value") : null; 118 } finally { 119 rs.close(); 120 ps.releasePreparedStatement(); 121 } 122 } 123 if (val != null) 124 storeToCache(cacheKey, val); 125 return val; 126 } 127 128 134 public void storeGenericProperty(String key1, String key2, String key3, String key4, String key5, String value) throws Exception { 135 propertyCache.clear(); 136 JDBCPreparedStatement ps = db.getStatement("select.property"); 137 ps.setString(1, key1); 138 ps.setString(2, key2); 139 ps.setString(3, key3); 140 ps.setString(4, key4); 141 ps.setString(5, key5); 142 143 ResultSet rs = ps.executeQuery(); 144 145 JDBCPreparedStatement ps2; 146 try { 147 if (!rs.next()) { 148 if (log.isDebugEnabled()) 149 log.debug("Property doesnt currently exist, inserting value '" + value + "'"); 150 151 ps2 = db.getStatement("insert.property"); 152 ps2.setString(1, key1); 153 ps2.setString(2, key2); 154 ps2.setString(3, key3); 155 ps2.setString(4, key4); 156 ps2.setString(5, key5); 157 158 ps2.setString(6, value); 160 161 try { 162 ps2.execute(); 163 } finally { 164 ps2.releasePreparedStatement(); 165 } 166 167 } else { 168 if (log.isDebugEnabled()) 169 log.debug("Property exists, updating value '" + value + "'"); 170 171 ps2 = db.getStatement("update.property"); 172 173 ps2.setString(1, value); 175 ps2.setString(2, key1); 176 ps2.setString(3, key2); 177 ps2.setString(4, key3); 178 ps2.setString(5, key4); 179 ps2.setString(6, key5); 180 try { 181 ps2.execute(); 182 } finally { 183 ps2.releasePreparedStatement(); 184 } 185 186 } 187 } finally { 188 rs.close(); 189 ps.releasePreparedStatement(); 190 } 191 192 } 193 194 197 public List <PropertyProfile> getPropertyProfiles(String username, boolean includeGlobal, int realmID) throws Exception { 198 199 JDBCPreparedStatement ps; 200 if (includeGlobal) { 201 ps = db.getStatement("select.global.profiles"); 202 } else { 203 ps = db.getStatement("select.profiles"); 204 } 205 206 try { 207 ps.setString(1, username == null ? "" : username); 208 ps.setInt(2, realmID); 209 210 ResultSet rs = ps.executeQuery(); 211 try { 212 213 Set <PropertyProfile> v = new HashSet <PropertyProfile>(); 214 while (rs.next()) { 215 v.add(buildPropertyProfile(rs)); 216 } 217 return new ArrayList <PropertyProfile>(v); 218 } finally { 219 rs.close(); 220 } 221 } finally { 222 ps.releasePreparedStatement(); 223 } 224 } 225 226 231 public PropertyProfile getPropertyProfile(int id) throws Exception { 232 233 JDBCPreparedStatement ps = db.getStatement("select.profile"); 234 ResultSet rs = null; 235 try { 236 ps.setInt(1, id); 237 238 rs = ps.executeQuery(); 239 if (rs.next()) { 240 return buildPropertyProfile(rs); 241 } 242 } finally { 243 if (rs != null) 244 rs.close(); 245 ps.releasePreparedStatement(); 246 } 247 return null; 248 } 249 250 251 254 public PropertyProfile createPropertyProfile(String username, String shortName, String description, int baseOn, 255 int realmID) throws Exception { 256 257 JDBCPreparedStatement ps = db.getStatement("insert.profile"); 258 Calendar c = Calendar.getInstance(); 259 260 try { 261 ps.setString(1, username == null ? "" : username); 262 ps.setString(2, shortName); 263 ps.setString(3, description); 264 ps.setString(4, db.formatTimestamp(c)); 265 ps.setString(5, db.formatTimestamp(c)); 266 ps.setInt(6, realmID); 267 ps.execute(); 268 } finally { 269 ps.releasePreparedStatement(); 270 } 271 int id = db.getLastInsertId(ps, "insert.profile.lastInsertId"); 272 PropertyProfile profile = new DefaultPropertyProfile(realmID, id, username == null ? "" : username, shortName, description, 273 c, c); 274 profile.setResourceName(shortName); 275 profile.setResourceDescription(description); 276 277 if (baseOn != -1) { 278 for (PropertyDefinition def : PropertyClassManager.getInstance() 279 .getPropertyClass(ProfileProperties.NAME) 280 .getDefinitions()) { 281 String val = Property.getProperty(new ProfilePropertyKey(baseOn, username, def.getName(), realmID)); 282 storeGenericProperty(def.getName(), username == null ? "" : username, String.valueOf(id), String.valueOf(realmID), "", val); 283 } 284 } 285 286 return profile; 287 288 } 289 290 293 public void updatePropertyProfile(int id, String shortName, String description) throws Exception { 294 295 JDBCPreparedStatement ps = db.getStatement("update.profile"); 296 297 try { 298 ps.setString(1, shortName); 299 ps.setString(2, description); 300 ps.setString(3, db.formatTimestamp(Calendar.getInstance())); 301 ps.setInt(4, id); 302 ps.execute(); 303 } finally { 304 ps.releasePreparedStatement(); 305 } 306 307 } 308 309 314 public PropertyProfile deletePropertyProfile(int id) throws Exception { 315 PropertyProfile prof = getPropertyProfile(id); 316 if (prof == null) { 317 throw new Exception ("No property profile with " + id + "."); 318 } 319 propertyCache.clear(); 320 JDBCPreparedStatement ps = db.getStatement("delete.profile.1"); 321 ps.setInt(1, id); 322 323 try { 324 ps.execute(); 325 } finally { 326 ps.releasePreparedStatement(); 327 } 328 329 ps = db.getStatement("delete.profile.2"); 330 ps.setInt(1, id); 331 332 try { 333 ps.execute(); 334 } finally { 335 ps.releasePreparedStatement(); 336 } 337 return prof; 338 } 339 340 343 public PropertyProfile getPropertyProfile(String username, String name, int realmID) throws Exception { 344 345 JDBCPreparedStatement ps = db.getStatement("select.profile.short"); 346 ResultSet rs = null; 347 348 try { 349 ps.setString(1, username == null ? "" : username); 350 ps.setString(2, name); 351 ps.setInt(3, realmID); 352 353 rs = ps.executeQuery(); 354 355 if (rs.next()) { 356 return buildPropertyProfile(rs); 357 } 358 return null; 359 } finally { 360 if (rs != null) 361 rs.close(); 362 ps.releasePreparedStatement(); 363 } 364 } 365 366 371 public void cleanup() throws Exception { 372 } 373 374 public void storeAttributeValue(AbstractAttributeKey key, String value) throws Exception { 375 JDBCPreparedStatement ps = db.getStatement("storeAttributeValue.delete"); 377 try { 378 ps.setString(1, key.getPropertyClassName()); 379 ps.setString(2, key.getAttributeClassKey()); 380 ps.setString(3, key.getName()); 381 ps.execute(); 382 } finally { 383 ps.releasePreparedStatement(); 384 } 385 if (value != null) { 387 JDBCPreparedStatement ps2 = db.getStatement(ps, "storeAttributeValue.insert"); 388 try { 389 ps2.setString(1, key.getPropertyClassName()); 390 ps2.setString(2, key.getAttributeClassKey()); 391 ps2.setString(3, key.getName()); 392 ps2.setString(4, value); 393 ps2.execute(); 394 } finally { 395 ps2.releasePreparedStatement(); 396 } 397 } 398 } 399 400 405 public String retrieveAttributeValue(AbstractAttributeKey attribute) throws Exception { 406 JDBCPreparedStatement ps = db.getStatement("retrieveAttributeValue.select"); 407 try { 408 ps.setString(1, attribute.getAttributeClassKey()); 409 ps.setString(2, attribute.getPropertyClassName()); 410 ps.setString(3, attribute.getName()); 411 ResultSet rs = ps.executeQuery(); 412 if (rs.next()) { 413 return rs.getString("attribute_value"); 414 } 415 } finally { 416 ps.releasePreparedStatement(); 417 } 418 return null; 419 } 420 421 426 public void createAttributeDefinition(AttributeDefinition definition) throws Exception { 427 if (definition.isSystem()) { 428 throw new Exception ("System attribute definitions may not be created."); 429 } 430 JDBCPreparedStatement ps = db.getStatement("createAttributeDefinition.create"); 431 try { 432 ps.setString(1, definition.getName()); 433 ps.setString(2, definition.getPropertyClass().getName()); 434 ps.setInt(3, definition.getVisibility()); 435 ps.setInt(4, definition.getType()); 436 ps.setInt(5, definition.getSortOrder()); 437 ps.setString(6, definition.getLabel()); 438 ps.setString(7, definition.getDescription()); 439 ps.setString(8, definition.getTypeMeta()); 440 ps.setInt(9, definition.getCategory()); 441 ps.setString(10, definition.getCategoryLabel()); 442 ps.setString(11, definition.getDefaultValue()); 443 ps.setInt(12, definition.isHidden() ? 1 : 0); 444 ps.setString(13, definition.getValidationString()); 445 ps.execute(); 446 } finally { 447 ps.releasePreparedStatement(); 448 } 449 } 450 451 457 public void deleteAttributeDefinition(String propertyClassName, String definitionName) throws Exception { 458 AttributeDefinition def = (AttributeDefinition) PropertyClassManager.getInstance() 459 .getPropertyClass(propertyClassName) 460 .getDefinition(definitionName); 461 if (def == null) { 462 throw new Exception ("Definition with name " + definitionName + " cannot be deleted as it does not exist."); 463 } 464 if (def.isSystem()) { 465 throw new Exception ("Definition with name " + definitionName + " cannot be deleted as it is a system definition."); 466 } 467 JDBCPreparedStatement ps = db.getStatement("deleteAttributeDefinition.delete"); 468 try { 469 ps.setString(1, propertyClassName); 470 ps.setString(2, definitionName); 471 ps.execute(); 472 } finally { 473 ps.releasePreparedStatement(); 474 } 475 } 476 477 482 public void updateAttributeDefinition(AttributeDefinition definition) throws Exception { 483 if (definition.isSystem()) { 484 throw new Exception ("System attribute definitions may not be updated."); 485 } 486 JDBCPreparedStatement ps = db.getStatement("updateAttributeDefinition.update"); 487 try { 488 ps.setInt(1, definition.getVisibility()); 489 ps.setInt(2, definition.getType()); 490 ps.setInt(3, definition.getSortOrder()); 491 ps.setString(4, definition.getLabel()); 492 ps.setString(5, definition.getDescription()); 493 ps.setString(6, definition.getTypeMeta()); 494 ps.setInt(7, definition.getCategory()); 495 ps.setString(8, definition.getCategoryLabel()); 496 ps.setString(9, definition.getDefaultValue()); 497 ps.setInt(10, definition.isHidden() ? 1 : 0); 498 ps.setString(11, definition.getValidationString()); 499 ps.setString(12, definition.getName()); 500 ps.setString(13, definition.getPropertyClass().getName()); 501 ps.execute(); 502 } finally { 503 ps.releasePreparedStatement(); 504 } 505 506 } 507 508 void loadAttributeDefinitions() throws Exception { 509 JDBCPreparedStatement ps = db.getStatement("loadAttributeDefinitions.select"); 510 ResultSet rs = ps.executeQuery(); 511 try { 512 while (rs.next()) { 513 String propertyClassName = rs.getString("property_class"); 514 PropertyClass ua = PropertyClassManager.getInstance().getPropertyClass(propertyClassName); 515 if (ua == null) { 516 log.warn("Found user attribute '" + rs.getString("name") 517 + "' with a property class of '" 518 + propertyClassName 519 + "'. This property class does not exist. Perhaps a plugin has been uninstalled?"); 520 } else { 521 ua.registerPropertyDefinition(new DefaultAttributeDefinition(rs.getInt("type"), 522 rs.getString("name"), 523 rs.getString("type_meta"), 524 rs.getInt("category"), 525 rs.getString("category_label"), 526 rs.getString("default_value"), 527 rs.getInt("visibility"), 528 rs.getInt("sort_order"), 529 null, 530 rs.getInt("hidden") == 1, 531 rs.getString("text_label"), 532 rs.getString("text_description"), 533 false, 534 true, 535 rs.getString("validation_string"))); 536 } 537 } 538 } finally { 539 rs.close(); 540 ps.releasePreparedStatement(); 541 } 542 } 543 544 PropertyProfile buildPropertyProfile(ResultSet rs) throws SQLException { 545 String username = rs.getString("username"); 546 Timestamp cd = rs.getTimestamp("date_created"); 547 Calendar c = Calendar.getInstance(); 548 c.setTimeInMillis(cd == null ? System.currentTimeMillis() : cd.getTime()); 549 Timestamp ad = rs.getTimestamp("date_amended"); 550 Calendar a = Calendar.getInstance(); 551 a.setTimeInMillis(ad == null ? System.currentTimeMillis() : ad.getTime()); 552 return new DefaultPropertyProfile(rs.getInt("realm_id"), rs.getInt("id"), username.equals("") ? null : username, rs 553 .getString("short_name"), rs.getString("description"), c, a); 554 } 555 556 void storeToCache(Serializable key, Serializable object) { 557 if (log.isDebugEnabled()) { 558 log.debug("Caching under " + key + ", ttl=" + CACHE_TTL + ", cost=" + CACHE_COST); 559 } 560 561 if ("true".equals(System.getProperty("sslexplorer.useDevConfig")) | "true".equals(System.getProperty("sslexplorer.testing"))) { 563 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 564 try { 565 ObjectOutputStream oos = new ObjectOutputStream (baos); 566 oos.writeObject(object); 567 } catch (Exception e) { 568 String string = "********** Failed to cache policy database object. There is probably a non-serializable object somewhere in the object graph. PLEASE FIX ME ****************"; 569 System.err 570 .println(string); 571 e.printStackTrace(); 572 throw new RuntimeException (string); 573 } 574 } 575 576 propertyCache.store(key, object, new Long (CACHE_TTL.longValue() + System.currentTimeMillis()), CACHE_COST); 577 if (log.isDebugEnabled()) { 578 log.debug("NUM_RETRIEVE_REQUESTED " + propertyCache.getStat(CacheStat.NUM_RETRIEVE_REQUESTED)); 579 log.debug("NUM_RETRIEVE_FOUND " + propertyCache.getStat(CacheStat.NUM_RETRIEVE_FOUND)); 580 log.debug("NUM_RETRIEVE_NOT_FOUND " + propertyCache.getStat(CacheStat.NUM_RETRIEVE_NOT_FOUND)); 581 log.debug("NUM_STORE_REQUESTED " + propertyCache.getStat(CacheStat.NUM_STORE_REQUESTED)); 582 log.debug("NUM_STORE_STORED " + propertyCache.getStat(CacheStat.NUM_STORE_STORED)); 583 log.debug("NUM_STORE_NOT_STORED " + propertyCache.getStat(CacheStat.NUM_STORE_NOT_STORED)); 584 log.debug("CUR_CAPACITY " + propertyCache.getStat(CacheStat.CUR_CAPACITY)); 585 } 586 } 587 588 } 589 | Popular Tags |