PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/java/client/src/org/openqa/selenium/remote/BeanToJsonConverter.java

https://bitbucket.org/abahdanovich/selenium
Java | 281 lines | 203 code | 42 blank | 36 comment | 43 complexity | 7ed68bce3122decac348fd3d75782da3 MD5 | raw file
Possible License(s): LGPL-2.1, MPL-2.0-no-copyleft-exception, AGPL-1.0, MIT, Apache-2.0, BSD-3-Clause, GPL-2.0
  1. /*
  2. Copyright 2007-2012 Selenium committers
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package org.openqa.selenium.remote;
  14. import org.json.JSONArray;
  15. import org.json.JSONException;
  16. import org.json.JSONObject;
  17. import org.openqa.selenium.Capabilities;
  18. import org.openqa.selenium.Cookie;
  19. import org.openqa.selenium.WebDriverException;
  20. import org.openqa.selenium.browserlaunchers.DoNotUseProxyPac;
  21. import org.openqa.selenium.logging.LogEntries;
  22. import org.openqa.selenium.logging.LoggingPreferences;
  23. import org.openqa.selenium.logging.SessionLogs;
  24. import java.io.File;
  25. import java.lang.reflect.Array;
  26. import java.lang.reflect.InvocationTargetException;
  27. import java.lang.reflect.Method;
  28. import java.util.ArrayList;
  29. import java.util.Collection;
  30. import java.util.Date;
  31. import java.util.HashMap;
  32. import java.util.Iterator;
  33. import java.util.List;
  34. import java.util.Map;
  35. import java.util.concurrent.TimeUnit;
  36. import java.util.logging.Level;
  37. /**
  38. * Utility class for converting between JSON and Java Objects.
  39. */
  40. public class BeanToJsonConverter {
  41. private static final int MAX_DEPTH = 5;
  42. /**
  43. * Convert an object that may or may not be a JSONArray or JSONObject into its JSON string
  44. * representation, handling the case where it is neither in a graceful way.
  45. *
  46. * @param object which needs conversion
  47. * @return the JSON string representation of object
  48. */
  49. public String convert(Object object) {
  50. if (object == null) {
  51. return null;
  52. }
  53. try {
  54. Object converted = convertObject(object, MAX_DEPTH);
  55. if (converted instanceof JSONObject
  56. || converted instanceof JSONArray
  57. || converted instanceof String
  58. || converted instanceof Number) {
  59. return converted.toString();
  60. }
  61. return String.valueOf(object);
  62. } catch (Exception e) {
  63. throw new WebDriverException("Unable to convert: " + object, e);
  64. }
  65. }
  66. /**
  67. * Convert a JSON[Array|Object] into the equivalent Java Collection type (that is, List|Map)
  68. * returning other objects untouched. This method is used for preparing values for use by the
  69. * HttpCommandExecutor
  70. *
  71. * @param o Object to convert
  72. * @return a Map, List or the unconverted Object
  73. */
  74. private Object convertUnknownObjectFromJson(Object o) {
  75. if (o instanceof JSONArray) {
  76. return convertJsonArray((JSONArray) o);
  77. }
  78. if (o instanceof JSONObject) {
  79. return convertJsonObject((JSONObject) o);
  80. }
  81. return o;
  82. }
  83. private Map<String, Object> convertJsonObject(JSONObject jsonObject) {
  84. Map<String, Object> toReturn = new HashMap<String, Object>();
  85. Iterator<?> allKeys = jsonObject.keys();
  86. while (allKeys.hasNext()) {
  87. String key = (String) allKeys.next();
  88. try {
  89. toReturn.put(key, convertUnknownObjectFromJson(jsonObject.get(key)));
  90. } catch (JSONException e) {
  91. throw new IllegalStateException("Unable to access key: " + key, e);
  92. }
  93. }
  94. return toReturn;
  95. }
  96. private List<Object> convertJsonArray(JSONArray jsonArray) {
  97. List<Object> toReturn = new ArrayList<Object>();
  98. for (int i = 0; i < jsonArray.length(); i++) {
  99. try {
  100. toReturn.add(convertUnknownObjectFromJson(jsonArray.get(i)));
  101. } catch (JSONException e) {
  102. throw new IllegalStateException("Cannot convert object at index: " + i, e);
  103. }
  104. }
  105. return toReturn;
  106. }
  107. @SuppressWarnings("unchecked")
  108. private Object convertObject(Object toConvert, int maxDepth) throws Exception {
  109. if (toConvert == null) {
  110. return JSONObject.NULL;
  111. }
  112. if (toConvert instanceof Boolean ||
  113. toConvert instanceof CharSequence ||
  114. toConvert instanceof Number) {
  115. return toConvert;
  116. }
  117. if (toConvert instanceof Level) {
  118. return toConvert.toString();
  119. }
  120. if (toConvert.getClass().isEnum() || toConvert instanceof Enum) {
  121. return toConvert.toString();
  122. }
  123. if (toConvert instanceof LoggingPreferences) {
  124. LoggingPreferences prefs = (LoggingPreferences) toConvert;
  125. JSONObject converted = new JSONObject();
  126. for (String logType : prefs.getEnabledLogTypes()) {
  127. converted.put(logType, prefs.getLevel(logType));
  128. }
  129. return converted;
  130. }
  131. if (toConvert instanceof SessionLogs) {
  132. return convertObject(((SessionLogs)toConvert).getAll(), maxDepth - 1);
  133. }
  134. if (toConvert instanceof LogEntries) {
  135. return convertObject(((LogEntries)toConvert).getAll(), maxDepth - 1);
  136. }
  137. if (toConvert instanceof Map) {
  138. JSONObject converted = new JSONObject();
  139. for (Object objectEntry : ((Map) toConvert).entrySet()) {
  140. Map.Entry<String, Object> entry = (Map.Entry) objectEntry;
  141. converted.put(entry.getKey(), convertObject(entry.getValue(), maxDepth - 1));
  142. }
  143. return converted;
  144. }
  145. if (toConvert instanceof JSONObject) {
  146. return toConvert;
  147. }
  148. if (toConvert instanceof Collection) {
  149. JSONArray array = new JSONArray();
  150. for (Object o : (Collection) toConvert) {
  151. array.put(convertObject(o, maxDepth - 1));
  152. }
  153. return array;
  154. }
  155. if (toConvert.getClass().isArray()) {
  156. JSONArray converted = new JSONArray();
  157. int length = Array.getLength(toConvert);
  158. for (int i = 0; i < length; i++) {
  159. converted.put(convertObject(Array.get(toConvert, i), maxDepth - 1));
  160. }
  161. return converted;
  162. }
  163. if (toConvert instanceof SessionId) {
  164. JSONObject converted = new JSONObject();
  165. converted.put("value", toConvert.toString());
  166. return converted;
  167. }
  168. if (toConvert instanceof Capabilities) {
  169. return convertObject(((Capabilities) toConvert).asMap(), maxDepth - 1);
  170. }
  171. if (toConvert instanceof DoNotUseProxyPac) {
  172. return convertObject(((DoNotUseProxyPac) toConvert).asMap(), maxDepth - 1);
  173. }
  174. if (toConvert instanceof Date) {
  175. return TimeUnit.MILLISECONDS.toSeconds(((Date) toConvert).getTime());
  176. }
  177. if (toConvert instanceof File) {
  178. return ((File) toConvert).getAbsolutePath();
  179. }
  180. Method toJson = getToJsonMethod(toConvert);
  181. if (toJson != null) {
  182. try {
  183. return toJson.invoke(toConvert);
  184. } catch (IllegalArgumentException e) {
  185. throw new WebDriverException(e);
  186. } catch (IllegalAccessException e) {
  187. throw new WebDriverException(e);
  188. } catch (InvocationTargetException e) {
  189. throw new WebDriverException(e);
  190. }
  191. }
  192. try {
  193. return mapObject(toConvert, maxDepth - 1, toConvert instanceof Cookie);
  194. } catch (Exception e) {
  195. throw new WebDriverException(e);
  196. }
  197. }
  198. private Method getToJsonMethod(Object toConvert) {
  199. try {
  200. return toConvert.getClass().getMethod("toJson");
  201. } catch (SecurityException e) {
  202. // fall through
  203. } catch (NoSuchMethodException e) {
  204. // fall through
  205. }
  206. return null;
  207. }
  208. private Object mapObject(Object toConvert, int maxDepth, boolean skipNulls) throws Exception {
  209. if (maxDepth < 1) {
  210. return null;
  211. }
  212. // Raw object via reflection? Nope, not needed
  213. JSONObject mapped = new JSONObject();
  214. for (SimplePropertyDescriptor pd : SimplePropertyDescriptor
  215. .getPropertyDescriptors(toConvert.getClass())) {
  216. if ("class".equals(pd.getName())) {
  217. mapped.put("class", toConvert.getClass().getName());
  218. continue;
  219. }
  220. Method readMethod = pd.getReadMethod();
  221. if (readMethod == null) {
  222. continue;
  223. }
  224. if (readMethod.getParameterTypes().length > 0) {
  225. continue;
  226. }
  227. readMethod.setAccessible(true);
  228. Object result = readMethod.invoke(toConvert);
  229. result = convertObject(result, maxDepth - 1);
  230. if (!skipNulls || result != JSONObject.NULL) {
  231. mapped.put(pd.getName(), result);
  232. }
  233. }
  234. return mapped;
  235. }
  236. }