
org.adoptopenjdk.jitwatch.model.AbstractMetaMember Maven / Gradle / Ivy
/*
* Copyright (c) 2013-2016 Chris Newland.
* Licensed under https://github.com/AdoptOpenJDK/jitwatch/blob/master/LICENSE-BSD
* Instructions: https://github.com/AdoptOpenJDK/jitwatch/wiki
*/
package org.adoptopenjdk.jitwatch.model;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_CLOSE_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_DOLLAR;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_HAT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_OPEN_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_OPEN_SQUARE_BRACKET;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.C_SPACE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING_ASSEMBLY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.DEBUG_LOGGING_SIG_MATCH;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_GROUP_ANY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_ONE_OR_MORE_SPACES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_UNICODE_PACKAGE_NAME;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_UNICODE_PARAM_NAME;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.REGEX_ZERO_OR_MORE_SPACES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_CLOSE_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_COMMA;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_DOT;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_EMPTY;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_CLOSE_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_CLOSE_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_OPEN_PARENTHESES;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_ESCAPED_OPEN_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_OPEN_SQUARE;
import static org.adoptopenjdk.jitwatch.core.JITWatchConstants.S_POLYMORPHIC_SIGNATURE;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.adoptopenjdk.jitwatch.model.assembly.AssemblyMethod;
import org.adoptopenjdk.jitwatch.model.bytecode.BytecodeInstruction;
import org.adoptopenjdk.jitwatch.model.bytecode.ClassBC;
import org.adoptopenjdk.jitwatch.model.bytecode.MemberBytecode;
import org.adoptopenjdk.jitwatch.util.ParseUtil;
import org.adoptopenjdk.jitwatch.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public abstract class AbstractMetaMember implements IMetaMember, Comparable
{
protected static final Logger logger = LoggerFactory.getLogger(AbstractMetaMember.class);
protected MetaClass metaClass;
private List assemblyMethods = new ArrayList<>();
private boolean isQueued = false;
private boolean isCompiled = false;
private Journal journal = new Journal();
private Map queuedAttributes = new ConcurrentHashMap<>();
private Map compiledAttributes = new ConcurrentHashMap<>();
protected boolean isVarArgs = false;
protected boolean isPolymorphicSignature = false;
protected int modifier; // bitset
private String memberName;
protected Class> returnType;
protected List> paramTypes;
public AbstractMetaMember(String memberName)
{
this.memberName = memberName;
}
protected void checkPolymorphicSignature(Method method)
{
for (Annotation anno : method.getAnnotations())
{
if (S_POLYMORPHIC_SIGNATURE.equals(anno.annotationType().getSimpleName()))
{
isPolymorphicSignature = true;
break;
}
}
}
@Override
public String getMemberName()
{
return memberName;
}
@Override
public String getFullyQualifiedMemberName()
{
return metaClass.getFullyQualifiedName() + C_DOT + memberName;
}
@Override
public String getAbbreviatedFullyQualifiedMemberName()
{
return metaClass.getAbbreviatedFullyQualifiedName() + C_DOT + memberName;
}
@Override
public int getModifier()
{
return modifier;
}
@Override
public String getModifierString()
{
return Modifier.toString(modifier);
}
private boolean nameMatches(MemberSignatureParts msp)
{
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("nameMatches this.memberName: '{}' fq: '{}' other '{}' fq: '{}'", memberName, getFullyQualifiedMemberName(), msp.getMemberName(), msp.getFullyQualifiedClassName());
}
boolean match = memberName.equals(msp.getMemberName());
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("nameMatches {}", match);
}
return match;
}
private boolean returnTypeMatches(MemberSignatureParts msp) throws ClassNotFoundException
{
boolean matched = false;
String returnTypeClassName = msp.applyGenericSubstitutionsForClassLoading(msp.getReturnType());
if (returnTypeClassName != null)
{
Class> sigReturnType = ParseUtil.findClassForLogCompilationParameter(returnTypeClassName);
matched = returnType.equals(sigReturnType);
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Return: '{}' === '{}' ? {}", returnType.getName(), sigReturnType.getName(), matched);
}
}
else
{
matched = (this instanceof MetaConstructor);
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Constructor found");
}
}
return matched;
}
@Override
public boolean matchesSignature(MemberSignatureParts msp, boolean matchTypesExactly)
{
boolean result = false;
if (nameMatches(msp))
{
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Comparing:\n--------------\n{}\n--------------\n{}\n--------------", this, msp);
}
if (isPolymorphicSignature)
{
// assumption: method overloading not possible
// with polymorphic signatures so this is a match
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Member has PolymorphicSignature");
}
result = true;
}
else
{
try
{
if (returnTypeMatches(msp))
{
List> mspClassTypes = getClassesForParamTypes(msp);
if (ParseUtil.paramClassesMatch(isVarArgs, this.paramTypes, mspClassTypes, matchTypesExactly))
{
result = true;
}
}
}
catch (ClassNotFoundException cnfe)
{
logger.error("Class not found while matching signature:\n{}", msp, cnfe);
}
}
if (DEBUG_LOGGING_SIG_MATCH)
{
logger.debug("Match: {}", result);
}
}
return result;
}
private List> getClassesForParamTypes(MemberSignatureParts msp) throws ClassNotFoundException
{
List> result = new ArrayList<>();
for (String param : msp.getParamTypes())
{
String paramClassName = msp.applyGenericSubstitutionsForClassLoading(param);
Class> clazz = ParseUtil.findClassForLogCompilationParameter(paramClassName);
result.add(clazz);
}
return result;
}
@Override
public String getReturnTypeName()
{
return (returnType == null) ? S_EMPTY : ParseUtil.expandParameterType(returnType.getName());
}
@Override
public String[] getParamTypeNames()
{
List typeNames = new ArrayList<>();
for (Class> paramClass : paramTypes)
{
typeNames.add(ParseUtil.expandParameterType(paramClass.getName()));
}
return typeNames.toArray(new String[typeNames.size()]);
}
@Override
public MemberBytecode getMemberBytecode()
{
MemberBytecode result = null;
if (metaClass != null)
{
ClassBC classBytecode = metaClass.getClassBytecode();
if (classBytecode != null)
{
result = classBytecode.getMemberBytecode(this);
}
}
return result;
}
@Override
public List getInstructions()
{
List result = null;
MemberBytecode memberBytecode = getMemberBytecode();
if (memberBytecode != null)
{
result = memberBytecode.getInstructions();
}
else
{
result = new ArrayList<>();
}
return result;
}
@Override
public MetaClass getMetaClass()
{
return metaClass;
}
@Override
public String getQueuedAttribute(String key)
{
return queuedAttributes.get(key);
}
@Override
public String getCompiledAttribute(String key)
{
return compiledAttributes.get(key);
}
@Override
public void addCompiledAttribute(String key, String value)
{
compiledAttributes.put(key, value);
}
@Override
public void setQueuedAttributes(Map queuedAttributes)
{
isQueued = true;
this.queuedAttributes = queuedAttributes;
}
@Override
public boolean isQueued()
{
return isQueued;
}
@Override
public void setCompiledAttributes(Map compiledAttributes)
{
isCompiled = true;
isQueued = false;
this.compiledAttributes = compiledAttributes;
// inform package tree it contains class with a compiled method
getMetaClass().getPackage().setHasCompiledClasses();
}
@Override
public void addCompiledAttributes(Map additionalAttrs)
{
compiledAttributes.putAll(additionalAttrs);
}
@Override
public boolean isCompiled()
{
return isCompiled;
}
@Override
public Map getQueuedAttributes()
{
return queuedAttributes;
}
@Override
public Map getCompiledAttributes()
{
return compiledAttributes;
}
@Override
public String toStringUnqualifiedMethodName(boolean fqParamTypes)
{
StringBuilder builder = new StringBuilder();
if (modifier != 0)
{
builder.append(Modifier.toString(modifier)).append(C_SPACE);
}
if (returnType != null)
{
builder.append(expandParam(returnType.getName(), fqParamTypes)).append(C_SPACE);
}
builder.append(memberName);
builder.append(C_OPEN_PARENTHESES);
if (paramTypes.size() > 0)
{
for (Class> paramClass : paramTypes)
{
builder.append(expandParam(paramClass.getName(), fqParamTypes)).append(C_COMMA);
}
builder.deleteCharAt(builder.length() - 1);
}
builder.append(C_CLOSE_PARENTHESES);
return builder.toString();
}
@Override
public List getAssemblyMethods()
{
return assemblyMethods;
}
@Override
public void addAssembly(AssemblyMethod asmMethod)
{
if (DEBUG_LOGGING_ASSEMBLY)
{
logger.debug("setAssembly on member {}", getFullyQualifiedMemberName());
}
assemblyMethods.add(asmMethod);
}
@Override
public String getSignatureRegEx()
{
StringBuilder builder = new StringBuilder();
builder.append(C_HAT);
builder.append(REGEX_GROUP_ANY);
String modifiers = Modifier.toString(modifier);
if (modifiers.length() > 0)
{
builder.append(modifiers).append(C_SPACE);
}
// return type of constructor is not declared in signature
if (!(this instanceof MetaConstructor) && returnType != null)
{
String rt = expandParamRegEx(returnType.getName());
builder.append(rt);
builder.append(C_SPACE);
}
if (this instanceof MetaConstructor)
{
builder.append(REGEX_UNICODE_PACKAGE_NAME);
builder.append(StringUtil.getUnqualifiedClassName(memberName));
}
else
{
builder.append(memberName);
}
builder.append(REGEX_ZERO_OR_MORE_SPACES);
builder.append(S_ESCAPED_OPEN_PARENTHESES);
if (paramTypes.size() > 0)
{
for (Class> paramClass : paramTypes)
{
builder.append(REGEX_ZERO_OR_MORE_SPACES);
String paramType = expandParamRegEx(paramClass.getName());
builder.append(paramType);
builder.append(REGEX_ONE_OR_MORE_SPACES);
builder.append(REGEX_UNICODE_PARAM_NAME);
builder.append(S_COMMA);
}
builder.deleteCharAt(builder.length() - 1);
}
builder.append(REGEX_ZERO_OR_MORE_SPACES);
builder.append(S_ESCAPED_CLOSE_PARENTHESES);
builder.append(REGEX_GROUP_ANY);
builder.append(C_DOLLAR);
return builder.toString();
}
public static String expandParam(String inParamType, boolean fullyQualifiedType)
{
String paramType = inParamType;
if (paramType.charAt(0) == C_OPEN_SQUARE_BRACKET)
{
paramType = ParseUtil.expandParameterType(paramType);
}
if (paramType.contains(S_DOT) && !fullyQualifiedType)
{
paramType = StringUtil.getUnqualifiedClassName(paramType);
}
return paramType;
}
public static String expandParamRegEx(String inParamType)
{
String paramType = inParamType;
if (paramType.charAt(0) == C_OPEN_SQUARE_BRACKET)
{
paramType = ParseUtil.expandParameterType(paramType);
paramType = paramType.replace(S_OPEN_SQUARE, S_ESCAPED_OPEN_SQUARE).replace(S_CLOSE_SQUARE, S_ESCAPED_CLOSE_SQUARE);
}
if (paramType.contains(S_DOT))
{
paramType = REGEX_UNICODE_PACKAGE_NAME + StringUtil.getUnqualifiedClassName(paramType);
}
return paramType;
}
@Override
public int compareTo(IMetaMember other)
{
if (other == null)
{
return -1;
}
else
{
return getMemberName().compareTo(other.getMemberName());
}
}
@Override
public Journal getJournal()
{
return journal;
}
@Override
public void addJournalEntry(Tag entry)
{
journal.addEntry(entry);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy