29 import java.lang.reflect.Method; |
29 import java.lang.reflect.Method; |
30 import java.lang.reflect.Type; |
30 import java.lang.reflect.Type; |
31 |
31 |
32 import javax.management.Descriptor; |
32 import javax.management.Descriptor; |
33 import javax.management.MBeanException; |
33 import javax.management.MBeanException; |
|
34 import javax.management.openmbean.MXBeanMapping; |
|
35 import javax.management.openmbean.MXBeanMappingFactory; |
34 import javax.management.openmbean.OpenDataException; |
36 import javax.management.openmbean.OpenDataException; |
35 import javax.management.openmbean.OpenType; |
37 import javax.management.openmbean.OpenType; |
36 |
38 |
37 final class ConvertingMethod { |
39 final class ConvertingMethod { |
38 static ConvertingMethod from(Method m) { |
40 static ConvertingMethod from(Method m, MXBeanMappingFactory mappingFactory) { |
39 try { |
41 try { |
40 return new ConvertingMethod(m); |
42 return new ConvertingMethod(m, mappingFactory); |
41 } catch (OpenDataException ode) { |
43 } catch (OpenDataException ode) { |
42 final String msg = "Method " + m.getDeclaringClass().getName() + |
44 final String msg = "Method " + m.getDeclaringClass().getName() + |
43 "." + m.getName() + " has parameter or return type that " + |
45 "." + m.getName() + " has parameter or return type that " + |
44 "cannot be translated into an open type"; |
46 "cannot be translated into an open type"; |
45 throw new IllegalArgumentException(msg, ode); |
47 throw new IllegalArgumentException(msg, ode); |
100 * The return type will be converted back to a Java type, so it |
102 * The return type will be converted back to a Java type, so it |
101 * must be "reconstructible". The parameters will be converted to |
103 * must be "reconstructible". The parameters will be converted to |
102 * open types, so if it is convertible at all there is no further |
104 * open types, so if it is convertible at all there is no further |
103 * check needed. |
105 * check needed. |
104 */ |
106 */ |
105 void checkCallToOpen() throws IllegalArgumentException { |
107 void checkCallToOpen() { |
106 try { |
108 try { |
107 returnConverter.checkReconstructible(); |
109 returnMapping.checkReconstructible(); |
108 } catch (InvalidObjectException e) { |
110 } catch (InvalidObjectException e) { |
109 throw new IllegalArgumentException(e); |
111 throw new IllegalArgumentException(e); |
110 } |
112 } |
111 } |
113 } |
112 |
114 |
113 String[] getOpenSignature() { |
115 String[] getOpenSignature() { |
114 if (paramConverters.length == 0) |
116 if (paramMappings.length == 0) |
115 return noStrings; |
117 return noStrings; |
116 |
118 |
117 String[] sig = new String[paramConverters.length]; |
119 String[] sig = new String[paramMappings.length]; |
118 for (int i = 0; i < paramConverters.length; i++) |
120 for (int i = 0; i < paramMappings.length; i++) |
119 sig[i] = paramConverters[i].getOpenClass().getName(); |
121 sig[i] = paramMappings[i].getOpenClass().getName(); |
120 return sig; |
122 return sig; |
121 } |
123 } |
122 |
124 |
123 final Object toOpenReturnValue(MXBeanLookup lookup, Object ret) |
125 final Object toOpenReturnValue(MXBeanLookup lookup, Object ret) |
124 throws OpenDataException { |
126 throws OpenDataException { |
125 return returnConverter.toOpenValue(lookup, ret); |
127 return returnMapping.toOpenValue(ret); |
126 } |
128 } |
127 |
129 |
128 final Object fromOpenReturnValue(MXBeanLookup lookup, Object ret) |
130 final Object fromOpenReturnValue(MXBeanLookup lookup, Object ret) |
129 throws InvalidObjectException { |
131 throws InvalidObjectException { |
130 return returnConverter.fromOpenValue(lookup, ret); |
132 return returnMapping.fromOpenValue(ret); |
131 } |
133 } |
132 |
134 |
133 final Object[] toOpenParameters(MXBeanLookup lookup, Object[] params) |
135 final Object[] toOpenParameters(MXBeanLookup lookup, Object[] params) |
134 throws OpenDataException { |
136 throws OpenDataException { |
135 if (paramConversionIsIdentity || params == null) |
137 if (paramConversionIsIdentity || params == null) |
136 return params; |
138 return params; |
137 final Object[] oparams = new Object[params.length]; |
139 final Object[] oparams = new Object[params.length]; |
138 for (int i = 0; i < params.length; i++) |
140 for (int i = 0; i < params.length; i++) |
139 oparams[i] = paramConverters[i].toOpenValue(lookup, params[i]); |
141 oparams[i] = paramMappings[i].toOpenValue(params[i]); |
140 return oparams; |
142 return oparams; |
141 } |
143 } |
142 |
144 |
143 final Object[] fromOpenParameters(MXBeanLookup lookup, Object[] params) |
145 final Object[] fromOpenParameters(Object[] params) |
144 throws InvalidObjectException { |
146 throws InvalidObjectException { |
145 if (paramConversionIsIdentity || params == null) |
147 if (paramConversionIsIdentity || params == null) |
146 return params; |
148 return params; |
147 final Object[] jparams = new Object[params.length]; |
149 final Object[] jparams = new Object[params.length]; |
148 for (int i = 0; i < params.length; i++) |
150 for (int i = 0; i < params.length; i++) |
149 jparams[i] = paramConverters[i].fromOpenValue(lookup, params[i]); |
151 jparams[i] = paramMappings[i].fromOpenValue(params[i]); |
150 return jparams; |
152 return jparams; |
151 } |
153 } |
152 |
154 |
153 final Object toOpenParameter(MXBeanLookup lookup, |
155 final Object toOpenParameter(MXBeanLookup lookup, |
154 Object param, |
156 Object param, |
155 int paramNo) |
157 int paramNo) |
156 throws OpenDataException { |
158 throws OpenDataException { |
157 return paramConverters[paramNo].toOpenValue(lookup, param); |
159 return paramMappings[paramNo].toOpenValue(param); |
158 } |
160 } |
159 |
161 |
160 final Object fromOpenParameter(MXBeanLookup lookup, |
162 final Object fromOpenParameter(MXBeanLookup lookup, |
161 Object param, |
163 Object param, |
162 int paramNo) |
164 int paramNo) |
163 throws InvalidObjectException { |
165 throws InvalidObjectException { |
164 return paramConverters[paramNo].fromOpenValue(lookup, param); |
166 return paramMappings[paramNo].fromOpenValue(param); |
165 } |
167 } |
166 |
168 |
167 Object invokeWithOpenReturn(MXBeanLookup lookup, |
169 Object invokeWithOpenReturn(MXBeanLookup lookup, |
168 Object obj, Object[] params) |
170 Object obj, Object[] params) |
169 throws MBeanException, IllegalAccessException, |
171 throws MBeanException, IllegalAccessException, |
170 InvocationTargetException { |
172 InvocationTargetException { |
|
173 MXBeanLookup old = MXBeanLookup.getLookup(); |
|
174 try { |
|
175 MXBeanLookup.setLookup(lookup); |
|
176 return invokeWithOpenReturn(obj, params); |
|
177 } finally { |
|
178 MXBeanLookup.setLookup(old); |
|
179 } |
|
180 } |
|
181 |
|
182 private Object invokeWithOpenReturn(Object obj, Object[] params) |
|
183 throws MBeanException, IllegalAccessException, |
|
184 InvocationTargetException { |
171 final Object[] javaParams; |
185 final Object[] javaParams; |
172 try { |
186 try { |
173 javaParams = fromOpenParameters(lookup, params); |
187 javaParams = fromOpenParameters(params); |
174 } catch (InvalidObjectException e) { |
188 } catch (InvalidObjectException e) { |
175 // probably can't happen |
189 // probably can't happen |
176 final String msg = methodName() + ": cannot convert parameters " + |
190 final String msg = methodName() + ": cannot convert parameters " + |
177 "from open values: " + e; |
191 "from open values: " + e; |
178 throw new MBeanException(e, msg); |
192 throw new MBeanException(e, msg); |
179 } |
193 } |
180 final Object javaReturn = method.invoke(obj, javaParams); |
194 final Object javaReturn = method.invoke(obj, javaParams); |
181 try { |
195 try { |
182 return returnConverter.toOpenValue(lookup, javaReturn); |
196 return returnMapping.toOpenValue(javaReturn); |
183 } catch (OpenDataException e) { |
197 } catch (OpenDataException e) { |
184 // probably can't happen |
198 // probably can't happen |
185 final String msg = methodName() + ": cannot convert return " + |
199 final String msg = methodName() + ": cannot convert return " + |
186 "value to open value: " + e; |
200 "value to open value: " + e; |
187 throw new MBeanException(e, msg); |
201 throw new MBeanException(e, msg); |
190 |
204 |
191 private String methodName() { |
205 private String methodName() { |
192 return method.getDeclaringClass() + "." + method.getName(); |
206 return method.getDeclaringClass() + "." + method.getName(); |
193 } |
207 } |
194 |
208 |
195 private ConvertingMethod(Method m) throws OpenDataException { |
209 private ConvertingMethod(Method m, MXBeanMappingFactory mappingFactory) |
|
210 throws OpenDataException { |
196 this.method = m; |
211 this.method = m; |
197 returnConverter = OpenConverter.toConverter(m.getGenericReturnType()); |
212 returnMapping = |
|
213 mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory); |
198 Type[] params = m.getGenericParameterTypes(); |
214 Type[] params = m.getGenericParameterTypes(); |
199 paramConverters = new OpenConverter[params.length]; |
215 paramMappings = new MXBeanMapping[params.length]; |
200 boolean identity = true; |
216 boolean identity = true; |
201 for (int i = 0; i < params.length; i++) { |
217 for (int i = 0; i < params.length; i++) { |
202 paramConverters[i] = OpenConverter.toConverter(params[i]); |
218 paramMappings[i] = mappingFactory.mappingForType(params[i], mappingFactory); |
203 identity &= paramConverters[i].isIdentity(); |
219 identity &= DefaultMXBeanMappingFactory.isIdentity(paramMappings[i]); |
204 } |
220 } |
205 paramConversionIsIdentity = identity; |
221 paramConversionIsIdentity = identity; |
206 } |
222 } |
207 |
223 |
208 private static final String[] noStrings = new String[0]; |
224 private static final String[] noStrings = new String[0]; |
209 |
225 |
210 private final Method method; |
226 private final Method method; |
211 private final OpenConverter returnConverter; |
227 private final MXBeanMapping returnMapping; |
212 private final OpenConverter[] paramConverters; |
228 private final MXBeanMapping[] paramMappings; |
213 private final boolean paramConversionIsIdentity; |
229 private final boolean paramConversionIsIdentity; |
214 } |
230 } |