public void endElement()

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();
        }