Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010-2012 VMware and contributors
*
* 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.springsource.loaded;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
/**
* Representation of a Method. Some of the bitflags and state are only set for 'incremental' methods - those found in a secondary
* type descriptor representing a type reload.
*
* @author Andy Clement
* @since 0.5.0
*/
public class MethodMember extends AbstractMember {
final static MethodMember[] NONE = new MethodMember[0];
protected final String[] exceptions;
public int bits;
// computed up front:
public final static int BIT_CATCHER = 0x001;
public final static int BIT_CLASH = 0x0002;
// identifies a catcher method placed into an abstract class (where a method from a super interface hasn't been implemented)
public final static int BIT_CATCHER_INTERFACE = 0x004;
public final static int BIT_SUPERDISPATCHER = 0x0008;
// computed on incremental members to indicate what changed:
public final static int MADE_STATIC = 0x0010;
public final static int MADE_NON_STATIC = 0x0020;
public final static int VISIBILITY_CHANGE = 0x0040;
public final static int IS_NEW = 0x0080;
public final static int WAS_DELETED = 0x0100;
public final static int EXCEPTIONS_CHANGE = 0x0200;
// For MethodMembers in an incremental type descriptor, this tracks the method in the original type descriptor (if there was one)
public MethodMember original;
public final String nameAndDescriptor;
public Method cachedMethod;
protected MethodMember(int modifiers, String name, String descriptor, String signature, String[] exceptions) {
super(modifiers, name, descriptor, signature);
this.exceptions = perhapsSortIfNecessary(exceptions);
this.nameAndDescriptor = new StringBuilder(name).append(descriptor).toString();
}
private String[] perhapsSortIfNecessary(String[] exceptions) {
if (exceptions == null) {
return Constants.NO_STRINGS;
}
// Arrays.sort(exceptions);
return exceptions;
}
public String[] getExceptions() {
return exceptions;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("0x").append(Integer.toHexString(modifiers));
sb.append(" ").append(name).append(descriptor);
if (exceptions.length != 0) {
sb.append(" throws ");
for (String ex : exceptions) {
sb.append(ex).append(" ");
}
}
return sb.toString().trim();
}
public String getParamDescriptor() {
// more likely to be at the end, lets go back from there
for (int pos = descriptor.length() - 1; pos > 0; pos--) {
if (descriptor.charAt(pos) == ')') {
return descriptor.substring(0, pos + 1);
}
}
throw new IllegalStateException("Method has invalid descriptor: " + descriptor);
}
public boolean hasReturnValue() {
return descriptor.charAt(descriptor.length() - 1) != 'V';
}
public boolean equals(Object other) {
if (!(other instanceof MethodMember)) {
return false;
}
MethodMember o = (MethodMember) other;
if (!name.equals(o.name)) {
return false;
}
if (modifiers != o.modifiers) {
return false;
}
if (!descriptor.equals(o.descriptor)) {
return false;
}
if (exceptions.length != o.exceptions.length) {
return false;
}
if (signature == null && o.signature != null) {
return false;
}
if (signature != null && o.signature == null) {
return false;
}
if (signature != null) {
if (!signature.equals(o.signature)) {
return false;
}
}
for (int i = 0; i < exceptions.length; i++) {
if (!exceptions[i].equals(o.exceptions[i])) {
return false;
}
}
return true;
}
public int hashCode() {
int result = modifiers;
result = result * 37 + name.hashCode();
result = result * 37 + descriptor.hashCode();
if (signature != null) {
result = result * 37 + signature.hashCode();
}
if (exceptions != null) {
for (String ex : exceptions) {
result = result * 37 + ex.hashCode();
}
}
return result;
}
public MethodMember catcherCopyOf() {
int newModifiers = modifiers & ~Modifier.NATIVE;
if (name.equals("clone") && (modifiers & Modifier.NATIVE) != 0) {
newModifiers = Modifier.PUBLIC;
} else if ((modifiers & Modifier.PROTECTED) != 0) {
// promote to public
// The reason for this is that the executor may try and call these things and as it is not in the hierarchy
// it cannot. The necessary knock on effect is that subtypes get their methods promoted to public too...
newModifiers = Modifier.PUBLIC;
} else if ((modifiers & Constants.ACC_PUBLIC_PRIVATE_PROTECTED) == 0) {
// promote to public from default
// The reason for this is that the executor may try and call these things and as it is not in the hierarchy
// it cannot. The necessary knock on effect is that subtypes get their methods promoted to public too...
newModifiers = Modifier.PUBLIC;
}
MethodMember copy = new MethodMember(newModifiers, name, descriptor, signature, exceptions);
copy.bits |= MethodMember.BIT_CATCHER;
return copy;
}
public MethodMember superDispatcherFor() {
int newModifiers = modifiers & ~Modifier.NATIVE;
if (name.equals("clone") && (modifiers & Modifier.NATIVE) != 0) {
newModifiers = Modifier.PUBLIC;
} else if ((modifiers & Modifier.PROTECTED) != 0) {
// promote to public
// The reason for this is that the executor may try and call these things and as it is not in the hierarchy
// it cannot. The necessary knock on effect is that subtypes get their methods promoted to public too...
newModifiers = Modifier.PUBLIC;
} else if ((modifiers & Constants.ACC_PUBLIC_PRIVATE_PROTECTED) == 0) {
// promote to public from default
// The reason for this is that the executor may try and call these things and as it is not in the hierarchy
// it cannot. The necessary knock on effect is that subtypes get their methods promoted to public too...
newModifiers = Modifier.PUBLIC;
}
MethodMember copy = new MethodMember(newModifiers, name+"_$superdispatcher$", descriptor, signature, exceptions);
copy.bits |= MethodMember.BIT_SUPERDISPATCHER;
return copy;
}
public MethodMember catcherCopyOfWithAbstractRemoved() {
int newModifiers = modifiers & ~(Modifier.NATIVE | Modifier.ABSTRACT);
if (name.equals("clone") && (modifiers & Modifier.NATIVE) != 0) {
newModifiers = Modifier.PUBLIC;
} else if ((modifiers & Modifier.PROTECTED) != 0) {
// promote to public
// The reason for this is that the executor may try and call these things and as it is not in the hierarchy
// it cannot. The necessary knock on effect is that subtypes get their methods promoted to public too...
newModifiers = Modifier.PUBLIC;
} else if ((modifiers & Constants.ACC_PUBLIC_PRIVATE_PROTECTED) == 0) {
// promote to public from default
// The reason for this is that the executor may try and call these things and as it is not in the hierarchy
// it cannot. The necessary knock on effect is that subtypes get their methods promoted to public too...
newModifiers = Modifier.PUBLIC;
}
MethodMember copy = new MethodMember(newModifiers, name, descriptor, signature, exceptions);
copy.bits |= MethodMember.BIT_CATCHER;
copy.bits |= MethodMember.BIT_CATCHER_INTERFACE;
return copy;
}
public boolean equalsApartFromModifiers(MethodMember other) {
if (!(other instanceof MethodMember)) {
return false;
}
MethodMember o = other;
if (!name.equals(o.name)) {
return false;
}
if (!descriptor.equals(o.descriptor)) {
return false;
}
// if (exceptions.length != o.exceptions.length) {
// return false;
// }
// for (int i = 0; i < exceptions.length; i++) {
// if (!exceptions[i].equals(o.exceptions[i])) {
// return false;
// }
// }
return true;
}
public String getNameAndDescriptor() {
return nameAndDescriptor;
}
public static boolean isClash(MethodMember method) {
return (method.bits & MethodMember.BIT_CLASH) != 0;
}
public static boolean isSuperDispatcher(MethodMember method) {
return (method.bits & BIT_SUPERDISPATCHER) != 0;
}
public static boolean isCatcher(MethodMember method) {
return (method.bits & BIT_CATCHER) != 0;
}
public static boolean isCatcherForInterfaceMethod(MethodMember method) {
return (method.bits & BIT_CATCHER_INTERFACE) != 0;
}
public static boolean isDeleted(MethodMember method) {
return (method.bits & WAS_DELETED) != 0;
}
public Object bitsToString() {
StringBuilder s = new StringBuilder();
if ((bits & BIT_CATCHER) != 0) {
s.append("catcher ");
}
if ((bits & BIT_CLASH) != 0) {
s.append("clash ");
}
if ((bits & BIT_SUPERDISPATCHER) != 0) {
s.append("superdispatcher ");
}
if ((bits & MADE_STATIC) != 0) {
s.append("made_static ");
}
if ((bits & MADE_NON_STATIC) != 0) {
s.append("made_non_static ");
}
if ((bits & VISIBILITY_CHANGE) != 0) {
s.append("vis_change ");
}
if ((bits & IS_NEW) != 0) {
s.append("is_new ");
}
if ((bits & WAS_DELETED) != 0) {
s.append("is_new ");
}
return "[" + s.toString().trim() + "]";
}
/*
* Determine whether this method should replace the other method on reload. In accordance to how JVM works at class load time,
* this will be the case if this and other have the same Class, name, parameter types and return type. I.e. formally, in JVM
* bytecode (unlike source code) a method doesn't override a method with a different return type. When such a situation occurs
* in source code, the compiler will introduce a bridge method in bytecode.
*/
public boolean shouldReplace(MethodMember other) {
if (!name.equals(other.name)) {
return false;
}
if (!descriptor.equals(other.descriptor)) {
return false;
}
return true;
}
public boolean isConstructor() {
return name.equals("");
}
}