• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 &sect;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