in freemarker-javax-servlet/src/main/java/freemarker/ext/jsp/TaglibFactory.java [1682:1810]
public void endElement(String nsuri, String localName, String qName) throws TldParsingSAXException {
if (!stack.peek().equals(qName)) {
throw new TldParsingSAXException("Unbalanced tag nesting at \"" + qName + "\" end-tag.", locator);
}
if (stack.size() == 3) {
if (E_NAME.equals(qName)) {
if (E_TAG.equals(stack.get(1))) {
tagNameCData = pullCData();
} else if (E_FUNCTION.equals(stack.get(1))) {
functionNameCData = pullCData();
}
} else if (E_TAG_CLASS_LEGACY.equals(qName) || E_TAG_CLASS.equals(qName)) {
tagClassCData = pullCData();
} else if (E_LISTENER_CLASS.equals(qName)) {
listenerClassCData = pullCData();
} else if (E_FUNCTION_CLASS.equals(qName)) {
functionClassCData = pullCData();
} else if (E_FUNCTION_SIGNATURE.equals(qName)) {
functionSignatureCData = pullCData();
}
} else if (stack.size() == 2) {
if (E_TAG.equals(qName)) {
checkChildElementNotNull(qName, E_NAME, tagNameCData);
checkChildElementNotNull(qName, E_TAG_CLASS, tagClassCData);
final Class tagClass = resoveClassFromTLD(tagClassCData, "custom tag", tagNameCData);
final TemplateModel customTagModel;
try {
if (Tag.class.isAssignableFrom(tagClass)) {
customTagModel = new TagTransformModel(tagNameCData, tagClass);
} else {
customTagModel = new SimpleTagDirectiveModel(tagNameCData, tagClass);
}
} catch (IntrospectionException e) {
throw new TldParsingSAXException(
"JavaBean introspection failed on custom tag class " + tagClassCData,
locator,
e);
}
TemplateModel replacedTagOrFunction = tagsAndFunctions.put(tagNameCData, customTagModel);
if (replacedTagOrFunction != null) {
if (CustomTagAndELFunctionCombiner.canBeCombinedAsELFunction(replacedTagOrFunction)) {
tagsAndFunctions.put(tagNameCData, CustomTagAndELFunctionCombiner.combine(
customTagModel, (TemplateMethodModelEx) replacedTagOrFunction));
} else {
LOG.warn("TLD contains multiple tags with name " + StringUtil.jQuote(tagNameCData)
+ "; keeping only the last one.");
}
}
tagNameCData = null;
tagClassCData = null;
} else if (E_FUNCTION.equals(qName) && beansWrapper != null) {
checkChildElementNotNull(qName, E_FUNCTION_CLASS, functionClassCData);
checkChildElementNotNull(qName, E_FUNCTION_SIGNATURE, functionSignatureCData);
checkChildElementNotNull(qName, E_NAME, functionNameCData);
final Class functionClass = resoveClassFromTLD(
functionClassCData, "custom EL function", functionNameCData);
final Method functionMethod;
try {
functionMethod = TaglibMethodUtil.getMethodByFunctionSignature(
functionClass, functionSignatureCData);
} catch (Exception e) {
throw new TldParsingSAXException(
"Error while trying to resolve signature " + StringUtil.jQuote(functionSignatureCData)
+ " on class " + StringUtil.jQuote(functionClass.getName())
+ " for custom EL function " + StringUtil.jQuote(functionNameCData) + ".",
locator,
e);
}
final int modifiers = functionMethod.getModifiers();
if (!Modifier.isPublic(modifiers) || !Modifier.isStatic(modifiers)) {
throw new TldParsingSAXException(
"The custom EL function method must be public and static: " + functionMethod,
locator);
}
final TemplateMethodModelEx elFunctionModel;
try {
elFunctionModel = beansWrapper.wrap(null, functionMethod);
} catch (Exception e) {
throw new TldParsingSAXException(
"FreeMarker object wrapping failed on method : " + functionMethod,
locator);
}
TemplateModel replacedTagOrFunction = tagsAndFunctions.put(functionNameCData, elFunctionModel);
if (replacedTagOrFunction != null) {
if (CustomTagAndELFunctionCombiner.canBeCombinedAsCustomTag(replacedTagOrFunction)) {
tagsAndFunctions.put(functionNameCData, CustomTagAndELFunctionCombiner.combine(
replacedTagOrFunction, elFunctionModel));
} else {
LOG.warn("TLD contains multiple functions with name " + StringUtil.jQuote(functionNameCData)
+ "; keeping only the last one.");
}
}
functionNameCData = null;
functionClassCData = null;
functionSignatureCData = null;
} else if (E_LISTENER.equals(qName)) {
checkChildElementNotNull(qName, E_LISTENER_CLASS, listenerClassCData);
final Class listenerClass = resoveClassFromTLD(listenerClassCData, E_LISTENER, null);
final Object listener;
try {
listener = listenerClass.newInstance();
} catch (Exception e) {
throw new TldParsingSAXException(
"Failed to create new instantiate from listener class " + listenerClassCData,
locator,
e);
}
listeners.add(listener);
listenerClassCData = null;
}
}
stack.pop();
}