throw new SerializationException(exception);
}
// Don't pollute the engine namespace with the listener functions
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(language);
scriptEngine.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
// Create an invocation handler for this listener
AttributeInvocationHandler handler =
new AttributeInvocationHandler(scriptEngine,
attribute.localName.substring(attribute.localName.lastIndexOf(".") + 1),
attribute.value);
Object listener = Proxy.newProxyInstance(ThreadUtilities.getClassLoader(),
new Class<?>[]{propertyClass}, handler);
// Add the listener
Class<?> listenerListClass = listenerList.getClass();
Method addMethod;
try {
addMethod = listenerListClass.getMethod("add", Object.class);
} catch (NoSuchMethodException exception) {
throw new RuntimeException(exception);
}
try {
addMethod.invoke(listenerList, listener);
} catch (IllegalAccessException exception) {
throw new SerializationException(exception);
} catch (InvocationTargetException exception) {
throw new SerializationException(exception);
}
} else {
// The attribute reprsents a static setter
Object value = resolve(attribute.value);
Class<?> objectType = element.value.getClass();
String propertyName = attribute.localName.substring(attribute.localName.lastIndexOf(".") + 1);
propertyName = Character.toUpperCase(propertyName.charAt(0)) +
propertyName.substring(1);
Method setterMethod = null;
if (value != null) {
setterMethod = getStaticSetterMethod(propertyClass, propertyName,
objectType, value.getClass());
}
if (setterMethod == null) {
Method getterMethod = getStaticGetterMethod(propertyClass, propertyName, objectType);
if (getterMethod != null) {
Class<?> propertyType = getterMethod.getReturnType();
setterMethod = getStaticSetterMethod(propertyClass, propertyName,
objectType, propertyType);
if (value instanceof String) {
value = BeanDictionary.coerce((String)value, propertyType);
}
}
}
if (setterMethod == null) {
throw new SerializationException(attribute.localName + " is not valid static property.");
}
// Invoke the setter
try {
setterMethod.invoke(null, element.value, value);
} catch (Exception exception) {
throw new SerializationException(exception);
}
}
}
}
// If the parent element is a writable property, set this as its
// value; it will be applied later in the parent's closing tag
if (element.parent != null
&& element.parent.type == Element.Type.WRITABLE_PROPERTY) {
element.parent.value = element.value;
}
break;
}
case READ_ONLY_PROPERTY: {
if (element.value instanceof Dictionary<?, ?>) {
// Process attributes looking for instance property setters
for (Attribute attribute : element.attributes) {
if (Character.isUpperCase(attribute.localName.charAt(0))) {
throw new SerializationException("Static setters are not supported"
+ " for read-only properties.");
}
Dictionary<String, Object> dictionary =
(Dictionary<String, Object>)element.value;
dictionary.put(attribute.localName, resolve(attribute.value));
}
}
break;
}
case WRITABLE_PROPERTY: {
BeanDictionary beanDictionary = new BeanDictionary(element.parent.value);
beanDictionary.put(localName, element.value);
break;
}
case SCRIPT: {
// Process attributes looking for src and language
String src = null;
String language = this.language;
for (Attribute attribute : element.attributes) {
if (attribute.localName.equals(SCRIPT_SRC_ATTRIBUTE)) {
src = attribute.value;
} else if (attribute.localName.equals(SCRIPT_LANGUAGE_ATTRIBUTE)) {
language = attribute.value;
} else {
throw new SerializationException(attribute.localName + " is not a valid"
+ " attribute for the " + WTKX_PREFIX + ":" + SCRIPT_TAG + " tag.");
}
}
Bindings bindings;
if (element.parent.value instanceof ListenerList<?>) {
// Don't pollute the engine namespace with the listener functions
bindings = new SimpleBindings();
} else {
bindings = scriptEngineManager.getBindings();
}
// Execute script