org.exist.xmlrpc.XmlRpcTest.java Source code

Java tutorial

Introduction

Here is the source code for org.exist.xmlrpc.XmlRpcTest.java

Source

/*
 * eXist Open Source Native XML Database
 * Copyright (C) 2004-2009 The eXist Project
 * http://exist-db.org
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *  
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *  
 *  $Id$
 */
package org.exist.xmlrpc;

import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.custommonkey.xmlunit.XMLAssert;
import org.exist.jetty.JettyStart;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.exist.security.MessageDigester;
import org.exist.storage.serializers.EXistOutputKeys;
import org.exist.test.TestConstants;
import org.exist.util.MimeType;
import org.exist.xmldb.XmldbURI;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import javax.xml.transform.OutputKeys;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;
import org.exist.security.Permission;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * JUnit test for XMLRPC interface methods.
 * @author wolf
 * @author Pierrick Brihaye <pierrick.brihaye@free.fr>
 * @author ljo
 */
public class XmlRpcTest {

    private static JettyStart server = null;
    // jetty.port.standalone
    private final static String URI = "http://localhost:" + System.getProperty("jetty.port", "8088") + "/xmlrpc";

    private final static XmldbURI TARGET_COLLECTION = XmldbURI.ROOT_COLLECTION_URI.append("xmlrpc");

    private final static XmldbURI TARGET_RESOURCE = TARGET_COLLECTION.append(TestConstants.TEST_XML_URI);

    public final static XmldbURI MODULE_RESOURCE = TARGET_COLLECTION.append(TestConstants.TEST_MODULE_URI);

    private final static XmldbURI SPECIAL_COLLECTION = TARGET_COLLECTION.append(TestConstants.SPECIAL_NAME);

    private final static XmldbURI SPECIAL_RESOURCE = SPECIAL_COLLECTION.append(TestConstants.SPECIAL_XML_URI);

    private final static String XML_DATA = "<test>"
            + "<para>\u00E4\u00E4\u00F6\u00F6\u00FC\u00FC\u00C4\u00C4\u00D6\u00D6\u00DC\u00DC\u00DF\u00DF</para>"
            + "<para>\uC5F4\uB2E8\uACC4</para>" + "</test>";

    private final static String XSL_DATA = "<xsl:stylesheet xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\" "
            + "version=\"1.0\">" + "<xsl:param name=\"testparam\"/>"
            + "<xsl:template match=\"test\"><test><xsl:apply-templates/></test></xsl:template>"
            + "<xsl:template match=\"para\">"
            + "<p><xsl:value-of select=\"$testparam\"/>: <xsl:apply-templates/></p></xsl:template>"
            + "</xsl:stylesheet>";

    public final static String MODULE_DATA = "module namespace tm = \"http://exist-db.org/test/module\"; "
            + "declare variable $tm:imported-external-string as xs:string external;";

    public final static String QUERY_MODULE_DATA = "xquery version \"1.0\";"
            + "declare namespace tm-query = \"http://exist-db.org/test/module/query\";"
            + "import module namespace tm = \"http://exist-db.org/test/module\" " + "at \"xmldb:exist://"
            + MODULE_RESOURCE.toString() + "\"; "
            + "declare variable $tm-query:local-external-string as xs:string external;"
            + "($tm:imported-external-string, $tm-query:local-external-string)";

    public XmlRpcTest() {
    }

    @BeforeClass
    public static void setUp() {
        System.out.println("==================================");
        //Don't worry about closing the server : the shutdownDB hook will do the job
        initServer();
    }

    @AfterClass
    public static void stopServer() {
        server.shutdown();
        server = null;
        System.gc();
        try {
            Thread.sleep(500);
        } catch (InterruptedException ex) {
            ex.printStackTrace();
        }
    }

    protected void tearDown() {
        XmlRpcClient xmlrpc = getClient();
        try {
            List<String> params = new ArrayList<String>(1);
            params.add(TARGET_COLLECTION.toString());
            @SuppressWarnings("unused")
            Boolean b = (Boolean) xmlrpc.execute("removeCollection", params);
        } catch (XmlRpcException e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }

    private static void initServer() {
        try {
            if (server == null) {
                server = new JettyStart();
                System.out.println("Starting standalone server...");
                server.run();
            }
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testStoreAndRetrieve() {
        System.out.println("---testStoreAndRetrieve");
        try {
            System.out.println("Creating collection " + TARGET_COLLECTION);
            XmlRpcClient xmlrpc = getClient();
            Vector<Object> params = new Vector<Object>();
            params.addElement(TARGET_COLLECTION.toString());
            Boolean result = (Boolean) xmlrpc.execute("createCollection", params);
            Assert.assertTrue(result.booleanValue());

            System.out.println("Storing document " + XML_DATA);
            params.clear();
            params.addElement(XML_DATA);
            params.addElement(TARGET_RESOURCE.toString());
            params.addElement(new Integer(1));

            result = (Boolean) xmlrpc.execute("parse", params);
            Assert.assertTrue(result.booleanValue());

            System.out.println("Documents stored.");

            HashMap<String, String> options = new HashMap<String, String>();
            params.clear();
            params.addElement(TARGET_RESOURCE.toString());
            params.addElement(options);

            byte[] data = (byte[]) xmlrpc.execute("getDocument", params);
            System.out.println(new String(data, "UTF-8"));
            Assert.assertNotNull(data);

            params.clear();
            params.addElement(TARGET_RESOURCE.toString());
            params.addElement("UTF-8");
            params.addElement(0);

            data = (byte[]) xmlrpc.execute("getDocument", params);
            System.out.println(new String(data, "UTF-8"));
            Assert.assertNotNull(data);

            params.clear();
            params.addElement(TARGET_RESOURCE.toString());
            params.addElement(0);
            String sdata = (String) xmlrpc.execute("getDocumentAsString", params);
            System.out.println(sdata);
            Assert.assertNotNull(data);

            params.clear();
            params.addElement(TARGET_RESOURCE.toString());
            params.addElement(options);
            HashMap<?, ?> table = (HashMap<?, ?>) xmlrpc.execute("getDocumentData", params);
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            int offset = ((Integer) table.get("offset")).intValue();
            data = (byte[]) table.get("data");
            os.write(data);
            while (offset > 0) {
                params.clear();
                params.add(table.get("handle"));
                params.add(Integer.valueOf(offset));
                table = (HashMap<?, ?>) xmlrpc.execute("getNextChunk", params);
                offset = ((Integer) table.get("offset")).intValue();
                data = (byte[]) table.get("data");
                os.write(data);
            }
            data = os.toByteArray();
            Assert.assertTrue(data.length > 0);
            System.out.println(new String(data, "UTF-8"));

            params.clear();
            params.addElement(TARGET_RESOURCE.toString());
            Boolean b = (Boolean) xmlrpc.execute("hasDocument", params);
            Assert.assertTrue(b.booleanValue());
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }

    private void storeData() {
        System.out.println("---storeData");
        try {
            System.out.println("Creating collection " + TARGET_COLLECTION);
            XmlRpcClient xmlrpc = getClient();
            Vector<Object> params = new Vector<Object>();
            params.addElement(TARGET_COLLECTION.toString());
            Boolean result = (Boolean) xmlrpc.execute("createCollection", params);
            Assert.assertTrue(result.booleanValue());

            System.out.println("Storing document " + XML_DATA);
            params.clear();
            params.addElement(XML_DATA);
            params.addElement(TARGET_RESOURCE.toString());
            params.addElement(Integer.valueOf(1));

            result = (Boolean) xmlrpc.execute("parse", params);
            Assert.assertTrue(result.booleanValue());

            System.out.println("Storing resource " + XSL_DATA);
            params.setElementAt(XSL_DATA, 0);
            params.setElementAt(TARGET_COLLECTION.append("test.xsl").toString(), 1);
            result = (Boolean) xmlrpc.execute("parse", params);
            Assert.assertTrue(result.booleanValue());

            System.out.println("Storing resource " + MODULE_DATA);
            params.setElementAt(MODULE_DATA.getBytes(UTF_8), 0);
            params.setElementAt(MODULE_RESOURCE.toString(), 1);
            params.setElementAt(MimeType.XQUERY_TYPE.getName(), 2);
            params.addElement(Boolean.TRUE);
            result = (Boolean) xmlrpc.execute("storeBinary", params);
            Assert.assertTrue(result.booleanValue());

            System.out.println("Documents stored.");
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testRemoveCollection() {
        System.out.println("---testRemoveCollection");
        storeData();
        XmlRpcClient xmlrpc = getClient();
        try {
            List<Object> params = new ArrayList<Object>(1);
            params.add(TARGET_COLLECTION.toString());
            Boolean b = (Boolean) xmlrpc.execute("hasCollection", params);
            Assert.assertTrue(b.booleanValue());

            b = (Boolean) xmlrpc.execute("removeCollection", params);
            Assert.assertTrue(b.booleanValue());

            b = (Boolean) xmlrpc.execute("hasCollection", params);
            Assert.assertFalse(b.booleanValue());
        } catch (XmlRpcException e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testRemoveDoc() {
        System.out.println("---testRemoveDoc");
        storeData();
        XmlRpcClient xmlrpc = getClient();
        try {
            List<Object> params = new ArrayList<Object>(1);
            params.add(TARGET_RESOURCE.toString());
            Boolean b = (Boolean) xmlrpc.execute("hasDocument", params);

            Assert.assertTrue(b.booleanValue());

            b = (Boolean) xmlrpc.execute("remove", params);
            Assert.assertTrue(b.booleanValue());

            b = (Boolean) xmlrpc.execute("hasDocument", params);
            Assert.assertFalse(b.booleanValue());
        } catch (XmlRpcException e) {
            e.printStackTrace();
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testRetrieveDoc() {
        System.out.println("---testRetrieveDoc");
        storeData();
        System.out.println("Retrieving document " + TARGET_RESOURCE);
        Hashtable<String, String> options = new Hashtable<String, String>();
        options.put("indent", "yes");
        options.put("encoding", "UTF-8");
        options.put("expand-xincludes", "yes");
        options.put("process-xsl-pi", "no");

        Vector<Object> params = new Vector<Object>();
        params.addElement(TARGET_RESOURCE.toString());
        params.addElement(options);

        try {
            // execute the call
            XmlRpcClient xmlrpc = getClient();
            byte[] data = (byte[]) xmlrpc.execute("getDocument", params);
            System.out.println(new String(data, "UTF-8"));

            System.out.println("Retrieving document with stylesheet applied");
            options.put("stylesheet", "test.xsl");
            data = (byte[]) xmlrpc.execute("getDocument", params);
            System.out.println(new String(data, "UTF-8"));
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testCharEncoding() {
        System.out.println("---testCharEncoding");
        storeData();
        try {
            System.out.println("Testing charsets returned by query");
            Vector<Object> params = new Vector<Object>();
            String query = "distinct-values(//para)";
            params.addElement(query.getBytes(UTF_8));
            params.addElement(new Hashtable<Object, Object>());
            XmlRpcClient xmlrpc = getClient();
            HashMap<?, ?> result = (HashMap<?, ?>) xmlrpc.execute("queryP", params);
            Object[] resources = (Object[]) result.get("results");
            //TODO : check the number of resources before !
            Assert.assertEquals(resources.length, 2);
            String value = (String) resources[0];
            Assert.assertEquals(value,
                    "\u00E4\u00E4\u00F6\u00F6\u00FC\u00FC\u00C4\u00C4\u00D6\u00D6\u00DC\u00DC\u00DF\u00DF");
            System.out.println("Result1: " + value);
            value = (String) resources[1];
            Assert.assertEquals(value, "\uC5F4\uB2E8\uACC4");
            System.out.println("Result2: " + value);
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testQuery() {
        System.out.println("---testQuery");
        storeData();
        try {
            Vector<Object> params = new Vector<Object>();
            String query = "(::pragma exist:serialize indent=no::) //para";
            params.addElement(query.getBytes(UTF_8));
            params.addElement(Integer.valueOf(10));
            params.addElement(Integer.valueOf(1));
            params.addElement(new Hashtable());
            XmlRpcClient xmlrpc = getClient();
            byte[] result = (byte[]) xmlrpc.execute("query", params);
            Assert.assertNotNull(result);
            Assert.assertTrue(result.length > 0);
            System.out.println(new String(result, "UTF-8"));
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testQueryWithStylesheet() {
        System.out.println("---testQueryWithStylesheet");
        storeData();
        try {
            HashMap<String, String> options = new HashMap<String, String>();
            options.put(EXistOutputKeys.STYLESHEET, "test.xsl");
            options.put(EXistOutputKeys.STYLESHEET_PARAM + ".testparam", "Test");
            options.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
            //TODO : check the number of resources before !
            Vector<Object> params = new Vector<Object>();
            String query = "//para[1]";
            params.addElement(query.getBytes(UTF_8));
            params.addElement(options);
            XmlRpcClient xmlrpc = getClient();
            Integer handle = (Integer) xmlrpc.execute("executeQuery", params);
            Assert.assertNotNull(handle);

            params.clear();
            params.addElement(handle);
            params.addElement(Integer.valueOf(0));
            params.addElement(options);
            byte[] item = (byte[]) xmlrpc.execute("retrieve", params);
            Assert.assertNotNull(item);
            Assert.assertTrue(item.length > 0);
            String out = new String(item, UTF_8);
            System.out.println("Received: " + out);
            XMLAssert.assertXMLEqual("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
                    + "<p>Test: \u00E4\u00E4\u00F6\u00F6\u00FC\u00FC\u00C4\u00C4\u00D6\u00D6\u00DC\u00DC\u00DF\u00DF</p>",
                    out);
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testCompile() {
        System.out.println("---testCompile");
        storeData();
        try {
            Vector<Object> params = new Vector<Object>();
            String query = "<a>Invalid<a>";
            params.addElement(query.getBytes(UTF_8));
            params.addElement(new Hashtable<Object, Object>());
            XmlRpcClient xmlrpc = getClient();
            System.out.println("Executing query: " + query);
            Map stats = (Map) xmlrpc.execute("compile", params);
            Assert.assertNotNull(stats);
            Assert.assertNotNull(stats.get("error"));
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testAddAccount() {
        System.out.println("---testAddAccount");
        try {
            String user = "rudi";
            String passwd = "pass";
            String simpleMd5 = MessageDigester.md5(passwd, true);
            String digest = MessageDigester.md5(user + ":exist:" + passwd, false);
            List<Object> params = new ArrayList<Object>(12);
            params.add("rudi");
            params.add(simpleMd5);
            params.add(digest);
            params.add(new String[] { "guest" });
            params.add(true);
            params.add(Permission.DEFAULT_UMASK);
            params.add(new HashMap<String, String>());

            XmlRpcClient xmlrpc = getClient();
            xmlrpc.execute("addAccount", params);

            XmlRpcClientConfigImpl config = (XmlRpcClientConfigImpl) xmlrpc.getClientConfig();
            config.setBasicUserName("admin");
            config.setBasicPassword("");
            xmlrpc.execute("sync", new ArrayList());
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testExecuteQuery() {
        System.out.println("---testExecuteQuery");
        storeData();
        try {
            Vector<Object> params = new Vector<Object>();
            String query = "distinct-values(//para)";
            params.addElement(query.getBytes(UTF_8));
            params.addElement(new Hashtable<Object, Object>());
            XmlRpcClient xmlrpc = getClient();
            System.out.println("Executing query: " + query);
            Integer handle = (Integer) xmlrpc.execute("executeQuery", params);
            Assert.assertNotNull(handle);

            params.clear();
            params.addElement(handle);
            Integer hits = (Integer) xmlrpc.execute("getHits", params);
            Assert.assertNotNull(hits);
            System.out.println("Found: " + hits.intValue());

            Assert.assertEquals(hits.intValue(), 2);

            params.addElement(new Integer(0));
            params.addElement(new Hashtable<Object, Object>());
            byte[] item = (byte[]) xmlrpc.execute("retrieve", params);
            System.out.println(new String(item, "UTF-8"));

            params.clear();
            params.addElement(handle);
            params.addElement(Integer.valueOf(1));
            params.addElement(new Hashtable<Object, Object>());
            item = (byte[]) xmlrpc.execute("retrieve", params);
            System.out.println(new String(item, "UTF-8"));
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testQueryModuleExternalVar() {
        System.out.println("---testQueryModuleExternalVar");
        storeData();
        try {
            System.out.println("Quering with external variable definied in module ...");
            Vector<Object> params = new Vector<Object>();
            params.addElement(QUERY_MODULE_DATA.getBytes(UTF_8));

            Hashtable<String, Object> qp = new Hashtable<String, Object>();

            HashMap<String, Object> namespaceDecls = new HashMap<String, Object>();
            namespaceDecls.put("tm", "http://exist-db.org/test/module");
            namespaceDecls.put("tm-query", "http://exist-db.org/test/module/query");
            qp.put(RpcAPI.NAMESPACES, namespaceDecls);

            HashMap<String, Object> variableDecls = new HashMap<String, Object>();
            variableDecls.put("tm:imported-external-string", "imported-string-value");
            variableDecls.put("tm-query:local-external-string", "local-string-value");
            qp.put(RpcAPI.VARIABLES, variableDecls);

            params.addElement(qp);

            XmlRpcClient xmlrpc = getClient();
            HashMap<String, Object[]> result = (HashMap) xmlrpc.execute("queryP", params);
            Object[] resources = (Object[]) result.get("results");
            Assert.assertEquals(resources.length, 2);
            String value = (String) resources[0];
            Assert.assertEquals(value, "imported-string-value");
            System.out.println("Imported external: " + value);
            value = (String) resources[1];
            Assert.assertEquals(value, "local-string-value");
            System.out.println("Local external: " + value);

        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    @Test
    public void testCollectionWithAccentsAndSpaces() {
        System.out.println("---testCollectionWithAccentsAndSpaces");
        storeData();
        try {
            System.out.println("Creating collection with accents and spaces in name ...");
            Vector<Object> params = new Vector<Object>();
            params.addElement(SPECIAL_COLLECTION.toString());
            XmlRpcClient xmlrpc = getClient();
            xmlrpc.execute("createCollection", params);

            System.out.println("Storing document " + XML_DATA);
            params.clear();
            params.addElement(XML_DATA);
            params.addElement(SPECIAL_RESOURCE.toString());
            params.addElement(Integer.valueOf(1));

            Boolean result = (Boolean) xmlrpc.execute("parse", params);
            Assert.assertTrue(result.booleanValue());

            params.clear();
            params.addElement(SPECIAL_COLLECTION.removeLastSegment().toString());

            HashMap collection = (HashMap) xmlrpc.execute("describeCollection", params);
            Object[] collections = (Object[]) collection.get("collections");
            boolean foundMatch = false;
            String targetCollectionName = SPECIAL_COLLECTION.lastSegment().toString();
            for (int i = 0; i < collections.length; i++) {
                String childName = (String) collections[i];
                System.out.println("Child collection: " + childName);
                if (childName.equals(targetCollectionName)) {
                    foundMatch = true;
                    break;
                }
            }
            Assert.assertTrue("added collection not found", foundMatch);

            System.out.println("Retrieving document '" + SPECIAL_RESOURCE.toString() + "'");
            HashMap<String, String> options = new HashMap<String, String>();
            options.put("indent", "yes");
            options.put("encoding", "UTF-8");
            options.put("expand-xincludes", "yes");
            options.put("process-xsl-pi", "no");

            params.clear();
            params.addElement(SPECIAL_RESOURCE.toString());
            params.addElement(options);

            // execute the call
            byte[] data = (byte[]) xmlrpc.execute("getDocument", params);
            System.out.println(new String(data, "UTF-8"));
        } catch (Exception e) {
            Assert.fail(e.getMessage());
        }
    }

    protected XmlRpcClient getClient() {
        try {
            XmlRpcClient client = new XmlRpcClient();
            XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
            config.setEnabledForExtensions(true);
            config.setServerURL(new URL(URI));
            config.setBasicUserName("admin");
            config.setBasicPassword("");
            client.setConfig(config);
            return client;
        } catch (MalformedURLException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static void main(String[] args) {
        org.junit.runner.JUnitCore.main(XmlRpcTest.class.getName());
        //Explicit shutdownDB for the shutdownDB hook
        System.exit(0);
    }
}