/** * Returns the index of the parameter declared with the given type, ensuring that there is exactly one such parameter. * * @throws NoSuchFieldError if there is no or more than one parameter with that type. */ public static int getParameterIndexByType(final Member method, final Class<?> type) { final Class<?>[] classes = (method instanceof Method) ? ((Method) method).getParameterTypes() : ((Constructor<?>) method).getParameterTypes(); int idx = -1; for (int i = 0; i < classes.length; ++i) { if (classes[i] == type) { if (idx == -1) { idx = i; } else { throw new NoSuchFieldError("More than one parameter of type " + type + " found in " + method); } } } if (idx != -1) { return idx; } else { throw new NoSuchFieldError("No parameter of type " + type + " found in " + method); } }
@Override MethodHandle getTarget(final CallSiteDescriptor desc) { final MethodHandles.Lookup lookup = AccessController.doPrivileged( (PrivilegedAction<MethodHandles.Lookup>)()->desc.getLookup(), GET_LOOKUP_CONTEXT); if(target instanceof Method) { final MethodHandle mh = unreflect(lookup, (Method)target); if(Modifier.isStatic(((Member)target).getModifiers())) { return StaticClassIntrospector.editStaticMethodHandle(mh); } return mh; } return StaticClassIntrospector.editConstructorMethodHandle(unreflectConstructor(lookup, (Constructor<?>)target)); }
public void testPatchingPublic() throws Exception { Class<?> c = new L().loadClass(C.class.getName()); assertNotSame(c, C.class); Member m; m = c.getDeclaredConstructor(boolean.class); assertEquals(0, m.getModifiers() & Modifier.PUBLIC); assertEquals(Modifier.PRIVATE, m.getModifiers() & Modifier.PRIVATE); m = c.getDeclaredConstructor(int.class); assertEquals(Modifier.PUBLIC, m.getModifiers() & Modifier.PUBLIC); assertEquals(0, m.getModifiers() & Modifier.PRIVATE); m = c.getDeclaredMethod("m1"); assertEquals(0, m.getModifiers() & Modifier.PUBLIC); assertEquals(Modifier.PRIVATE, m.getModifiers() & Modifier.PRIVATE); m = c.getDeclaredMethod("m2"); assertEquals(Modifier.PUBLIC, m.getModifiers() & Modifier.PUBLIC); assertEquals(0, m.getModifiers() & Modifier.PRIVATE); }
public void testExecutingConstructor() throws Exception { ClassLoader l = new L(); Class<?> c = l.loadClass(CAPI.class.getName()); Member m = c.getDeclaredConstructor(int.class); Constructor ctor = (Constructor)m; ctor.setAccessible(true); Object o = ctor.newInstance(5); assertSame(c, o.getClass()); assertTrue("Invalid API superclass", Superclazz.class.isInstance(o)); assertEquals("@ConstructorDelegate method did not execute", 5, ((Superclazz)o).val); Field f = o.getClass().getField("otherVal"); Object v = f.get(o); assertEquals("Patched API constructor did not execute", v, 1); }
private static boolean typesMatch (Member function, Class<?>[] formals, Object[] actuals) { if ((actuals.length == formals.length) || (actuals.length >= formals.length && isVarArgs(function))) { int idx = 0; // check each parameter individually for (; idx < formals.length - 1; idx++) { if (!isInstance(formals[idx], actuals[idx])) { return false; } } // check each of the last actual args to see if they can be one of varargs Class<?> type = (formals[idx].isArray()) ? formals[idx].getComponentType() : formals[idx]; for (; idx < actuals.length; idx++) { if (!isInstance(type, actuals[idx])) { return false; } } // it was possible, and nothing else returned false, so return true; } // sizes don't match return false; }
/** * Returns the resolved generic parameter types of {@code methodOrConstructor}. * * @param methodOrConstructor a method or constructor defined by this or any supertype. * @since 2.0 */ public List<TypeLiteral<?>> getParameterTypes(Member methodOrConstructor) { Type[] genericParameterTypes; if (methodOrConstructor instanceof Method) { Method method = (Method) methodOrConstructor; if (!method.getDeclaringClass().isAssignableFrom(rawType)) { throw new IllegalArgumentException(method + " is not defined by a supertype of " + type); } genericParameterTypes = method.getGenericParameterTypes(); } else if (methodOrConstructor instanceof Constructor) { Constructor constructor = (Constructor) methodOrConstructor; if (!constructor.getDeclaringClass().isAssignableFrom(rawType)) { throw new IllegalArgumentException(constructor + " does not construct a supertype of " + type); } genericParameterTypes = constructor.getGenericParameterTypes(); } else { throw new IllegalArgumentException("Not a method or a constructor: " + methodOrConstructor); } return resolveAll(genericParameterTypes); }
Member getReadMember(Class targetClass) throws NameNotFoundException { // mapping: public field (same name), method (getAttribute()), // method (attribute()) List key = new ArrayList(); key.add(targetClass); key.add(_name); Member m = (Member) _cache.get(key); if (m != null) return m; m = getReadField(targetClass); if (m == null) m = getReadMethod(targetClass); if (m != null) _cache.putIfAbsent(key, m); else throw new NameNotFoundException( LocalizedStrings.AttributeDescriptor_NO_PUBLIC_ATTRIBUTE_NAMED_0_WAS_FOUND_IN_CLASS_1 .toLocalizedString(new Object[] {_name, targetClass.getName()})); // override security for nonpublic derived classes with public members ((AccessibleObject) m).setAccessible(true); return m; }
static MethodSignature[] removePrivateAndSort(Member[] m) { int numNonPrivate = 0; for (int i = 0; i < m.length; i++) { if (! Modifier.isPrivate(m[i].getModifiers())) { numNonPrivate++; } } MethodSignature[] cm = new MethodSignature[numNonPrivate]; int cmi = 0; for (int i = 0; i < m.length; i++) { if (! Modifier.isPrivate(m[i].getModifiers())) { cm[cmi] = new MethodSignature(m[i]); cmi++; } } if (cmi > 0) Arrays.sort(cm, cm[0]); return cm; }
private List<Dependency<?>> forMember(Member member, TypeLiteral<?> type, Annotation[][] parameterAnnotations) { Errors errors = new Errors(member); Iterator<Annotation[]> annotationsIterator = Arrays.asList(parameterAnnotations).iterator(); List<Dependency<?>> dependencies = new ArrayList<>(); int index = 0; for (TypeLiteral<?> parameterType : type.getParameterTypes(member)) { try { Annotation[] paramAnnotations = annotationsIterator.next(); Key<?> key = Annotations.getKey(parameterType, member, paramAnnotations, errors); dependencies.add(newDependency(key, Nullability.allowsNull(paramAnnotations), index)); index++; } catch (ErrorsException e) { errors.merge(e.getErrors()); } } errors.throwConfigurationExceptionIfErrorsExist(); return Collections.unmodifiableList(dependencies); }
/** * Returns a FastClass proxy for invoking the given member or {@code null} if access rules * disallow it. * * <p>FastClass works by generating a type in the same package as the target {@code type}. This * may or may not work depending on the access level of the class/member. It breaks down into the * following cases depending on accessibility: * <ul> * <li>Public: This always works since we can generate the type into the * {@link BridgeClassLoader} which ensures there are no versioning issues. * <li>Package private and Protected: This works as long as: * <ul> * <li>We can generate into the same classloader as the type. This is not possible for JDK * types which use the 'bootstrap' loader. * <li>The classloader of the type has the same version of {@code FastClass} as we do. This * may be violated when running in OSGI bundles. * </ul> * <li>Private: This never works. * </ul> * * If we are unable to generate the type, then we return null and callers should work around by * using normal java reflection. */ public static net.sf.cglib.reflect.FastClass newFastClassForMember(Class<?> type, Member member) { if (!new net.sf.cglib.core.VisibilityPredicate(type, false).evaluate(member)) { // the member cannot be indexed by fast class. Bail out. return null; } boolean publiclyCallable = isPubliclyCallable(member); if (!publiclyCallable && !hasSameVersionOfCglib(type.getClassLoader())) { // The type is in a classloader with a different version of cglib and is not publicly visible // (so we can't use the bridge classloader to work around). Bail out. return null; } net.sf.cglib.reflect.FastClass.Generator generator = new net.sf.cglib.reflect.FastClass.Generator(); if (publiclyCallable) { // Use the bridge classloader if we can generator.setClassLoader(getClassLoader(type)); } generator.setType(type); generator.setNamingPolicy(FASTCLASS_NAMING_POLICY); if (logger.isLoggable(Level.FINE)) { logger.fine("Loading " + type + " FastClass with " + generator.getClassLoader()); } return generator.create(); }
private static <M extends Member & AnnotatedElement> void addInjectorsForMembers( TypeLiteral<?> typeLiteral, Factory<M> factory, boolean statics, Collection<InjectionPoint> injectionPoints, Errors errors) { for (M member : factory.getMembers(getRawType(typeLiteral.getType()))) { if (isStatic(member) != statics) { continue; } Inject inject = member.getAnnotation(Inject.class); if (inject == null) { continue; } try { injectionPoints.add(factory.create(typeLiteral, member, errors)); } catch (ConfigurationException ignorable) { if (!inject.optional()) { errors.merge(ignorable.getErrorMessages()); } } } }
public static void formatInjectionPoint(Formatter formatter, Dependency<?> dependency, InjectionPoint injectionPoint) { Member member = injectionPoint.getMember(); Class<? extends Member> memberType = MoreTypes.memberType(member); if (memberType == Field.class) { dependency = injectionPoint.getDependencies().get(0); formatter.format(" while locating %s%n", convert(dependency.getKey())); formatter.format(" for field at %s%n", StackTraceElements.forMember(member)); } else if (dependency != null) { formatter.format(" while locating %s%n", convert(dependency.getKey())); formatter.format(" for parameter %s at %s%n", dependency.getParameterIndex(), StackTraceElements.forMember(member)); } else { formatSource(formatter, injectionPoint.getMember()); } }
/** * Returns the member that the given node index represents on the given class. * * @param index the node index (inclusive) * @param c the class that have this node * @param args the arguments that will be used to access this node. * @return the member * @see #getMemberOf(int) * @see #getMemberOf(int, Map) * @see #getMemberOf(int, Class) * @see #getLastMember(Class, Map) * @see #needArguments() * @throws IndexOutOfBoundsException if the index is invalid * @throws IllegalArgumentException if the static path expression not support the given root obj */ public Member getMemberOf(int index, Class<?> c, Map<String, Object> args) { checkIfSupport(c, true); checkRange("Index", index, false); Member member = null; int i = 0; for (ExpressionNode node : NODES) { member = node.getMember(c, args); if (i == index) { return member; } if (i < LAST_INDEX) { c = getMemberType(member); while (c.isArray()) { c = c.getComponentType(); } } i++; } return member; }
/** * Does a conservative approximation of member access check. Use this if * you don't have an actual 'userland' caller Class/ClassLoader available. * This might be more restrictive than a precise member access check where * you have a caller, but should never allow a member access that is * forbidden. * * @param m the {@code Member} about to be accessed */ public static void conservativeCheckMemberAccess(Member m) throws SecurityException{ final SecurityManager sm = System.getSecurityManager(); if (sm == null) return; // Check for package access on the declaring class. // // In addition, unless the member and the declaring class are both // public check for access declared member permissions. // // This is done regardless of ClassLoader relations between the {@code // Member m} and any potential caller. final Class<?> declaringClass = m.getDeclaringClass(); checkPackageAccess(declaringClass); if (Modifier.isPublic(m.getModifiers()) && Modifier.isPublic(declaringClass.getModifiers())) return; // Check for declared member access. sm.checkPermission(SecurityConstants.CHECK_MEMBER_ACCESS_PERMISSION); }
static boolean setAccessibleWorkaround(final AccessibleObject o) { if (o == null || o.isAccessible()) { return false; } final Member m = (Member) o; if (!o.isAccessible() && Modifier.isPublic(m.getModifiers()) && isPackageAccess(m .getDeclaringClass().getModifiers())) { try { o.setAccessible(true); return true; } catch (final SecurityException e) { // NOPMD // ignore in favor of subsequent IllegalAccessException } } return false; }
/** * Returns true if the the given member is a method that overrides {@link Object#equals(Object)}. * * <p>The documentation for {@link Object#equals} says it should accept null, so don't require an * explicit {@code @Nullable} annotation (see <a * href="https://github.com/google/guava/issues/1819">#1819</a>). * * <p>It is not necessary to consider visibility, return type, or type parameter declarations. The * declaration of a method with the same name and formal parameters as {@link Object#equals} that * is not public and boolean-returning, or that declares any type parameters, would be rejected at * compile-time. */ private static boolean isEquals(Member member) { if (!(member instanceof Method)) { return false; } Method method = (Method) member; if (!method.getName().contentEquals("equals")) { return false; } Class<?>[] parameters = method.getParameterTypes(); if (parameters.length != 1) { return false; } if (!parameters[0].equals(Object.class)) { return false; } return true; }
public static <T extends AccessibleObject> T a(T t) { if (t == null) { return null; } if (t instanceof Member) { Member member = (Member) t; if (Modifier.isPublic(member.getModifiers()) && Modifier.isPublic(member .getDeclaringClass().getModifiers())) { return t; } } if (t.isAccessible()) { return t; } t.setAccessible(true); return t; }
boolean isAccessible(final Member m) { final Class<?> declaring = m.getDeclaringClass(); // (declaring == clazz) is just an optimization - we're calling this only from code that operates on a // non-restricted class, so if the declaring class is identical to the class being inspected, then forego // a potentially expensive restricted-package check. return declaring == clazz || !CheckRestrictedPackage.isRestrictedClass(declaring); }
public static void hook(final Member origin, final Method replace) { warnKnownIssue(origin.getDeclaringClass(), replace); final int slot = AndHook.backup(origin); if (slot != -1 && saveBackupSlot(slot, replace)) { AndHook.hook(origin, replace, slot); } }
/** * Returns an array containing {@code Class} objects representing all * the public classes and interfaces that are members of the class * represented by this {@code Class} object. This includes public * class and interface members inherited from superclasses and public class * and interface members declared by the class. This method returns an * array of length 0 if this {@code Class} object has no public member * classes or interfaces. This method also returns an array of length 0 if * this {@code Class} object represents a primitive type, an array * class, or void. * * @return the array of {@code Class} objects representing the public * members of this class * @throws SecurityException * If a security manager, <i>s</i>, is present and * the caller's class loader is not the same as or an * ancestor of the class loader for the current class and * invocation of {@link SecurityManager#checkPackageAccess * s.checkPackageAccess()} denies access to the package * of this class. * * @since 1.1 */ @CallerSensitive public Class<?>[] getClasses() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { checkMemberAccess(sm, Member.PUBLIC, Reflection.getCallerClass(), false); } // Privileged so this implementation can look at DECLARED classes, // something the caller might not have privilege to do. The code here // is allowed to look at DECLARED classes because (1) it does not hand // out anything other than public members and (2) public member access // has already been ok'd by the SecurityManager. return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<>() { public Class<?>[] run() { List<Class<?>> list = new ArrayList<>(); Class<?> currentClass = Class.this; while (currentClass != null) { for (Class<?> m : currentClass.getDeclaredClasses()) { if (Modifier.isPublic(m.getModifiers())) { list.add(m); } } currentClass = currentClass.getSuperclass(); } return list.toArray(new Class<?>[0]); } }); }
private static <M extends Member> Matcher<M> nameMatches(final Matcher<String> nameMatcher) { return new TypeSafeMatcher<M>() { @Override public void describeTo(Description description) { description.appendText("name ").appendDescriptionOf(nameMatcher); } @Override protected boolean matchesSafely(M item) { return nameMatcher.matches(item.getName()); } }; }
private Constructor<T> getConstructor0(Class<?>[] parameterTypes, int which) throws NoSuchMethodException { Constructor<T>[] constructors = privateGetDeclaredConstructors((which == Member.PUBLIC)); for (Constructor<T> constructor : constructors) { if (arrayContentsEq(parameterTypes, constructor.getParameterTypes())) { return getReflectionFactory().copyConstructor(constructor); } } throw new NoSuchMethodException(getName() + ".<init>" + argumentTypesToString(parameterTypes)); }
/** * Returns an array containing {@code Class} objects representing all * the public classes and interfaces that are members of the class * represented by this {@code Class} object. This includes public * class and interface members inherited from superclasses and public class * and interface members declared by the class. This method returns an * array of length 0 if this {@code Class} object has no public member * classes or interfaces. This method also returns an array of length 0 if * this {@code Class} object represents a primitive type, an array * class, or void. * * @return the array of {@code Class} objects representing the public * members of this class * @throws SecurityException * If a security manager, <i>s</i>, is present and * the caller's class loader is not the same as or an * ancestor of the class loader for the current class and * invocation of {@link SecurityManager#checkPackageAccess * s.checkPackageAccess()} denies access to the package * of this class. * * @since JDK1.1 */ @CallerSensitive public Class<?>[] getClasses() { checkMemberAccess(Member.PUBLIC, Reflection.getCallerClass(), false); // Privileged so this implementation can look at DECLARED classes, // something the caller might not have privilege to do. The code here // is allowed to look at DECLARED classes because (1) it does not hand // out anything other than public members and (2) public member access // has already been ok'd by the SecurityManager. return java.security.AccessController.doPrivileged( new java.security.PrivilegedAction<Class<?>[]>() { public Class<?>[] run() { List<Class<?>> list = new ArrayList<>(); Class<?> currentClass = Class.this; while (currentClass != null) { Class<?>[] members = currentClass.getDeclaredClasses(); for (int i = 0; i < members.length; i++) { if (Modifier.isPublic(members[i].getModifiers())) { list.add(members[i]); } } currentClass = currentClass.getSuperclass(); } return list.toArray(new Class<?>[0]); } }); }
/** * Hook all constructors of the specified class. * * @param hookClass The class to check for constructors. * @param callback The callback to be executed when the hooked constructors are called. * @return A set containing one object for each found constructor which can be used to unhook it. */ @SuppressWarnings("all") public static HashSet<XC_MethodHook.Unhook> hookAllConstructors(final Class<?> hookClass, final XC_MethodHook callback) { final HashSet<XC_MethodHook.Unhook> unhooks = new HashSet<>(); for (final Member constructor : hookClass.getDeclaredConstructors()) unhooks.add(hookMethod(constructor, callback)); return unhooks; }
@Test public void testLastMember() throws Exception { Field expectedMember = wrap(Address.class).getField("country"); PathExpression pathExpression = compile(Person.class, "addresses.country"); Member lastMember = pathExpression.getLastMember(); assertEquals(expectedMember, lastMember); }
/** * Hooks all methods with a certain name that were declared in the specified class. Inherited * methods and constructors are not considered. For constructors, use * {@link #hookAllConstructors} instead. * * @param hookClass The class to check for declared methods. * @param methodName The name of the method(s) to hook. * @param callback The callback to be executed when the hooked methods are called. * @return A set containing one object for each found method which can be used to unhook it. */ @SuppressWarnings("all") public static HashSet<XC_MethodHook.Unhook> hookAllMethods(final Class<?> hookClass, final String methodName, final XC_MethodHook callback) { final HashSet<XC_MethodHook.Unhook> unhooks = new HashSet<>(); for (final Member method : hookClass.getDeclaredMethods()) if (method.getName().equals(methodName)) unhooks.add(hookMethod(method, callback)); return unhooks; }
private static MethodType getMethodType(final AccessibleObject ao) { final boolean isMethod = ao instanceof Method; final Class<?> rtype = isMethod ? ((Method)ao).getReturnType() : ((Constructor<?>)ao).getDeclaringClass(); final Class<?>[] ptypes = isMethod ? ((Method)ao).getParameterTypes() : ((Constructor<?>)ao).getParameterTypes(); final MethodType type = MethodType.methodType(rtype, ptypes); final Member m = (Member)ao; return type.insertParameterTypes(0, isMethod ? Modifier.isStatic(m.getModifiers()) ? Object.class : m.getDeclaringClass() : StaticClass.class); }
private static <T extends Member & AnnotatedElement> String getExpectedNameOf(T member, String name) { String base = member.getDeclaringClass().getName() + "." + name; if (member instanceof Method) { return base + expectedParametersOf(((Method) member).getParameterTypes()); } if (member instanceof Constructor<?>) { return base + expectedParametersOf(((Constructor<?>) member).getParameterTypes()); } return base; }
public static void formatSource(Formatter formatter, Object source) { if (source instanceof Dependency) { Dependency<?> dependency = (Dependency<?>) source; InjectionPoint injectionPoint = dependency.getInjectionPoint(); if (injectionPoint != null) { formatInjectionPoint(formatter, dependency, injectionPoint); } else { formatSource(formatter, dependency.getKey()); } } else if (source instanceof InjectionPoint) { formatInjectionPoint(formatter, null, (InjectionPoint) source); } else if (source instanceof Class) { formatter.format(" at %s%n", StackTraceElements.forType((Class<?>) source)); } else if (source instanceof Member) { formatter.format(" at %s%n", StackTraceElements.forMember((Member) source)); } else if (source instanceof TypeLiteral) { formatter.format(" while locating %s%n", source); } else if (source instanceof Key) { Key<?> key = (Key<?>) source; formatter.format(" while locating %s%n", convert(key)); } else { formatter.format(" at %s%n", source); } }
private MethodSignature(Member m) { member = m; if (isConstructor()) { signature = ObjectStreamClass.getSignature((Constructor)m); } else { signature = ObjectStreamClass.getSignature((Method)m); } }
@Override ScriptableObject getPropertyDescriptor(Context cx, Scriptable scope) { int attr = getAttributes(); ScriptableObject desc = new NativeObject(); ScriptRuntime.setBuiltinProtoAndParent(desc, scope, TopLevel.Builtins.Object); desc.defineProperty("enumerable", (attr & DONTENUM) == 0, EMPTY); desc.defineProperty("configurable", (attr & PERMANENT) == 0, EMPTY); if (getter == null && setter == null) { desc.defineProperty("writable", (attr & READONLY) == 0, EMPTY); } if (getter != null) { if( getter instanceof MemberBox ) { desc.defineProperty("get", new FunctionObject("f", ((MemberBox)getter).member(),scope), EMPTY); } else if( getter instanceof Member ) { desc.defineProperty("get", new FunctionObject("f",(Member)getter,scope), EMPTY); } else { desc.defineProperty("get", getter, EMPTY); } } if (setter != null) { if( setter instanceof MemberBox ) { desc.defineProperty("set", new FunctionObject("f", ((MemberBox)setter).member(),scope), EMPTY); } else if( setter instanceof Member ) { desc.defineProperty("set", new FunctionObject("f",(Member)setter,scope), EMPTY); } else { desc.defineProperty("set", setter, EMPTY); } } return desc; }
private static Member findAnnotatedMember(AccessibleObject[] members, Class<? extends Annotation> annotation) { for (AccessibleObject member : members) { if (member.isAnnotationPresent(annotation)) { return (Member) member; } } return null; }
/** * @param first a Member * @param second a Member * @return true if the first Member is more specific than the second, * false otherwise. Specificity is determined according to the * procedure in the Java Language Specification, section 15.12.2. */ private boolean memberIsMoreSpecific( Member first, Member second ) { Class<?>[] firstParamTypes = paramMap.get(first); Class<?>[] secondParamTypes = paramMap.get(second); return ClassUtilities.compatibleClasses(firstParamTypes, secondParamTypes, customMatchingRules); }
public static void setAccessible( Field f ) { try { f.setAccessible( true ); } catch( Exception e ) { setAccessible( (Member)f ); } }
public static String multilineDescription(Class<?> cls) { final String text = cls.getName(); final Member member = enclosingMember(cls); if(member != null) { return text + "\n in " + multilineDescription(member); } final Class<?> outer = cls.getEnclosingClass(); if(outer != null) { return text + "\n in " + multilineDescription(outer); } return text; }
@Override protected String[] get(Event e) { return Arrays.stream(target.getArray(e)) .map(Util::toClass) .flatMap(mapper) .map(Member::getName) .distinct() .toArray(String[]::new); }