001package net.gdface.codegen.webclient; 002 003import java.lang.reflect.Modifier; 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.HashMap; 007import java.util.Iterator; 008import java.util.Map; 009 010import org.slf4j.Logger; 011import org.slf4j.LoggerFactory; 012 013import net.gdface.annotation.AnnotationException; 014import net.gdface.annotation.AnnotationRuntimeException; 015import net.gdface.annotation.Remote; 016import net.gdface.annotation.Service; 017import net.gdface.annotation.ServicePort; 018import net.gdface.codegen.AnnotationUtils; 019import net.gdface.codegen.NewSourceInfoAbstract; 020import net.gdface.codegen.ServiceInfo; 021import net.gdface.codegen.Method; 022import net.gdface.codegen.MethodException; 023import net.gdface.exception.ServiceRuntime; 024import net.gdface.utils.Assert; 025import net.gdface.utils.ParameterNames; 026 027public class WebClient<T> extends NewSourceInfoAbstract<T> { 028 private static final Logger logger = LoggerFactory.getLogger(WebClient.class); 029 protected ServiceInfo serviceInfo; 030 protected final Class<?> serviceClass; 031 public final ParameterNames serviceParamTable; 032 033 protected Map<Method, Method> method2PortMap = new HashMap<Method, Method>(); 034 private final Map<String, java.lang.reflect.Method> servicePorts; 035 @SuppressWarnings("unchecked") 036 public WebClient(Class<T> interfaceClass, Class<? extends T> refClass, Class<?> serviceClass) { 037 super(interfaceClass, refClass, (Class<? extends T>) refClass.getSuperclass()); 038 Assert.notNull(serviceClass, "serviceClass"); 039 this.serviceClass = serviceClass; 040 try { 041 servicePorts=getServicePorts(this.serviceClass); 042 } catch (DuplicatedNameMethodException e) { 043 throw new ExceptionInInitializerError(e); 044 } 045 serviceParamTable = new ParameterNames(serviceClass); 046 getImportedList().put("ServiceRuntime", net.gdface.exception.ServiceRuntime.class); 047 } 048 049 @Override 050 protected void createMethodsNeedGenerated() { 051 ArrayList<java.lang.reflect.Method> interfaceMethods = new ArrayList<java.lang.reflect.Method>( 052 Arrays.asList(interfaceClass.getMethods())); 053 java.lang.reflect.Method[] baseMethods = null != baseClass ? baseClass.getMethods() 054 : new java.lang.reflect.Method[0]; 055 try { 056 for (Iterator<java.lang.reflect.Method> it = interfaceMethods.iterator(); it.hasNext();) { 057 java.lang.reflect.Method im = it.next(); 058 if(needImpl(im)||!isImplemented(baseMethods, im)) 059 //if(!isImplemented(baseMethods, im)) 060 this.methodsNeedGenerated.add(new Method(refClass.getMethod(im.getName(), im.getParameterTypes()), 061 this.paramTable.getParameterNames(im.getName(), im.getParameterTypes()))); 062 } 063 } catch (NoSuchMethodException e) { 064 throw new RuntimeException(e); 065 } 066 } 067 068 @Override 069 public String toString() { 070 StringBuilder builder = new StringBuilder(); 071 int c = 0; 072 builder.append("//classes need imported in new Class:\n"); 073 for (Class<?> clazz : importedList.values()) { 074 builder.append("//[" + (++c) + "]\nimported ").append(clazz.getName()).append(";\n"); 075 } 076 builder.append("public class NewClass"); 077 if (null != this.baseClass) 078 builder.append("extends " + this.baseClass.getSimpleName()); 079 else 080 builder.append(" implements " + this.interfaceClass.getSimpleName()); 081 builder.append("{\n"); 082 c = 0; 083 builder.append("//methods thad need generated in new Class:\n"); 084 for (Method m : methodsNeedGenerated) { 085 builder.append("//[" + (++c) + "]\n").append(m.toGenericString()).append("{}\n"); 086 } 087 builder.append("}\n"); 088 return builder.toString(); 089 } 090 091 @Override 092 public boolean compile() { 093 boolean compileOk = false; 094 try { 095 if (super.compile()) { 096 Service service = AnnotationUtils.getServiceAnnotation(interfaceClass); 097// if (null != service) 098// addImportedClass(service.genericTypeClasses()); 099 addImportedClass(interfaceClass); 100 serviceInfo = new ServiceInfo(service); 101// method2PortMap = createMap(); 102 compileOk = true; 103 } 104 } catch (AnnotationException e) { 105 logger.error(e.toString()); 106 } catch (AnnotationRuntimeException e) { 107 logger.error(e.toString()); 108 } /*catch (DuplicatedNameMethodException e) { 109 logger.error(e.toString()); 110 } catch (NoSuchMethodException e) { 111 logger.error(e.toString()); 112 }*/ 113 return compileOk; 114 } 115 116 protected Map<Method, Method> createMethod2PortMapMap() throws NoSuchMethodException { 117 ServicePort portDesc; 118 String portName; 119 java.lang.reflect.Method portMethod; 120 Map<Method, Method> method2PortMap = new HashMap<Method, Method>(); 121 String portPrefix = serviceInfo.getPortPrefix(); 122 Method m; 123 StringBuilder builder; 124 for (Method method : methodsNeedGenerated) { 125 builder=new StringBuilder(portPrefix); 126 try { 127 if (needImpl(method)) { 128 Remote remoteAnnotation = getRemoteAnnotation(method); 129 m = getPrimitiveMethod(refClass, method); 130 portDesc = m.getAnnotation(ServicePort.class); 131 if (portDesc != null){ 132 String suffix = method.getName().substring(remoteAnnotation.primtiveName().length()); 133 builder.append(remoteAnnotation.primtiveName()).append(portDesc.suffix()).append(suffix); 134 } 135 else 136 builder.append(method.getName()); 137 }else{ 138 portDesc = method.getAnnotation(ServicePort.class); 139 builder.append(method.getName()); 140 if (portDesc != null) 141 builder.append(portDesc.suffix()); 142 } 143 } catch (MethodException e) { 144 throw new RuntimeException(e); 145 } 146 portName = builder.toString(); 147 if ((portMethod = servicePorts.get(portName)) == null) 148 throw new NoSuchMethodException(String.format("not found webservice port %s for method %s ", portName, 149 method.getDocSignature())); 150 method2PortMap.put(method, new Method(portMethod, getPortParameterNames(portMethod))); 151 } 152 return method2PortMap; 153 } 154 155 /** 156 * 157 * @param method 接口中的方法 158 * @return Servcie Class中对应的方法 159 */ 160 protected java.lang.reflect.Method getServicePort(Method method) { 161 ServicePort portDesc; 162 String portName; 163 String portPrefix = serviceInfo.getPortPrefix(); 164 StringBuilder builder; 165 builder=new StringBuilder(portPrefix); 166 try { 167 if (needImpl(method)) { 168 Remote remoteAnnotation = getRemoteAnnotation(method); 169 Method m = getPrimitiveMethod(refClass, method); 170 portDesc = m.getAnnotation(ServicePort.class); 171 if (portDesc != null){ 172 String suffix = method.getName().substring(remoteAnnotation.primtiveName().length()); 173 builder.append(remoteAnnotation.primtiveName()).append(portDesc.suffix()).append(suffix); 174 } 175 else 176 builder.append(method.getName()); 177 }else{ 178 portDesc = method.getAnnotation(ServicePort.class); 179 builder.append(method.getName()); 180 if (portDesc != null) 181 builder.append(portDesc.suffix()); 182 } 183 } catch (MethodException e) { 184 throw new RuntimeException(e); 185 } 186 portName = builder.toString(); 187 return servicePorts.get(portName); 188 } 189 190 private final String[] getPortParameterNames(java.lang.reflect.Method portMethod) throws NoSuchMethodException { 191 return serviceParamTable.getParameterNames(portMethod.getName(), portMethod.getParameterTypes()); 192 } 193 protected final Map<String, java.lang.reflect.Method> getServicePorts(Class<?> serviceClass) 194 throws DuplicatedNameMethodException { 195 java.lang.reflect.Method[] methods = serviceClass.getDeclaredMethods(); 196 Map<String, java.lang.reflect.Method> servicePorts = new HashMap<String, java.lang.reflect.Method>( 197 methods.length << 1); 198 int modifier ; 199 for (java.lang.reflect.Method method : methods) { 200 modifier=method.getModifiers(); 201 if(Modifier.isPublic(modifier)){ 202 if (servicePorts.keySet().contains(method.getName())) 203 throw new DuplicatedNameMethodException(serviceClass, method.getName()); 204 servicePorts.put(method.getName(), method); 205 } 206 } 207 return servicePorts; 208 } 209 210 /** 211 * @return serviceInfo 212 */ 213 public ServiceInfo getServiceInfo() { 214 return serviceInfo; 215 } 216 217 /** 218 * @return method2PortMap 219 */ 220 public Map<Method, Method> getMethod2PortMap() { 221 return method2PortMap; 222 } 223 224 /** 225 * @return serviceClass 226 */ 227 public Class<?> getServiceClass() { 228 return serviceClass; 229 } 230 public boolean isServiceRuntime(Class<?> exp){ 231 return ServiceRuntime.class.isAssignableFrom(exp); 232 } 233 public boolean needImpl(Method method){ 234 return getRemoteAnnotation(method)!=null; 235 } 236 public boolean needImpl(java.lang.reflect.Method method){ 237 return getRemoteAnnotation(method)!=null; 238 } 239 public Remote getRemoteAnnotation(Method method){ 240 return method.getAnnotation(Remote.class); 241 } 242 public Remote getRemoteAnnotation(java.lang.reflect.Method method){ 243 return method.getAnnotation(Remote.class); 244 } 245 246 public boolean isGenericTypeClass(Method method, Class<?> parameterType) { 247 Remote remoteAnnotation = getRemoteAnnotation(method); 248 return serviceInfo.getBridgeType() == String.class 249 && remoteAnnotation != null 250 && remoteAnnotation.value() 251 && remoteAnnotation.genericTypeClass() == parameterType; 252 } 253 254 public Method getPrimitiveMethod(Class<?> from,Method deriveMethod) throws MethodException { 255 Remote remoteAnnotation = getRemoteAnnotation(deriveMethod); 256 return getMatchedGenericMethod(from, deriveMethod, serviceInfo.getTargetType(), remoteAnnotation.genericParam(), 257 remoteAnnotation.genericTypeClass(),remoteAnnotation.primtiveName()); 258 } 259}