/* * eXist Open Source Native XML Database * Copyright (C) 2001, Wolfgang M. Meier (meier@ifs.tu-darmstadt.de) * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This library 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 Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Id: RpcServer.java,v 1.6 2003/04/07 12:22:58 wolfgang_m Exp $ */ /* * Modified by Chris Sheridan to extend the timeout for search results from 3 minutes * to 30 minutes. See class ConnectionPool. 10/26/2003. */ package org.exist.xmlrpc; import it.unimi.dsi.fastutil.Int2ObjectOpenHashMap; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Hashtable; import java.util.Iterator; import java.util.Stack; import java.util.Vector; import org.apache.log4j.Category; import org.exist.EXistException; import org.exist.security.PermissionDeniedException; import org.exist.security.User; import org.exist.storage.BrokerPool; import org.exist.util.Configuration; /** * Handler class for XMLRPC calls.

* * To allow calls by many parallel users, RpcServer does not directly execute * calls. Instead it delegates all calls to instances of the inner class * RpcConnection, which run in their own thread.

* * On startup, RpcServer creates a pool of RpcConnections. For every call the * server first gets a RpcConnection object from the pool, executes the call * and releases the RpcConnection.

* * If the pool's maximum of concurrent connections (MAX_CONNECT) is reached, * RpcServer will block until a connection is available.

* * All methods returning XML data will return UTF-8 encoded strings, unless an * encoding is specified. Methods that allow to set the encoding will always * return byte[] instead of string. byte[]-values are handled as binary data * and are automatically BASE64-encoded by the XMLRPC engine. This way the * correct character encoding is preserved during transport.

* *@author Wolfgang Meier *@created 18. Mai 2002 */ public class RpcServer implements RpcAPI { private static Category LOG = Category.getInstance(RpcServer.class.getName()); protected final static int MIN_CONNECT = 1; protected final static int MAX_CONNECT = 10; protected ConnectionPool pool; /** * Constructor for the RpcServer object * *@param conf Description of the Parameter *@exception EXistException Description of the Exception */ public RpcServer(Configuration conf) throws EXistException { pool = new ConnectionPool(MIN_CONNECT, MAX_CONNECT, conf); } /** * Description of the Method * *@param name Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean createCollection(User user, String name) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { con.createCollection(user, name); return true; } catch (Exception e) { handleException(e); return false; } finally { pool.release(con); } } /** * Description of the Method * *@param collection Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public String createId(User user, String collection) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.createId(user, collection); } finally { pool.release(con); } } /** * Description of the Method * *@param xpath Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public int executeQuery(User user, String xpath) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.executeQuery(user, xpath); } catch (Exception e) { handleException(e); return -1; } finally { pool.release(con); } } /** * Description of the Method * *@param xpath Description of the Parameter *@param encoding Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public int executeQuery(User user, byte[] xpath, String encoding) throws EXistException, PermissionDeniedException { String xpathString = null; if (encoding != null) try { xpathString = new String(xpath, encoding); } catch (UnsupportedEncodingException e) { } if (xpathString == null) xpathString = new String(xpath); LOG.debug("query: " + xpathString); return executeQuery(user, xpathString); } /** * Description of the Method * *@param xpath Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public int executeQuery(User user, byte[] xpath) throws EXistException, PermissionDeniedException { return executeQuery(user, xpath, null); } /** * Gets the collectionDesc attribute of the RpcServer object * *@param rootCollection Description of the Parameter *@param user Description of the Parameter *@return The collectionDesc value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public Hashtable getCollectionDesc(User user, String rootCollection) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.getCollectionDesc(user, rootCollection); } catch (Exception e) { handleException(e); throw new EXistException("collection " + rootCollection + " not found!"); } finally { pool.release(con); } } /** * This method is provided to retrieve a document with encodings other than * UTF-8. Since the data is handled as binary data, character encodings are * preserved. byte[]-values are automatically BASE64-encoded by the XMLRPC * library. * *@param name Description of the Parameter *@param encoding Description of the Parameter *@param prettyPrint Description of the Parameter *@param user Description of the Parameter *@return The document value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] getDocument(User user, String name, String encoding, int prettyPrint) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { String xml = con.getDocument(user, name, (prettyPrint > 0), encoding, null); if (xml == null) throw new EXistException("document " + name + " not found!"); try { return xml.getBytes(encoding); } catch (UnsupportedEncodingException uee) { return xml.getBytes(); } } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * This method is provided to retrieve a document with encodings other than * UTF-8. Since the data is handled as binary data, character encodings are * preserved. byte[]-values are automatically BASE64-encoded by the XMLRPC * library. * *@param name Description of the Parameter *@param encoding Description of the Parameter *@param prettyPrint Description of the Parameter *@param stylesheet Description of the Parameter *@param user Description of the Parameter *@return The document value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] getDocument( User user, String name, String encoding, int prettyPrint, String stylesheet) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { String xml = con.getDocument(user, name, (prettyPrint > 0), encoding, stylesheet); if (xml == null) throw new EXistException("document " + name + " not found!"); try { return xml.getBytes(encoding); } catch (UnsupportedEncodingException uee) { return xml.getBytes(); } } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * get a list of all documents contained in the repository. * *@param user Description of the Parameter *@return The documentListing value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public Vector getDocumentListing(User user) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { Vector result = con.getDocumentListing(user); return result; } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * get a list of all documents contained in the collection. * *@param collection Description of the Parameter *@param user Description of the Parameter *@return The documentListing value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public Vector getDocumentListing(User user, String collection) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { Vector result = con.getDocumentListing(user, collection); return result; } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } public Hashtable listDocumentPermissions(User user, String name) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.listDocumentPermissions(user, name); } finally { pool.release(con); } } public Hashtable listCollectionPermissions(User user, String name) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.listCollectionPermissions(user, name); } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * Gets the hits attribute of the RpcServer object * *@param resultId Description of the Parameter *@param user Description of the Parameter *@return The hits value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public int getHits(User user, int resultId) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.getHits(user, resultId); } finally { pool.release(con); } } /** * Gets the permissions attribute of the RpcServer object * *@param docName Description of the Parameter *@param user Description of the Parameter *@return The permissions value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public Hashtable getPermissions(User user, String docName) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.getPermissions(user, docName); } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * Gets the user attribute of the RpcServer object * *@param user Description of the Parameter *@param name Description of the Parameter *@return The user value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public Hashtable getUser(User user, String name) throws EXistException, PermissionDeniedException { RpcConnection con = null; try { con = pool.get(); return con.getUser(user, name); } finally { pool.release(con); } } public Vector getUsers(User user) throws EXistException, PermissionDeniedException { RpcConnection con = null; try { con = pool.get(); return con.getUsers(user); } finally { pool.release(con); } } public Vector getIndexedElements(User user, String collectionName, boolean inclusive) throws EXistException, PermissionDeniedException { RpcConnection con = null; try { con = pool.get(); return con.getIndexedElements(user, collectionName, inclusive); } finally { pool.release(con); } } public Vector scanIndexTerms( User user, String collectionName, String start, String end, boolean inclusive) throws PermissionDeniedException, EXistException { RpcConnection con = null; try { con = pool.get(); return con.scanIndexTerms(user, collectionName, start, end, inclusive); } finally { pool.release(con); } } private void handleException(Exception e) throws EXistException, PermissionDeniedException { LOG.debug(e.getMessage()); StringWriter sw = new StringWriter(); e.printStackTrace(new PrintWriter(sw)); LOG.error(sw.toString()); if (e instanceof EXistException) throw (EXistException) e; else if (e instanceof PermissionDeniedException) throw (PermissionDeniedException) e; else throw new EXistException(e.getMessage()); } /** * does a document called name exist in the repository? * *@param name Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean hasDocument(User user, String name) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.hasDocument(user, name); } catch (Exception e) { handleException(e); return false; } finally { pool.release(con); } } /** * parse an XML document and store it into the database. The document will * later be identified by docName. Some xmlrpc clients seem to * have problems with character encodings when sending xml content. To * avoid this, parse() accepts the xml document content as byte[]. * *@param xmlData the document's XML content as UTF-8 * encoded array of bytes. *@param docName the document's name *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean parse(User user, byte[] xmlData, String docName) throws EXistException, PermissionDeniedException { return parse(user, xmlData, docName, 0); } /** * parse an XML document and store it into the database. The document will * later be identified by docName. Some xmlrpc clients seem to * have problems with character encodings when sending xml content. To * avoid this, parse() accepts the xml document content as byte[]. * *@param xmlData the document's XML content as UTF-8 * encoded array of bytes. *@param docName the document's name *@param overwrite replace an existing document with * the same name? (1=yes, 0=no) *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean parse(User user, byte[] xmlData, String docName, int overwrite) throws EXistException, PermissionDeniedException { String xml = null; try { xml = new String(xmlData, "UTF-8"); } catch (UnsupportedEncodingException e) { xml = new String(xmlData); } // some clients (Perl) encode strings with a \0 at the end. // remove it ... if (xml.charAt(xml.length() - 1) == 0x0) xml = xml.substring(0, xml.length() - 1); return parse(user, xml, docName, overwrite); } /** * Description of the Method * *@param xml Description of the Parameter *@param docName Description of the Parameter *@param overwrite Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean parse(User user, String xml, String docName, int overwrite) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.parse(user, xml.getBytes("UTF-8"), docName, (overwrite != 0)); } catch (Exception e) { handleException(e); return false; } finally { con.synchronize(); pool.release(con); } } /** * Description of the Method * *@param xml Description of the Parameter *@param docName Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean parse(User user, String xml, String docName) throws EXistException, PermissionDeniedException { return parse(user, xml, docName, 0); } /** * execute XPath query and return a list of results. The result is an array * of String[][2], which represents a two dimensional table, where every * row consists of a document-name / node-id pair. e.g.: * * * * * * hamlet.xml * * * * 8398 * * * * * * * * hamlet.xml * * * * 8399 * * * * * * You may use this information with the retrieve-call to retrieve the * actual nodes. * *@param xpath the XPath query to execute. *@param encoding Description of the Parameter *@param user Description of the Parameter *@return string[][2] *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public Vector query(User user, byte[] xpath, String encoding) throws EXistException, PermissionDeniedException { String xpathString = null; if (encoding != null) try { xpathString = new String(xpath, encoding); } catch (UnsupportedEncodingException e) { } if (xpathString == null) xpathString = new String(xpath); // some clients (Perl) encode strings with a \0 at the end. // remove it ... if (xpathString.charAt(xpathString.length() - 1) == 0x0) xpathString = xpathString.substring(0, xpathString.length() - 1); return query(user, xpathString); } public Hashtable queryP(User user, byte[] xpath) throws EXistException, PermissionDeniedException { return queryP(user, xpath, null); } public Hashtable queryP(User user, byte[] xpath, byte[] sortExpr) throws EXistException, PermissionDeniedException { return queryP(user, xpath, null, null, sortExpr); } public Hashtable queryP(User user, byte[] xpath, String docName, String s_id) throws EXistException, PermissionDeniedException { return queryP(user, xpath, docName, s_id, null); } public Hashtable queryP(User user, byte[] xpath, String docName, String s_id, byte[] sortExpr) throws EXistException, PermissionDeniedException { String xpathString = null; String sortString = null; try { xpathString = new String(xpath, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new EXistException("failed to decode xpath expression"); } if(sortExpr != null) try { sortString = new String(sortExpr, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new EXistException("failed to decode xpath expression"); } // some clients (Perl) encode strings with a \0 at the end. // remove it ... if (xpathString.charAt(xpathString.length() - 1) == 0x0) xpathString = xpathString.substring(0, xpathString.length() - 1); RpcConnection con = pool.get(); try { return con.queryP(user, xpathString, docName, s_id, sortString); } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } public void releaseQueryResult(int handle) { RpcConnection con = pool.get(); try { con.releaseQueryResult(handle); } finally { pool.release(con); } } public Vector query(User user, byte[] xpath) throws EXistException, PermissionDeniedException { return query(user, xpath, "UTF-8"); } public Vector query(User user, String xpath) throws EXistException, PermissionDeniedException { return query(user, xpath, null, null); } public Vector query(User user, String xpath, String docId, String s_id) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.query(user, xpath, docId, s_id); } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * execute XPath query and return howmany nodes from the result set, * starting at position start. If prettyPrint is * set to >0 (true), results are pretty printed. * *@param xpath the XPath query to execute *@param howmany maximum number of results to * return. *@param start item in the result set to start * with. *@param prettyPrint turn on pretty printing if >0. *@param encoding the character encoding to use. *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] query( User user, String xpath, String encoding, int howmany, int start, int prettyPrint) throws EXistException, PermissionDeniedException { return query(user, xpath, encoding, howmany, start, prettyPrint, null); } /** * execute XPath query and return howmany nodes from the result set, * starting at position start. If prettyPrint is * set to >0 (true), results are pretty printed. * *@param xpath the XPath query to execute *@param howmany maximum number of results to * return. *@param start item in the result set to start * with. *@param prettyPrint turn on pretty printing if >0. *@param encoding the character encoding to use. *@param sortExpr Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] query( User user, String xpath, String encoding, int howmany, int start, int prettyPrint, String sortExpr) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); String result = null; try { try { result = con.query( user, xpath, howmany, start, (prettyPrint > 0), false, encoding, sortExpr); return result.getBytes(encoding); } catch (UnsupportedEncodingException uee) { return result.getBytes(); } } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * Description of the Method * *@param resultId Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception PermissionDeniedException Description of the Exception *@exception EXistException Description of the Exception */ public Hashtable querySummary(User user, int resultId) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.summary(user, resultId); } finally { pool.release(con); } } /** * execute XPath query and return a summary of hits per document and hits * per doctype. This method returns a struct with the following fields: * * * * * * * "queryTime" * * * * int * * * * * * * * "hits" * * * * int * * * * * * * * "documents" * * * * array of array: Object[][3] * * * * * * * * "doctypes" * * * * array of array: Object[][2] * * * * * * Documents and doctypes represent tables where each row describes one * document or doctype for which hits were found. Each document entry has * the following structure: docId (int), docName (string), hits (int) The * doctype entry has this structure: doctypeName (string), hits (int) * *@param xpath Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public Hashtable querySummary(User user, String xpath) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.summary(user, xpath); } catch (Exception e) { handleException(e); throw new EXistException(e); } finally { pool.release(con); } } /** * remove a document from the repository. * *@param docName Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean remove(User user, String docName) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { con.remove(user, docName); return true; } catch (Exception e) { handleException(e); return false; } finally { con.synchronize(); pool.release(con); } } /** * Description of the Method * *@param name Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean removeCollection(User user, String name) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.removeCollection(user, name); } catch (Exception e) { handleException(e); return false; } finally { con.synchronize(); pool.release(con); } } /** * Description of the Method * *@param user Description of the Parameter *@param name Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean removeUser(User user, String name) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { return con.removeUser(user, name); } finally { pool.release(con); } } /** * retrieve a single node from a document. The node is identified by it's * internal id. * *@param doc the document containing the node *@param id the node's internal id *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] retrieve(User user, String doc, String id) throws EXistException, PermissionDeniedException { return retrieve(user, doc, id, 1); } /** * retrieve a single node from a document. The node is identified by it's * internal id. * *@param doc the document containing the node *@param id the node's internal id *@param prettyPrint result is pretty printed if >0 *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] retrieve(User user, String doc, String id, int prettyPrint) throws EXistException, PermissionDeniedException { return retrieve(user, doc, id, prettyPrint, "UTF-8"); } /** * retrieve a single node from a document. The node is identified by it's * internal id. * *@param doc the document containing the node *@param id the node's internal id *@param prettyPrint result is pretty printed if >0 *@param encoding character encoding to use *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] retrieve(User user, String doc, String id, int prettyPrint, String encoding) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); String xml = null; try { xml = con.retrieve(user, doc, id, (prettyPrint > 0), encoding); try { return xml.getBytes(encoding); } catch (UnsupportedEncodingException uee) { return xml.getBytes(); } } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * Description of the Method * *@param resultId Description of the Parameter *@param num Description of the Parameter *@param prettyPrint Description of the Parameter *@param encoding Description of the Parameter *@param user Description of the Parameter *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public byte[] retrieve(User user, int resultId, int num, int prettyPrint, String encoding) throws EXistException, PermissionDeniedException { RpcConnection con = pool.get(); try { String xml = con.retrieve(user, resultId, num, (prettyPrint > 0), encoding); try { return xml.getBytes(encoding); } catch (UnsupportedEncodingException uee) { return xml.getBytes(); } } catch (Exception e) { handleException(e); return null; } finally { pool.release(con); } } /** * Sets the permissions attribute of the RpcServer object * *@param user The new permissions value *@param resource The new permissions value *@param permissions The new permissions value *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean setPermissions(User user, String resource, String permissions) throws EXistException, PermissionDeniedException { return setPermissions(user, resource, null, null, permissions); } /** * Sets the permissions attribute of the RpcServer object * *@param user The new permissions value *@param resource The new permissions value *@param permissions The new permissions value *@param owner The new permissions value *@param ownerGroup The new permissions value *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean setPermissions( User user, String resource, String owner, String ownerGroup, String permissions) throws EXistException, PermissionDeniedException { RpcConnection con = null; try { con = pool.get(); return con.setPermissions(user, resource, owner, ownerGroup, permissions); } catch (Exception e) { handleException(e); return false; } finally { pool.release(con); } } /** * @see org.exist.xmlrpc.RpcAPI#setPermissions(org.exist.security.User, java.lang.String, int) */ public boolean setPermissions(User user, String resource, int permissions) throws EXistException, PermissionDeniedException { RpcConnection con = null; try { con = pool.get(); return con.setPermissions(user, resource, null, null, permissions); } catch (Exception e) { handleException(e); return false; } finally { pool.release(con); } } /** * @see org.exist.xmlrpc.RpcAPI#setPermissions(org.exist.security.User, java.lang.String, java.lang.String, java.lang.String, int) */ public boolean setPermissions( User user, String resource, String owner, String ownerGroup, int permissions) throws EXistException, PermissionDeniedException { RpcConnection con = null; try { con = pool.get(); return con.setPermissions(user, resource, owner, ownerGroup, permissions); } catch (Exception e) { handleException(e); return false; } finally { pool.release(con); } } /** * Sets the password attribute of the RpcServer object * *@param user The new password value *@param name The new password value *@param password The new password value *@param groups The new user value *@return Description of the Return Value *@exception EXistException Description of the Exception *@exception PermissionDeniedException Description of the Exception */ public boolean setUser(User user, String name, String password, Vector groups, String home) throws EXistException, PermissionDeniedException { RpcConnection con = null; try { con = pool.get(); return con.setUser(user, name, password, groups, home); } catch(Exception e) { handleException(e); return false; } finally { pool.release(con); } } public boolean setUser(User user, String name, String password, Vector groups) throws EXistException, PermissionDeniedException { return setUser(user, name, password, groups, null); } public boolean shutdown(User user) throws PermissionDeniedException { if (!user.hasGroup("dba")) throw new PermissionDeniedException("not allowed to shut down" + "the database"); try { BrokerPool.stop(); return true; } catch (EXistException e) { LOG.warn("shutdown failed", e); return false; } } /** * Description of the Class * *@author wolf *@created 28. Mai 2002 */ class ConnectionPool { public final static int CHECK_INTERVAL = 5000; // public final static int TIMEOUT = 180000; public final static int TIMEOUT = 1800000; /* 30 minutes */ protected Configuration conf; protected int connections = 0; protected long lastCheck = System.currentTimeMillis(); protected int max = 1; protected int min = 0; protected Int2ObjectOpenHashMap resultSets = new Int2ObjectOpenHashMap(); protected Stack pool = new Stack(); protected ArrayList threads = new ArrayList(); public ConnectionPool(int min, int max, Configuration conf) { this.min = min; this.max = max; this.conf = conf; initialize(); } private void checkResultSets() { for (Iterator i = resultSets.values().iterator(); i.hasNext();) { final QueryResult qr = (QueryResult) i.next(); long ts = ((QueryResult) qr).timestamp; if (System.currentTimeMillis() - ts > TIMEOUT) { LOG.debug("releasing result set " + qr.hashCode()); i.remove(); } } } protected RpcConnection createConnection() { try { RpcConnection con = new RpcConnection(conf, this); threads.add(con); con.start(); connections++; return con; } catch (EXistException ee) { LOG.warn(ee); return null; } } public synchronized RpcConnection get() { if (pool.isEmpty()) { if (connections < max) return createConnection(); else while (pool.isEmpty()) { LOG.debug("waiting for connection to become available"); try { this.wait(); } catch (InterruptedException e) { } } } RpcConnection con = (RpcConnection) pool.pop(); this.notifyAll(); if (System.currentTimeMillis() - lastCheck > CHECK_INTERVAL) checkResultSets(); return con; } protected void initialize() { RpcConnection con; for (int i = 0; i < min; i++) { con = createConnection(); pool.push(con); } } public synchronized void release(RpcConnection con) { pool.push(con); this.notifyAll(); } public synchronized void shutdown() { for (Iterator i = threads.iterator(); i.hasNext();) ((RpcConnection) i.next()).terminate(); while (pool.size() < connections) try { this.wait(); } catch (InterruptedException e) { } try { BrokerPool.stop(); } catch (EXistException e) { LOG.warn("shutdown failed", e); } } public synchronized void synchronize() { for (Iterator i = threads.iterator(); i.hasNext();) ((RpcConnection) i.next()).synchronize(); } } }