github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/java/src/testPackage/RpcDemo.java (about)

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