1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/share/classes/com/sun/tools/classfile/ReferenceFinder.java Tue Apr 30 15:43:00 2013 -0700 1.3 @@ -0,0 +1,240 @@ 1.4 +/* 1.5 + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. Oracle designates this 1.11 + * particular file as subject to the "Classpath" exception as provided 1.12 + * by Oracle in the LICENSE file that accompanied this code. 1.13 + * 1.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.17 + * version 2 for more details (a copy is included in the LICENSE file that 1.18 + * accompanied this code). 1.19 + * 1.20 + * You should have received a copy of the GNU General Public License version 1.21 + * 2 along with this work; if not, write to the Free Software Foundation, 1.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.23 + * 1.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.25 + * or visit www.oracle.com if you need additional information or have any 1.26 + * questions. 1.27 + */ 1.28 + 1.29 +package com.sun.tools.classfile; 1.30 + 1.31 +import java.util.ArrayList; 1.32 +import java.util.HashSet; 1.33 +import java.util.List; 1.34 +import java.util.Objects; 1.35 +import java.util.Set; 1.36 +import com.sun.tools.classfile.Instruction.TypeKind; 1.37 +import static com.sun.tools.classfile.ConstantPool.*; 1.38 + 1.39 +/** 1.40 + * A utility class to find where in a ClassFile references 1.41 + * a {@link CONSTANT_Methodref_info method}, 1.42 + * a {@link CONSTANT_InterfaceMethodref_info interface method, 1.43 + * or a {@link CONSTANT_Fieldref_info field}. 1.44 + */ 1.45 +public final class ReferenceFinder { 1.46 + /** 1.47 + * Filter for ReferenceFinder of what constant pool entries for reference lookup. 1.48 + */ 1.49 + public interface Filter { 1.50 + /** 1.51 + * Decides if the given CPRefInfo entry should be accepted or filtered. 1.52 + * 1.53 + * @param cpool ConstantPool of the ClassFile being parsed 1.54 + * @param cpref constant pool entry representing a reference to 1.55 + * a fields method, and interface method. 1.56 + * @return {@code true} if accepted; otherwise {@code false} 1.57 + */ 1.58 + boolean accept(ConstantPool cpool, CPRefInfo cpref); 1.59 + } 1.60 + 1.61 + /** 1.62 + * Visitor of individual method of a ClassFile that references the 1.63 + * accepted field, method, or interface method references. 1.64 + */ 1.65 + public interface Visitor { 1.66 + /** 1.67 + * Invoked for a method containing one or more accepted CPRefInfo entries 1.68 + * 1.69 + * @param cf ClassFile 1.70 + * @param method Method that does the references the accepted references 1.71 + * @param refs Accepted constant pool method/field reference 1.72 + */ 1.73 + void visit(ClassFile cf, Method method, List<CPRefInfo> refConstantPool); 1.74 + } 1.75 + 1.76 + private final Filter filter; 1.77 + private final Visitor visitor; 1.78 + 1.79 + /** 1.80 + * Constructor. 1.81 + */ 1.82 + public ReferenceFinder(Filter filter, Visitor visitor) { 1.83 + this.filter = Objects.requireNonNull(filter); 1.84 + this.visitor = Objects.requireNonNull(visitor); 1.85 + } 1.86 + 1.87 + /** 1.88 + * Parses a given ClassFile and invoke the visitor if there is any reference 1.89 + * to the constant pool entries referencing field, method, or 1.90 + * interface method that are accepted. This method will return 1.91 + * {@code true} if there is one or more accepted constant pool entries 1.92 + * to lookup; otherwise, it will return {@code false}. 1.93 + * 1.94 + * @param cf ClassFile 1.95 + * @return {@code true} if the given class file is processed to lookup 1.96 + * references 1.97 + * @throws ConstantPoolException if an error of the constant pool 1.98 + */ 1.99 + public boolean parse(ClassFile cf) throws ConstantPoolException { 1.100 + List<Integer> cprefs = new ArrayList<Integer>(); 1.101 + int index = 1; 1.102 + for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) { 1.103 + if (cpInfo.accept(cpVisitor, cf.constant_pool)) { 1.104 + cprefs.add(index); 1.105 + } 1.106 + index += cpInfo.size(); 1.107 + } 1.108 + 1.109 + if (cprefs.isEmpty()) { 1.110 + return false; 1.111 + } 1.112 + 1.113 + for (Method m : cf.methods) { 1.114 + Set<Integer> ids = new HashSet<Integer>(); 1.115 + Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code); 1.116 + if (c_attr != null) { 1.117 + for (Instruction instr : c_attr.getInstructions()) { 1.118 + int idx = instr.accept(codeVisitor, cprefs); 1.119 + if (idx > 0) { 1.120 + ids.add(idx); 1.121 + } 1.122 + } 1.123 + } 1.124 + if (ids.size() > 0) { 1.125 + List<CPRefInfo> refInfos = new ArrayList<CPRefInfo>(ids.size()); 1.126 + for (int id : ids) { 1.127 + refInfos.add(CPRefInfo.class.cast(cf.constant_pool.get(id))); 1.128 + } 1.129 + visitor.visit(cf, m, refInfos); 1.130 + } 1.131 + } 1.132 + return true; 1.133 + } 1.134 + 1.135 + private ConstantPool.Visitor<Boolean,ConstantPool> cpVisitor = 1.136 + new ConstantPool.Visitor<Boolean,ConstantPool>() 1.137 + { 1.138 + public Boolean visitClass(CONSTANT_Class_info info, ConstantPool cpool) { 1.139 + return false; 1.140 + } 1.141 + 1.142 + public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ConstantPool cpool) { 1.143 + return filter.accept(cpool, info); 1.144 + } 1.145 + 1.146 + public Boolean visitMethodref(CONSTANT_Methodref_info info, ConstantPool cpool) { 1.147 + return filter.accept(cpool, info); 1.148 + } 1.149 + 1.150 + public Boolean visitFieldref(CONSTANT_Fieldref_info info, ConstantPool cpool) { 1.151 + return filter.accept(cpool, info); 1.152 + } 1.153 + 1.154 + public Boolean visitDouble(CONSTANT_Double_info info, ConstantPool cpool) { 1.155 + return false; 1.156 + } 1.157 + 1.158 + public Boolean visitFloat(CONSTANT_Float_info info, ConstantPool cpool) { 1.159 + return false; 1.160 + } 1.161 + 1.162 + public Boolean visitInteger(CONSTANT_Integer_info info, ConstantPool cpool) { 1.163 + return false; 1.164 + } 1.165 + 1.166 + public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ConstantPool cpool) { 1.167 + return false; 1.168 + } 1.169 + 1.170 + public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) { 1.171 + return false; 1.172 + } 1.173 + 1.174 + public Boolean visitNameAndType(CONSTANT_NameAndType_info info, ConstantPool cpool) { 1.175 + return false; 1.176 + } 1.177 + 1.178 + public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, ConstantPool cpool) { 1.179 + return false; 1.180 + } 1.181 + 1.182 + public Boolean visitMethodType(CONSTANT_MethodType_info info, ConstantPool cpool) { 1.183 + return false; 1.184 + } 1.185 + 1.186 + public Boolean visitString(CONSTANT_String_info info, ConstantPool cpool) { 1.187 + return false; 1.188 + } 1.189 + 1.190 + public Boolean visitUtf8(CONSTANT_Utf8_info info, ConstantPool cpool) { 1.191 + return false; 1.192 + } 1.193 + }; 1.194 + 1.195 + private Instruction.KindVisitor<Integer, List<Integer>> codeVisitor = 1.196 + new Instruction.KindVisitor<Integer, List<Integer>>() 1.197 + { 1.198 + public Integer visitNoOperands(Instruction instr, List<Integer> p) { 1.199 + return 0; 1.200 + } 1.201 + 1.202 + public Integer visitArrayType(Instruction instr, TypeKind kind, List<Integer> p) { 1.203 + return 0; 1.204 + } 1.205 + 1.206 + public Integer visitBranch(Instruction instr, int offset, List<Integer> p) { 1.207 + return 0; 1.208 + } 1.209 + 1.210 + public Integer visitConstantPoolRef(Instruction instr, int index, List<Integer> p) { 1.211 + return p.contains(index) ? index : 0; 1.212 + } 1.213 + 1.214 + public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List<Integer> p) { 1.215 + return p.contains(index) ? index : 0; 1.216 + } 1.217 + 1.218 + public Integer visitLocal(Instruction instr, int index, List<Integer> p) { 1.219 + return 0; 1.220 + } 1.221 + 1.222 + public Integer visitLocalAndValue(Instruction instr, int index, int value, List<Integer> p) { 1.223 + return 0; 1.224 + } 1.225 + 1.226 + public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List<Integer> p) { 1.227 + return 0; 1.228 + } 1.229 + 1.230 + public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List<Integer> p) { 1.231 + return 0; 1.232 + } 1.233 + 1.234 + public Integer visitValue(Instruction instr, int value, List<Integer> p) { 1.235 + return 0; 1.236 + } 1.237 + 1.238 + public Integer visitUnknown(Instruction instr, List<Integer> p) { 1.239 + return 0; 1.240 + } 1.241 + }; 1.242 +} 1.243 +