93 import jdk.internal.dynalink.linker.LinkRequest; |
93 import jdk.internal.dynalink.linker.LinkRequest; |
94 import jdk.internal.dynalink.linker.LinkerServices; |
94 import jdk.internal.dynalink.linker.LinkerServices; |
95 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; |
95 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker; |
96 |
96 |
97 /** |
97 /** |
98 * A linker for POJOs. Normally used as the ultimate fallback linker by the {@link DynamicLinkerFactory} so it is given |
98 * A linker for ordinary Java objects. Normally used as the ultimate fallback |
99 * the chance to link calls to all objects that no other language runtime recognizes. Specifically, this linker will: |
99 * linker by the {@link DynamicLinkerFactory} so it is given the chance to link |
|
100 * calls to all objects that no other linker recognized. Specifically, this |
|
101 * linker will: |
100 * <ul> |
102 * <ul> |
101 * <li>expose all public methods of form {@code setXxx()}, {@code getXxx()}, and {@code isXxx()} as property setters and |
103 * <li>expose all public methods of form {@code setXxx()}, {@code getXxx()}, |
102 * getters for {@code dyn:setProp} and {@code dyn:getProp} operations;</li> |
104 * and {@code isXxx()} as property setters and getters for {@code dyn:setProp} |
103 * <li>expose all public methods for invocation through {@code dyn:callMethod} operation;</li> |
105 * and {@code dyn:getProp} operations;</li> |
104 * <li>expose all public methods for retrieval for {@code dyn:getMethod} operation; the methods thus retrieved can then |
106 * <li>expose all public methods for invocation through {@code dyn:callMethod} |
105 * be invoked using {@code dyn:call};</li> |
107 * operation;</li> |
106 * <li>expose all public fields as properties, unless there are getters or setters for the properties of the same name;</li> |
108 * <li>expose all public methods for retrieval for {@code dyn:getMethod} |
107 * <li>expose {@code dyn:getLength}, {@code dyn:getElem} and {@code dyn:setElem} on native Java arrays, as well as |
109 * operation; the methods thus retrieved can then be invoked using |
108 * {@link java.util.List} and {@link java.util.Map} objects; ({@code dyn:getLength} works on any |
110 * {@code dyn:call};</li> |
|
111 * <li>expose all public fields as properties, unless there are getters or |
|
112 * setters for the properties of the same name;</li> |
|
113 * <li>expose {@code dyn:getLength}, {@code dyn:getElem} and |
|
114 * {@code dyn:setElem} on native Java arrays, as well as {@link java.util.List} |
|
115 * and {@link java.util.Map} objects; ({@code dyn:getLength} works on any |
109 * {@link java.util.Collection});</li> |
116 * {@link java.util.Collection});</li> |
110 * <li>expose a virtual property named {@code length} on Java arrays;</li> |
117 * <li>expose a virtual property named {@code length} on Java arrays;</li> |
111 * <li>expose {@code dyn:new} on instances of {@link StaticClass} as calls to constructors, including those static class |
118 * <li>expose {@code dyn:new} on instances of {@link StaticClass} as calls to |
112 * objects that represent Java arrays (their constructors take a single {@code int} parameter representing the length of |
119 * constructors, including those static class objects that represent Java arrays |
113 * the array to create);</li> |
120 * (their constructors take a single {@code int} parameter representing the |
114 * <li>expose static methods, fields, and properties of classes in a similar manner to how instance method, fields, and |
121 * length of the array to create);</li> |
115 * properties are exposed, on {@link StaticClass} objects.</li> |
122 * <li>expose static methods, fields, and properties of classes in a similar |
116 * <li>expose a virtual property named {@code static} on instances of {@link java.lang.Class} to access their |
123 * manner to how instance method, fields, and properties are exposed, on |
117 * {@link StaticClass}.</li> |
124 * {@link StaticClass} objects.</li> |
|
125 * <li>expose a virtual property named {@code static} on instances of |
|
126 * {@link java.lang.Class} to access their {@link StaticClass}.</li> |
118 * </ul> |
127 * </ul> |
119 * <p><strong>Overloaded method resolution</strong> is performed automatically for property setters, methods, and |
128 * <p><strong>Overloaded method resolution</strong> is performed automatically |
120 * constructors. Additionally, manual overloaded method selection is supported by having a call site specify a name for |
129 * for property setters, methods, and constructors. Additionally, manual |
121 * a method that contains an explicit signature, i.e. {@code dyn:getMethod:parseInt(String,int)}. You can use |
130 * overloaded method selection is supported by having a call site specify a name |
122 * non-qualified class names in such signatures regardless of those classes' packages, they will match any class with |
131 * for a method that contains an explicit signature, i.e. |
123 * the same non-qualified name. You only have to use a fully qualified class name in case non-qualified class names |
132 * {@code dyn:getMethod:parseInt(String,int)}. You can use non-qualified class |
124 * would cause selection ambiguity (that is extremely rare).</p> |
133 * names in such signatures regardless of those classes' packages, they will |
125 * <p><strong>Variable argument invocation</strong> is handled for both methods and constructors.</p> |
134 * match any class with the same non-qualified name. You only have to use a |
126 * <p>Currently, only public fields and methods are supported. Any Lookup objects passed in the |
135 * fully qualified class name in case non-qualified class names would cause |
127 * {@link LinkRequest}s are ignored and {@link MethodHandles#publicLookup()} is used instead.</p> |
136 * selection ambiguity (that is extremely rare). Overloaded resolution for |
|
137 * constructors is not automatic as there is no logical place to attach that |
|
138 * functionality to but if a language wishes to provide this functionality, it |
|
139 * can use {@link #getConstructorMethod(Class, String)} as a useful building |
|
140 * block for it.</p> |
|
141 * <p><strong>Variable argument invocation</strong> is handled for both methods |
|
142 * and constructors.</p> |
|
143 * <p><strong>Caller sensitive methods</strong> can be linked as long as they |
|
144 * are otherwise public and link requests have call site descriptors carrying |
|
145 * full-strength {@link Lookup} objects and not weakened lookups or the public |
|
146 * lookup.</p> |
|
147 * <p>The class also exposes various static methods for discovery of available |
|
148 * property and method names on classes and class instances, as well as access |
|
149 * to per-class linkers using the {@link #getLinkerForClass(Class)} |
|
150 * method.</p> |
128 */ |
151 */ |
129 public class BeansLinker implements GuardingDynamicLinker { |
152 public class BeansLinker implements GuardingDynamicLinker { |
130 private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() { |
153 private static final ClassValue<TypeBasedGuardingDynamicLinker> linkers = new ClassValue<TypeBasedGuardingDynamicLinker>() { |
131 @Override |
154 @Override |
132 protected TypeBasedGuardingDynamicLinker computeValue(final Class<?> clazz) { |
155 protected TypeBasedGuardingDynamicLinker computeValue(final Class<?> clazz) { |
138 new BeanLinker(clazz); |
161 new BeanLinker(clazz); |
139 } |
162 } |
140 }; |
163 }; |
141 |
164 |
142 /** |
165 /** |
143 * Creates a new POJO linker. |
166 * Creates a new beans linker. |
144 */ |
167 */ |
145 public BeansLinker() { |
168 public BeansLinker() { |
146 } |
169 } |
147 |
170 |
148 /** |
171 /** |
149 * Returns a bean linker for a particular single class. Useful when you need to override or extend the behavior of |
172 * Returns a bean linker for a particular single class. Useful when you need |
150 * linking for some classes in your language runtime's linker, but still want to delegate to the default behavior in |
173 * to override or extend the behavior of linking for some classes in your |
151 * some cases. |
174 * language runtime's linker, but still want to delegate to the default |
|
175 * behavior in some cases. |
152 * @param clazz the class |
176 * @param clazz the class |
153 * @return a bean linker for that class |
177 * @return a bean linker for that class |
154 */ |
178 */ |
155 public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) { |
179 public static TypeBasedGuardingDynamicLinker getLinkerForClass(final Class<?> clazz) { |
156 return linkers.get(clazz); |
180 return linkers.get(clazz); |
157 } |
181 } |
158 |
182 |
159 /** |
183 /** |
160 * Returns true if the object is a Dynalink Java dynamic method. |
184 * Returns true if the object is a Java dynamic method (e.g., one |
|
185 * obtained through a {@code dyn:getMethod} call on a Java object or |
|
186 * {@link StaticClass} or through |
|
187 * {@link #getConstructorMethod(Class, String)}. |
161 * |
188 * |
162 * @param obj the object we want to test for being a dynamic method |
189 * @param obj the object we want to test for being a Java dynamic method. |
163 * @return true if it is a dynamic method, false otherwise. |
190 * @return true if it is a dynamic method, false otherwise. |
164 */ |
191 */ |
165 public static boolean isDynamicMethod(final Object obj) { |
192 public static boolean isDynamicMethod(final Object obj) { |
166 return obj instanceof DynamicMethod; |
193 return obj instanceof DynamicMethod; |
167 } |
194 } |
168 |
195 |
169 /** |
196 /** |
170 * Returns true if the object is a Dynalink Java constructor. |
197 * Returns true if the object is a Java constructor (obtained through |
|
198 * {@link #getConstructorMethod(Class, String)}}. |
171 * |
199 * |
172 * @param obj the object we want to test for being a constructor |
200 * @param obj the object we want to test for being a Java constructor. |
173 * @return true if it is a constructor, false otherwise. |
201 * @return true if it is a constructor, false otherwise. |
174 */ |
202 */ |
175 public static boolean isDynamicConstructor(final Object obj) { |
203 public static boolean isDynamicConstructor(final Object obj) { |
176 return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor(); |
204 return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor(); |
177 } |
205 } |
178 |
206 |
179 /** |
207 /** |
180 * Return the dynamic method of constructor of the given class and the given signature. |
208 * Return the dynamic method of constructor of the given class and the given |
|
209 * signature. This method is useful for exposing a functionality for |
|
210 * selecting an overloaded constructor based on an explicit signature, as |
|
211 * this functionality is not otherwise exposed by Dynalink as |
|
212 * {@link StaticClass} objects act as overloaded constructors without |
|
213 * explicit signature selection. |
181 * @param clazz the class |
214 * @param clazz the class |
182 * @param signature full signature of the constructor |
215 * @param signature full signature of the constructor |
183 * @return DynamicMethod for the constructor |
216 * @return dynamic method for the constructor |
184 */ |
217 */ |
185 public static Object getConstructorMethod(final Class<?> clazz, final String signature) { |
218 public static Object getConstructorMethod(final Class<?> clazz, final String signature) { |
186 return StaticClassLinker.getConstructorMethod(clazz, signature); |
219 return StaticClassLinker.getConstructorMethod(clazz, signature); |
187 } |
220 } |
188 |
221 |