package org.exist.xmlrpc;
import org.exist.StandaloneServer;
import org.exist.TestDataGenerator;
import org.exist.xmldb.IndexQueryService;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mortbay.util.MultiException;
import org.xmldb.api.DatabaseManager;
import org.xmldb.api.base.*;
import org.xmldb.api.modules.CollectionManagementService;
import org.xmldb.api.modules.XQueryService;
import java.io.File;
import java.net.BindException;
import java.util.Iterator;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
*/
public class QuerySessionTest {
private final static String generateXQ = "<book id=\"{$filename}\" n=\"{$count}\">"
+ " <chapter xml:id=\"chapter{$count}\">"
+ " <title>{pt:random-text(7)}</title>"
+ " {"
+ " for $section in 1 to 8 return"
+ " <section id=\"sect{$section}\">"
+ " <title>{pt:random-text(7)}</title>"
+ " {"
+ " for $para in 1 to 10 return"
+ " <para>{pt:random-text(40)}</para>"
+ " }"
+ " </section>"
+ " }"
+ " </chapter>" + "</book>";
private final static String COLLECTION_CONFIG =
"<collection xmlns=\"http://exist-db.org/collection-config/1.0\">" +
" <index>" +
" <fulltext default=\"all\" attributes=\"false\"/>" +
" <create qname=\"@xml:id\" type=\"xs:string\"/>" +
" </index>" +
"</collection>";
private final static String QUERY =
"declare variable $n external;" +
"//chapter[@xml:id = $n]";
private final static String baseURI = "xmldb:exist://localhost:8088/xmlrpc";
private final static int N_THREADS = 10;
private final static int DOC_COUNT = 100;
private static StandaloneServer server;
private Random random = new Random();
@Test (expected=XMLDBException.class)
public void manualRelease() throws XMLDBException {
Collection test = DatabaseManager.getCollection(baseURI + "/db/rpctest", "admin", "");
XQueryService service = (XQueryService) test.getService("XQueryService", "1.0");
ResourceSet result = service.query("//chapter[@xml:id = 'chapter1']");
Assert.assertEquals(1, result.getSize());
// clear should release the query result on the server
result.clear();
// the result has been cleared already. we should get an exception here
Resource members = result.getMembersAsResource();
System.out.println("members: " + members.getContent().toString());
}
@Test
public void runTasks() {
ExecutorService executor = Executors.newFixedThreadPool(N_THREADS);
for (int i = 0; i < 1000; i++) {
executor.submit(new QueryTask(QUERY));
}
executor.shutdown();
boolean terminated = false;
try {
terminated = executor.awaitTermination(60 * 60, TimeUnit.SECONDS);
} catch (InterruptedException e) {
}
Assert.assertTrue(terminated);
}
private class QueryTask implements Runnable {
private String query;
private QueryTask(String query) {
this.query = query;
}
public void run() {
try {
Collection test = DatabaseManager.getCollection(baseURI + "/db/rpctest", "admin", "");
XQueryService service = (XQueryService) test.getService("XQueryService", "1.0");
int n = random.nextInt(DOC_COUNT) + 1;
service.declareVariable("n", "chapter" + n);
ResourceSet result = service.query(query);
Assert.assertEquals(1, result.getSize());
} catch (XMLDBException e) {
e.printStackTrace();
Assert.fail(e.getMessage());
}
}
}
@BeforeClass
public static void startServer() throws Exception {
try {
server = new StandaloneServer();
System.out.println("Starting standalone server...");
String[] args = {};
System.out.println("Waiting for server to start...");
server.run(args);
while (!server.isStarted()) {
synchronized (server) {
server.wait(10000);
}
}
} catch (MultiException e) {
boolean rethrow = true;
Iterator i = e.getExceptions().iterator();
while (i.hasNext()) {
Exception e0 = (Exception)i.next();
if (e0 instanceof BindException) {
System.out.println("A server is running already !");
rethrow = false;
break;
}
}
if (rethrow) throw e;
}
// initialize XML:DB driver
Class cl = Class.forName("org.exist.xmldb.DatabaseImpl");
Database database = (Database) cl.newInstance();
DatabaseManager.registerDatabase(database);
Collection root = DatabaseManager.getCollection(baseURI + "/db", "admin", "");
CollectionManagementService mgmt =
(CollectionManagementService) root.getService("CollectionManagementService", "1.0");
Collection test = mgmt.createCollection("rpctest");
IndexQueryService idxs = (IndexQueryService) test.getService("IndexQueryService", "1.0");
idxs.configureCollection(COLLECTION_CONFIG);
Resource resource = test.createResource("strings.xml", "XMLResource");
resource.setContent(new File("samples/shakespeare/macbeth.xml"));
test.storeResource(resource);
TestDataGenerator generator = new TestDataGenerator("xdb", DOC_COUNT);
File[] files = generator.generate(test, generateXQ);
for (int i = 0; i < files.length; i++) {
resource = test.createResource(files[i].getName(), "XMLResource");
resource.setContent(files[i]);
test.storeResource(resource);
}
generator.releaseAll();
}
@AfterClass
public static void stopServer() {
try {
Collection root = DatabaseManager.getCollection(baseURI + "/db", "admin", "");
CollectionManagementService mgmt =
(CollectionManagementService) root.getService("CollectionManagementService", "1.0");
mgmt.removeCollection("rpctest");
Collection config = DatabaseManager.getCollection(baseURI + "/db/system/config/db", "admin", "");
mgmt =
(CollectionManagementService) config.getService("CollectionManagementService", "1.0");
mgmt.removeCollection("rpctest");
} catch (XMLDBException e) {
e.printStackTrace();
}
server.shutdown();
server = null;
}
}