taganalyzer.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 802 行 · 第 1/2 页
JAVA
802 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.jsp;import com.caucho.bytecode.*;import com.caucho.log.Log;import com.caucho.util.L10N;import javax.annotation.Resource;import javax.ejb.EJB;import javax.servlet.jsp.tagext.*;//import javax.xml.ws.WebServiceRef;import java.io.InputStream;import java.lang.reflect.Field;import java.lang.reflect.Method;import java.util.HashMap;import java.util.logging.Level;import java.util.logging.Logger;/** * Analyzes the class for tag. * * Resin performs optimizations in the java code it produces from a jsp * depending on the nature of the taglib's that are used. For example, if a * taglib class does not use doAfterBody() then Resin can optimize the code it * produces for the jsp that uses that tag. * * In order to determine the nature of a certain tag, and thus the * optimizations that can be performed, Resin analyzes the tag's class. * It does this in two stages: first it uses reflection to look at the class * and then it uses bytecode analysis to look at the class. * * @see com.caucho.jsp.AnalyzedTag */public class TagAnalyzer{ private static final Logger log = Logger.getLogger(TagAnalyzer.class.getName()); static final L10N L = new L10N(TagAnalyzer.class); private HashMap<Class,AnalyzedTag> _analyzedTags = new HashMap<Class,AnalyzedTag>(); /** * Analyzes a tag. */ public AnalyzedTag analyze(Class tagClass) { if (tagClass == null) return null; AnalyzedTag analyzedTag = _analyzedTags.get(tagClass); if (analyzedTag != null) return analyzedTag; if (! JspTag.class.isAssignableFrom(tagClass)) { return null; } if (tagClass.isInterface()) { return null; } AnalyzedTag parent = analyze(tagClass.getSuperclass()); String name = tagClass.getName().replace('.', '/') + ".class"; ClassLoader loader = Thread.currentThread().getContextClassLoader(); AnalyzedTag tag = new AnalyzedTag(); tag.setParent(parent); try { analyzeByReflection(tagClass, tag, parent); InputStream is = loader.getResourceAsStream(name); if (is == null) return tag; try { JavaClass javaClass = new ByteCodeParser().parse(is); tag.setJavaClass(javaClass); analyze(tag, "doStartTag", "()I", new StartAnalyzer(tag)); analyze(tag, "doEndTag", "()I", new EndAnalyzer(tag)); if (IterationTag.class.isAssignableFrom(tagClass)) { analyze(tag, "doAfterBody", "()I", new AfterAnalyzer(tag)); } if (BodyTag.class.isAssignableFrom(tagClass)) { analyze(tag, "doInitBody", "()V", new InitAnalyzer()); } if (TryCatchFinally.class.isAssignableFrom(tagClass)) { analyze(tag, "doCatch", "(Ljava/lang/Throwable;)V", new CatchAnalyzer()); analyze(tag, "doFinally", "()V", new FinallyAnalyzer()); } } finally { is.close(); } } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); } return tag; } /** * Analyzes the tag by reflection. */ public void analyzeByReflection(Class tagClass, AnalyzedTag tag, AnalyzedTag parent) { tag.setBodyTag(BodyTag.class.isAssignableFrom(tagClass)); Method doStartMethod = getMethod(tagClass, "doStartTag", new Class[0]); if (doStartMethod != null && doStartMethod.getDeclaringClass().equals(tagClass)) { if (TagSupport.class.equals(tagClass)) { tag.setDoStart(false); tag.setStartReturnsSkip(false); tag.setStartReturnsInclude(true); tag.setStartReturnsBuffered(false); } else if (BodyTagSupport.class.equals(tagClass)) { tag.setDoStart(false); tag.setStartReturnsSkip(false); tag.setStartReturnsInclude(false); tag.setStartReturnsBuffered(true); } else if (BodyTag.class.isAssignableFrom(tagClass)) { tag.setDoStart(true); tag.setStartReturnsSkip(true); tag.setStartReturnsInclude(true); tag.setStartReturnsBuffered(true); } else { tag.setDoStart(true); tag.setStartReturnsSkip(true); tag.setStartReturnsInclude(true); tag.setStartReturnsBuffered(false); } } else if (parent != null) { tag.setDoStart(parent.getDoStart()); tag.setStartReturnsSkip(parent.getStartReturnsSkip()); tag.setStartReturnsInclude(parent.getStartReturnsInclude()); tag.setStartReturnsBuffered(parent.getStartReturnsBufferedAsParent()); } Method doEndMethod = getMethod(tagClass, "doEndTag", new Class[0]); if (doEndMethod != null && doEndMethod.getDeclaringClass().equals(tagClass)) { if (TagSupport.class.equals(tagClass) || BodyTagSupport.class.equals(tagClass)) { tag.setDoEnd(false); tag.setEndReturnsSkip(false); tag.setEndReturnsEval(true); } else { tag.setDoEnd(true); tag.setEndReturnsSkip(true); tag.setEndReturnsEval(true); } } else if (parent != null) { tag.setDoEnd(parent.getDoEnd()); tag.setEndReturnsSkip(parent.getEndReturnsSkip()); tag.setEndReturnsEval(parent.getEndReturnsEval()); } Method doAfterBody = getMethod(tagClass, "doAfterBody", new Class[0]); if (doAfterBody != null && doAfterBody.getDeclaringClass().equals(tagClass)) { if (TagSupport.class.equals(tagClass) || BodyTagSupport.class.equals(tagClass)) { tag.setDoAfter(false); tag.setAfterReturnsAgain(false); } else if (! IterationTag.class.isAssignableFrom(tagClass)) { tag.setDoAfter(false); tag.setAfterReturnsAgain(false); } else { tag.setDoAfter(true); tag.setAfterReturnsAgain(true); } } else if (parent != null) { tag.setDoAfter(parent.getDoAfter()); tag.setAfterReturnsAgain(parent.getAfterReturnsAgain()); } Method doInitBody = getMethod(tagClass, "doInitBody", new Class[0]); if (doInitBody != null && doInitBody.getDeclaringClass().equals(tagClass)) { if (BodyTagSupport.class.equals(tagClass)) { tag.setDoInit(false); } else if (! BodyTag.class.isAssignableFrom(tagClass)) { tag.setDoInit(false); } else { tag.setDoInit(true); } } else if (parent != null) { tag.setDoInit(parent.getDoInit()); } Method doCatch = getMethod(tagClass, "doCatch", new Class[] { Throwable.class }); if (doCatch != null && doCatch.getDeclaringClass().equals(tagClass)) { if (! TryCatchFinally.class.isAssignableFrom(tagClass)) { tag.setDoCatch(false); } else { tag.setDoCatch(true); } } else if (parent != null) { tag.setDoCatch(parent.getDoCatch()); } Method doFinally = getMethod(tagClass, "doFinally", new Class[0]); if (doFinally != null && doFinally.getDeclaringClass().equals(tagClass)) { if (! TryCatchFinally.class.isAssignableFrom(tagClass)) { tag.setDoFinally(false); } else { tag.setDoFinally(true); } } else if (parent != null) { tag.setDoFinally(parent.getDoFinally()); } // check for @Resource injection for (Method method : tagClass.getDeclaredMethods()) { if (method.getName().startsWith("set") && (method.isAnnotationPresent(Resource.class) || method.isAnnotationPresent(EJB.class))) { // || method.isAnnotationPresent(WebServiceRef.class))) { tag.setHasInjection(true); } } for (Field field : tagClass.getDeclaredFields()) { if (field.isAnnotationPresent(Resource.class) || field.isAnnotationPresent(EJB.class)) { // || field.isAnnotationPresent(WebServiceRef.class)) { tag.setHasInjection(true); } } } private Method getMethod(Class tagClass, String name, Class []args) { try { return tagClass.getMethod(name, args); } catch (Throwable e) { return null; } } /** * Analyzes the code for a method */ private void analyze(AnalyzedTag tag, String name, String signature, Analyzer analyzer) { JavaClass javaClass = null; JavaMethod method = null; for (AnalyzedTag defTag = tag; defTag != null; defTag = defTag.getParent()) { method = defTag.getJavaClass().findMethod(name, signature); if (method != null) { javaClass = defTag.getJavaClass(); break; } } if (method == null) return; CodeAttribute codeAttribute = method.getCode(); if (codeAttribute == null) return; CodeVisitor visitor = new CodeVisitor(javaClass, codeAttribute); try { visitor.analyze(analyzer); } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); } analyzer.complete(tag); } static IntMethodAnalyzer analyzeIntMethod(AnalyzedTag tag, String name, String signature) { if (! "()I".equals(signature)) return null; JavaMethod method = null; JavaClass javaClass = tag.getJavaClass(); while (method == null && javaClass != null) { method = javaClass.findMethod(name, signature); if (method == null) { JClass parent = javaClass.getSuperClass(); if (parent == null || ! (parent instanceof JavaClass)) return null; javaClass = (JavaClass) parent; } } if (method == null) return null; IntMethodAnalyzer analyzer = new IntMethodAnalyzer(); CodeAttribute codeAttribute = method.getCode(); if (codeAttribute == null) return null; CodeVisitor visitor = new CodeVisitor(javaClass, codeAttribute); try { visitor.analyze(analyzer); } catch (Exception e) { log.log(Level.WARNING, e.toString(), e); } if (analyzer.isUnique()) return analyzer; else return null; } static class Analyzer extends com.caucho.bytecode.Analyzer { public void analyze(CodeVisitor visitor) { } public void complete(AnalyzedTag tag) { } } /** * Callback analyzing the methods.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?