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