package ren.yale.java; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.http.HttpServerRequest; import io.vertx.core.http.HttpServerResponse; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.Route; import io.vertx.ext.web.Router; import io.vertx.ext.web.RoutingContext; import io.vertx.ext.web.Session; import io.vertx.ext.web.handler.BodyHandler; import io.vertx.ext.web.handler.CookieHandler; import io.vertx.ext.web.handler.SessionHandler; import io.vertx.ext.web.sstore.LocalSessionStore; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import ren.yale.java.interceptor.Interceptor; import ren.yale.java.method.ArgInfo; import ren.yale.java.method.ClassInfo; import ren.yale.java.method.MethodInfo; import ren.yale.java.tools.*; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.ByteArrayOutputStream; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Yale * * create at: 2018-02-01 14:08 **/ public class SummerRouter { private final static Logger LOGGER = LogManager.getLogger(SummerRouter.class.getName()); private List<ClassInfo> classInfos; private Router router; private Vertx vertx; private String contextPath=""; public SummerRouter(Router router,Vertx vertx){ this.router = router; this.vertx =vertx; this.classInfos = new ArrayList<>(); this.init(); } public String getContextPath() { return contextPath; } public void setContextPath(String contextPath) { if (!StringUtils.isEmpty(contextPath)){ this.contextPath = contextPath; } } public Router getRouter() { return router; } private void init(){ router.route().handler(BodyHandler.create()); router.route().handler(CookieHandler.create()); SessionHandler handler = SessionHandler.create(LocalSessionStore.create(vertx)); handler.setNagHttps(true); router.route().handler(handler); } private boolean isRegister(Class clazz){ for (ClassInfo classInfo:classInfos) { if (classInfo.getClazz() == clazz){ return true; } } return false; } public void registerResource(Class clazz){ if (isRegister(clazz)){ return; } ClassInfo classInfo = MethodsProcessor.get(classInfos, clazz); if (classInfo!=null){ for (MethodInfo methodInfo:classInfo.getMethodInfoList()) { String p = classInfo.getClassPath()+methodInfo.getMethodPath(); p = PathParamConverter.converter(p); p =addContextPath(p); Route route=null; if (methodInfo.getHttpMethod()== null){ route = router.route(p); }else if (methodInfo.getHttpMethod()== GET.class){ route = router.get(p); }else if (methodInfo.getHttpMethod()== POST.class){ route = router.post(p); }else if (methodInfo.getHttpMethod()== PUT.class){ route = router.put(p); }else if (methodInfo.getHttpMethod()== DELETE.class){ route = router.delete(p); }else if (methodInfo.getHttpMethod()== OPTIONS.class){ route = router.options(p); }else if (methodInfo.getHttpMethod()== HEAD.class){ route = router.head(p); } if (methodInfo.isBlocking()){ route.blockingHandler(getHandler(classInfo,methodInfo)); }else{ route.handler(getHandler(classInfo,methodInfo)); } } } } private String addContextPath(String path) { return contextPath+path; } private Object covertType(Class type,String v) throws Exception{ String typeName = type.getTypeName(); if (type == String.class){ return v; } if (type == Integer.class||typeName.equals("int")){ return Integer.parseInt(v); } if (type == Long.class||typeName.equals("long")){ return Long.parseLong(v); } if (type == Float.class||typeName.equals("float")){ return Float.parseFloat(v); } if (type == Double.class||typeName.equals("double")){ return Double.parseDouble(v); } return null; } private Object getPathParamArg(RoutingContext routingContext, ArgInfo argInfo){ try { String path = routingContext.request().getParam(argInfo.getPathParam()); if (!StringUtils.isEmpty(path)){ return covertType(argInfo.getClazz(),path); } if (!StringUtils.isEmpty(argInfo.getDefaultValue())){ return covertType(argInfo.getClazz(),argInfo.getDefaultValue()); } }catch (Exception e){ LOGGER.error(e.getMessage()); } return null; } private Object getFromParamArg(RoutingContext routingContext,ArgInfo argInfo){ try { String q = routingContext.request().getParam(argInfo.getFormParam()); if (!StringUtils.isEmpty(q)){ return covertType(argInfo.getClazz(),q); } if (!StringUtils.isEmpty(argInfo.getDefaultValue())){ return covertType(argInfo.getClazz(),argInfo.getDefaultValue()); } }catch (Exception e){ LOGGER.error(e.getMessage()); } return null; } private Object getQueryParamArg(RoutingContext routingContext,ArgInfo argInfo){ try { String q = routingContext.request().getParam(argInfo.getQueryParam()); if (!StringUtils.isEmpty(q)){ return covertType(argInfo.getClazz(),q); } if (!StringUtils.isEmpty(argInfo.getDefaultValue())){ return covertType(argInfo.getClazz(),argInfo.getDefaultValue()); } }catch (Exception e){ LOGGER.error(e.getMessage()); } return null; } private Object getContext(RoutingContext routingContext,ArgInfo argInfo){ Class clz = argInfo.getClazz(); if (clz ==RoutingContext.class){ return routingContext; }else if (clz == HttpServerRequest.class){ return routingContext.request(); }else if (clz == HttpServerResponse.class){ return routingContext.response(); }else if (clz == Session.class){ return routingContext.session(); }else if (clz == Vertx.class){ return vertx; } return null; } private Object[] getArgs(RoutingContext routingContext,ClassInfo classInfo,MethodInfo methodInfo){ Object[] objects = new Object[methodInfo.getArgInfoList().size()]; int i =0; for (ArgInfo argInfo:methodInfo.getArgInfoList()){ if (argInfo.isContext()){ objects[i] = getContext(routingContext,argInfo); }else if (argInfo.isQueryParam()){ objects[i] = getQueryParamArg(routingContext,argInfo); }else if (argInfo.isFormParam()){ objects[i] = getFromParamArg(routingContext,argInfo); }else if (argInfo.isPathParam()){ objects[i] = getPathParamArg(routingContext,argInfo); }else{ objects[i] = null; } i++; } return objects; } private String convert2XML(Object object) throws JAXBException { JAXBContext context = JAXBContext.newInstance(object.getClass()); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8"); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); ByteArrayOutputStream baos = new ByteArrayOutputStream(); marshaller.marshal(object, baos); return new String(baos.toByteArray()); } private boolean handleBefores(RoutingContext routingContext,ClassInfo classInfo, MethodInfo methodInfo){ List<Interceptor> beforeList = new ArrayList<>(); if (methodInfo.getBefores()!=null){ beforeList.addAll(Arrays.asList(methodInfo.getBefores())); } if (classInfo.getBefores()!=null){ beforeList.addAll(Arrays.asList(classInfo.getBefores())); } for (Interceptor inter:beforeList) { if (inter.handle(routingContext,null)){ return true; } } return false; } private boolean handleAfters(RoutingContext routingContext,ClassInfo classInfo, MethodInfo methodInfo ,Object obj){ List<Interceptor> list = new ArrayList<>(); if (methodInfo.getAfters()!=null){ list.addAll(Arrays.asList(methodInfo.getAfters())); } if (classInfo.getAfters()!=null){ list.addAll(Arrays.asList(classInfo.getAfters())); } for (Interceptor inter:list) { if (inter.handle(routingContext,obj)){ return true; } } return false; } private void handlers(ClassInfo classInfo, MethodInfo methodInfo,RoutingContext routingContext){ if (handleBefores(routingContext,classInfo,methodInfo)){ return; } Object[] args = getArgs(routingContext,classInfo,methodInfo); routingContext.response().putHeader("Content-Type",methodInfo.getProducesType()) .setStatusCode(200); try { Object result = methodInfo.getMethod().invoke(classInfo.getClazzObj(),args); if (result!=null&&result.getClass() != Void.class){ if (!routingContext.response().ended()){ if( handleAfters(routingContext,classInfo,methodInfo,result)){ return; } if (!routingContext.response().ended()){ if (result instanceof String){ routingContext.response().end((String) result); }else{ if (methodInfo.getProducesType().indexOf(MediaType.TEXT_XML)>=0|| methodInfo.getProducesType().indexOf(MediaType.APPLICATION_XML)>=0 ){ routingContext.response().end(convert2XML(result)); }else{ routingContext.response() .putHeader("Content-Type", MediaType.APPLICATION_JSON+";charset=utf-8").end(JsonObject.mapFrom(result).encodePrettily()); } } } } } }catch (Exception e){ LOGGER.error(e.toString()); routingContext.response().setStatusCode(500).putHeader("Content-Type", MediaType.TEXT_PLAIN+";charset=utf-8") .end(e.toString()); } } private Handler<RoutingContext> getHandler(ClassInfo classInfo, MethodInfo methodInfo){ return (routingContext -> { try { handlers(classInfo,methodInfo,routingContext); } catch (Exception e) { LOGGER.error(e.getMessage()); routingContext.response().setStatusCode(500).putHeader("Content-Type", MediaType.TEXT_PLAIN+";charset=utf-8") .end(e.toString()); } }); } }