📄 propertyconglomerate.java
字号:
return mappedValue; } /** Call the property set callbacks to map a proposed property value to a value to save. <P> The caller must run this in a block synchronized on this to serialize validations with changes to the set of property callbacks */ private Serializable map(String key, Serializable value, Dictionary set) throws StandardException { return pf.doMap(key, value, set); } /** Call the property set callbacks to validate a property change against the property set provided. <P> The caller must run this in a block synchronized on this to serialize validations with changes to the set of property callbacks */ private void validate(String key, Serializable value, Dictionary set) throws StandardException { pf.validateSingleProperty(key, value, set); } private boolean bootPasswordChange(TransactionController tc, String key, Serializable value) throws StandardException { // first check for boot password change - we don't put boot password // in the servicePropertyList because if we do, then we expose the // boot password in clear text if (key.equals(Attribute.BOOT_PASSWORD)) { // The user is trying to change the secret key. // The secret key is never stored in clear text, but we // store the encrypted form in the services.properties // file. Swap the secret key with the encrypted form and // put that in the services.properties file. AccessFactory af = ((TransactionManager)tc).getAccessManager(); RawStoreFactory rsf = (RawStoreFactory) Monitor.findServiceModule(af, RawStoreFactory.MODULE); // remove secret key from properties list if possible serviceProperties.remove(Attribute.BOOT_PASSWORD); value = rsf.changeBootPassword(serviceProperties, value); serviceProperties.put(RawStoreFactory.ENCRYPTED_KEY,value); return true; } else { return false; } } /** * Sets the Serializable object associated with a property key. * <p> * This implementation turns the setProperty into an insert into the * PropertyConglomerate conglomerate. * <p> * See the discussion of getProperty(). * <p> * The value stored may be a Formatable object or a Serializable object * whose class name starts with java.*. This stops arbitary objects being * stored in the database by class name, which will cause problems in * obfuscated/non-obfuscated systems. * * @param tc The transaction to do the Conglomerate work under. * @param key The key used to lookup this property. * @param value The value to be associated with this key. If null, * delete the property from the properties list. * * @exception StandardException Standard exception policy. **/ void setProperty( TransactionController tc, String key, Serializable value, boolean dbOnlyProperty) throws StandardException { if (SanityManager.DEBUG) { if (!((value == null) || (value instanceof Formatable))) { if (!(value.getClass().getName().startsWith("java."))) { SanityManager.THROWASSERT( "Non-formattable, non-java class - " + value.getClass().getName()); } } } lockProperties(tc); Serializable valueToValidateAndApply = value; // //If we remove a property we validate and apply its default. if (value == null) valueToValidateAndApply = getPropertyDefault(tc,key); Serializable valueToSave = validateApplyAndMap(tc,key,valueToValidateAndApply, dbOnlyProperty); // //if this is a bootPasswordChange we save it in //a special way. if (bootPasswordChange(tc,key,value)) return; // //value==null means we are removing a property. //To remove the property we call saveProperty with //a null value. Note we avoid saving the mapped //DEFAULT value returned by validateAndApply. else if (value==null) saveProperty(tc,key,null); // //value != null means we simply save the possibly //mapped value of the property returned by //validateAndApply. else saveProperty(tc,key,valueToSave); } private Serializable readProperty(TransactionController tc, String key) throws StandardException { // scan the table for a row with matching "key" ScanController scan = openScan(tc, key, 0); DataValueDescriptor[] row = makeNewTemplate(); // did we find at least one row? boolean isThere = scan.fetchNext(row); scan.close(); if (!isThere) return null; return (Serializable) (((UserType) row[1]).getObject()); } private Serializable getCachedProperty(TransactionController tc, String key) throws StandardException { // //Get the cached set of properties. Dictionary dbProps = getCachedDbProperties(tc); // //Return the value if it is defined. if (dbProps.get(key) != null) return (Serializable) dbProps.get(key); else return getCachedPropertyDefault(tc,key,dbProps); } private Serializable getCachedPropertyDefault(TransactionController tc, String key, Dictionary dbProps) throws StandardException { // //Get the cached set of properties. if (dbProps == null) dbProps = getCachedDbProperties(tc); // //return the default for the value if it is defined. Dictionary defaults = (Dictionary)dbProps.get(AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); if (defaults == null) return null; else return (Serializable)defaults.get(key); } /** * Gets the de-serialized object associated with a property key. * <p> * The Store provides a transaction protected list of database properties. * Higher levels of the system can store and retrieve these properties * once Recovery has finished. Each property is a serializable object * and is stored/retrieved using a String key. * <p> * In this implementation a lookup is done on the PropertyConglomerate * conglomerate, using a scan with "key" as the qualifier. * <p> * @param tc The transaction to do the Conglomerate work under. * @param key The "key" of the property that is being requested. * * @return object The object associated with property key. n * ull means no such key-value pair. * * @exception StandardException Standard exception policy. **/ Serializable getProperty( TransactionController tc, String key) throws StandardException { // //Try service properties first. if(PropertyUtil.isServiceProperty(key)) return serviceProperties.getProperty(key); // See if I'm the exclusive owner. If so I cannot populate // the cache as it would contain my uncommitted changes. if (iHoldTheUpdateLock(tc)) { // //Return the property value if it is defined. Serializable v = readProperty(tc,key); if (v != null) return v; return getPropertyDefault(tc,key); } else { return getCachedProperty(tc,key); } } /** * Get the default for a property. * @exception StandardException Standard exception policy. */ Serializable getPropertyDefault(TransactionController tc, String key) throws StandardException { // See if I'm the exclusive owner. If so I cannot populate // the cache as it would contain my uncommitted changes. if (iHoldTheUpdateLock(tc)) { // //Return the property default value (may be null) if //defined. Dictionary defaults = (Dictionary)readProperty(tc,AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); if (defaults == null) return null; else return (Serializable)defaults.get(key); } else { return getCachedPropertyDefault(tc,key,null); } } private Dictionary copyValues(Dictionary to, Dictionary from, boolean stringsOnly) { if (from == null) return to; for (Enumeration keys = from.keys(); keys.hasMoreElements(); ) { String key = (String) keys.nextElement(); Object value = from.get(key); if ((value instanceof String) || !stringsOnly) to.put(key, value); } return to; } /** Fetch the set of properties as a Properties object. This means that only keys that have String values will be included. */ Properties getProperties(TransactionController tc) throws StandardException { Properties p = new Properties(); getProperties(tc,p,true/*stringsOnly*/,false/*!defaultsOnly*/); return p; } public void getProperties(TransactionController tc, Dictionary d, boolean stringsOnly, boolean defaultsOnly) throws StandardException { // See if I'm the exclusive owner. If so I cannot populate // the cache as it would contain my uncommitted changes. if (iHoldTheUpdateLock(tc)) { Dictionary dbProps = readDbProperties(tc); Dictionary defaults = (Dictionary)dbProps.get(AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); copyValues(d,defaults,stringsOnly); if (!defaultsOnly)copyValues(d,dbProps,stringsOnly); } else { Dictionary dbProps = getCachedDbProperties(tc); Dictionary defaults = (Dictionary)dbProps.get(AccessFactoryGlobals.DEFAULT_PROPERTY_NAME); copyValues(d,defaults,stringsOnly); if (!defaultsOnly)copyValues(d,dbProps,stringsOnly); } } void resetCache() {cachedSet = null;} /** Read the database properties and add in the service set. */ private Dictionary readDbProperties(TransactionController tc) throws StandardException { Dictionary set = new Hashtable(); // scan the table for a row with no matching "key" ScanController scan = openScan(tc, (String) null, 0); DataValueDescriptor[] row = makeNewTemplate(); while (scan.fetchNext(row)) { Object key = ((UserType) row[0]).getObject(); Object value = ((UserType) row[1]).getObject(); if (SanityManager.DEBUG) { if (!(key instanceof String)) SanityManager.THROWASSERT( "Key is not a string " + key.getClass().getName()); } set.put(key, value); } scan.close(); // add the known properties from the service properties set for (int i = 0; i < PropertyUtil.servicePropertyList.length; i++) { String value = serviceProperties.getProperty(PropertyUtil.servicePropertyList[i]); if (value != null) set.put(PropertyUtil.servicePropertyList[i], value); } return set; } private Dictionary getCachedDbProperties(TransactionController tc) throws StandardException { Dictionary dbProps = cachedSet; //Get the cached set of properties. if (dbProps == null) { dbProps = readDbProperties(tc); cachedSet = dbProps; } return dbProps; } /** Lock the database properties for an update. */ void lockProperties(TransactionController tc) throws StandardException { // lock the property set until the transaction commits. // This allows correct operation of the cache. The cache remains // valid for all transactions except the one that is modifying // it. Thus readers see the old uncommited values. When this // thread releases its exclusive lock the cached is cleared // and the next reader will re-populate the cache. Object csGroup = tc.getLockObject(); lf.lockObject(csGroup, csGroup, cachedLock, ShExQual.EX, C_LockFactory.TIMED_WAIT); } /** Return true if the caller holds the exclusive update lock on the property conglomerate. */ private boolean iHoldTheUpdateLock(TransactionController tc) throws StandardException { Object csGroup = tc.getLockObject(); return lf.isLockHeld(csGroup, csGroup, cachedLock, ShExQual.EX); }}/** Only used for exclusive lock purposes.*/class CacheLock extends ShExLockable { private PropertyConglomerate pc; CacheLock(PropertyConglomerate pc) { this.pc = pc; } public void unlockEvent(Latch lockInfo) { super.unlockEvent(lockInfo); pc.resetCache(); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -