tagfileprocessor.java

来自「精通tomcat书籍原代码,希望大家共同学习」· Java 代码 · 共 609 行 · 第 1/2 页

JAVA
609
字号
            }

            if (bodycontent == null) {
                bodycontent = TagInfo.BODY_CONTENT_SCRIPTLESS;
            }

            String tagClassName = JspUtil.getTagHandlerClassName(path, err);

            TagVariableInfo[] tagVariableInfos
                = new TagVariableInfo[variableVector.size()];
            variableVector.copyInto(tagVariableInfos);

            TagAttributeInfo[] tagAttributeInfo
                = new TagAttributeInfo[attributeVector.size()];
            attributeVector.copyInto(tagAttributeInfo);

            return new JasperTagInfo(name,
			       tagClassName,
			       bodycontent,
			       description,
			       tagLibInfo,
			       tei,
			       tagAttributeInfo,
			       displayName,
			       smallIcon,
			       largeIcon,
			       tagVariableInfos,
			       dynamicAttrsMapName);
        }

        static class NameEntry {
            private String type;
            private Node node;
            private TagAttributeInfo attr;

            NameEntry(String type, Node node, TagAttributeInfo attr) {
                this.type = type;
                this.node = node;
                this.attr = attr;
            }

            String getType() { return type;}
            Node getNode() { return node; }
            TagAttributeInfo getTagAttributeInfo() { return attr; }
        }

        /**
         * Reports a translation error if names specified in attributes of
         * directives are not unique in this translation unit.
         *
         * The value of the following attributes must be unique.
         *   1. 'name' attribute of an attribute directive
         *   2. 'name-given' attribute of a variable directive
         *   3. 'alias' attribute of variable directive
         *   4. 'dynamic-attributes' of a tag directive
         * except that 'dynamic-attributes' can (and must) have the same
         * value when it appears in multiple tag directives.
         *
         * Also, 'name-from' attribute of a variable directive cannot have
         * the same value as that from another variable directive.
         */
        private void checkUniqueName(String name, String type, Node n)
                throws JasperException {
            checkUniqueName(name, type, n, null);
        }

        private void checkUniqueName(String name, String type, Node n,
                                     TagAttributeInfo attr)
                throws JasperException {

            HashMap table = (type == VAR_NAME_FROM)? nameFromTable: nameTable;
            NameEntry nameEntry = (NameEntry) table.get(name);
            if (nameEntry != null) {
                if (type != TAG_DYNAMIC || nameEntry.getType() != TAG_DYNAMIC) {
                    int line = nameEntry.getNode().getStart().getLineNumber();
                    err.jspError(n, "jsp.error.tagfile.nameNotUnique",
                         type, nameEntry.getType(), Integer.toString(line));
                }
            } else {
                table.put(name, new NameEntry(type, n, attr));
            }
        }

        /**
         * Perform miscellean checks after the nodes are visited.
         */
        void postCheck() throws JasperException {
            // Check that var.name-from-attributes has valid values.
	    Iterator iter = nameFromTable.keySet().iterator();
            while (iter.hasNext()) {
                String nameFrom = (String) iter.next();
                NameEntry nameEntry = (NameEntry) nameTable.get(nameFrom);
                NameEntry nameFromEntry =
                    (NameEntry) nameFromTable.get(nameFrom);
                Node nameFromNode = nameFromEntry.getNode();
                if (nameEntry == null) {
                    err.jspError(nameFromNode,
                                 "jsp.error.tagfile.nameFrom.noAttribute",
                                 nameFrom);
                } else {
                    Node node = nameEntry.getNode();
                    TagAttributeInfo tagAttr = nameEntry.getTagAttributeInfo();
                    if (! "java.lang.String".equals(tagAttr.getTypeName())
                            || ! tagAttr.isRequired()
                            || tagAttr.canBeRequestTime()){
                        err.jspError(nameFromNode,
                            "jsp.error.tagfile.nameFrom.badAttribute",
                            nameFrom,
                            Integer.toString(node.getStart().getLineNumber()));
                     }
                }
            }
        }
    }

    /**
     * Parses the tag file, and collects information on the directives included
     * in it.  The method is used to obtain the info on the tag file, when the 
     * handler that it represents is referenced.  The tag file is not compiled
     * here.
     *
     * @param pc the current ParserController used in this compilation
     * @param name the tag name as specified in the TLD
     * @param tagfile the path for the tagfile
     * @param tagLibInfo the TagLibraryInfo object associated with this TagInfo
     * @return a TagInfo object assembled from the directives in the tag file.
     */
    public static TagInfo parseTagFileDirectives(ParserController pc,
						 String name,
						 String path,
						 TagLibraryInfo tagLibInfo)
                        throws JasperException {

        ErrorDispatcher err = pc.getCompiler().getErrorDispatcher();

        Node.Nodes page = null;
        try {
            page = pc.parseTagFileDirectives(path);
        } catch (FileNotFoundException e) {
            err.jspError("jsp.error.file.not.found", path);
        } catch (IOException e) {
            err.jspError("jsp.error.file.not.found", path);
        }

        TagFileDirectiveVisitor tagFileVisitor
            = new TagFileDirectiveVisitor(pc.getCompiler(), tagLibInfo, name,
                                          path);
        page.visit(tagFileVisitor);
        tagFileVisitor.postCheck();

        return tagFileVisitor.getTagInfo();
    }

    /**
     * Compiles and loads a tagfile.
     */
    private Class loadTagFile(Compiler compiler,
                              String tagFilePath, TagInfo tagInfo,
                              PageInfo parentPageInfo)
        throws JasperException {

        JspCompilationContext ctxt = compiler.getCompilationContext();
        JspRuntimeContext rctxt = ctxt.getRuntimeContext();
        JspServletWrapper wrapper =
                (JspServletWrapper) rctxt.getWrapper(tagFilePath);

        synchronized(rctxt) {
            if (wrapper == null) {
                wrapper = new JspServletWrapper(ctxt.getServletContext(),
                                                ctxt.getOptions(),
                                                tagFilePath,
                                                tagInfo,
                                                ctxt.getRuntimeContext(),
                                                (URL) ctxt.getTagFileJarUrls().get(tagFilePath));
                    rctxt.addWrapper(tagFilePath,wrapper);

		// Use same classloader and classpath for compiling tag files
		wrapper.getJspEngineContext().setClassLoader(
				(URLClassLoader) ctxt.getClassLoader());
		wrapper.getJspEngineContext().setClassPath(ctxt.getClassPath());
            }
            else {
                // Make sure that JspCompilationContext gets the latest TagInfo
                // for the tag file.  TagInfo instance was created the last
                // time the tag file was scanned for directives, and the tag
                // file may have been modified since then.
                wrapper.getJspEngineContext().setTagInfo(tagInfo);
            }

            Class tagClazz;
            int tripCount = wrapper.incTripCount();
            try {
                if (tripCount > 0) {
                    // When tripCount is greater than zero, a circular
                    // dependency exists.  The circularily dependant tag
                    // file is compiled in prototype mode, to avoid infinite
                    // recursion.

                    JspServletWrapper tempWrapper
                        = new JspServletWrapper(ctxt.getServletContext(),
                                                ctxt.getOptions(),
                                                tagFilePath,
                                                tagInfo,
                                                ctxt.getRuntimeContext(),
                                                (URL) ctxt.getTagFileJarUrls().get(tagFilePath));
                    tagClazz = tempWrapper.loadTagFilePrototype();
                    tempVector.add(
                               tempWrapper.getJspEngineContext().getCompiler());
                } else {
                    tagClazz = wrapper.loadTagFile();
                }
            } finally {
                wrapper.decTripCount();
            }
        
            // Add the dependants for this tag file to its parent's
            // dependant list.  The only reliable dependency information
            // can only be obtained from the tag instance.
            try {
                Object tagIns = tagClazz.newInstance();
                if (tagIns instanceof JspSourceDependent) {
                    Iterator iter = 
                        ((List) ((JspSourceDependent) tagIns).getDependants()).iterator();
                    while (iter.hasNext()) {
                        parentPageInfo.addDependant((String)iter.next());
                    }
                }
            } catch (Exception e) {
                // ignore errors
            }
        
            return tagClazz;
        }
    }


    /*
     * Visitor which scans the page and looks for tag handlers that are tag
     * files, compiling (if necessary) and loading them.
     */ 
    private class TagFileLoaderVisitor extends Node.Visitor {

        private Compiler compiler;
        private PageInfo pageInfo;

        TagFileLoaderVisitor(Compiler compiler) {
            
            this.compiler = compiler;
            this.pageInfo = compiler.getPageInfo();
        }

        public void visit(Node.CustomTag n) throws JasperException {
            TagFileInfo tagFileInfo = n.getTagFileInfo();
            if (tagFileInfo != null) {
                String tagFilePath = tagFileInfo.getPath();
		JspCompilationContext ctxt = compiler.getCompilationContext();
		if (ctxt.getTagFileJarUrls().get(tagFilePath) == null) {
		    // Omit tag file dependency info on jar files for now.
                    pageInfo.addDependant(tagFilePath);
		}
                Class c = loadTagFile(compiler, tagFilePath, n.getTagInfo(),
                                      pageInfo);
                n.setTagHandlerClass(c);
            }
            visitBody(n);
        }
    }

    /**
     * Implements a phase of the translation that compiles (if necessary)
     * the tag files used in a JSP files.  The directives in the tag files
     * are assumed to have been proccessed and encapsulated as TagFileInfo
     * in the CustomTag nodes.
     */
    public void loadTagFiles(Compiler compiler, Node.Nodes page)
                throws JasperException {

        tempVector = new Vector();
        page.visit(new TagFileLoaderVisitor(compiler));
    }

    /**
     * Removed the java and class files for the tag prototype 
     * generated from the current compilation.
     * @param classFileName If non-null, remove only the class file with
     *        with this name.
     */
    public void removeProtoTypeFiles(String classFileName) {
        Iterator iter = tempVector.iterator();
        while (iter.hasNext()) {
            Compiler c = (Compiler) iter.next();
            if (classFileName == null) {
                c.removeGeneratedClassFiles();
            } else if (classFileName.equals(
                        c.getCompilationContext().getClassFileName())) {
                c.removeGeneratedClassFiles();
                tempVector.remove(c);
                return;
            }
        }
    }
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?