/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common Development
* and Distribution License("CDDL") (collectively, the "License"). You
* may not use this file except in compliance with the License. You can obtain
* a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
* or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
* language governing permissions and limitations under the License.
*
* When distributing the software, include this License Header Notice in each
* file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [year]
* [name of copyright owner]"
*
* Contributor(s):
*
* If you wish your version of this file to be governed by only the CDDL or
* only the GPL Version 2, indicate your decision by adding "[Contributor]
* elects to include this software in this distribution under the [CDDL or GPL
* Version 2] license." If you don't indicate a single choice of license, a
* recipient has the option to distribute your version of this file under
* either the CDDL, the GPL Version 2 or to extend the choice of license to
* its licensees as provided above. However, if you add GPL Version 2 code
* and therefore, elected the GPL Version 2 license, then the option applies
* only if the new code is made subject to such option by the copyright
* holder.
*/
package com.sun.enterprise.config;
import java.util.Enumeration;
import java.util.Vector;
import java.io.Serializable;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import org.netbeans.modules.schema2beans.BaseBean;
//FIXME: TO BE REMOVED
import org.netbeans.modules.schema2beans.Version;
import org.netbeans.modules.schema2beans.BaseProperty;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.logging.Logger;
import java.util.logging.Level;
import com.sun.enterprise.config.pluggable.ConfigBeanInterceptor;
import com.sun.enterprise.config.pluggable.ConfigBeansSettings;
import com.sun.enterprise.config.pluggable.EnvironmentFactory;
import com.sun.enterprise.config.util.LoggerHelper;
import com.sun.enterprise.config.impl.ConfigContextImpl;
import org.w3c.dom.DocumentType;
/**
* ConfigBean is the root class for all objects (beans)
* representing Config information in server.xml
*
*@author Sridatta Viswanath
*/
public abstract class ConfigBean extends ConfigBeanBase implements Serializable {
/**
* is pluggable for adding additional functionality
* FIXME: to be initialized
*/
transient private ConfigBeanInterceptor _interceptor = null;
transient private ConfigBeansSettings _cbSettings = null;
transient protected ConfigContext ctx = null;
transient private Hashtable transientProperties = null;
private static final String UNINITIALIZED_ATTRIBUTE_VALUE = "DONOTKNOW";
private static final long UNINITIALIZED_LAST_MODIFIED_VALUE = -1;
/**
* lastModifed keeps track of the timestamp when it was
* modified last. This is not user visible and is
* automatically updated and maintained. User gets
* a StaleWriteConfigException if timestamp is different
* while updating from config change List. Changes to
* this feature are in updateFromConfig* methods
*
* There is no meaning for lastModified in a deserialized
* ConfigBean. So, it is transient. However, we do copy it
* during the clone operation.
* -1 is uninitialized value.
*/
transient private long thisLastModified = UNINITIALIZED_LAST_MODIFIED_VALUE;
transient private long globalLastModified = UNINITIALIZED_LAST_MODIFIED_VALUE;
private String xpath;
/**
* Get transient property value
*
* returns value for transientProperty or null if it did not have one
**/
public Object getTransientProperty(String name)
{
if(name==null || transientProperties==null)
return null;
return transientProperties.get(name);
}
/**
* Set value for named transientProperty
* if value==null then the property will be removed
* returns the previous value of the specified key,
* or null if it did not have one
**/
public Object setTransientProperty(String name, Object value)
{
if(name==null)
return null;
if(value==null)
{
if(transientProperties==null)
return null;
value = transientProperties.get(name);
if(value!=null)
transientProperties.remove(name);
return value;
}
if(transientProperties==null)
transientProperties=new Hashtable();
return transientProperties.put(name, value);
}
public void setXPath(String xpath) {
this.xpath = (null != xpath ? xpath.trim() : xpath);
}
public String getXPath() {
return (null != xpath ? xpath.trim() : xpath);
}
/**
* Indicate if the receiver can have siblings (i.e. there can be
* more than one of this kind of child under the current parent).
* @return true iff the receiver can have siblings
*/
public boolean canHaveSiblings(){
return beanProp() != null && beanProp().isIndexed();
}
public ConfigContext getConfigContext() {
return ctx;
}
public void setConfigContext(ConfigContext ctx) {
//FIXME make it package specific
this.ctx = ctx;
}
//FIXME: reimplement??
public void cleanup() {
this.ctx = null;
this._interceptor = null;
setInvalidState();
}
public ConfigBean() {
super(null, new org.netbeans.modules.schema2beans.Version(4, 0, 0));
setThisLastModified();
//_interceptor = getInterceptor();
_cbSettings = getConfigBeansSettings();
}
/*
* FIXME: TO BE REMOVED
*/
public ConfigBean(Vector comps, Version version) {
super(comps, version);
setThisLastModified();
//_interceptor = getInterceptor();
_cbSettings = getConfigBeansSettings();
}
/**
* This method is used to convert a string value to boolean.
* @return true if the value is one of true, on, yes, 1. Note
* that the values are case sensitive. If it is not one of these
* values, then, it returns false. A finest message is printed if
* the value is null or a info message if the values are
* wrong cases for valid true values.
*/
public static boolean toBoolean(final String value){
final String v = (null != value ? value.trim() : value);
return null != v && (v.equals("true")
|| v.equals("yes")
|| v.equals("on")
|| v.equals("1"));
}
public void setAttributeValue(String name, String value) {
try {
setAttributeValue(name, value, true);
} catch(StaleWriteConfigException swce) {
String url = (this.ctx==null)?" ":ctx.getUrl();
LoggerHelper.finest("Detected external changes to config file \"" +
url +
"\". Ignoring the condition and proceeding");
}
}
/**
* @deprecated. will be made private soon.
*/
public void setAttributeValue(String name, String value , boolean overwrite)
throws StaleWriteConfigException {
final String nm = (null != name ? name.trim() : name);
final String vl = (null != value ? value.trim() : value);
//FIXME: make this private.
// Do nothing if the value hasn't actually changed
if (getAttributeValueSafe(nm) != null && getAttributeValueSafe(nm).equals(vl)){
return;
}
if(!overwrite && this.ctx != null && this.ctx.isFileChangedExternally()) {
throw new StaleWriteConfigException
("ConfigBean: cannot change since FileChangedExternally");
}
String oldValue = UNINITIALIZED_ATTRIBUTE_VALUE;
//special case for description
if(_cbSettings.isSpecialElement(nm)) {
oldValue = preSetAttributeValueSpecial(nm);
super.setValue(nm, vl);
postSetAttributeValueSpecial(nm, vl, oldValue);
} else {
oldValue = preSetAttributeValue(nm, vl);
super.setAttributeValue(nm, vl);
postSetAttributeValue(nm, vl, oldValue);
}
}
/**
* to get the child element generically
*/
public ConfigBean[] getChildBeansByName(String childBeanName) {
validateState();
if(childBeanName == null) return null;
childBeanName = childBeanName.trim();
childBeanName = _cbSettings.mapElementName(childBeanName);
ConfigBean[] ret = null;
try {
ret = (ConfigBean[]) getValues(childBeanName);
} catch(Exception e) {
// is a single valued element
ret = getChildBeanByName(childBeanName);
}
return ret;
}
/**
* get All child beans
*/
public ConfigBean[] getAllChildBeans() {
ArrayList cbRet = new ArrayList();
String[] childNames = getChildBeanNames();
if(childNames == null || childNames.length == 0) return null;
for(int i = 0;i<childNames.length;i++) {
ConfigBean[] cb = getChildBeansByName(childNames[i]);
if (cb == null) continue;
for(int k=0;k<cb.length;k++) {
cbRet.add(cb[k]);
}
}
return toConfigBeanArray(cbRet);
}
/**
* getAll child bean names
*/
private String[] getChildBeanNames() {
BaseProperty[] bp = super.listProperties();
if(bp == null) return null;
String[] s = new String[bp.length];
for(int i = 0;i< bp.length;i++) {
s[i] = bp[i].getDtdName();
}
return s;
}
public int removeChild(ConfigBean child) throws ConfigException {
//FIXME: remove???
return removeChild(child, true);
}
/**
* generically remove child
* returns the index of removed child
*/
public int removeChild(ConfigBean child, boolean overwrite) throws ConfigException {
//FIXME: to be removed??
if(!overwrite && this.ctx != null && this.ctx.isFileChangedExternally()) {
throw new StaleWriteConfigException
("ConfigBean: cannot change since FileChangedExternally");
}
if(child == null)
throw new ConfigException("Cannot remove null child");
return this.removeValue(child.name(), child);
}
public int addValue(String name, Object value) {
int i=0;
try {
i= addValue(name, value, true);
} catch(StaleWriteConfigException swce) {
//dont throw it!!
}
return i;
}
/**
* throws StaleWriteConfigException for the case of checking timestamps
* throws exception if overwrite is false and file changed
* externally
*/
public int addValue(String name, Object value, boolean overwrite)
throws StaleWriteConfigException {
if (null != name){
name = name.trim();
}
if(!overwrite && this.ctx != null && this.ctx.isFileChangedExternally()) {
throw new StaleWriteConfigException
("ConfigBean: cannot change since FileChangedExternally");
}
preAddValue(name, value);
int i = super.addValue(name, value);
postAddValue(name, value);
return i;
}
public int removeValue(String name, Object value) {
if (null != name){
name = name.trim();
}
int i=0;
try {
i= removeValue(name, value, true);
} catch (StaleWriteConfigException swce) {
//dont throw it!!
}
return i;
}
public int removeValue(String name, Object value, boolean overwrite)
throws StaleWriteConfigException {
if (null != name) {
name = name.trim();
}
if(!overwrite && this.ctx != null && this.ctx.isFileChangedExternally()) {
throw new StaleWriteConfigException
("ConfigBean: cannot change since FileChangedExternally");
}
preRemoveValue(name, value);
int i = super.removeValue(name, value);
postRemoveValue(name, value);
return i;
}
public Object getValue(String name)
{
if (null != name) {
name = name.trim();
}
Object res = super.getValue(name);
res = postGetValue(name, res);
return res;
}
public Object getValue(String name, int index)
{
if (null != name) {
name = name.trim();
}
Object res = super.getValue(name, index);
res = postGetValue(name, res);
return res;
}
public Object getValueById(String name, int id)
{
if (null != name) {
name = name.trim();
}
Object res = super.getValueById(name, id);
res = postGetValue(name, res);
return res;
}
public Object[] getValues(String name)
{
if (null != name) {
name = name.trim();
}
Object[] res = super.getValues(name);
res = postGetValues(name, res);
return res;
}
public void setValue(String name, Object value) {
if (null != name) {
name = name.trim();
}
try {
setValue(name, value, true);
} catch(StaleWriteConfigException swce) {
// dont throw it!!
}
}
public void setValue(String name, Object value, boolean overwrite) throws StaleWriteConfigException {
if (null != name) {
name = name.trim();
}
if(!overwrite && this.ctx != null && this.ctx.isFileChangedExternally()) {
throw new StaleWriteConfigException
("ConfigBean: cannot change since FileChangedExternally");
}
Object oldValue = super.getValue(name);
preSetValue(name, value);
super.setValue(name, value);
if(oldValue!=null && oldValue!=value && oldValue instanceof ConfigBean)
postRemoveValue(name, oldValue);
postSetValue(name, value);
}
/**
*/
//FIXME: to take care of overwrite and config change event
public void setValue(String name, Object[] value) {
if (null != name) {
name = name.trim();
}
preSetArrayValue(name, value);
super.setValue(name, value);
postSetArrayValue(name, value);
}
/**
* generic method to get default value from dtd. will be over ridden in beans
* note that it is also static which can cause some confusion
* @deprecated use getDefaultAttributeValue
*/
public static String getDefaultAttributeValueFromDtd(String attr) {
if (null != attr) {
attr = attr.trim();
}
return getDefaultAttributeValue(attr);
}
/**
* generic method to get default value from dtd. will be over ridden in beans
* note that it is also static which can cause some confusion
*/
public static String getDefaultAttributeValue(String attr) {
return null;
}
/**
* get the xpath representation for this element
* returns something like abc[@name='value'] or abc
* depending on the type of the bean
*/
protected String getRelativeXPath() {
return null;
}
/**
* get absolute xpath given the parent xpath
*
*/
public String getAbsoluteXPath(String parentXpath) {
if(xpath!=null)
return this.xpath.trim();
if(parentXpath==null)
return null;
String rel = getRelativeXPath();
if(rel == null) return null;
return parentXpath.trim() + "/" + getRelativeXPath().trim();
}
/**
* All attribute values containing strings of form ${system-property}
* are modified such that all occurrences of ${system-property} are
* replaced by the corresponding value of the specifed system
* property. If you wish to fetch the un-mapped value you must invoke
* getRawAttributeValue instead.
**/
public synchronized String getAttributeValue(String name) {
if (null != name) {
name = name.trim();
}
String res = getRawAttributeValue(name);
return postGetAttributeValue(name, res);
}
/**
* We must support a clone() operation in which attribute values
* are not expanded. In other words the clone must have all system property
* references kept in the form ${xxxx} without expanding xxxx. The clone
* operation is synchronized with getAttributeValue so that an invocation of
* get AttributeValue while a clone is in progress will not result in a
* raw attribute value.
*
* We also clone the last modified timestamp.
*/
public synchronized Object clone() {
final Object orig = preClone();
final ConfigBean result = (ConfigBean) super.clone();
if (this == parent()){
result.setDoctype(this.getPublicId(), this.getSystemId());
}
postClone(orig, result);
result.setGlobalLastModified(getThisLastModified());
return result;
}
// We keep a copy of the public/system ids because the copies
// in the graph manager are read only. We also try to ensure
// that the ones in the graph manager take precedence - after
// all, the graph manager might be changed underneath us and
// we wouldn't know!
// This mechanism is really only for root objects (i.e the
// Domain bean). Hence we're not exposing it any further than
// necessary - its not been designed nor tested with
// inheritance and/or wider use n mind, hence its private.
private String publicId;
private String systemId;
private void setDoctype(final String pid, final String sid){
publicId = (null != pid ? pid.trim() : pid);
systemId = (null != sid ? sid.trim() : sid);
if (graphManager() != null){
graphManager().setDoctype(pid,sid);
}
}
private String getPublicId() {
if (getDoctype() != null){
publicId = getDoctype().getPublicId();
}
return publicId.trim();
}
private String getSystemId() {
if (getDoctype() != null){
systemId = getDoctype().getSystemId();
}
return systemId.trim();
}
private DocumentType getDoctype(){
return (graphManager().getXmlDocument() != null
? graphManager().getXmlDocument().getDoctype()
: (DocumentType) null);
}
public String getRawAttributeValue(String name) {
if (null != name) {
name = name.trim();
}
//FIXME: description fix later for config change event.
if(_cbSettings.isSpecialElement(name)) {
final String v = (String)super.getValue(name);
return (null != v ? v.trim() : v);
}
preRawGetAttributeValue(name);
String s = super.getAttributeValue(name);
postRawGetAttributeValue(name, s);
return (null != s ? s.trim() : s);
}
/**
* overriding BaseBean.java to maskout user names and passwords
*/
public void dumpAttributes(String name, int index, StringBuffer str,
String indent) {
if (null != name) {
name = name.trim();
}
String[] names = this.getAttributeNames(name);
for (int i=0; i<names.length; i++) {
String v = null;
//To mask out Password and UserName
if(names[i].indexOf("Password") != -1 || names[i].indexOf("UserName") != -1) {
v = "*****";
} else {
v = this.getAttributeValue(name, index, names[i]);
}
if (v != null) {
str.append(indent + "\t attr: "); // NOI18N
str.append(names[i]);
str.append("="); // NOI18N
str.append(v);
}
}
}
// FIXME: TO BE REMOVED
public void changed() {
}
//ROB: config changes - added to fix compilation errors in subclasses
/**
*
*/
public boolean isEnabled() {
//FIXME: to be removed
return true;
}
//ROB: config changes - added to fix compilation errors in subclasses
/**
*
*/
public void setEnabled(boolean enabled) {
//FIXME: to be removed
//do nothing
}
// Temporary FIX for monitoring enabled. will be changed to use new monitoring service element later.
public boolean isMonitoringEnabled() {
//FIXME: to be removed
return false;
}
//FIXME: move camelize into another class and make it the base class
// and make the gen classes extend from that class.
/**
* camelize will convert the lower case into upper case in the following
* format. Eg: user-group ==> UserGroup
*
* Convert a DTD name into a bean name:
*
* Any - or _ character is removed. The letter following - and _
* is changed to be upper-case.
* If the user mixes upper-case and lower-case, the case is not
* changed.
* If the Word is entirely in upper-case, the word is changed to
* lower-case (except the characters following - and _)
* The first letter is always upper-case.
*/
//FIXME: TO BE REMOVED. Making it private.
public static String camelize(String name)
{
if (null != name) {
name = name.trim();
}
CharacterIterator ci;
StringBuffer n = new StringBuffer();
boolean up = true;
boolean keepCase = false;
char c;
ci = new StringCharacterIterator(name);
c = ci.first();
// If everything is uppercase, we'll lowercase the name.
while (c != CharacterIterator.DONE)
{
if (Character.isLowerCase(c))
{
keepCase = true;
break;
}
c = ci.next();
}
c = ci.first();
while (c != CharacterIterator.DONE)
{
if (c == '-' || c == '_')
up = true;
else
{
if (up)
c = Character.toUpperCase(c);
else
if (!keepCase)
c = Character.toLowerCase(c);
n.append(c);
up = false;
}
c = ci.next();
}
return n.toString();
}
/**
* should be called from the constructor and
* all the changeable methods
* Sets the lastModified to current time.
*/
private void setThisLastModified() {
thisLastModified = System.currentTimeMillis();
}
/**
* should be called ONLY from clone
* sets the lastmodified to timestamp
*/
private void setGlobalLastModified(long timestamp) {
globalLastModified = timestamp;
}
/**
* is package scope since it is called from configcontext
* FIXME: temporarily making it public for testing
*/
public long getGlobalLastModified() {
return globalLastModified;
}
public long getThisLastModified() {
return thisLastModified;
}
public synchronized void setInterceptor(ConfigBeanInterceptor cbi) {
this._interceptor = cbi;
}
public synchronized ConfigBeanInterceptor getInterceptor() {
if (null != _interceptor) {
return _interceptor;
}
ConfigBeanInterceptor cbi = null;
//get interceptor of ctx.
if (null != ctx) {
/**
* Should have used the ConfigContext interface. Too late and
* risky to change the interface.
*/
cbi = ((ConfigContextImpl)ctx).getConfigBeanInterceptor();
} else {
//get interceptor of parent.
ConfigBean parent = (ConfigBean)parent();
/*
Hack :- BaseBean.parent() returns 'this' if this is root.
Added the check (this != parent) to avoid recursion.
*/
if ((null != parent) && (this != parent)) {
cbi = parent.getInterceptor();
}
}
/*
if (null == cbi) {
cbi = EnvironmentFactory.getEnvironmentFactory().
getConfigEnvironment().getConfigBeanInterceptor();
}*/
//_interceptor = cbi;
return cbi;
}
private ConfigBeansSettings getConfigBeansSettings() {
return EnvironmentFactory.
getEnvironmentFactory().
getConfigEnvironment().
getConfigBeansSettings();
}
private Object postGetValue(String name, Object res) {
addXPathToChild(res);
return (getInterceptor()==null)
?res:getInterceptor().postGetValue(this, name, res);
}
private Object[] postGetValues(String name, Object[] res) {
addXPathToChild(res);
return (getInterceptor()==null)
?res:getInterceptor().postGetValues(name, res);
}
private String postGetAttributeValue(String name, String res) {
String s = (getInterceptor()==null)
?res:getInterceptor().postGetAttributeValue(name, res);
return (null != s ? s.trim() : s);
}
private Object preClone() {
if(getInterceptor() != null)
return getInterceptor().preClone();
return null;
}
private void postClone(Object o, Object result) {
final ConfigBeanInterceptor cbi = getInterceptor();
if(cbi != null) {
cbi.postClone(o);
}
}
/** remove this if getattribute value is always safe
*/
private String getAttributeValueSafe(String name) {
try {
return this.getAttributeValue(name);
} catch(Throwable t){
//ignore exceptions. all kind.
}
return null;
}
private void addToConfigChangeList(String xpath,
String tag,
String oldValue,
String newValue) {
ConfigChange cChange = null;
if(ctx != null) {
cChange = this.ctx.addToConfigChangeList(
(null != xpath ? xpath.trim() : xpath),
(null != tag ? tag.trim() : tag),
(null != oldValue ? oldValue.trim() : oldValue),
(null != newValue ? newValue.trim() : newValue));
if(cChange!=null) //can be null for "description" change
cChange.setGlobalLastModified(getGlobalLastModified());
}
}
private String preSetAttributeValue(String name, String value) {
preConfigChange(name, value, ConfigContextEvent.PRE_UPDATE_CHANGE, "UPDATE",
(null != this.name() ? this.name().trim() : this.name()));
return this.getAttributeValueSafe(name);
}
private void preAddValue(String name, Object value) {
preConfigChange(name, value, ConfigContextEvent.PRE_ADD_CHANGE, "ADD");
}
private void preRemoveValue(String name, Object value) {
preConfigChange(name, value, ConfigContextEvent.PRE_DELETE_CHANGE, "DELETE");
}
private void preSetValue(String name, Object value) {
preConfigChange(name, value, ConfigContextEvent.PRE_SET_CHANGE, "SET");
}
private void preConfigChange(String name, Object value, String type, String operation){
preConfigChange(name, value, type,operation, null);
}
private void preConfigChange(String name, Object value, String type, String operation, String beanName) {
validateState();
if(ctx !=null) {
ConfigContextEvent ccce = new ConfigContextEvent(ctx, type,name,value,operation, beanName);
ccce.setClassObject(this);
ctx.preChange(ccce);
}
}
private void postSetAttributeValue(String name, String value, String oldValue) {
//reset the lastmodified timestamp
setThisLastModified();
ConfigChange cChange = null;
if(ctx != null) {
cChange = this.ctx.addToConfigChangeList(this.xpath, name, oldValue, value);
if(cChange != null) cChange.setGlobalLastModified(this.getGlobalLastModified());
// <addition> srini@sun.com server.xml verifier
//this.ctx.postChange(ConfigContextEvent.POST_UPDATE_CHANGE);
ConfigContextEvent ccce = new ConfigContextEvent(ctx, ConfigContextEvent.POST_UPDATE_CHANGE,name,value,"UPDATE");
this.ctx.postChange(ccce);
// </addition> server.xml verifier
}
}
private void postAddValue(String name, Object value) {
//reset the lastmodified timestamp
setThisLastModified();
//notification
if(ctx != null) {
if(value instanceof ConfigBean) {
try {
//FIXME: clone?
ConfigChange cChange =
this.ctx.addToConfigChangeList(
this.xpath,
((ConfigBean)value).getAbsoluteXPath(this.xpath),
name,
//this clone adds a lot of overhead and was there
//because of a bug in schema2beans
//((ConfigBean)this.ctx.getRootConfigBean().clone()));
((ConfigBean)this.ctx.getRootConfigBean()));
if(cChange != null) cChange.setGlobalLastModified(this.getGlobalLastModified());
} catch(Exception ce) {
ce.printStackTrace();
}
((ConfigBean)value).setConfigContext(this.ctx);
((ConfigBean)value).setXPath(((ConfigBean)value).getAbsoluteXPath(this.xpath));
}
ConfigContextEvent ccce = new ConfigContextEvent(ctx, ConfigContextEvent.POST_ADD_CHANGE,name,value,"ADD");
this.ctx.postChange(ccce);
} else {
//_logger.log(Level.INFO,"config.change_not_registered");
}
}
private void postSetValue(String name, Object value) {
//reset the lastmodified timestamp
setThisLastModified();
if(ctx != null) {
// this.ctx.addToConfigChangeList(this.xpath, name, value, null);
//FIXME: remove later
if(value instanceof ConfigBean) {
//FIXME: clone?
ConfigChange cChange = this.ctx.addToConfigChangeList(this.xpath, name, ((ConfigBean)value).clone(), null);
if(cChange != null) cChange.setGlobalLastModified(this.getGlobalLastModified());
((ConfigBean)value).setConfigContext(this.ctx); //incase of description
((ConfigBean)value).setXPath(((ConfigBean)value).getAbsoluteXPath(this.xpath));
// <addition> srini@sun.com
//ctx.postChange(ConfigContextEvent.POST_SET_CHANGE);
ConfigContextEvent ccce = new ConfigContextEvent(ctx,ConfigContextEvent.POST_SET_CHANGE,name,value,"SET");
ctx.postChange(ccce);
// </addition> server.xml verifier
} else {
ConfigChange cChange = this.ctx.addToConfigChangeList(this.xpath, name, value, null);
if(cChange != null) cChange.setGlobalLastModified(this.getGlobalLastModified());
}
} else {
//_logger.log(Level.INFO,"config.change_not_registered");
}
}
private void postRemoveValue(String name, Object value) {
//reset the lastmodified timestamp
setThisLastModified();
//notification
if(value instanceof ConfigBean){
if(ctx != null) {
ConfigChange cChange = this.ctx.addToConfigChangeList(((ConfigBean)value).getXPath());
if(cChange != null) cChange.setGlobalLastModified(this.getGlobalLastModified());
// <addition> srini@sun.com server.xml verifier
//ctx.postChange(ConfigContextEvent.POST_DELETE_CHANGE);
ConfigContextEvent ccce = new ConfigContextEvent(ctx, ConfigContextEvent.POST_DELETE_CHANGE,name,value,"DELETE");
ctx.postChange(ccce);
// </addition> server.xml verifier
} else {
//_logger.log(Level.INFO,"config.change_not_registered");
}
}
}
private String preSetAttributeValueSpecial(String name) {
return getAttributeValueSafe(name);
}
private void postSetAttributeValueSpecial(String name,
String value, String oldValue) {
//reset the lastmodified timestamp
setThisLastModified();
addToConfigChangeList(this.xpath,
name,
oldValue,
value);
}
private ConfigBean[] toConfigBeanArray(ArrayList cbRet) {
ConfigBean[] ret = new ConfigBean[cbRet.size()];
for(int j=0;j<cbRet.size();j++) {
ret[j] = (ConfigBean) cbRet.get(j);
}
return ret;
}
private ConfigBean[] getChildBeanByName(String childBeanName) {
ConfigBean[] ret = null;
try {
ConfigBean cb = (ConfigBean) getValue(childBeanName);
if(cb!=null)
{
ret = new ConfigBean[1];
ret[0] = cb;
}
} catch (Exception c) {}
return ret;
}
private void addXPathToChild(Object obj)
{
if(obj!=null && obj instanceof ConfigBean)
{
//set XPath for child bean
ConfigBean cb = (ConfigBean)obj;
if(cb.xpath==null && this.xpath!=null)
cb.setXPath(cb.getAbsoluteXPath(this.xpath));
}
}
private void addXPathToChild(Object[] obj)
{
if(obj==null)
return;
for(int i=0; i<obj.length; i++)
{
addXPathToChild(obj[i]);
}
}
private void preRawGetAttributeValue(String name) {
validateState();
if(ctx !=null) {
ConfigContextEvent ccce = new ConfigContextEvent(ctx, ConfigContextEvent.PRE_ACCESS);
ccce.setClassObject(this);
ctx.preChange(ccce);
}
}
private void postRawGetAttributeValue(String name, String s) {
if(ctx !=null) {
ConfigContextEvent ccce = new ConfigContextEvent(ctx, ConfigContextEvent.POST_ACCESS);
ctx.postChange(ccce);
}
}
private void preSetArrayValue(String name, Object[] value) {
validateState();
if(ctx !=null) {
ConfigContextEvent ccce =
new ConfigContextEvent(ctx,
ConfigContextEvent.PRE_SET_CHANGE,
name,
value,
"SET");
ccce.setClassObject(this);
ccce.setBeanName(this.name());
ctx.preChange(ccce);
}
}
private void postSetArrayValue(String name, Object[] value) {
//reset the lastmodified timestamp
setThisLastModified();
if(ctx != null) {
ConfigChange cChange =
this.ctx.addToConfigChangeList(this.xpath, name, null, value);
if(cChange != null) {
cChange.setGlobalLastModified(this.getGlobalLastModified());
}
ConfigContextEvent ccce =
new ConfigContextEvent(ctx,
ConfigContextEvent.POST_SET_CHANGE,
name,
value,
"SET");
//ccce.setClassObject(this); //why FIXME??
ccce.setBeanName(this.name());
try {
ctx.postChange(ccce);
} catch(Exception e) {
//catch for now. may remove later.
//e.printStackTrace(); //FIXME
}
} else {
//_logger.log(Level.INFO,"config.change_not_registered");
}
}
/**
* state of the config beans
*/
transient private String _state = VALID_STATE;
/*
* possible states
*/
private static final String VALID_STATE = "valid_state";
private static final String INVALID_STATE = "invalid_state";
/**
* is used to validate state before any operation to the config bean.
* If the state is not valid, a runtime exception will be thrown
*/
private void validateState() {
if(!VALID_STATE.equals(_state)) {
throw new ConfigRuntimeException("Config API Usage Error: State of ConfigBean is INVALID. No operations are permitted");
}
}
private void setInvalidState() {
_state = INVALID_STATE;
}
}
|