// Path: jsptest-generic/jsptest-framework/src/main/java/net/sf/jsptest/TagKey.java
// public class TagKey {
// 
//     private final String prefix;
//     private final String name;
// 
//     public TagKey(String prefix) {
//         this(prefix, "*");
//     }
// 
//     public TagKey(String prefix, String name) {
//         this.prefix = prefix;
//         this.name = name;
//     }
// 
//     public String toString() {
//         return prefix + ":" + name;
//     }
// 
//     public int hashCode() {
//         final int prime = 31;
//         int result = 1;
//         result = prime * result + ((name == null) ? 0 : name.hashCode());
//         result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
//         return result;
//     }
// 
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null) {
//             return false;
//         }
//         if (getClass() != obj.getClass()) {
//             return false;
//         }
//         final TagKey other = (TagKey) obj;
//         if (name == null) {
//             if (other.name != null) {
//                 return false;
//             }
//         } else if (!name.equals(other.name)) {
//             return false;
//         }
//         if (prefix == null) {
//             if (other.prefix != null) {
//                 return false;
//             }
//         } else if (!prefix.equals(other.prefix)) {
//             return false;
//         }
//         return true;
//     }
// }


import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.jsp.tagext.TagInfo;
import net.sf.jsptest.TagKey;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.Node.Nodes;
        substituteMocksFor(nodes);
    }

    private void substituteMocksFor(Nodes nodes) throws JasperException {
        nodes.visit(new TagSubstitutor(mockTaglibs));
    }

    /**
     * Walks through the node tree representing the JSP and replaces the <i>handler</i> of certain
     * tags with a mock implementation if one has been configured.
     */
    private static class TagSubstitutor extends Node.Visitor {

        private final Map mocks;

        public TagSubstitutor(Map mockTaglibs) {
            this.mocks = mockTaglibs;
        }

        public void visit(Node.CustomTag n) throws JasperException {
            Class mockClass = substitute(n.getTagInfo());
            if (mockClass != null) {
                n.setTagHandlerClass(mockClass);
            }
            super.visit(n);
        }

        private Class substitute(TagInfo tagInfo) {
            String prefix = tagInfo.getTagLibrary().getPrefixString();
            String name = tagInfo.getTagName();
// Path: jsptest-generic/jsptest-framework/src/main/java/net/sf/jsptest/TagKey.java
// public class TagKey {
// 
//     private final String prefix;
//     private final String name;
// 
//     public TagKey(String prefix) {
//         this(prefix, "*");
//     }
// 
//     public TagKey(String prefix, String name) {
//         this.prefix = prefix;
//         this.name = name;
//     }
// 
//     public String toString() {
//         return prefix + ":" + name;
//     }
// 
//     public int hashCode() {
//         final int prime = 31;
//         int result = 1;
//         result = prime * result + ((name == null) ? 0 : name.hashCode());
//         result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
//         return result;
//     }
// 
//     public boolean equals(Object obj) {
//         if (this == obj) {
//             return true;
//         }
//         if (obj == null) {
//             return false;
//         }
//         if (getClass() != obj.getClass()) {
//             return false;
//         }
//         final TagKey other = (TagKey) obj;
//         if (name == null) {
//             if (other.name != null) {
//                 return false;
//             }
//         } else if (!name.equals(other.name)) {
//             return false;
//         }
//         if (prefix == null) {
//             if (other.prefix != null) {
//                 return false;
//             }
//         } else if (!prefix.equals(other.prefix)) {
//             return false;
//         }
//         return true;
//     }
// }


// Path: jsptest-jsp20/src/main/java/org/apache/jasper/compiler/MockTagPluginManager.java
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.jsp.tagext.TagInfo;
import net.sf.jsptest.TagKey;
import org.apache.jasper.JasperException;
import org.apache.jasper.compiler.Node.Nodes;

        substituteMocksFor(nodes);
    }

    private void substituteMocksFor(Nodes nodes) throws JasperException {
        nodes.visit(new TagSubstitutor(mockTaglibs));
    }

    /**
     * Walks through the node tree representing the JSP and replaces the <i>handler</i> of certain
     * tags with a mock implementation if one has been configured.
     */
    private static class TagSubstitutor extends Node.Visitor {

        private final Map mocks;

        public TagSubstitutor(Map mockTaglibs) {
            this.mocks = mockTaglibs;
        }

        public void visit(Node.CustomTag n) throws JasperException {
            Class mockClass = substitute(n.getTagInfo());
            if (mockClass != null) {
                n.setTagHandlerClass(mockClass);
            }
            super.visit(n);
        }

        private Class substitute(TagInfo tagInfo) {
            String prefix = tagInfo.getTagLibrary().getPrefixString();
            String name = tagInfo.getTagName();
            TagKey[] matchingOrder = new TagKey[] { new TagKey(prefix, name), new TagKey(prefix) };