/* * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code 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. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. * */ package com.sun.classanalyzer; import com.sun.classanalyzer.Klass.Method; /** * * @author mchung */ public class ResolutionInfo implements Comparable { enum Type { REFLECTION("reflection", true), NATIVE("native", true), INTERFACE("interface", false), SUPER("super", false), EXPLICIT("explicit", false), VERIFICATION("verification", false), METHODTRACE("method trace", true), CONSTANT_POOL("constant pool", true), CHECKED_EXCEPTION("throws", true), METHOD("method", true), FIELD("field", true), EXTENDS("extends", true), IMPLEMENTS("implements", true), NOINFO("No info", false); private final String name; private final boolean hasInfo; private Type(String name, boolean hasInfo) { this.name = name; this.hasInfo = hasInfo; } public String getName() { return name; } public boolean hasInfo() { return hasInfo; } public static Type getType(String s) { if (s.isEmpty()) { return NOINFO; } for (Type t : values()) { if (s.equals(t.name)) { return t; } } // Need to fix the VM output to add "native" // throw new IllegalArgumentException("Invalid ResolutionInfo.type \"" + s + "\""); System.out.println("WARNING: Invalid ResolutionInfo.type \"" + s + "\""); return null; } } final Klass fromClass; final Method method; final Klass toClass; final int linenumber; final Type type; final String info; private boolean isPublic = false; private ResolutionInfo(Klass from, Klass to, int linenumber, Type type, String info) { this.fromClass = from; this.method = null; this.toClass = to; this.linenumber = linenumber; this.type = type; this.info = info; } private ResolutionInfo(Klass from, Method m, Klass to, int linenumber, Type type) { this.fromClass = from; this.method = m; this.toClass = to; this.linenumber = linenumber; this.type = type; this.info = m.toString(); } public boolean isPublic() { return isPublic; } public void setPublicAccess(boolean value) { isPublic = value; } static ResolutionInfo resolved(Klass from, Klass to) { return new ResolutionInfo(from, to, 0, Type.NOINFO, ""); } static ResolutionInfo resolved(Klass from, Klass to, int linenumber) { return new ResolutionInfo(from, to, linenumber, Type.NOINFO, ""); } static ResolutionInfo resolved(Klass from, Klass to, int linenumber, String reason) { String[] ss = reason.split("\\s+"); Type type; String info; if (linenumber == -1) { type = Type.NATIVE; info = ss[0]; // native method name } else { info = ss.length == 2 ? ss[1] : ""; type = Type.getType(ss[0]); if (type == null) { if (reason.isEmpty()) { throw new IllegalArgumentException("Invalid type: " + reason + " (" + ss[0] + ")" + ss.length); } // assume it's native type = Type.NATIVE; info = reason.isEmpty() ? ss[0] : reason; } } return new ResolutionInfo(from, to, linenumber, type, info); } static ResolutionInfo resolved(Klass from, Klass to, Method callee) { return new ResolutionInfo(from, callee, to, 0, Type.METHODTRACE); } static ResolutionInfo resolvedConstantPool(Klass from, Klass to, int index) { return new ResolutionInfo(from, to, 0, Type.CONSTANT_POOL, "#" + index); } static ResolutionInfo resolvedField(Klass from, Klass to, String fieldname) { return new ResolutionInfo(from, to, 0, Type.FIELD, fieldname); } static ResolutionInfo resolvedMethodSignature(Klass from, Klass to, Method m) { return new ResolutionInfo(from, m, to, 0, Type.METHOD); } static ResolutionInfo resolvedCheckedException(Klass from, Klass to, Method m) { return new ResolutionInfo(from, m, to, 0, Type.CHECKED_EXCEPTION); } static ResolutionInfo resolvedExtends(Klass from, Klass to) { String info = from.getClassName() + " implements " + to.getClassName(); return new ResolutionInfo(from, to, 0, Type.EXTENDS, info); } static ResolutionInfo resolvedImplements(Klass from, Klass to) { String info = from.getClassName() + " implements " + to.getClassName(); return new ResolutionInfo(from, to, 0, Type.IMPLEMENTS, info); } @Override public int compareTo(ResolutionInfo ri) { if (this.fromClass == ri.fromClass && this.toClass == ri.toClass && this.linenumber == ri.linenumber && this.type == ri.type && this.info.equals(ri.info)) { return 0; } else if (this.fromClass == ri.fromClass) { if (this.linenumber > ri.linenumber) { return 1; } else if (this.linenumber < ri.linenumber) { return -1; } else if (this.type != ri.type) { return this.type.getName().compareTo(ri.type.getName()); } else if (this.toClass != ri.toClass) { return this.toClass.compareTo(ri.toClass); } else { return this.info.compareTo(ri.info); } } else { return this.fromClass.compareTo(ri.fromClass); } } }