001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.reflect; 018 019import static org.apache.juneau.commons.utils.Utils.*; 020import static org.apache.juneau.commons.utils.AssertionUtils.*; 021 022import java.lang.reflect.*; 023 024/** 025 * Abstract base class for reflection info classes that wrap {@link AccessibleObject}. 026 * 027 * <p> 028 * This class extends {@link ElementInfo} to provide common functionality for reflection elements that can be made 029 * accessible (fields, methods, and constructors). It mirrors the {@link AccessibleObject} API, allowing private 030 * members to be accessed via reflection. 031 * 032 * <h5 class='section'>Features:</h5> 033 * <ul class='spaced-list'> 034 * <li>Accessibility control - make private members accessible 035 * <li>Security exception handling - gracefully handles security exceptions 036 * <li>Accessibility checking - check if an element is accessible 037 * <li>Fluent API - methods return <c>this</c> for method chaining 038 * </ul> 039 * 040 * <h5 class='section'>Use Cases:</h5> 041 * <ul class='spaced-list'> 042 * <li>Accessing private fields, methods, or constructors 043 * <li>Building frameworks that need to work with non-public members 044 * <li>Testing scenarios where private members need to be accessed 045 * </ul> 046 * 047 * <h5 class='section'>Usage:</h5> 048 * <p class='bjava'> 049 * <jc>// Make accessible</jc> 050 * AccessibleInfo <jv>ai</jv> = ...; 051 * <jv>ai</jv>.setAccessible(); <jc>// Makes private member accessible</jc> 052 * 053 * <jc>// Check accessibility</jc> 054 * <jk>if</jk> (! <jv>ai</jv>.isAccessible()) { 055 * <jv>ai</jv>.setAccessible(); 056 * } 057 * 058 * <jc>// Fluent API</jc> 059 * <jv>ai</jv>.accessible(); <jc>// Returns this after making accessible</jc> 060 * </p> 061 * 062 * <h5 class='section'>Security:</h5> 063 * <p> 064 * The {@link #setAccessible()} method attempts to make the element accessible and quietly ignores 065 * {@link SecurityException} if the security manager denies access. This allows code to work in 066 * both secure and non-secure environments. 067 * 068 * <h5 class='section'>See Also:</h5><ul> 069 * <li class='jc'>{@link ElementInfo} - Base class for all reflection elements 070 * <li class='jc'>{@link FieldInfo} - Field introspection 071 * <li class='jc'>{@link MethodInfo} - Method introspection 072 * <li class='jc'>{@link ConstructorInfo} - Constructor introspection 073 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsReflection">Reflection Package</a> 074 * </ul> 075 */ 076public abstract class AccessibleInfo extends ElementInfo { 077 078 private final AccessibleObject inner; 079 080 /** 081 * Constructor. 082 * 083 * @param inner The {@link AccessibleObject} being wrapped. 084 */ 085 protected AccessibleInfo(AccessibleObject inner, int modifiers) { 086 super(modifiers); 087 this.inner = assertArgNotNull("inner", inner); 088 } 089 090 //----------------------------------------------------------------------------------------------------------------- 091 // Accessibility 092 //----------------------------------------------------------------------------------------------------------------- 093 094 /** 095 * Returns <jk>true</jk> if this object is accessible. 096 * 097 * <p> 098 * This method was added in Java 9. For earlier versions, this always returns <jk>false</jk>. 099 * 100 * <h5 class='section'>Example:</h5> 101 * <p class='bjava'> 102 * <jc>// Check if accessible without security checks</jc> 103 * <jk>if</jk> (!accessibleInfo.isAccessible()) { 104 * accessibleInfo.setAccessible(); 105 * } 106 * </p> 107 * 108 * @return <jk>true</jk> if this object is accessible, <jk>false</jk> otherwise or if not supported. 109 */ 110 public boolean isAccessible() { 111 return safeOpt(() -> (boolean)AccessibleObject.class.getMethod("isAccessible").invoke(inner)).orElse(false); 112 } 113 114 /** 115 * Attempts to call <code>x.setAccessible(<jk>true</jk>)</code> and quietly ignores security exceptions. 116 * 117 * @return <jk>true</jk> if call was successful. 118 */ 119 public boolean setAccessible() { 120 return safeOpt(() -> { inner.setAccessible(true); return true;}).orElse(false); 121 } 122}