blob: f0a8b29329eed9dd17d056ac67b4828290065e5d [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.dubbo.common.json;
import com.alibaba.dubbo.common.bytecode.Wrapper;
import com.alibaba.dubbo.common.utils.Stack;
import com.alibaba.dubbo.common.utils.StringUtils;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* JSON to Object visitor.
*/
@Deprecated
class J2oVisitor implements JSONVisitor {
public static final boolean[] EMPTY_BOOL_ARRAY = new boolean[0];
public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
public static final char[] EMPTY_CHAR_ARRAY = new char[0];
public static final short[] EMPTY_SHORT_ARRAY = new short[0];
public static final int[] EMPTY_INT_ARRAY = new int[0];
public static final long[] EMPTY_LONG_ARRAY = new long[0];
public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
public static final String[] EMPTY_STRING_ARRAY = new String[0];
private Class<?>[] mTypes;
private Class<?> mType = Object[].class;
private Object mValue;
private Wrapper mWrapper;
private JSONConverter mConverter;
private Stack<Object> mStack = new Stack<Object>();
J2oVisitor(Class<?> type, JSONConverter jc) {
mType = type;
mConverter = jc;
}
J2oVisitor(Class<?>[] types, JSONConverter jc) {
mTypes = types;
mConverter = jc;
}
private static Object toArray(Class<?> c, Stack<Object> list, int len) throws ParseException {
if (c == String.class) {
if (len == 0) {
return EMPTY_STRING_ARRAY;
} else {
Object o;
String ss[] = new String[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
ss[i] = (o == null ? null : o.toString());
}
return ss;
}
}
if (c == boolean.class) {
if (len == 0) return EMPTY_BOOL_ARRAY;
Object o;
boolean[] ret = new boolean[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Boolean)
ret[i] = ((Boolean) o).booleanValue();
}
return ret;
}
if (c == int.class) {
if (len == 0) return EMPTY_INT_ARRAY;
Object o;
int[] ret = new int[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Number)
ret[i] = ((Number) o).intValue();
}
return ret;
}
if (c == long.class) {
if (len == 0) return EMPTY_LONG_ARRAY;
Object o;
long[] ret = new long[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Number)
ret[i] = ((Number) o).longValue();
}
return ret;
}
if (c == float.class) {
if (len == 0) return EMPTY_FLOAT_ARRAY;
Object o;
float[] ret = new float[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Number)
ret[i] = ((Number) o).floatValue();
}
return ret;
}
if (c == double.class) {
if (len == 0) return EMPTY_DOUBLE_ARRAY;
Object o;
double[] ret = new double[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Number)
ret[i] = ((Number) o).doubleValue();
}
return ret;
}
if (c == byte.class) {
if (len == 0) return EMPTY_BYTE_ARRAY;
Object o;
byte[] ret = new byte[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Number)
ret[i] = ((Number) o).byteValue();
}
return ret;
}
if (c == char.class) {
if (len == 0) return EMPTY_CHAR_ARRAY;
Object o;
char[] ret = new char[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Character)
ret[i] = ((Character) o).charValue();
}
return ret;
}
if (c == short.class) {
if (len == 0) return EMPTY_SHORT_ARRAY;
Object o;
short[] ret = new short[len];
for (int i = len - 1; i >= 0; i--) {
o = list.pop();
if (o instanceof Number)
ret[i] = ((Number) o).shortValue();
}
return ret;
}
Object ret = Array.newInstance(c, len);
for (int i = len - 1; i >= 0; i--)
Array.set(ret, i, list.pop());
return ret;
}
private static String name(Class<?>[] types) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < types.length; i++) {
if (i > 0)
sb.append(", ");
sb.append(types[i].getName());
}
return sb.toString();
}
@Override
public void begin() {
}
@Override
public Object end(Object obj, boolean isValue) throws ParseException {
mStack.clear();
try {
return mConverter.readValue(mType, obj);
} catch (IOException e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
@Override
public void objectBegin() throws ParseException {
mStack.push(mValue);
mStack.push(mType);
mStack.push(mWrapper);
if (mType == Object.class || Map.class.isAssignableFrom(mType)) {
if (!mType.isInterface() && mType != Object.class) {
try {
mValue = mType.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
} else if (mType == ConcurrentMap.class) {
mValue = new ConcurrentHashMap<String, Object>();
} else {
mValue = new HashMap<String, Object>();
}
mWrapper = null;
} else {
try {
mValue = mType.newInstance();
mWrapper = Wrapper.getWrapper(mType);
} catch (IllegalAccessException e) {
throw new ParseException(StringUtils.toString(e));
} catch (InstantiationException e) {
throw new ParseException(StringUtils.toString(e));
}
}
}
@Override
public Object objectEnd(int count) {
Object ret = mValue;
mWrapper = (Wrapper) mStack.pop();
mType = (Class<?>) mStack.pop();
mValue = mStack.pop();
return ret;
}
@Override
public void objectItem(String name) {
mStack.push(name); // push name.
mType = (mWrapper == null ? Object.class : mWrapper.getPropertyType(name));
}
@Override
@SuppressWarnings("unchecked")
public void objectItemValue(Object obj, boolean isValue) throws ParseException {
String name = (String) mStack.pop(); // pop name.
if (mWrapper == null) {
((Map<String, Object>) mValue).put(name, obj);
} else {
if (mType != null) {
if (isValue && obj != null) {
try {
obj = mConverter.readValue(mType, obj);
} catch (IOException e) {
throw new ParseException(StringUtils.toString(e));
}
}
if (mValue instanceof Throwable && "message".equals(name)) {
try {
Field field = Throwable.class.getDeclaredField("detailMessage");
if (!field.isAccessible()) {
field.setAccessible(true);
}
field.set(mValue, obj);
} catch (NoSuchFieldException e) {
throw new ParseException(StringUtils.toString(e));
} catch (IllegalAccessException e) {
throw new ParseException(StringUtils.toString(e));
}
} else if (!CLASS_PROPERTY.equals(name)) {
mWrapper.setPropertyValue(mValue, name, obj);
}
}
}
}
@Override
public void arrayBegin() throws ParseException {
mStack.push(mType);
if (mType.isArray())
mType = mType.getComponentType();
else if (mType == Object.class || Collection.class.isAssignableFrom(mType))
mType = Object.class;
else
throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "].");
}
@Override
@SuppressWarnings("unchecked")
public Object arrayEnd(int count) throws ParseException {
Object ret;
mType = (Class<?>) mStack.get(-1 - count);
if (mType.isArray()) {
ret = toArray(mType.getComponentType(), mStack, count);
} else {
Collection<Object> items;
if (mType == Object.class || Collection.class.isAssignableFrom(mType)) {
if (!mType.isInterface() && mType != Object.class) {
try {
items = (Collection<Object>) mType.newInstance();
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
} else if (mType.isAssignableFrom(ArrayList.class)) { // List
items = new ArrayList<Object>(count);
} else if (mType.isAssignableFrom(HashSet.class)) { // Set
items = new HashSet<Object>(count);
} else if (mType.isAssignableFrom(LinkedList.class)) { // Queue
items = new LinkedList<Object>();
} else { // Other
items = new ArrayList<Object>(count);
}
} else {
throw new ParseException("Convert error, can not load json array data into class [" + mType.getName() + "].");
}
for (int i = 0; i < count; i++)
items.add(mStack.remove(i - count));
ret = items;
}
mStack.pop();
return ret;
}
@Override
public void arrayItem(int index) throws ParseException {
if (mTypes != null && mStack.size() == index + 1) {
if (index < mTypes.length)
mType = mTypes[index];
else
throw new ParseException("Can not load json array data into [" + name(mTypes) + "].");
}
}
@Override
public void arrayItemValue(int index, Object obj, boolean isValue) throws ParseException {
if (isValue && obj != null) {
try {
obj = mConverter.readValue(mType, obj);
} catch (IOException e) {
throw new ParseException(e.getMessage());
}
}
mStack.push(obj);
}
}