guneysus
12/22/2014 - 9:10 AM

From https://www.drupal.org/node/1267522

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.XmlRpcRequest;
import org.apache.xmlrpc.client.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;


/**
 * Testing XML-RPC client with Drupal7.
 * This example uses xml-rpc with methodology for calling remote drupal functionality
 * as presented by "Services 3.X"
 * <p/>
 * For Xml-Rpc I use "org.apache.xmlrpc.client" library with depandencies <a href="http://ws.apache.org/xmlrpc/client.html">http://ws.apache.org/xmlrpc/client.html</a>.
 */
public class Drupal7XmlRpcClientTest {


    /**
     * Name of remote functions used by this example
     */
    public static final String METHOD_SYSTEM_CONNECT = "system.connect";
    public static final String METHOD_USER_LOGOUT = "user.logout";
    public static final String METHOD_USER_LOGIN = "user.login";
    public static final String METHOD_USER_CREATE = "user.create";
    public static final String METHOD_FILE_SAVE = "file.save";


    private Logger log = Logger.getLogger(Drupal7XmlRpcClientTest.class.getName());


    /**
     * Endpoint is defined within Drupal services module configuration in order to define
     * a URL that is avilable for serving a specific set of service calls. See drupal
     * documentation for "Services 3.X". <a href="http://drupal.org/node/783236">http://drupal.org/node/783236</a>
     */
    private final String endpointURL;


    /**
     * Xml-Rpc clinet object
     */
    private XmlRpcClient xmlRpcClient;


    /**
     * Cookie value create upon login. We provide it only as an info. User does not have to handle
     * setting of Cookie. Instead, the {@link #login} method do it upon successful login, and allow
     * any following service call, to be handled in the scope of the login user.
     *
     * @see #login(String, String)
     */
    private String cookie;


    /**
     * Initialize the XmlRpcClient client with basic configuration of endpoint URL.
     * The serviceURL must be a valid URL.
     *
     * @param endpointURL the URL of the Drupal service's endpoint. example: http://www.example.com/drupal/test_endpoint
     * @throws java.net.MalformedURLException if the serviceURL is not a URL
     */
    public Drupal7XmlRpcClientTest(String endpointURL) throws MalformedURLException {
        this.endpointURL = endpointURL;
        log.setLevel(Level.INFO);


        //create the Xml-Rpc clinet object.
        XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
        config.setServerURL(new URL(this.endpointURL));
        xmlRpcClient = new XmlRpcClient();
        xmlRpcClient.setConfig(config);
    }


    /**
     * Call system.connect
     *
     * @throws Exception if fail
     */
    public void connect() throws Exception {
        try {
            Map response = (Map) xmlRpcClient.execute(METHOD_SYSTEM_CONNECT, new Object[]{});
            log.info("Connected to server using SessionID: " + response.get("sessid"));
        } catch (Exception x) {
            throw new Exception("cannot connect to " + endpointURL + ": " + x.getMessage(), x);
        }
    }


    /**
     * Call user.login
     *
     * @param username user name
     * @param password password
     * @return Map with details of login user (response.get("user")) and login session-name   and session-id
     *         that are used internally to construct the Cookie used by following calls.
     * @throws Exception if operation fail
     */
    public Map login(String username, String password) throws Exception {
        // Add Login Paramaters
        Vector<Object> params = new Vector<Object>();
        params.add(username);
        params.add(password);
        Map response = (Map) xmlRpcClient.execute(METHOD_USER_LOGIN, params);


        //The user.login call return two attributes in which we use to construct value for a "Cookie" header.
        //With then set xmlRpcClient with new XmlRpcTransportFactory that set  'Cookie' header using the composed cookie value
        cookie = response.get("session_name") + "=" + response.get("sessid");
        XmlRpcTransportFactory factory = new XmlRpcSunHttpTransportFactory(xmlRpcClient) {
            public XmlRpcTransport getTransport() {
                return new XmlRpcSunHttpTransport(xmlRpcClient) {
                    @Override
                    protected void initHttpHeaders(XmlRpcRequest request) throws XmlRpcClientException {
                        super.initHttpHeaders(request);
                        setRequestHeader("Cookie", cookie);
                    }
                };
            }
        };
        xmlRpcClient.setTransportFactory(factory);


        return response;
    }


    /**
     * Call user.logout
     *
     * @throws Exception if operatino fail
     */
    public void logout() throws Exception {
        Vector<Object> params = new Vector<Object>();
        xmlRpcClient.execute(METHOD_USER_LOGOUT, params);
        log.info("Logout Sucessfull");
    }


    /**
     * Call user.create that is equivalent to user.register.
     * <p/>
     * On the server side this call handle user regitration by emulating user's registration form.
     * It means that basic fields 'name' , 'pass', 'mail' MUST be provided into and 'account' object
     * as well as all other Required custom fields. In this case there aretwo such custom fields required
     * per user registration: 'field_newsletter' and 'field_accept_terms'
     * <p/>
     * Important note: on Drupal to 'pass' value provided by form is relevant only when login user is "admin"
     * by permissions or that user_email_verification is not set to TRUe
     * <pre>
     * Taken from "user.module" file:
     * <p/>
     * if (!variable_get('user_email_verification', TRUE) || $admin) {
     * $pass = $form_state['values']['pass'];
     * }
     * </pre>
     * <p/>
     * In short! if you plan to set custom password by xml-rpc call, make sure that login user is admin.
     *
     * @param name  name
     * @param pass  password
     * @param email email
     * @return Map with details of createduser
     * @throws org.apache.xmlrpc.XmlRpcException
     *          if operaton fail
     */
    public Map createUser(String name, String pass, String email) throws XmlRpcException {
        HashMap<String, Object> account = new HashMap<String, Object>();
        account.put("name", name);
        account.put("pass", pass);
        account.put("mail", email);
        account.put("status", "1"); //indicate if user will become active or not
        account.put("notify", "1"); //indicate ifnotification should be sent


        account.put("field_newsletter", prepareCheckboxValueParam("1")); //this is custom field
        account.put("field_accept_terms", prepareCheckboxValueParam("1")); //this is custom field


        // Add Login Paramaters
        Vector<Object> params = new Vector<Object>();
        params.add(account);


        log.info("Creating user");
        return (Map) xmlRpcClient.execute(METHOD_USER_CREATE, params);
    }


    /**
     * Checkbox value is set into 3-level associate array like data structure
     * <p/>
     * Example of what is expected in Drupal server-side for a custom field of type "checkbox"
     * <pre>
     * array(1) {
     *      ["und"]=> array(1) {
     *          [0]=> array(1) {
     *              ["value"]=> int([value])
     *          }
     *      }
     * }
     * </pre>
     *
     * @param value the value to cset for the checkbox - for example "1" or "0" depanding on field definition
     *              on the specific drupal applicationl
     * @return Map of params constructed for checkbox field
     */
    public static HashMap<String, HashMap> prepareCheckboxValueParam(String value) {
        HashMap<String, String> arr111 = new HashMap<String, String>();
        arr111.put("value", value);


        HashMap<String, HashMap> arr11 = new HashMap<String, HashMap>();
        arr11.put("0", arr111);


        HashMap<String, HashMap> arr1 = new HashMap<String, HashMap>();
        arr1.put("und", arr11);
        return arr1;
    }
public Map<String, Object> retrieveNode(int nid) throws XmlRpcException {
        HashMap<String, Object> node = new HashMap<String, Object>();
        node.put("nid", "" + nid);
        Vector<Object> params = new Vector<Object>();
        params.add(node);
        final String token = getToken(url);
        XmlRpcTransportFactory factory = new XmlRpcSunHttpTransportFactory(xmlRpcClient) {
            public XmlRpcTransport getTransport() {
                return new XmlRpcSunHttpTransport(xmlRpcClient) {
                    @Override
                    protected void initHttpHeaders(XmlRpcRequest request) throws XmlRpcClientException {
                        super.initHttpHeaders(request);
                        setRequestHeader("Cookie",cookie);
                        setRequestHeader("X-CSRF-Token",token);
                    }
                };
            }
        };
        xmlRpcClient.setTransportFactory(factory);
        Map<String, Object> response = (Map<String, Object>) xmlRpcClient.execute("node.retrieve", params);
        //get individual fields of the node
        String name = (String) response.get("title");
        String fieldValue = (String) getFieldData(response, "field_myfield");
        
        return response;
    }

public String getToken(String urlToRead) {
      URL url;
      HttpURLConnection conn;
      BufferedReader rd;
      String line;
      String result = "";
      try {
         url = new URL(urlToRead);
         conn = (HttpURLConnection) url.openConnection();
         conn.setRequestProperty("Cookie", cookie);
         conn.setRequestMethod("GET");
         rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
         while ((line = rd.readLine()) != null) {
            result += line;
         }
         rd.close();
      } catch (Exception e) {
         e.printStackTrace();
      }
      return result;
   }


    /**
     * Testing flow:
     * 1. Connect <br/>
     * 2. Login <br/>
     * 3. Create user <br/>
     * 4. Logout <br/>
     *
     * @param args not used
     */
    public static void main(String[] args) {
        String endpointURL = "http://drupal7/test_endpoint"; //Set your own http://[drupal host]/[endpoint] URL
        String adminName = "????"; //Set your own admin user name
        String adminPass = "????"; //Set your own admin user password


        //Basic details of sample new user
        String newUserName = "kuku2";
        String newUserPass = "123456";
        String newUserEmail = "kuku2@mail";


        try {
            Drupal7XmlRpcClientTest service = new Drupal7XmlRpcClientTest(endpointURL);


            // 1) connect
            service.connect();


            // 2) login with admin
            Map login = service.login(adminName, adminPass);
            // you can create "watch" on 'login' to see the details of login user (the admin user)


            // 3) create new user
            Map userData = service.createUser(newUserName, newUserPass, newUserEmail);
            //you can create "watch" on 'userData' to see the "uid" of new created user


            // 4) logout
            service.logout();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}