OpenConcerto

Dépôt officiel du code source de l'ERP OpenConcerto
sonarqube

svn://code.openconcerto.org/openconcerto

Rev

Blame | Last modification | View Log | RSS feed

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 * 
 * Copyright 2011-2019 OpenConcerto, by ILM Informatique. All rights reserved.
 * 
 * The contents of this file are subject to the terms of the GNU General Public License Version 3
 * only ("GPL"). You may not use this file except in compliance with the License. You can obtain a
 * copy of the License at http://www.gnu.org/licenses/gpl-3.0.html See the License for the specific
 * language governing permissions and limitations under the License.
 * 
 * When distributing the software, include this License Header Notice in each file.
 */
 
 package org.openconcerto.utils.jsonrpc;

import org.openconcerto.utils.Base64;
import org.openconcerto.utils.NetUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.HttpsURLConnection;

import net.minidev.json.JSONObject;
import net.minidev.json.JSONStyle;
import net.minidev.json.parser.JSONParser;
import net.minidev.json.parser.ParseException;

public class JSONRPCClient {
    private boolean trustAllContext;
    private String token;
    private String login;
    private String encodedPassword;

    public JSONRPCClient(boolean trustAllContext) {
        this.trustAllContext = trustAllContext;
    }

    public void setAuthToken(String token) {
        this.token = token;
    }

    /**
     * @param login : login
     * @param encodedPassword : Base64 encoded hash of the password
     */
    public void setCredentials(String login, String encodedPassword) {
        this.login = login;
        this.encodedPassword = encodedPassword;
    }

    public Object rpcCall(String url, String method, JSONObject params) throws IOException {
        final JSONObject request = new JSONObject();
        request.put("jsonrpc", "2.0");
        request.put("method", method);
        request.put("id", UUID.randomUUID().toString());
        request.put("params", params);

        final HttpURLConnection con;
        if (url.startsWith("https")) {
            HttpsURLConnection cons = (HttpsURLConnection) new URL(url).openConnection();
            if (this.trustAllContext) {
                try {
                    cons.setSSLSocketFactory(NetUtils.createTrustAllContext().getSocketFactory());
                    cons.setHostnameVerifier(NetUtils.HostnameNonVerifier);
                } catch (KeyManagementException | NoSuchAlgorithmException e1) {
                    throw new IOException(e1);
                }
            }
            con = cons;
        } else {
            con = (HttpURLConnection) new URL(url).openConnection();
        }
        con.setRequestProperty("Accept-Encoding", "gzip");
        con.setDoOutput(true);

        final String str = request.toJSONString(JSONStyle.NO_COMPRESS);

        final byte[] bytes = str.getBytes(StandardCharsets.UTF_8);

        con.setRequestProperty("Content-Type", "application/json; charset=utf-8");
        if (this.token != null) {
            con.setRequestProperty("Authorization", "Bearer " + this.token);
        } else {
            // X_LOGIN and X_PASSWORD_HASH are Base64 encoded
            if (this.login != null) {
                con.setRequestProperty("X_LOGIN", Base64.encodeBytes(this.login.getBytes(StandardCharsets.UTF_8)));
            }
            if (this.encodedPassword != null) {
                con.setRequestProperty("X_PASSWORD_HASH", this.encodedPassword);
            }
        }

        try (final OutputStream out = con.getOutputStream()) {
            out.write(bytes);
        }

        final JSONParser p = new JSONParser(JSONParser.MODE_PERMISSIVE);

        try (InputStream inputStream = "gzip".equals(con.getContentEncoding()) ? new GZIPInputStream(con.getInputStream()) : con.getInputStream()) {
            final JSONObject response = (JSONObject) p.parse(inputStream);
            if (response.containsKey("error")) {
                final JSONObject jsonObject = (JSONObject) response.get("error");
                if (jsonObject.getAsNumber("code").intValue() == -32601) {
                    throw new IOException("method not found on server :" + method + " code : " + jsonObject.getAsNumber("code") + " : " + jsonObject.getAsString("message"));
                } else {
                    throw new IOException("rpc call error, code : " + jsonObject.getAsNumber("code") + " : " + jsonObject.getAsString("message"));
                }
            }
            return response.get("result");
        } catch (final ParseException e) {
            throw new IOException(e);
        }

    }

}