github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/tplGenerateCode.gotpl (about) 1 <? 2 package kmgRpcJava 3 func tplGenerateCode(config *tplConfig) string { 4 ?> 5 package <?=config.OutPackageName?>; 6 7 import com.google.gson.Gson; 8 import com.google.gson.GsonBuilder; 9 import com.google.gson.JsonDeserializationContext; 10 import com.google.gson.JsonDeserializer; 11 import com.google.gson.JsonElement; 12 import com.google.gson.JsonParseException; 13 import com.google.gson.JsonPrimitive; 14 import com.google.gson.JsonSerializationContext; 15 import com.google.gson.JsonSerializer; 16 import com.google.gson.JsonSyntaxException; 17 18 import javax.crypto.Cipher; 19 import javax.crypto.spec.IvParameterSpec; 20 import javax.crypto.spec.SecretKeySpec; 21 import java.io.ByteArrayOutputStream; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.OutputStream; 25 import java.lang.reflect.Type; 26 import java.net.HttpURLConnection; 27 import java.net.URL; 28 import java.nio.charset.Charset; 29 import java.security.MessageDigest; 30 import java.security.SecureRandom; 31 import java.util.Arrays; 32 import java.util.Calendar; 33 import java.util.Date; 34 import java.util.List; 35 import java.util.SimpleTimeZone; 36 import java.util.TimeZone; 37 import java.util.zip.Deflater; 38 import java.util.zip.Inflater; 39 40 /* 41 example: 42 RpcDemo.ConfigDefaultClient("http://127.0.0.1:34567","abc psk") // added in some init function. 43 String result = RpcDemo.GetDefaultClient().PostScoreInt("abc",1) // use the rpc everywhere. 44 */ 45 46 public class <?=config.ClassName ?> { 47 //类型列表 48 <?for _,innerClass:=range config.InnerClassList{ ?> 49 <?=innerClass.tplInnerClass()?> 50 <? } ?> 51 52 public static class Client{ 53 // 所有Api列表 54 <?for _,api:=range config.ApiList{ ?> 55 <?=api.tplApiClient()?> 56 <? } ?> 57 58 59 //引入的不会变的库代码.还需要com.google.gson 这个package的依赖 60 public String RemoteUrl; 61 public byte[] Psk; 62 private <T> T sendRequest(String apiName,Object reqData,Class<T> tClass) throws Exception{ 63 String inDataString = kmgJson.MarshalToString(reqData); // UTF8? 啥编码? 64 if (apiName.length()>255){ 65 throw new Exception("len(apiName)>255"); 66 } 67 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 68 baos.write(apiName.length()); 69 baos.write(KmgString.StringToArrayByte(apiName)); 70 baos.write(KmgString.StringToArrayByte(inDataString)); 71 byte[] inByte = baos.toByteArray(); 72 if (this.Psk!=null){ 73 inByte = kmgCrypto.CompressAndEncryptBytesEncodeV2(this.Psk, inByte); 74 } 75 byte[] outBytes = kmgHttp.SimplePost(this.RemoteUrl, inByte); 76 outBytes = kmgCrypto.CompressAndEncryptBytesDecodeV2(this.Psk, outBytes); 77 if (outBytes.length==0){ 78 throw new Exception("outBytes.length==0"); 79 } 80 String AfterString = KmgString.ArrayByteToString(Arrays.copyOfRange(outBytes,1,outBytes.length)); 81 if (outBytes[0]==1){ //error 82 throw new Exception(AfterString); 83 }else if (outBytes[0]==2) { //success 84 return kmgJson.UnmarshalFromString(AfterString, tClass); 85 } 86 throw new Exception("httpjsonApi protocol error 1 "+outBytes[0]); 87 } 88 } 89 public static void ConfigDefaultClient(String RemoteUrl,String pskStr){ 90 defaultClient = new Client(); 91 defaultClient.RemoteUrl = RemoteUrl; 92 defaultClient.Psk = kmgCrypto.Get32PskFromString(pskStr); 93 } 94 private static Client defaultClient; 95 public static Client GetDefaultClient(){ 96 return defaultClient; 97 } 98 public static class KmgString{ 99 public static final Charset UTF_8 = Charset.forName("UTF-8"); 100 public static byte[] StringToArrayByte(String str){ 101 return str.getBytes(UTF_8); 102 } 103 public static String ArrayByteToString(byte[] bytes){ 104 return new String(bytes, UTF_8); 105 } 106 } 107 public static class kmgBytes { 108 public static byte[] Slice(byte[] in,int start,int end){ 109 return Arrays.copyOfRange(in,start,end); 110 } 111 } 112 public static class kmgIo { 113 private static final int EOF = -1; 114 public static byte[] InputStreamReadAll(final InputStream input) throws IOException { 115 final ByteArrayOutputStream output = new ByteArrayOutputStream(); 116 copy(input, output); 117 return output.toByteArray(); 118 } 119 public static int copy(final InputStream input, final OutputStream output) throws IOException { 120 final long count = copyLarge(input, output,new byte[8192]); 121 if (count > Integer.MAX_VALUE) { 122 return -1; 123 } 124 return (int) count; 125 } 126 public static long copyLarge(final InputStream input, final OutputStream output, final byte[] buffer) 127 throws IOException { 128 long count = 0; 129 int n = 0; 130 while (EOF != (n = input.read(buffer))) { 131 output.write(buffer, 0, n); 132 count += n; 133 } 134 return count; 135 } 136 } 137 public static class kmgHttp { 138 public static byte[] SimplePost(String urls,byte[] inByte) throws Exception{ 139 System.setProperty("http.keepAlive", "false"); 140 URL url = new URL(urls); 141 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 142 conn.setRequestMethod("POST"); 143 conn.setRequestProperty("Content-Type", "image/jpeg"); 144 conn.setUseCaches(false); 145 conn.setDoInput(true); 146 conn.setDoOutput(true); 147 conn.setReadTimeout(10000); 148 conn.setConnectTimeout(5000); 149 OutputStream os = conn.getOutputStream(); 150 os.write(inByte); 151 os.flush(); 152 os.close(); 153 InputStream is; 154 if (conn.getResponseCode()==200){ 155 is = conn.getInputStream(); 156 }else{ 157 is = conn.getErrorStream(); 158 } 159 byte[] outByte = kmgIo.InputStreamReadAll(is); 160 is.close(); 161 return outByte; 162 } 163 } 164 public static class kmgCrypto { 165 private static byte[] magicCode4 = new byte[]{(byte)0xa7,(byte)0x97,0x6d,0x15}; 166 // key lenth 32 167 public static byte[] CompressAndEncryptBytesEncodeV2(byte[] key,byte[] data) throws Exception{ 168 data = compressV2(data); 169 byte[] cbcIv = KmgRand.MustCryptoRandBytes(16); 170 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 171 buf.write(data); 172 buf.write(magicCode4); 173 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); 174 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(cbcIv)); 175 byte[] encrypted = cipher.doFinal(buf.toByteArray()); 176 buf = new ByteArrayOutputStream(); 177 buf.write(cbcIv); 178 buf.write(encrypted); 179 return buf.toByteArray(); 180 } 181 // key lenth 32 182 public static byte[] CompressAndEncryptBytesDecodeV2(byte[] key,byte[] data) throws Exception { 183 if (data.length < 21) { 184 throw new Exception("[kmgCrypto.CompressAndEncryptBytesDecode] input data too small"); 185 } 186 byte[] cbcIv = kmgBytes.Slice(data, 0, 16); 187 byte[] encrypted = kmgBytes.Slice(data, 16, data.length); 188 Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); 189 cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(cbcIv)); 190 byte[] decrypted = cipher.doFinal(encrypted); 191 byte[] compressed = kmgBytes.Slice(decrypted, 0, decrypted.length - 4); 192 if (!Arrays.equals(magicCode4, kmgBytes.Slice(decrypted, decrypted.length - 4, decrypted.length))){ 193 throw new Exception("[kmgCrypto.CompressAndEncryptBytesDecode] magicCode not match"); 194 } 195 return uncompressV2(compressed); 196 } 197 private static byte[] compressV2(byte[] data) throws Exception{ 198 byte[] outData = kmgCompress.ZlibMustCompress(data); 199 if (outData.length>=data.length){ 200 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 201 buf.write(0); 202 buf.write(data); 203 return buf.toByteArray(); 204 }else{ 205 ByteArrayOutputStream buf = new ByteArrayOutputStream(); 206 buf.write(1); 207 buf.write(outData); 208 return buf.toByteArray(); 209 } 210 } 211 private static byte[] uncompressV2(byte[] data) throws Exception{ 212 if (data.length==0){ 213 throw new Exception("[uncopressV2] len(inData)==0"); 214 } 215 if (data[0]==0){ 216 return kmgBytes.Slice(data, 1, data.length); 217 } 218 return kmgCompress.ZlibUnCompress(kmgBytes.Slice(data, 1, data.length)); 219 } 220 public static byte[] Sha512Sum(byte[] data) { 221 try { 222 MessageDigest sh = MessageDigest.getInstance("SHA-512"); 223 sh.update(data); 224 return sh.digest(); 225 }catch(Exception e){ 226 System.out.println(e.getMessage()); 227 e.printStackTrace(); 228 } 229 return null; 230 } 231 public static byte[] Get32PskFromString(String s){ 232 return kmgBytes.Slice(kmgCrypto.Sha512Sum(KmgString.StringToArrayByte(s)), 0, 32); 233 } 234 } 235 public static class kmgCompress { 236 public static byte[] ZlibMustCompress(byte[] inB){ 237 Deflater deflater = new Deflater(); 238 deflater.setInput(inB); 239 deflater.finish(); 240 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 241 byte[] buf = new byte[8192]; 242 while (!deflater.finished()) { 243 int byteCount = deflater.deflate(buf); 244 baos.write(buf, 0, byteCount); 245 } 246 deflater.end(); 247 byte[] out = baos.toByteArray(); 248 return out; 249 } 250 public static byte[] ZlibUnCompress(byte[] inB) throws Exception{ 251 Inflater deflater = new Inflater(); 252 deflater.setInput(inB); 253 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 254 byte[] buf = new byte[8192]; 255 while (!deflater.finished()) { 256 int byteCount = deflater.inflate(buf); 257 if (byteCount==0){ 258 break; 259 } 260 baos.write(buf, 0, byteCount); 261 } 262 deflater.end(); 263 return baos.toByteArray(); 264 } 265 } 266 public static class kmgSync { 267 public static class Once{ 268 private Object locker = new Object(); 269 private boolean isInit = false; 270 public void Do(Runnable f){ 271 synchronized (locker){ 272 if (isInit){ 273 return; 274 } 275 f.run(); 276 isInit = true; 277 } 278 } 279 } 280 } 281 public static class kmgJson { 282 public static String MarshalToString(Object data){ 283 return getGson().toJson(data); 284 } 285 public static<T> T UnmarshalFromString(String s,Class<T> t) throws JsonSyntaxException { 286 if (t==void.class){ 287 return null; 288 } 289 return getGson().fromJson(s,t); 290 } 291 private static Gson gson; 292 private static kmgSync.Once gsonOnce = new kmgSync.Once(); 293 private static Gson getGson(){ 294 gsonOnce.Do(new Runnable() { 295 @Override 296 public void run() { 297 JsonSerializer<Date> ser = new JsonSerializer<Date>() { 298 @Override 299 public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext 300 context) { 301 if (src == null) { 302 return null; 303 } else { 304 return new JsonPrimitive(KmgTime.FormatGolangDate(src)); 305 } 306 } 307 }; 308 JsonDeserializer<Date> deser = new JsonDeserializer<Date>() { 309 @Override 310 public Date deserialize(JsonElement json, Type typeOfT, 311 JsonDeserializationContext context) throws JsonParseException { 312 if (json == null) { 313 return null; 314 } else { 315 try { 316 return KmgTime.ParseGolangDate(json.getAsString()); 317 } catch (Exception e) { 318 throw new JsonParseException(e.getMessage()); 319 } 320 } 321 } 322 }; 323 gson = new GsonBuilder() 324 .registerTypeAdapter(Date.class, ser) 325 .registerTypeAdapter(Date.class, deser).create(); 326 } 327 }); 328 return gson; 329 } 330 } 331 public static class KmgRand{ 332 public static byte[] MustCryptoRandBytes(int length) { 333 SecureRandom sr = new SecureRandom(); 334 byte[] output = new byte[length]; 335 sr.nextBytes(output); 336 return output; 337 } 338 } 339 public static class KmgTime{ 340 public static Date ParseGolangDate(String st) throws Exception{ 341 Calendar cal = Calendar.getInstance(); 342 int year = Integer.parseInt(st.substring(0, 4)); 343 int month = Integer.parseInt(st.substring(5,7)); 344 int day = Integer.parseInt(st.substring(8,10)); 345 int hour = Integer.parseInt(st.substring(11, 13)); 346 int minute = Integer.parseInt(st.substring(14,16)); 347 int second = Integer.parseInt(st.substring(17,19)); 348 float nonaSecond = 0; 349 int tzStartPos = 19; 350 if (st.charAt(19)=='.'){ 351 // 从19开始找到第一个不是数字的字符串. 352 for (;;){ 353 tzStartPos++; 354 if (st.length()<=tzStartPos){ 355 throw new Exception("can not parse "+st); 356 } 357 char thisChar = st.charAt(tzStartPos); 358 if (thisChar>='0' && thisChar<='9'){ 359 }else{ 360 break; 361 } 362 } 363 nonaSecond = Float.parseFloat("0." + st.substring(20, tzStartPos)); 364 } 365 cal.set(Calendar.MILLISECOND,(int)(nonaSecond*1e3)); 366 char tzStart = st.charAt(tzStartPos); 367 if (tzStart=='Z'){ 368 cal.setTimeZone(TimeZone.getTimeZone("UTC")); 369 }else { 370 int tzHour = Integer.parseInt(st.substring(tzStartPos+1,tzStartPos+3)); 371 int tzMin = Integer.parseInt(st.substring(tzStartPos+4,tzStartPos+6)); 372 int tzOffset = tzHour*3600*1000 + tzMin * 60*1000; 373 if (tzStart=='-'){ 374 tzOffset = - tzOffset; 375 } 376 TimeZone tz = new SimpleTimeZone(tzOffset,""); 377 cal.setTimeZone(tz); 378 } 379 cal.set(year,month-1,day,hour,minute,second); 380 return cal.getTime(); 381 } 382 public static String FormatGolangDate(Date date){ 383 Calendar cal = Calendar.getInstance(); 384 cal.setTime(date); 385 StringBuilder buf = new StringBuilder(); 386 formatYear(cal,buf); 387 buf.append('-'); 388 formatMonth(cal, buf); 389 buf.append('-'); 390 formatDays(cal, buf); 391 buf.append('T'); 392 formatHours(cal, buf); 393 buf.append(':'); 394 formatMinutes(cal, buf); 395 buf.append(':'); 396 formatSeconds(cal,buf); 397 formatTimeZone(cal,buf); 398 return buf.toString(); 399 } 400 private static void formatYear(Calendar cal, StringBuilder buf) { 401 int year = cal.get(Calendar.YEAR); 402 String s; 403 if (year <= 0) // negative value 404 { 405 s = Integer.toString(1 - year); 406 } else // positive value 407 { 408 s = Integer.toString(year); 409 } 410 while (s.length() < 4) { 411 s = '0' + s; 412 } 413 if (year <= 0) { 414 s = '-' + s; 415 } 416 buf.append(s); 417 } 418 private static void formatMonth(Calendar cal, StringBuilder buf) { 419 formatTwoDigits(cal.get(Calendar.MONTH) + 1, buf); 420 } 421 private static void formatDays(Calendar cal, StringBuilder buf) { 422 formatTwoDigits(cal.get(Calendar.DAY_OF_MONTH), buf); 423 } 424 private static void formatHours(Calendar cal, StringBuilder buf) { 425 formatTwoDigits(cal.get(Calendar.HOUR_OF_DAY), buf); 426 } 427 private static void formatMinutes(Calendar cal, StringBuilder buf) { 428 formatTwoDigits(cal.get(Calendar.MINUTE), buf); 429 } 430 private static void formatSeconds(Calendar cal, StringBuilder buf) { 431 formatTwoDigits(cal.get(Calendar.SECOND), buf); 432 if (cal.isSet(Calendar.MILLISECOND)) { // milliseconds 433 int n = cal.get(Calendar.MILLISECOND); 434 if (n != 0) { 435 String ms = Integer.toString(n); 436 while (ms.length() < 3) { 437 ms = '0' + ms; // left 0 paddings. 438 } 439 buf.append('.'); 440 buf.append(ms); 441 } 442 } 443 } 444 /** formats time zone specifier. */ 445 private static void formatTimeZone(Calendar cal, StringBuilder buf) { 446 TimeZone tz = cal.getTimeZone(); 447 if (tz == null) { 448 return; 449 } 450 // otherwise print out normally. 451 int offset = tz.getOffset(cal.getTime().getTime()); 452 if (offset == 0) { 453 buf.append('Z'); 454 return; 455 } 456 if (offset >= 0) { 457 buf.append('+'); 458 } else { 459 buf.append('-'); 460 offset *= -1; 461 } 462 offset /= 60 * 1000; // offset is in milli-seconds 463 formatTwoDigits(offset / 60, buf); 464 buf.append(':'); 465 formatTwoDigits(offset % 60, buf); 466 } 467 /** formats Integer into two-character-wide string. */ 468 private static void formatTwoDigits(int n, StringBuilder buf) { 469 // n is always non-negative. 470 if (n < 10) { 471 buf.append('0'); 472 } 473 buf.append(n); 474 } 475 } 476 } 477 478 479 <? } ?> 480