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.
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
/*
* Copyright (C) 2008 The Android Open Source Project
*
* 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.
*/
/*
* Copyright (C) 2012 RoboVM AB
*
* 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 java.lang.reflect;
import java.lang.annotation.Annotation;
import java.util.Hashtable;
import com.bugvm.rt.ReflectionAccess;
/**
* {@code AccessibleObject} is the superclass of all member reflection classes
* (Field, Constructor, Method). AccessibleObject provides the ability to toggle
* a flag controlling access checks for these objects. By default, accessing a
* member (for example, setting a field or invoking a method) checks the
* validity of the access (for example, invoking a private method from outside
* the defining class is prohibited) and throws IllegalAccessException if the
* operation is not permitted. If the accessible flag is set to true, these
* checks are omitted. This allows privileged code, such as Java object
* serialization, object inspectors, and debuggers to have complete access to
* objects.
*
* @see Field
* @see Constructor
* @see Method
*/
public class AccessibleObject implements AnnotatedElement {
static final ReflectionAccess REFLECTION_ACCESS = new ReflectionAccess() {
public Method[] clone(Method[] m) {
if (m.length == 0) {
return m;
}
Method[] result = new Method[m.length];
for (int i = 0; i < result.length; i++) {
result[i] = new Method(m[i]);
}
return result;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
public Constructor>[] clone(Constructor>[] c) {
if (c.length == 0) {
return c;
}
Constructor[] result = new Constructor[c.length];
for (int i = 0; i < result.length; i++) {
result[i] = new Constructor(c[i]);
}
return result;
}
public Field[] clone(Field[] f) {
if (f.length == 0) {
return f;
}
Field[] result = new Field[f.length];
for (int i = 0; i < result.length; i++) {
result[i] = new Field(f[i]);
}
return result;
}
public Method clone(Method m) {
return new Method(m);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
public Constructor> clone(Constructor> c) {
return new Constructor(c);
}
public Field clone(Field f) {
return new Field(f);
}
public boolean equals(Method a, Method b) {
if (a.getReturnType() != b.getReturnType()) {
return false;
}
if (!a.getName().equals(b.getName())) {
return false;
}
return compareClassLists(a.getParameterTypes(false), b.getParameterTypes(false));
}
public boolean matchParameterTypes(Constructor> c, Class>[] parameterTypes) {
return compareClassLists(c.getParameterTypes(false), parameterTypes);
}
public boolean matchParameterTypes(Method m, Class>[] parameterTypes) {
return compareClassLists(m.getParameterTypes(false), parameterTypes);
}
private boolean compareClassLists(Class>[] a, Class>[] b) {
// Copied from Android's ClassCache.java
// Start (C) Android
if (a == null) {
return (b == null) || (b.length == 0);
}
int length = a.length;
if (b == null) {
return (length == 0);
}
if (length != b.length) {
return false;
}
for (int i = length - 1; i >= 0; i--) {
if (a[i] != b[i]) {
return false;
}
}
return true;
// End (C) Android
}
};
/**
* If true, object is accessible, bypassing normal access checks
*/
boolean flag = false;
// Holds a mapping from Java type names to native type codes.
static Hashtable trans;
static {
trans = new Hashtable(9);
trans.put("byte", "B");
trans.put("char", "C");
trans.put("short", "S");
trans.put("int", "I");
trans.put("long", "J");
trans.put("float", "F");
trans.put("double", "D");
trans.put("void", "V");
trans.put("boolean", "Z");
}
/**
* Attempts to set the value of the accessible flag for all the objects in
* the array provided. Setting this
* flag to {@code false} will enable access checks, setting to {@code true}
* will disable them.
*
* @param objects
* the accessible objects
* @param flag
* the new value for the accessible flag
*
* @see #setAccessible(boolean)
*/
public static void setAccessible(AccessibleObject[] objects, boolean flag) {
for (AccessibleObject object : objects) {
object.flag = flag;
}
}
/**
* Constructs a new {@code AccessibleObject} instance. {@code
* AccessibleObject} instances can only be constructed by the virtual
* machine.
*/
protected AccessibleObject() {
}
/**
* Indicates whether this object is accessible without access checks being
* performed. Returns the accessible flag.
*
* @return {@code true} if this object is accessible without access
* checks, {@code false} otherwise
*/
public boolean isAccessible() {
return flag;
}
/**
* Attempts to set the value of the accessible flag. Setting this flag to
* {@code false} will enable access checks, setting to {@code true} will
* disable them.
*
* @param flag
* the new value for the accessible flag
*/
public void setAccessible(boolean flag) {
this.flag = flag;
}
public boolean isAnnotationPresent(Class extends Annotation> annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
return getAnnotation(annotationType) != null;
}
public Annotation[] getDeclaredAnnotations() {
return getDeclaredAnnotations(true);
}
protected Annotation[] getDeclaredAnnotations(boolean copy) {
throw new UnsupportedOperationException();
}
public Annotation[] getAnnotations() {
// for all but Class, getAnnotations == getDeclaredAnnotations
return getDeclaredAnnotations();
}
/* slow, but works for all sub-classes */
public T getAnnotation(Class annotationType) {
if (annotationType == null) {
throw new NullPointerException("annotationType == null");
}
Annotation[] annos = getDeclaredAnnotations(false);
for (int i = annos.length-1; i >= 0; --i) {
if (annos[i].annotationType() == annotationType) {
return (T) annos[i];
}
}
return null;
}
/**
* Returns the signature for a class. This is the kind of signature used
* internally by the JVM, with one-character codes representing the basic
* types. It is not suitable for printing.
*
* @param clazz
* the class for which a signature is required
*
* @return The signature as a string
*/
String getSignature(Class> clazz) {
String result = "";
String nextType = clazz.getName();
if(trans.containsKey(nextType)) {
result = trans.get(nextType);
} else {
if(clazz.isArray()) {
result = "[" + getSignature(clazz.getComponentType());
} else {
result = "L" + nextType + ";";
}
}
return result;
}
/**
* Returns a printable String consisting of the canonical names of the
* classes contained in an array. The form is that used in parameter and
* exception lists, that is, the class or type names are separated by
* commas.
*
* @param types
* the array of classes
*
* @return The String of names
*/
String toString(Class>[] types) {
StringBuilder result = new StringBuilder();
if (types.length != 0) {
appendTypeName(result, types[0]);
for (int i = 1; i < types.length; i++) {
result.append(',');
appendTypeName(result, types[i]);
}
}
return result.toString();
}
/**
* Gets the Signature attribute for this instance. Returns {@code null}
* if not found.
*/
/*package*/ String getSignatureAttribute() {
/*
* Note: This method would have been declared abstract, but the
* standard API lists this class as concrete.
*/
throw new UnsupportedOperationException();
}
static boolean isSamePackage(Class> c1, Class> c2) {
if (c1 == c2) {
return true;
}
if (c1.getClassLoader() != c2.getClassLoader()) {
return false;
}
String n1 = c1.getName();
String n2 = c2.getName();
int dot1 = n1.lastIndexOf('.');
int dot2 = n2.lastIndexOf('.');
if (dot1 == -1) {
return dot2 == -1;
}
if (dot1 != dot2) {
return false;
}
return n1.substring(0, dot1).equals(n2.substring(0, dot2));
}
/**
* Returns the access flags for the specified {@link Class} without checking the InnerClasses
* attribute for inner classes. This is described in this bug report:
* http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4471811
*/
static native int getAccessFlags(Class> cls);
static boolean checkAccessibleFast(Member member) {
int access = member.getModifiers();
return (getAccessFlags(member.getDeclaringClass()) & access & Modifier.PUBLIC) > 0;
}
static boolean checkAccessible(Class> caller, Member member) {
Class> callee = member.getDeclaringClass();
if (caller == callee) {
return true;
}
boolean samePackage = false;
// Check if callee class is accessible
if ((getAccessFlags(callee) & Modifier.PUBLIC) == 0) {
samePackage = isSamePackage(caller, callee);
if (!samePackage) {
return false;
}
}
// Check member accessible
int access = member.getModifiers();
if ((access & Modifier.PUBLIC) > 0) {
return true;
}
if ((access & Modifier.PRIVATE) > 0) {
return false;
}
if ((access & Modifier.PROTECTED) > 0) {
Class> sc = caller.getSuperclass();
while (sc != null) {
if (sc == callee) {
return true;
}
sc = sc.getSuperclass();
}
}
return samePackage || isSamePackage(caller, callee);
}
/**
* Appends the best {@link #toString} name for {@code c} to {@code out}.
* This works around the fact that {@link Class#getName} is lousy for
* primitive arrays (it writes "[C" instead of "char[]") and {@link
* Class#getCanonicalName()} is lousy for nested classes (it uses a "."
* separator rather than a "$" separator).
*/
void appendTypeName(StringBuilder out, Class> c) {
int dimensions = 0;
while (c.isArray()) {
c = c.getComponentType();
dimensions++;
}
out.append(c.getName());
for (int d = 0; d < dimensions; d++) {
out.append("[]");
}
}
/**
* Appends names of the specified array classes to the buffer. The array
* elements may represent a simple type, a reference type or an array type.
* Output format: java.lang.Object[], java.io.File, void
*
* @param types array of classes to print the names
* @throws NullPointerException if any of the arguments is null
*/
void appendArrayGenericType(StringBuilder sb, Type[] types) {
if (types.length > 0) {
appendGenericType(sb, types[0]);
for (int i = 1; i < types.length; i++) {
sb.append(',');
appendGenericType(sb, types[i]);
}
}
}
/**
* Appends the generic type representation to the buffer.
*
* @param sb buffer
* @param obj the generic type which representation should be appended to the buffer
*
* @throws NullPointerException if any of the arguments is null
*/
void appendGenericType(StringBuilder sb, Type obj) {
if (obj instanceof TypeVariable) {
sb.append(((TypeVariable)obj).getName());
} else if (obj instanceof ParameterizedType) {
sb.append(obj.toString());
} else if (obj instanceof GenericArrayType) { //XXX: is it a working branch?
Type simplified = ((GenericArrayType)obj).getGenericComponentType();
appendGenericType(sb, simplified);
sb.append("[]");
} else if (obj instanceof Class) {
Class c = ((Class>)obj);
if (c.isArray()){
String as[] = c.getName().split("\\[");
int len = as.length-1;
if (as[len].length() > 1){
sb.append(as[len].substring(1, as[len].length()-1));
} else {
char ch = as[len].charAt(0);
if (ch == 'I')
sb.append("int");
else if (ch == 'B')
sb.append("byte");
else if (ch == 'J')
sb.append("long");
else if (ch == 'F')
sb.append("float");
else if (ch == 'D')
sb.append("double");
else if (ch == 'S')
sb.append("short");
else if (ch == 'C')
sb.append("char");
else if (ch == 'Z')
sb.append("boolean");
else if (ch == 'V') //XXX: is it a working branch?
sb.append("void");
}
for (int i = 0; i < len; i++){
sb.append("[]");
}
} else {
sb.append(c.getName());
}
}
}
}