Method getListenerListMethod;
try {
Class<?> type = element.value.getClass();
getListenerListMethod = type.getMethod(getListenerListMethodName);
} catch (NoSuchMethodException exception) {
throw new SerializationException(exception);
}
Object listenerList;
try {
listenerList = getListenerListMethod.invoke(element.value);
} catch (InvocationTargetException exception) {
throw new SerializationException(exception);
} catch (IllegalAccessException exception) {
throw new SerializationException(exception);
}
// Create an invocation handler for this listener
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(language);
AttributeInvocationHandler handler =
new AttributeInvocationHandler(scriptEngine, attribute.name,
(String)attribute.value);
Object listener = Proxy.newProxyInstance(classLoader,
new Class<?>[]{attribute.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 represents a static setter
setStaticProperty(element.value, attribute.propertyClass,
attribute.name, attribute.value);
}
}
}
if (element.parent != null) {
if (element.parent.type == Element.Type.WRITABLE_PROPERTY) {
// Set this as the property value; it will be applied later in the
// parent's closing tag
element.parent.value = element.value;
} else if (element.parent.value != null) {
// If the parent element has a default property, use it; otherwise, if the
// parent is a sequence, add the element to it
Class<?> parentType = element.parent.value.getClass();
DefaultProperty defaultProperty = parentType.getAnnotation(DefaultProperty.class);
if (defaultProperty == null) {
if (element.parent.value instanceof Sequence<?>) {
Sequence<Object> sequence = (Sequence<Object>)element.parent.value;
sequence.add(element.value);
} else {
throw new SerializationException(element.parent.value.getClass()
+ " is not a sequence.");
}
} else {
String defaultPropertyName = defaultProperty.value();
BeanAdapter beanAdapter = new BeanAdapter(element.parent.value);
Object defaultPropertyValue = beanAdapter.get(defaultPropertyName);
if (defaultPropertyValue instanceof Sequence<?>) {
Sequence<Object> sequence = (Sequence<Object>)defaultPropertyValue;
sequence.add(element.value);
} else {
beanAdapter.put(defaultPropertyName, element.value);
}
}
}
}
break;
}
case READ_ONLY_PROPERTY: {
Dictionary<String, Object> dictionary;
if (element.value instanceof Dictionary<?, ?>) {
dictionary = (Dictionary<String, Object>)element.value;
} else {
dictionary = new BeanAdapter(element.value);
}
// Process attributes looking for instance property setters
for (Attribute attribute : element.attributes) {
if (attribute.propertyClass != null) {
throw new SerializationException("Static setters are not supported"
+ " for read-only properties.");
}
dictionary.put(attribute.name, attribute.value);
}
break;
}
case WRITABLE_PROPERTY: {
if (element.propertyClass == null) {
Dictionary<String, Object> dictionary;
if (element.parent.value instanceof Dictionary) {
dictionary = (Dictionary<String, Object>)element.parent.value;
} else {
dictionary = new BeanAdapter(element.parent.value);
}
dictionary.put(element.name, element.value);
} else {
if (element.parent == null) {
throw new SerializationException("Element does not have a parent.");
}
if (element.parent.value == null) {
throw new SerializationException("Parent value is null.");
}
setStaticProperty(element.parent.value, element.propertyClass,
element.name, element.value);
}
break;
}
case LISTENER_LIST_PROPERTY: {
// Evaluate the script
String script = (String)element.value;
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(language);
if (scriptEngine == null) {
throw new SerializationException("Script engine for \"" + language + "\" not found.");
}
// Don't pollute the engine namespace with the listener functions
scriptEngine.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
try {
scriptEngine.eval(script);
} catch (ScriptException exception) {
System.err.println(exception);
break;
}
// Create the listener and add it to the list
BeanAdapter beanAdapter = new BeanAdapter(element.parent.value);
ListenerList<?> listenerList = (ListenerList<?>)beanAdapter.get(element.name);
Class<?> listenerListClass = listenerList.getClass();
java.lang.reflect.Type[] genericInterfaces = listenerListClass.getGenericInterfaces();
Class<?> listenerClass = (Class<?>)genericInterfaces[0];
ElementInvocationHandler handler = new ElementInvocationHandler(scriptEngine);
Method addMethod;
try {
addMethod = listenerListClass.getMethod("add", Object.class);
} catch (NoSuchMethodException exception) {
throw new RuntimeException(exception);
}
Object listener = Proxy.newProxyInstance(classLoader,
new Class<?>[]{listenerClass}, handler);
try {
addMethod.invoke(listenerList, listener);
} catch (IllegalAccessException exception) {
throw new SerializationException(exception);
} catch (InvocationTargetException exception) {
throw new SerializationException(exception);
}
break;
}
case SCRIPT: {
String src = null;
if (element.properties.containsKey(INCLUDE_SRC_ATTRIBUTE)) {
src = element.properties.get(INCLUDE_SRC_ATTRIBUTE);
}
if (src != null) {
int i = src.lastIndexOf(".");
if (i == -1) {
throw new SerializationException("Cannot determine type of script \""
+ src + "\".");
}
String extension = src.substring(i + 1);
ScriptEngine scriptEngine = scriptEngineManager.getEngineByExtension(extension);
if (scriptEngine == null) {
throw new SerializationException("Unable to find scripting engine for"
+ " extension " + extension + ".");
}
scriptEngine.setBindings(scriptEngineManager.getBindings(), ScriptContext.ENGINE_SCOPE);
try {
URL scriptLocation;
if (src.charAt(0) == '/') {
scriptLocation = classLoader.getResource(src.substring(1));
} else {
scriptLocation = new URL(location, src);
}
BufferedReader scriptReader = null;
try {
scriptReader = new BufferedReader(new InputStreamReader(scriptLocation.openStream()));
scriptEngine.eval(scriptReader);
} catch(ScriptException exception) {
exception.printStackTrace();
} finally {
if (scriptReader != null) {
scriptReader.close();
}
}
} catch (IOException exception) {
throw new SerializationException(exception);
}
}
if (element.value != null) {
// Evaluate the script
String script = (String)element.value;
ScriptEngine scriptEngine = scriptEngineManager.getEngineByName(language);
if (scriptEngine == null) {
throw new SerializationException("Unable to find scripting engine for"
+ " language \"" + language + "\".");
}
scriptEngine.setBindings(scriptEngineManager.getBindings(), ScriptContext.ENGINE_SCOPE);