/*
* Copyright 2006-2011 Brian S O'Neill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.cojen.dirmi.trace;
import java.lang.ref.WeakReference;
import org.cojen.classfile.TypeDesc;
/**
* Basic information regarding a traced method or constructor.
*
* @author Brian S O'Neill
*/
public class TracedMethod {
private static final Class[] NO_PARAMS = new Class[0];
/**
* @param mid method identifier
*/
public static boolean isRoot(int mid) {
return (mid & 0x80000000) != 0;
}
/**
* @param mid method identifier
*/
public static boolean isGraft(int mid) {
return (mid & 0x40000000) != 0;
}
private final int mMID;
private final String mOperation;
private final WeakReference<Class> mClass;
private final String mMethodName;
private final WeakReference<Class> mReturnType;
private final WeakReference<Class>[] mParamTypes;
private final String mStr;
/**
* @param mid reserved method identifier
* @param operation optional operation name
* @param clazz declaring class
* @param methodName method name or null for constructor
* @param returnType method return type, or null if void
* @param paramTypes method or constructor parameter types; first type must be null
* for non-static method or constructor; static method with no arguments can pass a
* null array
*/
TracedMethod(int mid, String operation,
Class clazz, String methodName, Class returnType, Class... paramTypes)
{
mMID = mid;
mOperation = operation;
StringBuilder b = new StringBuilder();
b.append(returnType == null ? "void" : returnType.getName()).append(' ');
b.append(TypeDesc.forClass(clazz).getFullName());
if (methodName != null) {
b.append('.').append(methodName);
}
b.append('(');
mClass = new WeakReference<Class>(clazz);
mMethodName = methodName;
if (returnType == null) {
mReturnType = null;
} else {
mReturnType = new WeakReference<Class>(returnType);
}
if (paramTypes == null || paramTypes.length == 0) {
mParamTypes = null;
} else {
mParamTypes = new WeakReference[paramTypes.length];
boolean any = false;
for (int i=0; i<paramTypes.length; i++) {
if (any) {
b.append(", ");
}
Class paramType = paramTypes[i];
if (paramType != null) {
b.append(TypeDesc.forClass(paramType).getFullName());
any = true;
}
mParamTypes[i] = paramType == null ? mClass : new WeakReference<Class>(paramType);
}
}
mStr = b.append(')').toString();
}
/**
* Returns the optional traced method operation.
*/
public String getOperation() {
return mOperation;
}
/**
* Returns true if traced method is a constructor.
*/
public boolean isConstructor() {
return mMethodName == null;
}
/**
* Returns true if traced method is static.
*/
public boolean isStatic() {
WeakReference<Class>[] paramTypes = mParamTypes;
return paramTypes == null || paramTypes[0] != mClass;
}
/**
* Returns the method's declaring class, or null if garbage collected.
*/
public Class getDeclaringClass() {
return mClass.get();
}
/**
* Returns the method's name, or null if a constructor.
*/
public String getMethodName() {
return mMethodName;
}
/**
* Returns the method's return type, which is null if void or if class has
* been garbage collected.
*/
public Class getReturnType() {
return mReturnType == null ? null : mReturnType.get();
}
/**
* Returns true if the method returns void.
*/
public boolean isVoid() {
return mReturnType == null;
}
/**
* Returns the method's parameter types, which may contain null elements if they have
* been garbage collected. First parameter of non-static method or constructor is
* always the "this" type.
*/
public Class[] getParameterTypes() {
WeakReference<Class>[] paramTypes = mParamTypes;
if (paramTypes == null) {
return NO_PARAMS;
}
int length = paramTypes.length;
Class[] classes = new Class[length];
for (int i=length; --i>=0; ) {
classes[i] = paramTypes[i].get();
}
return classes;
}
public boolean isRoot() {
return isRoot(mMID);
}
public boolean isGraft() {
return isGraft(mMID);
}
public int getMethodId() {
return mMID;
}
@Override
public String toString() {
return mStr;
}
}