1 package com.google.gson; 2 3 import com.google.gson.internal.ReflectionAccessFilterHelper; 4 import java.lang.reflect.AccessibleObject; 5 6 /** 7 * Filter for determining whether reflection based serialization and 8 * deserialization is allowed for a class. 9 * 10 * <p>A filter can be useful in multiple scenarios, for example when 11 * upgrading to newer Java versions which use the Java Platform Module 12 * System (JPMS). A filter then allows to {@linkplain FilterResult#BLOCK_INACCESSIBLE 13 * prevent making inaccessible members accessible}, even if the used 14 * Java version might still allow illegal access (but logs a warning), 15 * or if {@code java} command line arguments are used to open the inaccessible 16 * packages to other parts of the application. This interface defines some 17 * convenience filters for this task, such as {@link #BLOCK_INACCESSIBLE_JAVA}. 18 * 19 * <p>A filter can also be useful to prevent mixing model classes of a 20 * project with other non-model classes; the filter could 21 * {@linkplain FilterResult#BLOCK_ALL block all reflective access} to 22 * non-model classes. 23 * 24 * <p>A reflection access filter is similar to an {@link ExclusionStrategy} 25 * with the major difference that a filter will cause an exception to be 26 * thrown when access is disallowed while an exclusion strategy just skips 27 * fields and classes. 28 * 29 * @see GsonBuilder#addReflectionAccessFilter(ReflectionAccessFilter) 30 * @since 2.9.1 31 */ 32 public interface ReflectionAccessFilter { 33 /** 34 * Result of a filter check. 35 * 36 * @since 2.9.1 37 */ 38 enum FilterResult { 39 /** 40 * Reflection access for the class is allowed. 41 * 42 * <p>Note that this does not affect the Java access checks in any way, 43 * it only permits Gson to try using reflection for a class. The Java 44 * runtime might still deny such access. 45 */ 46 ALLOW, 47 /** 48 * The filter is indecisive whether reflection access should be allowed. 49 * The next registered filter will be consulted to get the result. If 50 * there is no next filter, this result acts like {@link #ALLOW}. 51 */ 52 INDECISIVE, 53 /** 54 * Blocks reflection access if a member of the class is not accessible 55 * by default and would have to be made accessible. This is unaffected 56 * by any {@code java} command line arguments being used to make packages 57 * accessible, or by module declaration directives which <i>open</i> the 58 * complete module or certain packages for reflection and will consider 59 * such packages inaccessible. 60 * 61 * <p>Note that this <b>only works for Java 9 and higher</b>, for older 62 * Java versions its functionality will be limited and it might behave like 63 * {@link #ALLOW}. Access checks are only performed as defined by the Java 64 * Language Specification (<a href="https://docs.oracle.com/javase/specs/jls/se11/html/jls-6.html#jls-6.6">JLS 11 §6.6</a>), 65 * restrictions imposed by a {@link SecurityManager} are not considered. 66 * 67 * <p>This result type is mainly intended to help enforce the access checks of 68 * the Java Platform Module System. It allows detecting illegal access, even if 69 * the used Java version would only log a warning, or is configured to open 70 * packages for reflection using command line arguments. 71 * 72 * @see AccessibleObject#canAccess(Object) 73 */ 74 BLOCK_INACCESSIBLE, 75 /** 76 * Blocks all reflection access for the class. Other means for serializing 77 * and deserializing the class, such as a {@link TypeAdapter}, have to 78 * be used. 79 */ 80 BLOCK_ALL 81 } 82 83 /** 84 * Blocks all reflection access to members of standard Java classes which are 85 * not accessible by default. However, reflection access is still allowed for 86 * classes for which all fields are accessible and which have an accessible 87 * no-args constructor (or for which an {@link InstanceCreator} has been registered). 88 * 89 * <p>If this filter encounters a class other than a standard Java class it 90 * returns {@link FilterResult#INDECISIVE}. 91 * 92 * <p>This filter is mainly intended to help enforcing the access checks of 93 * Java Platform Module System. It allows detecting illegal access, even if 94 * the used Java version would only log a warning, or is configured to open 95 * packages for reflection. However, this filter <b>only works for Java 9 and 96 * higher</b>, when using an older Java version its functionality will be 97 * limited. 98 * 99 * <p>Note that this filter might not cover all standard Java classes. Currently 100 * only classes in a {@code java.*} or {@code javax.*} package are considered. The 101 * set of detected classes might be expanded in the future without prior notice. 102 * 103 * @see FilterResult#BLOCK_INACCESSIBLE 104 */ 105 ReflectionAccessFilter BLOCK_INACCESSIBLE_JAVA = new ReflectionAccessFilter() { 106 @Override public FilterResult check(Class<?> rawClass) { 107 return ReflectionAccessFilterHelper.isJavaType(rawClass) 108 ? FilterResult.BLOCK_INACCESSIBLE 109 : FilterResult.INDECISIVE; 110 } 111 }; 112 113 /** 114 * Blocks all reflection access to members of standard Java classes. 115 * 116 * <p>If this filter encounters a class other than a standard Java class it 117 * returns {@link FilterResult#INDECISIVE}. 118 * 119 * <p>This filter is mainly intended to prevent depending on implementation 120 * details of the Java platform and to help applications prepare for upgrading 121 * to the Java Platform Module System. 122 * 123 * <p>Note that this filter might not cover all standard Java classes. Currently 124 * only classes in a {@code java.*} or {@code javax.*} package are considered. The 125 * set of detected classes might be expanded in the future without prior notice. 126 * 127 * @see #BLOCK_INACCESSIBLE_JAVA 128 * @see FilterResult#BLOCK_ALL 129 */ 130 ReflectionAccessFilter BLOCK_ALL_JAVA = new ReflectionAccessFilter() { 131 @Override public FilterResult check(Class<?> rawClass) { 132 return ReflectionAccessFilterHelper.isJavaType(rawClass) 133 ? FilterResult.BLOCK_ALL 134 : FilterResult.INDECISIVE; 135 } 136 }; 137 138 /** 139 * Blocks all reflection access to members of standard Android classes. 140 * 141 * <p>If this filter encounters a class other than a standard Android class it 142 * returns {@link FilterResult#INDECISIVE}. 143 * 144 * <p>This filter is mainly intended to prevent depending on implementation 145 * details of the Android platform. 146 * 147 * <p>Note that this filter might not cover all standard Android classes. Currently 148 * only classes in an {@code android.*} or {@code androidx.*} package, and standard 149 * Java classes in a {@code java.*} or {@code javax.*} package are considered. The 150 * set of detected classes might be expanded in the future without prior notice. 151 * 152 * @see FilterResult#BLOCK_ALL 153 */ 154 ReflectionAccessFilter BLOCK_ALL_ANDROID = new ReflectionAccessFilter() { 155 @Override public FilterResult check(Class<?> rawClass) { 156 return ReflectionAccessFilterHelper.isAndroidType(rawClass) 157 ? FilterResult.BLOCK_ALL 158 : FilterResult.INDECISIVE; 159 } 160 }; 161 162 /** 163 * Blocks all reflection access to members of classes belonging to programming 164 * language platforms, such as Java, Android, Kotlin or Scala. 165 * 166 * <p>If this filter encounters a class other than a standard platform class it 167 * returns {@link FilterResult#INDECISIVE}. 168 * 169 * <p>This filter is mainly intended to prevent depending on implementation 170 * details of the platform classes. 171 * 172 * <p>Note that this filter might not cover all platform classes. Currently it 173 * combines the filters {@link #BLOCK_ALL_JAVA} and {@link #BLOCK_ALL_ANDROID}, 174 * and checks for other language-specific platform classes like {@code kotlin.*}. 175 * The set of detected classes might be expanded in the future without prior notice. 176 * 177 * @see FilterResult#BLOCK_ALL 178 */ 179 ReflectionAccessFilter BLOCK_ALL_PLATFORM = new ReflectionAccessFilter() { 180 @Override public FilterResult check(Class<?> rawClass) { 181 return ReflectionAccessFilterHelper.isAnyPlatformType(rawClass) 182 ? FilterResult.BLOCK_ALL 183 : FilterResult.INDECISIVE; 184 } 185 }; 186 187 /** 188 * Checks if reflection access should be allowed for a class. 189 * 190 * @param rawClass 191 * Class to check 192 * @return 193 * Result indicating whether reflection access is allowed 194 */ check(Class<?> rawClass)195 FilterResult check(Class<?> rawClass); 196 } 197