View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.juneau.commons.reflect;
18  
19  import static org.apache.juneau.commons.utils.Utils.*;
20  import static org.apache.juneau.commons.utils.AssertionUtils.*;
21  
22  import java.lang.reflect.*;
23  
24  /**
25   * Abstract base class for reflection info classes that wrap {@link AccessibleObject}.
26   *
27   * <p>
28   * This class extends {@link ElementInfo} to provide common functionality for reflection elements that can be made
29   * accessible (fields, methods, and constructors). It mirrors the {@link AccessibleObject} API, allowing private
30   * members to be accessed via reflection.
31   *
32   * <h5 class='section'>Features:</h5>
33   * <ul class='spaced-list'>
34   * 	<li>Accessibility control - make private members accessible
35   * 	<li>Security exception handling - gracefully handles security exceptions
36   * 	<li>Accessibility checking - check if an element is accessible
37   * 	<li>Fluent API - methods return <c>this</c> for method chaining
38   * </ul>
39   *
40   * <h5 class='section'>Use Cases:</h5>
41   * <ul class='spaced-list'>
42   * 	<li>Accessing private fields, methods, or constructors
43   * 	<li>Building frameworks that need to work with non-public members
44   * 	<li>Testing scenarios where private members need to be accessed
45   * </ul>
46   *
47   * <h5 class='section'>Usage:</h5>
48   * <p class='bjava'>
49   * 	<jc>// Make accessible</jc>
50   * 	AccessibleInfo <jv>ai</jv> = ...;
51   * 	<jv>ai</jv>.setAccessible();  <jc>// Makes private member accessible</jc>
52   *
53   * 	<jc>// Check accessibility</jc>
54   * 	<jk>if</jk> (! <jv>ai</jv>.isAccessible()) {
55   * 		<jv>ai</jv>.setAccessible();
56   * 	}
57   *
58   * 	<jc>// Fluent API</jc>
59   * 	<jv>ai</jv>.accessible();  <jc>// Returns this after making accessible</jc>
60   * </p>
61   *
62   * <h5 class='section'>Security:</h5>
63   * <p>
64   * The {@link #setAccessible()} method attempts to make the element accessible and quietly ignores
65   * {@link SecurityException} if the security manager denies access. This allows code to work in
66   * both secure and non-secure environments.
67   *
68   * <h5 class='section'>See Also:</h5><ul>
69   * 	<li class='jc'>{@link ElementInfo} - Base class for all reflection elements
70   * 	<li class='jc'>{@link FieldInfo} - Field introspection
71   * 	<li class='jc'>{@link MethodInfo} - Method introspection
72   * 	<li class='jc'>{@link ConstructorInfo} - Constructor introspection
73   * 	<li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauCommonsReflection">Reflection Package</a>
74   * </ul>
75   */
76  public abstract class AccessibleInfo extends ElementInfo {
77  
78  	private final AccessibleObject inner;
79  
80  	/**
81  	 * Constructor.
82  	 *
83  	 * @param inner The {@link AccessibleObject} being wrapped.
84  	 */
85  	protected AccessibleInfo(AccessibleObject inner, int modifiers) {
86  		super(modifiers);
87  		this.inner = assertArgNotNull("inner", inner);
88  	}
89  
90  	//-----------------------------------------------------------------------------------------------------------------
91  	// Accessibility
92  	//-----------------------------------------------------------------------------------------------------------------
93  
94  	/**
95  	 * Returns <jk>true</jk> if this object is accessible.
96  	 *
97  	 * <p>
98  	 * This method was added in Java 9. For earlier versions, this always returns <jk>false</jk>.
99  	 *
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 }