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