All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.gdface.thrift.BaseThriftUtils Maven / Gradle / Ivy

The newest version!
package net.gdface.thrift;

import static com.facebook.swift.codec.metadata.FieldKind.THRIFT_FIELD;
import static com.google.common.base.Preconditions.*;
import static java.lang.String.format;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.net.URI;
import java.net.URL;
import java.nio.ByteBuffer;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.facebook.swift.codec.ThriftStruct;
import com.facebook.swift.codec.metadata.ThriftExtraction;
import com.facebook.swift.codec.metadata.ThriftFieldExtractor;
import com.facebook.swift.codec.metadata.ThriftFieldInjection;
import com.facebook.swift.codec.metadata.ThriftFieldMetadata;
import com.facebook.swift.codec.metadata.ThriftInjection;
import com.facebook.swift.codec.metadata.ThriftMethodExtractor;
import com.facebook.swift.codec.metadata.ThriftMethodInjection;
import com.facebook.swift.codec.metadata.ThriftParameterInjection;
import com.facebook.swift.codec.metadata.ThriftStructMetadata;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.reflect.TypeParameter;
import com.google.common.reflect.TypeToken;

import net.gdface.utils.BaseTypeTransformer;

/**
 * thrift工具
 * @author guyadong
 *
 */
public class BaseThriftUtils {
	public static final Set> THRIFT_BUILTIN_KNOWNTYPES = 
	ImmutableSet.of(
			boolean.class,
			byte.class,
			double.class,
			short.class,
			int.class,
			long.class,
			String.class,
			ByteBuffer.class,
			void.class,
			Boolean.class,
			Byte.class,
			Short.class,
			Integer.class,
			Long.class,
			Double.class);
	public static final Map,Class> CAST_TYPES = 
		ImmutableMap.,Class>builder()
			.put(byte[].class,ByteBuffer.class)
			.put(Date.class,Long.class)
			.put(java.sql.Date.class,Long.class)
			.put(java.sql.Time.class,Long.class)
			.put(float.class,double.class)
			.put(Float.class,Double.class)
			.put(URI.class,String.class)
			.put(URL.class,String.class)
			.build();
	public static final String DECORATOR_PKG_SUFFIX="decorator";
	public static final String CLIENT_SUFFIX="client";
	public static final String DECORATOR_CLIENT_PKG_SUFFIX= DECORATOR_PKG_SUFFIX + "." + CLIENT_SUFFIX;
	public static final String FIELD_INITIALIZED = "initialized";
	public static final String FIELD_MODIFIED = "modified";
	/**
	 * gu.sql2java.BaseBean 的内置字段名
	 */
	public static final ImmutableSet BASEBEAN_BUILTIN_FIELDS=ImmutableSet.of(FIELD_INITIALIZED,FIELD_MODIFIED);
	private static Class baseBeanClass;
	static{
		try {
			baseBeanClass = Class.forName("gu.sql2java.BaseBean",false,BaseThriftUtils.class.getClassLoader());
		} catch (ClassNotFoundException e) {			
		}
	}
	public BaseThriftUtils() {
	}

	public static Class getBaseBeanClass() {
		return baseBeanClass;
	}

	public static void setBaseBeanClass(Class baseBeanClass) {
		BaseThriftUtils.baseBeanClass = baseBeanClass;
	}

	/**
	 * 获取{@code field}指定的字段值
* 参见 com.facebook.swift.codec.internal.reflection.AbstractReflectionThriftCodec#getFieldValue(Object, ThriftFieldMetadata) * * @param instance * @param field * @return 字段值 * @throws Exception */ public static TypeValue getFieldValue(Object instance, ThriftFieldMetadata field) throws Exception { try { if (field.getExtraction().isPresent()) { ThriftExtraction extraction = field.getExtraction().get(); if (extraction instanceof ThriftFieldExtractor) { ThriftFieldExtractor thriftFieldExtractor = (ThriftFieldExtractor) extraction; Field f = thriftFieldExtractor.getField(); return new TypeValue(f.getGenericType(),f.get(instance)); } else if (extraction instanceof ThriftMethodExtractor) { ThriftMethodExtractor thriftMethodExtractor = (ThriftMethodExtractor) extraction; Method method = thriftMethodExtractor.getMethod(); return new TypeValue(method.getGenericReturnType(),method.invoke(instance)); } throw new IllegalAccessException("Unsupported field extractor type " + extraction.getClass().getName()); } throw new IllegalAccessException("No extraction present for " + field); } catch (InvocationTargetException e) { if (e.getTargetException() != null) { Throwables.throwIfInstanceOf(e.getTargetException(), Exception.class); } throw e; } } public static boolean isThriftStruct(Type type){ return type instanceof Class ? ((Class)type).isAnnotationPresent(ThriftStruct.class) : false; } public static boolean isThriftDecorator(Type type){ return type instanceof Class ? ThriftDecorator.class.isAssignableFrom((Class)type) : false; } /** * 如果{@code clazz}实现了{@link ThriftDecorator}接口, * 则返回该类型代理的类型,否则返回{@code null} * @param clazz * @since 1.2.3 */ public static Class delegateClassOf(Class clazz){ if(clazz != null && ThriftDecorator.class.isAssignableFrom(clazz)) { for(Type type:clazz.getGenericInterfaces()) { if(type instanceof ParameterizedType) { ParameterizedType parameterizedType = (ParameterizedType)type; if(ThriftDecorator.class.equals(parameterizedType.getRawType())) { return (Class) parameterizedType.getActualTypeArguments()[0]; } } } } return null; } /** * 如果输入类型是是装饰类({@link ThriftDecorator}),则返回代理类型,否则返回原样类型 * @param clazz * @since 1.2.6 */ public static Class delegateClassOrSelf(Class clazz){ Class delegateClass = delegateClassOf(clazz); return null == delegateClass ? clazz : delegateClass; } public static boolean isPrimitiveArray(Type type){ if(type instanceof Class){ Class clazz = (Class)type; return clazz.isArray() && clazz.getComponentType().isPrimitive(); } return false; } public static boolean isThriftBuildinType(Type type){ return THRIFT_BUILTIN_KNOWNTYPES.contains(type); } public static boolean isPrimitivefloat(Type type){ return type == float.class; } public static boolean isfloat(Type type){ return type == float.class || type == Float.class; } public static boolean isCastType(Type type){ return CAST_TYPES.containsKey(type); } public static boolean isException(Type type){ return null == type ? false : Exception.class.isAssignableFrom(TypeToken.of(type).getRawType()); } public static Constructor getConstructor(Class clazz,Class...parameterTypes){ try { return clazz.getConstructor(parameterTypes); } catch (NoSuchMethodException e) { return null; } } public static boolean hasConstructor(Class clazz,Class...parameterTypes){ return getConstructor(clazz,parameterTypes) != null; } public static boolean isThriftException(Type type){ return isException(type) && isThriftStruct(type); } public static boolean isThriftException(Type left, Type right){ return isThriftException(left) && isThriftException(right); } public static boolean needTransformer(Type type){ return ! isThriftBuildinType(type) && ! isfloat(type); } public static interface Action{ void doClass(Class type); } public static void traverseTypes(Type type,Action action){ checkArgument(null !=action,"action is null"); if(type instanceof Class){ action.doClass((Class) type); }else if( type instanceof ParameterizedType){ ParameterizedType paramType = (ParameterizedType)type; Type rawType = paramType.getRawType(); Type[] typeArgs = paramType.getActualTypeArguments(); traverseTypes(rawType,action); for(Type arg:typeArgs){ traverseTypes(arg,action); } }else if (type instanceof GenericArrayType) { traverseTypes(((GenericArrayType) type).getGenericComponentType(),action); } else if (type instanceof TypeVariable) { for (Type t : ((TypeVariable) type).getBounds()) { traverseTypes(t,action); } } else if (type instanceof WildcardType) { for (Type t : ((WildcardType) type).getLowerBounds()) { traverseTypes(t,action); } for (Type t : ((WildcardType) type).getUpperBounds()) { traverseTypes(t,action); } } else{ throw new IllegalArgumentException(String.format("not allow type %s", type.toString())); } } @SuppressWarnings("serial") public static TypeToken> mapToken(TypeToken keyToken, TypeToken valueToken) { return new TypeToken>() {} .where(new TypeParameter() {}, keyToken) .where(new TypeParameter() {}, valueToken); } @SuppressWarnings("serial") public static TypeToken> listToken(TypeToken keyToken) { return new TypeToken>() {} .where(new TypeParameter() {}, keyToken); } @SuppressWarnings("serial") public static TypeToken> setToken(TypeToken keyToken) { return new TypeToken>() {} .where(new TypeParameter() {}, keyToken); } /** * 返回{@code type}是否有对应的decorator类型 * @param type * @return 如果{@code type}有对应的decorator类型返回{@code true},否则返回{@code false} * @see #getDecoratorType(Type) */ public static boolean hasDecoratorType(Type type){ return getDecoratorType(type) !=null; } /** * 返回{@code clazz}对应的装饰类 * @param type * @return 如果没有装饰类则返回{@code null} */ @SuppressWarnings("unchecked") public static Class> getDecoratorType(Type type){ if(!isThriftStruct(type)){ return getDecoratorType((Class)type); } return null; } /** * 返回{@code clazz}对应的装饰类 * @param clazz * @return 如果没有装饰类则返回{@code null} */ @SuppressWarnings("unchecked") public static >Class getDecoratorType(Class clazz){ if(!isThriftStruct(clazz)){ String decoratorClazzName = clazz.getPackage().getName() + "." + DECORATOR_CLIENT_PKG_SUFFIX + "." + clazz.getSimpleName(); try { Class decoratorClazz = Class.forName(decoratorClazzName); checkState(isThriftDecoratorPair(decoratorClazz,clazz), "%s must immplement %s", decoratorClazz.getName(), ThriftDecorator.class.getName()); return (Class) decoratorClazz; } catch (ClassNotFoundException e) { } } return null; } /** * 判断 {@code left and right}之间是否为装饰类和被装饰类关系 * @param left 装饰类 * @param right 补装饰类 * @return 如果是装饰类和被装饰类关系返回{@code true},否则返回{@code false} */ public static boolean isThriftDecoratorPair(Classleft,Classright){ try { return isThriftDecorator(left) && left.getMethod("delegate").getReturnType() == right; } catch (NoSuchMethodException e) { throw new RuntimeException(e); } } /** * 判断 {@code right}是否为{@code left}对应的client端存根类型 * @param left * @param right * @return 如果是client端存根类型返回{@code true}否则返回{@code false} */ public static boolean isThriftClientPair(Classleft,Classright){ return getMiddleClass(left,right)!=null; } /** * 返回 {@code left & right}之间的decorator类型,如果没有找到decorator类型定义则返回{@code null} * @param left 原始类型 * @param right {@code left}对应的client端存根类型 * @return decorator类型 */ public static ,R>Class getMiddleClass(Classleft,Classright){ Class decoratorClass = getDecoratorType(left); if(null != decoratorClass && decoratorClass.getSimpleName().equals(left.getSimpleName())){ return decoratorClass; } return null; } /** * 返回 {@code left & right}之间的decorator类型,如果{@code right}不为thrift struct则抛出异常 * @param left 原始类型 * @param right {@code left}对应的client端存根类型 * @return decorator类型 */ @SuppressWarnings("unchecked") public static ,R>Class getMiddleClassChecked(Classleft,Classright){ return (Class) checkNotNull( getMiddleClass(left,right), "NOT FOUND decorator class for %s", left.getName()); } public static final String ISLOCAL_METHOD_NAME = "isLocal"; public static boolean isIsLocalMethod(Method method){ if(null == method){ return false; } return method.getName().equals(ISLOCAL_METHOD_NAME) && method.getParameterTypes().length == 0 && method.getExceptionTypes().length == 0 && method.getReturnType() == boolean.class; } protected static void injectMethods(ThriftStructMetadata metadata, Map data, Object instance, BaseTypeTransformer transformer, boolean useId) throws Exception{ List methodInjections = Lists.newArrayList(metadata.getMethodInjections()); final List builtinInjections = Lists.newArrayList(); ClassbaseBeanClass =getBaseBeanClass(); if(null != baseBeanClass && baseBeanClass.isInstance(instance)){ // 将BaseBean内置字段排除保存到 builtinInjections for(Iterator itor = methodInjections.iterator();itor.hasNext();){ ThriftMethodInjection input = itor.next(); if(BaseThriftUtils.BASEBEAN_BUILTIN_FIELDS.contains(input.getParameters().get(0).getName())){ builtinInjections.add(input); itor.remove(); } } } // inject methods injectMethods(data,instance,methodInjections, transformer, useId); // 所有其他字段都执行完成注入后再执行内置字段的注入 injectMethods(data,instance,builtinInjections, transformer, useId); } private static void injectMethods( Map data, Object instance, Iterable methodInjections, BaseTypeTransformer transformer, boolean useId) throws Exception{ for (ThriftMethodInjection methodInjection : methodInjections) { boolean shouldInvoke = false; Object[] parametersValues = new Object[methodInjection.getParameters().size()]; Type[] srcTypes = new Type[methodInjection.getParameters().size()]; for (ThriftParameterInjection parameter : methodInjection.getParameters()) { TypeValue value = data.get(useId ?parameter.getId():parameter.getName()); if (value != null) { parametersValues[parameter.getParameterIndex()] = value.value; srcTypes[parameter.getParameterIndex()] = value.type; shouldInvoke = true; } } if (shouldInvoke) { try { Method method = methodInjection.getMethod(); Type[] parameterTypes = method.getGenericParameterTypes(); for(int i = 0 ;i * 参见 com.facebook.swift.codec.internal.reflection.ReflectionThriftStructCodec#constructStruct(Map) * @param data * @param metadata * @param instance * @return instance always * @throws Exception */ @SuppressWarnings({ "unchecked", "rawtypes" }) protected static T fillStructField(Map data, ThriftStructMetadata metadata, T instance, BaseTypeTransformer transformer, boolean useId) throws Exception{ checkArgument(null != instance,"instance is null"); // inject fields for (ThriftFieldMetadata fieldMetadata : metadata.getFields(THRIFT_FIELD)) { for (ThriftInjection injection : fieldMetadata.getInjections()) { if (injection instanceof ThriftFieldInjection) { ThriftFieldInjection fieldInjection = (ThriftFieldInjection) injection; TypeValue value = data.get(useId ?fieldInjection.getId():fieldInjection.getName()); if (value != null) { Field f = fieldInjection.getField(); f.set(instance, transformer.cast(value.value,value.type,f.getGenericType())); } } } } // inject methods injectMethods(metadata, (Map)data, instance, transformer, useId); // builder method if (metadata.getBuilderMethod().isPresent()) { ThriftMethodInjection builderMethod = metadata.getBuilderMethod().get(); Object[] parametersValues = new Object[builderMethod.getParameters().size()]; for (ThriftParameterInjection parameter : builderMethod.getParameters()) { TypeValue value = data.get(useId ?parameter.getId():parameter.getName()); parametersValues[parameter.getParameterIndex()] = value.value; } try { instance = (T) builderMethod.getMethod().invoke(instance, parametersValues); if (instance == null) { throw new IllegalArgumentException("Builder method returned a null instance"); } if (!metadata.getStructClass().isInstance(instance)) { throw new IllegalArgumentException(format("Builder method returned instance of type %s, but an instance of %s is required", instance.getClass().getName(), metadata.getStructClass().getName())); } } catch (InvocationTargetException e) { if (e.getTargetException() != null) { Throwables.throwIfUnchecked(e.getTargetException()); throw new RuntimeException(e.getTargetException()); } throw e; } } return (T) instance; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy