PHPRPC 2.1 的 Java 客户端实现

原创作品,转载请注明出处。

这个 Java 客户端版本在 J2SE SDK 1.3.1 和更高版本下编译通过,更低版本的 JDK 没有找到,所以没有测试能不能用。这个客户端不仅可以用在 JSP 中,在任何 J2SE 程序中都可以使用。该客户端实现的是同步调用,支持设置代理服务器,支持引用参数传递,服务器端输出重定向,加密传输等功能。调用远程方法使用 invoke 方法,第一个参数为远程过程名,第二个参数为远程过程的参数的数组。第三个参数表示是否是引用传递(可选,默认为非引用传递)。

PHPRPCError.java
  1. /**
  2. * @author      Ma Bingyao(andot@ujn.edu.cn)
  3. * @copyright   CoolCode.CN
  4. * @package     JAVA_PHPRPC_CLIENT
  5. * @version     2.1
  6. * @last_update 2006-08-09
  7. * @link        http://www.coolcode.cn/?p=205
  8. */
  9.  
  10. package org.phprpc;
  11.  
  12.  
  13. import java.lang.*;
  14.  
  15.  
  16. public class PHPRPCError extends Exception {
  17.     private int __errno;
  18.     private String __errstr;
  19.     protected PHPRPCError(int errno, String errstr)
  20.     {
  21.         this.__errno = errno;
  22.         this.__errstr = errstr;
  23.     }
  24.     public int getNumber() {
  25.         return this.__errno;
  26.     }
  27.     public String getMessage() {
  28.         return this.__errstr;
  29.     }
  30.     public String toString() {
  31.         return this.__errno + ":" + this.__errstr;
  32.     }
  33. }
PHPRPCClient.java
  1. /**
  2. * @author      Ma Bingyao(andot@ujn.edu.cn)
  3. * @copyright   CoolCode.CN
  4. * @package     JAVA_PHPRPC_CLIENT
  5. * @version     2.1
  6. * @last_update 2006-08-09
  7. * @link        http://www.coolcode.cn/?p=205
  8. *
  9. * Example usage:
  10.  
  11. import java.lang.*;
  12. import org.phprpc.*;
  13.  
  14. public class SinTest
  15. {
  16.     public static void main(String[] args) {
  17.         PHPRPCClient rpc = new PHPRPCClient();
  18.         rpc.useService("http://localhost:8080/phprpc_2.1/sample/server.jsp", true);
  19.         rpc.setEncrypt(2);
  20.         System.out.println(rpc.invoke("sin", new Double(args[0])));
  21.    }
  22. }
  23.  
  24. *
  25. */
  26.  
  27. package org.phprpc;
  28.  
  29.  
  30. import java.lang.*;
  31. import java.io.*;
  32. import java.util.*;
  33. import java.math.*;
  34. import java.net.*;
  35. import org.phprpc.util.*;
  36.  
  37.  
  38. public class PHPRPCClient {
  39.     private String __uri;
  40.     private String __charset;
  41.     private String __cookies;
  42.     private String __output;
  43.     private byte __encrypt;
  44.     private PHPRPCError __warning;
  45.     private byte[] __key;
  46.     private HashMap __proxy = null;
  47.     private String __user;
  48.     private String __pass;
  49.  
  50.     public PHPRPCClient() {
  51.         this.__uri = null;
  52.         this.__proxy = null;
  53.         this.__encrypt = 0;
  54.         this.__user = null;
  55.         this.__pass = null;
  56.     }
  57.  
  58.     public String getOutput() {
  59.         return __output;
  60.     }
  61.  
  62.     public byte getEncrypt() {
  63.         return __encrypt;
  64.     }
  65.  
  66.     public void setEncrypt(int value) {
  67.         __encrypt = (byte)value;
  68.     }
  69.  
  70.     public PHPRPCError getWarning() {
  71.         return __warning;
  72.     }
  73.  
  74.     public void setProxy(String host, int port) {
  75.         this.__proxy = new HashMap();
  76.         this.__proxy.put("host", host);
  77.         this.__proxy.put("port", new Integer(port));
  78.     }
  79.  
  80.     public void setProxy(String host, int port, String user, String pass) {
  81.         this.__proxy = new HashMap();
  82.         this.__proxy.put("host", host);
  83.         this.__proxy.put("port", new Integer(port));
  84.         this.__proxy.put("user", user);
  85.         this.__proxy.put("pass", pass);
  86.     }
  87.  
  88.     public void setProxy(HashMap proxy) {
  89.         this.__proxy = proxy;
  90.     }
  91.  
  92.     public void setAuth(String user, String pass) {
  93.         this.__user = user;
  94.         this.__pass = pass;
  95.     }
  96.  
  97.     public boolean useService(String requestUriString) throws IOException, IllegalAccessException {
  98.         return useService(requestUriString, false);
  99.     }
  100.  
  101.     public boolean useService(String requestUriString, boolean encrypt) throws IOException, IllegalAccessException {
  102.         this.__uri = requestUriString;
  103.         this.__warning = null;
  104.         this.__output = "";
  105.         this.__cookies = null;
  106.         this.__charset = null;
  107.         this.__key = null;
  108.         if (encrypt) {
  109.             return SwitchKey();
  110.         } else {
  111.             Socket socket = this.__request("", "GET");
  112.             InputStream is = socket.getInputStream();
  113.             HashMap header = new HashMap();
  114.             this.__getContent(is, header, null);
  115.             is.close();
  116.             socket.close();
  117.             this.__charset = this.__getCharset(header);
  118.             return true;
  119.         }
  120.     }
  121.  
  122.     private String __getCharset(HashMap header) {
  123.         if (header.containsKey("Content-Type")) {
  124.             String charset = (String)header.get("Content-Type");
  125.             if (charset.startsWith("text/plain; charset=")) {
  126.                 return charset.substring(20);
  127.             }
  128.         }
  129.         return "UTF-8";
  130.     }
  131.  
  132.     private String __getCookies(HashMap header) {
  133.         if (header.containsKey("Set-Cookie")) {
  134.             String cookies = (String)header.get("Set-Cookie");
  135.             int pos1, pos2;
  136.             pos1 = cookies.indexOf("path=");
  137.             if (pos1 > -1) {
  138.                 pos2 = cookies.indexOf(";", pos1);
  139.                 if (pos2 == -1) {
  140.                     pos2 = cookies.length();
  141.                 } else {
  142.                     pos2++;
  143.                 }
  144.                 cookies = (new StringBuffer(cookies)).delete(pos1, pos2).toString();
  145.             }
  146.             pos1 = cookies.indexOf("domain=");
  147.             if (pos1 > -1) {
  148.                 pos2 = cookies.indexOf(";", pos1);
  149.                 if (pos2 == -1) {
  150.                     pos2 = cookies.length();
  151.                 } else {
  152.                     pos2++;
  153.                 }
  154.                 cookies = (new StringBuffer(cookies)).delete(pos1, pos2).toString();
  155.             }
  156.             return cookies;
  157.         } else {
  158.             return null;
  159.         }
  160.     }
  161.  
  162.     private Socket __request(String requestString, String method) throws IOException {
  163.         URL url = new URL(this.__uri);
  164.         String host = url.getHost();
  165.         int port = url.getPort();
  166.         if (port == -1) {
  167.             port = 80;
  168.         }
  169.         Socket socket;
  170.         try {
  171.             if (this.__proxy != null) {
  172.                 socket = new Socket((String)(this.__proxy.get("host")), ((Integer)(this.__proxy.get("port"))).intValue());
  173.             } else {
  174.                 socket = new Socket(host , port);
  175.             }
  176.         } catch (Exception e) {
  177.             return null;
  178.         }
  179.         String proxy = "";
  180.         if (this.__proxy != null) {
  181.             proxy = "Proxy-Connection: Keep-Alive\r\n";
  182.             if (this.__proxy.containsKey("user") && this.__proxy.containsKey("pass")) {
  183.                 proxy += "Proxy-Authorization: Basic " +
  184.                     Base64.encode(((String)(this.__proxy.get("user")) + ":" + (String)(this.__proxy.get("pass"))).getBytes()) +
  185.                     "\r\n";
  186.             }
  187.         }
  188.         String auth = "";
  189.         if (this.__user != null && this.__pass != null) {
  190.             auth = "Authorization: Basic " + Base64.encode((this.__user + ":" + this.__pass).getBytes()) + "\r\n";
  191.         }
  192.         String cookie = "";
  193.         if (this.__cookies != null) {
  194.             cookie = "Cookie: " + this.__cookies + "\r\n";
  195.         }
  196.         OutputStream os = socket.getOutputStream();
  197.         String httpHead;
  198.         if (method.toUpperCase().equals("GET")) {
  199.             httpHead = "GET " + url.toString() + "?" + requestString + " HTTP/1.0\r\n" +
  200.                 "User-Agent: PHPRPC Client/2.1\r\n" +
  201.                 "Host: " + host + ":" + port + "\r\n" +
  202.                 proxy + auth + cookie +
  203.                 "\r\n";
  204.             os.write(httpHead.getBytes());
  205.         } else {
  206.             byte[] content = requestString.getBytes(this.__charset);
  207.             httpHead = "POST " + url.toString() + " HTTP/1.0\r\n" +
  208.                 "User-Agent: PHPRPC Client/2.1\r\n" +
  209.                 "Host: " + host + ":" + port + "\r\n" +
  210.                 proxy + auth + cookie +
  211.                 "Content-Type: application/x-www-form-urlencoded; charset=" + this.__charset + "\r\n" +
  212.                 "Content-Length: " + content.length + "\r\n" +
  213.                 "\r\n";
  214.             os.write(httpHead.getBytes(this.__charset));
  215.             os.write(content);
  216.         }
  217.         return socket;
  218.     }
  219.  
  220.     private void __getContent(InputStream is, HashMap header, HashMap body) throws IOException {
  221.         BufferedReader in = new BufferedReader(new InputStreamReader(is, "UTF-8"));
  222.         String buf;
  223.         while ((buf = in.readLine()) != null) {
  224.             if (buf.equals("")) break;
  225.             if (buf.startsWith("HTTP/")) {
  226.                 header.put("Version", buf.substring(5, 8));
  227.                 header.put("StatusCode", buf.substring(9, 12));
  228.                 header.put("Status", buf.substring(13));
  229.             } else {
  230.                 int pos = buf.indexOf(": ");
  231.                 if (pos > -1) {
  232.                     header.put(buf.substring(0, pos), buf.substring(pos + 2));
  233.                 }
  234.             }
  235.         }
  236.         if (body == null) return;
  237.         while ((buf = in.readLine()) != null) {
  238.             int pos = buf.indexOf("=");
  239.             if (pos == -1) break;
  240.             if (buf.charAt(pos + 1) == '"') {
  241.                 body.put(buf.substring(0, pos), buf.substring(pos + 2, buf.length() - 2));
  242.             } else {
  243.                 body.put(buf.substring(0, pos), buf.substring(pos + 1, buf.length() - 1));
  244.             }
  245.         }
  246.     }
  247.  
  248.     private boolean SwitchKey() throws IOException, IllegalAccessException {
  249.         Socket socket = this.__request("phprpc_encrypt=true", "GET");
  250.         InputStream is = socket.getInputStream();
  251.         HashMap header = new HashMap();
  252.         HashMap body = new HashMap();
  253.         this.__getContent(is, header, body);
  254.         this.__charset = this.__getCharset(header);
  255.         this.__cookies = this.__getCookies(header);
  256.         is.close();
  257.         socket.close();
  258.         if (body.containsKey("phprpc_encrypt")) {
  259.             HashMap kp = (HashMap)PHPSerializer.unserialize(Base64.decode((String)(body.get("phprpc_encrypt"))), this.__charset);
  260.             BigInteger p = new BigInteger((String)kp.get("p"));
  261.             BigInteger g = new BigInteger((String)kp.get("g"));
  262.             BigInteger y = new BigInteger((String)kp.get("y"));
  263.             BigInteger x = new BigInteger(127, new Random());
  264.             this.__key = new byte[16];
  265.             byte[] key = y.modPow(x, p).toByteArray();
  266.             for (int i = 1, n = Math.min(key.length, 16); i <= n; i++) {
  267.                 this.__key[16 - i] = key[key.length - i];
  268.             }
  269.             this.__request("phprpc_encrypt=" + g.modPow(x, p).toString(), "GET").close();
  270.             return true;
  271.         } else {
  272.             this.__warning = new PHPRPCError(2, "PHPRPC Server can't support encrypt");
  273.             return false;
  274.         }
  275.     }
  276.  
  277.     private void setWarning(String errno, String errstr) {
  278.         int number = Integer.parseInt(errno);
  279.         if (number != 0) {
  280.             try {
  281.                 this.__warning = new PHPRPCError(number, new String(Base64.decode(errstr), this.__charset));
  282.             } catch (Exception e) { }
  283.         }
  284.     }
  285.  
  286.     private void setOutput(String output) {
  287.         try {
  288.             this.__output = new String(Base64.decode(output), this.__charset);
  289.         } catch (Exception e) { }
  290.     }
  291.  
  292.     public Object invoke(String function, Object[] args) throws PHPRPCError, IOException, IllegalAccessException {
  293.         return this.invoke(function, args, false);
  294.     }
  295.  
  296.     public Object invoke(String function, Object[] args, boolean byref) throws PHPRPCError, IOException, IllegalAccessException {
  297.         StringBuffer sb = new StringBuffer();
  298.         sb.append("phprpc_func=");
  299.         sb.append(function);
  300.         if (args.length > 0) {
  301.             byte[] arguments = PHPSerializer.serialize(args);
  302.             if (this.__key != null && this.__encrypt > 0) {
  303.                 arguments = XXTEA.encrypt(arguments, this.__key);
  304.             }
  305.             sb.append("&phprpc_args=");
  306.             sb.append(URLEncoder.encode(Base64.encode(arguments)));
  307.             if (!byref) {
  308.                 sb.append("&phprpc_ref=false");
  309.             }
  310.         }
  311.         if (this.__key != null) {
  312.             sb.append("&phprpc_encrypt=");
  313.             sb.append(this.__encrypt);
  314.         }
  315.         Socket socket = this.__request(sb.toString(), "POST");
  316.         InputStream is = socket.getInputStream();
  317.         HashMap header = new HashMap();
  318.         HashMap body = new HashMap();
  319.         this.__getContent(is, header, body);
  320.         is.close();
  321.         socket.close();
  322.         this.__warning = null;
  323.         if (body.containsKey("phprpc_result")) {
  324.             byte[] result = Base64.decode((String)body.get("phprpc_result"));
  325.             byte[] arguments = null;
  326.             boolean has_args = body.containsKey("phprpc_args");
  327.             if (has_args) {
  328.                 arguments = Base64.decode((String)body.get("phprpc_args"));
  329.             }
  330.             this.setWarning((String)body.get("phprpc_errno"), (String)body.get("phprpc_errstr"));
  331.             this.setOutput((String)body.get("phprpc_output"));
  332.             if ((this.__key != null) && (this.__encrypt > 0)) {
  333.                 if (this.__encrypt > 1) {
  334.                     result = XXTEA.decrypt(result, this.__key);
  335.                 }
  336.                 if (has_args) {
  337.                     arguments = XXTEA.decrypt(arguments, this.__key);
  338.                 }
  339.             }
  340.             if (has_args) {
  341.                 Object[] refargs = (Object[])PHPSerializer.unserialize(arguments, (new Object[0]).getClass(), this.__charset);
  342.                 for (int i = 0; i < args.length; i++) {
  343.                     args[i] = refargs[i];
  344.                 }
  345.             }
  346.             return PHPSerializer.unserialize(result, this.__charset);
  347.         } else if (body.containsKey("phprpc_errno")) {
  348.             throw new PHPRPCError(Integer.parseInt((String)(body.get("phprpc_errno"))), new String(Base64.decode((String)(body.get("phprpc_errstr")))));
  349.         } else {
  350.             throw new PHPRPCError(1, "Wrong PHPRPC Server!");
  351.         }
  352.     }
  353. }

标签: Java, PHPRPC

« 上一篇 | 下一篇 »

只显示10条记录相关文章

发表评论

评论 (必须):