PageRenderTime 28ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/dubbo-common/src/main/java/com/alibaba/dubbo/common/json/J2oVisitor.java

https://gitlab.com/sxyseo/dubbox
Java | 410 lines | 352 code | 37 blank | 21 comment | 113 complexity | 8852040e90a6a446778adb2b0466ce52 MD5 | raw file
  1. /*
  2. * Copyright 1999-2011 Alibaba Group.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.alibaba.dubbo.common.json;
  17. import java.io.IOException;
  18. import java.lang.reflect.Array;
  19. import java.lang.reflect.Field;
  20. import java.util.ArrayList;
  21. import java.util.Collection;
  22. import java.util.HashMap;
  23. import java.util.HashSet;
  24. import java.util.LinkedList;
  25. import java.util.Map;
  26. import java.util.concurrent.ConcurrentHashMap;
  27. import java.util.concurrent.ConcurrentMap;
  28. import com.alibaba.dubbo.common.bytecode.Wrapper;
  29. import com.alibaba.dubbo.common.utils.Stack;
  30. import com.alibaba.dubbo.common.utils.StringUtils;
  31. /**
  32. * JSON to Object visitor.
  33. *
  34. * @author qian.lei.
  35. */
  36. class J2oVisitor implements JSONVisitor
  37. {
  38. public static final boolean[] EMPTY_BOOL_ARRAY = new boolean[0];
  39. public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
  40. public static final char[] EMPTY_CHAR_ARRAY = new char[0];
  41. public static final short[] EMPTY_SHORT_ARRAY = new short[0];
  42. public static final int[] EMPTY_INT_ARRAY = new int[0];
  43. public static final long[] EMPTY_LONG_ARRAY = new long[0];
  44. public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
  45. public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
  46. public static final String[] EMPTY_STRING_ARRAY = new String[0];
  47. private Class<?>[] mTypes;
  48. private Class<?> mType = Object[].class;
  49. private Object mValue;
  50. private Wrapper mWrapper;
  51. private JSONConverter mConverter;
  52. private Stack<Object> mStack = new Stack<Object>();
  53. J2oVisitor(Class<?> type, JSONConverter jc)
  54. {
  55. mType = type;
  56. mConverter = jc;
  57. }
  58. J2oVisitor(Class<?>[] types, JSONConverter jc)
  59. {
  60. mTypes = types;
  61. mConverter = jc;
  62. }
  63. public void begin()
  64. {}
  65. public Object end(Object obj, boolean isValue) throws ParseException
  66. {
  67. mStack.clear();
  68. try {
  69. return mConverter.readValue(mType, obj);
  70. } catch (IOException e) {
  71. throw new IllegalStateException(e.getMessage(), e);
  72. }
  73. }
  74. public void objectBegin() throws ParseException
  75. {
  76. mStack.push(mValue);
  77. mStack.push(mType);
  78. mStack.push(mWrapper);
  79. if( mType == Object.class || Map.class.isAssignableFrom(mType) )
  80. {
  81. if (! mType.isInterface() && mType != Object.class) {
  82. try {
  83. mValue = mType.newInstance();
  84. } catch (Exception e) {
  85. throw new IllegalStateException(e.getMessage(), e);
  86. }
  87. } else if (mType == ConcurrentMap.class) {
  88. mValue = new ConcurrentHashMap<String, Object>();
  89. } else {
  90. mValue = new HashMap<String, Object>();
  91. }
  92. mWrapper = null;
  93. } else {
  94. try {
  95. mValue = mType.newInstance();
  96. mWrapper = Wrapper.getWrapper(mType);
  97. } catch(IllegalAccessException e){
  98. throw new ParseException(StringUtils.toString(e));
  99. } catch(InstantiationException e){
  100. throw new ParseException(StringUtils.toString(e));
  101. }
  102. }
  103. }
  104. public Object objectEnd(int count)
  105. {
  106. Object ret = mValue;
  107. mWrapper = (Wrapper)mStack.pop();
  108. mType = (Class<?>)mStack.pop();
  109. mValue = mStack.pop();
  110. return ret;
  111. }
  112. public void objectItem(String name)
  113. {
  114. mStack.push(name); // push name.
  115. mType = ( mWrapper == null ? Object.class : mWrapper.getPropertyType(name) );
  116. }
  117. @SuppressWarnings("unchecked")
  118. public void objectItemValue(Object obj, boolean isValue) throws ParseException
  119. {
  120. String name = (String)mStack.pop(); // pop name.
  121. if( mWrapper == null )
  122. {
  123. ((Map<String, Object>)mValue).put(name, obj);
  124. }
  125. else
  126. {
  127. if( mType != null )
  128. {
  129. if( isValue && obj != null )
  130. {
  131. try
  132. {
  133. obj = mConverter.readValue(mType, obj);
  134. }
  135. catch(IOException e)
  136. {
  137. throw new ParseException(StringUtils.toString(e));
  138. }
  139. }
  140. if (mValue instanceof Throwable && "message".equals(name)) {
  141. try {
  142. Field field = Throwable.class.getDeclaredField("detailMessage");
  143. if (!field.isAccessible()) {
  144. field.setAccessible(true);
  145. }
  146. field.set(mValue, obj);
  147. } catch (NoSuchFieldException e) {
  148. throw new ParseException(StringUtils.toString(e));
  149. } catch (IllegalAccessException e) {
  150. throw new ParseException(StringUtils.toString(e));
  151. }
  152. } else if (mValue instanceof Throwable && "suppressed".equals(name)) { // modified by lishen
  153. // simply ignore this field for jdk 1.7+
  154. } else if (! CLASS_PROPERTY.equals(name)) {
  155. mWrapper.setPropertyValue(mValue, name, obj);
  156. }
  157. }
  158. }
  159. }
  160. public void arrayBegin() throws ParseException
  161. {
  162. mStack.push(mType);
  163. if( mType.isArray() )
  164. mType = mType.getComponentType();
  165. else if( mType == Object.class || Collection.class.isAssignableFrom(mType) )
  166. mType = Object.class;
  167. else
  168. throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "].");
  169. }
  170. @SuppressWarnings("unchecked")
  171. public Object arrayEnd(int count) throws ParseException
  172. {
  173. Object ret;
  174. mType = (Class<?>)mStack.get(-1-count);
  175. if( mType.isArray() )
  176. {
  177. ret = toArray(mType.getComponentType(), mStack, count);
  178. }
  179. else
  180. {
  181. Collection<Object> items;
  182. if( mType == Object.class || Collection.class.isAssignableFrom(mType)) {
  183. if (! mType.isInterface() && mType != Object.class) {
  184. try {
  185. items = (Collection<Object>) mType.newInstance();
  186. } catch (Exception e) {
  187. throw new IllegalStateException(e.getMessage(), e);
  188. }
  189. } else if (mType.isAssignableFrom(ArrayList.class)) { // List
  190. items = new ArrayList<Object>(count);
  191. } else if (mType.isAssignableFrom(HashSet.class)) { // Set
  192. items = new HashSet<Object>(count);
  193. } else if (mType.isAssignableFrom(LinkedList.class)) { // Queue
  194. items = new LinkedList<Object>();
  195. } else { // Other
  196. items = new ArrayList<Object>(count);
  197. }
  198. } else {
  199. throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "].");
  200. }
  201. for(int i=0;i<count;i++)
  202. items.add(mStack.remove(i-count));
  203. ret = items;
  204. }
  205. mStack.pop();
  206. return ret;
  207. }
  208. public void arrayItem(int index) throws ParseException
  209. {
  210. if( mTypes != null && mStack.size() == index+1 )
  211. {
  212. if( index < mTypes.length )
  213. mType = mTypes[index];
  214. else
  215. throw new ParseException("Can not load json array data into [" + name(mTypes) + "].");
  216. }
  217. }
  218. public void arrayItemValue(int index, Object obj, boolean isValue) throws ParseException
  219. {
  220. if( isValue && obj != null )
  221. {
  222. try
  223. {
  224. obj = mConverter.readValue(mType, obj);
  225. }
  226. catch(IOException e)
  227. {
  228. throw new ParseException(e.getMessage());
  229. }
  230. }
  231. mStack.push(obj);
  232. }
  233. private static Object toArray(Class<?> c, Stack<Object> list, int len) throws ParseException
  234. {
  235. if( c == String.class )
  236. {
  237. if( len == 0 )
  238. {
  239. return EMPTY_STRING_ARRAY;
  240. }
  241. else
  242. {
  243. Object o;
  244. String ss[] = new String[len];
  245. for(int i=len-1;i>=0;i--)
  246. {
  247. o = list.pop();
  248. ss[i] = ( o == null ? null : o.toString() );
  249. }
  250. return ss;
  251. }
  252. }
  253. if( c == boolean.class )
  254. {
  255. if( len == 0 ) return EMPTY_BOOL_ARRAY;
  256. Object o;
  257. boolean[] ret = new boolean[len];
  258. for(int i=len-1;i>=0;i--)
  259. {
  260. o = list.pop();
  261. if( o instanceof Boolean )
  262. ret[i] = ((Boolean)o).booleanValue();
  263. }
  264. return ret;
  265. }
  266. if( c == int.class )
  267. {
  268. if( len == 0 ) return EMPTY_INT_ARRAY;
  269. Object o;
  270. int[] ret = new int[len];
  271. for(int i=len-1;i>=0;i--)
  272. {
  273. o = list.pop();
  274. if( o instanceof Number )
  275. ret[i] = ((Number)o).intValue();
  276. }
  277. return ret;
  278. }
  279. if( c == long.class )
  280. {
  281. if( len == 0 ) return EMPTY_LONG_ARRAY;
  282. Object o;
  283. long[] ret = new long[len];
  284. for(int i=len-1;i>=0;i--)
  285. {
  286. o = list.pop();
  287. if( o instanceof Number )
  288. ret[i] = ((Number)o).longValue();
  289. }
  290. return ret;
  291. }
  292. if( c == float.class )
  293. {
  294. if( len == 0 ) return EMPTY_FLOAT_ARRAY;
  295. Object o;
  296. float[] ret = new float[len];
  297. for(int i=len-1;i>=0;i--)
  298. {
  299. o = list.pop();
  300. if( o instanceof Number )
  301. ret[i] = ((Number)o).floatValue();
  302. }
  303. return ret;
  304. }
  305. if( c == double.class )
  306. {
  307. if( len == 0 ) return EMPTY_DOUBLE_ARRAY;
  308. Object o;
  309. double[] ret = new double[len];
  310. for(int i=len-1;i>=0;i--)
  311. {
  312. o = list.pop();
  313. if( o instanceof Number )
  314. ret[i] = ((Number)o).doubleValue();
  315. }
  316. return ret;
  317. }
  318. if( c == byte.class )
  319. {
  320. if( len == 0 ) return EMPTY_BYTE_ARRAY;
  321. Object o;
  322. byte[] ret = new byte[len];
  323. for(int i=len-1;i>=0;i--)
  324. {
  325. o = list.pop();
  326. if( o instanceof Number )
  327. ret[i] = ((Number)o).byteValue();
  328. }
  329. return ret;
  330. }
  331. if( c == char.class )
  332. {
  333. if( len == 0 ) return EMPTY_CHAR_ARRAY;
  334. Object o;
  335. char[] ret = new char[len];
  336. for(int i=len-1;i>=0;i--)
  337. {
  338. o = list.pop();
  339. if( o instanceof Character )
  340. ret[i] = ((Character)o).charValue();
  341. }
  342. return ret;
  343. }
  344. if( c == short.class )
  345. {
  346. if( len == 0 ) return EMPTY_SHORT_ARRAY;
  347. Object o;
  348. short[] ret = new short[len];
  349. for(int i=len-1;i>=0;i--)
  350. {
  351. o = list.pop();
  352. if( o instanceof Number )
  353. ret[i] = ((Number)o).shortValue();
  354. }
  355. return ret;
  356. }
  357. Object ret = Array.newInstance(c, len);
  358. for(int i=len-1;i>=0;i--)
  359. Array.set(ret, i, list.pop());
  360. return ret;
  361. }
  362. private static String name(Class<?>[] types)
  363. {
  364. StringBuilder sb = new StringBuilder();
  365. for(int i=0;i<types.length;i++)
  366. {
  367. if( i > 0 )
  368. sb.append(", ");
  369. sb.append(types[i].getName());
  370. }
  371. return sb.toString();
  372. }
  373. }