From: <wol...@us...> - 2008-07-23 09:17:45
|
Revision: 8053 http://exist.svn.sourceforge.net/exist/?rev=8053&view=rev Author: wolfgang_m Date: 2008-07-23 09:17:41 +0000 (Wed, 23 Jul 2008) Log Message: ----------- [bugfix] fixed memory leak: when validating a document, xerces can consume quite a lot of memory for temporary data structures. Unfortunately, those data structures are not cleared afterwards. Pooling the XML parser can thus cause a serious memory leak. To work around those issues, eXist now checks the size of the last document that was parsed. If the document was a small one, the XML parser is pooled. For larger documents, we throw the parser away. Modified Paths: -------------- trunk/eXist/src/org/exist/Indexer.java trunk/eXist/src/org/exist/collections/Collection.java Modified: trunk/eXist/src/org/exist/Indexer.java =================================================================== --- trunk/eXist/src/org/exist/Indexer.java 2008-07-22 19:39:20 UTC (rev 8052) +++ trunk/eXist/src/org/exist/Indexer.java 2008-07-23 09:17:41 UTC (rev 8053) @@ -123,6 +123,8 @@ protected boolean suppressWSmixed = false; + protected int docSize = 0; + /* used to record the number of children of an element during * validation phase. later, when storing the nodes, we already * know the child count and don't need to update the element @@ -135,8 +137,6 @@ // the current nodeFactoryInstanceCnt private int nodeFactoryInstanceCnt = 0; - - // reusable fields private TextImpl text = new TextImpl(); @@ -208,6 +208,7 @@ level = 0; currentPath.reset(); stack = new Stack(); + docSize = 0; nsMappings.clear(); indexListener = null; rootNode = null; @@ -227,7 +228,11 @@ public DocumentImpl getDocument() { return document; } - + + public int getDocSize() { + return docSize; + } + public void characters(char[] ch, int start, int length) { if (length <= 0) return; @@ -496,8 +501,9 @@ progress = new ProgressIndicator(currentLine, 100); document.setChildCount(0); elementCnt = 0; - } } + docSize = 0; + } public void startElement(String namespace, String name, String qname, Attributes attributes) throws SAXException { @@ -603,7 +609,6 @@ } document.appendChild(node); } - level++; String attrPrefix; @@ -659,6 +664,7 @@ } } } + ++docSize; } private void storeText() { Modified: trunk/eXist/src/org/exist/collections/Collection.java =================================================================== --- trunk/eXist/src/org/exist/collections/Collection.java 2008-07-22 19:39:20 UTC (rev 8052) +++ trunk/eXist/src/org/exist/collections/Collection.java 2008-07-23 09:17:41 UTC (rev 8053) @@ -98,11 +98,9 @@ public class Collection extends Observable implements Comparable, Cacheable { public static int LENGTH_COLLECTION_ID = 4; //sizeof int - - public Collection(){ - - } + public static final int POOL_PARSER_THRESHOLD = 500; + private final static int SHALLOW_SIZE = 550; private final static int DOCUMENT_SIZE = 450; @@ -152,6 +150,10 @@ /** is this a temporary collection? */ private boolean isTempCollection = false; + + public Collection(){ + + } public Collection(XmldbURI path) { setPath(path); @@ -913,7 +915,7 @@ } catch (IOException e) { throw new EXistException(e); } finally { - releaseReader(broker, reader); + releaseReader(broker, info, reader); } } }); @@ -948,7 +950,7 @@ } catch (IOException e) { throw new EXistException(e); } finally { - releaseReader(broker, reader); + releaseReader(broker, info, reader); } } }); @@ -1098,7 +1100,7 @@ } catch (IOException e) { throw new EXistException(e); } finally { - releaseReader(broker, reader); + releaseReader(broker, info, reader); } } }); @@ -1623,14 +1625,14 @@ // Get reader from readerpool. XMLReader reader= broker.getBrokerPool().getParserPool().borrowXMLReader(); - + // If Collection configuration exists (try to) get validation mode // and setup reader with this information. if( colconfig!=null ) { int mode=colconfig.getValidationMode(); - XMLReaderObjectFactory.setReaderValidationMode(mode, reader); - } - + XMLReaderObjectFactory.setReaderValidationMode(mode, reader); + } + // Return configured reader. return reader; } @@ -1638,11 +1640,12 @@ /** * Reset validation mode of reader and return reader to reader pool. */ - private void releaseReader(DBBroker broker, XMLReader reader) { + private void releaseReader(DBBroker broker, IndexInfo info, XMLReader reader) { if(userReader != null){ return; } - + if (info.getIndexer().getDocSize() > POOL_PARSER_THRESHOLD) + return; // Get validation mode from static configuration Configuration config = broker.getConfiguration(); String optionValue = (String) config.getProperty(XMLReaderObjectFactory.PROPERTY_VALIDATION_MODE); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2008-08-22 17:13:20
|
Revision: 8103 http://exist.svn.sourceforge.net/exist/?rev=8103&view=rev Author: wolfgang_m Date: 2008-08-22 17:13:17 +0000 (Fri, 22 Aug 2008) Log Message: ----------- [bugfix] fixed concurrent access conflicts caused by wrong acquire/release sequence in WebDAV MOVE; fixed potential deadlock condition. Modified Paths: -------------- trunk/eXist/src/org/exist/http/webdav/methods/Head.java trunk/eXist/src/org/exist/http/webdav/methods/Move.java trunk/eXist/src/org/exist/http/webdav/methods/Propfind.java trunk/eXist/src/org/exist/http/webdav/methods/Put.java trunk/eXist/src/org/exist/storage/BrokerPool.java Modified: trunk/eXist/src/org/exist/http/webdav/methods/Head.java =================================================================== --- trunk/eXist/src/org/exist/http/webdav/methods/Head.java 2008-08-22 00:18:03 UTC (rev 8102) +++ trunk/eXist/src/org/exist/http/webdav/methods/Head.java 2008-08-22 17:13:17 UTC (rev 8103) @@ -21,12 +21,6 @@ */ package org.exist.http.webdav.methods; -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.exist.EXistException; import org.exist.collections.Collection; import org.exist.dom.DocumentImpl; @@ -39,6 +33,11 @@ import org.exist.storage.lock.Lock; import org.exist.xmldb.XmldbURI; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + /** * @author wolf */ @@ -84,11 +83,11 @@ } catch (PermissionDeniedException e) { response.sendError(HttpServletResponse.SC_FORBIDDEN, READ_PERMISSION_DENIED); } finally { - if(collection != null) + pool.release(broker); + if(collection != null) collection.release(Lock.READ_LOCK); if(resource != null) resource.getUpdateLock().release(Lock.READ_LOCK); - pool.release(broker); } } } Modified: trunk/eXist/src/org/exist/http/webdav/methods/Move.java =================================================================== --- trunk/eXist/src/org/exist/http/webdav/methods/Move.java 2008-08-22 00:18:03 UTC (rev 8102) +++ trunk/eXist/src/org/exist/http/webdav/methods/Move.java 2008-08-22 17:13:17 UTC (rev 8103) @@ -21,14 +21,6 @@ */ package org.exist.http.webdav.methods; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.exist.EXistException; import org.exist.collections.Collection; import org.exist.dom.DocumentImpl; @@ -43,6 +35,13 @@ import org.exist.util.LockException; import org.exist.xmldb.XmldbURI; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + /** * Implements the WebDAV move method. * @author wolf @@ -178,7 +177,6 @@ if(destCollection != null) destCollection.release(Lock.WRITE_LOCK); transact.commit(txn); - pool.release(broker); } } catch (TransactionException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); Modified: trunk/eXist/src/org/exist/http/webdav/methods/Propfind.java =================================================================== --- trunk/eXist/src/org/exist/http/webdav/methods/Propfind.java 2008-08-22 00:18:03 UTC (rev 8102) +++ trunk/eXist/src/org/exist/http/webdav/methods/Propfind.java 2008-08-22 17:13:17 UTC (rev 8103) @@ -21,34 +21,6 @@ */ package org.exist.http.webdav.methods; -import java.io.IOException; -import java.io.OutputStream; -import java.io.StringWriter; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.TimeZone; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Result; -import javax.xml.transform.Source; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - import org.exist.EXistException; import org.exist.collections.Collection; import org.exist.dom.DocumentImpl; @@ -74,6 +46,33 @@ import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.OutputStream; +import java.io.StringWriter; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; + /** * Implements the WebDAV PROPFIND method. * @@ -152,126 +151,124 @@ DocumentImpl resource = null; try { broker = pool.get(user); - synchronized (pool.getCollectionsCache()) { - // open the collection or resource specified in the path - collection = broker.openCollection(path, Lock.READ_LOCK); + // open the collection or resource specified in the path + collection = broker.openCollection(path, Lock.READ_LOCK); + if(collection == null) { + ///TODO : use dedicated function in XmldbURI + // no collection found: check for a resource + XmldbURI docUri = path.lastSegment(); + XmldbURI collUri = path.removeLastSegment(); + collection = broker.openCollection(collUri, Lock.READ_LOCK); if(collection == null) { - ///TODO : use dedicated function in XmldbURI - // no collection found: check for a resource - XmldbURI docUri = path.lastSegment(); - XmldbURI collUri = path.removeLastSegment(); - collection = broker.openCollection(collUri, Lock.READ_LOCK); - if(collection == null) { - LOG.debug("No resource or collection found for path: " + path); - response.sendError(HttpServletResponse.SC_NOT_FOUND, NOT_FOUND_ERR); - return; - } - resource = collection.getDocumentWithLock(broker, docUri, Lock.READ_LOCK); - if(resource == null) { - LOG.debug("No resource found for path: " + path); - response.sendError(HttpServletResponse.SC_NOT_FOUND, NOT_FOUND_ERR); - return; - } + LOG.debug("No resource or collection found for path: " + path); + response.sendError(HttpServletResponse.SC_NOT_FOUND, NOT_FOUND_ERR); + return; } - if(!collection.getPermissions().validate(user, Permission.READ)) { - response.sendError(HttpServletResponse.SC_FORBIDDEN); + resource = collection.getDocumentWithLock(broker, docUri, Lock.READ_LOCK); + if(resource == null) { + LOG.debug("No resource found for path: " + path); + response.sendError(HttpServletResponse.SC_NOT_FOUND, NOT_FOUND_ERR); return; } - //TODO : release collection lock here ? - //Take care however : collection is still used below - - // parse the request contents - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); - docFactory.setNamespaceAware(true); - DocumentBuilder docBuilder; - try { - docBuilder = docFactory.newDocumentBuilder(); - } catch (ParserConfigurationException e1) { - throw new ServletException(WebDAVUtil.XML_CONFIGURATION_ERR, e1); - } - Document doc = WebDAVUtil.parseRequestContent(request, response, docBuilder); - - int type = FIND_ALL_PROPERTIES; - DAVProperties searchedProperties = new DAVProperties(); - + } + if(!collection.getPermissions().validate(user, Permission.READ)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN); + return; + } + //TODO : release collection lock here ? + //Take care however : collection is still used below + + // parse the request contents + DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); + docFactory.setNamespaceAware(true); + DocumentBuilder docBuilder; + try { + docBuilder = docFactory.newDocumentBuilder(); + } catch (ParserConfigurationException e1) { + throw new ServletException(WebDAVUtil.XML_CONFIGURATION_ERR, e1); + } + Document doc = WebDAVUtil.parseRequestContent(request, response, docBuilder); + + int type = FIND_ALL_PROPERTIES; + DAVProperties searchedProperties = new DAVProperties(); + // LOG.debug("input:\n"+xmlToString(doc)); - - if(doc != null) { - Element propfind = doc.getDocumentElement(); - if(!(propfind.getLocalName().equals("propfind") && - propfind.getNamespaceURI().equals(WebDAV.DAV_NS))) { - LOG.debug(WebDAVUtil.UNEXPECTED_ELEMENT_ERR + propfind.getNodeName()); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, - WebDAVUtil.UNEXPECTED_ELEMENT_ERR + propfind.getNodeName()); - return; - } - - NodeList childNodes = propfind.getChildNodes(); - for(int i = 0; i < childNodes.getLength(); i++) { - Node currentNode = childNodes.item(i); - if(currentNode.getNodeType() == Node.ELEMENT_NODE) { - if(currentNode.getNamespaceURI().equals(WebDAV.DAV_NS)) { - if(currentNode.getLocalName().equals("prop")) { - type = FIND_BY_PROPERTY; - getPropertyNames(currentNode, searchedProperties); - } - if(currentNode.getLocalName().equals("allprop")) - type = FIND_ALL_PROPERTIES; - if(currentNode.getLocalName().equals("propname")) - type = FIND_PROPERTY_NAMES; - } else { - // Found an unknown element: return with 400 Bad Request - LOG.debug("Unexpected child: " + currentNode.getNodeName()); - response.sendError(HttpServletResponse.SC_BAD_REQUEST, - WebDAVUtil.UNEXPECTED_ELEMENT_ERR + currentNode.getNodeName()); - return; + + if(doc != null) { + Element propfind = doc.getDocumentElement(); + if(!(propfind.getLocalName().equals("propfind") && + propfind.getNamespaceURI().equals(WebDAV.DAV_NS))) { + LOG.debug(WebDAVUtil.UNEXPECTED_ELEMENT_ERR + propfind.getNodeName()); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, + WebDAVUtil.UNEXPECTED_ELEMENT_ERR + propfind.getNodeName()); + return; + } + + NodeList childNodes = propfind.getChildNodes(); + for(int i = 0; i < childNodes.getLength(); i++) { + Node currentNode = childNodes.item(i); + if(currentNode.getNodeType() == Node.ELEMENT_NODE) { + if(currentNode.getNamespaceURI().equals(WebDAV.DAV_NS)) { + if(currentNode.getLocalName().equals("prop")) { + type = FIND_BY_PROPERTY; + getPropertyNames(currentNode, searchedProperties); } + if(currentNode.getLocalName().equals("allprop")) + type = FIND_ALL_PROPERTIES; + if(currentNode.getLocalName().equals("propname")) + type = FIND_PROPERTY_NAMES; + } else { + // Found an unknown element: return with 400 Bad Request + LOG.debug("Unexpected child: " + currentNode.getNodeName()); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, + WebDAVUtil.UNEXPECTED_ELEMENT_ERR + currentNode.getNodeName()); + return; } } } - - // write response - String servletPath = getServletPath(request); - int depth = getDepth(request); - StringWriter os = new StringWriter(); - SAXSerializer serializer = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class); - try { - serializer.setOutput(os, WebDAV.OUTPUT_PROPERTIES); - AttributesImpl attrs = new AttributesImpl(); - serializer.startDocument(); - serializer.startPrefixMapping(PREFIX, WebDAV.DAV_NS); - serializer.startElement(WebDAV.DAV_NS, "multistatus", "D:multistatus", attrs); - - if(type == FIND_ALL_PROPERTIES || type == FIND_BY_PROPERTY) { - if(resource != null) - writeResourceProperties(user, searchedProperties, type, collection, resource, serializer, servletPath); - else - writeCollectionProperties(user, broker, searchedProperties, type, collection, serializer, servletPath, depth, 0); - } else if(type == FIND_PROPERTY_NAMES) - writePropertyNames(collection, resource, serializer, servletPath); - - serializer.endElement(WebDAV.DAV_NS, "multistatus", "D:multistatus"); - serializer.endPrefixMapping(PREFIX); - serializer.endDocument(); - } catch (SAXException e) { - throw new ServletException("Exception while writing multistatus response: " + e.getMessage(), e); - } finally { - SerializerPool.getInstance().returnObject(serializer); - } - String content = os.toString(); -// LOG.debug("response:\n" + content); - writeResponse(response, content); } + + // write response + String servletPath = getServletPath(request); + int depth = getDepth(request); + StringWriter os = new StringWriter(); + SAXSerializer serializer = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class); + try { + serializer.setOutput(os, WebDAV.OUTPUT_PROPERTIES); + AttributesImpl attrs = new AttributesImpl(); + serializer.startDocument(); + serializer.startPrefixMapping(PREFIX, WebDAV.DAV_NS); + serializer.startElement(WebDAV.DAV_NS, "multistatus", "D:multistatus", attrs); + + if(type == FIND_ALL_PROPERTIES || type == FIND_BY_PROPERTY) { + if(resource != null) + writeResourceProperties(user, searchedProperties, type, collection, resource, serializer, servletPath); + else + writeCollectionProperties(user, broker, searchedProperties, type, collection, serializer, servletPath, depth, 0); + } else if(type == FIND_PROPERTY_NAMES) + writePropertyNames(collection, resource, serializer, servletPath); + + serializer.endElement(WebDAV.DAV_NS, "multistatus", "D:multistatus"); + serializer.endPrefixMapping(PREFIX); + serializer.endDocument(); + } catch (SAXException e) { + throw new ServletException("Exception while writing multistatus response: " + e.getMessage(), e); + } finally { + SerializerPool.getInstance().returnObject(serializer); + } + String content = os.toString(); +// LOG.debug("response:\n" + content); + writeResponse(response, content); } catch (EXistException e) { throw new ServletException(e.getMessage(), e); } catch (LockException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); } finally { + pool.release(broker); if(resource != null) resource.getUpdateLock().release(Lock.READ_LOCK); if(collection != null) collection.release(Lock.READ_LOCK); - pool.release(broker); } } Modified: trunk/eXist/src/org/exist/http/webdav/methods/Put.java =================================================================== --- trunk/eXist/src/org/exist/http/webdav/methods/Put.java 2008-08-22 00:18:03 UTC (rev 8102) +++ trunk/eXist/src/org/exist/http/webdav/methods/Put.java 2008-08-22 17:13:17 UTC (rev 8103) @@ -21,17 +21,6 @@ */ package org.exist.http.webdav.methods; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.ServletInputStream; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import org.exist.EXistException; import org.exist.collections.Collection; import org.exist.collections.IndexInfo; @@ -53,6 +42,16 @@ import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import javax.servlet.ServletException; +import javax.servlet.ServletInputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + /** * Implements the WebDAV PUT method. * @@ -121,7 +120,7 @@ mime = MimeType.BINARY_TYPE; } - + LOG.debug("Storing document " + pathUri + "; content-type='" + contentType+"'"); DocumentImpl doc = null; @@ -199,9 +198,9 @@ return; } finally { + pool.release(broker); if(collectionLocked && collection != null) collection.release(Lock.READ_LOCK); - pool.release(broker); tempFile.delete(); } response.setStatus(HttpServletResponse.SC_CREATED); Modified: trunk/eXist/src/org/exist/storage/BrokerPool.java =================================================================== --- trunk/eXist/src/org/exist/storage/BrokerPool.java 2008-08-22 00:18:03 UTC (rev 8102) +++ trunk/eXist/src/org/exist/storage/BrokerPool.java 2008-08-22 17:13:17 UTC (rev 8103) @@ -42,14 +42,25 @@ import org.exist.storage.txn.TransactionException; import org.exist.storage.txn.TransactionManager; import org.exist.storage.txn.Txn; -import org.exist.util.*; +import org.exist.util.Configuration; +import org.exist.util.DatabaseConfigurationException; +import org.exist.util.ReadOnlyException; +import org.exist.util.XMLReaderObjectFactory; +import org.exist.util.XMLReaderPool; import org.exist.xmldb.ShutdownListener; import org.exist.xmldb.XmldbURI; import java.io.File; import java.io.IOException; import java.text.NumberFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.TreeMap; +import java.util.Vector; /** * This class controls all available instances of the database. * Use it to configure, start and stop database instances. @@ -1072,7 +1083,7 @@ */ //TODO : rename as getBroker ? getInstance (when refactored) ? public DBBroker get(User user) throws EXistException { - if (!isInstanceConfigured()) + if (!isInstanceConfigured()) throw new EXistException("database instance '" + instanceName + "' is not available"); //Try to get an active broker @@ -1115,7 +1126,7 @@ } } } - broker = (DBBroker) inactiveBrokers.pop(); + broker = (DBBroker) inactiveBrokers.pop(); //activate the broker activeBrokers.put(Thread.currentThread(), broker); broker.incReferenceCount(); @@ -1126,7 +1137,7 @@ return broker; } } - + /** * Releases a broker for the database instance. If it is no more used, make if invactive. * If there are pending system maintenance tasks, @@ -1146,10 +1157,16 @@ if(broker.getReferenceCount() > 0) { //it is still in use and thus can't be marked as inactive return; - } - //Broker is no more used : inactivate it + } + //Broker is no more used : inactivate it synchronized (this) { - activeBrokers.remove(Thread.currentThread()); + for (int i = 0; i < inactiveBrokers.size(); i++) { + if (broker == inactiveBrokers.get(i)) { + LOG.error("Broker is already in the inactive list!!!"); + return; + } + } + activeBrokers.remove(Thread.currentThread()); inactiveBrokers.push(broker); //If the database is now idle, do some useful stuff if(activeBrokers.size() == 0) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2008-08-25 20:26:28
|
Revision: 8109 http://exist.svn.sourceforge.net/exist/?rev=8109&view=rev Author: wolfgang_m Date: 2008-08-25 20:19:54 +0000 (Mon, 25 Aug 2008) Log Message: ----------- [bugfix] using a different pageSize in conf.xml can cause corruptions in the fulltext and ngram indexes. Reason: pageSize was not properly set for those index files; it needs to be set early during database startup. Port of rev 8085 from 1.2 branch. Revision Links: -------------- http://exist.svn.sourceforge.net/exist/?rev=8085&view=rev Modified Paths: -------------- trunk/eXist/src/org/exist/dom/DocumentImpl.java trunk/eXist/src/org/exist/storage/BrokerPool.java trunk/eXist/src/org/exist/storage/DBBroker.java trunk/eXist/src/org/exist/storage/DefaultCacheManager.java trunk/eXist/src/org/exist/storage/NativeBroker.java trunk/eXist/src/org/exist/storage/btree/BTree.java trunk/eXist/src/org/exist/storage/btree/Paged.java trunk/eXist/src/org/exist/storage/dom/DOMFile.java trunk/eXist/src/org/exist/storage/index/BFile.java trunk/eXist/src/org/exist/util/Configuration.java Modified: trunk/eXist/src/org/exist/dom/DocumentImpl.java =================================================================== --- trunk/eXist/src/org/exist/dom/DocumentImpl.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/dom/DocumentImpl.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -382,7 +382,7 @@ * */ public int getContentLength() { - int length = getMetadata().getPageCount() * broker.getPageSize(); + int length = getMetadata().getPageCount() * broker.getBrokerPool().getPageSize(); return (length<0) ? 0 : length; } Modified: trunk/eXist/src/org/exist/storage/BrokerPool.java =================================================================== --- trunk/eXist/src/org/exist/storage/BrokerPool.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/BrokerPool.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -323,7 +323,10 @@ public final long DEFAULT_MAX_SHUTDOWN_WAIT = 45000; //TODO : move this default setting to org.exist.collections.CollectionCache ? public final int DEFAULT_COLLECTION_BUFFER_SIZE = 128; - + + public static final String PROPERTY_PAGE_SIZE = "db-connection.page-size"; + public static final int DEFAULT_PAGE_SIZE = 4096; + /** * <code>true</code> if the database instance is able to handle transactions. */ @@ -391,6 +394,8 @@ //TODO : for now, this member is used for recovery management private boolean isReadOnly; + private int pageSize; + private FileLock dataLock; /** @@ -560,7 +565,10 @@ } LOG.info("database instance '" + instanceName + "' is enabled for transactions : " + this.transactionsEnabled); - + pageSize = conf.getInteger(PROPERTY_PAGE_SIZE); + if (pageSize < 0) + pageSize = DEFAULT_PAGE_SIZE; + /* TODO: start -adam- remove OLD SystemTask initialization */ //How ugly : needs refactoring... @@ -853,6 +861,10 @@ public long getReservedMem() { return reservedMem - cacheManager.getSizeInBytes(); } + + public int getPageSize() { + return pageSize; + } /** * Whether or not the database instance is being initialized. Modified: trunk/eXist/src/org/exist/storage/DBBroker.java =================================================================== --- trunk/eXist/src/org/exist/storage/DBBroker.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/DBBroker.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -749,8 +749,6 @@ public void decReferenceCount() { --referenceCount; } - - public abstract int getPageSize(); public abstract IndexSpec getIndexConfiguration(); Modified: trunk/eXist/src/org/exist/storage/DefaultCacheManager.java =================================================================== --- trunk/eXist/src/org/exist/storage/DefaultCacheManager.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/DefaultCacheManager.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -118,9 +118,9 @@ public DefaultCacheManager(BrokerPool pool) { this.instanceName = pool.getId(); int cacheSize; - if ((pageSize = pool.getConfiguration().getInteger(NativeBroker.PROPERTY_PAGE_SIZE)) < 0) + if ((pageSize = pool.getConfiguration().getInteger(BrokerPool.PROPERTY_PAGE_SIZE)) < 0) //TODO : should we share the page size with the native broker ? - pageSize = NativeBroker.DEFAULT_PAGE_SIZE; + pageSize = BrokerPool.DEFAULT_PAGE_SIZE; if ((cacheSize = pool.getConfiguration().getInteger(PROPERTY_CACHE_SIZE)) < 0) { cacheSize = DEFAULT_CACHE_SIZE; } Modified: trunk/eXist/src/org/exist/storage/NativeBroker.java =================================================================== --- trunk/eXist/src/org/exist/storage/NativeBroker.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/NativeBroker.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -133,8 +133,7 @@ public static final String PAGE_SIZE_ATTRIBUTE = "pageSize"; public static final String INDEX_DEPTH_ATTRIBUTE = "index-depth"; - - public static final String PROPERTY_PAGE_SIZE = "db-connection.page-size"; + public static final String PROPERTY_INDEX_DEPTH = "indexer.index-depth"; private static final byte[] ALL_STORAGE_FILES = { @@ -147,7 +146,6 @@ private static final String DATABASE_IS_READ_ONLY = "database is read-only"; public static final String DEFAULT_DATA_DIR = "data"; - public static final int DEFAULT_PAGE_SIZE = 4096; public static final int DEFAULT_INDEX_DEPTH = 1; public static final int DEFAULT_MIN_MEMORY = 5000000; public static final long TEMP_FRAGMENT_TIMEOUT = 60000; @@ -180,7 +178,6 @@ protected int nodesCount = 0; protected String dataDir; - protected int pageSize; protected byte prepend; @@ -208,11 +205,6 @@ if (dataDir == null) dataDir = DEFAULT_DATA_DIR; - pageSize = config.getInteger(PROPERTY_PAGE_SIZE); - if (pageSize < 0) - pageSize = DEFAULT_PAGE_SIZE; - Paged.setPageSize(pageSize); - defaultIndexDepth = config.getInteger(PROPERTY_INDEX_DEPTH); if (defaultIndexDepth < 0) defaultIndexDepth = DEFAULT_INDEX_DEPTH; @@ -425,12 +417,8 @@ public boolean isReadOnly() { return readOnly; - } + } - public int getPageSize() { - return pageSize; - } - public DOMFile getDOMFile() { return domDb; } Modified: trunk/eXist/src/org/exist/storage/btree/BTree.java =================================================================== --- trunk/eXist/src/org/exist/storage/btree/BTree.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/btree/BTree.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -174,7 +174,7 @@ protected BTree(BrokerPool pool, byte fileId, boolean transactional, DefaultCacheManager cacheManager, double growthThreshold) throws DBException { - super(); + super(pool); this.pool = pool; this.cacheManager = cacheManager; this.buffers = cacheManager.getDefaultInitialSize(); @@ -2283,34 +2283,13 @@ //////////////////////////////////////////////////////////////////// /** - * @see org.exist.storage.btree.Paged#createFileHeader() + * @see org.exist.storage.btree.Paged#createFileHeader(int pageSize) */ - public FileHeader createFileHeader() { - return new BTreeFileHeader(PAGE_SIZE); + public FileHeader createFileHeader(int pageSize) { + return new BTreeFileHeader(pageSize); } /** - * @see org.exist.storage.btree.Paged#createFileHeader(boolean) - */ - public FileHeader createFileHeader(boolean read) throws IOException { - return new BTreeFileHeader(read); - } - - /** - * @see org.exist.storage.btree.Paged#createFileHeader(long) - */ - public FileHeader createFileHeader(long pageCount) { - return new BTreeFileHeader(pageCount, PAGE_SIZE); - } - - /** - * @see org.exist.storage.btree.Paged#createFileHeader(long, int) - */ - public FileHeader createFileHeader(long pageCount, int pageSize) { - return new BTreeFileHeader(pageCount, pageSize); - } - - /** * @see org.exist.storage.btree.Paged#createPageHeader() */ public PageHeader createPageHeader() { @@ -2372,7 +2351,7 @@ } public BTreeFileHeader(int pageSize) { - super(pageSize); + super(1024, pageSize); } public BTreeFileHeader(boolean read) throws IOException { Modified: trunk/eXist/src/org/exist/storage/btree/Paged.java =================================================================== --- trunk/eXist/src/org/exist/storage/btree/Paged.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/btree/Paged.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -73,6 +73,7 @@ */ import org.apache.log4j.Logger; +import org.exist.storage.BrokerPool; import org.exist.storage.journal.Lsn; import org.exist.util.ByteConversion; import org.exist.xquery.Constants; @@ -133,22 +134,17 @@ private byte[] tempPageData = null; private byte[] tempHeaderData = null; - public Paged() { - fileHeader = createFileHeader(); + public Paged(BrokerPool pool) { + fileHeader = createFileHeader(pool.getPageSize()); tempPageData = new byte[fileHeader.pageSize]; tempHeaderData = new byte[fileHeader.pageHeaderSize]; - } + } - public Paged(File file) throws DBException { - this(); - setFile(file); - } - public abstract short getFileVersion(); public final static void setPageSize(int pageSize) { - PAGE_SIZE = pageSize; - } + PAGE_SIZE = pageSize; + } public final static int getPageSize() { return PAGE_SIZE; @@ -176,7 +172,7 @@ public boolean create() throws DBException { try { fileHeader.write(); - return true; + return true; } catch (Exception e) { e.printStackTrace(); throw new DBException(0, "Error creating " + file.getName()); @@ -189,38 +185,9 @@ * *@return a new FileHeader */ - public abstract FileHeader createFileHeader(); + public abstract FileHeader createFileHeader(int pageSize); /** - * createFileHeader must be implemented by a Paged implementation in order - * to create an appropriate subclass instance of a FileHeader. - * - *@param read If true, reads the FileHeader from disk - *@return a new FileHeader - *@throws IOException if an exception occurs - */ - public abstract FileHeader createFileHeader(boolean read) throws IOException; - - /** - * createFileHeader must be implemented by a Paged implementation in order - * to create an appropriate subclass instance of a FileHeader. - * - *@param pageCount The number of pages to allocate for primary storage - *@return a new FileHeader - */ - public abstract FileHeader createFileHeader(long pageCount); - - /** - * createFileHeader must be implemented by a Paged implementation in order - * to create an appropriate subclass instance of a FileHeader. - * - *@param pageCount The number of pages to allocate for primary storage - *@param pageSize The size of a Page (should be a multiple of a FS block) - *@return a new FileHeader - */ - public abstract FileHeader createFileHeader(long pageCount, int pageSize); - - /** * createPageHeader must be implemented by a Paged implementation in order * to create an appropriate subclass instance of a PageHeader. * @@ -373,7 +340,7 @@ try { if (exists()) { fileHeader.read(); - if(fileHeader.getVersion() != expectedVersion) + if(fileHeader.getVersion() != expectedVersion) throw new DBException("Database file " + getFile().getName() + " has a storage format incompatible with this " + "version of eXist. Please do a backup/restore of your data first."); @@ -536,7 +503,7 @@ if (data.length != hdr.dataLen) { //TODO : where to get this 64 from ? if (hdr.dataLen != getPageSize() - 64) - LOG.warn("ouch"); + LOG.warn("ouch: " + fileHeader.workSize + " != " + data.length); hdr.dataLen = data.length; } page.write(data); Modified: trunk/eXist/src/org/exist/storage/dom/DOMFile.java =================================================================== --- trunk/eXist/src/org/exist/storage/dom/DOMFile.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/dom/DOMFile.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -1208,8 +1208,8 @@ return false; } - public FileHeader createFileHeader() { - return new BTreeFileHeader(1024, PAGE_SIZE); + public FileHeader createFileHeader(int pageSize) { + return new BTreeFileHeader(1024, pageSize); } protected void unlinkPages(Page page) throws IOException { Modified: trunk/eXist/src/org/exist/storage/index/BFile.java =================================================================== --- trunk/eXist/src/org/exist/storage/index/BFile.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/storage/index/BFile.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -309,19 +309,7 @@ } } - public FileHeader createFileHeader() { - return new BFileHeader(PAGE_SIZE); - } - - public FileHeader createFileHeader(boolean read) throws IOException { - return new BFileHeader(PAGE_SIZE); - } - - public FileHeader createFileHeader(long pageCount) { - return new BFileHeader(PAGE_SIZE); - } - - public FileHeader createFileHeader(long pageCount, int pageSize) { + public FileHeader createFileHeader(int pageSize) { return new BFileHeader(pageSize); } @@ -1460,7 +1448,7 @@ public final static int MAX_FREE_LIST_LEN = 128; public BFileHeader(int pageSize) { - super(); + super(pageSize); } public void addFreeSpace(FreeSpace freeSpace) { Modified: trunk/eXist/src/org/exist/util/Configuration.java =================================================================== --- trunk/eXist/src/org/exist/util/Configuration.java 2008-08-25 20:07:55 UTC (rev 8108) +++ trunk/eXist/src/org/exist/util/Configuration.java 2008-08-25 20:19:54 UTC (rev 8109) @@ -21,25 +21,7 @@ */ package org.exist.util; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; - import org.apache.log4j.Logger; - import org.exist.Indexer; import org.exist.cluster.ClusterComunication; import org.exist.cluster.journal.JournalManager; @@ -70,19 +52,32 @@ import org.exist.xquery.XQueryContext; import org.exist.xquery.XQueryWatchDog; import org.exist.xslt.TransformerFactoryAllocator; - import org.quartz.SimpleTrigger; - import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; - import org.xml.sax.ErrorHandler; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.XMLReader; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Properties; + public class Configuration implements ErrorHandler { private final static Logger LOG = Logger.getLogger(Configuration.class); //Logger @@ -707,8 +702,8 @@ String pageSize = con.getAttribute(NativeBroker.PAGE_SIZE_ATTRIBUTE); if (pageSize != null) { try { - config.put(NativeBroker.PROPERTY_PAGE_SIZE, new Integer(pageSize)); - LOG.debug(NativeBroker.PROPERTY_PAGE_SIZE + ": " + config.get(NativeBroker.PROPERTY_PAGE_SIZE)); + config.put(BrokerPool.PROPERTY_PAGE_SIZE, new Integer(pageSize)); + LOG.debug(BrokerPool.PROPERTY_PAGE_SIZE + ": " + config.get(BrokerPool.PROPERTY_PAGE_SIZE)); } catch (NumberFormatException nfe) { LOG.warn(nfe); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <di...@us...> - 2008-09-07 10:14:52
|
Revision: 8158 http://exist.svn.sourceforge.net/exist/?rev=8158&view=rev Author: dizzzz Date: 2008-09-07 10:14:50 +0000 (Sun, 07 Sep 2008) Log Message: ----------- [bugfix] when deployed in tomcat, the webstart code was not able to find the locations of the jar files Modified Paths: -------------- trunk/eXist/src/org/exist/start/LatestFileResolver.java trunk/eXist/src/org/exist/webstart/JnlpHelper.java trunk/eXist/src/org/exist/webstart/JnlpServlet.java Modified: trunk/eXist/src/org/exist/start/LatestFileResolver.java =================================================================== --- trunk/eXist/src/org/exist/start/LatestFileResolver.java 2008-09-07 10:11:44 UTC (rev 8157) +++ trunk/eXist/src/org/exist/start/LatestFileResolver.java 2008-09-07 10:14:50 UTC (rev 8158) @@ -87,7 +87,11 @@ return matches.find(); } }); - if (jars.length > 0) { + + if(jars==null){ + System.err.println("ERROR: No jars found in "+containerDir.getAbsolutePath()); + + } else if (jars.length > 0) { String actualFileName = jars[0].getAbsolutePath(); if (_debug) { System.err.println( Modified: trunk/eXist/src/org/exist/webstart/JnlpHelper.java =================================================================== --- trunk/eXist/src/org/exist/webstart/JnlpHelper.java 2008-09-07 10:11:44 UTC (rev 8157) +++ trunk/eXist/src/org/exist/webstart/JnlpHelper.java 2008-09-07 10:14:50 UTC (rev 8158) @@ -25,8 +25,6 @@ import java.io.File; import org.apache.log4j.Logger; -import org.exist.util.ConfigurationHelper; -import org.exist.util.SingleInstanceConfiguration; /** * Helper class for webstart. @@ -35,39 +33,51 @@ */ public class JnlpHelper { + private final static String LIB_CORE ="../lib/core"; + private final static String LIB_EXIST =".."; + private final static String LIB_WEBINF="WEB-INF/lib/"; + private static Logger logger = Logger.getLogger(JnlpHelper.class); - private File existHome = ConfigurationHelper.getExistHome(); private File coreJarsFolder=null; private File existJarFolder=null; - private File webappFolder=null; + private File webappsFolder=null; + + private boolean isInWarFile(File existHome){ + + if( new File(existHome, LIB_CORE).isDirectory() ) { + return false; + } + return true; + } + /** Creates a new instance of JnlpHelper */ - public JnlpHelper() { + public JnlpHelper(File contextRoot) { // Setup path based on installation (in jetty, container) - if(SingleInstanceConfiguration.isInWarFile()){ - // all files mixed in existHome/lib/ - logger.debug("eXist is running in container (.war)."); - coreJarsFolder= new File(existHome, "lib/"); - existJarFolder= new File(existHome, "lib/"); + if(isInWarFile(contextRoot)){ + // all files mixed in contextRoot/WEB-INF/lib + logger.debug("eXist is running in servlet container (.war)."); + coreJarsFolder= new File(contextRoot, LIB_WEBINF); + existJarFolder= coreJarsFolder; + webappsFolder=contextRoot; } else { - // all files located in existHome/lib/core/ + //files located in contextRoot/lib/core and contextRoot logger.debug("eXist is running private jetty server."); - coreJarsFolder= new File(existHome, "lib/core"); - existJarFolder= existHome; + coreJarsFolder= new File(contextRoot, LIB_CORE); + existJarFolder= new File(contextRoot, LIB_EXIST);; + webappsFolder=contextRoot; } - webappFolder=SingleInstanceConfiguration.getWebappHome(); - logger.debug("CORE jars location="+coreJarsFolder.getAbsolutePath()); logger.debug("EXIST jars location="+existJarFolder.getAbsolutePath()); - logger.debug("WEBAPP location="+webappFolder.getAbsolutePath()); + logger.debug("WEBAPP location="+webappsFolder.getAbsolutePath()); } public File getWebappFolder(){ - return webappFolder; + return webappsFolder; } public File getCoreJarsFolder(){ Modified: trunk/eXist/src/org/exist/webstart/JnlpServlet.java =================================================================== --- trunk/eXist/src/org/exist/webstart/JnlpServlet.java 2008-09-07 10:11:44 UTC (rev 8157) +++ trunk/eXist/src/org/exist/webstart/JnlpServlet.java 2008-09-07 10:14:50 UTC (rev 8158) @@ -22,6 +22,7 @@ package org.exist.webstart; +import java.io.File; import java.io.IOException; import javax.servlet.ServletException; @@ -42,12 +43,19 @@ private JnlpHelper jh=null; /** - * Initialize servlet. + * Initialize servlet.cd */ public void init() { logger.info("Initializing JNLP servlet"); - jh = new JnlpHelper(); + String realPath = getServletContext().getRealPath("/"); + if(realPath==null){ + logger.error("getServletContext().getRealPath() did not return a "+ + "value. Webstart is not available."); + } + File contextRoot=new File( realPath ); + + jh = new JnlpHelper(contextRoot); jf = new JnlpJarFiles(jh); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ch...@us...> - 2008-10-17 16:03:38
|
Revision: 8235 http://exist.svn.sourceforge.net/exist/?rev=8235&view=rev Author: chaeron Date: 2008-10-17 16:03:27 +0000 (Fri, 17 Oct 2008) Log Message: ----------- Added new system:get-running-xqueries() and system:kill-running-xquery() xquery functions. Also instrumented various XQuery source files to keep track of the type and source of the query. Modified Paths: -------------- trunk/eXist/src/org/exist/storage/XQueryMonitor.java trunk/eXist/src/org/exist/xquery/XQuery.java trunk/eXist/src/org/exist/xquery/XQueryContext.java trunk/eXist/src/org/exist/xquery/XQueryWatchDog.java trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java Added Paths: ----------- trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java Modified: trunk/eXist/src/org/exist/storage/XQueryMonitor.java =================================================================== --- trunk/eXist/src/org/exist/storage/XQueryMonitor.java 2008-10-17 14:44:44 UTC (rev 8234) +++ trunk/eXist/src/org/exist/storage/XQueryMonitor.java 2008-10-17 16:03:27 UTC (rev 8235) @@ -67,4 +67,9 @@ watchdog.kill(waitTime); } } + + public Iterator getRunningXQueriesIterator() + { + return( runningQueries.iterator() ); + } } Modified: trunk/eXist/src/org/exist/xquery/XQuery.java =================================================================== --- trunk/eXist/src/org/exist/xquery/XQuery.java 2008-10-17 14:44:44 UTC (rev 8234) +++ trunk/eXist/src/org/exist/xquery/XQuery.java 2008-10-17 16:03:27 UTC (rev 8235) @@ -88,6 +88,13 @@ public CompiledXQuery compile(XQueryContext context, Source source, boolean xpointer) throws XPathException, IOException { + + String sourceClassName = source.getClass().getName(); + + context.setSourceKey( source.getKey().toString() ); + + // Extract the source type from the classname by removing the package prefix and the "Source" suffix + context.setSourceType( sourceClassName.substring( 17, sourceClassName.length() - 6 ) ); XACMLSource xsource = XACMLSource.getInstance(source); Reader reader = source.getReader(); Modified: trunk/eXist/src/org/exist/xquery/XQueryContext.java =================================================================== --- trunk/eXist/src/org/exist/xquery/XQueryContext.java 2008-10-17 14:44:44 UTC (rev 8234) +++ trunk/eXist/src/org/exist/xquery/XQueryContext.java 2008-10-17 16:03:27 UTC (rev 8235) @@ -344,6 +344,10 @@ private boolean isShared = false; + private String sourceKey = "unknown"; + + private String sourceType = "unknown"; + private XQueryContext() {} protected XQueryContext(AccessContext accessCtx) { @@ -556,7 +560,52 @@ return expressionCounter; } + /** + * Called from the XQuery compiler to set the XQuery Source key value + * for this context. + * + * @param key + */ + public void setSourceKey( String key ) + { + this.sourceKey = key; + } + /** + * Returns the Source Key of the XQuery associated with + * this context. + * + * @return source key + */ + public String getSourceKey() + { + return( sourceKey ); + } + + /** + * Called from the XQuery compiler to set the XQuery Source type value + * for this context. + * + * @param type + */ + public void setSourceType( String type ) + { + this.sourceType = type; + } + + /** + * Returns the Source Type of the XQuery associated with + * this context. + * + * @return source type + */ + public String getSourceType() + { + return( sourceType ); + } + + + /** * Declare a user-defined static prefix/namespace mapping. * * eXist internally keeps a table containing all prefix/namespace Modified: trunk/eXist/src/org/exist/xquery/XQueryWatchDog.java =================================================================== --- trunk/eXist/src/org/exist/xquery/XQueryWatchDog.java 2008-10-17 14:44:44 UTC (rev 8234) +++ trunk/eXist/src/org/exist/xquery/XQueryWatchDog.java 2008-10-17 16:03:27 UTC (rev 8235) @@ -163,4 +163,9 @@ startTime = System.currentTimeMillis(); terminate = false; } + + public boolean isTerminating() + { + return( terminate ); + } } Added: trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java (rev 0) +++ trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java 2008-10-17 16:03:27 UTC (rev 8235) @@ -0,0 +1,127 @@ +/* + * eXist Open Source Native XML Database + * Copyright (C) 2001-06 Wolfgang M. Meier + * wol...@ex... + * http://exist.sourceforge.net + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: + */ +package org.exist.xquery.functions.system; + +import org.exist.dom.QName; +import org.exist.memtree.DocumentBuilderReceiver; +import org.exist.memtree.MemTreeBuilder; +import org.exist.memtree.NodeImpl; +import org.exist.storage.BrokerPool; +import org.exist.xquery.BasicFunction; +import org.exist.xquery.Cardinality; +import org.exist.xquery.FunctionSignature; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.XQueryWatchDog; +import org.exist.xquery.value.NodeValue; +import org.exist.xquery.value.Sequence; +import org.exist.xquery.value.SequenceType; +import org.exist.xquery.value.Type; + +import java.io.UnsupportedEncodingException; +import java.util.Iterator; +import java.net.URLEncoder; + +/** + * Return a list of the currently running XQueries (must be dba) + * + * @author Andrzej Taramina (an...@ch...) + */ +public class GetRunningXQueries extends BasicFunction +{ + final static String NAMESPACE_URI = SystemModule.NAMESPACE_URI; + final static String PREFIX = SystemModule.PREFIX; + + + public final static FunctionSignature signature = + new FunctionSignature( + new QName( "get-running-xqueries", SystemModule.NAMESPACE_URI, SystemModule.PREFIX ), + "Get a list of running XQueries (dba role only).", + null, + new SequenceType( Type.ITEM, Cardinality.EXACTLY_ONE ) + ); + + + public GetRunningXQueries( XQueryContext context, FunctionSignature signature ) + { + super( context, signature ); + } + + /* (non-Javadoc) + * @see org.exist.xquery.BasicFunction#eval(org.exist.xquery.value.Sequence[], org.exist.xquery.value.Sequence) + */ + public Sequence eval( Sequence[] args, Sequence contextSequence ) throws XPathException + { + if( !context.getUser().hasDbaRole() ) { + throw( new XPathException( getASTNode(), "Permission denied, calling user '" + context.getUser().getName() + "' must be a DBA to get the list of running xqueries" ) ); + } + + return( getRunningXQueries() ); + } + + + private Sequence getRunningXQueries() + { + Sequence xmlResponse = null; + + MemTreeBuilder builder = context.getDocumentBuilder(); + + builder.startDocument(); + builder.startElement( new QName( "xqueries", NAMESPACE_URI, PREFIX ), null ); + + //Add all the running xqueries + + for( Iterator i = getContext().getBroker().getBrokerPool().getXQueryMonitor().getRunningXQueriesIterator(); i.hasNext(); ) { + XQueryWatchDog watchdog = (XQueryWatchDog)i.next(); + XQueryContext context = watchdog.getContext(); + + getRunningXQuery( builder, context, watchdog ); + } + + builder.endElement(); + + xmlResponse = (NodeValue)builder.getDocument().getDocumentElement(); + + return( xmlResponse ); + } + + private void getRunningXQuery( MemTreeBuilder builder, XQueryContext context, XQueryWatchDog watchdog ) + { + builder.startElement( new QName( "xquery", NAMESPACE_URI, PREFIX ), null ); + + builder.addAttribute( new QName( "id", null, null ), "" + context.hashCode() ); + builder.addAttribute( new QName( "sourceType", null, null ), context.getSourceType() ); + builder.addAttribute( new QName( "terminating", null, null ), ( watchdog.isTerminating() ? "true" : "false" ) ); + + builder.startElement( new QName( "sourceKey", NAMESPACE_URI, PREFIX ), null ); + builder.characters( context.getSourceKey() ); + builder.endElement(); + + builder.startElement( new QName( "xqueryExpression", NAMESPACE_URI, PREFIX ), null ); + builder.characters( context.getRootExpression().toString() ); + builder.endElement(); + + builder.endElement(); + } + +} Added: trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java (rev 0) +++ trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java 2008-10-17 16:03:27 UTC (rev 8235) @@ -0,0 +1,133 @@ +/* + * eXist Open Source Native XML Database + * Copyright (C) 2001-06 Wolfgang M. Meier + * wol...@ex... + * http://exist.sourceforge.net + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: + */ +package org.exist.xquery.functions.system; + +import org.exist.dom.QName; +import org.exist.memtree.DocumentBuilderReceiver; +import org.exist.memtree.MemTreeBuilder; +import org.exist.memtree.NodeImpl; +import org.exist.storage.BrokerPool; +import org.exist.xquery.BasicFunction; +import org.exist.xquery.Cardinality; +import org.exist.xquery.FunctionSignature; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.XQueryWatchDog; +import org.exist.xquery.value.NodeValue; +import org.exist.xquery.value.NumericValue; +import org.exist.xquery.value.Sequence; +import org.exist.xquery.value.SequenceType; +import org.exist.xquery.value.Type; + +import java.util.Iterator; + + +/** + * Kill a running XQuery (must be dba) + * + * @author Andrzej Taramina (an...@ch...) + */ +public class KillRunningXQuery extends BasicFunction +{ + final static String NAMESPACE_URI = SystemModule.NAMESPACE_URI; + final static String PREFIX = SystemModule.PREFIX; + + + public final static FunctionSignature signatures[] = { + new FunctionSignature( + new QName( "kill-running-xquery", SystemModule.NAMESPACE_URI, SystemModule.PREFIX ), + "Kill a running XQuey (dba role only). $a is the XQuery ID obtained from get-running-xqueries()", + new SequenceType[] { + new SequenceType( Type.INTEGER, Cardinality.EXACTLY_ONE ) + }, + new SequenceType( Type.ITEM, Cardinality.EMPTY ) + ), + + new FunctionSignature( + new QName( "kill-running-xquery", SystemModule.NAMESPACE_URI, SystemModule.PREFIX ), + "Kill a running XQuey (dba role only). $a is the XQuery ID obtained from get-running-xqueries(), $b is the wait time in milliseconds", + new SequenceType[] { + new SequenceType( Type.INTEGER, Cardinality.EXACTLY_ONE ), + new SequenceType( Type.LONG, Cardinality.EXACTLY_ONE ) + }, + new SequenceType( Type.ITEM, Cardinality.EMPTY ) + ), + }; + + + + public KillRunningXQuery( XQueryContext context, FunctionSignature signature ) + { + super( context, signature ); + } + + /* (non-Javadoc) + * @see org.exist.xquery.BasicFunction#eval(org.exist.xquery.value.Sequence[], org.exist.xquery.value.Sequence) + */ + public Sequence eval( Sequence[] args, Sequence contextSequence ) throws XPathException + { + if( !context.getUser().hasDbaRole() ) { + throw( new XPathException( getASTNode(), "Permission denied, calling user '" + context.getUser().getName() + "' must be a DBA to kill a running xquery" ) ); + } + + killXQuery( args ); + + return( Sequence.EMPTY_SEQUENCE ); + } + + + private void killXQuery( Sequence[] args ) throws XPathException + { + int id = 0; + long waittime = 0; + + //determine the query id to kill + if( args.length == 1 ) { + if( !args[0].isEmpty() ) { + id = ((NumericValue)args[0].itemAt(0)).getInt(); + } + } + + //determine the wait time + if( args.length == 2 ) { + if( !args[1].isEmpty() ) { + waittime = ((NumericValue)args[1].itemAt(0)).getLong(); + } + } + + if( id != 0 ) { + for( Iterator i = getContext().getBroker().getBrokerPool().getXQueryMonitor().getRunningXQueriesIterator(); i.hasNext(); ) { + XQueryWatchDog watchdog = (XQueryWatchDog)i.next(); + XQueryContext context = watchdog.getContext(); + + if( id == context.hashCode() ) { + if( !watchdog.isTerminating() ) { + watchdog.kill( waittime ); + } + break; + } + } + } + } + +} Modified: trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java 2008-10-17 14:44:44 UTC (rev 8234) +++ trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java 2008-10-17 16:03:27 UTC (rev 8235) @@ -50,7 +50,10 @@ new FunctionDef(TriggerSystemTask.signature, TriggerSystemTask.class), new FunctionDef(AsUser.signature, AsUser.class), new FunctionDef(GetIndexStatistics.signature, GetIndexStatistics.class), - new FunctionDef(UpdateStatistics.signature, UpdateStatistics.class) + new FunctionDef(UpdateStatistics.signature, UpdateStatistics.class), + new FunctionDef(GetRunningXQueries.signature, GetRunningXQueries.class), + new FunctionDef(KillRunningXQuery.signatures[0], KillRunningXQuery.class), + new FunctionDef(KillRunningXQuery.signatures[1], KillRunningXQuery.class) }; public SystemModule() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2008-11-11 12:22:39
|
Revision: 8318 http://exist.svn.sourceforge.net/exist/?rev=8318&view=rev Author: wolfgang_m Date: 2008-11-11 11:44:17 +0000 (Tue, 11 Nov 2008) Log Message: ----------- [bugfix] fixed regression introduced by rev 8315. Revision Links: -------------- http://exist.svn.sourceforge.net/exist/?rev=8315&view=rev Modified Paths: -------------- trunk/eXist/src/org/exist/dom/VirtualNodeSet.java trunk/eXist/src/org/exist/xquery/BindingExpression.java trunk/eXist/src/org/exist/xquery/LocationStep.java Modified: trunk/eXist/src/org/exist/dom/VirtualNodeSet.java =================================================================== --- trunk/eXist/src/org/exist/dom/VirtualNodeSet.java 2008-11-09 22:04:40 UTC (rev 8317) +++ trunk/eXist/src/org/exist/dom/VirtualNodeSet.java 2008-11-11 11:44:17 UTC (rev 8318) @@ -605,6 +605,12 @@ */ public void setSelfIsContext() { useSelfAsContext = true; + if (realSet != null && realSetIsComplete) { + for (Iterator i = realSet.iterator(); i.hasNext();) { + NodeProxy p = (NodeProxy) i.next(); + p.addContextNode(contextId, p); + } + } } /** Modified: trunk/eXist/src/org/exist/xquery/BindingExpression.java =================================================================== --- trunk/eXist/src/org/exist/xquery/BindingExpression.java 2008-11-09 22:04:40 UTC (rev 8317) +++ trunk/eXist/src/org/exist/xquery/BindingExpression.java 2008-11-11 11:44:17 UTC (rev 8318) @@ -274,8 +274,8 @@ protected final static void setContext(int contextId, Sequence seq) { if (seq instanceof VirtualNodeSet) { - ((VirtualNodeSet)seq).setSelfIsContext(); ((VirtualNodeSet)seq).setInPredicate(true); + ((VirtualNodeSet)seq).setSelfIsContext(); } else { Item next; for (SequenceIterator i = seq.unorderedIterator(); i.hasNext();) { Modified: trunk/eXist/src/org/exist/xquery/LocationStep.java =================================================================== --- trunk/eXist/src/org/exist/xquery/LocationStep.java 2008-11-09 22:04:40 UTC (rev 8317) +++ trunk/eXist/src/org/exist/xquery/LocationStep.java 2008-11-11 11:44:17 UTC (rev 8318) @@ -401,8 +401,8 @@ if (Expression.NO_CONTEXT_ID != contextId) { if (contextSet instanceof VirtualNodeSet) { ((VirtualNodeSet) contextSet).setInPredicate(true); + ((VirtualNodeSet) contextSet).setContextId(contextId); ((VirtualNodeSet) contextSet).setSelfIsContext(); - ((VirtualNodeSet) contextSet).setContextId(contextId); } else if (Type.subTypeOf(contextSet.getItemType(), Type.NODE)) { NodeProxy p; for (Iterator i = contextSet.iterator(); i.hasNext();) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2008-11-30 17:36:29
|
Revision: 8339 http://exist.svn.sourceforge.net/exist/?rev=8339&view=rev Author: wolfgang_m Date: 2008-11-30 17:36:23 +0000 (Sun, 30 Nov 2008) Log Message: ----------- [general] updated Apache XMLRPC libraries from version 1.2 to 3.1.1; redesigned eXist's XMLRPC services to work with the new xmlrpc libs. For backwards compatibility, only small changes have been made to the XMLRPC API exposed by eXist. Most clients should work as before. Modified Paths: -------------- trunk/eXist/src/org/exist/StandaloneServer.java trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcDownload.java trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java trunk/eXist/src/org/exist/start/start.config trunk/eXist/src/org/exist/storage/serializers/Serializer.java trunk/eXist/src/org/exist/validation/service/RemoteValidationService.java trunk/eXist/src/org/exist/xmldb/CollectionImpl.java trunk/eXist/src/org/exist/xmldb/DatabaseImpl.java trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java trunk/eXist/src/org/exist/xmldb/RemoteCollection.java trunk/eXist/src/org/exist/xmldb/RemoteCollectionManagementService.java trunk/eXist/src/org/exist/xmldb/RemoteDatabaseInstanceManager.java trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java trunk/eXist/src/org/exist/xmldb/RemoteResourceIterator.java trunk/eXist/src/org/exist/xmldb/RemoteResourceSet.java trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java trunk/eXist/src/org/exist/xmldb/RemoteXMLResource.java trunk/eXist/src/org/exist/xmldb/RemoteXPathQueryService.java trunk/eXist/src/org/exist/xmldb/RemoteXUpdateQueryService.java trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java Added Paths: ----------- trunk/eXist/src/org/exist/xmlrpc/XmldbRequestProcessorFactory.java Removed Paths: ------------- trunk/eXist/src/org/exist/xmlrpc/AuthenticatedHandler.java trunk/eXist/src/org/exist/xmlrpc/RpcServer.java Modified: trunk/eXist/src/org/exist/StandaloneServer.java =================================================================== --- trunk/eXist/src/org/exist/StandaloneServer.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/StandaloneServer.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -47,7 +47,6 @@ import org.apache.avalon.excalibur.cli.CLOptionDescriptor; import org.apache.avalon.excalibur.cli.CLUtil; import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpc; import org.exist.memtree.SAXAdapter; import org.exist.storage.BrokerPool; import org.exist.util.Configuration; @@ -161,7 +160,6 @@ printHelp(); return; case DEBUG_OPT : - XmlRpc.setDebug(true); break; case HTTP_PORT_OPT : Properties httpListener = (Properties)listeners.get("http"); @@ -228,7 +226,6 @@ * Configures a minimal Jetty webserver (no webapplication support, * no file system access) and registers the WebDAV and REST servlets. * - * @param httpPort * @throws UnknownHostException * @throws IllegalArgumentException * @throws MultiException Modified: trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcDownload.java =================================================================== --- trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcDownload.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcDownload.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -26,10 +26,11 @@ import java.io.OutputStream; import java.util.Hashtable; import java.util.Vector; +import java.net.URL; import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpc; -import org.apache.xmlrpc.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import org.exist.protocolhandler.xmldb.XmldbURL; import org.exist.storage.io.ExistIOException; @@ -54,14 +55,19 @@ public void stream(XmldbURL xmldbURL, OutputStream os) throws IOException { LOG.debug("Begin document download"); try { + XmlRpcClient client = new XmlRpcClient(); + XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); + config.setEncoding("UTF-8"); + config.setEnabledForExtensions(true); + config.setServerURL(new URL(xmldbURL.getXmlRpcURL())); + // Setup client client - XmlRpc.setEncoding("UTF-8"); - XmlRpcClient client = new XmlRpcClient( xmldbURL.getXmlRpcURL() ); - - if(xmldbURL.hasUserInfo()){ - client.setBasicAuthentication(xmldbURL.getUsername(), xmldbURL.getPassword()); + if(xmldbURL.hasUserInfo()) { + config.setBasicUserName(xmldbURL.getUsername()); + config.setBasicPassword(xmldbURL.getPassword()); } - + client.setConfig(config); + // Setup xml serializer Hashtable options = new Hashtable(); options.put("indent", "no"); Modified: trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java =================================================================== --- trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/protocolhandler/xmlrpc/XmlrpcUpload.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -25,10 +25,13 @@ import java.io.IOException; import java.io.InputStream; import java.util.Vector; +import java.util.ArrayList; +import java.util.List; +import java.net.URL; import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpc; -import org.apache.xmlrpc.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import org.exist.protocolhandler.xmldb.XmldbURL; import org.exist.storage.io.ExistIOException; import org.exist.util.MimeTable; @@ -62,13 +65,18 @@ LOG.debug("Begin document upload"); try { // Setup xmlrpc client - XmlRpc.setEncoding("UTF-8"); - XmlRpcClient xmlrpc = new XmlRpcClient( xmldbURL.getXmlRpcURL() ); - - if(xmldbURL.hasUserInfo()){ - xmlrpc.setBasicAuthentication(xmldbURL.getUsername(), xmldbURL.getPassword()); + XmlRpcClient client = new XmlRpcClient(); + XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); + config.setEncoding("UTF-8"); + config.setEnabledForExtensions(true); + config.setServerURL(new URL(xmldbURL.getXmlRpcURL())); + + if(xmldbURL.hasUserInfo()) { + config.setBasicUserName(xmldbURL.getUsername()); + config.setBasicPassword(xmldbURL.getPassword()); } - + client.setConfig(config); + String contentType=MimeType.BINARY_TYPE.getName(); MimeType mime = MimeTable.getInstance().getContentTypeFor(xmldbURL.getDocumentName()); @@ -77,7 +85,7 @@ } // Initialize xmlrpc parameters - Vector params = new Vector(); + List params = new ArrayList(5); String handle=null; // Copy data from inputstream to database @@ -86,20 +94,20 @@ while ((len = is.read(buf)) > 0) { params.clear(); if(handle!=null){ - params.addElement(handle); + params.add(handle); } - params.addElement(buf); - params.addElement(new Integer(len)); - handle = (String)xmlrpc.execute("upload", params); + params.add(buf); + params.add(new Integer(len)); + handle = (String)client.execute("upload", params); } // All data transported, now parse data on server params.clear(); - params.addElement(handle); - params.addElement(xmldbURL.getCollectionPath() ); - params.addElement(Boolean.valueOf(true)); - params.addElement(contentType); - Boolean result =(Boolean)xmlrpc.execute("parseLocal", params); + params.add(handle); + params.add(xmldbURL.getCollectionPath() ); + params.add(Boolean.valueOf(true)); + params.add(contentType); + Boolean result =(Boolean)client.execute("parseLocal", params); // Check XMLRPC result if(result.booleanValue()){ Modified: trunk/eXist/src/org/exist/start/start.config =================================================================== --- trunk/eXist/src/org/exist/start/start.config 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/start/start.config 2008-11-30 17:36:23 UTC (rev 8339) @@ -41,7 +41,10 @@ lib/core/log4j-%latest%.jar always lib/core/sunxacml.jar always lib/core/xmldb.jar always -lib/core/xmlrpc-%latest%-patched.jar always +lib/core/xmlrpc-common-3.1.1.jar always +lib/core/xmlrpc-server-3.1.1.jar always +lib/core/xmlrpc-client-3.1.1.jar always +lib/core/ws-commons-util-1.0.2.jar always lib/core/jgroups-all.jar always lib/core/javax.servlet-1.4.jar always lib/core/jEdit-syntax.jar mode == client Modified: trunk/eXist/src/org/exist/storage/serializers/Serializer.java =================================================================== --- trunk/eXist/src/org/exist/storage/serializers/Serializer.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/storage/serializers/Serializer.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -88,6 +88,7 @@ import java.util.Iterator; import java.util.Map; import java.util.Properties; +import java.util.HashMap; /** * Serializer base class, used to serialize a document or document fragment @@ -233,7 +234,7 @@ } } - public void setProperties(Hashtable table) + public void setProperties(HashMap table) throws SAXNotRecognizedException, SAXNotSupportedException { if(table == null) return; Modified: trunk/eXist/src/org/exist/validation/service/RemoteValidationService.java =================================================================== --- trunk/eXist/src/org/exist/validation/service/RemoteValidationService.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/validation/service/RemoteValidationService.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -21,18 +21,18 @@ */ package org.exist.validation.service; -import java.io.IOException; -import java.util.Vector; - import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpcClient; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; import org.exist.validation.Validator; import org.exist.xmldb.RemoteCollection; import org.xmldb.api.base.Collection; import org.xmldb.api.base.ErrorCodes; import org.xmldb.api.base.XMLDBException; +import java.util.ArrayList; +import java.util.List; + /** * XML validation service for eXist database. * @@ -72,12 +72,12 @@ logger.info("Validating resource '" + documentPath + "'"); boolean documentIsValid = false; // documentPath = remoteCollection.getPathURI().resolveCollectionPath(documentPath); + + List params = new ArrayList(1); + params.add( documentPath ); - Vector params = new Vector(); - params.addElement( documentPath ); - if(grammarPath!=null){ - params.addElement( grammarPath ); + params.add( grammarPath ); } try { @@ -85,10 +85,8 @@ documentIsValid= result.booleanValue(); } catch (XmlRpcException xre) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); } - + return documentIsValid; } Modified: trunk/eXist/src/org/exist/xmldb/CollectionImpl.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/CollectionImpl.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/CollectionImpl.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -46,8 +46,6 @@ public void storeResource(Resource res, Date a, Date b) throws XMLDBException; - public XmldbURI getURI(); - public XmldbURI getPathURI(); Modified: trunk/eXist/src/org/exist/xmldb/DatabaseImpl.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/DatabaseImpl.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/DatabaseImpl.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -22,8 +22,8 @@ package org.exist.xmldb; import org.apache.log4j.Logger; -import org.apache.xmlrpc.XmlRpc; -import org.apache.xmlrpc.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClient; +import org.apache.xmlrpc.client.XmlRpcClientConfigImpl; import org.exist.EXistException; import org.exist.security.SecurityManager; import org.exist.security.User; @@ -83,11 +83,6 @@ protected int mode = UNKNOWN_CONNECTION; public DatabaseImpl() { - try { - //TODO : make this configurable - XmlRpc.setEncoding( "UTF-8" ); - } catch ( Exception e ) { - } String initdb = System.getProperty( "exist.initdb" ); if(initdb != null) autoCreate = initdb.equalsIgnoreCase("true"); @@ -286,14 +281,19 @@ * @throws XMLDBException */ private XmlRpcClient getRpcClient(String user, String password, URL url) throws XMLDBException { - String key = user + "@" + url.toString(); - XmlRpcClient client = (XmlRpcClient) rpcClients.get(key); - if (client == null) { - client = new XmlRpcClient(url); - rpcClients.put(key, client); - } - client.setBasicAuthentication(user, password); - return client; + String key = user + "@" + url.toString(); + XmlRpcClient client = (XmlRpcClient) rpcClients.get(key); + XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl(); + config.setEnabledForExtensions(true); + config.setServerURL(url); + config.setBasicUserName(user); + config.setBasicPassword(password); + if (client == null) { + client = new XmlRpcClient(); + rpcClients.put(key, client); + } + client.setConfig(config); + return client; } /** Modified: trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -116,10 +116,8 @@ data = (byte[])parent.getClient().execute("getBinaryResource", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - return data; + return data; } protected InputStream getStreamContent() { Modified: trunk/eXist/src/org/exist/xmldb/RemoteCollection.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteCollection.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteCollection.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -23,23 +23,8 @@ */ package org.exist.xmldb; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Date; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; -import java.util.Vector; - -import org.apache.xmlrpc.XmlRpcClient; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; import org.exist.security.Permission; import org.exist.security.PermissionFactory; import org.exist.util.Compressor; @@ -52,6 +37,21 @@ import org.xmldb.api.base.Service; import org.xmldb.api.base.XMLDBException; +import java.io.BufferedInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + /** * A remote implementation of the Collection interface. This * implementation communicates with the server through the XMLRPC @@ -103,25 +103,21 @@ public void close() throws XMLDBException { try { - rpcClient.execute("sync", new Vector()); + rpcClient.execute("sync", new ArrayList()); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "failed to close collection", e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "failed to close collection", e); } - } + } public String createId() throws XMLDBException { - Vector params = new Vector(1); - params.addElement(getPath()); + List params = new ArrayList(1); + params.add(getPath()); try { return (String)rpcClient.execute("createResourceId", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "failed to close collection", e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "failed to close collection", e); } - } + } public Resource createResource(String id, String type) throws XMLDBException { XmldbURI newId; @@ -227,16 +223,14 @@ } public int getResourceCount() throws XMLDBException { - Vector params = new Vector(1); - params.addElement(getPath()); + List params = new ArrayList(1); + params.add(getPath()); try { return ((Integer)rpcClient.execute("getResourceCount", params)).intValue(); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "failed to close collection", e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, "failed to close collection", e); } - } + } public Service getService(String name, String version) throws XMLDBException { if (name.equals("XPathQueryService")) @@ -310,18 +304,17 @@ } public String[] listResources() throws XMLDBException { - Vector params = new Vector(); - params.addElement(getPath()); + List params = new ArrayList(1); + params.add(getPath()); try { - Vector vec = (Vector)rpcClient.execute("getDocumentListing", params); - String[] resources = new String[vec.size()]; - return (String[])vec.toArray(resources); + Object[] r = (Object[]) rpcClient.execute("getDocumentListing", params); + String[] resources = new String[r.length]; + System.arraycopy(r, 0, resources, 0, r.length); + return resources; } catch (XmlRpcException xre) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "An IO error occurred: " + ioe.getMessage(), ioe); } - } + } /* (non-Javadoc) * @see org.exist.xmldb.CollectionImpl#getResources() @@ -331,23 +324,21 @@ } public Resource getResource(String name) throws XMLDBException { - Vector params = new Vector(); + List params = new ArrayList(1); XmldbURI docUri; try { docUri = XmldbURI.xmldbUriFor(name); } catch(URISyntaxException e) { throw new XMLDBException(ErrorCodes.INVALID_URI,e); } - params.addElement(getPathURI().append(docUri).toString()); - Hashtable hash; + params.add(getPathURI().append(docUri).toString()); + HashMap hash; try { - hash = (Hashtable) rpcClient.execute("describeResource", params); + hash = (HashMap) rpcClient.execute("describeResource", params); } catch (XmlRpcException xre) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "An IO error occurred: " + ioe.getMessage(), ioe); } - String docName = (String) hash.get("name"); + String docName = (String) hash.get("name"); if(docName == null) return null; // resource does not exist! @@ -387,25 +378,23 @@ private void readCollection() throws XMLDBException { childCollections = new HashMap(); - Vector params = new Vector(); - params.addElement(getPath()); + List params = new ArrayList(1); + params.add(getPath()); - Hashtable collection; + HashMap collection; try { - collection = (Hashtable) rpcClient.execute("describeCollection", params); + collection = (HashMap) rpcClient.execute("describeCollection", params); } catch (XmlRpcException xre) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.INVALID_COLLECTION, "An IO error occurred: " + ioe.getMessage(), ioe); } - Vector collections = (Vector) collection.get("collections"); + Object[] collections = (Object[]) collection.get("collections"); permissions = PermissionFactory.getPermission( (String) collection.get("owner"), (String) collection.get("group"), ((Integer) collection.get("permissions")).intValue()); String childName; - for (int i = 0; i < collections.size(); i++) { - childName = (String) collections.elementAt(i); + for (int i = 0; i < collections.length; i++) { + childName = (String) collections[i]; try { //TODO: Should this use the checked version instead? RemoteCollection child = @@ -435,9 +424,9 @@ } public void removeResource(Resource res) throws XMLDBException { - Vector params = new Vector(); + List params = new ArrayList(1); try { - params.addElement(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); + params.add(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); } catch(URISyntaxException e) { throw new XMLDBException(ErrorCodes.INVALID_URI,e); } @@ -446,22 +435,18 @@ rpcClient.execute("remove", params); } catch (XmlRpcException xre) { throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); } - } + } public Date getCreationTime() throws XMLDBException { - Vector params = new Vector(1); - params.addElement(getPath()); + List params = new ArrayList(1); + params.add(getPath()); try { return (Date) rpcClient.execute("getCreationDate", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(), e); } - } + } public void setProperty(String property, String value) throws XMLDBException { if(properties == null) @@ -517,18 +502,18 @@ private void store(RemoteXMLResource res) throws XMLDBException { byte[] data = res.getData(); - Vector params = new Vector(); - params.addElement(data); + List params = new ArrayList(1); + params.add(data); try { - params.addElement(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); + params.add(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); } catch(URISyntaxException e) { throw new XMLDBException(ErrorCodes.INVALID_URI,e); } - params.addElement(new Integer(1)); + params.add(new Integer(1)); if (res.dateCreated != null) { - params.addElement(res.dateCreated ); - params.addElement(res.dateModified ); + params.add(res.dateCreated ); + params.add(res.dateModified ); } try { @@ -538,27 +523,25 @@ ErrorCodes.INVALID_RESOURCE, xre == null ? "unknown error" : xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); } - } + } private void store(RemoteBinaryResource res) throws XMLDBException { byte[] data = (byte[])res.getContent(); - Vector params = new Vector(); - params.addElement(data); + List params = new ArrayList(1); + params.add(data); try { - params.addElement(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); + params.add(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); } catch(URISyntaxException e) { throw new XMLDBException(ErrorCodes.INVALID_URI,e); } - params.addElement(res.getMimeType()); - params.addElement(Boolean.TRUE); + params.add(res.getMimeType()); + params.add(Boolean.TRUE); - if ((Date)res.dateCreated != null) { - params.addElement((Date)res.dateCreated ); - params.addElement((Date)res.dateModified ); + if (res.dateCreated != null) { + params.add((Date)res.dateCreated ); + params.add((Date)res.dateModified ); } try { @@ -573,10 +556,8 @@ ErrorCodes.UNKNOWN_ERROR, xre == null ? "unknown error" : xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); } - } + } private void uploadAndStore(Resource res) throws XMLDBException { InputStream is=null; @@ -608,29 +589,29 @@ try { int len; String fileName = null; - Vector params; + List params; byte[] compressed; while ((len = is.read(chunk)) > -1) { compressed = Compressor.compress(chunk, len); - params = new Vector(); + params = new ArrayList(3); if (fileName != null) - params.addElement(fileName); - params.addElement(compressed); - params.addElement(new Integer(len)); + params.add(fileName); + params.add(compressed); + params.add(new Integer(len)); fileName = (String) rpcClient.execute("uploadCompressed", params); } - params = new Vector(); - params.addElement(fileName); + params = new ArrayList(6); + params.add(fileName); try { - params.addElement(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); + params.add(getPathURI().append(XmldbURI.xmldbUriFor(res.getId())).toString()); } catch(URISyntaxException e) { throw new XMLDBException(ErrorCodes.INVALID_URI,e); } - params.addElement(Boolean.TRUE); - params.addElement(((RemoteXMLResource)res).getMimeType()); + params.add(Boolean.TRUE); + params.add(((RemoteXMLResource)res).getMimeType()); if ( ((RemoteXMLResource)res).dateCreated != null ) { - params.addElement( ((RemoteXMLResource)res).dateCreated ); - params.addElement( ((RemoteXMLResource)res).dateModified ); + params.add( ((RemoteXMLResource)res).dateCreated ); + params.add( ((RemoteXMLResource)res).dateModified ); } rpcClient.execute("parseLocal", params); @@ -654,25 +635,5 @@ public boolean isRemoteCollection() throws XMLDBException { return true; } - - //You probably will have to call this method from this cast : - //((org.exist.xmldb.CollectionImpl)collection).getURI() - public XmldbURI getURI() { - StringBuffer accessor = new StringBuffer(XmldbURI.XMLDB_URI_PREFIX); - //TODO : get the name from client - accessor.append("exist"); - accessor.append("://"); - accessor.append(rpcClient.getURL().getHost()); - if (rpcClient.getURL().getPort() != -1) - accessor.append(":").append(rpcClient.getURL().getPort()); - accessor.append(rpcClient.getURL().getPath()); - try { - //TODO : cache it when constructed - return XmldbURI.create(accessor.toString(), getPath()); - } catch (XMLDBException e) { - //TODO : should never happen - return null; - } - } } Modified: trunk/eXist/src/org/exist/xmldb/RemoteCollectionManagementService.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteCollectionManagementService.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteCollectionManagementService.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -22,19 +22,19 @@ package org.exist.xmldb; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Date; -import java.util.Vector; - -import org.apache.xmlrpc.XmlRpcClient; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; import org.w3c.dom.Document; import org.xmldb.api.base.Collection; import org.xmldb.api.base.ErrorCodes; import org.xmldb.api.base.XMLDBException; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + public class RemoteCollectionManagementService implements CollectionManagementServiceImpl { protected XmlRpcClient client; @@ -63,13 +63,13 @@ public Collection createCollection( XmldbURI collName, Date created ) throws XMLDBException { if (parent != null) - collName = parent.getPathURI().resolveCollectionPath(collName); + collName = parent.getPathURI().resolveCollectionPath(collName); - Vector params = new Vector(); - params.addElement( collName.toString() ); + List params = new ArrayList(2); + params.add( collName.toString() ); if (created != null) { - params.addElement( created ); + params.add( created ); } try { @@ -78,10 +78,6 @@ throw new XMLDBException( ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre ); - } catch ( IOException ioe ) { - throw new XMLDBException( ErrorCodes.VENDOR_ERROR, - ioe.getMessage(), - ioe ); } RemoteCollection collection = new RemoteCollection( client, (RemoteCollection) parent, collName ); @@ -125,20 +121,16 @@ public void removeCollection( XmldbURI collName ) throws XMLDBException { if (parent != null) - collName = parent.getPathURI().resolveCollectionPath(collName); + collName = parent.getPathURI().resolveCollectionPath(collName); - Vector params = new Vector(); - params.addElement( collName.toString() ); + List params = new ArrayList(1); + params.add( collName.toString() ); try { client.execute( "removeCollection", params ); } catch ( XmlRpcException xre ) { throw new XMLDBException( ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre ); - } catch ( IOException ioe ) { - throw new XMLDBException( ErrorCodes.VENDOR_ERROR, - ioe.getMessage(), - ioe); } parent.removeChildCollection( collName ); } @@ -170,22 +162,18 @@ if(newName == null) { newName = collectionPath.lastSegment(); } - Vector params = new Vector(); - params.addElement( collectionPath.toString() ); - params.addElement( destinationPath.toString() ); - params.addElement( newName.toString() ); + List params = new ArrayList(1); + params.add( collectionPath.toString() ); + params.add( destinationPath.toString() ); + params.add( newName.toString() ); try { client.execute( "moveCollection", params ); } catch ( XmlRpcException xre ) { throw new XMLDBException( ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre ); - } catch ( IOException ioe ) { - throw new XMLDBException( ErrorCodes.VENDOR_ERROR, - ioe.getMessage(), - ioe); } - } + } public void moveResource(String resourcePath, String destinationPath, String newName) throws XMLDBException { @@ -206,20 +194,16 @@ newName = resourcePath.lastSegment(); } - Vector params = new Vector(); - params.addElement( resourcePath.toString() ); - params.addElement( destinationPath.toString() ); - params.addElement( newName.toString() ); + List params = new ArrayList(1); + params.add( resourcePath.toString() ); + params.add( destinationPath.toString() ); + params.add( newName.toString() ); try { client.execute( "moveResource", params ); } catch ( XmlRpcException xre ) { throw new XMLDBException( ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre ); - } catch ( IOException ioe ) { - throw new XMLDBException( ErrorCodes.VENDOR_ERROR, - ioe.getMessage(), - ioe); } } @@ -243,22 +227,18 @@ newName = collectionPath.lastSegment(); } - Vector params = new Vector(); - params.addElement( collectionPath.toString() ); - params.addElement( destinationPath.toString() ); - params.addElement( newName.toString() ); + List params = new ArrayList(1); + params.add( collectionPath.toString() ); + params.add( destinationPath.toString() ); + params.add( newName.toString() ); try { client.execute( "copyCollection", params ); } catch ( XmlRpcException xre ) { throw new XMLDBException( ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre ); - } catch ( IOException ioe ) { - throw new XMLDBException( ErrorCodes.VENDOR_ERROR, - ioe.getMessage(), - ioe); } - } + } public void copyResource(String resourcePath, String destinationPath, String newName) throws XMLDBException { @@ -279,20 +259,16 @@ if(newName == null) { newName = resourcePath.lastSegment(); } - Vector params = new Vector(); - params.addElement( resourcePath.toString() ); - params.addElement( destinationPath.toString() ); - params.addElement( newName.toString() ); + List params = new ArrayList(1); + params.add( resourcePath.toString() ); + params.add( destinationPath.toString() ); + params.add( newName.toString() ); try { client.execute( "copyResource", params ); } catch ( XmlRpcException xre ) { throw new XMLDBException( ErrorCodes.VENDOR_ERROR, xre.getMessage(), xre ); - } catch ( IOException ioe ) { - throw new XMLDBException( ErrorCodes.VENDOR_ERROR, - ioe.getMessage(), - ioe); } } } Modified: trunk/eXist/src/org/exist/xmldb/RemoteDatabaseInstanceManager.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteDatabaseInstanceManager.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteDatabaseInstanceManager.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -1,14 +1,14 @@ package org.exist.xmldb; -import java.io.IOException; -import java.util.Vector; - -import org.apache.xmlrpc.XmlRpcClient; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; import org.xmldb.api.base.Collection; import org.xmldb.api.base.ErrorCodes; import org.xmldb.api.base.XMLDBException; +import java.util.ArrayList; +import java.util.List; + public class RemoteDatabaseInstanceManager implements DatabaseInstanceManager { protected XmlRpcClient client; @@ -31,31 +31,24 @@ * @see org.exist.xmldb.DatabaseInstanceManager#shutdown() */ public void shutdown(long delay) throws XMLDBException { - Vector params = new Vector(); + List params = new ArrayList(1); if(delay > 0) - params.addElement(new Long(delay)); + params.add(new Long(delay)); try { client.execute("shutdown", params); } catch(XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "shutdown failed", e); - } catch(IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, - "shutdown failed", - e); - } - } + } + } public boolean enterServiceMode() throws XMLDBException { try { - client.execute("enterServiceMode", new Vector()); + client.execute("enterServiceMode", new ArrayList(1)); } catch(XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to switch db to service mode: " + e.getMessage(), e); - } catch(IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, - "Failed to switch db to service mode: " + e.getMessage(), e); } return true; } @@ -63,13 +56,10 @@ public void exitServiceMode() throws XMLDBException { try { - client.execute("exitServiceMode", new Vector()); + client.execute("exitServiceMode", new ArrayList(1)); } catch(XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Failed to switch db to service mode: " + e.getMessage(), e); - } catch(IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, - "Failed to switch db to service mode: " + e.getMessage(), e); } } @@ -120,7 +110,7 @@ public boolean isXACMLEnabled() throws XMLDBException { - Vector params = new Vector(); + List params = new ArrayList(1); try { Object result = client.execute("isXACMLEnabled", params); if(result instanceof Boolean) @@ -131,11 +121,7 @@ throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Error determining if XACML is enabled: " + e.getMessage(), e); - } catch(IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, - "Error determining if XACML is enabled: " + e.getMessage(), - e); } - } + } } Modified: trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -24,9 +24,11 @@ import java.io.IOException; import java.net.URISyntaxException; import java.util.Vector; +import java.util.ArrayList; +import java.util.List; -import org.apache.xmlrpc.XmlRpcClient; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; import org.exist.dom.QName; import org.exist.util.Occurrences; import org.xmldb.api.base.Collection; @@ -65,30 +67,26 @@ */ public void reindexCollection(XmldbURI collectionPath) throws XMLDBException { if (parent != null) - collectionPath = parent.getPathURI().resolveCollectionPath(collectionPath); - Vector params = new Vector(); - params.addElement(collectionPath.toString()); + collectionPath = parent.getPathURI().resolveCollectionPath(collectionPath); + List params = new ArrayList(1); + params.add(collectionPath.toString()); try { rpcClient.execute("reindexCollection", params); } catch (XmlRpcException e) { throw new XMLDBException( ErrorCodes.UNKNOWN_ERROR, "xmlrpc error while doing reindexCollection: ", e); - } catch (IOException e) { - throw new XMLDBException( - ErrorCodes.UNKNOWN_ERROR, - "xmlrpc error while doing reindexCollection: ", e); } - } + } /* (non-Javadoc) * @see org.exist.xmldb.IndexQueryService#getIndexedElements(boolean) */ public Occurrences[] getIndexedElements(boolean inclusive) throws XMLDBException { try { - Vector params = new Vector(); - params.addElement(parent.getPath()); - params.addElement(Boolean.valueOf(inclusive)); + List params = new ArrayList(1); + params.add(parent.getPath()); + params.add(Boolean.valueOf(inclusive)); Vector result = (Vector) rpcClient.execute("getIndexedElements", params); Occurrences occurrences[] = new Occurrences[result.size()]; Vector row; @@ -105,13 +103,8 @@ ErrorCodes.UNKNOWN_ERROR, "xmlrpc error while retrieving indexed elements", e); - } catch (IOException e) { - throw new XMLDBException( - ErrorCodes.UNKNOWN_ERROR, - "io error while retrieving indexed elements", - e); } - } + } /* (non-Javadoc) * @see org.exist.xmldb.IndexQueryService#scanIndexTerms(java.lang.String, java.lang.String, boolean) @@ -119,11 +112,11 @@ public Occurrences[] scanIndexTerms(String start, String end, boolean inclusive) throws XMLDBException { try { - Vector params = new Vector(); - params.addElement(parent.getPath()); - params.addElement(start); - params.addElement(end); - params.addElement(Boolean.valueOf(inclusive)); + List params = new ArrayList(1); + params.add(parent.getPath()); + params.add(start); + params.add(end); + params.add(Boolean.valueOf(inclusive)); Vector result = (Vector) rpcClient.execute("scanIndexTerms", params); Occurrences occurrences[] = new Occurrences[result.size()]; Vector row; @@ -138,23 +131,18 @@ ErrorCodes.UNKNOWN_ERROR, "xmlrpc error while retrieving indexed elements", e); - } catch (IOException e) { - throw new XMLDBException( - ErrorCodes.UNKNOWN_ERROR, - "io error while retrieving indexed elements", - e); } - } + } /* (non-Javadoc) * @see org.exist.xmldb.IndexQueryService#scanIndexTerms(java.lang.String, java.lang.String, java.lang.String) */ public Occurrences[] scanIndexTerms(String xpath, String start, String end) throws XMLDBException { try { - Vector params = new Vector(); - params.addElement(xpath); - params.addElement(start); - params.addElement(end); + List params = new ArrayList(1); + params.add(xpath); + params.add(start); + params.add(end); Vector result = (Vector) rpcClient.execute("scanIndexTerms", params); Occurrences occurrences[] = new Occurrences[result.size()]; Vector row; @@ -169,13 +157,8 @@ ErrorCodes.UNKNOWN_ERROR, "xmlrpc error while retrieving indexed elements", e); - } catch (IOException e) { - throw new XMLDBException( - ErrorCodes.UNKNOWN_ERROR, - "io error while retrieving indexed elements", - e); } - } + } /* (non-Javadoc) * @see org.xmldb.api.base.Service#getName() @@ -217,20 +200,16 @@ */ public void configureCollection(String configData) throws XMLDBException { String path = parent.getPath(); - Vector params = new Vector(); - params.addElement(path); - params.addElement(configData); + List params = new ArrayList(1); + params.add(path); + params.add(configData); try { rpcClient.execute("configureCollection", params); } catch (XmlRpcException e) { throw new XMLDBException( ErrorCodes.UNKNOWN_ERROR, "xmlrpc error while doing reindexCollection: ", e); - } catch (IOException e) { - throw new XMLDBException( - ErrorCodes.UNKNOWN_ERROR, - "xmlrpc error while doing reindexCollection: ", e); - } - } + } + } } Modified: trunk/eXist/src/org/exist/xmldb/RemoteResourceIterator.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteResourceIterator.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteResourceIterator.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -24,8 +24,8 @@ import java.net.URISyntaxException; import java.util.Vector; -import org.apache.xmlrpc.XmlRpcClient; import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.client.XmlRpcClient; import org.xmldb.api.base.ErrorCodes; import org.xmldb.api.base.Resource; import org.xmldb.api.base.ResourceIterator; @@ -79,7 +79,7 @@ try { byte[] data = (byte[])collection.getClient().execute("retrieve", params); XMLResource res = new RemoteXMLResource(collection, XmldbURI.xmldbUriFor(doc), doc + "_" + s_id); - res.setContent((Object)new String(data, encoding)); + res.setContent(new String(data, encoding)); return res; } catch(XmlRpcException xre) { throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre); Modified: trunk/eXist/src/org/exist/xmldb/RemoteResourceSet.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteResourceSet.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteResourceSet.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -1,11 +1,11 @@ package org.exist.xmldb; -import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.util.Properties; -import java.util.Vector; +import java.util.List; +import java.util.ArrayList; import javax.xml.transform.OutputKeys; @@ -21,31 +21,32 @@ protected RemoteCollection collection; protected int handle = -1; - protected Vector resources; + protected List resources; protected Properties outputProperties; private static Logger LOG = Logger.getLogger(RemoteResourceSet.class.getName()); - public RemoteResourceSet( RemoteCollection col, Properties properties, Vector resources, int handle ) { + public RemoteResourceSet( RemoteCollection col, Properties properties, Object[] resources, int handle ) { this.handle = handle; - this.resources = resources; + this.resources = new ArrayList(resources.length); + for (int i = 0; i < resources.length; i++) { + this.resources.add(resources[i]); + } this.collection = col; this.outputProperties = properties; } public void addResource( Resource resource ) { - resources.addElement( resource ); + resources.add( resource ); } public void clear() throws XMLDBException { - Vector params = new Vector(); - params.addElement(new Integer(handle)); + List params = new ArrayList(1); + params.add(new Integer(handle)); try { collection.getClient().execute("releaseQueryResult", params); } catch (XmlRpcException e) { System.err.println("Failed to release query result on server: " + e.getMessage()); - } catch (IOException e) { - System.err.println("Failed to release query result on server: " + e.getMessage()); } resources.clear(); } @@ -60,9 +61,9 @@ public Resource getMembersAsResource() throws XMLDBException { - Vector params = new Vector(); - params.addElement(new Integer(handle)); - params.addElement(outputProperties); + List params = new ArrayList(2); + params.add(new Integer(handle)); + params.add(outputProperties); try { byte[] data = (byte[]) collection.getClient().execute("retrieveAll", params); String content; @@ -79,8 +80,6 @@ return res; } catch (XmlRpcException xre) { throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre); - } catch (IOException ioe) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); } } @@ -88,11 +87,11 @@ if ( pos >= resources.size() ) return null; // node or value? - if ( resources.elementAt( (int) pos ) instanceof Vector ) { + if ( resources.get( (int) pos ) instanceof Object[] ) { // node - Vector v = (Vector) resources.elementAt( (int) pos ); - String doc = (String) v.elementAt( 0 ); - String s_id = (String) v.elementAt( 1 ); + Object[] v = (Object[]) resources.get( (int) pos ); + String doc = (String) v[0]; + String s_id = (String) v[1]; XmldbURI docUri; try { docUri = XmldbURI.xmldbUriFor(doc); @@ -107,13 +106,13 @@ (int)pos, docUri, s_id ); res.setProperties(outputProperties); return res; - } else if ( resources.elementAt( (int) pos ) instanceof Resource ) - return (Resource) resources.elementAt( (int) pos ); + } else if ( resources.get( (int) pos ) instanceof Resource ) + return (Resource) resources.get( (int) pos ); else { // value RemoteXMLResource res = new RemoteXMLResource( collection, handle, (int)pos, XmldbURI.create(Long.toString( pos )), null ); - res.setContent( resources.elementAt( (int) pos ) ); + res.setContent( resources.get( (int) pos ) ); res.setProperties(outputProperties); return res; } @@ -124,7 +123,7 @@ } public void removeResource( long pos ) throws XMLDBException { - resources.removeElementAt( (int) pos ); + resources.get( (int) pos ); } class NewResourceIterator implements ResourceIterator { Modified: trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java 2008-11-30 17:32:10 UTC (rev 8338) +++ trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java 2008-11-30 17:36:23 UTC (rev 8339) @@ -1,10 +1,5 @@ package org.exist.xmldb; -import java.io.IOException; -import java.util.Hashtable; -import java.util.Iterator; -import java.util.Vector; - import org.apache.xmlrpc.XmlRpcException; import org.exist.security.Permission; import org.exist.security.UnixStylePermission; @@ -14,7 +9,12 @@ import org.xmldb.api.base.Resource; import org.xmldb.api.base.XMLDBException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Vector; + /************************************************* * Modified by {Marco.Tampucci, Massimo.Martinelli} @isti.cnr.it **************************************/ @@ -35,24 +35,19 @@ */ public void addUser(User user) throws XMLDBException { try { - Vector params = new Vector(); - params.addElement(user.getName()); - params.addElement(user.getPassword() == null ? "" : user.getPassword()); - params.addElement(user.getDigestPassword() == null ? "" : user.getDigestPassword()); - Vector groups = new Vector(); + List params = new ArrayList(12); + params.add(user.getName()); + params.add(user.getPassword() == null ? "" : user.getPassword()); + params.add(user.getDigestPassword() == null ? "" : user.getDigestPassword()); String[] gl = user.getGroups(); - for (int i = 0; i < gl.length; i++) - groups.addElement(gl[i]); - params.addElement(groups); + params.add(gl); if (user.getHome() != null) - params.addElement(user.getHome().toString()); + params.add(user.getHome().toString()); parent.getClient().execute("setUser", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * Change permissions for a resource. @@ -61,18 +56,16 @@ //TODO : use dedicated function in XmldbURI String path = ((RemoteCollection) res.getParentCollection()).getPath() + "/" + res.getId(); try { - Vector params = new Vector(); - params.addElement(path); - params.addElement(perms.getOwner()); - params.addElement(perms.getOwnerGroup()); - params.addElement(new Integer(perms.getPermissions())); + List params = new ArrayList(1); + params.add(path); + params.add(perms.getOwner()); + params.add(perms.getOwnerGroup()); + params.add(new Integer(perms.getPermissions())); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * Change permissions for a resource. @@ -80,18 +73,16 @@ public void setPermissions(Collection child, Permission perms) throws XMLDBException { String path = ((RemoteCollection) child).getPath(); try { - Vector params = new Vector(); - params.addElement(path); - params.addElement(perms.getOwner()); - params.addElement(perms.getOwnerGroup()); - params.addElement(new Integer(perms.getPermissions())); + List params = new ArrayList(4); + params.add(path); + params.add(perms.getOwner()); + params.add(perms.getOwnerGroup()); + params.add(new Integer(perms.getPermissions())); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * Change access mode of a resource @@ -104,16 +95,14 @@ //TODO : use dedicated function in XmldbURI String path = ((RemoteCollection) res.getParentCollection()).getPath() + "/" + res.getId(); try { - Vector params = new Vector(); - params.addElement(path); - params.addElement(mode); + List params = new ArrayList(2); + params.add(path); + params.add(mode); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * @see org.exist.xmldb.UserManagementService#chmod(org.xmldb.api.base.Resource, int) @@ -122,16 +111,14 @@ //TODO : use dedicated function in XmldbURI String path = ((RemoteCollection) res.getParentCollection()).getPath() + "/" + res.getId(); try { - Vector params = new Vector(); - params.addElement(path); - params.addElement(new Integer(mode)); + List params = new ArrayList(2); + params.add(path); + params.add(new Integer(mode)); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * Change access mode of the current collection @@ -141,32 +128,28 @@ */ public void chmod(String mode) throws XMLDBException { try { - Vector params = new Vector(); - params.addElement(parent.getPath()); - params.addElement(mode); + List params = new ArrayList(2); + params.add(parent.getPath()); + params.add(mode); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * @see org.exist.xmldb.UserManagementService#chmod(int) */ public void chmod(int mode) throws XMLDBException { try { - Vector params = new Vector(); - params.addElement(parent.getPath()); - params.addElement(new Integer(mode)); + List params = new ArrayList(2); + params.add(parent.getPath()); + params.add(new Integer(mode)); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /* (non-Javadoc) * @see org.exist.xmldb.UserManagementService#lockResource(org.xmldb.api.base.Resource, org.exist.security.User) @@ -175,16 +158,14 @@ //TODO : use dedicated function in XmldbURI String path = ((RemoteCollection) res.getParentCollection()).getPath() + "/" + res.getId(); try { - Vector params = new Vector(); - params.addElement(path); - params.addElement(u.getName()); + List params = new ArrayList(2); + params.add(path); + params.add(u.getName()); parent.getClient().execute("lockResource", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /* (non-Javadoc) * @see org.exist.xmldb.UserManagementService#hasUserLock(org.xmldb.api.base.Resource) @@ -193,16 +174,14 @@ //TODO : use dedicated function in XmldbURI String path = ((RemoteCollection) res.getParentCollection()).getPath() + "/" + res.getId(); try { - Vector params = new Vector(); - params.addElement(path); + List params = new ArrayList(1); + params.add(path); String userName = (String)parent.getClient().execute("hasUserLock", params); return userName != null && userName.length() > 0 ? userName : null; } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /* (non-Javadoc) * @see org.exist.xmldb.UserManagementService#unlockResource(org.xmldb.api.base.Resource) @@ -211,15 +190,13 @@ //TODO : use dedicated function in XmldbURI String path = ((RemoteCollection) res.getParentCollection()).getPath() + "/" + res.getId(); try { - Vector params = new Vector(); - params.addElement(path); + List params = new ArrayList(1); + params.add(path); parent.getClient().execute("unlockResource", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * Change the owner of the current collection @@ -230,18 +207,16 @@ */ public void chown(User u, String group) throws XMLDBException { try { - Vector params = new Vector(); - params.addElement(parent.getPath()); - params.addElement(u.getName()); - params.addElement(group); - params.addElement(""); + List params = new ArrayList(4); + params.add(parent.getPath()); + params.add(u.getName()); + params.add(group); + params.add(""); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * Change the owner of a resource @@ -255,18 +230,16 @@ //TODO : use dedicated function in XmldbURI String path = ((RemoteCollection) res.getParentCollection()).getPath() + "/" + res.getId(); try { - Vector params = new Vector(); - params.addElement(path); - params.addElement(u.getName()); - params.addElement(group); - params.addElement(""); + List params = new ArrayList(4); + params.add(path); + params.add(u.getName()); + params.add(group); + params.add(""); parent.getClient().execute("setPermissions", params); } catch (XmlRpcException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); - } catch (IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e); } - } + } /** * Gets the ... [truncated message content] |
From: <wol...@us...> - 2008-11-30 20:51:05
|
Revision: 8343 http://exist.svn.sourceforge.net/exist/?rev=8343&view=rev Author: wolfgang_m Date: 2008-11-30 20:50:59 +0000 (Sun, 30 Nov 2008) Log Message: ----------- [general] updated Apache XMLRPC libraries from version 1.2 to 3.1.1; redesigned eXist's XMLRPC services to work with the new xmlrpc libs. For backwards compatibility, only small changes have been made to the XMLRPC API exposed by eXist. Most clients should work as before. Modified Paths: -------------- trunk/eXist/src/org/exist/http/servlets/HttpServletRequestWrapper.java trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java trunk/eXist/src/org/exist/xmlrpc/XmldbRequestProcessorFactory.java Modified: trunk/eXist/src/org/exist/http/servlets/HttpServletRequestWrapper.java =================================================================== --- trunk/eXist/src/org/exist/http/servlets/HttpServletRequestWrapper.java 2008-11-30 18:00:06 UTC (rev 8342) +++ trunk/eXist/src/org/exist/http/servlets/HttpServletRequestWrapper.java 2008-11-30 20:50:59 UTC (rev 8343) @@ -33,6 +33,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; +import java.io.InputStreamReader; import java.net.URLDecoder; import java.security.Principal; import java.util.Enumeration; @@ -603,7 +604,10 @@ */ public ServletInputStream getInputStream() throws IOException { - return request.getInputStream(); + if (contentBodyRecorded()) + return new CachingServletInputStream(); + else + return request.getInputStream(); } // public InputStream getStringBufferInputStream() throws IOException { @@ -755,7 +759,11 @@ public BufferedReader getReader() throws IOException { - return request.getReader(); + if (contentBodyRecorded()) + return new BufferedReader(new InputStreamReader(getContentBodyInputStream(), + request.getCharacterEncoding())); + else + return request.getReader(); } /** @@ -927,4 +935,31 @@ && contentBody.length > 0; } + private class CachingServletInputStream extends ServletInputStream { + + private ByteArrayInputStream istream; + + public CachingServletInputStream() { + if (contentBody == null) + istream = new ByteArrayInputStream(new byte[0]); + else + istream = new ByteArrayInputStream(contentBody); + } + + public int read() throws IOException { + return istream.read(); + } + + public int read(byte b[]) throws IOException { + return istream.read(b); + } + + public int read(byte b[], int off, int len) throws IOException { + return istream.read(b, off, len); + } + + public int available() throws IOException { + return istream.available(); + } + } } Modified: trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java 2008-11-30 18:00:06 UTC (rev 8342) +++ trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java 2008-11-30 20:50:59 UTC (rev 8343) @@ -2345,7 +2345,6 @@ queryResult.result = resultSeq; queryResult.queryTime = (System.currentTimeMillis() - startTime); int id = factory.resultSets.add(queryResult); - System.out.println("Factory: " + factory.hashCode()); ret.put("id", new Integer(id)); ret.put("results", result); return ret; @@ -2683,7 +2682,6 @@ DBBroker broker = null; try { broker = factory.getBrokerPool().get(user); - System.out.println("Factory: " + factory.hashCode()); QueryResult qr = factory.resultSets.get(resultId); if (qr == null) throw new EXistException("result set unknown or timed out"); Modified: trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java 2008-11-30 18:00:06 UTC (rev 8342) +++ trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java 2008-11-30 20:50:59 UTC (rev 8343) @@ -29,9 +29,33 @@ import org.apache.xmlrpc.XmlRpcException; import org.apache.xmlrpc.XmlRpcHandler; import org.exist.EXistException; +import org.exist.http.Descriptor; +import org.exist.http.servlets.HttpServletRequestWrapper; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import java.io.IOException; +import java.io.InputStream; + public class RpcServlet extends XmlRpcServlet { + @Override + public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + // Request logger + + Descriptor descriptor = Descriptor.getDescriptorSingleton(); + if( descriptor.allowRequestLogging() ) { + // Wrap HttpServletRequest, because both request Logger and xmlrpc + // need the request InputStream, which is consumed when read. + request = + new HttpServletRequestWrapper(request, /*formEncoding*/ "utf-8" ); + descriptor.doLogRequestInReplayLog(request); + } + + super.doPost(request, response); + } + protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() throws XmlRpcException { DefaultHandlerMapping mapping = new DefaultHandlerMapping(); mapping.setVoidMethodEnabled(true); Modified: trunk/eXist/src/org/exist/xmlrpc/XmldbRequestProcessorFactory.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/XmldbRequestProcessorFactory.java 2008-11-30 18:00:06 UTC (rev 8342) +++ trunk/eXist/src/org/exist/xmlrpc/XmldbRequestProcessorFactory.java 2008-11-30 20:50:59 UTC (rev 8343) @@ -30,6 +30,11 @@ import org.exist.security.User; import org.exist.storage.BrokerPool; +/** + * Factory creates a new handler for each XMLRPC request. For eXist, the handler is implemented + * by class {@link org.exist.xmlrpc.RpcConnection}. The factory is needed to make sure that each + * RpcConnection is properly initialized. + */ public class XmldbRequestProcessorFactory implements RequestProcessorFactoryFactory.RequestProcessorFactory { private final static Logger LOG = Logger.getLogger(XmldbRequestProcessorFactory.class); @@ -54,6 +59,7 @@ } public Object getRequestProcessor(XmlRpcRequest pRequest) throws XmlRpcException { + checkResultSets(); XmlRpcHttpRequestConfig config = (XmlRpcHttpRequestConfig) pRequest.getConfig(); User user = authenticate(config.getBasicUserName(), config.getBasicPassword()); return new RpcConnection(this, user); @@ -81,8 +87,11 @@ return brokerPool; } - private void checkResultSets() { - resultSets.checkTimestamps(); + protected void checkResultSets() { + if (System.currentTimeMillis() - lastCheck > CHECK_INTERVAL) { + resultSets.checkTimestamps(); + lastCheck = System.currentTimeMillis(); + } } public synchronized void shutdown() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2008-12-01 22:05:56
|
Revision: 8346 http://exist.svn.sourceforge.net/exist/?rev=8346&view=rev Author: wolfgang_m Date: 2008-12-01 22:05:51 +0000 (Mon, 01 Dec 2008) Log Message: ----------- [ignore] fixed a few more xmlrpc problems. Modified Paths: -------------- trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java Modified: trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java 2008-12-01 11:57:54 UTC (rev 8345) +++ trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java 2008-12-01 22:05:51 UTC (rev 8346) @@ -30,7 +30,8 @@ import java.io.IOException; import java.io.InputStream; import java.util.Date; -import java.util.Vector; +import java.util.ArrayList; +import java.util.List; import org.apache.xmlrpc.XmlRpcException; import org.exist.security.Permission; @@ -110,8 +111,8 @@ return data; } - Vector params = new Vector(); - params.addElement(path.toString()); + List params = new ArrayList(); + params.add(path.toString()); try { data = (byte[])parent.getClient().execute("getBinaryResource", params); } catch (XmlRpcException e) { Modified: trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java 2008-12-01 11:57:54 UTC (rev 8345) +++ trunk/eXist/src/org/exist/xmldb/RemoteIndexQueryService.java 2008-12-01 22:05:51 UTC (rev 8346) @@ -23,7 +23,6 @@ import java.io.IOException; import java.net.URISyntaxException; -import java.util.Vector; import java.util.ArrayList; import java.util.List; @@ -87,15 +86,15 @@ List params = new ArrayList(1); params.add(parent.getPath()); params.add(Boolean.valueOf(inclusive)); - Vector result = (Vector) rpcClient.execute("getIndexedElements", params); - Occurrences occurrences[] = new Occurrences[result.size()]; - Vector row; + Object[] result = (Object[]) rpcClient.execute("getIndexedElements", params); + Occurrences occurrences[] = new Occurrences[result.length]; + Object[] row; for (int i = 0; i < occurrences.length; i++) { - row = (Vector) result.elementAt(i); - QName qname = new QName((String)row.elementAt(0), (String)row.elementAt(1), - (String)row.elementAt(2)); + row = (Object[]) result[i]; + QName qname = new QName((String)row[0], (String)row[1], + (String)row[2]); occurrences[i] = new Occurrences(qname); - occurrences[i].addOccurrences(((Integer) row.elementAt(3)).intValue()); + occurrences[i].addOccurrences(((Integer) row[3]).intValue()); } return occurrences; } catch (XmlRpcException e) { @@ -117,13 +116,13 @@ params.add(start); params.add(end); params.add(Boolean.valueOf(inclusive)); - Vector result = (Vector) rpcClient.execute("scanIndexTerms", params); - Occurrences occurrences[] = new Occurrences[result.size()]; - Vector row; + Object[] result = (Object[]) rpcClient.execute("scanIndexTerms", params); + Occurrences occurrences[] = new Occurrences[result.length]; + Object[] row; for (int i = 0; i < occurrences.length; i++) { - row = (Vector) result.elementAt(i); - occurrences[i] = new Occurrences((String) row.elementAt(0)); - occurrences[i].addOccurrences(((Integer) row.elementAt(1)).intValue()); + row = (Object[]) result[i]; + occurrences[i] = new Occurrences((String) row[0]); + occurrences[i].addOccurrences(((Integer) row[1]).intValue()); } return occurrences; } catch (XmlRpcException e) { @@ -143,13 +142,13 @@ params.add(xpath); params.add(start); params.add(end); - Vector result = (Vector) rpcClient.execute("scanIndexTerms", params); - Occurrences occurrences[] = new Occurrences[result.size()]; - Vector row; + Object[] result = (Object[]) rpcClient.execute("scanIndexTerms", params); + Occurrences occurrences[] = new Occurrences[result.length]; + Object[] row; for (int i = 0; i < occurrences.length; i++) { - row = (Vector) result.elementAt(i); - occurrences[i] = new Occurrences((String) row.elementAt(0)); - occurrences[i].addOccurrences(((Integer) row.elementAt(1)).intValue()); + row = (Object[]) result[i]; + occurrences[i] = new Occurrences((String) row[0]); + occurrences[i].addOccurrences(((Integer) row[1]).intValue()); } return occurrences; } catch (XmlRpcException e) { Modified: trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java 2008-12-01 11:57:54 UTC (rev 8345) +++ trunk/eXist/src/org/exist/xmldb/RemoteUserManagementService.java 2008-12-01 22:05:51 UTC (rev 8346) @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; -import java.util.Vector; /************************************************* @@ -312,13 +311,13 @@ (HashMap) parent.getClient().execute("listDocumentPermissions", params); Permission perm[] = new Permission[result.size()]; String[] resources = parent.listResources(); - Vector t; + Object[] t; for (int i = 0; i < resources.length; i++) { - t = (Vector) result.get(resources[i]); + t = (Object[]) result.get(resources[i]); perm[i] = new UnixStylePermission(); - perm[i].setOwner((String) t.elementAt(0)); - perm[i].setGroup((String) t.elementAt(1)); - perm[i].setPermissions(((Integer) t.elementAt(2)).intValue()); + perm[i].setOwner((String) t[0]); + perm[i].setGroup((String) t[1]); + perm[i].setPermissions(((Integer) t[2]).intValue()); } return perm; } catch (XmlRpcException e) { @@ -334,13 +333,13 @@ (HashMap) parent.getClient().execute("listCollectionPermissions", params); Permission perm[] = new Permission[result.size()]; String collections[] = parent.listChildCollections(); - Vector t; + Object[] t; for (int i = 0; i < collections.length; i++) { - t = (Vector) result.get(collections[i]); + t = (Object[]) result.get(collections[i]); perm[i] = new UnixStylePermission(); - perm[i].setOwner((String) t.elementAt(0)); - perm[i].setGroup((String) t.elementAt(1)); - perm[i].setPermissions(((Integer) t.elementAt(2)).intValue()); + perm[i].setOwner((String) t[0]); + perm[i].setGroup((String) t[1]); + perm[i].setPermissions(((Integer) t[2]).intValue()); } return perm; } catch (XmlRpcException e) { Modified: trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java 2008-12-01 11:57:54 UTC (rev 8345) +++ trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java 2008-12-01 22:05:51 UTC (rev 8346) @@ -4127,23 +4127,22 @@ parametri.put(OutputKeys.ENCODING, "UTF-8"); HashMap lista = getCollectionDesc(name); - Vector collezioni = (Vector) lista.get("collections"); - Vector documents = (Vector) lista.get("documents"); + Object[] collezioni = (Object[]) lista.get("collections"); + Object[] documents = (Object[]) lista.get("documents"); //ricrea le directory - Iterator collezioniItr = collezioni.iterator(); String nome; - while (collezioniItr.hasNext()) { - nome = collezioniItr.next().toString(); + for (int i = 0; i < collezioni.length; i++) { + nome = collezioni[i].toString(); createCollection(namedest + "/" + nome); copyCollection(name + "/" + nome, namedest + "/" + nome); } //Copy i file HashMap hash; - int p, dsize = documents.size(); + int p, dsize = documents.length; for (int i = 0; i < dsize; i++) { - hash = (HashMap) documents.elementAt(i); + hash = (HashMap) documents[i]; nome = (String) hash.get("name"); //TODO : use dedicated function in XmldbURI if ((p = nome.lastIndexOf("/")) != Constants.STRING_NOT_FOUND) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <di...@us...> - 2008-12-02 22:17:12
|
Revision: 8354 http://exist.svn.sourceforge.net/exist/?rev=8354&view=rev Author: dizzzz Date: 2008-12-02 22:17:10 +0000 (Tue, 02 Dec 2008) Log Message: ----------- [patch] Integrated patch 1988515 "XMLDB: Allow huge binary resource uploads/downloads" https://sourceforge.net/support/tracker.php?aid=1988515 ; patch by Jos?\195?\169 Mar?\195?\173a Fern?\195?\161ndez ( jmfg ) Modified Paths: -------------- trunk/eXist/src/org/exist/backup/Backup.java trunk/eXist/src/org/exist/client/ClientFrame.java trunk/eXist/src/org/exist/client/InteractiveClient.java trunk/eXist/src/org/exist/client/messages.properties trunk/eXist/src/org/exist/client/messages_es_ES.properties trunk/eXist/src/org/exist/cocoon/XMLDBSource.java trunk/eXist/src/org/exist/storage/NativeBroker.java trunk/eXist/src/org/exist/xmldb/LocalBinaryResource.java trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java trunk/eXist/src/org/exist/xmldb/RemoteCollection.java trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java Added Paths: ----------- trunk/eXist/src/org/exist/xmldb/ExtendedBinaryResource.java trunk/eXist/src/org/exist/xmldb/ExtendedResource.java Modified: trunk/eXist/src/org/exist/backup/Backup.java =================================================================== --- trunk/eXist/src/org/exist/backup/Backup.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/backup/Backup.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -30,6 +30,7 @@ import org.exist.util.serializer.SerializerPool; import org.exist.xmldb.CollectionImpl; import org.exist.xmldb.EXistResource; +import org.exist.xmldb.ExtendedResource; import org.exist.xmldb.UserManagementService; import org.exist.xmldb.XmldbURI; import org.exist.xquery.util.URIUtils; @@ -272,8 +273,7 @@ os = output.newEntry(encode(URIUtils.urlDecodeUtf8(resources[i]))); if(resource.getResourceType().equals("BinaryResource")) { - byte[] bdata = (byte[])resource.getContent(); - os.write(bdata); + ((ExtendedResource)resource).getContentIntoAStream(os); } else { try { writer = Modified: trunk/eXist/src/org/exist/client/ClientFrame.java =================================================================== --- trunk/eXist/src/org/exist/client/ClientFrame.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/client/ClientFrame.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -43,6 +43,7 @@ import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; +import java.io.InputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.io.PrintWriter; @@ -105,6 +106,7 @@ import org.exist.xmldb.CollectionImpl; import org.exist.xmldb.CollectionManagementServiceImpl; import org.exist.xmldb.DatabaseInstanceManager; +import org.exist.xmldb.ExtendedResource; import org.exist.xmldb.EXistResource; import org.exist.xmldb.IndexQueryService; import org.exist.xmldb.UserManagementService; @@ -420,7 +422,7 @@ }); fileMenu.add(item); - item = new JMenuItem("Export a resource to file ...", KeyEvent.VK_E); + item = new JMenuItem(Messages.getString("ClientFrame.47"), KeyEvent.VK_E); item.setAccelerator(KeyStroke.getKeyStroke("control E")); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { @@ -1250,9 +1252,7 @@ .getResource(desc.getName().toString()); os = new FileOutputStream(file); if (resource.getResourceType().equals("BinaryResource")) { - byte[] bdata = (byte[]) resource.getContent(); - os.write(bdata); - os.close(); + ((ExtendedResource)resource).getContentIntoAStream(os); } else { writer = new BufferedWriter(new OutputStreamWriter(os, Modified: trunk/eXist/src/org/exist/client/InteractiveClient.java =================================================================== --- trunk/eXist/src/org/exist/client/InteractiveClient.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/client/InteractiveClient.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -22,6 +22,7 @@ package org.exist.client; import java.awt.Dimension; +import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.EOFException; @@ -36,6 +37,7 @@ import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.OutputStreamWriter; +import java.io.PrintStream; import java.io.PushbackInputStream; import java.io.StreamTokenizer; import java.io.StringReader; @@ -100,6 +102,7 @@ import org.exist.xmldb.CollectionManagementServiceImpl; import org.exist.xmldb.DatabaseInstanceManager; import org.exist.xmldb.EXistResource; +import org.exist.xmldb.ExtendedResource; import org.exist.xmldb.IndexQueryService; import org.exist.xmldb.UserManagementService; import org.exist.xmldb.XPathQueryServiceImpl; @@ -1325,21 +1328,21 @@ } else { long start1 = System.currentTimeMillis(); mimeType = MimeTable.getInstance().getContentTypeFor(files[i].getName()); - if(mimeType == null) + if(mimeType == null) { messageln("File " + files[i].getName() + " has an unknown " + "suffix. Cannot determine file type."); - else { - message("storing document " + files[i].getName() + " (" + i - + " of " + files.length + ") " + "..."); - document = collection.createResource(URIUtils.urlEncodeUtf8(files[i] - .getName()), mimeType.getXMLDBType()); - document.setContent(files[i]); - ((EXistResource)document).setMimeType(mimeType.getName()); - collection.storeResource(document); - ++filesCount; - messageln(" " + files[i].length() + " bytes in " - + (System.currentTimeMillis() - start1) + "ms."); + mimeType = MimeType.BINARY_TYPE; } + message("storing document " + files[i].getName() + " (" + i + + " of " + files.length + ") " + "..."); + document = collection.createResource(URIUtils.urlEncodeUtf8(files[i] + .getName()), mimeType.getXMLDBType()); + document.setContent(files[i]); + ((EXistResource)document).setMimeType(mimeType.getName()); + collection.storeResource(document); + ++filesCount; + messageln(" " + files[i].length() + " bytes in " + + (System.currentTimeMillis() - start1) + "ms."); } } catch (URISyntaxException e) { messageln("uri syntax exception parsing " + files[i].getAbsolutePath() + ": " + e.getMessage()); @@ -1458,20 +1461,20 @@ } } mimeType = MimeTable.getInstance().getContentTypeFor(localName); - if(mimeType == null) + if(mimeType == null) { messageln("File " + compressedName + " has an unknown " + "suffix. Cannot determine file type."); - else { - message("storing document " + compressedName + " (" + i - + " of " + files.length + ") " + "..."); - document = collection.createResource(URIUtils.urlEncodeUtf8(compressedName), mimeType.getXMLDBType()); - document.setContent(isCompressed?new GZIPInputSource(files[i]):files[i]); - ((EXistResource)document).setMimeType(mimeType.getName()); - collection.storeResource(document); - ++filesCount; - messageln(" " + files[i].length() + (isCompressed?" compressed":"") + " bytes in " - + (System.currentTimeMillis() - start1) + "ms."); - } + mimeType = MimeType.BINARY_TYPE; + } + message("storing document " + compressedName + " (" + i + + " of " + files.length + ") " + "..."); + document = collection.createResource(URIUtils.urlEncodeUtf8(compressedName), mimeType.getXMLDBType()); + document.setContent(isCompressed?new GZIPInputSource(files[i]):files[i]); + ((EXistResource)document).setMimeType(mimeType.getName()); + collection.storeResource(document); + ++filesCount; + messageln(" " + files[i].length() + (isCompressed?" compressed":"") + " bytes in " + + (System.currentTimeMillis() - start1) + "ms."); } } catch (URISyntaxException e) { messageln("uri syntax exception parsing " + files[i].getAbsolutePath() + ": " + e.getMessage()); @@ -1765,9 +1768,9 @@ upload.showMessage(file.getAbsolutePath() + " - unknown suffix. No matching mime-type found in : " + MimeTable.getInstance().getSrc()); - return; + // if some one prefers to store it as binary by default, but dangerous - // if (mimeType == null) mimeType = MimeType.BINARY_TYPE; + mimeType = MimeType.BINARY_TYPE; } try { Resource res = collection.createResource( @@ -2142,11 +2145,13 @@ else System.out.println(res.getContent().toString()); } else { - if (cOpt.optionOutputFile != null) - writeOutputFile(cOpt.optionOutputFile, res.getContent()); - else - System.out.println(new String((byte[]) res - .getContent())); + if (cOpt.optionOutputFile != null) { + ((ExtendedResource)res).getContentIntoAFile(new File(cOpt.optionOutputFile)); + ((ExtendedResource)res).freeLocalResources(); + } else { + ((ExtendedResource)res).getContentIntoAStream(System.out); + System.out.println(); + } } } } catch (XMLDBException e) { @@ -2215,13 +2220,29 @@ if (maxResults <= 0) maxResults = (int) result.getSize(); if (cOpt.optionOutputFile == null) { - for (int i = 0; i < maxResults && i < result.getSize(); i++) - System.out.println((result.getResource(i)).getContent()); + for (int i = 0; i < maxResults && i < result.getSize(); i++) { + Resource res=result.getResource(i); + if(res instanceof ExtendedResource) { + ((ExtendedResource)res).getContentIntoAStream(System.out); + } else { + System.out.println(res.getContent()); + } + } } else { - FileWriter writer = new FileWriter(cOpt.optionOutputFile, false); - for (int i = 0; i < maxResults && i < result.getSize(); i++) - writer.write((result.getResource(i)).getContent().toString()); - writer.close(); + FileOutputStream fos=new FileOutputStream(cOpt.optionOutputFile); + BufferedOutputStream bos=new BufferedOutputStream(fos); + PrintStream ps=new PrintStream(bos); + for (int i = 0; i < maxResults && i < result.getSize(); i++) { + Resource res=result.getResource(i); + if(res instanceof ExtendedResource) { + ((ExtendedResource)res).getContentIntoAStream(ps); + } else { + ps.print(res.getContent().toString()); + } + } + ps.close(); + bos.close(); + fos.close(); } } catch (XMLDBException e) { System.err.println("XMLDBException during query: " Modified: trunk/eXist/src/org/exist/client/messages.properties =================================================================== --- trunk/eXist/src/org/exist/client/messages.properties 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/client/messages.properties 2008-12-02 22:17:10 UTC (rev 8354) @@ -26,6 +26,7 @@ ClientFrame.42=Copy ClientFrame.44=Move ClientFrame.46=Rename +ClientFrame.47=Export a resource to file ... ClientFrame.48=Reindex collection ClientFrame.50=Resource properties ClientFrame.52=Quit @@ -323,4 +324,4 @@ CreateBackupDialog.5=Select target for backup CreateBackupDialog.6a=Target CreateBackupDialog.6b= exists. OK to delete? -CreateBackupDialog.6c=Confirm deletion \ No newline at end of file +CreateBackupDialog.6c=Confirm deletion Modified: trunk/eXist/src/org/exist/client/messages_es_ES.properties =================================================================== --- trunk/eXist/src/org/exist/client/messages_es_ES.properties 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/client/messages_es_ES.properties 2008-12-02 22:17:10 UTC (rev 8354) @@ -26,6 +26,7 @@ ClientFrame.42=Copiar ClientFrame.44=Mover ClientFrame.46=Renombrar +ClientFrame.47=Exportar recurso a fichero ... ClientFrame.48=Reindexar colecci\xF3n ClientFrame.50=Propiedades del recurso ClientFrame.52=Salir Modified: trunk/eXist/src/org/exist/cocoon/XMLDBSource.java =================================================================== --- trunk/eXist/src/org/exist/cocoon/XMLDBSource.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/cocoon/XMLDBSource.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -48,6 +48,7 @@ import org.apache.excalibur.xml.sax.XMLizable; import org.exist.xmldb.CollectionImpl; import org.exist.xmldb.EXistResource; +import org.exist.xmldb.ExtendedResource; import org.w3c.dom.Node; import org.xml.sax.ContentHandler; import org.xml.sax.SAXException; @@ -591,14 +592,8 @@ try { setup(); // Check if it's binary - if (resource instanceof BinaryResource) { - Object obj = resource.getContent(); - if (obj == null) obj = new byte[0]; - if (obj instanceof byte[]) { - return new ByteArrayInputStream((byte[])obj); - } else { - throw new SourceException("Binary resource has returned a " + obj.getClass() + " for " + getURI()); - } + if (resource instanceof ExtendedResource) { + return ((ExtendedResource)resource).getStreamContent(); } else { // Serialize SAX result TransformerFactory tf = TransformerFactory.newInstance(); Modified: trunk/eXist/src/org/exist/storage/NativeBroker.java =================================================================== --- trunk/eXist/src/org/exist/storage/NativeBroker.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/storage/NativeBroker.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -1676,7 +1676,7 @@ } } - byte [] buffer = new byte[4096]; + byte [] buffer = new byte[65536]; OutputStream os = new FileOutputStream(binFile); int len; while ((len = is.read(buffer))>=0) { @@ -1829,7 +1829,7 @@ }.run(); */ InputStream is = getBinaryResource(blob); - byte [] buffer = new byte[4096]; + byte [] buffer = new byte[65536]; int len; while ((len=is.read(buffer))>=0) { os.write(buffer,0,len); Added: trunk/eXist/src/org/exist/xmldb/ExtendedBinaryResource.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/ExtendedBinaryResource.java (rev 0) +++ trunk/eXist/src/org/exist/xmldb/ExtendedBinaryResource.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -0,0 +1,74 @@ +/* + * eXist Open Source Native XML Database + * Copyright (C) 2001-08 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * $Id$ + */ + +package org.exist.xmldb; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Writer; + +import org.xmldb.api.base.XMLDBException; +import org.xmldb.api.modules.BinaryResource; + +/** + * An extension to BinaryResource interface, which adds the + * common methods needed by LocalBinaryResource and RemoteBinaryResource, + * so they can be streamlined. + * @author jmfernandez + * + */ +public interface ExtendedBinaryResource + extends BinaryResource +{ + /** + * It returns an object representing the content, in the representation + * which eats less memory. + */ + public Object getExtendedContent() throws XMLDBException; + /** + * It returns an stream to the content, whichever it is its origin + */ + public InputStream getStreamContent() throws XMLDBException; + /** + * It returns the length of the content, whichever it is its origin + */ + public long getStreamLength() throws XMLDBException; + + /** + * It saves the resource to the local file given as input parameter. + * Do NOT confuse with set content. + */ + public void getContentIntoAFile(File localfile) throws XMLDBException; + + /** + * It saves the resource to the local stream given as input parameter. + * Do NOT confuse with set content. + */ + public void getContentIntoAStream(OutputStream os) throws XMLDBException; + + /** + * It erases the internal reference to any file set with getContentIntoAFile, + * either explicitly or implicitly using, for instance, getStreamContent. + */ + public void freeLocalResources(); +} Added: trunk/eXist/src/org/exist/xmldb/ExtendedResource.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/ExtendedResource.java (rev 0) +++ trunk/eXist/src/org/exist/xmldb/ExtendedResource.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -0,0 +1,71 @@ +/* + * eXist Open Source Native XML Database + * Copyright (C) 2001-08 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * $Id$ + */ + +package org.exist.xmldb; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; + +import org.xmldb.api.base.XMLDBException; + +/** + * An extension to BinaryResource interface, which adds the + * common methods needed by LocalBinaryResource and RemoteBinaryResource, + * so they can be streamlined. + * @author jmfernandez + * + */ +public interface ExtendedResource +{ + /** + * It returns an object representing the content, in the representation + * which needs less memory. + */ + public Object getExtendedContent() throws XMLDBException; + /** + * It returns an stream to the content, whichever it is its origin + */ + public InputStream getStreamContent() throws XMLDBException; + /** + * It returns the length of the content, whichever it is its origin + */ + public long getStreamLength() throws XMLDBException; + + /** + * It saves the resource to the local file given as input parameter. + * Do NOT confuse with set content. + */ + public void getContentIntoAFile(File localfile) throws XMLDBException; + + /** + * It saves the resource to the local stream given as input parameter. + * Do NOT confuse with set content. + */ + public void getContentIntoAStream(OutputStream os) throws XMLDBException; + + /** + * It erases the internal reference to any file set with getContentIntoAFile, + * either explicitly or implicitly using, for instance, getStreamContent. + */ + public void freeLocalResources(); +} Modified: trunk/eXist/src/org/exist/xmldb/LocalBinaryResource.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/LocalBinaryResource.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/xmldb/LocalBinaryResource.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -22,14 +22,17 @@ */ package org.exist.xmldb; +import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.InputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.Date; import org.exist.EXistException; @@ -51,11 +54,12 @@ /** * @author wolf */ -public class LocalBinaryResource extends AbstractEXistResource implements BinaryResource { +public class LocalBinaryResource extends AbstractEXistResource implements ExtendedResource, BinaryResource, EXistResource { protected InputSource inputSource = null; protected File file = null; protected byte[] rawData = null; + private boolean isExternal=false; protected Date datecreated= null; protected Date datemodified= null; @@ -88,42 +92,55 @@ return "BinaryResource"; } + public Object getExtendedContent() throws XMLDBException { + if(file!=null) + return file; + if(inputSource!=null) + return inputSource; + + DBBroker broker = null; + BinaryDocument blob = null; + InputStream rawDataStream = null; + try { + broker = pool.get(user); + blob = (BinaryDocument)getDocument(broker, Lock.READ_LOCK); + if(!blob.getPermissions().validate(user, Permission.READ)) + throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, + "Permission denied to read resource"); + + rawDataStream = broker.getBinaryResource(blob); + } catch(EXistException e) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), e); + } catch(IOException e) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), e); + } finally { + if(blob!=null) + parent.getCollection().releaseDocument(blob, Lock.READ_LOCK); + if(broker!=null) + pool.release(broker); + } + + return rawDataStream; + } + /* (non-Javadoc) * @see org.xmldb.api.base.Resource#getContent() */ public Object getContent() throws XMLDBException { - if(rawData == null) { - if(file!=null) { - readFile(file); - } else if(inputSource!=null) { - readFile(inputSource); - } else { - DBBroker broker = null; - BinaryDocument blob = null; - try { - broker = pool.get(user); - blob = (BinaryDocument)getDocument(broker, Lock.READ_LOCK); - if(!blob.getPermissions().validate(user, Permission.READ)) - throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, - "Permission denied to read resource"); - InputStream is = broker.getBinaryResource(blob); - rawData = new byte[(int)broker.getBinaryResourceSize(blob)]; - is.read(rawData); - is.close(); - - } catch(EXistException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, - "error while loading binary resource " + getId(), e); - } catch(IOException e) { - throw new XMLDBException(ErrorCodes.VENDOR_ERROR, - "error while loading binary resource " + getId(), e); - } finally { - parent.getCollection().releaseDocument(blob, Lock.READ_LOCK); - pool.release(broker); - } + Object res=getExtendedContent(); + if(res!=null) { + if(res instanceof File) { + return readFile((File)res); + } else if(res instanceof InputSource) { + return readFile((InputSource)res); + } else if(res instanceof InputStream) { + return readFile((InputStream)res); } } - return rawData; + + return res; } /* (non-Javadoc) @@ -132,35 +149,122 @@ public void setContent(Object value) throws XMLDBException { if(value instanceof File) { file=(File)value; + isExternal=true; } else if(value instanceof InputSource) { - inputSource=(InputSource)value; - } else if(value instanceof byte[]) + inputSource=(InputSource)value; + isExternal=true; + } else if(value instanceof byte[]) { rawData = (byte[])value; - else if(value instanceof String) + isExternal=true; + } else if(value instanceof String) { rawData = ((String)value).getBytes(); - else + isExternal=true; + } else throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "don't know how to handle value of type " + value.getClass().getName()); } - protected InputStream getStreamContent() { + public InputStream getStreamContent() throws XMLDBException { InputStream retval=null; if(file!=null) { try { retval=new FileInputStream(file); } catch(FileNotFoundException fnfe) { // Cannot fire it :-( + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, fnfe.getMessage(), fnfe); } } else if(inputSource!=null) { retval=inputSource.getByteStream(); } else if(rawData!=null) { retval=new ByteArrayInputStream(rawData); + } else { + DBBroker broker = null; + BinaryDocument blob = null; + try { + broker = pool.get(user); + blob = (BinaryDocument)getDocument(broker, Lock.READ_LOCK); + if(!blob.getPermissions().validate(user, Permission.READ)) + throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, + "Permission denied to read resource"); + + retval = broker.getBinaryResource(blob); + } catch(EXistException e) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), e); + } catch(IOException e) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), e); + } finally { + if(blob!=null) + parent.getCollection().releaseDocument(blob, Lock.READ_LOCK); + if(broker!=null) + pool.release(broker); + } } return retval; } - protected long getStreamLength() { + public void getContentIntoAFile(File tmpfile) throws XMLDBException { + try { + FileOutputStream fos=new FileOutputStream(tmpfile); + BufferedOutputStream bos=new BufferedOutputStream(fos); + getContentIntoAStream(bos); + bos.close(); + fos.close(); + } catch(IOException ioe) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), ioe); + } + } + + public void getContentIntoAStream(OutputStream os) throws XMLDBException { + DBBroker broker = null; + BinaryDocument blob = null; + boolean doClose=false; + try { + broker = pool.get(user); + blob = (BinaryDocument)getDocument(broker, Lock.READ_LOCK); + if(!blob.getPermissions().validate(user, Permission.READ)) + throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, + "Permission denied to read resource"); + + // Improving the performance a bit for files! + if(os instanceof FileOutputStream) { + os = new BufferedOutputStream(os,655360); + doClose=true; + } + + broker.readBinaryResource(blob, os); + } catch(EXistException e) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), e); + } catch(IOException ioe) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), ioe); + } finally { + if(blob!=null) + parent.getCollection().releaseDocument(blob, Lock.READ_LOCK); + if(broker!=null) + pool.release(broker); + if(doClose) { + try { + os.close(); + } catch(IOException ioe) { + // IgnoreIT(R) + } + } + } + } + + public void freeLocalResources() + { + if(!isExternal && file!=null) { + file=null; + } + } + + public long getStreamLength() throws XMLDBException { long retval=-1; if(file!=null) { retval=file.length(); @@ -168,25 +272,42 @@ retval=((EXistInputSource)inputSource).getByteStreamLength(); } else if(rawData!=null) { retval=rawData.length; + } else { + DBBroker broker = null; + BinaryDocument blob = null; + try { + broker = pool.get(user); + blob = (BinaryDocument)getDocument(broker, Lock.READ_LOCK); + retval=blob.getContentLength(); + } catch(EXistException e) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, + "error while loading binary resource " + getId(), e); + } finally { + if(blob!=null) + parent.getCollection().releaseDocument(blob, Lock.READ_LOCK); + + if(broker!=null) + pool.release(broker); + } } return retval; } - private void readFile(File file) throws XMLDBException { + private byte[] readFile(File file) throws XMLDBException { try { - readFile(new FileInputStream(file)); + return readFile(new FileInputStream(file)); } catch (FileNotFoundException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "file " + file.getAbsolutePath() + " could not be found", e); } } - private void readFile(InputSource is) throws XMLDBException { - readFile(is.getByteStream()); + private byte[] readFile(InputSource is) throws XMLDBException { + return readFile(is.getByteStream()); } - private void readFile(InputStream is) throws XMLDBException { + private byte[] readFile(InputStream is) throws XMLDBException { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(2048); byte[] temp = new byte[1024]; @@ -194,7 +315,7 @@ while((count = is.read(temp)) > -1) { bos.write(temp, 0, count); } - rawData = bos.toByteArray(); + return bos.toByteArray(); } catch (FileNotFoundException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "file " + file.getAbsolutePath() + " could not be found", e); Modified: trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/xmldb/RemoteBinaryResource.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -22,16 +22,21 @@ */ package org.exist.xmldb; +import java.io.BufferedOutputStream; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.util.Date; +import java.util.Map; +import java.util.Properties; +import java.util.List; import java.util.ArrayList; -import java.util.List; import org.apache.xmlrpc.XmlRpcException; import org.exist.security.Permission; @@ -50,7 +55,7 @@ * @author wolf * */ -public class RemoteBinaryResource implements BinaryResource, EXistResource { +public class RemoteBinaryResource implements ExtendedResource, BinaryResource, EXistResource { private XmldbURI path; private String mimeType = MimeType.BINARY_TYPE.getName(); @@ -58,6 +63,7 @@ private byte[] data = null; private File file = null; private InputSource inputSource = null; + private boolean isExternal=false; private Permission permissions = null; private int contentLen = 0; @@ -97,47 +103,135 @@ } /* (non-Javadoc) - * @see org.xmldb.api.base.Resource#getContent() + * @see org.exist.xmldb.ExtendedResource#getExtendedContent() */ - public Object getContent() throws XMLDBException { - if(data != null || file!=null || inputSource!=null) { - if(data==null) { - if(file!=null) { - readFile(file); - } else if(inputSource!=null) { - readFile(inputSource); - } - } + public Object getExtendedContent() throws XMLDBException { + if(file!=null) + return file; + if(inputSource!=null) + return inputSource; + if(data != null) return data; - } + List params = new ArrayList(); params.add(path.toString()); + File tmpfile=null; try { - data = (byte[])parent.getClient().execute("getBinaryResource", params); - } catch (XmlRpcException e) { - throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, e.getMessage(), e); + tmpfile=File.createTempFile("eXistRBR",".bin"); + tmpfile.deleteOnExit(); + getContentIntoAFile(tmpfile); + } catch(IOException ioe) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); } - return data; + return tmpfile; } - - protected InputStream getStreamContent() { + + /* (non-Javadoc) + * @see org.xmldb.api.base.Resource#getContent() + */ + public Object getContent() throws XMLDBException { + Object res=getExtendedContent(); + if(res!=null) { + if(res instanceof File) { + return readFile((File)res); + } else if(res instanceof InputSource) { + return readFile((InputSource)res); + } + } + + return res; + } + + public InputStream getStreamContent() + throws XMLDBException + { InputStream retval=null; if(file!=null) { try { retval=new FileInputStream(file); } catch(FileNotFoundException fnfe) { - // Cannot fire it :-( + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, fnfe.getMessage(), fnfe); } } else if(inputSource!=null) { retval=inputSource.getByteStream(); } else if(data!=null) { retval=new ByteArrayInputStream(data); + } else { + try { + File tmpfile=File.createTempFile("eXistRBR",".bin"); + tmpfile.deleteOnExit(); + getContentIntoAFile(tmpfile); + retval = new FileInputStream(tmpfile); + } catch(IOException ioe) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); + } } return retval; } + public void getContentIntoAFile(File tmpfile) + throws XMLDBException + { + try { + FileOutputStream fos=new FileOutputStream(tmpfile); + BufferedOutputStream bos=new BufferedOutputStream(fos); + + getContentIntoAStream(bos); + bos.close(); + fos.close(); + + file=tmpfile; + } catch (IOException ioe) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); + } + } + + public void getContentIntoAStream(OutputStream os) + throws XMLDBException + { + Properties properties = parent.getProperties(); + List params = new ArrayList(); + params.add(path.toString()); + params.add(properties); + try { + Map table = (Map) parent.getClient().execute("getDocumentData", params); + String method; + boolean useLongOffset; + if(table.containsKey("supports-long-offset") && (Boolean)(table.get("supports-long-offset"))) { + useLongOffset=true; + method="getNextExtendedChunk"; + } else { + useLongOffset=false; + method="getNextChunk"; + } + long offset = ((Integer)table.get("offset")).intValue(); + byte[] data = (byte[])table.get("data"); + os.write(data); + while(offset > 0) { + params.clear(); + params.add(table.get("handle")); + params.add(useLongOffset?Long.toString(offset):new Integer((int)offset)); + table = (Map) parent.getClient().execute(method, params); + offset = useLongOffset?new Long((String)table.get("offset")).longValue():((Integer)table.get("offset")).longValue(); + data = (byte[])table.get("data"); + os.write(data); + } + } catch (XmlRpcException xre) { + throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre); + } catch (IOException ioe) { + throw new XMLDBException(ErrorCodes.VENDOR_ERROR, ioe.getMessage(), ioe); + } + } + + public void freeLocalResources() + { + if(!isExternal && file!=null) { + file=null; + } + } + protected String getStreamSymbolicPath() { String retval="<streamunknown>"; @@ -150,7 +244,9 @@ return retval; } - protected long getStreamLength() { + public long getStreamLength() + throws XMLDBException + { long retval=-1; if(file!=null) { retval=file.length(); @@ -158,6 +254,17 @@ retval=((EXistInputSource)inputSource).getByteStreamLength(); } else if(data!=null) { retval=data.length; + } else { + Properties properties = parent.getProperties(); + List params = new ArrayList(); + params.add(path.toString()); + params.add(properties); + try { + Map table = (Map) parent.getClient().execute("describeResource", params); + retval=((Integer)table.get("content-length")).intValue(); + } catch (XmlRpcException xre) { + throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, xre.getMessage(), xre); + } } return retval; @@ -169,31 +276,35 @@ public void setContent(Object obj) throws XMLDBException { if(obj instanceof File) { file=(File)obj; + isExternal=true; } else if(obj instanceof InputSource) { inputSource=(InputSource)obj; - } else if(obj instanceof byte[]) + isExternal=true; + } else if(obj instanceof byte[]) { data = (byte[])obj; - else if(obj instanceof String) + isExternal=true; + } else if(obj instanceof String) { data = ((String)obj).getBytes(); - else + isExternal=true; + } else throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "don't know how to handle value of type " + obj.getClass().getName()); } - private void readFile(File file) throws XMLDBException { + private byte[] readFile(File file) throws XMLDBException { try { - readFile(new FileInputStream(file)); + return readFile(new FileInputStream(file)); } catch (FileNotFoundException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "file " + file.getAbsolutePath() + " could not be found", e); } } - private void readFile(InputSource is) throws XMLDBException { - readFile(is.getByteStream()); + private byte[] readFile(InputSource is) throws XMLDBException { + return readFile(is.getByteStream()); } - private void readFile(InputStream is) throws XMLDBException { + private byte[] readFile(InputStream is) throws XMLDBException { try { ByteArrayOutputStream bos = new ByteArrayOutputStream(2048); byte[] temp = new byte[1024]; @@ -201,7 +312,7 @@ while((count = is.read(temp)) > -1) { bos.write(temp, 0, count); } - data = bos.toByteArray(); + return bos.toByteArray(); } catch (FileNotFoundException e) { throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "file " + file.getAbsolutePath() + " could not be found", e); Modified: trunk/eXist/src/org/exist/xmldb/RemoteCollection.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteCollection.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/xmldb/RemoteCollection.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -459,7 +459,10 @@ } public void storeResource(Resource res, Date a, Date b) throws XMLDBException { - Object content = res.getContent(); + Object content = (res instanceof ExtendedResource)? + ((ExtendedResource)res).getExtendedContent(): + res.getContent(); + if (content instanceof File || content instanceof InputSource) { long fileLength=-1; if(content instanceof File) { @@ -486,18 +489,16 @@ } else { uploadAndStore(res); } - } else if(res.getResourceType().equals("BinaryResource")) - { + } else if(res.getResourceType().equals("BinaryResource")) { ((RemoteBinaryResource)res).dateCreated =a; - ((RemoteBinaryResource)res).dateModified =b; + ((RemoteBinaryResource)res).dateModified =b; store((RemoteBinaryResource)res); - } - else { + } else { ((RemoteXMLResource)res).dateCreated =a; ((RemoteXMLResource)res).dateModified =b; store((RemoteXMLResource)res); + } } - } private void store(RemoteXMLResource res) throws XMLDBException { @@ -512,8 +513,8 @@ params.add(new Integer(1)); if (res.dateCreated != null) { - params.add(res.dateCreated ); - params.add(res.dateModified ); + params.add(res.dateCreated ); + params.add(res.dateModified ); } try { @@ -542,7 +543,7 @@ if (res.dateCreated != null) { params.add((Date)res.dateCreated ); params.add((Date)res.dateModified ); - } + } try { rpcClient.execute("storeBinary", params); @@ -608,12 +609,15 @@ throw new XMLDBException(ErrorCodes.INVALID_URI,e); } params.add(Boolean.TRUE); - params.add(((RemoteXMLResource)res).getMimeType()); - if ( ((RemoteXMLResource)res).dateCreated != null ) { - params.add( ((RemoteXMLResource)res).dateCreated ); - params.add( ((RemoteXMLResource)res).dateModified ); + if(res instanceof EXistResource) { + EXistResource rxres=(EXistResource)res; + params.add(rxres.getMimeType()); + if(rxres.getCreationTime() != null) { + params.add(rxres.getCreationTime()); + params.add(rxres.getLastModificationTime()); } - + } + rpcClient.execute("parseLocal", params); } catch (IOException e) { throw new XMLDBException( Modified: trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -147,6 +147,9 @@ HashMap getNextChunk(String handle, int offset) throws EXistException, PermissionDeniedException; + HashMap getNextExtendedChunk(String handle, String offset) + throws EXistException, PermissionDeniedException; + byte[] getBinaryResource(String name) throws EXistException, PermissionDeniedException, URISyntaxException; Modified: trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java 2008-12-02 20:48:24 UTC (rev 8353) +++ trunk/eXist/src/org/exist/xmlrpc/RpcConnection.java 2008-12-02 22:17:10 UTC (rev 8354) @@ -844,7 +844,8 @@ Serializer serializer = broker.getSerializer(); serializer.setProperties(parameters); HashMap result = new HashMap(); - if(doc.getContentLength() > MAX_DOWNLOAD_CHUNK_SIZE) { + // A tweak for very large XML resources + if(doc.getContentLength()<0 || doc.getContentLength() > MAX_DOWNLOAD_CHUNK_SIZE) { File tempFile = File.createTempFile("eXistRPCC", ".xml"); tempFile.deleteOnExit(); LOG.debug("Writing to temporary file: " + tempFile.getName()); @@ -858,6 +859,7 @@ result.put("data", firstChunk); result.put("handle", tempFile.getAbsolutePath()); result.put("offset", new Integer(firstChunk.length)); + result.put("supports-long-offset", new Boolean(true)); } else { String xml = serializer.serialize(doc); result.put("data", xml.getBytes(encoding)); @@ -866,7 +868,8 @@ return result; } else { HashMap result = new HashMap(); - if(doc.getContentLength() > MAX_DOWNLOAD_CHUNK_SIZE) { + // A tweak for very large binary resources + if(doc.getContentLength()<0 || doc.getContentLength() > MAX_DOWNLOAD_CHUNK_SIZE) { File tempFile = File.createTempFile("eXistRPCC", ".bin"); tempFile.deleteOnExit(); LOG.debug("Writing to temporary file: " + tempFile.getName()); @@ -878,12 +881,18 @@ result.put("data", firstChunk); result.put("handle", tempFile.getAbsolutePath()); result.put("offset", new Integer(firstChunk.length)); - + result.put("supports-long-offset", new Boolean(true)); } else { try { InputStream is = broker.getBinaryResource((BinaryDocument)doc); - byte[] data = new byte[(int)broker.getBinaryResourceSize((BinaryDocument)doc)]; - is.read(data); + int datasize=(int)broker.getBinaryResourceSize((BinaryDocument)doc); + byte[] data = new byte[datasize]; + int datapos=0; + int dataread=0; + while(datasize>0 && (dataread=is.read(data, datapos, datasize))!=-1) { + datapos+=dataread; + datasize-=dataread; + } is.close(); result.put("data", data); result.put("offset", new Integer(0)); @@ -921,16 +930,16 @@ if(offset <= 0 || offset > file.length()) throw new EXistException("No more data available"); byte[] chunk = getChunk(file, offset); - int nextChunk = offset + chunk.length; + long nextChunk = offset + chunk.length; HashMap result = new HashMap(); result.put("data", chunk); result.put("handle", handle); - if(nextChunk == file.length()) { + if(nextChunk > (long)Integer.MAX_VALUE || nextChunk == file.length()) { file.delete(); result.put("offset", new Integer(0)); } else - result.put("offset", new Integer(nextChunk)); + result.put("offset", new Integer((int)nextChunk)); return result; } catch (Exception e) { handleException(e); @@ -939,20 +948,54 @@ } /** + * The method <code>getNextExtendedChunk</code> + * + * @param handle a <code>String</code> value + * @param offset a <code>String</code> value + * @return a <code>HashMap</code> value + * @exception Exception if an error occurs + */ + public HashMap getNextExtendedChunk(String handle, String offset) throws EXistException, PermissionDeniedException { + try { + File file = new File(handle); + if(!(file.isFile() && file.canRead())) + throw new EXistException("Invalid handle specified"); + long longOffset=new Long(offset).longValue(); + if(longOffset > file.length()) + throw new EXistException("No more data available"); + byte[] chunk = getChunk(file, longOffset); + long nextChunk = longOffset + chunk.length; + + HashMap result = new HashMap(); + result.put("data", chunk); + result.put("handle", handle); + if(nextChunk == file.length()) { + file.delete(); + result.put("offset", Long.toString(0)); + } else + result.put("offset", Long.toString(nextChunk)); + return result; + } catch (Exception e) { + handleException(e); + return null; + } + } + + /** * The method <code>getChunk</code> * * @param file a <code>File</code> value - * @param offset an <code>int</code> value + * @param offset a <code>long</code> value * @return a <code>byte[]</code> value * @exception IOException if an error occurs */ - private byte[] getChunk(File file, int offset) throws IOException { + private byte[] getChunk(File file, long offset) throws IOException { RandomAccessFile raf = new RandomAccessFile(file, "r"); - raf.seek((long)offset); - int remaining = (int)(raf.length() - offset); + raf.seek(offset); + long remaining = raf.length() - offset; if(remaining > MAX_DOWNLOAD_CHUNK_SIZE) remaining = MAX_DOWNLOAD_CHUNK_SIZE; - byte[] data = new byte[remaining]; + byte[] data = new byte[(int)remaining]; raf.readFully(data); raf.close(); return data; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2008-12-07 16:27:18
|
Revision: 8372 http://exist.svn.sourceforge.net/exist/?rev=8372&view=rev Author: wolfgang_m Date: 2008-12-07 16:27:13 +0000 (Sun, 07 Dec 2008) Log Message: ----------- [feature] extended XQueryURLRewrite into a basic model-view-controller framework. Requests can now be filtered through one or more views before being returned. Data can be passed through the request stream or request attributes. Added XSLTServlet for transformations. Changed XQueryServlet to optionally write the result into a request attribute, which can be read by XSLTServlet. Modified Paths: -------------- trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java trunk/eXist/src/org/exist/http/urlrewrite/Forward.java trunk/eXist/src/org/exist/http/urlrewrite/URLRewrite.java trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java trunk/eXist/src/org/exist/storage/serializers/Serializer.java trunk/eXist/src/org/exist/storage/serializers/XIncludeFilter.java trunk/eXist/src/org/exist/xmldb/LocalResourceSet.java trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java trunk/eXist/src/org/exist/xslt/TransformerFactoryAllocator.java Added Paths: ----------- trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java trunk/eXist/src/org/exist/util/serializer/SAXToReceiver.java Modified: trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java =================================================================== --- trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -44,6 +44,7 @@ import org.exist.xmldb.CollectionImpl; import org.exist.xmldb.XQueryService; import org.exist.xmldb.XmldbURI; +import org.exist.xmldb.LocalResourceSet; import org.exist.xquery.Constants; import org.exist.xquery.XPathException; import org.exist.xquery.functions.request.RequestModule; @@ -342,7 +343,9 @@ } if(actualUser == null) actualUser = user; if(actualPassword == null) actualPassword = password; - + + String requestAttr = (String) request.getAttribute("xquery.attribute"); + try { Collection collection = DatabaseManager.getCollection(collectionURI.toString(), actualUser, actualPassword); XQueryService service = (XQueryService) @@ -363,9 +366,13 @@ if (!response.isCommitted()) response.setContentType(mediaType + "; charset=" + formEncoding); } - for(ResourceIterator i = result.getIterator(); i.hasMoreResources(); ) { - Resource res = i.nextResource(); - output.println(res.getContent().toString()); + if (requestAttr != null && !((CollectionImpl)collection).isRemoteCollection()) { + request.setAttribute(requestAttr, ((LocalResourceSet)result).toSequence()); + } else { + for(ResourceIterator i = result.getIterator(); i.hasMoreResources(); ) { + Resource res = i.nextResource(); + output.println(res.getContent().toString()); + } } } catch (XMLDBException e) { LOG.debug(e); Added: trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java =================================================================== --- trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java (rev 0) +++ trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -0,0 +1,347 @@ +/* + * eXist Open Source Native XML Database + * Copyright (C) 2001-07 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * $Id$ + */ +package org.exist.http.servlets; + +import org.exist.xquery.value.Item; +import org.exist.xquery.value.NodeValue; +import org.exist.xquery.value.Type; +import org.exist.xquery.XPathException; +import org.exist.xquery.Constants; +import org.exist.xquery.XQueryContext; +import org.exist.xslt.TransformerFactoryAllocator; +import org.exist.storage.lock.Lock; +import org.exist.storage.serializers.Serializer; +import org.exist.storage.serializers.XIncludeFilter; +import org.exist.storage.BrokerPool; +import org.exist.storage.DBBroker; +import org.exist.security.PermissionDeniedException; +import org.exist.security.Permission; +import org.exist.security.User; +import org.exist.xmldb.XmldbURI; +import org.exist.dom.DocumentImpl; +import org.exist.collections.Collection; +import org.exist.EXistException; +import org.exist.util.serializer.Receiver; +import org.exist.util.serializer.ReceiverToSAX; +import org.exist.util.serializer.SAXToReceiver; +import org.xml.sax.SAXException; +import org.xml.sax.XMLReader; +import org.xml.sax.InputSource; +import org.apache.log4j.Logger; + +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.ServletException; +import javax.xml.transform.sax.TransformerHandler; +import javax.xml.transform.sax.SAXTransformerFactory; +import javax.xml.transform.sax.TemplatesHandler; +import javax.xml.transform.TransformerFactoryConfigurationError; +import javax.xml.transform.Templates; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.URIResolver; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerException; +import javax.xml.transform.Transformer; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamSource; +import javax.xml.transform.stream.StreamResult; +import java.io.IOException; +import java.io.File; +import java.io.OutputStream; +import java.io.BufferedOutputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Map; +import java.util.HashMap; + +public class XSLTServlet extends HttpServlet { + + private final static Logger LOG = Logger.getLogger(XSLTServlet.class); + + private BrokerPool pool; + + private final Map cache = new HashMap(); + + protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + String stylesheet = (String) request.getAttribute("xslt.stylesheet"); + if (stylesheet == null) + throw new ServletException("No stylesheet source specified!"); + + Item inputNode = null; + String sourceAttrib = (String) request.getAttribute("xslt.input"); + if (sourceAttrib != null) { + Object sourceObj = request.getAttribute(sourceAttrib); + if (sourceObj != null) { + if (sourceObj instanceof Item) { + inputNode = (Item) sourceObj; + if (!Type.subTypeOf(inputNode.getType(), Type.NODE)) + throw new ServletException("Input for XSLT servlet is not a node. Read from attribute " + + sourceAttrib); + LOG.debug("Taking XSLT input from request attribute " + sourceAttrib); + } else + throw new ServletException("Input for XSLT servlet is not a node. Read from attribute " + + sourceAttrib); + } + } + + String userParam = (String) request.getAttribute("xslt.user"); + String passwd = (String) request.getAttribute("xslt.password"); + if (userParam == null) { + userParam = org.exist.security.SecurityManager.GUEST_USER; + passwd = userParam; + } + + try { + pool = BrokerPool.getInstance(); + User user = pool.getSecurityManager().getUser(userParam); + if (user != null) { + if (!user.validate(passwd)) { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Wrong password or user"); + } + } + + SAXTransformerFactory factory = TransformerFactoryAllocator.getTransformerFactory(pool); + Templates templates = getSource(user, request, factory, stylesheet); + //do the transformation + DBBroker broker = null; + try { + broker = pool.get(user); + OutputStream os = response.getOutputStream(); + OutputStream bufferedOutputStream = new BufferedOutputStream(os); + StreamResult result = new StreamResult(bufferedOutputStream); + TransformerHandler handler = factory.newTransformerHandler(templates); + handler.setResult(result); + String mediaType = handler.getTransformer().getOutputProperty("media-type"); + String encoding = handler.getTransformer().getOutputProperty("encoding"); + if (mediaType != null) { + if (encoding == null) + response.setContentType(mediaType); + else + response.setContentType(mediaType + "; charset=" + encoding); + } + Serializer serializer = broker.getSerializer(); + serializer.reset(); + Receiver receiver = new ReceiverToSAX(handler); + try { + XIncludeFilter xinclude = new XIncludeFilter(serializer, receiver); + receiver = xinclude; + String requestPath = request.getRequestURI(); + int p = requestPath.lastIndexOf("/"); + if(p != Constants.STRING_NOT_FOUND) + requestPath = requestPath.substring(0, p); + String moduleLoadPath = getServletContext().getRealPath(requestPath.substring(request.getContextPath().length())); + xinclude.setModuleLoadPath(moduleLoadPath); + serializer.setReceiver(receiver); + if (inputNode != null) + serializer.toSAX((NodeValue)inputNode); + else { + SAXToReceiver saxreceiver = new SAXToReceiver(receiver); + XMLReader reader = pool.getParserPool().borrowXMLReader(); + reader.setContentHandler(saxreceiver); + reader.parse(new InputSource(request.getInputStream())); + } + } catch (SAXException e) { + throw new ServletException("SAX exception while transforming node: " + e.getMessage(), e); + } + bufferedOutputStream.close(); + response.flushBuffer(); + } catch (IOException e) { + throw new ServletException("IO exception while transforming node: " + e.getMessage(), e); + } catch (TransformerException e) { + throw new ServletException("Exception while transforming node: " + e.getMessage(), e); + } finally { + pool.release(broker); + } + } catch (EXistException e) { + throw new ServletException(e.getMessage(), e); + } + } + + private Templates getSource(User user, HttpServletRequest request, SAXTransformerFactory factory, String stylesheet) + throws ServletException { + String base; + if(stylesheet.indexOf(':') == Constants.STRING_NOT_FOUND) { + File f = new File(stylesheet); + if (f.canRead()) + stylesheet = f.toURI().toASCIIString(); + else { + stylesheet = request.getRealPath(stylesheet); + f = new File(stylesheet); + stylesheet = f.toURI().toASCIIString(); + } + } + int p = stylesheet.lastIndexOf("/"); + if(p != Constants.STRING_NOT_FOUND) + base = stylesheet.substring(0, p); + else + base = stylesheet; + CachedStylesheet cached = (CachedStylesheet)cache.get(stylesheet); + if(cached == null) { + cached = new CachedStylesheet(factory, user, stylesheet, base); + cache.put(stylesheet, cached); + } + return cached.getTemplates(user); + } + + private class CachedStylesheet { + + SAXTransformerFactory factory; + long lastModified = -1; + Templates templates = null; + String uri; + + public CachedStylesheet(SAXTransformerFactory factory, User user, String uri, String baseURI) throws ServletException { + this.factory = factory; + this.uri = uri; + if (!baseURI.startsWith("xmldb:exist://")) + factory.setURIResolver(new ExternalResolver(baseURI)); + getTemplates(user); + } + + public Templates getTemplates(User user) throws ServletException { + if (uri.startsWith("xmldb:exist://")) { + String docPath = uri.substring("xmldb:exist://".length()); + DocumentImpl doc = null; + DBBroker broker = null; + try { + broker = pool.get(user); + doc = broker.getXMLResource(XmldbURI.create(docPath), Lock.READ_LOCK); + if (doc != null && (templates == null || doc.getMetadata().getLastModified() > lastModified)) + templates = getSource(broker, doc); + lastModified = doc.getMetadata().getLastModified(); + } catch (PermissionDeniedException e) { + throw new ServletException("Permission denied to read stylesheet: " + uri, e); + } catch (EXistException e) { + throw new ServletException("Error while reading stylesheet source from db: " + e.getMessage(), e); + } finally { + pool.release(broker); + doc.getUpdateLock().release(Lock.READ_LOCK); + } + } else { + try { + URL url = new URL(uri); + URLConnection connection = url.openConnection(); + long modified = connection.getLastModified(); + if(templates == null || modified > lastModified || modified == 0) { + LOG.debug("compiling stylesheet " + url.toString()); + templates = factory.newTemplates(new StreamSource(connection.getInputStream())); + } + lastModified = modified; + } catch (IOException e) { + throw new ServletException("Error while reading stylesheet source from uri: " + uri + + ": " + e.getMessage(), e); + } catch (TransformerConfigurationException e) { + throw new ServletException("Error while reading stylesheet source from uri: " + uri + + ": " + e.getMessage(), e); + } + } + return templates; + } + + private Templates getSource(DBBroker broker, DocumentImpl stylesheet) + throws ServletException { + factory.setURIResolver(new DatabaseResolver(broker, stylesheet)); + try { + TemplatesHandler handler = factory.newTemplatesHandler(); + handler.startDocument(); + Serializer serializer = broker.getSerializer(); + serializer.reset(); + serializer.setSAXHandlers(handler, null); + serializer.toSAX(stylesheet); + handler.endDocument(); + return handler.getTemplates(); + } catch (SAXException e) { + throw new ServletException("A SAX exception occurred while compiling the stylesheet: " + e.getMessage(), e); + } catch (TransformerConfigurationException e) { + throw new ServletException("A configuration exception occurred while compiling the stylesheet: " + e.getMessage(), e); + } + } + } + + private class ExternalResolver implements URIResolver { + + private String baseURI; + + public ExternalResolver(String base) { + this.baseURI = base; + } + + /* (non-Javadoc) + * @see javax.xml.transform.URIResolver#resolve(java.lang.String, java.lang.String) + */ + public Source resolve(String href, String base) + throws TransformerException { + URL url; + try { + //TODO : use dedicated function in XmldbURI + url = new URL(baseURI + "/" + href); + URLConnection connection = url.openConnection(); + return new StreamSource(connection.getInputStream()); + } catch (MalformedURLException e) { + return null; + } catch (IOException e) { + return null; + } + } + } + + private class DatabaseResolver implements URIResolver { + + DocumentImpl doc; + DBBroker broker; + + public DatabaseResolver(DBBroker broker, DocumentImpl myDoc) { + this.doc = myDoc; + } + + + /* (non-Javadoc) + * @see javax.xml.transform.URIResolver#resolve(java.lang.String, java.lang.String) + */ + public Source resolve(String href, String base) + throws TransformerException { + Collection collection = doc.getCollection(); + String path; + //TODO : use dedicated function in XmldbURI + if(href.startsWith("/")) + path = href; + else + path = collection.getURI() + "/" + href; + DocumentImpl xslDoc; + try { + xslDoc = (DocumentImpl) broker.getXMLResource(XmldbURI.create(path)); + } catch (PermissionDeniedException e) { + throw new TransformerException(e.getMessage(), e); + } + if(xslDoc == null) { + LOG.debug("Document " + href + " not found in collection " + collection.getURI()); + return null; + } + if(!xslDoc.getPermissions().validate(broker.getUser(), Permission.READ)) + throw new TransformerException("Insufficient privileges to read resource " + path); + DOMSource source = new DOMSource(xslDoc); + return source; + } + } +} Modified: trunk/eXist/src/org/exist/http/urlrewrite/Forward.java =================================================================== --- trunk/eXist/src/org/exist/http/urlrewrite/Forward.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/http/urlrewrite/Forward.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -37,7 +37,10 @@ } public void doRewrite(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { - getRequestDispatcher(request).forward(request, response); + RequestDispatcher dispatcher = getRequestDispatcher(request); + if (dispatcher == null) + throw new ServletException("Failed to initialize request dispatcher to forward request to " + uri); + dispatcher.forward(request, response); } protected abstract RequestDispatcher getRequestDispatcher(HttpServletRequest request); Modified: trunk/eXist/src/org/exist/http/urlrewrite/URLRewrite.java =================================================================== --- trunk/eXist/src/org/exist/http/urlrewrite/URLRewrite.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/http/urlrewrite/URLRewrite.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -22,12 +22,17 @@ package org.exist.http.urlrewrite; import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.exist.Namespaces; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.FilterChain; import javax.servlet.ServletException; import java.io.IOException; +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; /** * Base class for all rewritten URLs. @@ -36,11 +41,42 @@ protected String uri; protected String target; + protected Map attributes = null; + protected Map parameters = null; + protected Map headers = null; protected URLRewrite(Element config, String uri) { this.uri = uri; + // Check for add-parameter elements etc. + if (config.hasChildNodes()) { + Node node = config.getFirstChild(); + while (node != null) { + if (node.getNodeType() == Node.ELEMENT_NODE && Namespaces.EXIST_NS.equals(node.getNamespaceURI())) { + Element elem = (Element) node; + if ("add-parameter".equals(elem.getLocalName())) { + addParameter(elem.getAttribute("name"), elem.getAttribute("value")); + } else if ("set-attribute".equals(elem.getLocalName())) { + setAttribute(elem.getAttribute("name"), elem.getAttribute("value")); + } + } + node = node.getNextSibling(); + } + } } + private void addParameter(String name, String value) { + if (parameters == null) + parameters = new HashMap(); + parameters.put(name, value); + } + + private void setAttribute(String name, String value) { + if (attributes == null) + attributes = new HashMap(); + attributes.put(name, value); + } + + public void setTarget(String target) { this.target = target; } @@ -48,6 +84,21 @@ public abstract void doRewrite(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException; + public void prepareRequest(XQueryURLRewrite.RequestWrapper request) { + if (parameters != null) { + for (Iterator iterator = parameters.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + request.addParameter(entry.getKey().toString(), (String) entry.getValue()); + } + } + if (attributes != null) { + for (Iterator iterator = attributes.entrySet().iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + request.setAttribute(entry.getKey().toString(), entry.getValue()); + } + } + } + protected static String normalizePath(String path) { StringBuffer sb = new StringBuffer(path.length()); for (int i = 0; i < path.length(); i++) { Modified: trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java =================================================================== --- trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -23,14 +23,13 @@ package org.exist.http.urlrewrite; import org.apache.log4j.Logger; -import org.exist.xmldb.XmldbURI; -import org.exist.xmldb.XQueryService; -import org.exist.xmldb.CollectionImpl; import org.exist.source.FileSource; +import org.exist.source.Source; +import org.exist.source.DBSource; +import org.exist.source.SourceFactory; import org.exist.xquery.functions.request.RequestModule; import org.exist.xquery.functions.response.ResponseModule; import org.exist.xquery.functions.session.SessionModule; -import org.exist.xquery.Constants; import org.exist.xquery.XQuery; import org.exist.xquery.XQueryContext; import org.exist.xquery.CompiledXQuery; @@ -41,6 +40,9 @@ import org.exist.xquery.value.NodeValue; import org.exist.Namespaces; import org.exist.EXistException; +import org.exist.dom.DocumentImpl; +import org.exist.dom.BinaryDocument; +import org.exist.xmldb.XmldbURI; import org.exist.util.serializer.SAXSerializer; import org.exist.util.serializer.SerializerPool; import org.exist.security.*; @@ -48,21 +50,14 @@ import org.exist.storage.BrokerPool; import org.exist.storage.DBBroker; import org.exist.storage.XQueryPool; +import org.exist.storage.lock.Lock; import org.exist.storage.serializers.Serializer; import org.exist.http.servlets.HttpRequestWrapper; import org.exist.http.servlets.HttpResponseWrapper; -import org.exist.http.servlets.HttpSessionWrapper; -import org.exist.http.servlets.ResponseWrapper; -import org.exist.http.BadRequestException; -import org.xmldb.api.base.Database; -import org.xmldb.api.base.Collection; -import org.xmldb.api.base.ResourceSet; -import org.xmldb.api.base.XMLDBException; -import org.xmldb.api.DatabaseManager; -import org.xmldb.api.modules.XMLResource; import org.w3c.dom.Node; import org.w3c.dom.Document; import org.w3c.dom.Element; +import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.servlet.Filter; @@ -71,21 +66,31 @@ import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.FilterChain; -import javax.servlet.RequestDispatcher; import javax.servlet.ServletOutputStream; +import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponseWrapper; import java.io.IOException; import java.io.File; import java.io.Writer; import java.io.OutputStreamWriter; -import java.net.URISyntaxException; +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.ByteArrayInputStream; +import java.io.UnsupportedEncodingException; import java.util.Map; import java.util.HashMap; import java.util.Enumeration; import java.util.Vector; import java.util.Iterator; import java.util.Properties; +import java.util.List; +import java.util.ArrayList; +import java.util.LinkedList; +import java.net.URISyntaxException; /** * A filter to redirect HTTP requests. Similar to the popular UrlRewriteFilter, but @@ -184,6 +189,8 @@ // path to the query private String query = null; + private Source source = null; + private boolean checkModified = true; public void init(FilterConfig filterConfig) throws ServletException { // save FilterConfig for later use @@ -192,9 +199,14 @@ query = filterConfig.getInitParameter("xquery"); if (query == null) throw new ServletException(getClass().getName() + " requires a parameter 'xquery'."); + + String opt = filterConfig.getInitParameter("check-modified"); + if (opt != null) + checkModified = opt != null && opt.equalsIgnoreCase("true"); } public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + long start = System.currentTimeMillis(); HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; if (request.getCharacterEncoding() == null) { @@ -204,24 +216,49 @@ } } - DBBroker broker = null; + LOG.debug(request.getRequestURI()); + try { configure(); - broker = pool.get(user); - URLRewrite rewrite = (URLRewrite) urlCache.get(request.getRequestURI()); - if (rewrite == null) { + DBBroker broker = null; + if (source != null && checkModified) { + if (source instanceof DBSource) { + // Check if the XQuery source changed. If yes, clear all caches. + try { + broker = pool.get(user); + if (source.isValid(broker) != Source.VALID) + urlCache.clear(); + } finally { + pool.release(broker); + } + } else { + if (source.isValid((DBBroker)null) != Source.VALID) + urlCache.clear(); + } + } + + RequestWrapper modifiedRequest = new RequestWrapper(request); + // check if the request URI is already in the url cache + ModelAndView modelView = (ModelAndView) urlCache.get(request.getRequestURI()); + // no: create a new model and view configuration + if (modelView == null) { + modelView = new ModelAndView(); // Execute the query - Sequence result = runQuery(broker, request, response); + Sequence result = Sequence.EMPTY_SEQUENCE; + try { + broker = pool.get(user); + result = runQuery(broker, request, response); + } finally { + pool.release(broker); + } - RequestWrapper modifiedRequest = null; - boolean useCache = false; // process the query result if (result.getItemCount() == 1) { Item resource = result.itemAt(0); if (!Type.subTypeOf(resource.getType(), Type.NODE)) throw new ServletException("XQueryURLRewrite: urlrewrite query should return an element!"); - Node node = ((NodeValue)resource).getNode(); + Node node = ((NodeValue) resource).getNode(); if (node.getNodeType() == Node.DOCUMENT_NODE) node = ((Document) node).getDocumentElement(); if (node.getNodeType() != Node.ELEMENT_NODE) { @@ -237,74 +274,120 @@ while (node != null) { if (node.getNodeType() == Node.ELEMENT_NODE && Namespaces.EXIST_NS.equals(node.getNamespaceURI())) { Element action = (Element) node; - if ("forward".equals(action.getLocalName())) { - rewrite = new PathForward(config, action, request.getRequestURI()); - } else if ("redirect".equals(action.getLocalName())) { - rewrite = new Redirect(action, request.getRequestURI()); - } else if ("call".equals(action.getLocalName())) { - rewrite = new ModuleCall(action, queryContext, request.getRequestURI()); + if ("view".equals(action.getLocalName())) { + parseViews(request, action, modelView); + } else if ("cache-control".equals(action.getLocalName())) { + String option = action.getAttribute("cache"); + modelView.setUseCache("yes".equals(option)); + } else { + URLRewrite urw = parseAction(request, action); + if (urw != null) + modelView.setModel(urw); } } node = node.getNextSibling(); } + if (modelView.getModel() == null) + modelView.setModel(new PassThrough(elem, request.getRequestURI())); } else if ("ignore".equals(elem.getLocalName())) { - rewrite = new PassThrough(elem, request.getRequestURI()); - } - - // Check for add-parameter elements etc. - if (elem.hasChildNodes()) { - node = elem.getFirstChild(); - while (node != null) { - if (node.getNodeType() == Node.ELEMENT_NODE && Namespaces.EXIST_NS.equals(node.getNamespaceURI())) { - elem = (Element) node; - if ("add-parameter".equals(elem.getLocalName())) { - if (modifiedRequest == null) - modifiedRequest = new RequestWrapper(request); - modifiedRequest.addParameter(elem.getAttribute("name"), elem.getAttribute("value")); - } else if ("cache-control".equals(elem.getLocalName())) { - String option = elem.getAttribute("cache"); - useCache = "yes".equals(option); - } - } - node = node.getNextSibling(); + modelView.setModel(new PassThrough(elem, request.getRequestURI())); + NodeList nl = elem.getElementsByTagNameNS(Namespaces.EXIST_NS, "cache-control"); + if (nl.getLength() > 0) { + elem = (Element) nl.item(0); + String option = elem.getAttribute("cache"); + modelView.setUseCache("yes".equals(option)); } } - if (modifiedRequest != null) - request = modifiedRequest; - } else { - // empty result: pass through the filter chain - rewrite = new PassThrough(request.getRequestURI()); } // store the original request URI to org.exist.forward.request-uri - request.setAttribute(RQ_ATTR_REQUEST_URI, request.getRequestURI()); - request.setAttribute(RQ_ATTR_SERVLET_PATH, request.getServletPath()); + modifiedRequest.setAttribute(RQ_ATTR_REQUEST_URI, request.getRequestURI()); + modifiedRequest.setAttribute(RQ_ATTR_SERVLET_PATH, request.getServletPath()); - if (useCache) { - urlCache.put(request.getRequestURI(), rewrite); + if (modelView.useCache()) { + urlCache.put(request.getRequestURI(), modelView); } - } - LOG.debug("REQUEST: " + request.getClass().getName()); - if (rewrite == null) - throw new ServletException("No URL rewrite rule found! Giving up."); - rewrite.doRewrite(request, response, filterChain); + } else + if (LOG.isDebugEnabled()) + LOG.debug("Request URI found in cache: " + request.getRequestURI()); - Sequence result; - if ((result = (Sequence) request.getAttribute(RQ_ATTR_RESULT)) != null) { - writeResults(response, broker, result); + if (LOG.isDebugEnabled()) + LOG.debug("URLRewrite took " + (System.currentTimeMillis() - start) + "ms."); + + HttpServletResponse wrappedResponse = response; + if (modelView.hasViews()) + wrappedResponse = new CachingResponseWrapper(response); + modelView.getModel().prepareRequest(modifiedRequest); + modelView.getModel().doRewrite(modifiedRequest, wrappedResponse, filterChain); + + if (modelView.hasViews()) { + int status = ((CachingResponseWrapper) wrappedResponse).getStatus(); + if (status < 300) { + List views = modelView.views; + for (int i = 0; i < views.size(); i++) { + URLRewrite view = (URLRewrite) views.get(i); + RequestWrapper wrappedReq = new RequestWrapper(request); + wrappedReq.setMethod("POST"); + wrappedReq.setCharacterEncoding(wrappedResponse.getCharacterEncoding()); + wrappedReq.setContentType(wrappedResponse.getContentType()); + byte[] data = ((CachingResponseWrapper) wrappedResponse).getData(); + if (data != null) + wrappedReq.setData(data); + + if (i < views.size() - 1) + wrappedResponse = new CachingResponseWrapper(response); + else + wrappedResponse = response; + view.prepareRequest(wrappedReq); + view.doRewrite(wrappedReq, wrappedResponse, null); + wrappedResponse.flushBuffer(); + } + } else { + byte[] data = ((CachingResponseWrapper) wrappedResponse).getData(); + if (data != null) { + response.setContentType(wrappedResponse.getContentType()); + response.setCharacterEncoding(wrappedResponse.getCharacterEncoding()); + response.getOutputStream().write(data); + response.flushBuffer(); + } + } } +// Sequence result; +// if ((result = (Sequence) request.getAttribute(RQ_ATTR_RESULT)) != null) { +// writeResults(response, broker, result); +// } } catch (EXistException e) { throw new ServletException("An error occurred while retrieving query results: " + e.getMessage(), e); } catch (XPathException e) { throw new ServletException("An error occurred while executing the urlrewrite query: " + e.getMessage(), e); - } catch (SAXException e) { - throw new ServletException("Error while serializing results: " + e.getMessage(), e); - } finally { - if (pool != null) - pool.release(broker); +// } catch (SAXException e) { +// throw new ServletException("Error while serializing results: " + e.getMessage(), e); } } + private URLRewrite parseAction(HttpServletRequest request, Element action) throws ServletException { + URLRewrite rewrite = null; + if ("forward".equals(action.getLocalName())) { + rewrite = new PathForward(config, action, request.getRequestURI()); + } else if ("redirect".equals(action.getLocalName())) { + rewrite = new Redirect(action, request.getRequestURI()); +// } else if ("call".equals(action.getLocalName())) { +// rewrite = new ModuleCall(action, queryContext, request.getRequestURI()); + } + return rewrite; + } + + private void parseViews(HttpServletRequest request, Element view, ModelAndView modelView) throws ServletException { + Node node = view.getFirstChild(); + while (node != null) { + if (node.getNodeType() == Node.ELEMENT_NODE && Namespaces.EXIST_NS.equals(node.getNamespaceURI())) { + URLRewrite urw = parseAction(request, (Element) node); + modelView.addView(urw); + } + node = node.getNextSibling(); + } + } + private void configure() throws EXistException, ServletException { if (pool == null) { String username = config.getInitParameter("user"); @@ -345,14 +428,39 @@ private Sequence runQuery(DBBroker broker, HttpServletRequest request, HttpServletResponse response) throws ServletException, XPathException { // Try to find the XQuery - String qpath = config.getServletContext().getRealPath(query); - if (qpath == null) - qpath = query; - File f = new File(qpath); - if (!(f.canRead() && f.isFile())) - throw new ServletException("Cannot read XQuery source from " + f.getAbsolutePath()); - FileSource source = new FileSource(f, "UTF-8", true); - + String moduleLoadPath = config.getServletContext().getRealPath("."); + if (query.startsWith(XmldbURI.XMLDB_URI_PREFIX)) { + // Is the module source stored in the database? + try { + XmldbURI locationUri = XmldbURI.xmldbUriFor(query); + DocumentImpl sourceDoc = null; + try { + sourceDoc = broker.getXMLResource(locationUri.toCollectionPathURI(), Lock.READ_LOCK); + if (sourceDoc == null) + throw new ServletException("XQuery resource: " + query + " not found in database"); + if (sourceDoc.getResourceType() != DocumentImpl.BINARY_FILE || + !sourceDoc.getMetadata().getMimeType().equals("application/xquery")) + throw new ServletException("XQuery resource: " + query + " is not an XQuery or " + + "declares a wrong mime-type"); + source = new DBSource(broker, (BinaryDocument) sourceDoc, true); + } catch (PermissionDeniedException e) { + throw new ServletException("permission denied to read module source from " + query); + } finally { + if(sourceDoc != null) + sourceDoc.getUpdateLock().release(Lock.READ_LOCK); + } + } catch(URISyntaxException e) { + throw new ServletException(e.getMessage(), e); + } + } else { + try { + source = SourceFactory.getSource(broker, moduleLoadPath, query, true); + } catch (IOException e) { + throw new ServletException("IO error while reading XQuery source: " + query); + } catch (PermissionDeniedException e) { + throw new ServletException("Permission denied while reading XQuery source: " + query); + } + } XQuery xquery = broker.getXQueryService(); XQueryPool pool = xquery.getXQueryPool(); CompiledXQuery compiled = pool.borrowCompiledXQuery(broker, source); @@ -362,13 +470,13 @@ queryContext = compiled.getContext(); } // Find correct module load path - queryContext.setModuleLoadPath(f.getParentFile().getAbsolutePath()); + queryContext.setModuleLoadPath(moduleLoadPath); declareVariables(queryContext, request, response); if (compiled == null) { try { compiled = xquery.compile(queryContext, source); } catch (IOException e) { - throw new ServletException("Failed to read query from " + f.getAbsolutePath(), e); + throw new ServletException("Failed to read query from " + query, e); } } try { @@ -390,10 +498,54 @@ context.declareVariable(SessionModule.PREFIX + ":session", reqw.getSession()); } - private class RequestWrapper extends javax.servlet.http.HttpServletRequestWrapper { + private class ModelAndView { + URLRewrite rewrite = null; + List views = new LinkedList(); + boolean useCache = false; + + private ModelAndView() { + } + + public void setModel(URLRewrite model) { + this.rewrite = model; + } + + public URLRewrite getModel() { + return rewrite; + } + + public void addView(URLRewrite view) { + views.add(view); + } + + public boolean hasViews() { + return views.size() > 0; + } + + public boolean useCache() { + return useCache; + } + + public void setUseCache(boolean useCache) { + this.useCache = useCache; + } + } + + public static class RequestWrapper extends javax.servlet.http.HttpServletRequestWrapper { + Map addedParams = new HashMap(); + Map attributes = new HashMap(); + + ServletInputStream sis = null; + BufferedReader reader = null; + + String contentType = null; + int contentLength = 0; + String characterEncoding = null; + String method = null; + private RequestWrapper(HttpServletRequest request) { super(request); // copy parameters @@ -405,8 +557,27 @@ else addedParams.put(key, value); } + + contentType = request.getContentType(); } + public String getMethod() { + if (method == null) + return super.getMethod(); + return method; + } + + public void setMethod(String method) { + this.method = method; + } + + protected void setData(byte[] data) { + if (data == null) + data = new byte[0]; + contentLength = data.length; + sis = new CachingServletInputStream(data); + } + public void addParameter(String name, String value) { addedParams.put(name, value); } @@ -438,5 +609,180 @@ } return null; } + + public ServletInputStream getInputStream() throws IOException { + if (sis == null) + return super.getInputStream(); + return sis; + } + + public BufferedReader getReader() throws IOException { + if (sis == null) + return super.getReader(); + if (reader == null) + reader = new BufferedReader(new InputStreamReader(sis, getCharacterEncoding())); + return reader; + } + + public String getContentType() { + if (contentType == null) + return super.getContentType(); + return contentType; + } + + protected void setContentType(String contentType) { + this.contentType = contentType; + } + + public int getContentLength() { + if (sis == null) + return super.getContentLength(); + return contentLength; + } + + public void setCharacterEncoding(String encoding) throws UnsupportedEncodingException { + this.characterEncoding = encoding; + } + + public String getCharacterEncoding() { + if (characterEncoding == null) + return super.getCharacterEncoding(); + return characterEncoding; + } + +// public void setAttribute(String key, Object value) { +// attributes.put(key, value); +// } +// +// public Object getAttribute(String key) { +// Object value = attributes.get(key); +// if (value == null) +// value = super.getAttribute(key); +// return value; +// } +// +// public Enumeration getAttributeNames() { +// Vector v = new Vector(); +// for (Enumeration e = super.getAttributeNames(); e.hasMoreElements();) { +// v.add(e.nextElement()); +// } +// for (Iterator i = attributes.keySet().iterator(); i.hasNext();) { +// v.add(i.next()); +// } +// return v.elements(); +// } } + + private class CachingResponseWrapper extends HttpServletResponseWrapper { + + protected HttpServletResponse origResponse; + protected CachingServletOutputStream sos = null; + protected PrintWriter writer = null; + protected int status = HttpServletResponse.SC_OK; + + public CachingResponseWrapper(HttpServletResponse servletResponse) { + super(servletResponse); + origResponse = servletResponse; + } + + public PrintWriter getWriter() throws IOException { + if (sos != null) + throw new IOException("getWriter cannnot be called after getOutputStream"); + sos = new CachingServletOutputStream(); + if (writer == null) + writer = new PrintWriter(new OutputStreamWriter(sos, getCharacterEncoding())); + return writer; + } + + public ServletOutputStream getOutputStream() throws IOException { + if (writer != null) + throw new IOException("getOutputStream cannnot be called after getWriter"); + if (sos == null) + sos = new CachingServletOutputStream(); + return sos; + } + + public byte[] getData() { + return sos != null ? sos.getData() : null; + } + + public int getStatus() { + return status; + } + + public void setStatus(int i) { + this.status = i; + super.setStatus(i); + } + + public void setStatus(int i, String msg) { + this.status = i; + super.setStatus(i, msg); + } + + public void sendError(int i, String msg) throws IOException { + this.status = i; + super.sendError(i, msg); + } + + public void sendError(int i) throws IOException { + this.status = i; + super.sendError(i); + } + + public void setContentLength(int i) { + } + + public void flushBuffer() throws IOException { + } + } + + private class CachingServletOutputStream extends ServletOutputStream { + + protected ByteArrayOutputStream ostream = new ByteArrayOutputStream(512); + + protected byte[] getData() { + return ostream.toByteArray(); + } + + public void write(int b) throws IOException { + ostream.write(b); + } + + public void write(byte b[]) throws IOException { + ostream.write(b); + } + + public void write(byte b[], int off, int len) throws IOException { + ostream.write(b, off, len); + } + } + + private static class CachingServletInputStream extends ServletInputStream { + + protected ByteArrayInputStream istream; + + public CachingServletInputStream(byte[] data) { + if (data == null) + istream = new ByteArrayInputStream(new byte[0]); + else + istream = new ByteArrayInputStream(data); + } + + public int read() throws IOException { + return istream.read(); + } + + public int read(byte b[]) throws IOException { + return istream.read(b); + } + + public int read(byte b[], int off, int len) throws IOException { + return istream.read(b, off, len); + } + + public int available() throws IOException { + return istream.available(); + } + } } Modified: trunk/eXist/src/org/exist/storage/serializers/Serializer.java =================================================================== --- trunk/eXist/src/org/exist/storage/serializers/Serializer.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/storage/serializers/Serializer.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -359,7 +359,8 @@ } protected void setXQueryContext(XQueryContext context) { - xinclude.setXQueryContext(context); + if (context != null) + xinclude.setModuleLoadPath(context.getModuleLoadPath()); } public void parse(String systemId) throws IOException, SAXException { Modified: trunk/eXist/src/org/exist/storage/serializers/XIncludeFilter.java =================================================================== --- trunk/eXist/src/org/exist/storage/serializers/XIncludeFilter.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/storage/serializers/XIncludeFilter.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -103,7 +103,7 @@ private Receiver receiver; private Serializer serializer; private DocumentImpl document = null; - private XQueryContext context = null; + private String moduleLoadPath = null; private HashMap namespaces = new HashMap(10); @@ -134,8 +134,8 @@ this.error = null; } - public void setXQueryContext(XQueryContext context) { - this.context = context; + public void setModuleLoadPath(String path) { + this.moduleLoadPath = path; } /* (non-Javadoc) @@ -337,11 +337,11 @@ // we have to check if it is a relative path, and if yes, try to // interpret it relative to the moduleLoadPath property of the current // XQuery context. - if (scheme == null && context != null) { + if (scheme == null && moduleLoadPath != null) { String path = externalUri.getSchemeSpecificPart(); File f = new File(path); if (!f.isAbsolute()) { - f = new File(context.getModuleLoadPath() + '/' + path); + f = new File(moduleLoadPath + '/' + path); externalUri = f.toURI(); } } Added: trunk/eXist/src/org/exist/util/serializer/SAXToReceiver.java =================================================================== --- trunk/eXist/src/org/exist/util/serializer/SAXToReceiver.java (rev 0) +++ trunk/eXist/src/org/exist/util/serializer/SAXToReceiver.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -0,0 +1,135 @@ +/* + * eXist Open Source Native XML Database + * Copyright (C) 2001-07 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 library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * $Id$ + */ +package org.exist.util.serializer; + +import org.xml.sax.ext.LexicalHandler; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.Attributes; +import org.exist.dom.QName; +import org.exist.dom.AttrImpl; +import org.exist.util.XMLString; + +public class SAXToReceiver implements ContentHandler, LexicalHandler { + + private Receiver receiver; + private boolean inCDATASection = false; + + public SAXToReceiver(Receiver receiver) { + this.receiver = receiver; + } + + public void setDocumentLocator(Locator locator) { + } + + public void startDocument() throws SAXException { + receiver.startDocument(); + } + + public void endDocument() throws SAXException { + receiver.endDocument(); + } + + public void startPrefixMapping(String prefix, String uri) throws SAXException { + receiver.startPrefixMapping(prefix, uri); + } + + public void endPrefixMapping(String prefix) throws SAXException { + receiver.endPrefixMapping(prefix); + } + + public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { + String prefix = null; + int p = qName.indexOf(':'); + if (p > -1) + prefix = qName.substring(0, p - 1); + AttrList attrs = new AttrList(); + for (int i = 0; i < atts.getLength(); i++) { + if (atts.getQName(i).startsWith("xmlns")) + continue; + String attrPrefix = null; + p = atts.getQName(i).indexOf(':'); + if (p > -1) + attrPrefix = atts.getQName(i).substring(0, p - 1); + int type = AttrImpl.CDATA; + String atype = atts.getType(i); + if ("ID".equals(atype)) + type = AttrImpl.ID; + else if ("IDREF".equals(atype)) + type = AttrImpl.IDREF; + else if ("IDREFS".equals(atype)) + type = AttrImpl.IDREFS; + attrs.addAttribute(new QName(atts.getLocalName(i), atts.getURI(i), attrPrefix), atts.getValue(i), type); + } + receiver.startElement(new QName(localName, uri, prefix), attrs); + } + + public void endElement(String uri, String localName, String qName) throws SAXException { + String prefix = null; + int p = qName.indexOf(':'); + if (p > -1) + prefix = qName.substring(0, p - 1); + receiver.endElement(new QName(localName, uri, prefix)); + } + + public void characters(char[] ch, int start, int length) throws SAXException { + if (inCDATASection) + receiver.cdataSection(ch, start, length); + else + receiver.characters(new XMLString(ch, start, length)); + } + + public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + } + + public void processingInstruction(String target, String data) throws SAXException { + receiver.processingInstruction(target, data); + } + + public void skippedEntity(String name) throws SAXException { + } + + public void startDTD(String name, String publicId, String systemId) throws SAXException { + } + + public void endDTD() throws SAXException { + } + + public void startEntity(String name) throws SAXException { + } + + public void endEntity(String name) throws SAXException { + } + + public void startCDATA() throws SAXException { + inCDATASection = true; + } + + public void endCDATA() throws SAXException { + inCDATASection = false; + } + + public void comment(char[] ch, int start, int length) throws SAXException { + receiver.comment(ch, start, length); + } +} Modified: trunk/eXist/src/org/exist/xmldb/LocalResourceSet.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/LocalResourceSet.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/xmldb/LocalResourceSet.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -43,6 +43,7 @@ import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceIterator; import org.exist.xquery.value.Type; +import org.exist.xquery.value.ValueSequence; import org.w3c.dom.Node; import org.xml.sax.SAXException; import org.xml.sax.helpers.AttributesImpl; @@ -203,6 +204,19 @@ return res; } + public Sequence toSequence() { + if (resources.size() == 0) + return Sequence.EMPTY_SEQUENCE; + if (resources.size() == 1) + return ((Item) resources.get(0)).toSequence(); + ValueSequence s = new ValueSequence(); + for (int i = 0; i < resources.size(); i++) { + Item item = (Item) resources.get(i); + s.add(item); + } + return s; + } + /** * Gets the size attribute of the LocalResourceSet object * Modified: trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java 2008-12-05 20:32:12 UTC (rev 8371) +++ trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java 2008-12-07 16:27:13 UTC (rev 8372) @@ -209,7 +209,7 @@ serializer.setProperties(serializeOptions); if (expandXIncludes) { XIncludeFilter xinclude = new XIncludeFilter(serializer, receiver); - xinclude.setXQueryContext(context); + xinclude.setModuleLoadPath(context.getMo... [truncated message content] |
From: <di...@us...> - 2008-12-19 12:07:34
|
Revision: 8396 http://exist.svn.sourceforge.net/exist/?rev=8396&view=rev Author: dizzzz Date: 2008-12-19 11:36:50 +0000 (Fri, 19 Dec 2008) Log Message: ----------- [ignore] Added for all HTTP interfaces a catch(Throwable). In these cases now an stacktrace is actually logged and a ServletException is thrown. Modified Paths: -------------- trunk/eXist/src/org/exist/atom/http/AtomServlet.java trunk/eXist/src/org/exist/http/servlets/EXistServlet.java trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java trunk/eXist/src/org/exist/http/webdav/WebDAV.java trunk/eXist/src/org/exist/webstart/JnlpServlet.java trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java Modified: trunk/eXist/src/org/exist/atom/http/AtomServlet.java =================================================================== --- trunk/eXist/src/org/exist/atom/http/AtomServlet.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/atom/http/AtomServlet.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -443,25 +443,35 @@ try { broker = pool.get(user); module.process(broker,new HttpRequestMessage(request,path,'/'+moduleName),new HttpResponseMessage(response)); + } catch (NotFoundException ex) { LOG.info("Resource "+path+" not found by "+moduleName,ex); - response.sendError(404,ex.getMessage()); + response.sendError(HttpServletResponse.SC_NOT_FOUND,ex.getMessage()); + } catch (PermissionDeniedException ex) { LOG.info("Permission denied to "+path+" by "+moduleName+" for "+user.getName(),ex); - response.sendError(401,ex.getMessage()); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED,ex.getMessage()); + } catch (BadRequestException ex) { LOG.info("Bad request throw from module "+moduleName,ex); - response.sendError(400,ex.getMessage()); + response.sendError(HttpServletResponse.SC_BAD_REQUEST,ex.getMessage()); + } catch (EXistException ex) { LOG.fatal("Exception getting broker from pool for user "+user.getName(),ex); - response.sendError(500,"Service is not available."); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Service is not available."); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An error occurred: " + e.getMessage(), e); + } finally { pool.release(broker); } + } catch (IOException ex) { LOG.fatal("I/O exception on request.",ex); try { - response.sendError(500,"Service is not available."); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Service is not available."); } catch (IOException finalEx) { LOG.fatal("Cannot return 500 on exception.",ex); } Modified: trunk/eXist/src/org/exist/http/servlets/EXistServlet.java =================================================================== --- trunk/eXist/src/org/exist/http/servlets/EXistServlet.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/http/servlets/EXistServlet.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -196,34 +196,36 @@ DBBroker broker = null; File tempFile = null; try { - XmldbURI dbpath = XmldbURI.create(path); - broker = pool.get(user); - Collection collection = broker.getCollection(dbpath); - if (collection != null) { - response.sendError(400,"A PUT request is not allowed against a plain collection path."); - return; - } - //fourth, process the request - ServletInputStream is = request.getInputStream(); - int len = request.getContentLength(); - // put may send a lot of data, so save it - // to a temporary file first. - tempFile = File.createTempFile("existSRV", ".tmp"); - FileOutputStream fos = new FileOutputStream(tempFile); - BufferedOutputStream os = new BufferedOutputStream(fos); - byte[] buffer = new byte[4096]; - int count, l = 0; - do { - count = is.read(buffer); - if (count > 0) - os.write(buffer, 0, count); - l += count; - } while (l < len); - os.close(); - - srvREST.doPut(broker, tempFile, dbpath, request, response); + XmldbURI dbpath = XmldbURI.create(path); + broker = pool.get(user); + Collection collection = broker.getCollection(dbpath); + if (collection != null) { + response.sendError(400,"A PUT request is not allowed against a plain collection path."); + return; + } + //fourth, process the request + ServletInputStream is = request.getInputStream(); + int len = request.getContentLength(); + // put may send a lot of data, so save it + // to a temporary file first. + tempFile = File.createTempFile("existSRV", ".tmp"); + FileOutputStream fos = new FileOutputStream(tempFile); + BufferedOutputStream os = new BufferedOutputStream(fos); + byte[] buffer = new byte[4096]; + int count, l = 0; + do { + count = is.read(buffer); + if (count > 0) + os.write(buffer, 0, count); + l += count; + } while (l < len); + os.close(); + + srvREST.doPut(broker, tempFile, dbpath, request, response); + } catch (BadRequestException e) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } catch (PermissionDeniedException e) { //If the current user is the Default User and they do not have permission //then send a challenge request to prompt the client for a username/password. @@ -233,15 +235,21 @@ } else { response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); } + } catch (EXistException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An unknown error occurred: " + e.getMessage(), e); + } finally { - if (broker!=null) { - pool.release(broker); - } - if (tempFile!=null) { - tempFile.delete(); - } + if (broker!=null) { + pool.release(broker); + } + if (tempFile!=null) { + tempFile.delete(); + } } } @@ -309,8 +317,8 @@ srvREST.doGet(broker, request, response, path); } } catch (BadRequestException e) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST, e - .getMessage()); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } catch (PermissionDeniedException e) { //If the current user is the Default User and they do not have permission //then send a challenge request to prompt the client for a username/password. @@ -318,15 +326,20 @@ if (user.equals(defaultUser)) { authenticator.sendChallenge(request, response); } else { - response - .sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); + response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); } + } catch (NotFoundException e) { - response - .sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); + response.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); + } catch (EXistException e) { - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e - .getMessage()); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + e.getMessage()); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An error occurred: " + e.getMessage(), e); + } finally { pool.release(broker); } @@ -362,9 +375,10 @@ try { broker = pool.get(user); srvREST.doHead(broker, request, response, path); + } catch (BadRequestException e) { - response.sendError(HttpServletResponse.SC_BAD_REQUEST, e - .getMessage()); + response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } catch (PermissionDeniedException e) { //If the current user is the Default User and they do not have permission //then send a challenge request to prompt the client for a username/password. @@ -375,12 +389,18 @@ response .sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); } + } catch (NotFoundException e) { - response - .sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); + response.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); + } catch (EXistException e) { - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e - .getMessage()); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, + e.getMessage()); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An unknown error occurred: " + e.getMessage(), e); + } finally { pool.release(broker); } @@ -416,6 +436,7 @@ try { broker = pool.get(user); srvREST.doDelete(broker, XmldbURI.create(path), response); + } catch (PermissionDeniedException e) { //If the current user is the Default User and they do not have permission //then send a challenge request to prompt the client for a username/password. @@ -426,12 +447,17 @@ response .sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); } + } catch (NotFoundException e) { - response - .sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); + response.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); + } catch (EXistException e) { - response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e - .getMessage()); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage()); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An unknown error occurred: " + e.getMessage(), e); + } finally { pool.release(broker); } @@ -509,6 +535,7 @@ //REST Server srvREST.doPost(broker, request, response, path); } + } catch (PermissionDeniedException e) { //If the current user is the Default User and they do not have permission //then send a challenge request to prompt the client for a username/password. @@ -519,13 +546,21 @@ response .sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage()); } + } catch (EXistException e) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e .getMessage()); + } catch (BadRequestException e) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + } catch (NotFoundException e) { response.sendError(HttpServletResponse.SC_NOT_FOUND, e.getMessage()); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An unknown error occurred: " + e.getMessage(), e); + } finally { pool.release(broker); } Modified: trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java =================================================================== --- trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/http/servlets/XQueryServlet.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -374,11 +374,18 @@ output.println(res.getContent().toString()); } } + } catch (XMLDBException e) { LOG.debug(e); response.setStatus(HttpServletResponse.SC_BAD_REQUEST); sendError(output, e.getMessage(), e); + + } catch (Throwable e){ + LOG.error(e); + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + sendError(output, "Error", e.getMessage()); } + output.flush(); } Modified: trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java =================================================================== --- trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/http/servlets/XSLTServlet.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -166,10 +166,17 @@ } bufferedOutputStream.close(); response.flushBuffer(); + } catch (IOException e) { throw new ServletException("IO exception while transforming node: " + e.getMessage(), e); + } catch (TransformerException e) { throw new ServletException("Exception while transforming node: " + e.getMessage(), e); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An error occurred: " + e.getMessage(), e); + } finally { pool.release(broker); } Modified: trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java =================================================================== --- trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/http/urlrewrite/XQueryURLRewrite.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -23,7 +23,7 @@ package org.exist.http.urlrewrite; import org.apache.log4j.Logger; -import org.exist.source.FileSource; + import org.exist.source.Source; import org.exist.source.DBSource; import org.exist.source.SourceFactory; @@ -54,6 +54,7 @@ import org.exist.storage.serializers.Serializer; import org.exist.http.servlets.HttpRequestWrapper; import org.exist.http.servlets.HttpResponseWrapper; + import org.w3c.dom.Node; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -71,8 +72,8 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponseWrapper; + import java.io.IOException; -import java.io.File; import java.io.Writer; import java.io.OutputStreamWriter; import java.io.ByteArrayOutputStream; @@ -88,7 +89,6 @@ import java.util.Iterator; import java.util.Properties; import java.util.List; -import java.util.ArrayList; import java.util.LinkedList; import java.net.URISyntaxException; @@ -357,11 +357,22 @@ // writeResults(response, broker, result); // } } catch (EXistException e) { - throw new ServletException("An error occurred while retrieving query results: " + e.getMessage(), e); + LOG.error(e); + throw new ServletException("An error occurred while retrieving query results: " + + e.getMessage(), e); + } catch (XPathException e) { - throw new ServletException("An error occurred while executing the urlrewrite query: " + e.getMessage(), e); + LOG.error(e); + throw new ServletException("An error occurred while executing the urlrewrite query: " + + e.getMessage(), e); + // } catch (SAXException e) { // throw new ServletException("Error while serializing results: " + e.getMessage(), e); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An error occurred: " + + e.getMessage(), e); } } Modified: trunk/eXist/src/org/exist/http/webdav/WebDAV.java =================================================================== --- trunk/eXist/src/org/exist/http/webdav/WebDAV.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/http/webdav/WebDAV.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -153,6 +153,10 @@ } catch (URISyntaxException e) { response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage()); + + } catch (Throwable e){ + LOG.error(e); + throw new ServletException("An error occurred: " + e.getMessage(), e); } finally { // for debugging webdav Modified: trunk/eXist/src/org/exist/webstart/JnlpServlet.java =================================================================== --- trunk/eXist/src/org/exist/webstart/JnlpServlet.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/webstart/JnlpServlet.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -75,27 +75,33 @@ */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{ - - JnlpWriter jw=new JnlpWriter(); - - String URI = request.getRequestURI(); - logger.debug("Requested URI="+URI); - - if(URI.endsWith(".jnlp")){ - jw.writeJnlpXML(jf, request, response); + + try { + JnlpWriter jw=new JnlpWriter(); + + String URI = request.getRequestURI(); + logger.debug("Requested URI="+URI); + + if(URI.endsWith(".jnlp")){ + jw.writeJnlpXML(jf, request, response); + + } else if (URI.endsWith(".jar")){ + String filename = stripFilename( request.getPathInfo() ); + jw.sendJar(jf, filename, request, response); + + } else if ( URI.endsWith(".gif") || URI.endsWith(".jpg") ){ + String filename = stripFilename( request.getPathInfo() ); + jw.sendImage(jh, jf, filename, response); + + } else { + logger.error("Invalid filename extension."); + response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid filename extension."); + return; + } - } else if (URI.endsWith(".jar")){ - String filename = stripFilename( request.getPathInfo() ); - jw.sendJar(jf, filename, request, response); - - } else if ( URI.endsWith(".gif") || URI.endsWith(".jpg") ){ - String filename = stripFilename( request.getPathInfo() ); - jw.sendImage(jh, jf, filename, response); - - } else { - logger.error("Invalid filename extension."); - response.sendError(HttpServletResponse.SC_FORBIDDEN, "Invalid filename extension."); - return; + } catch (Throwable e){ + logger.error(e); + throw new ServletException("An error occurred: " + e.getMessage(), e); } } Modified: trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java 2008-12-19 09:56:24 UTC (rev 8395) +++ trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java 2008-12-19 11:36:50 UTC (rev 8396) @@ -53,7 +53,12 @@ descriptor.doLogRequestInReplayLog(request); } - super.doPost(request, response); + try { + super.doPost(request, response); + } catch (Throwable e){ + log("Problem during XmlRpc execution", e); + throw new ServletException("An unknown error occurred: " + e.getMessage(), e); + } } protected XmlRpcHandlerMapping newXmlRpcHandlerMapping() throws XmlRpcException { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pka...@us...> - 2008-12-19 19:27:14
|
Revision: 8399 http://exist.svn.sourceforge.net/exist/?rev=8399&view=rev Author: pkaminsk2 Date: 2008-12-19 19:27:09 +0000 (Fri, 19 Dec 2008) Log Message: ----------- Factored out the common parts of NodeProxy and StoredNode into a new NodeHandle interface to get rid of some code duplication. Modified Paths: -------------- trunk/eXist/src/org/exist/dom/NodeProxy.java trunk/eXist/src/org/exist/dom/StoredNode.java trunk/eXist/src/org/exist/stax/EmbeddedXMLStreamReader.java trunk/eXist/src/org/exist/storage/DBBroker.java trunk/eXist/src/org/exist/storage/NativeBroker.java trunk/eXist/src/org/exist/storage/dom/RawNodeIterator.java Added Paths: ----------- trunk/eXist/src/org/exist/dom/NodeHandle.java Added: trunk/eXist/src/org/exist/dom/NodeHandle.java =================================================================== --- trunk/eXist/src/org/exist/dom/NodeHandle.java (rev 0) +++ trunk/eXist/src/org/exist/dom/NodeHandle.java 2008-12-19 19:27:09 UTC (rev 8399) @@ -0,0 +1,22 @@ +package org.exist.dom; + +import org.exist.numbering.NodeId; +import org.w3c.dom.Document; + +public interface NodeHandle { + + public NodeId getNodeId(); + + public void setNodeId(NodeId dln); + + public long getInternalAddress(); + + public void setInternalAddress(long internalAddress); + + public short getNodeType(); + + public Document getOwnerDocument(); + + public DocumentImpl getDocument(); + +} \ No newline at end of file Property changes on: trunk/eXist/src/org/exist/dom/NodeHandle.java ___________________________________________________________________ Added: svn:mime-type + text/plain Modified: trunk/eXist/src/org/exist/dom/NodeProxy.java =================================================================== --- trunk/eXist/src/org/exist/dom/NodeProxy.java 2008-12-19 12:56:40 UTC (rev 8398) +++ trunk/eXist/src/org/exist/dom/NodeProxy.java 2008-12-19 19:27:09 UTC (rev 8399) @@ -76,7 +76,7 @@ * *@author Wolfgang Meier <wol...@ex...> */ -public class NodeProxy implements NodeSet, NodeValue, DocumentSet, Comparable { +public class NodeProxy implements NodeSet, NodeValue, NodeHandle, DocumentSet, Comparable { /* * Special values for nodes gid : @@ -169,21 +169,14 @@ /** * Creates a new <code>NodeProxy</code> instance. * - * @param p a <code>NodeProxy</code> value - */ - public NodeProxy(NodeProxy p) { - this(p.doc, p.nodeId, p.nodeType, p.internalAddress); - match = p.match; - //TODO : what about node's context ? - } - - /** - * Creates a new <code>NodeProxy</code> instance. - * * @param n a <code>StoredNode</code> value */ - public NodeProxy(StoredNode n) { - this((DocumentImpl)n.getOwnerDocument(), n.getNodeId(), n.getNodeType(), n.getInternalAddress()); + public NodeProxy(NodeHandle n) { + this(n.getDocument(), n.getNodeId(), n.getNodeType(), n.getInternalAddress()); + if (n instanceof NodeProxy) { + this.match = ((NodeProxy) n).match; + //TODO : what about node's context ? + } } /** Modified: trunk/eXist/src/org/exist/dom/StoredNode.java =================================================================== --- trunk/eXist/src/org/exist/dom/StoredNode.java 2008-12-19 12:56:40 UTC (rev 8398) +++ trunk/eXist/src/org/exist/dom/StoredNode.java 2008-12-19 19:27:09 UTC (rev 8399) @@ -42,7 +42,7 @@ * *@author Wolfgang Meier <me...@if...> */ -public class StoredNode extends NodeImpl implements Visitable { +public class StoredNode extends NodeImpl implements Visitable, NodeHandle { public final static int LENGTH_SIGNATURE_LENGTH = 1; //sizeof byte public final static long UNKNOWN_NODE_IMPL_ADDRESS = -1; Modified: trunk/eXist/src/org/exist/stax/EmbeddedXMLStreamReader.java =================================================================== --- trunk/eXist/src/org/exist/stax/EmbeddedXMLStreamReader.java 2008-12-19 12:56:40 UTC (rev 8398) +++ trunk/eXist/src/org/exist/stax/EmbeddedXMLStreamReader.java 2008-12-19 19:27:09 UTC (rev 8399) @@ -22,12 +22,7 @@ package org.exist.stax; import org.apache.log4j.Logger; -import org.exist.dom.AttrImpl; -import org.exist.dom.CharacterDataImpl; -import org.exist.dom.DocumentImpl; -import org.exist.dom.ElementImpl; -import org.exist.dom.NodeProxy; -import org.exist.dom.StoredNode; +import org.exist.dom.*; import org.exist.numbering.NodeId; import org.exist.storage.DBBroker; import org.exist.storage.Signatures; @@ -76,8 +71,7 @@ private NodeId nodeId; - private NodeProxy originProxy; - private StoredNode originNode; + private NodeHandle origin; private QName qname = null; @@ -97,21 +91,18 @@ * * @param doc the document to which the start node belongs. * @param iterator a RawNodeIterator positioned on the start node. - * @param originNode an optional StoredNode whose nodeId should match the first node in the stream - * (or null if no need to check); at most one of originNode and originProxy should be set - * @param originProxy an optional NodeProxy whose nodeId should match the first node in the stream - * (or null if no need to check); at most one of originNode and originProxy should be set + * @param origin an optional NodeHandle whose nodeId should match the first node in the stream + * (or null if no need to check) * @param reportAttributes if set to true, attributes will be reported as top-level events. * @throws XMLStreamException */ - public EmbeddedXMLStreamReader(DBBroker broker, DocumentImpl doc, RawNodeIterator iterator, StoredNode originNode, NodeProxy originProxy, boolean reportAttributes) + public EmbeddedXMLStreamReader(DBBroker broker, DocumentImpl doc, RawNodeIterator iterator, NodeHandle origin, boolean reportAttributes) throws XMLStreamException { this.broker = broker; this.document = doc; this.iterator = iterator; this.reportAttribs = reportAttributes; - this.originProxy = originProxy; - this.originNode = originNode; + this.origin = origin; } /** @@ -121,7 +112,7 @@ * @param reportAttributes if set to true, attributes will be reported as top-level events. * @throws IOException */ - public void reposition(DBBroker broker, StoredNode node, boolean reportAttributes) throws IOException { + public void reposition(DBBroker broker, NodeHandle node, boolean reportAttributes) throws IOException { this.broker = broker; // Seeking to a node with unknown address will reuse this reader, so do it before setting all // the fields otherwise they could get overwritten. @@ -133,33 +124,9 @@ this.state = START_DOCUMENT; this.reportAttribs = reportAttributes; this.document = (DocumentImpl) node.getOwnerDocument(); - this.originProxy = null; - this.originNode = node; + this.origin = node; } - /** - * Reposition the stream reader to another start node, maybe in a different document. - * - * @param proxy the new start node. - * @param reportAttributes if set to true, attributes will be reported as top-level events. - * @throws IOException - */ - public void reposition(DBBroker broker, NodeProxy proxy, boolean reportAttributes) throws IOException { - this.broker = broker; - // Seeking to a proxy with unknown address will reuse this reader, so do it before setting all - // the fields otherwise they could get overwritten. - iterator.seek(proxy); - reset(); - this.current = null; - this.previous = null; - this.elementStack.clear(); - this.state = START_DOCUMENT; - this.reportAttribs = reportAttributes; - this.document = (DocumentImpl) proxy.getOwnerDocument(); - this.originProxy = proxy; - this.originNode = null; - } - public short getNodeType() { return Signatures.getType(current.data()[current.start()]); } @@ -246,32 +213,22 @@ boolean first = state == START_DOCUMENT; current = iterator.next(); initNode(); - if (first && (originProxy != null || originNode != null)) { + if (first && origin != null) { verifyOriginNodeId(); - originProxy = null; - originNode = null; + origin = null; } return state; } private void verifyOriginNodeId() throws XMLStreamException { - NodeId desiredId = originNode != null ? originNode.getNodeId() : originProxy.getNodeId(); - if (!nodeId.equals(desiredId)) { + if (!nodeId.equals(origin.getNodeId())) { // Node got moved, we had the wrong address. Resync iterator by nodeid. - LOG.warn("expected node id " + desiredId + ", got " + nodeId + "; resyncing address"); - if (originNode != null) { - originNode.setInternalAddress(StoredNode.UNKNOWN_NODE_IMPL_ADDRESS); - } else { - originProxy.setInternalAddress(StoredNode.UNKNOWN_NODE_IMPL_ADDRESS); - } + LOG.warn("expected node id " + origin.getNodeId() + ", got " + nodeId + "; resyncing address"); + origin.setInternalAddress(StoredNode.UNKNOWN_NODE_IMPL_ADDRESS); boolean reportAttribsBackup = reportAttribs; DocumentImpl documentBackup = document; try { - if (originNode != null) { - iterator.seek(originNode); - } else { - iterator.seek(originProxy); - } + iterator.seek(origin); } catch (IOException e) { throw new XMLStreamException(e); } @@ -283,11 +240,7 @@ document = documentBackup; current = iterator.next(); initNode(); - if (originNode != null) { - originNode.setInternalAddress(iterator.currentAddress()); - } else { - originProxy.setInternalAddress(iterator.currentAddress()); - } + origin.setInternalAddress(iterator.currentAddress()); } } Modified: trunk/eXist/src/org/exist/storage/DBBroker.java =================================================================== --- trunk/eXist/src/org/exist/storage/DBBroker.java 2008-12-19 12:56:40 UTC (rev 8398) +++ trunk/eXist/src/org/exist/storage/DBBroker.java 2008-12-19 19:27:09 UTC (rev 8399) @@ -26,11 +26,7 @@ import org.exist.EXistException; import org.exist.backup.RawDataBackup; import org.exist.collections.Collection; -import org.exist.dom.BinaryDocument; -import org.exist.dom.DocumentImpl; -import org.exist.dom.MutableDocumentSet; -import org.exist.dom.NodeProxy; -import org.exist.dom.StoredNode; +import org.exist.dom.*; import org.exist.indexing.IndexController; import org.exist.indexing.StreamListener; import org.exist.numbering.NodeId; @@ -764,11 +760,8 @@ return id; } - public abstract EmbeddedXMLStreamReader getXMLStreamReader(StoredNode node, boolean reportAttributes) + public abstract EmbeddedXMLStreamReader getXMLStreamReader(NodeHandle node, boolean reportAttributes) throws IOException, XMLStreamException; - public abstract EmbeddedXMLStreamReader getXMLStreamReader(NodeProxy node, boolean reportAttributes) - throws IOException, XMLStreamException; - public abstract void backupToArchive(RawDataBackup backup) throws IOException; } Modified: trunk/eXist/src/org/exist/storage/NativeBroker.java =================================================================== --- trunk/eXist/src/org/exist/storage/NativeBroker.java 2008-12-19 12:56:40 UTC (rev 8398) +++ trunk/eXist/src/org/exist/storage/NativeBroker.java 2008-12-19 19:27:09 UTC (rev 8399) @@ -28,17 +28,7 @@ import org.exist.collections.CollectionCache; import org.exist.collections.CollectionConfiguration; import org.exist.collections.triggers.TriggerException; -import org.exist.dom.AttrImpl; -import org.exist.dom.BinaryDocument; -import org.exist.dom.DefaultDocumentSet; -import org.exist.dom.DocumentImpl; -import org.exist.dom.DocumentMetadata; -import org.exist.dom.ElementImpl; -import org.exist.dom.MutableDocumentSet; -import org.exist.dom.NodeProxy; -import org.exist.dom.QName; -import org.exist.dom.StoredNode; -import org.exist.dom.TextImpl; +import org.exist.dom.*; import org.exist.fulltext.FTIndex; import org.exist.fulltext.FTIndexWorker; import org.exist.indexing.StreamListener; @@ -82,7 +72,6 @@ import org.exist.util.DatabaseConfigurationException; import org.exist.util.LockException; import org.exist.util.ReadOnlyException; -import org.exist.util.sanity.SanityCheck; import org.exist.xmldb.XmldbURI; import org.exist.xquery.*; import org.exist.xquery.value.*; @@ -520,28 +509,17 @@ return worker.getEngine(); } - public EmbeddedXMLStreamReader getXMLStreamReader(StoredNode node, boolean reportAttributes) + public EmbeddedXMLStreamReader getXMLStreamReader(NodeHandle node, boolean reportAttributes) throws IOException, XMLStreamException { if (streamReader == null) { RawNodeIterator iterator = new RawNodeIterator(this, domDb, node); - streamReader = new EmbeddedXMLStreamReader(this, (DocumentImpl) node.getOwnerDocument(), iterator, node, null, reportAttributes); + streamReader = new EmbeddedXMLStreamReader(this, (DocumentImpl) node.getOwnerDocument(), iterator, node, reportAttributes); } else { streamReader.reposition(this, node, reportAttributes); } return streamReader; } - public EmbeddedXMLStreamReader getXMLStreamReader(NodeProxy proxy, boolean reportAttributes) - throws IOException, XMLStreamException { - if (streamReader == null) { - RawNodeIterator iterator = new RawNodeIterator(this, domDb, proxy); - streamReader = new EmbeddedXMLStreamReader(this, (DocumentImpl) proxy.getOwnerDocument(), iterator, null, proxy, reportAttributes); - } else { - streamReader.reposition(this, proxy, reportAttributes); - } - return streamReader; - } - public Iterator getNodeIterator(StoredNode node) { if (node == null) throw new IllegalArgumentException("The node parameter cannot be null."); Modified: trunk/eXist/src/org/exist/storage/dom/RawNodeIterator.java =================================================================== --- trunk/eXist/src/org/exist/storage/dom/RawNodeIterator.java 2008-12-19 12:56:40 UTC (rev 8398) +++ trunk/eXist/src/org/exist/storage/dom/RawNodeIterator.java 2008-12-19 19:27:09 UTC (rev 8399) @@ -22,6 +22,7 @@ package org.exist.storage.dom; import org.apache.log4j.Logger; +import org.exist.dom.NodeHandle; import org.exist.dom.NodeProxy; import org.exist.dom.StoredNode; import org.exist.storage.DBBroker; @@ -63,34 +64,19 @@ * @param node the start node where the iterator will be positioned. * @throws IOException */ - public RawNodeIterator(DBBroker broker, DOMFile db, StoredNode node) throws IOException { + public RawNodeIterator(DBBroker broker, DOMFile db, NodeHandle node) throws IOException { this.db = db; this.broker = broker; seek(node); } /** - * Construct the iterator. The iterator will be positioned before the specified - * start node. - * - * @param broker the owner object used to acquire a lock on the underlying data file (usually a DBBroker) - * @param db the underlying data file - * @param proxy the start node where the iterator will be positioned. - * @throws IOException - */ - public RawNodeIterator(DBBroker broker, DOMFile db, NodeProxy proxy) throws IOException { - this.db = db; - this.broker = broker; - seek(proxy); - } - - /** * Reposition the iterator to the start of the specified node. * * @param node the start node where the iterator will be positioned. * @throws IOException */ - public void seek(StoredNode node) throws IOException { + public void seek(NodeHandle node) throws IOException { Lock lock = db.getLock(); try { lock.acquire(Lock.READ_LOCK); @@ -119,40 +105,6 @@ } /** - * Reposition the iterator to the start of the specified node. - * - * @param proxy the start node where the iterator will be positioned. - * @throws IOException - */ - public void seek(NodeProxy proxy) throws IOException { - Lock lock = db.getLock(); - try { - lock.acquire(Lock.READ_LOCK); - RecordPos rec = null; - if (proxy.getInternalAddress() != StoredNode.UNKNOWN_NODE_IMPL_ADDRESS) - rec = db.findRecord(proxy.getInternalAddress()); - if (rec == null) { - try { - long addr = db.findValue(broker, proxy); - if (addr == BTree.KEY_NOT_FOUND) - throw new IOException("Node not found."); - rec = db.findRecord(addr); - } catch (BTreeException e) { - throw new IOException("Node not found: " + e.getMessage()); - } - } - page = rec.getPage().getPageNum(); - //Position the stream at the very beginning of the record - offset = rec.offset - DOMFile.LENGTH_TID; - p = rec.getPage(); - } catch (LockException e) { - throw new IOException("Exception while scanning document: " + e.getMessage()); - } finally { - lock.release(Lock.READ_LOCK); - } - } - - /** * Returns the raw data of the next node in document order. * @return the raw data of the node */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pka...@us...> - 2008-12-26 00:59:12
|
Revision: 8417 http://exist.svn.sourceforge.net/exist/?rev=8417&view=rev Author: pkaminsk2 Date: 2008-12-26 00:59:09 +0000 (Fri, 26 Dec 2008) Log Message: ----------- Performance: External modules (i.e., ones defined in XQuery) are now cached in the XQueryPool, and can be shared across cached queries. This greatly improves performance if many queries are importing the same module since the module only has to be compiled once. The code is a little hairy, but the unit tests and XQTS are no worse off than before (and the module tests in XQTS seem to be running a lot faster). Performance: Took out eager initialization of the calendar and time zone in the query context, since getting the calendar is surprisingly slow. They'll be initialized lazily on demand. This could make a slight difference in long-running queries that don't try to get the current time until later, but is spec-compliant. Modified Paths: -------------- trunk/eXist/src/org/exist/storage/XQueryPool.java trunk/eXist/src/org/exist/xquery/CompiledXQuery.java trunk/eXist/src/org/exist/xquery/ExternalModule.java trunk/eXist/src/org/exist/xquery/ExternalModuleImpl.java trunk/eXist/src/org/exist/xquery/InternalFunctionCall.java trunk/eXist/src/org/exist/xquery/ModuleContext.java trunk/eXist/src/org/exist/xquery/PathExpr.java trunk/eXist/src/org/exist/xquery/XQueryContext.java Modified: trunk/eXist/src/org/exist/storage/XQueryPool.java =================================================================== --- trunk/eXist/src/org/exist/storage/XQueryPool.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/storage/XQueryPool.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -23,15 +23,13 @@ package org.exist.storage; import java.text.NumberFormat; -import java.util.Iterator; -import java.util.Stack; +import java.util.*; import org.apache.log4j.Logger; import org.exist.source.Source; import org.exist.util.Configuration; import org.exist.util.hashtable.Object2ObjectHashMap; -import org.exist.xquery.CompiledXQuery; -import org.exist.xquery.XQueryContext; +import org.exist.xquery.*; /** * Global pool for pre-compiled XQuery expressions. Expressions are @@ -117,8 +115,28 @@ } - public synchronized void returnCompiledXQuery(Source source, - CompiledXQuery xquery) { + public void returnCompiledXQuery(Source source, CompiledXQuery xquery) { + returnModules(xquery.getContext(), null); + returnObject(source, xquery); + } + + private void returnModules(XQueryContext context, ExternalModule self) { + for (Iterator it = context.getModules(); it.hasNext(); ) { + Module module = (Module) it.next(); + if (module != self && !module.isInternalModule()) { + ExternalModule extModule = (ExternalModule) module; + returnModule(extModule.getSource(), extModule); + } + } + } + + public void returnModule(Source source, ExternalModule module) { + returnModules(module.getContext(), module); + returnObject(source, module); + } + + private synchronized void returnObject(Source source, Object o) { + if (size() >= maxPoolSize) timeoutCheck(); if (size() < maxPoolSize) { Stack stack = (Stack) get(source); if (stack == null) { @@ -127,44 +145,89 @@ put(source, stack); } if (stack.size() < maxStackSize) { - stack.push(xquery); + stack.push(o); } } - timeoutCheck(); } + + private synchronized Object borrowObject(DBBroker broker, Source source) { + int idx = getIndex(source); + if (idx < 0) { + return null; + } + Source key = (Source) keys[idx]; + int validity = key.isValid(broker); + if (validity == Source.UNKNOWN) + validity = key.isValid(source); + if (validity == Source.INVALID || validity == Source.UNKNOWN) { + keys[idx] = REMOVED; + values[idx] = null; + LOG.debug(source.getKey() + " is invalid"); + return null; + } + Stack stack = (Stack) values[idx]; + if (stack == null || stack.isEmpty()) return null; + return stack.pop(); + } public synchronized CompiledXQuery borrowCompiledXQuery(DBBroker broker, Source source) { - int idx = getIndex(source); - if (idx < 0) { - return null; - } - Source key = (Source) keys[idx]; - int validity = key.isValid(broker); - if (validity == Source.UNKNOWN) - validity = key.isValid(source); - if (validity == Source.INVALID || validity == Source.UNKNOWN) { - keys[idx] = REMOVED; - values[idx] = null; - LOG.debug(source.getKey() + " is invalid"); - return null; - } - Stack stack = (Stack) values[idx]; - if (stack != null && !stack.isEmpty()) { - // now check if the compiled expression is valid - // it might become invalid if an imported module has changed. - CompiledXQuery query = (CompiledXQuery) stack.pop(); - XQueryContext context = query.getContext(); - context.setBroker(broker); - if (!query.isValid()) { - // the compiled query is no longer valid: one of the imported - // modules may have changed - remove(key); - return null; - } else - return query; - } - return null; + CompiledXQuery query = (CompiledXQuery) borrowObject(broker, source); + if (query == null) return null; + // now check if the compiled expression is valid + // it might become invalid if an imported module has changed. + XQueryContext context = query.getContext(); + context.setBroker(broker); + if (!borrowModules(broker, context, null)) { + // the compiled query is no longer valid: one of the imported + // modules may have changed + remove(source); + return null; + } else { + return query; + } } + + private synchronized boolean borrowModules(DBBroker broker, XQueryContext context, ExternalModule self) { + Map borrowedModules = new TreeMap(); + for (Iterator it = context.getModules(); it.hasNext(); ) { + Module module = (Module) it.next(); + if (module != self && !module.isInternalModule()) { + ExternalModule extModule = (ExternalModule) module; + ExternalModule borrowedModule = borrowModule(broker, extModule.getSource()); + if (borrowedModule == null) { + for (Iterator it2 = borrowedModules.values().iterator(); it2.hasNext(); ) { + ExternalModule moduleToReturn = (ExternalModule) it2.next(); + returnModule(moduleToReturn.getSource(), moduleToReturn); + } + return false; + } + borrowedModules.put(extModule.getNamespaceURI(), borrowedModule); + } + } + for (Iterator it = borrowedModules.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = (Map.Entry) it.next(); + context.setModule((String) entry.getKey(), (ExternalModule) entry.getValue()); + } + return true; + } + + public synchronized ExternalModule borrowModule(DBBroker broker, Source source) { + ExternalModule module = (ExternalModule) borrowObject(broker, source); + if (module == null) return null; + XQueryContext context = module.getContext(); + context.setBroker(broker); + if (!module.moduleIsValid()) { + LOG.debug("Module with URI " + module.getNamespaceURI() + + " has changed and needs to be reloaded"); + // fall through + } else if (!borrowModules(broker, context, module)) { + // fall through + } else { + return module; + } + remove(source); + return null; + } private void timeoutCheck() { final long currentTime = System.currentTimeMillis(); Modified: trunk/eXist/src/org/exist/xquery/CompiledXQuery.java =================================================================== --- trunk/eXist/src/org/exist/xquery/CompiledXQuery.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/xquery/CompiledXQuery.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -57,12 +57,6 @@ public Sequence eval(Sequence contextSequence) throws XPathException; /** - * Is the compiled expression still valid? Returns false if, for example, - * the source code of one of the imported modules has changed. - */ - public boolean isValid(); - - /** * Writes a diagnostic dump of the expression structure to the * specified writer. */ Modified: trunk/eXist/src/org/exist/xquery/ExternalModule.java =================================================================== --- trunk/eXist/src/org/exist/xquery/ExternalModule.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/xquery/ExternalModule.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -67,6 +67,8 @@ */ public void setSource(Source source); + public XQueryContext getContext(); + /** * Set the XQueryContext of this module. This will be a sub-context * of the main context as parts of the static context are shared. Modified: trunk/eXist/src/org/exist/xquery/ExternalModuleImpl.java =================================================================== --- trunk/eXist/src/org/exist/xquery/ExternalModuleImpl.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/xquery/ExternalModuleImpl.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -173,14 +173,15 @@ mContext = context; } + public XQueryContext getContext() { + return mContext; + } + /* (non-Javadoc) * @see org.exist.xquery.ExternalModule#moduleIsValid() */ public boolean moduleIsValid() { - if(mSource.isValid(mContext.getBroker()) != Source.VALID) - return false; - // check other modules imported from here - return mContext.checkModulesValid(); + return mSource.isValid(mContext.getBroker()) == Source.VALID; } public void reset(XQueryContext xqueryContext) { Modified: trunk/eXist/src/org/exist/xquery/InternalFunctionCall.java =================================================================== --- trunk/eXist/src/org/exist/xquery/InternalFunctionCall.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/xquery/InternalFunctionCall.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -171,10 +171,6 @@ { return function.isCalledAs(localName); } - public boolean isValid() - { - return function.isValid(); - } public void replaceLastExpression(Expression s) { function.replaceLastExpression(s); Modified: trunk/eXist/src/org/exist/xquery/ModuleContext.java =================================================================== --- trunk/eXist/src/org/exist/xquery/ModuleContext.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/xquery/ModuleContext.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -43,7 +43,6 @@ private XQueryContext parentContext; private String modulePrefix; private String moduleNamespace; - private boolean initializing = true; /** * @param parentContext @@ -52,13 +51,16 @@ super(parentContext.getAccessContext()); this.moduleNamespace = moduleNamespace; this.modulePrefix = modulePrefix; - this.parentContext = parentContext; + setParentContext(parentContext); + loadDefaults(broker.getConfiguration()); + } + + void setParentContext(XQueryContext parentContext) { + this.parentContext = parentContext; this.broker = parentContext.broker; baseURI = parentContext.baseURI; moduleLoadPath = parentContext.moduleLoadPath; - loadDefaults(broker.getConfiguration()); - initializing = false; - } + } public boolean hasParent() { return true; Modified: trunk/eXist/src/org/exist/xquery/PathExpr.java =================================================================== --- trunk/eXist/src/org/exist/xquery/PathExpr.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/xquery/PathExpr.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -455,13 +455,6 @@ public void reset() { resetState(false); } - - /* (non-Javadoc) - * @see org.exist.xquery.CompiledXQuery#isValid() - */ - public boolean isValid() { - return context.checkModulesValid(); - } /* (non-Javadoc) * @see org.exist.xquery.CompiledXQuery#dump(java.io.Writer) Modified: trunk/eXist/src/org/exist/xquery/XQueryContext.java =================================================================== --- trunk/eXist/src/org/exist/xquery/XQueryContext.java 2008-12-24 05:50:43 UTC (rev 8416) +++ trunk/eXist/src/org/exist/xquery/XQueryContext.java 2008-12-26 00:59:09 UTC (rev 8417) @@ -477,19 +477,6 @@ //Reset current context position setContextPosition(0); //Note that, for some reasons, an XQueryContext might be used without calling this method - try { - if (calendar == null) { - //Initialize to current dateTime - calendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()); - } - } catch (DatatypeConfigurationException e) { - LOG.error(e.getMessage(), e); - } - if (implicitTimeZone == null) { - implicitTimeZone = TimeZone.getDefault(); - if (implicitTimeZone.inDaylightTime(new Date())) - implicitTimeZone.setRawOffset(implicitTimeZone.getRawOffset() + implicitTimeZone.getDSTSavings()); - } } public AccessContext getAccessContext() { @@ -1257,24 +1244,12 @@ public Module getModule(String namespaceURI) { return (Module) modules.get(namespaceURI); } - - /** - * For compiled expressions: check if the source of any - * module imported by the current query has changed since - * compilation. - */ - public boolean checkModulesValid() { - for(Iterator i = modules.values().iterator(); i.hasNext(); ) { - Module module = (Module)i.next(); - if(!module.isInternalModule()) { - if(!((ExternalModule)module).moduleIsValid()) { - LOG.debug("Module with URI " + module.getNamespaceURI() + - " has changed and needs to be reloaded"); - return false; - } - } + + public void setModule(String namespaceURI, Module module) { + modules.put(namespaceURI, module); + if (!module.isInternalModule()) { + ((ModuleContext) ((ExternalModule) module).getContext()).setParentContext(this); } - return true; } /** @@ -2024,7 +1999,8 @@ throw new XPathException("source for module " + location + " is not an XQuery or " + "declares a wrong mime-type"); source = new DBSource(broker, (BinaryDocument) sourceDoc, true); - module = compileModule(prefix, namespaceURI, location, module, source); + // we don't know if the module will get returned, oh well + module = compileOrBorrowModule(prefix, namespaceURI, location, source); } catch (PermissionDeniedException e) { throw new XPathException("permission denied to read module source from " + location); } finally { @@ -2049,7 +2025,8 @@ throw new XPathException("Permission denied to access module '" + namespaceURI + "' at '" + location + "': " + e.getMessage()); } - module = compileModule(prefix, namespaceURI, location, module, source); + // we don't know if the module will get returned, oh well + module = compileOrBorrowModule(prefix, namespaceURI, location, source); } } } @@ -2057,6 +2034,14 @@ prefix = module.getDefaultPrefix(); declareNamespace(prefix, namespaceURI); } + + private ExternalModule compileOrBorrowModule(String prefix, String namespaceURI, String location, Source source) throws XPathException { + ExternalModule module = broker.getBrokerPool().getXQueryPool().borrowModule(broker, source); + if (module == null) module = compileModule(prefix, namespaceURI, location, source); + modules.put(module.getNamespaceURI(), module); + declareModuleVars(module); + return module; + } /** * @param namespaceURI @@ -2066,7 +2051,7 @@ * @return The compiled module. * @throws XPathException */ - private Module compileModule(String prefix, String namespaceURI, String location, Module module, Source source) throws XPathException { + private ExternalModule compileModule(String prefix, String namespaceURI, String location, Source source) throws XPathException { LOG.debug("Loading module from " + location); Reader reader; @@ -2104,10 +2089,9 @@ if(!modExternal.getNamespaceURI().equals(namespaceURI)) throw new XPathException("namespace URI declared by module (" + modExternal.getNamespaceURI() + ") does not match namespace URI in import statement, which was: " + namespaceURI); - modules.put(modExternal.getNamespaceURI(), modExternal); modExternal.setSource(source); modExternal.setContext(modContext); - module = modExternal; + return modExternal; } catch (RecognitionException e) { throw new XPathException( "error found while loading module from " + location + ": " + e.getMessage(), @@ -2128,8 +2112,6 @@ LOG.warn("Error while closing module source: " + e.getMessage(), e); } } - declareModuleVars(module); - return module; } private void declareModuleVars(Module module) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <br...@us...> - 2009-01-03 20:55:28
|
Revision: 8468 http://exist.svn.sourceforge.net/exist/?rev=8468&view=rev Author: brihaye Date: 2009-01-03 20:55:26 +0000 (Sat, 03 Jan 2009) Log Message: ----------- [ignore] refactored imports Modified Paths: -------------- trunk/eXist/src/org/exist/indexing/Index.java trunk/eXist/src/org/exist/xquery/functions/FunNamespaceURIForPrefix.java trunk/eXist/src/org/exist/xquery/functions/request/GetExists.java trunk/eXist/src/org/exist/xquery/functions/response/GetExists.java trunk/eXist/src/org/exist/xquery/functions/response/SetStatusCode.java trunk/eXist/src/org/exist/xquery/functions/session/GetExists.java trunk/eXist/src/org/exist/xquery/functions/session/SetAttribute.java trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java trunk/eXist/src/org/exist/xquery/functions/util/ExtractDocs.java trunk/eXist/src/org/exist/xquery/functions/util/Hash.java Modified: trunk/eXist/src/org/exist/indexing/Index.java =================================================================== --- trunk/eXist/src/org/exist/indexing/Index.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/indexing/Index.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -25,7 +25,6 @@ import org.exist.storage.DBBroker; import org.exist.storage.btree.DBException; import org.exist.util.DatabaseConfigurationException; -import org.exist.backup.RawDataBackup; import org.w3c.dom.Element; /** Modified: trunk/eXist/src/org/exist/xquery/functions/FunNamespaceURIForPrefix.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/FunNamespaceURIForPrefix.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/FunNamespaceURIForPrefix.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -44,7 +44,6 @@ import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceType; import org.exist.xquery.value.Type; -import org.w3c.dom.Element; import org.w3c.dom.Node; public class FunNamespaceURIForPrefix extends BasicFunction { Modified: trunk/eXist/src/org/exist/xquery/functions/request/GetExists.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/request/GetExists.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/request/GetExists.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -23,18 +23,15 @@ package org.exist.xquery.functions.request; import org.exist.dom.QName; -import org.exist.http.servlets.RequestWrapper; import org.exist.xquery.BasicFunction; import org.exist.xquery.Cardinality; import org.exist.xquery.FunctionSignature; import org.exist.xquery.Variable; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; -import org.exist.xquery.value.JavaObjectValue; import org.exist.xquery.value.BooleanValue; import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceType; -import org.exist.xquery.value.StringValue; import org.exist.xquery.value.Type; /** Modified: trunk/eXist/src/org/exist/xquery/functions/response/GetExists.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/response/GetExists.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/response/GetExists.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -29,11 +29,9 @@ import org.exist.xquery.Variable; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; -import org.exist.xquery.value.JavaObjectValue; import org.exist.xquery.value.BooleanValue; import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceType; -import org.exist.xquery.value.StringValue; import org.exist.xquery.value.Type; /** Modified: trunk/eXist/src/org/exist/xquery/functions/response/SetStatusCode.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/response/SetStatusCode.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/response/SetStatusCode.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -32,9 +32,8 @@ import org.exist.xquery.Variable; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; -import org.exist.xquery.functions.request.RequestModule; -import org.exist.xquery.value.Item; import org.exist.xquery.value.IntegerValue; +import org.exist.xquery.value.Item; import org.exist.xquery.value.JavaObjectValue; import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceType; Modified: trunk/eXist/src/org/exist/xquery/functions/session/GetExists.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/session/GetExists.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/session/GetExists.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -29,11 +29,9 @@ import org.exist.xquery.Variable; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; -import org.exist.xquery.value.JavaObjectValue; import org.exist.xquery.value.BooleanValue; import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceType; -import org.exist.xquery.value.StringValue; import org.exist.xquery.value.Type; /** Modified: trunk/eXist/src/org/exist/xquery/functions/session/SetAttribute.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/session/SetAttribute.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/session/SetAttribute.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -32,7 +32,6 @@ import org.exist.xquery.Variable; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; -import org.exist.xquery.functions.request.RequestModule; import org.exist.xquery.value.Item; import org.exist.xquery.value.JavaObjectValue; import org.exist.xquery.value.Sequence; Modified: trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -22,11 +22,10 @@ */ package org.exist.xquery.functions.system; +import java.util.Iterator; + import org.exist.dom.QName; -import org.exist.memtree.DocumentBuilderReceiver; import org.exist.memtree.MemTreeBuilder; -import org.exist.memtree.NodeImpl; -import org.exist.storage.BrokerPool; import org.exist.xquery.BasicFunction; import org.exist.xquery.Cardinality; import org.exist.xquery.FunctionSignature; @@ -38,10 +37,6 @@ import org.exist.xquery.value.SequenceType; import org.exist.xquery.value.Type; -import java.io.UnsupportedEncodingException; -import java.util.Iterator; -import java.net.URLEncoder; - /** * Return a list of the currently running XQueries (must be dba) * Modified: trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -22,26 +22,21 @@ */ package org.exist.xquery.functions.system; +import java.util.Iterator; + import org.exist.dom.QName; -import org.exist.memtree.DocumentBuilderReceiver; -import org.exist.memtree.MemTreeBuilder; -import org.exist.memtree.NodeImpl; -import org.exist.storage.BrokerPool; import org.exist.xquery.BasicFunction; import org.exist.xquery.Cardinality; import org.exist.xquery.FunctionSignature; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; import org.exist.xquery.XQueryWatchDog; -import org.exist.xquery.value.NodeValue; import org.exist.xquery.value.NumericValue; import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceType; import org.exist.xquery.value.Type; -import java.util.Iterator; - /** * Kill a running XQuery (must be dba) * Modified: trunk/eXist/src/org/exist/xquery/functions/util/ExtractDocs.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/util/ExtractDocs.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/util/ExtractDocs.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -1,16 +1,19 @@ package org.exist.xquery.functions.util; import org.exist.dom.QName; -import org.exist.xquery.*; +import org.exist.memtree.DocumentImpl; +import org.exist.memtree.MemTreeBuilder; +import org.exist.xquery.BasicFunction; +import org.exist.xquery.Cardinality; +import org.exist.xquery.FunctionSignature; +import org.exist.xquery.Module; +import org.exist.xquery.XPathException; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.value.Sequence; import org.exist.xquery.value.SequenceType; import org.exist.xquery.value.Type; -import org.exist.xquery.value.Sequence; -import org.exist.memtree.MemTreeBuilder; -import org.exist.memtree.DocumentImpl; import org.xml.sax.helpers.AttributesImpl; -import java.util.Iterator; - public class ExtractDocs extends BasicFunction { public final static FunctionSignature signature = Modified: trunk/eXist/src/org/exist/xquery/functions/util/Hash.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/util/Hash.java 2009-01-03 16:23:21 UTC (rev 8467) +++ trunk/eXist/src/org/exist/xquery/functions/util/Hash.java 2009-01-03 20:55:26 UTC (rev 8468) @@ -23,8 +23,9 @@ package org.exist.xquery.functions.util; import org.exist.dom.QName; -import org.exist.xquery.Cardinality; +import org.exist.security.MessageDigester; import org.exist.xquery.BasicFunction; +import org.exist.xquery.Cardinality; import org.exist.xquery.FunctionSignature; import org.exist.xquery.XPathException; import org.exist.xquery.XQueryContext; @@ -32,10 +33,7 @@ import org.exist.xquery.value.SequenceType; import org.exist.xquery.value.StringValue; import org.exist.xquery.value.Type; -import org.exist.security.MessageDigester; -import java.security.NoSuchAlgorithmException; - /** * Generate a massage digest (hashcode) from a string. Typically supported * algorithms are MD5 and SHA1. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <br...@us...> - 2009-01-04 22:25:55
|
Revision: 8472 http://exist.svn.sourceforge.net/exist/?rev=8472&view=rev Author: brihaye Date: 2009-01-04 22:25:50 +0000 (Sun, 04 Jan 2009) Log Message: ----------- [ignore] refactored imports Modified Paths: -------------- trunk/eXist/src/org/exist/backup/ConsistencyCheck.java trunk/eXist/src/org/exist/management/impl/SystemInfo.java trunk/eXist/src/org/exist/util/FileInputSource.java trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java Modified: trunk/eXist/src/org/exist/backup/ConsistencyCheck.java =================================================================== --- trunk/eXist/src/org/exist/backup/ConsistencyCheck.java 2009-01-04 21:32:47 UTC (rev 8471) +++ trunk/eXist/src/org/exist/backup/ConsistencyCheck.java 2009-01-04 22:25:50 UTC (rev 8472) @@ -21,6 +21,15 @@ */ package org.exist.backup; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + import org.exist.collections.Collection; import org.exist.dom.BinaryDocument; import org.exist.dom.DocumentImpl; @@ -33,23 +42,15 @@ import org.exist.storage.NativeBroker; import org.exist.storage.btree.BTreeCallback; import org.exist.storage.btree.Value; -import org.exist.storage.dom.*; +import org.exist.storage.dom.DOMFile; +import org.exist.storage.dom.DOMTransaction; import org.exist.storage.index.CollectionStore; import org.exist.storage.io.VariableByteInput; import org.exist.storage.lock.Lock; -import org.exist.util.LockException; import org.exist.xmldb.XmldbURI; import org.exist.xquery.TerminatedException; import org.w3c.dom.Node; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Stack; - public class ConsistencyCheck { private Stack elementStack = new Stack(); Modified: trunk/eXist/src/org/exist/management/impl/SystemInfo.java =================================================================== --- trunk/eXist/src/org/exist/management/impl/SystemInfo.java 2009-01-04 21:32:47 UTC (rev 8471) +++ trunk/eXist/src/org/exist/management/impl/SystemInfo.java 2009-01-04 22:25:50 UTC (rev 8472) @@ -25,7 +25,7 @@ import java.io.InputStreamReader; import java.util.Locale; import java.util.Properties; -import javax.management.*; + import org.apache.log4j.Logger; /** Modified: trunk/eXist/src/org/exist/util/FileInputSource.java =================================================================== --- trunk/eXist/src/org/exist/util/FileInputSource.java 2009-01-04 21:32:47 UTC (rev 8471) +++ trunk/eXist/src/org/exist/util/FileInputSource.java 2009-01-04 22:25:50 UTC (rev 8472) @@ -4,10 +4,8 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; -import java.io.IOException; import java.io.InputStream; import java.io.Reader; -import java.util.zip.GZIPInputStream; public class FileInputSource extends EXistInputSource { Modified: trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java 2009-01-04 21:32:47 UTC (rev 8471) +++ trunk/eXist/src/org/exist/xmlrpc/RpcAPI.java 2009-01-04 22:25:50 UTC (rev 8472) @@ -21,16 +21,15 @@ */ package org.exist.xmlrpc; import java.io.IOException; +import java.net.URISyntaxException; import java.util.Date; import java.util.HashMap; -import java.util.Vector; import java.util.List; -import java.net.URISyntaxException; +import java.util.Vector; import org.exist.EXistException; -import org.exist.util.LockException; import org.exist.security.PermissionDeniedException; -import org.exist.security.User; +import org.exist.util.LockException; import org.exist.xquery.XPathException; import org.xml.sax.SAXException; Modified: trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java =================================================================== --- trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java 2009-01-04 21:32:47 UTC (rev 8471) +++ trunk/eXist/src/org/exist/xmlrpc/RpcServlet.java 2009-01-04 22:25:50 UTC (rev 8472) @@ -21,23 +21,23 @@ */ package org.exist.xmlrpc; -import org.apache.xmlrpc.webserver.XmlRpcServlet; -import org.apache.xmlrpc.server.XmlRpcHandlerMapping; +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.xmlrpc.XmlRpcException; +import org.apache.xmlrpc.XmlRpcHandler; import org.apache.xmlrpc.server.AbstractReflectiveHandlerMapping; import org.apache.xmlrpc.server.RequestProcessorFactoryFactory; +import org.apache.xmlrpc.server.XmlRpcHandlerMapping; import org.apache.xmlrpc.server.XmlRpcNoSuchHandlerException; -import org.apache.xmlrpc.XmlRpcException; -import org.apache.xmlrpc.XmlRpcHandler; +import org.apache.xmlrpc.webserver.XmlRpcServlet; import org.exist.EXistException; import org.exist.http.Descriptor; import org.exist.http.servlets.HttpServletRequestWrapper; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.ServletException; -import java.io.IOException; -import java.io.InputStream; - public class RpcServlet extends XmlRpcServlet { @Override This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-01-06 22:13:29
|
Revision: 8481 http://exist.svn.sourceforge.net/exist/?rev=8481&view=rev Author: wolfgang_m Date: 2009-01-06 22:13:28 +0000 (Tue, 06 Jan 2009) Log Message: ----------- [feature] Extended the old XQueryMonitor into a more general ProcessMonitor, which gets notified whenever a thread starts or ends a major job like storing a document, removing a document or collection and the like. The admin web client has been changed to display running jobs in addition to running XQueries. Access to ProcessMonitor is now synchronized to avoid potential concurrency conflicts. Modified Paths: -------------- trunk/eXist/src/org/exist/collections/Collection.java trunk/eXist/src/org/exist/storage/BrokerPool.java trunk/eXist/src/org/exist/storage/NativeBroker.java trunk/eXist/src/org/exist/xquery/XQuery.java trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java Added Paths: ----------- trunk/eXist/src/org/exist/storage/ProcessMonitor.java trunk/eXist/src/org/exist/xquery/functions/system/GetRunningJobs.java Removed Paths: ------------- trunk/eXist/src/org/exist/storage/XQueryMonitor.java Modified: trunk/eXist/src/org/exist/collections/Collection.java =================================================================== --- trunk/eXist/src/org/exist/collections/Collection.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/collections/Collection.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -48,6 +48,7 @@ import org.exist.storage.NodePath; import org.exist.storage.QNameRangeIndexSpec; import org.exist.storage.UpdateListener; +import org.exist.storage.ProcessMonitor; import org.exist.storage.cache.Cacheable; import org.exist.storage.index.BFile; import org.exist.storage.io.VariableByteInput; @@ -753,6 +754,8 @@ throws PermissionDeniedException, TriggerException, LockException { DocumentImpl doc = null; try { + broker.getBrokerPool().getProcessMonitor().startJob(ProcessMonitor.ACTION_REMOVE_XML, docUri); + //Doh ! READ lock ? getLock().acquire(Lock.READ_LOCK); @@ -799,6 +802,7 @@ broker.getBrokerPool().getNotificationService().notifyUpdate(doc, UpdateListener.REMOVE); } finally { + broker.getBrokerPool().getProcessMonitor().endJob(); if (doc != null) doc.getUpdateLock().release(Lock.WRITE_LOCK); //Doh ! A READ lock ? @@ -808,7 +812,6 @@ public void removeBinaryResource(Txn transaction, DBBroker broker, XmldbURI uri) throws PermissionDeniedException, LockException, TriggerException { - try { getLock().acquire(Lock.WRITE_LOCK); @@ -837,7 +840,8 @@ return; try { - getLock().acquire(Lock.WRITE_LOCK); + broker.getBrokerPool().getProcessMonitor().startJob(ProcessMonitor.ACTION_REMOVE_BINARY, doc.getFileURI()); + getLock().acquire(Lock.WRITE_LOCK); if (doc.getResourceType() != DocumentImpl.BINARY_FILE) throw new PermissionDeniedException("document " + doc.getFileURI() + " is not a binary object"); @@ -876,6 +880,7 @@ trigger.finish(Trigger.REMOVE_DOCUMENT_EVENT, broker, transaction, doc.getURI(), null); } } finally { + broker.getBrokerPool().getProcessMonitor().endJob(); getLock().release(Lock.WRITE_LOCK); } } @@ -1006,6 +1011,7 @@ LOG.warn("document is not locked for write !"); } try { + broker.getBrokerPool().getProcessMonitor().startJob(ProcessMonitor.ACTION_STORE_DOC, document.getFileURI()); doParse.run(); broker.storeXMLResource(transaction, document); @@ -1025,6 +1031,7 @@ } finally { //This lock has been acquired in validateXMLResourceInternal() document.getUpdateLock().release(Lock.WRITE_LOCK); + broker.getBrokerPool().getProcessMonitor().endJob(); } collectionConfEnabled = true; @@ -1156,6 +1163,7 @@ DocumentImpl oldDoc = null; boolean oldDocLocked = false; try { + broker.getBrokerPool().getProcessMonitor().startJob(ProcessMonitor.ACTION_VALIDATE_DOC, docUri); getLock().acquire(Lock.WRITE_LOCK); DocumentImpl document = new DocumentImpl(broker.getBrokerPool(), this, docUri); @@ -1225,6 +1233,7 @@ if (oldDocLocked) oldDoc.getUpdateLock().release(Lock.WRITE_LOCK); getLock().release(Lock.WRITE_LOCK); + broker.getBrokerPool().getProcessMonitor().endJob(); } } @@ -1398,7 +1407,7 @@ DocumentImpl oldDoc = getDocument(broker, docUri); try { - + broker.getBrokerPool().getProcessMonitor().startJob(ProcessMonitor.ACTION_STORE_BINARY, docUri); getLock().acquire(Lock.WRITE_LOCK); checkPermissions(transaction, broker, oldDoc); @@ -1469,7 +1478,8 @@ return blob; } finally { - getLock().release(Lock.WRITE_LOCK); + broker.getBrokerPool().getProcessMonitor().endJob(); + getLock().release(Lock.WRITE_LOCK); } } Modified: trunk/eXist/src/org/exist/storage/BrokerPool.java =================================================================== --- trunk/eXist/src/org/exist/storage/BrokerPool.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/storage/BrokerPool.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -124,9 +124,9 @@ }; //TODO : make this defaut value configurable ? useless if we have a registerShutdownHook(Thread aThread) method (null = deregister) - private static boolean registerShutdownHook = true; - - /** + private static boolean registerShutdownHook = true; + + /** * Whether of not the JVM should run the shutdown thread. * @param register <code>true</code> if the JVM should run the thread */ @@ -477,7 +477,7 @@ /** * The monitor in which the database instance's strong>running</strong> XQueries are managed. */ - private XQueryMonitor xQueryMonitor; + private ProcessMonitor processMonitor; /** * The global manager for accessing collection configuration files from the database instance. @@ -697,7 +697,7 @@ //REFACTOR : construct then configure xQueryPool = new XQueryPool(conf); //REFACTOR : construct then... configure - xQueryMonitor = new XQueryMonitor(); + processMonitor = new ProcessMonitor(); //REFACTOR : construct then... configure xmlReaderPool = new XMLReaderPool(conf, new XMLReaderObjectFactory(this), 5, 0); //REFACTOR : construct then... configure @@ -1050,8 +1050,8 @@ * * @return The monitor */ - public XQueryMonitor getXQueryMonitor() { - return xQueryMonitor; + public ProcessMonitor getProcessMonitor() { + return processMonitor; } /** @@ -1473,7 +1473,7 @@ } //Notify all running XQueries that we are shutting down - xQueryMonitor.killAll(500); + processMonitor.killAll(500); //TODO : close other objects using varying methods ? set them to null ? //cacheManager.something(); //xQueryPool.something(); @@ -1559,7 +1559,7 @@ collectionCache = null; collectionCacheMgr = null; xQueryPool = null; - xQueryMonitor = null; + processMonitor = null; collectionConfigurationManager = null; notificationService = null; indexManager = null; Modified: trunk/eXist/src/org/exist/storage/NativeBroker.java =================================================================== --- trunk/eXist/src/org/exist/storage/NativeBroker.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/storage/NativeBroker.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -751,85 +751,95 @@ if(!destination.getPermissions().validate(getUser(), Permission.WRITE)) throw new PermissionDeniedException("Insufficient privileges on target collection " + destination.getURI()); - //TODO : relativize URI !!! - if(newUri == null) { - newUri = collection.getURI().lastSegment(); - } - // check if another collection with the same name exists at the destination - //TODO : resolve URIs !!! (destination.getURI().resolve(newURI)) - Collection old = openCollection(destination.getURI().append(newUri), Lock.WRITE_LOCK); - if(old != null) { - LOG.debug("removing old collection: " + newUri); + try { + pool.getProcessMonitor().startJob(ProcessMonitor.ACTION_COPY_COLLECTION, collection.getURI()); + //TODO : relativize URI !!! + if(newUri == null) { + newUri = collection.getURI().lastSegment(); + } + // check if another collection with the same name exists at the destination + //TODO : resolve URIs !!! (destination.getURI().resolve(newURI)) + Collection old = openCollection(destination.getURI().append(newUri), Lock.WRITE_LOCK); + if(old != null) { + LOG.debug("removing old collection: " + newUri); + try { + removeCollection(transaction, old); + } finally { + old.release(Lock.WRITE_LOCK); + } + } + Collection destCollection = null; + Lock lock = collectionsDb.getLock(); try { - removeCollection(transaction, old); + lock.acquire(Lock.WRITE_LOCK); + //TODO : resolve URIs !!! + newUri = destination.getURI().append(newUri); + LOG.debug("Copying collection to '" + newUri + "'"); + destCollection = getOrCreateCollection(transaction, newUri); + for(Iterator i = collection.iterator(this); i.hasNext(); ) { + DocumentImpl child = (DocumentImpl) i.next(); + LOG.debug("Copying resource: '" + child.getURI() + "'"); + if (child.getResourceType() == DocumentImpl.XML_FILE) { + //TODO : put a lock on newDoc ? + DocumentImpl newDoc = new DocumentImpl(pool, destCollection, child.getFileURI()); + newDoc.copyOf(child); + newDoc.setDocId(getNextResourceId(transaction, destination)); + copyXMLResource(transaction, child, newDoc); + storeXMLResource(transaction, newDoc); + destCollection.addDocument(transaction, this, newDoc); + } else { + BinaryDocument newDoc = new BinaryDocument(pool, destCollection, child.getFileURI()); + newDoc.copyOf(child); + newDoc.setDocId(getNextResourceId(transaction, destination)); + /* + byte[] data = getBinaryResource((BinaryDocument) child); + storeBinaryResource(transaction, newDoc, data); + */ + InputStream is = getBinaryResource((BinaryDocument)child); + storeBinaryResource(transaction,newDoc,is); + is.close(); + storeXMLResource(transaction, newDoc); + destCollection.addDocument(transaction, this, newDoc); + } + } + saveCollection(transaction, destCollection); } finally { - old.release(Lock.WRITE_LOCK); + lock.release(Lock.WRITE_LOCK); } - } - Collection destCollection = null; - Lock lock = collectionsDb.getLock(); - try { - lock.acquire(Lock.WRITE_LOCK); - //TODO : resolve URIs !!! - newUri = destination.getURI().append(newUri); - LOG.debug("Copying collection to '" + newUri + "'"); - destCollection = getOrCreateCollection(transaction, newUri); - for(Iterator i = collection.iterator(this); i.hasNext(); ) { - DocumentImpl child = (DocumentImpl) i.next(); - LOG.debug("Copying resource: '" + child.getURI() + "'"); - if (child.getResourceType() == DocumentImpl.XML_FILE) { - //TODO : put a lock on newDoc ? - DocumentImpl newDoc = new DocumentImpl(pool, destCollection, child.getFileURI()); - newDoc.copyOf(child); - newDoc.setDocId(getNextResourceId(transaction, destination)); - copyXMLResource(transaction, child, newDoc); - storeXMLResource(transaction, newDoc); - destCollection.addDocument(transaction, this, newDoc); - } else { - BinaryDocument newDoc = new BinaryDocument(pool, destCollection, child.getFileURI()); - newDoc.copyOf(child); - newDoc.setDocId(getNextResourceId(transaction, destination)); - /* - byte[] data = getBinaryResource((BinaryDocument) child); - storeBinaryResource(transaction, newDoc, data); - */ - InputStream is = getBinaryResource((BinaryDocument)child); - storeBinaryResource(transaction,newDoc,is); - is.close(); - storeXMLResource(transaction, newDoc); - destCollection.addDocument(transaction, this, newDoc); + + XmldbURI name = collection.getURI(); + for(Iterator i = collection.collectionIterator(); i.hasNext(); ) { + XmldbURI childName = (XmldbURI)i.next(); + //TODO : resolve URIs ! collection.getURI().resolve(childName) + Collection child = openCollection(name.append(childName), Lock.WRITE_LOCK); + if(child == null) + LOG.warn("Child collection '" + childName + "' not found"); + else { + try { + copyCollection(transaction, child, destCollection, childName); + } finally { + child.release(Lock.WRITE_LOCK); + } } } saveCollection(transaction, destCollection); + saveCollection(transaction, destination); } finally { - lock.release(Lock.WRITE_LOCK); + pool.getProcessMonitor().endJob(); } - - XmldbURI name = collection.getURI(); - for(Iterator i = collection.collectionIterator(); i.hasNext(); ) { - XmldbURI childName = (XmldbURI)i.next(); - //TODO : resolve URIs ! collection.getURI().resolve(childName) - Collection child = openCollection(name.append(childName), Lock.WRITE_LOCK); - if(child == null) - LOG.warn("Child collection '" + childName + "' not found"); - else { - try { - copyCollection(transaction, child, destCollection, childName); - } finally { - child.release(Lock.WRITE_LOCK); - } - } - } - saveCollection(transaction, destCollection); - saveCollection(transaction, destination); } public void moveCollection(Txn transaction, Collection collection, Collection destination, XmldbURI newName) throws PermissionDeniedException, LockException, IOException { - // Need to move each collection in the source tree individually, so recurse. - moveCollectionRecursive(transaction, collection, destination, newName); - // For binary resources, though, just move the top level directory and all descendants come with it. - moveBinaryFork(transaction, collection, destination, newName); + pool.getProcessMonitor().startJob(ProcessMonitor.ACTION_MOVE_COLLECTION, collection.getURI()); + try { +// Need to move each collection in the source tree individually, so recurse. + moveCollectionRecursive(transaction, collection, destination, newName); + // For binary resources, though, just move the top level directory and all descendants come with it. + moveBinaryFork(transaction, collection, destination, newName); + } finally { + pool.getProcessMonitor().endJob(); + } } private void moveBinaryFork(Txn transaction, Collection collection, Collection destination, XmldbURI newName) throws IOException { @@ -961,213 +971,218 @@ { if(readOnly) throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); - + if(!collection.getPermissions().validate(getUser(), Permission.WRITE)) throw new PermissionDeniedException("User '"+ getUser().getName() + "' not allowed to remove collection '" + collection.getURI() + "'"); - - long start = System.currentTimeMillis(); - final CollectionCache collectionsCache = pool.getCollectionsCache(); - File sourceDir = getCollectionFile(fsDir,collection.getURI(),false); - File targetDir = getCollectionFile(fsBackupDir,transaction,collection.getURI(),true); - - synchronized(collectionsCache) + + try { + pool.getProcessMonitor().startJob(ProcessMonitor.ACTION_REMOVE_COLLECTION, collection.getURI()); + long start = System.currentTimeMillis(); + final CollectionCache collectionsCache = pool.getCollectionsCache(); + File sourceDir = getCollectionFile(fsDir,collection.getURI(),false); + File targetDir = getCollectionFile(fsBackupDir,transaction,collection.getURI(),true); + + synchronized(collectionsCache) { canRemoveCollection(collection); - + final XmldbURI uri = collection.getURI(); - final String collName = uri.getRawCollectionPath(); - final boolean isRoot = collection.getParentURI() == null; + final String collName = uri.getRawCollectionPath(); + final boolean isRoot = collection.getParentURI() == null; - // Notify the collection configuration manager - pool.getConfigurationManager().invalidateAll(uri); - - // remove child collections - if(LOG.isDebugEnabled()) - LOG.debug("Removing children collections from their parent '" + collName + "'..."); - - for(Iterator i = collection.collectionIterator(); i.hasNext();) - { - final XmldbURI childName = (XmldbURI) i.next(); - //TODO : resolve from collection's base URI - //TODO : resulve URIs !!! (uri.resolve(childName)) - Collection childCollection = openCollection(uri.append(childName), Lock.WRITE_LOCK); - try { - removeCollection(transaction, childCollection); - } finally { - if (childCollection != null) - childCollection.getLock().release(Lock.WRITE_LOCK); - else - LOG.warn("childCollection is null !"); + // Notify the collection configuration manager + pool.getConfigurationManager().invalidateAll(uri); + + // remove child collections + if(LOG.isDebugEnabled()) + LOG.debug("Removing children collections from their parent '" + collName + "'..."); + + for(Iterator i = collection.collectionIterator(); i.hasNext();) + { + final XmldbURI childName = (XmldbURI) i.next(); + //TODO : resolve from collection's base URI + //TODO : resulve URIs !!! (uri.resolve(childName)) + Collection childCollection = openCollection(uri.append(childName), Lock.WRITE_LOCK); + try { + removeCollection(transaction, childCollection); + } finally { + if (childCollection != null) + childCollection.getLock().release(Lock.WRITE_LOCK); + else + LOG.warn("childCollection is null !"); + } } - } - //Drop all index entries - notifyDropIndex(collection); + //Drop all index entries + notifyDropIndex(collection); - // Drop custom indexes - indexController.removeCollection(collection, this); - - if(!isRoot) - { - // remove from parent collection - //TODO : resolve URIs ! (uri.resolve("..")) - Collection parentCollection = openCollection(collection.getParentURI(), Lock.WRITE_LOCK); + // Drop custom indexes + indexController.removeCollection(collection, this); - // keep the lock for the transaction - if(transaction != null) - transaction.registerLock(parentCollection.getLock(), Lock.WRITE_LOCK); + if(!isRoot) + { + // remove from parent collection + //TODO : resolve URIs ! (uri.resolve("..")) + Collection parentCollection = openCollection(collection.getParentURI(), Lock.WRITE_LOCK); - if(parentCollection != null) - { - try + // keep the lock for the transaction + if(transaction != null) + transaction.registerLock(parentCollection.getLock(), Lock.WRITE_LOCK); + + if(parentCollection != null) { - LOG.debug("Removing collection '" + collName + "' from its parent..."); - //TODO : resolve from collection's base URI - parentCollection.removeCollection(uri.lastSegment()); - saveCollection(transaction, parentCollection); + try + { + LOG.debug("Removing collection '" + collName + "' from its parent..."); + //TODO : resolve from collection's base URI + parentCollection.removeCollection(uri.lastSegment()); + saveCollection(transaction, parentCollection); + } + catch(LockException e) + { + LOG.warn("LockException while removing collection '" + collName + "'"); + } + finally + { + if(transaction == null) + parentCollection.getLock().release(Lock.WRITE_LOCK); + } } - catch(LockException e) + } + + //Update current state + Lock lock = collectionsDb.getLock(); + try + { + lock.acquire(Lock.WRITE_LOCK); + // remove the metadata of all documents in the collection + Value docKey = new CollectionStore.DocumentKey(collection.getId()); + IndexQuery query = new IndexQuery(IndexQuery.TRUNC_RIGHT, docKey); + collectionsDb.removeAll(transaction, query); + + // if this is not the root collection remove it... + if(!isRoot) { - LOG.warn("LockException while removing collection '" + collName + "'"); + Value key = new CollectionStore.CollectionKey(collName); + //... from the disk + collectionsDb.remove(transaction, key); + //... from the cache + collectionsCache.remove(collection); + //and free its id for any futher use + freeCollectionId(transaction, collection.getId()); } - finally + else { - if(transaction == null) - parentCollection.getLock().release(Lock.WRITE_LOCK); + //Simply save the collection on disk + //It will remain cached + //and its id well never be made available + saveCollection(transaction, collection); } } - } - - //Update current state - Lock lock = collectionsDb.getLock(); - try - { - lock.acquire(Lock.WRITE_LOCK); - // remove the metadata of all documents in the collection - Value docKey = new CollectionStore.DocumentKey(collection.getId()); - IndexQuery query = new IndexQuery(IndexQuery.TRUNC_RIGHT, docKey); - collectionsDb.removeAll(transaction, query); - - // if this is not the root collection remove it... - if(!isRoot) + catch(LockException e) { - Value key = new CollectionStore.CollectionKey(collName); - //... from the disk - collectionsDb.remove(transaction, key); - //... from the cache - collectionsCache.remove(collection); - //and free its id for any futher use - freeCollectionId(transaction, collection.getId()); + LOG.warn("Failed to acquire lock on '" + collectionsDb.getFile().getName() + "'"); } - else + catch(ReadOnlyException e) { - //Simply save the collection on disk - //It will remain cached - //and its id well never be made available - saveCollection(transaction, collection); + throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); } - } - catch(LockException e) - { - LOG.warn("Failed to acquire lock on '" + collectionsDb.getFile().getName() + "'"); - } - catch(ReadOnlyException e) - { - throw new PermissionDeniedException(DATABASE_IS_READ_ONLY); - } - catch(BTreeException e) - { - LOG.warn("Exception while removing collection: " + e.getMessage(), e); - } - catch(IOException e) - { - LOG.warn("Exception while removing collection: " + e.getMessage(), e); - } - finally - { - lock.release(Lock.WRITE_LOCK); - } - - //Remove child resources - if (LOG.isDebugEnabled()) - LOG.debug("Removing resources in '" + collName + "'..."); - - for(Iterator i = collection.iterator(this); i.hasNext();) - { - final DocumentImpl doc = (DocumentImpl) i.next(); - //Remove doc's metadata - // WM: now removed in one step. see above. - //removeResourceMetadata(transaction, doc); - //Remove document nodes' index entries - new DOMTransaction(this, domDb, Lock.WRITE_LOCK) + catch(BTreeException e) { - public Object start() + LOG.warn("Exception while removing collection: " + e.getMessage(), e); + } + catch(IOException e) + { + LOG.warn("Exception while removing collection: " + e.getMessage(), e); + } + finally + { + lock.release(Lock.WRITE_LOCK); + } + + //Remove child resources + if (LOG.isDebugEnabled()) + LOG.debug("Removing resources in '" + collName + "'..."); + + for(Iterator i = collection.iterator(this); i.hasNext();) + { + final DocumentImpl doc = (DocumentImpl) i.next(); + //Remove doc's metadata + // WM: now removed in one step. see above. + //removeResourceMetadata(transaction, doc); + //Remove document nodes' index entries + new DOMTransaction(this, domDb, Lock.WRITE_LOCK) { - try - { - Value ref = new NodeRef(doc.getDocId()); - IndexQuery query = new IndexQuery(IndexQuery.TRUNC_RIGHT, ref); - domDb.remove(transaction, query, null); - } - catch(BTreeException e) + public Object start() { - LOG.warn("btree error while removing document", e); + try + { + Value ref = new NodeRef(doc.getDocId()); + IndexQuery query = new IndexQuery(IndexQuery.TRUNC_RIGHT, ref); + domDb.remove(transaction, query, null); + } + catch(BTreeException e) + { + LOG.warn("btree error while removing document", e); + } + catch(IOException e) + { + LOG.warn("io error while removing document", e); + } + catch(TerminatedException e) + { + LOG.warn("method terminated", e); + } + return null; } - catch(IOException e) - { - LOG.warn("io error while removing document", e); - } - catch(TerminatedException e) - { - LOG.warn("method terminated", e); - } - return null; - } - }.run(); + }.run(); - //Remove nodes themselves - new DOMTransaction(this, domDb, Lock.WRITE_LOCK) - { - public Object start() + //Remove nodes themselves + new DOMTransaction(this, domDb, Lock.WRITE_LOCK) { - if(doc.getResourceType() == DocumentImpl.BINARY_FILE) + public Object start() { - long page = ((BinaryDocument)doc).getPage(); - - if (page > Page.NO_PAGE) - domDb.removeOverflowValue(transaction, page); + if(doc.getResourceType() == DocumentImpl.BINARY_FILE) + { + long page = ((BinaryDocument)doc).getPage(); + + if (page > Page.NO_PAGE) + domDb.removeOverflowValue(transaction, page); + } + else + { + StoredNode node = (StoredNode)doc.getFirstChild(); + domDb.removeAll(transaction, node.getInternalAddress()); + } + return null; } - else - { - StoredNode node = (StoredNode)doc.getFirstChild(); - domDb.removeAll(transaction, node.getInternalAddress()); - } - return null; - } - }.run(); + }.run(); - //Make doc's id available again - freeResourceId(transaction, doc.getDocId()); + //Make doc's id available again + freeResourceId(transaction, doc.getDocId()); + } + + if (sourceDir.exists()) { + targetDir.getParentFile().mkdirs(); + if (sourceDir.renameTo(targetDir)) { + Loggable loggable = new RenameBinaryLoggable(this,transaction,sourceDir,targetDir); + try { + logManager.writeToLog(loggable); + } catch (TransactionException e) { + LOG.warn(e.getMessage(), e); + } + + } else { + LOG.fatal("Cannot rename "+sourceDir+" to "+targetDir); + } + } + if(LOG.isDebugEnabled()) + LOG.debug("Removing collection '" + collName + "' took " + (System.currentTimeMillis() - start)); + + return true; } - - if (sourceDir.exists()) { - targetDir.getParentFile().mkdirs(); - if (sourceDir.renameTo(targetDir)) { - Loggable loggable = new RenameBinaryLoggable(this,transaction,sourceDir,targetDir); - try { - logManager.writeToLog(loggable); - } catch (TransactionException e) { - LOG.warn(e.getMessage(), e); - } - - } else { - LOG.fatal("Cannot rename "+sourceDir+" to "+targetDir); - } - } - if(LOG.isDebugEnabled()) - LOG.debug("Removing collection '" + collName + "' took " + (System.currentTimeMillis() - start)); - - return true; + } finally { + pool.getProcessMonitor().endJob(); } } @@ -1351,11 +1366,14 @@ TransactionManager transact = pool.getTransactionManager(); Txn transaction = transact.beginTransaction(); try { + pool.getProcessMonitor().startJob(ProcessMonitor.ACTION_REINDEX_COLLECTION, collection.getURI()); reindexCollection(transaction, collection, mode); transact.commit(transaction); } catch (TransactionException e) { transact.abort(transaction); LOG.warn("An error occurred during reindex: " + e.getMessage(), e); + } finally { + pool.getProcessMonitor().endJob(); } } Added: trunk/eXist/src/org/exist/storage/ProcessMonitor.java =================================================================== --- trunk/eXist/src/org/exist/storage/ProcessMonitor.java (rev 0) +++ trunk/eXist/src/org/exist/storage/ProcessMonitor.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -0,0 +1,165 @@ +/* + * eXist Open Source Native XML Database + * Copyright (C) 2001-04 Wolfgang M. Meier + * wol...@ex... + * http://exist.sourceforge.net + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: ProcessMonitor.java 8235 2008-10-17 16:03:27Z chaeron $ + */ +package org.exist.storage; + +import org.apache.log4j.Logger; +import org.exist.xquery.XQueryWatchDog; +import org.exist.xquery.util.ExpressionDumper; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +/** + * Class to keep track of all running queries in a database instance. The main + * purpose of this class is to signal running queries that the database is going to + * shut down. This is done through the {@link org.exist.xquery.XQueryWatchDog} + * registered by each query. It is up to the query to check the watchdog's state. + * If it simply ignores the terminate signal, it will be killed after the shutdown + * timeout is reached. + * + * @author wolf + */ +public class ProcessMonitor { + + public final static String ACTION_UNSPECIFIED = "unspecified"; + public final static String ACTION_VALIDATE_DOC = "validating document"; + public final static String ACTION_STORE_DOC = "storing document"; + public final static String ACTION_STORE_BINARY = "storing binary resource"; + public final static String ACTION_REMOVE_XML = "remove XML resource"; + public final static String ACTION_REMOVE_BINARY = "remove binary resource"; + public final static String ACTION_REMOVE_COLLECTION = "remove collection"; + public final static String ACTION_REINDEX_COLLECTION = "reindex collection"; + public final static String ACTION_COPY_COLLECTION = "copy collection"; + public final static String ACTION_MOVE_COLLECTION = "move collection"; + + private final static Logger LOG = Logger.getLogger(ProcessMonitor.class); + + private Set runningQueries = new HashSet(); + + private Map processes = new HashMap(); + + public ProcessMonitor() { + super(); + } + + public void startJob(String action) { + startJob(action, null); + } + + public void startJob(String action, Object addInfo) { + JobInfo info = new JobInfo(action); + info.setAddInfo(addInfo); + synchronized (processes) { + processes.put(info.getThread(), info); + } + } + + public void endJob() { + synchronized (processes) { + processes.remove(Thread.currentThread()); + } + } + + public JobInfo[] runningJobs() { + synchronized (processes) { + JobInfo jobs[] = new JobInfo[processes.size()]; + int j = 0; + for (Iterator i = processes.keySet().iterator(); i.hasNext(); j++) { + jobs[j] = (JobInfo) i.next(); + } + return jobs; + } + } + + public void queryStarted(XQueryWatchDog watchdog) { + synchronized (runningQueries) { + runningQueries.add(watchdog); + } + } + + public void queryCompleted(XQueryWatchDog watchdog) { + synchronized (runningQueries) { + runningQueries.remove(watchdog); + } + } + + public void killAll(long waitTime) { + // directly called from BrokerPool itself. no need to synchronize. + XQueryWatchDog watchdog; + for(Iterator i = runningQueries.iterator(); i.hasNext(); ) { + watchdog = (XQueryWatchDog) i.next(); + LOG.debug("Killing query: " + + ExpressionDumper.dump(watchdog.getContext().getRootExpression())); + watchdog.kill(waitTime); + } + } + + public XQueryWatchDog[] getRunningXQueries() + { + synchronized (runningQueries) { + XQueryWatchDog watchdogs[] = new XQueryWatchDog[runningQueries.size()]; + int j = 0; + for (Iterator i = runningQueries.iterator(); i.hasNext(); j++) { + watchdogs[j] = (XQueryWatchDog) i.next(); + } + return watchdogs; + } + } + + public final static class JobInfo { + + private Thread thread; + private String action; + private long startTime; + private Object addInfo = null; + + public JobInfo(String action) { + this.thread = Thread.currentThread(); + this.action = action; + this.startTime = System.currentTimeMillis(); + } + + public String getAction() { + return action; + } + + public Thread getThread() { + return thread; + } + + public long getStartTime() { + return startTime; + } + + public void setAddInfo(Object info) { + this.addInfo = info; + } + + public Object getAddInfo() { + return addInfo; + } + } +} Deleted: trunk/eXist/src/org/exist/storage/XQueryMonitor.java =================================================================== --- trunk/eXist/src/org/exist/storage/XQueryMonitor.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/storage/XQueryMonitor.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -1,75 +0,0 @@ -/* - * eXist Open Source Native XML Database - * Copyright (C) 2001-04 Wolfgang M. Meier - * wol...@ex... - * http://exist.sourceforge.net - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * $Id$ - */ -package org.exist.storage; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import org.apache.log4j.Logger; -import org.exist.xquery.XQueryWatchDog; -import org.exist.xquery.util.ExpressionDumper; - -/** - * Class to keep track of all running queries in a database instance. The main - * purpose of this class is to signal running queries that the database is going to - * shut down. This is done through the {@link org.exist.xquery.XQueryWatchDog} - * registered by each query. It is up to the query to check the watchdog's state. - * If it simply ignores the terminate signal, it will be killed after the shutdown - * timeout is reached. - * - * @author wolf - */ -public class XQueryMonitor { - - private final static Logger LOG = Logger.getLogger(XQueryMonitor.class); - - private Set runningQueries = new HashSet(); - - public XQueryMonitor() { - super(); - } - - public void queryStarted(XQueryWatchDog watchdog) { - runningQueries.add(watchdog); - } - - public void queryCompleted(XQueryWatchDog watchdog) { - runningQueries.remove(watchdog); - } - - public void killAll(long waitTime) { - XQueryWatchDog watchdog; - for(Iterator i = runningQueries.iterator(); i.hasNext(); ) { - watchdog = (XQueryWatchDog) i.next(); - LOG.debug("Killing query: " + - ExpressionDumper.dump(watchdog.getContext().getRootExpression())); - watchdog.kill(waitTime); - } - } - - public Iterator getRunningXQueriesIterator() - { - return( runningQueries.iterator() ); - } -} Modified: trunk/eXist/src/org/exist/xquery/XQuery.java =================================================================== --- trunk/eXist/src/org/exist/xquery/XQuery.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/xquery/XQuery.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -219,7 +219,7 @@ //do any preparation before execution context.prepare(); - broker.getBrokerPool().getXQueryMonitor().queryStarted(context.getWatchDog()); + broker.getBrokerPool().getProcessMonitor().queryStarted(context.getWatchDog()); try { Sequence result = expression.eval(contextSequence); if (LOG.isDebugEnabled()) { @@ -231,7 +231,7 @@ expression.reset(); if (resetContext) context.reset(); - broker.getBrokerPool().getXQueryMonitor().queryCompleted(context.getWatchDog()); + broker.getBrokerPool().getProcessMonitor().queryCompleted(context.getWatchDog()); } } Added: trunk/eXist/src/org/exist/xquery/functions/system/GetRunningJobs.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/GetRunningJobs.java (rev 0) +++ trunk/eXist/src/org/exist/xquery/functions/system/GetRunningJobs.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -0,0 +1,65 @@ +package org.exist.xquery.functions.system; + +import org.exist.xquery.BasicFunction; +import org.exist.xquery.FunctionSignature; +import org.exist.xquery.Cardinality; +import org.exist.xquery.XQueryContext; +import org.exist.xquery.XPathException; +import org.exist.xquery.value.SequenceType; +import org.exist.xquery.value.Type; +import org.exist.xquery.value.Sequence; +import org.exist.xquery.value.NodeValue; +import org.exist.xquery.value.DateTimeValue; +import org.exist.dom.QName; +import org.exist.memtree.MemTreeBuilder; +import org.exist.storage.ProcessMonitor; + +import java.util.Iterator; +import java.util.Date; + +public class GetRunningJobs extends BasicFunction { + + final static String NAMESPACE_URI = SystemModule.NAMESPACE_URI; + final static String PREFIX = SystemModule.PREFIX; + + public final static FunctionSignature signature = + new FunctionSignature( + new QName( "get-running-jobs", SystemModule.NAMESPACE_URI, SystemModule.PREFIX ), + "Get a list of running jobs (dba role only).", + null, + new SequenceType( Type.ITEM, Cardinality.EXACTLY_ONE ) + ); + + public GetRunningJobs(XQueryContext context) { + super(context, signature); + } + + public Sequence eval(Sequence[] args, Sequence contextSequence) throws XPathException { + if( !context.getUser().hasDbaRole() ) { + throw( new XPathException( getASTNode(), "Permission denied, calling user '" + context.getUser().getName() + "' must be a DBA to get the list of running xqueries" ) ); + } + + MemTreeBuilder builder = context.getDocumentBuilder(); + + builder.startDocument(); + builder.startElement( new QName( "jobs", NAMESPACE_URI, PREFIX ), null ); + + ProcessMonitor monitor = context.getBroker().getBrokerPool().getProcessMonitor(); + ProcessMonitor.JobInfo[] jobs = monitor.runningJobs(); + for (int i = 0; i < jobs.length; i++) { + Thread process = jobs[i].getThread(); + Date startDate = new Date(jobs[i].getStartTime()); + builder.startElement( new QName( "job", NAMESPACE_URI, PREFIX ), null); + builder.addAttribute( new QName("id", null, null), process.getName()); + builder.addAttribute( new QName("action", null, null), jobs[i].getAction()); + builder.addAttribute( new QName("start", null, null), new DateTimeValue(startDate).getStringValue()); + builder.addAttribute(new QName("info", null, null), jobs[i].getAddInfo().toString()); + builder.endElement(); + } + + builder.endElement(); + builder.endDocument(); + + return (NodeValue)builder.getDocument().getDocumentElement(); + } +} Modified: trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/xquery/functions/system/GetRunningXQueries.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -22,8 +22,6 @@ */ package org.exist.xquery.functions.system; -import java.util.Iterator; - import org.exist.dom.QName; import org.exist.memtree.MemTreeBuilder; import org.exist.xquery.BasicFunction; @@ -85,12 +83,11 @@ builder.startElement( new QName( "xqueries", NAMESPACE_URI, PREFIX ), null ); //Add all the running xqueries - - for( Iterator i = getContext().getBroker().getBrokerPool().getXQueryMonitor().getRunningXQueriesIterator(); i.hasNext(); ) { - XQueryWatchDog watchdog = (XQueryWatchDog)i.next(); - XQueryContext context = watchdog.getContext(); + XQueryWatchDog watchdogs[] = getContext().getBroker().getBrokerPool().getProcessMonitor().getRunningXQueries(); + for (int i = 0; i < watchdogs.length; i++) { + XQueryContext context = watchdogs[i].getContext(); - getRunningXQuery( builder, context, watchdog ); + getRunningXQuery( builder, context, watchdogs[i] ); } builder.endElement(); Modified: trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/xquery/functions/system/KillRunningXQuery.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -22,8 +22,6 @@ */ package org.exist.xquery.functions.system; -import java.util.Iterator; - import org.exist.dom.QName; import org.exist.xquery.BasicFunction; import org.exist.xquery.Cardinality; @@ -36,7 +34,9 @@ import org.exist.xquery.value.SequenceType; import org.exist.xquery.value.Type; +import java.util.Iterator; + /** * Kill a running XQuery (must be dba) * @@ -111,13 +111,13 @@ } if( id != 0 ) { - for( Iterator i = getContext().getBroker().getBrokerPool().getXQueryMonitor().getRunningXQueriesIterator(); i.hasNext(); ) { - XQueryWatchDog watchdog = (XQueryWatchDog)i.next(); - XQueryContext context = watchdog.getContext(); + XQueryWatchDog watchdogs[] = getContext().getBroker().getBrokerPool().getProcessMonitor().getRunningXQueries(); + for (int i = 0; i < watchdogs.length; i++) { + XQueryContext context = watchdogs[i].getContext(); if( id == context.hashCode() ) { - if( !watchdog.isTerminating() ) { - watchdog.kill( waittime ); + if( !watchdogs[i].isTerminating() ) { + watchdogs[i].kill( waittime ); } break; } Modified: trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java 2009-01-06 19:11:36 UTC (rev 8480) +++ trunk/eXist/src/org/exist/xquery/functions/system/SystemModule.java 2009-01-06 22:13:28 UTC (rev 8481) @@ -53,7 +53,8 @@ new FunctionDef(UpdateStatistics.signature, UpdateStatistics.class), new FunctionDef(GetRunningXQueries.signature, GetRunningXQueries.class), new FunctionDef(KillRunningXQuery.signatures[0], KillRunningXQuery.class), - new FunctionDef(KillRunningXQuery.signatures[1], KillRunningXQuery.class) + new FunctionDef(KillRunningXQuery.signatures[1], KillRunningXQuery.class), + new FunctionDef(GetRunningJobs.signature, GetRunningJobs.class) }; public SystemModule() { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <pka...@us...> - 2009-01-12 02:10:11
|
Revision: 8500 http://exist.svn.sourceforge.net/exist/?rev=8500&view=rev Author: pkaminsk2 Date: 2009-01-12 01:45:28 +0000 (Mon, 12 Jan 2009) Log Message: ----------- Fixed some bugs with module borrowing, where functions from a freshly borrowed module wouldn't get analyzed. However, there's still bugs left: a borrowed module might've had its functions analyzed in the wrong context, or had optimization applied when it's off in the root context (or vice-versa). Fixing these issue might require a top-to-bottom reworking of the context and module system. Also fixed util:registered-modules(), broken by a previous change. Modified Paths: -------------- trunk/eXist/src/org/exist/storage/XQueryPool.java trunk/eXist/src/org/exist/xquery/FunctionCall.java trunk/eXist/src/org/exist/xquery/ModuleContext.java trunk/eXist/src/org/exist/xquery/XQuery.java trunk/eXist/src/org/exist/xquery/XQueryContext.java trunk/eXist/src/org/exist/xquery/functions/util/Compile.java trunk/eXist/src/org/exist/xquery/functions/util/ModuleInfo.java Modified: trunk/eXist/src/org/exist/storage/XQueryPool.java =================================================================== --- trunk/eXist/src/org/exist/storage/XQueryPool.java 2009-01-11 19:05:19 UTC (rev 8499) +++ trunk/eXist/src/org/exist/storage/XQueryPool.java 2009-01-12 01:45:28 UTC (rev 8500) @@ -183,6 +183,16 @@ remove(source); return null; } else { + if (query instanceof PathExpr) try { + // This is necessary because eXist performs whole-expression analysis, so a function + // can only be analyzed as part of the expression it's called from. It might be better + // to make module functions more stand-alone, so they only need to be analyzed + // once. + context.analyzeAndOptimizeIfModulesChanged((PathExpr) query); + } catch (XPathException e) { + remove(source); + return null; + } return query; } } Modified: trunk/eXist/src/org/exist/xquery/FunctionCall.java =================================================================== --- trunk/eXist/src/org/exist/xquery/FunctionCall.java 2009-01-11 19:05:19 UTC (rev 8499) +++ trunk/eXist/src/org/exist/xquery/FunctionCall.java 2009-01-12 01:45:28 UTC (rev 8500) @@ -34,7 +34,7 @@ import org.exist.xquery.value.SequenceType; import org.exist.xquery.value.Type; -import java.util.List; +import java.util.*; /** * Represents a call to a user-defined function @@ -55,8 +55,6 @@ private List arguments = null; private boolean isRecursive = false; - - private boolean analyzed = false; private VariableReference varDeps[]; @@ -89,35 +87,52 @@ expression = new DynamicTypeCheck(context, returnType.getPrimaryType(), expression); } + /** + * For calls to functions in external modules, check that the instance of the function we were + * bound to matches the current implementation of the module bound to our context. If not, + * rebind to the correct instance, but don't bother resetting the signature since it's guaranteed + * (I hope!) to be the same. + */ + private void updateFunction() { + if (functionDef.getContext() instanceof ModuleContext) { + ModuleContext modContext = (ModuleContext) functionDef.getContext(); + if (modContext.getParentContext() != context) { + UserDefinedFunction replacementFunctionDef = + ((ExternalModule) context.getModule(functionDef.getName().getNamespaceURI())) + .getFunction(functionDef.getName(), getArgumentCount()); + if (replacementFunctionDef == null) throw new NoSuchElementException("internal error: unable to rebind cached function reference " + functionDef.getName().getStringValue() + "/" + getArgumentCount() + " to new instance of module"); + expression = functionDef = replacementFunctionDef; + } + } + } + /* (non-Javadoc) * @see org.exist.xquery.Function#analyze(org.exist.xquery.AnalyzeContextInfo) */ public void analyze(AnalyzeContextInfo contextInfo) throws XPathException { + updateFunction(); contextInfo.setParent(this); - if (!analyzed) { - AnalyzeContextInfo newContextInfo = new AnalyzeContextInfo(contextInfo); - newContextInfo.removeFlag(IN_NODE_CONSTRUCTOR); - super.analyze(newContextInfo); - if (context.tailRecursiveCall(functionDef.getSignature())) { - isRecursive = true; - } - context.functionStart(functionDef.getSignature()); - try { - expression.analyze(newContextInfo); - analyzed = true; - } finally { - context.functionEnd(); - } + AnalyzeContextInfo newContextInfo = new AnalyzeContextInfo(contextInfo); + newContextInfo.removeFlag(IN_NODE_CONSTRUCTOR); + super.analyze(newContextInfo); + if (context.tailRecursiveCall(functionDef.getSignature())) { + isRecursive = true; + } + context.functionStart(functionDef.getSignature()); + try { + expression.analyze(newContextInfo); + } finally { + context.functionEnd(); + } - varDeps = new VariableReference[getArgumentCount()]; - for(int i = 0; i < getArgumentCount(); i++) { - Expression arg = getArgument(i); - VariableReference varRef = BasicExpressionVisitor.findVariableRef(arg); - if (varRef != null) { - varDeps[i] = varRef; - } - } - } + varDeps = new VariableReference[getArgumentCount()]; + for(int i = 0; i < getArgumentCount(); i++) { + Expression arg = getArgument(i); + VariableReference varRef = BasicExpressionVisitor.findVariableRef(arg); + if (varRef != null) { + varDeps[i] = varRef; + } + } } /** @@ -271,7 +286,6 @@ public void resetState(boolean postOptimization) { super.resetState(postOptimization); functionDef.resetState(postOptimization); - analyzed = false; //TODO : reset expression ? } Modified: trunk/eXist/src/org/exist/xquery/ModuleContext.java =================================================================== --- trunk/eXist/src/org/exist/xquery/ModuleContext.java 2009-01-11 19:05:19 UTC (rev 8499) +++ trunk/eXist/src/org/exist/xquery/ModuleContext.java 2009-01-12 01:45:28 UTC (rev 8500) @@ -55,12 +55,20 @@ loadDefaults(broker.getConfiguration()); } + void setModulesChanged() { + parentContext.setModulesChanged(); + } + void setParentContext(XQueryContext parentContext) { this.parentContext = parentContext; this.broker = parentContext.broker; baseURI = parentContext.baseURI; moduleLoadPath = parentContext.moduleLoadPath; } + + XQueryContext getParentContext() { + return parentContext; + } public boolean hasParent() { return true; @@ -101,6 +109,13 @@ module = parentContext.getModule(namespaceURI); return module; } + + /** + * @return iterator over all modules registered in the root context + */ + public Iterator getRootModules() { + return parentContext.getRootModules(); + } /** * Overwritten method: the module will be loaded by the parent context, but Modified: trunk/eXist/src/org/exist/xquery/XQuery.java =================================================================== --- trunk/eXist/src/org/exist/xquery/XQuery.java 2009-01-11 19:05:19 UTC (rev 8499) +++ trunk/eXist/src/org/exist/xquery/XQuery.java 2009-01-12 01:45:28 UTC (rev 8500) @@ -149,19 +149,9 @@ treeParser.getErrorMessage(), treeParser.getLastException()); } + + context.analyzeAndOptimizeIfModulesChanged(expr); - expr.analyze(new AnalyzeContextInfo()); - - if (context.optimizationsEnabled()) { - Optimizer optimizer = new Optimizer(context); - expr.accept(optimizer); - if (optimizer.hasOptimized()) { - context.reset(true); - expr.resetState(true); - expr.analyze(new AnalyzeContextInfo()); - } - } - // Log the query if it is not too large, but avoid // dumping huge queries to the log if (context.getExpressionCount() < 150) { Modified: trunk/eXist/src/org/exist/xquery/XQueryContext.java =================================================================== --- trunk/eXist/src/org/exist/xquery/XQueryContext.java 2009-01-11 19:05:19 UTC (rev 8499) +++ trunk/eXist/src/org/exist/xquery/XQueryContext.java 2009-01-12 01:45:28 UTC (rev 8500) @@ -202,6 +202,12 @@ * Loaded modules. */ protected HashMap modules = new HashMap(); + + /** + * Whether some modules were rebound to new instances since the last time this context's + * query was analyzed. (This assumes that each context is attached to at most one query.) + */ + private boolean modulesChanged = true; /** * The set of statically known documents specified as @@ -1227,12 +1233,18 @@ } /** - * @return iterator over all built-in modules currently - * registered. - */ + * @return iterator over all modules imported into this context + */ public Iterator getModules() { return modules.values().iterator(); } + + /** + * @return iterator over all modules registered in the root context + */ + public Iterator getRootModules() { + return getModules(); + } /** * Get the built-in module registered for the given namespace @@ -1246,12 +1258,33 @@ } public void setModule(String namespaceURI, Module module) { - modules.put(namespaceURI, module); if (!module.isInternalModule()) { ((ModuleContext) ((ExternalModule) module).getContext()).setParentContext(this); } + if (modules.get(namespaceURI) != module) setModulesChanged(); + modules.put(namespaceURI, module); } + void setModulesChanged() { + this.modulesChanged = true; + } + + public void analyzeAndOptimizeIfModulesChanged(PathExpr expr) throws XPathException { + if (modulesChanged) { + expr.analyze(new AnalyzeContextInfo()); + if (optimizationsEnabled()) { + Optimizer optimizer = new Optimizer(this); + expr.accept(optimizer); + if (optimizer.hasOptimized()) { + reset(true); + expr.resetState(true); + expr.analyze(new AnalyzeContextInfo()); + } + } + modulesChanged = false; + } + } + /** * Load a built-in module from the given class name and assign it to the * namespace URI. The specified class should be a subclass of Modified: trunk/eXist/src/org/exist/xquery/functions/util/Compile.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/util/Compile.java 2009-01-11 19:05:19 UTC (rev 8499) +++ trunk/eXist/src/org/exist/xquery/functions/util/Compile.java 2009-01-12 01:45:28 UTC (rev 8500) @@ -68,6 +68,7 @@ return new EmptySequence(); context.pushNamespaceContext(); LOG.debug("eval: " + expr); + // TODO(pkaminsk2): why replicate XQuery.compile here? XQueryLexer lexer = new XQueryLexer(context, new StringReader(expr)); XQueryParser parser = new XQueryParser(lexer); // shares the context of the outer expression Modified: trunk/eXist/src/org/exist/xquery/functions/util/ModuleInfo.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/util/ModuleInfo.java 2009-01-11 19:05:19 UTC (rev 8499) +++ trunk/eXist/src/org/exist/xquery/functions/util/ModuleInfo.java 2009-01-12 01:45:28 UTC (rev 8500) @@ -62,7 +62,7 @@ return new StringValue(module.getDescription()); } else { ValueSequence resultSeq = new ValueSequence(); - for(Iterator i = context.getModules(); i.hasNext(); ) { + for(Iterator i = context.getRootModules(); i.hasNext(); ) { Module module = (Module)i.next(); resultSeq.add(new StringValue(module.getNamespaceURI())); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-01-20 08:57:34
|
Revision: 8508 http://exist.svn.sourceforge.net/exist/?rev=8508&view=rev Author: wolfgang_m Date: 2009-01-20 08:57:29 +0000 (Tue, 20 Jan 2009) Log Message: ----------- [feature] allow serialization filters to be plugged into the output stream generated by the serializer. This is currently used by the versioning extension to inject versioning metadata into the XML document. Modified Paths: -------------- trunk/eXist/src/org/exist/atom/http/WebDAVServlet.java trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java trunk/eXist/src/org/exist/collections/CollectionConfiguration.java trunk/eXist/src/org/exist/collections/triggers/TriggerException.java trunk/eXist/src/org/exist/http/RESTServer.java trunk/eXist/src/org/exist/indexing/AbstractMatchListener.java trunk/eXist/src/org/exist/security/XMLSecurityManager.java trunk/eXist/src/org/exist/storage/serializers/Serializer.java trunk/eXist/src/org/exist/util/Configuration.java Added Paths: ----------- trunk/eXist/src/org/exist/storage/serializers/CustomMatchListener.java trunk/eXist/src/org/exist/storage/serializers/CustomMatchListenerFactory.java Modified: trunk/eXist/src/org/exist/atom/http/WebDAVServlet.java =================================================================== --- trunk/eXist/src/org/exist/atom/http/WebDAVServlet.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/atom/http/WebDAVServlet.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -363,12 +363,12 @@ } catch (ParserConfigurationException ex) { transact.abort(transaction); throw new ServletException("SAX error: "+ex.getMessage(),ex); + } catch (TriggerException ex) { + transact.abort(transaction); + throw new ServletException("Trigger failed: "+ex.getMessage(),ex); } catch (SAXException ex) { transact.abort(transaction); throw new ServletException("SAX error: "+ex.getMessage(),ex); - } catch (TriggerException ex) { - transact.abort(transaction); - throw new ServletException("Trigger failed: "+ex.getMessage(),ex); } catch (LockException ex) { transact.abort(transaction); throw new ServletException("Cannot acquire write lock.",ex); Modified: trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java =================================================================== --- trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -297,12 +297,12 @@ } catch (IOException ex) { transact.abort(transaction); throw new EXistException("IO error: "+ex.getMessage(),ex); + } catch (TriggerException ex) { + transact.abort(transaction); + throw new EXistException("Trigger failed: "+ex.getMessage(),ex); } catch (SAXException ex) { transact.abort(transaction); throw new EXistException("SAX error: "+ex.getMessage(),ex); - } catch (TriggerException ex) { - transact.abort(transaction); - throw new EXistException("Trigger failed: "+ex.getMessage(),ex); } catch (LockException ex) { transact.abort(transaction); throw new EXistException("Cannot acquire write lock.",ex); @@ -400,6 +400,9 @@ throw new BadRequestException("Parsing exception at " + e.getLineNumber() + "/" + e.getColumnNumber() + ": " + e.toString()); + } catch (TriggerException e) { + transact.abort(transaction); + throw new PermissionDeniedException(e.getMessage()); } catch (SAXException e) { transact.abort(transaction); Exception o = e.getException(); @@ -407,9 +410,6 @@ o = e; throw new BadRequestException("Parsing exception: " + o.getMessage()); - } catch (TriggerException e) { - transact.abort(transaction); - throw new PermissionDeniedException(e.getMessage()); } catch (LockException e) { transact.abort(transaction); throw new PermissionDeniedException(e.getMessage()); @@ -620,6 +620,9 @@ throw new BadRequestException("Parsing exception at " + e.getLineNumber() + "/" + e.getColumnNumber() + ": " + e.toString()); + } catch (TriggerException e) { + transact.abort(transaction); + throw new PermissionDeniedException(e.getMessage()); } catch (SAXException e) { transact.abort(transaction); Exception o = e.getException(); @@ -627,9 +630,6 @@ o = e; throw new BadRequestException("Parsing exception: " + o.getMessage()); - } catch (TriggerException e) { - transact.abort(transaction); - throw new PermissionDeniedException(e.getMessage()); } catch (LockException e) { transact.abort(transaction); throw new PermissionDeniedException(e.getMessage()); Modified: trunk/eXist/src/org/exist/collections/CollectionConfiguration.java =================================================================== --- trunk/eXist/src/org/exist/collections/CollectionConfiguration.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/collections/CollectionConfiguration.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -249,7 +249,15 @@ public TriggerConfig getTriggerConfiguration(int eventType) { return triggers[eventType]; } - + + public boolean triggerRegistered(Class triggerClass) { + for (int i = 0; i < triggers.length; i++) { + if (triggers[i] != null && triggers[i].getTriggerClass() == triggerClass) + return true; + } + return false; + } + private void createTrigger(DBBroker broker, Element node, boolean testConfig) throws CollectionConfigurationException { Modified: trunk/eXist/src/org/exist/collections/triggers/TriggerException.java =================================================================== --- trunk/eXist/src/org/exist/collections/triggers/TriggerException.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/collections/triggers/TriggerException.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -23,10 +23,12 @@ */ package org.exist.collections.triggers; +import org.xml.sax.SAXException; + /** * @author wolf */ -public class TriggerException extends Exception { +public class TriggerException extends SAXException { /** * @@ -45,7 +47,7 @@ /** * @param cause */ - public TriggerException(Throwable cause) { + public TriggerException(Exception cause) { super(cause); } @@ -53,7 +55,7 @@ * @param message * @param cause */ - public TriggerException(String message, Throwable cause) { + public TriggerException(String message, Exception cause) { super(message, cause); } Modified: trunk/eXist/src/org/exist/http/RESTServer.java =================================================================== --- trunk/eXist/src/org/exist/http/RESTServer.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/http/RESTServer.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -937,6 +937,9 @@ throw new BadRequestException("Parsing exception at " + e.getLineNumber() + "/" + e.getColumnNumber() + ": " + e.toString()); + } catch (TriggerException e) { + transact.abort(transaction); + throw new PermissionDeniedException(e.getMessage()); } catch (SAXException e) { transact.abort(transaction); Exception o = e.getException(); @@ -947,9 +950,6 @@ } catch (EXistException e) { transact.abort(transaction); throw new BadRequestException("Internal error: " + e.getMessage()); - } catch (TriggerException e) { - transact.abort(transaction); - throw new PermissionDeniedException(e.getMessage()); } catch (LockException e) { transact.abort(transaction); throw new PermissionDeniedException(e.getMessage()); Modified: trunk/eXist/src/org/exist/indexing/AbstractMatchListener.java =================================================================== --- trunk/eXist/src/org/exist/indexing/AbstractMatchListener.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/indexing/AbstractMatchListener.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -37,7 +37,8 @@ public void setCurrentNode(StoredNode node) { this.currentNode = node; - getNextInChain().setCurrentNode(node); + if (nextListener != null) + getNextInChain().setCurrentNode(node); } protected StoredNode getCurrentNode() { Modified: trunk/eXist/src/org/exist/security/XMLSecurityManager.java =================================================================== --- trunk/eXist/src/org/exist/security/XMLSecurityManager.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/security/XMLSecurityManager.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -383,12 +383,12 @@ broker.saveCollection(transaction, doc.getCollection()); } catch (IOException e) { throw new EXistException(e.getMessage()); + } catch (TriggerException e) { + throw new EXistException(e.getMessage()); } catch (SAXException e) { throw new EXistException(e.getMessage()); } catch (PermissionDeniedException e) { throw new EXistException(e.getMessage()); - } catch (TriggerException e) { - throw new EXistException(e.getMessage()); } catch (LockException e) { throw new EXistException(e.getMessage()); } Added: trunk/eXist/src/org/exist/storage/serializers/CustomMatchListener.java =================================================================== --- trunk/eXist/src/org/exist/storage/serializers/CustomMatchListener.java (rev 0) +++ trunk/eXist/src/org/exist/storage/serializers/CustomMatchListener.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -0,0 +1,29 @@ +package org.exist.storage.serializers; + +import org.exist.indexing.AbstractMatchListener; +import org.exist.storage.DBBroker; + +/** + * Base class for custom filters which can be applied to the serialization + * stream generated by the {@link org.exist.storage.serializers.Serializer}. + * Custom filters can be registered in conf.xml. + * + * TODO: MatchListener should probably be renamed into SerializationFilter + * or similar. + */ +public abstract class CustomMatchListener extends AbstractMatchListener { + + private DBBroker broker; + + protected void reset() { + setCurrentNode(null); + } + + protected void setBroker(DBBroker broker) { + this.broker = broker; + } + + protected DBBroker getBroker() { + return broker; + } +} \ No newline at end of file Added: trunk/eXist/src/org/exist/storage/serializers/CustomMatchListenerFactory.java =================================================================== --- trunk/eXist/src/org/exist/storage/serializers/CustomMatchListenerFactory.java (rev 0) +++ trunk/eXist/src/org/exist/storage/serializers/CustomMatchListenerFactory.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -0,0 +1,63 @@ +package org.exist.storage.serializers; + +import org.apache.log4j.Logger; +import org.exist.indexing.MatchListener; +import org.exist.storage.DBBroker; +import org.exist.util.Configuration; + +import java.util.List; + +/** + * Configures and maintains a list of {@link org.exist.storage.serializers.CustomMatchListener}. + * There will be one CustomMatchListenerFactory for every {@link org.exist.storage.serializers.Serializer} + * instance. + */ +public class CustomMatchListenerFactory { + + private final static Logger LOG = Logger.getLogger(CustomMatchListenerFactory.class); + + public final static String CONFIGURATION_ELEMENT = "custom-filter"; + public final static String CONFIGURATION_ATTR_CLASS = "class"; + public final static String CONFIG_MATCH_LISTENERS = "serialization.custom-match-listeners"; + + private CustomMatchListener first = null; + private CustomMatchListener last = null; + + public CustomMatchListenerFactory(DBBroker broker, Configuration config) { + List classes = (List) config.getProperty(CONFIG_MATCH_LISTENERS); + if (classes == null) + return; + CustomMatchListener listener; + for (int i = 0; i < classes.size(); i++) { + try { + Class listenerClass = Class.forName(classes.get(i).toString()); + if (CustomMatchListener.class.isAssignableFrom(listenerClass)) { + listener = (CustomMatchListener) listenerClass.newInstance(); + listener.setBroker(broker); + if (first == null) { + first = listener; + last = listener; + } else { + last.setNextInChain(listener); + last = listener; + } + } else + LOG.error("Failed to instantiate class " + listenerClass.getName() + + ": it is not a subclass of CustomMatchListener"); + } catch (Exception e) { + LOG.error("An exception was caught while trying to instantiate a custom MatchListener: " + + e.getMessage(), e); + } + } + } + + public MatchListener getFirst() { + if (first != null) + first.reset(); + return first; + } + + public MatchListener getLast() { + return last; + } +} \ No newline at end of file Modified: trunk/eXist/src/org/exist/storage/serializers/Serializer.java =================================================================== --- trunk/eXist/src/org/exist/storage/serializers/Serializer.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/storage/serializers/Serializer.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -164,6 +164,7 @@ protected Templates templates = null; protected TransformerHandler xslHandler = null; protected XIncludeFilter xinclude; + protected CustomMatchListenerFactory customMatchListeners; protected Receiver receiver = null; protected SAXSerializer xmlout = null; protected LexicalHandler lexicalHandler = null; @@ -173,6 +174,7 @@ this.broker = broker; factory = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); xinclude = new XIncludeFilter(this); + customMatchListeners = new CustomMatchListenerFactory(broker, config); receiver = xinclude; String option = (String) config.getProperty(PROPERTY_ENABLE_XSL); @@ -415,7 +417,8 @@ if (templates != null) applyXSLHandler(writer); else - setPrettyPrinter(writer, outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION, "yes").equals("no"), null); //setPrettyPrinter(writer, false); + setPrettyPrinter(writer, outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION, "yes").equals("no"), + null, true); //setPrettyPrinter(writer, false); serializeToReceiver(doc, true); releasePrettyPrinter(); @@ -432,7 +435,7 @@ applyXSLHandler(out); else setPrettyPrinter(out, outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION, "yes").equals("no"), - n.getImplementationType() == NodeValue.PERSISTENT_NODE ? (NodeProxy)n : null); //setPrettyPrinter(out, false); + n.getImplementationType() == NodeValue.PERSISTENT_NODE ? (NodeProxy)n : null, false); //setPrettyPrinter(out, false); serializeToReceiver(n, true); releasePrettyPrinter(); return out.toString(); @@ -455,7 +458,8 @@ if (templates != null) applyXSLHandler(out); else - setPrettyPrinter(out, outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION, "yes").equals("no"), p); //setPrettyPrinter(out, false); + setPrettyPrinter(out, outputProperties.getProperty(OutputKeys.OMIT_XML_DECLARATION, "yes").equals("no"), + p, false); //setPrettyPrinter(out, false); serializeToReceiver(p, false); releasePrettyPrinter(); return out.toString(); @@ -540,7 +544,7 @@ throw new SAXNotRecognizedException(name); } - protected void setPrettyPrinter(Writer writer, boolean xmlDecl, NodeProxy root) { + protected void setPrettyPrinter(Writer writer, boolean xmlDecl, NodeProxy root, boolean applyFilters) { outputProperties.setProperty( OutputKeys.OMIT_XML_DECLARATION, xmlDecl ? "no" : "yes"); @@ -561,6 +565,10 @@ receiver = listener; } } + if (root == null && applyFilters && customMatchListeners.getFirst() != null) { + customMatchListeners.getLast().setNextInChain(receiver); + receiver = customMatchListeners.getFirst(); + } } protected Receiver setupMatchListeners(NodeProxy p) { @@ -700,7 +708,7 @@ xslHandler.getTransformer().setParameter(param, value); } - protected void setXSLHandler(NodeProxy root) { + protected void setXSLHandler(NodeProxy root, boolean applyFilters) { if (templates != null && xslHandler != null) { SAXResult result = new SAXResult(); boolean processXInclude = @@ -734,6 +742,10 @@ receiver = listener; } } + if (applyFilters && root == null && customMatchListeners.getFirst() != null) { + customMatchListeners.getLast().setNextInChain(receiver); + receiver = customMatchListeners.getFirst(); + } } public void toSAX(DocumentImpl doc) throws SAXException { @@ -751,7 +763,7 @@ } catch (TransformerConfigurationException e) { throw new SAXException(e.getMessage(), e); } - setXSLHandler(null); + setXSLHandler(null, true); serializeToReceiver( doc, getProperty(GENERATE_DOC_EVENTS, "false").equals("true")); @@ -763,7 +775,7 @@ } catch (TransformerConfigurationException e) { throw new SAXException(e.getMessage(), e); } - setXSLHandler(n.getImplementationType() == NodeValue.PERSISTENT_NODE ? (NodeProxy)n : null); + setXSLHandler(n.getImplementationType() == NodeValue.PERSISTENT_NODE ? (NodeProxy)n : null, false); serializeToReceiver( n, getProperty(GENERATE_DOC_EVENTS, "false").equals("true")); @@ -775,7 +787,7 @@ } catch (TransformerConfigurationException e) { throw new SAXException(e.getMessage(), e); } - setXSLHandler(p); + setXSLHandler(p, false); if (p.getNodeId() == NodeId.DOCUMENT_NODE) { serializeToReceiver(p.getDocument(), getProperty(GENERATE_DOC_EVENTS, "false").equals("true")); } else { @@ -802,7 +814,7 @@ } catch (TransformerConfigurationException e) { throw new SAXException(e.getMessage(), e); } - setXSLHandler(null); + setXSLHandler(null, false); AttrList attrs = new AttrList(); attrs.addAttribute(ATTR_HITS_QNAME, Integer.toString(seq.getItemCount())); attrs.addAttribute(ATTR_START_QNAME, Integer.toString(start)); Modified: trunk/eXist/src/org/exist/util/Configuration.java =================================================================== --- trunk/eXist/src/org/exist/util/Configuration.java 2009-01-19 18:01:25 UTC (rev 8507) +++ trunk/eXist/src/org/exist/util/Configuration.java 2009-01-20 08:57:29 UTC (rev 8508) @@ -45,6 +45,7 @@ import org.exist.storage.XQueryPool; import org.exist.storage.journal.Journal; import org.exist.storage.serializers.Serializer; +import org.exist.storage.serializers.CustomMatchListenerFactory; import org.exist.storage.txn.TransactionManager; import org.exist.validation.GrammarPool; import org.exist.validation.resolver.eXistXMLCatalogResolver; @@ -549,8 +550,26 @@ config.put(Serializer.PROPERTY_TAG_MATCHING_ATTRIBUTES, tagAttributeMatches); LOG.debug(Serializer.PROPERTY_TAG_MATCHING_ATTRIBUTES + ": " + config.get(Serializer.PROPERTY_TAG_MATCHING_ATTRIBUTES)); } + + NodeList nlFilters = serializer.getElementsByTagName(CustomMatchListenerFactory.CONFIGURATION_ELEMENT); + if (nlFilters == null) + return; + + List filters = new ArrayList(nlFilters.getLength()); + for (int i = 0; i < nlFilters.getLength(); i++) { + Element filterElem = (Element) nlFilters.item(i); + String filterClass = filterElem.getAttribute(CustomMatchListenerFactory.CONFIGURATION_ATTR_CLASS); + if (filterClass != null) { + filters.add(filterClass); + LOG.debug(CustomMatchListenerFactory.CONFIG_MATCH_LISTENERS + ": " + filterClass); + } else { + LOG.warn("Configuration element " + CustomMatchListenerFactory.CONFIGURATION_ELEMENT + + " needs an attribute 'class'"); + } + } + config.put(CustomMatchListenerFactory.CONFIG_MATCH_LISTENERS, filters); } - + /** * Reads the scheduler configuration */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-01-26 13:14:57
|
Revision: 8531 http://exist.svn.sourceforge.net/exist/?rev=8531&view=rev Author: wolfgang_m Date: 2009-01-26 11:36:54 +0000 (Mon, 26 Jan 2009) Log Message: ----------- [bugfix] Applied patch 2537381: Fix for remote zero sized binary resources. Modified Paths: -------------- trunk/eXist/src/org/exist/backup/Restore.java trunk/eXist/src/org/exist/xmldb/RemoteCollection.java Modified: trunk/eXist/src/org/exist/backup/Restore.java =================================================================== --- trunk/eXist/src/org/exist/backup/Restore.java 2009-01-25 11:25:52 UTC (rev 8530) +++ trunk/eXist/src/org/exist/backup/Restore.java 2009-01-26 11:36:54 UTC (rev 8531) @@ -278,7 +278,7 @@ return; } } - InputSource is=contents.getInputSource(filename); + EXistInputSource is=contents.getInputSource(filename); try { if (dialog != null && current instanceof Observable) { ((Observable) current).addObserver(dialog.getObserver()); @@ -290,7 +290,11 @@ if (mimetype != null) ((EXistResource)res).setMimeType(mimetype); - res.setContent(is); + if(is.getByteStreamLength() > 0) { + res.setContent(is); + } else { + res.setContent(""); + } // Restoring name Modified: trunk/eXist/src/org/exist/xmldb/RemoteCollection.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/RemoteCollection.java 2009-01-25 11:25:52 UTC (rev 8530) +++ trunk/eXist/src/org/exist/xmldb/RemoteCollection.java 2009-01-26 11:36:54 UTC (rev 8531) @@ -601,6 +601,15 @@ params.add(new Integer(len)); fileName = (String) rpcClient.execute("uploadCompressed", params); } + // Zero length stream? Let's get a fileName! + if(fileName==null) { + compressed=Compressor.compress(new byte[0],0); + params = new ArrayList(3); + params.add(compressed); + params.add(new Integer(0)); + fileName = (String) rpcClient.execute("uploadCompressed", params); + } + params = new ArrayList(6); params.add(fileName); try { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-02-04 12:16:20
|
Revision: 8557 http://exist.svn.sourceforge.net/exist/?rev=8557&view=rev Author: wolfgang_m Date: 2009-02-04 12:16:11 +0000 (Wed, 04 Feb 2009) Log Message: ----------- [feature] Java admin client now remembers last directory for backup/restore and upload. Modified Paths: -------------- trunk/eXist/src/org/exist/backup/CreateBackupDialog.java trunk/eXist/src/org/exist/client/ClientFrame.java Modified: trunk/eXist/src/org/exist/backup/CreateBackupDialog.java =================================================================== --- trunk/eXist/src/org/exist/backup/CreateBackupDialog.java 2009-02-03 21:37:43 UTC (rev 8556) +++ trunk/eXist/src/org/exist/backup/CreateBackupDialog.java 2009-02-04 12:16:11 UTC (rev 8557) @@ -28,21 +28,23 @@ JComboBox collections; JTextField backupTarget; + File backupDir; String uri; String user; String passwd; - public CreateBackupDialog(String uri, String user, String passwd, String backupDir) + public CreateBackupDialog(String uri, String user, String passwd, File backupDir) throws HeadlessException { super(false); this.uri = uri; this.user = user; this.passwd = passwd; - setupComponents(backupDir); + this.backupDir = backupDir; + setupComponents(); setSize(new Dimension(350, 200)); } - private void setupComponents(String backupDir) { + private void setupComponents() { GridBagLayout grid = new GridBagLayout(); setLayout(grid); GridBagConstraints c = new GridBagConstraints(); @@ -77,7 +79,7 @@ grid.setConstraints(label, c); add(label); - backupTarget = new JTextField(backupDir, 40); + backupTarget = new JTextField(new File(backupDir, "eXist-backup.zip").getAbsolutePath(), 40); c.gridx = 1; c.gridy = 1; c.anchor = GridBagConstraints.EAST; @@ -106,13 +108,14 @@ JFileChooser chooser = new JFileChooser(); chooser.setMultiSelectionEnabled(false); chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - chooser.addChoosableFileFilter(new MimeTypeFileFilter("application/zip")); - chooser.setSelectedFile(new File("eXist-backup.zip")); - chooser.setCurrentDirectory(null); + chooser.addChoosableFileFilter(new MimeTypeFileFilter("application/zip")); + chooser.setSelectedFile(new File("eXist-backup.zip")); + chooser.setCurrentDirectory(backupDir); if (chooser.showDialog(this, Messages.getString("CreateBackupDialog.5")) == JFileChooser.APPROVE_OPTION) { backupTarget.setText(chooser.getSelectedFile().getAbsolutePath()); + backupDir = chooser.getCurrentDirectory(); } } @@ -145,4 +148,8 @@ public String getBackupTarget() { return backupTarget.getText(); } + + public File getBackupDir() { + return backupDir; + } } Modified: trunk/eXist/src/org/exist/client/ClientFrame.java =================================================================== --- trunk/eXist/src/org/exist/client/ClientFrame.java 2009-02-03 21:37:43 UTC (rev 8556) +++ trunk/eXist/src/org/exist/client/ClientFrame.java 2009-02-04 12:16:11 UTC (rev 8557) @@ -55,6 +55,7 @@ import java.util.Date; import java.util.List; import java.util.Properties; +import java.util.prefs.Preferences; import javax.swing.BorderFactory; import javax.swing.ImageIcon; @@ -156,7 +157,8 @@ private XmldbURI path = null; private ProcessThread process = new ProcessThread(); private Properties properties; - + private Preferences preferences; + /** * @throws java.awt.HeadlessException */ @@ -177,6 +179,8 @@ process.start(); shell.requestFocus(); + + preferences = Preferences.userNodeForPackage(ClientFrame.class); } private void setupComponents() { @@ -1071,13 +1075,15 @@ private void uploadAction(ActionEvent ev) { // TODO store last file choose in properties - String dir = properties.getProperty(Messages.getString("ClientFrame.145"), SingleInstanceConfiguration.getPath()); //$NON-NLS-1$ - JFileChooser chooser = new JFileChooser(dir); + JFileChooser chooser = new JFileChooser(preferences.get("directory.last", System.getProperty("user.dir"))); chooser.setMultiSelectionEnabled(true); chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); chooser.addChoosableFileFilter(new BinaryFileFilter()); chooser.addChoosableFileFilter(new XMLFileFilter()); if (chooser.showDialog(this, Messages.getString("ClientFrame.146")) == JFileChooser.APPROVE_OPTION) { //$NON-NLS-1$ + // remember directory in preferences + preferences.put("directory.last", chooser.getCurrentDirectory().getAbsolutePath()); + final File[] files = chooser.getSelectedFiles(); if (files.length > 0) { new Thread() { @@ -1093,9 +1099,6 @@ } }.start(); } - File selectedDir = chooser.getCurrentDirectory(); - properties - .setProperty("working-dir", selectedDir.getAbsolutePath()); //$NON-NLS-1$ } } @@ -1119,11 +1122,11 @@ properties.getProperty("uri", "xmldb:exist://"), properties.getProperty("user", "admin"), properties.getProperty("password", null), - properties.getProperty("backup-dir", System.getProperty("user.home") - + File.separatorChar + "eXist-backup.zip")); + new File(preferences.get("directory.backup", System.getProperty("user.home")))); if (JOptionPane.showOptionDialog(this, dialog, Messages.getString("ClientFrame.157"), JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null) == JOptionPane.YES_OPTION) { + String collection = dialog.getCollection(); String backuptarget = dialog.getBackupTarget(); @@ -1168,7 +1171,7 @@ private void restoreAction(ActionEvent ev) { - JFileChooser chooser = new JFileChooser(); + JFileChooser chooser = new JFileChooser(preferences.get("directory.backup", System.getProperty("user.dir"))); chooser.setMultiSelectionEnabled(false); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.addChoosableFileFilter(new BackupContentsFilter()); @@ -1177,6 +1180,8 @@ //chooser.setSelectedFile(new File("eXist-backup.zip")); if (chooser.showDialog(null, Messages.getString("ClientFrame.169")) == JFileChooser.APPROVE_OPTION) { //$NON-NLS-1$ + File f = chooser.getSelectedFile(); + preferences.put("directory.backup", chooser.getCurrentDirectory().getAbsolutePath()); JPanel askPass = new JPanel(new BorderLayout()); askPass.add(new JLabel(Messages.getString("ClientFrame.170")), BorderLayout.NORTH); //$NON-NLS-1$ JPasswordField passInput = new JPasswordField(25); @@ -1185,7 +1190,6 @@ JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, null, null) == JOptionPane.YES_OPTION) { String newDbaPass = passInput.getPassword().length == 0 ? null : new String(passInput.getPassword()); - File f = chooser.getSelectedFile(); String restoreFile = f.getAbsolutePath(); try { Restore restore = new Restore(properties.getProperty("user", //$NON-NLS-1$ @@ -1226,18 +1230,17 @@ if (desc.isCollection()) return; - String workDir = properties.getProperty("working-dir", System - .getProperty("user.dir")); - JFileChooser chooser = new JFileChooser(workDir); + JFileChooser chooser = new JFileChooser(preferences.get("directory.last", System.getProperty("user.dir"))); chooser.setMultiSelectionEnabled(false); chooser.setFileSelectionMode(JFileChooser.FILES_ONLY); chooser.setSelectedFile(new File(desc.getName().toString())); if (chooser.showDialog(this, "Select file for export") == JFileChooser.APPROVE_OPTION) { + preferences.put("directory.last", chooser.getCurrentDirectory().getAbsolutePath()); File file = chooser.getSelectedFile(); if (file.exists() && JOptionPane.showConfirmDialog(this, - "File exists. Overwrite?", "Overwrite?", - JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) + "File exists. Overwrite?", "Overwrite?", + JOptionPane.YES_NO_OPTION) == JOptionPane.NO_OPTION) return; Resource resource; FileOutputStream os; @@ -1251,7 +1254,7 @@ .getResource(desc.getName().toString()); os = new FileOutputStream(file); if (resource.getResourceType().equals("BinaryResource")) { - ((ExtendedResource)resource).getContentIntoAStream(os); + ((ExtendedResource) resource).getContentIntoAStream(os); } else { writer = new BufferedWriter(new OutputStreamWriter(os, @@ -1421,7 +1424,7 @@ e.printStackTrace(); } } - + private void close() { setVisible(false); dispose(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-02-10 14:28:36
|
Revision: 8571 http://exist.svn.sourceforge.net/exist/?rev=8571&view=rev Author: wolfgang_m Date: 2009-02-10 14:28:32 +0000 (Tue, 10 Feb 2009) Log Message: ----------- [bugfix] changed DocumentBuilderReceiver to preserve namespace declarations even if those namespaces are never used in the document. DocumentBuilderReceiver is used by functions such as transform:transform(). This fixes bug report #2564004. Modified Paths: -------------- trunk/eXist/src/org/exist/memtree/DocumentBuilderReceiver.java trunk/eXist/src/org/exist/xquery/functions/FunDocAvailable.java trunk/eXist/src/org/exist/xquery/functions/request/GetData.java trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java trunk/eXist/src/org/exist/xquery/functions/util/Expand.java Modified: trunk/eXist/src/org/exist/memtree/DocumentBuilderReceiver.java =================================================================== --- trunk/eXist/src/org/exist/memtree/DocumentBuilderReceiver.java 2009-02-09 22:22:39 UTC (rev 8570) +++ trunk/eXist/src/org/exist/memtree/DocumentBuilderReceiver.java 2009-02-10 14:28:32 UTC (rev 8571) @@ -34,8 +34,13 @@ import org.xml.sax.ContentHandler; import org.xml.sax.Locator; import org.xml.sax.SAXException; +import org.xml.sax.helpers.NamespaceSupport; import org.xml.sax.ext.LexicalHandler; +import java.util.Map; +import java.util.HashMap; +import java.util.Iterator; + /** * Builds an in-memory DOM tree from SAX {@link org.exist.util.serializer.Receiver} * events. @@ -45,16 +50,24 @@ public class DocumentBuilderReceiver implements ContentHandler, LexicalHandler, Receiver { private MemTreeBuilder builder = null; - + + private Map namespaces = null; + private boolean explicitNSDecl = false; + public DocumentBuilderReceiver() { super(); } public DocumentBuilderReceiver(MemTreeBuilder builder) { - super(); - this.builder = builder; + this(builder, false); } - + + public DocumentBuilderReceiver(MemTreeBuilder builder, boolean declareNamespaces) { + super(); + this.builder = builder; + this.explicitNSDecl = declareNamespaces; + } + public Document getDocument() { return builder.getDocument(); } @@ -62,7 +75,7 @@ public XQueryContext getContext() { return builder.getContext(); } - + /* (non-Javadoc) * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) */ @@ -89,7 +102,12 @@ /* (non-Javadoc) * @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String) */ - public void startPrefixMapping(String arg0, String arg1) throws SAXException { + public void startPrefixMapping(String prefix, String namespace) throws SAXException { + if (!explicitNSDecl) + return; + if (namespaces == null) + namespaces = new HashMap(); + namespaces.put(prefix, namespace); } /* (non-Javadoc) @@ -101,13 +119,25 @@ /* (non-Javadoc) * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) */ - public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) + public void startElement(String namespaceURI, String localName, String qName, Attributes attrs) throws SAXException { builder.startElement(namespaceURI, localName, qName, attrs); - } + declareNamespaces(); + } - public void startElement(QName qname, AttrList attribs) { + private void declareNamespaces() { + if (explicitNSDecl && namespaces != null) { + for (Iterator i = namespaces.entrySet().iterator(); i.hasNext();) { + Map.Entry entry = (Map.Entry) i.next(); + builder.namespaceNode((String) entry.getKey(), (String) entry.getValue()); + } + namespaces.clear(); + } + } + + public void startElement(QName qname, AttrList attribs) { builder.startElement(qname, null); + declareNamespaces(); if(attribs != null) { for (int i = 0; i < attribs.getLength(); i++) { builder.addAttribute(attribs.getQName(i), attribs.getValue(i)); Modified: trunk/eXist/src/org/exist/xquery/functions/FunDocAvailable.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/FunDocAvailable.java 2009-02-09 22:22:39 UTC (rev 8570) +++ trunk/eXist/src/org/exist/xquery/functions/FunDocAvailable.java 2009-02-10 14:28:32 UTC (rev 8571) @@ -82,7 +82,7 @@ result = BooleanValue.valueOf(DocUtils.isDocumentAvailable(this.context, path)); } catch (Exception e) { - throw new XPathException(getASTNode(), e.getMessage()); + throw new XPathException(getASTNode(), e.getMessage(), e); } } Modified: trunk/eXist/src/org/exist/xquery/functions/request/GetData.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/request/GetData.java 2009-02-09 22:22:39 UTC (rev 8570) +++ trunk/eXist/src/org/exist/xquery/functions/request/GetData.java 2009-02-10 14:28:32 UTC (rev 8571) @@ -168,7 +168,7 @@ SAXParser parser = factory.newSAXParser(); XMLReader reader = parser.getXMLReader(); MemTreeBuilder builder = context.getDocumentBuilder(); - DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder); + DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder, true); reader.setContentHandler(receiver); reader.parse(src); Document doc = receiver.getDocument(); Modified: trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java 2009-02-09 22:22:39 UTC (rev 8570) +++ trunk/eXist/src/org/exist/xquery/functions/transform/Transform.java 2009-02-10 14:28:32 UTC (rev 8571) @@ -199,7 +199,7 @@ ValueSequence seq = new ValueSequence(); context.pushDocumentContext(); MemTreeBuilder builder = context.getDocumentBuilder(); - DocumentBuilderReceiver builderReceiver = new DocumentBuilderReceiver(builder); + DocumentBuilderReceiver builderReceiver = new DocumentBuilderReceiver(builder, true); SAXResult result = new SAXResult(builderReceiver); result.setLexicalHandler(builderReceiver); //preserve comments etc... from xslt output handler.setResult(result); Modified: trunk/eXist/src/org/exist/xquery/functions/util/Expand.java =================================================================== --- trunk/eXist/src/org/exist/xquery/functions/util/Expand.java 2009-02-09 22:22:39 UTC (rev 8570) +++ trunk/eXist/src/org/exist/xquery/functions/util/Expand.java 2009-02-10 14:28:32 UTC (rev 8571) @@ -97,7 +97,7 @@ try { InMemoryNodeSet result = new InMemoryNodeSet(); MemTreeBuilder builder = context.getDocumentBuilder(); - DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder); + DocumentBuilderReceiver receiver = new DocumentBuilderReceiver(builder, true); for (SequenceIterator i = args[0].iterate(); i.hasNext(); ) { int nodeNr = builder.getDocument().getLastNode(); NodeValue next = (NodeValue) i.nextItem(); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-02-14 16:31:35
|
Revision: 8583 http://exist.svn.sourceforge.net/exist/?rev=8583&view=rev Author: wolfgang_m Date: 2009-02-14 16:31:31 +0000 (Sat, 14 Feb 2009) Log Message: ----------- [feature] added configuration option to automatically run a consistency check if errors were detected during crash recovery. Port of rev 8328 Revision Links: -------------- http://exist.svn.sourceforge.net/exist/?rev=8328&view=rev Modified Paths: -------------- trunk/eXist/src/org/exist/management/impl/JMXAgent.java trunk/eXist/src/org/exist/storage/BrokerPool.java trunk/eXist/src/org/exist/util/Configuration.java Modified: trunk/eXist/src/org/exist/management/impl/JMXAgent.java =================================================================== --- trunk/eXist/src/org/exist/management/impl/JMXAgent.java 2009-02-14 16:28:41 UTC (rev 8582) +++ trunk/eXist/src/org/exist/management/impl/JMXAgent.java 2009-02-14 16:31:31 UTC (rev 8583) @@ -169,7 +169,8 @@ try { ObjectName name = new ObjectName("org.exist.management." + instance.getId() + ".tasks:type=SanityReport"); SanityReport report = (SanityReport) beanInstances.get(name); - report.updateErrors(errorList, startTime); + if (report != null) + report.updateErrors(errorList, startTime); } catch (MalformedObjectNameException e) { LOG.warn("Problem calling mbean: " + e.getMessage(), e); } Modified: trunk/eXist/src/org/exist/storage/BrokerPool.java =================================================================== --- trunk/eXist/src/org/exist/storage/BrokerPool.java 2009-02-14 16:28:41 UTC (rev 8582) +++ trunk/eXist/src/org/exist/storage/BrokerPool.java 2009-02-14 16:31:31 UTC (rev 8583) @@ -20,6 +20,19 @@ */ package org.exist.storage; +import java.io.File; +import java.io.IOException; +import java.text.NumberFormat; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.TreeMap; +import java.util.Vector; +import java.util.Properties; + import org.apache.log4j.Logger; import org.exist.EXistException; import org.exist.collections.CollectionCache; @@ -89,6 +102,7 @@ public static final String DATA_DIR_ATTRIBUTE = "files"; //TODO : move elsewhere ? public final static String RECOVERY_ENABLED_ATTRIBUTE = "enabled"; + public final static String RECOVERY_POST_RECOVERY_CHECK = "consistency-check"; //TODO : move elsewhere ? public final static String COLLECTION_CACHE_SIZE_ATTRIBUTE = "collectionCacheSize"; public final static String MIN_CONNECTIONS_ATTRIBUTE = "min"; @@ -108,6 +122,7 @@ public final static String DEFAULT_SECURITY_CLASS = "org.exist.security.XMLSecurityManager"; public final static String PROPERTY_SECURITY_CLASS = "db-connection.security.class"; public final static String PROPERTY_RECOVERY_ENABLED = "db-connection.recovery.enabled"; + public final static String PROPERTY_RECOVERY_CHECK = "db-connection.recovery.consistency-check"; public final static String PROPERTY_SYSTEM_TASK_CONFIG = "db-connection.system-task-config"; //TODO : inline the class ? or... make it configurable ? @@ -796,6 +811,14 @@ } catch (PermissionDeniedException e) { LOG.warn("Error during recovery: " + e.getMessage(), e); } + if (((Boolean)conf.getProperty(PROPERTY_RECOVERY_CHECK)).booleanValue()) { + ConsistencyCheckTask task = new ConsistencyCheckTask(); + Properties props = new Properties(); + props.setProperty("backup", "no"); + props.setProperty("output", "sanity"); + task.configure(conf, props); + task.execute(broker); + } } //OK : the DB is repaired; let's make a few RW operations Modified: trunk/eXist/src/org/exist/util/Configuration.java =================================================================== --- trunk/eXist/src/org/exist/util/Configuration.java 2009-02-14 16:28:41 UTC (rev 8582) +++ trunk/eXist/src/org/exist/util/Configuration.java 2009-02-14 16:31:31 UTC (rev 8583) @@ -886,6 +886,14 @@ } setProperty(TransactionManager.PROPERTY_RECOVERY_FORCE_RESTART, new Boolean(value)); LOG.debug(TransactionManager.PROPERTY_RECOVERY_FORCE_RESTART + ": " + config.get(TransactionManager.PROPERTY_RECOVERY_FORCE_RESTART)); + + option = recovery.getAttribute(BrokerPool.RECOVERY_POST_RECOVERY_CHECK); + value = false; + if (option != null) { + value = option.equals("yes"); + } + setProperty(BrokerPool.PROPERTY_RECOVERY_CHECK, new Boolean(value)); + LOG.debug(BrokerPool.PROPERTY_RECOVERY_CHECK + ": " + config.get(BrokerPool.PROPERTY_RECOVERY_CHECK)); } private void configurePermissions(Element defaultPermission) throws DatabaseConfigurationException { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-02-15 16:33:35
|
Revision: 8603 http://exist.svn.sourceforge.net/exist/?rev=8603&view=rev Author: wolfgang_m Date: 2009-02-15 16:33:31 +0000 (Sun, 15 Feb 2009) Log Message: ----------- [bugfix] disable validation while actually storing a document. The document was already validated before. This will also fix problems with default element and attribute values defined in a schema: those should *not* be stored into the db. Modified Paths: -------------- trunk/eXist/src/org/exist/Indexer.java trunk/eXist/src/org/exist/collections/Collection.java Modified: trunk/eXist/src/org/exist/Indexer.java =================================================================== --- trunk/eXist/src/org/exist/Indexer.java 2009-02-15 12:11:34 UTC (rev 8602) +++ trunk/eXist/src/org/exist/Indexer.java 2009-02-15 16:33:31 UTC (rev 8603) @@ -131,7 +131,7 @@ * a second time. */ private int childCnt[] = new int[0x1000]; - + // the current position in childCnt private int elementCnt = 0; @@ -339,28 +339,29 @@ if (!validate && GeneralRangeIndexSpec.hasQNameOrValueIndex(last.getIndexType())) { elemContent = (XMLString) nodeContentStack.pop(); } - - if (!validate) { - final String content = elemContent == null ? null : elemContent.toString(); - broker.endElement(last, currentPath, content); - if (indexListener != null) - indexListener.endElement(transaction, last, currentPath); + + if (!validate) { + final String content = elemContent == null ? null : elemContent.toString(); + broker.endElement(last, currentPath, content); + if (indexListener != null) + indexListener.endElement(transaction, last, currentPath); + } + + currentPath.removeLastComponent(); + if (validate) { + if (childCnt != null) + setChildCount(last); + } else { + document.setOwnerDocument(document); + if ((childCnt == null && last.getChildCount() > 0) || + (childCnt != null && childCnt[last.getPosition()] != last.getChildCount())) { + broker.updateNode(transaction, last, false); } - - currentPath.removeLastComponent(); - if (validate) { - if (childCnt != null) - setChildCount(last); - } else { - document.setOwnerDocument(document); - if (childCnt == null && last.getChildCount() > 0) { - broker.updateNode(transaction, last, false); - } - } - setPrevious(last); - level--; - } + } + setPrevious(last); + level--; } + } /** * @param last @@ -516,7 +517,7 @@ attrNS = attributes.getURI(i); attrQName = attributes.getQName(i); if (attrQName.startsWith("xmlns") || attrNS.equals(Namespaces.EXIST_NS)) - --attrLength; + --attrLength; } ElementImpl last; Modified: trunk/eXist/src/org/exist/collections/Collection.java =================================================================== --- trunk/eXist/src/org/exist/collections/Collection.java 2009-02-15 12:11:34 UTC (rev 8602) +++ trunk/eXist/src/org/exist/collections/Collection.java 2009-02-15 16:33:31 UTC (rev 8603) @@ -916,7 +916,7 @@ // mark is not supported: exception is expected, do nothing } - XMLReader reader = getReader(broker, info.getCollectionConfig()); + XMLReader reader = getReader(broker, false, info.getCollectionConfig()); info.setReader(reader, null); try { @@ -951,7 +951,7 @@ CollectionConfiguration colconf = info.getDocument().getCollection().getConfiguration(broker); - XMLReader reader = getReader(broker, colconf); + XMLReader reader = getReader(broker, false, colconf); info.setReader(reader, null); try { @@ -1103,7 +1103,7 @@ final CollectionConfiguration colconf = getConfiguration(broker); return validateXMLResourceInternal(transaction, broker, docUri, colconf, new ValidateBlock() { public void run(IndexInfo info) throws SAXException, EXistException { - XMLReader reader = getReader(broker, colconf); + XMLReader reader = getReader(broker, true, colconf); info.setReader(reader, null); try { @@ -1649,7 +1649,7 @@ /** * Get xml reader from readerpool and setup validation when needed. */ - private XMLReader getReader(DBBroker broker, CollectionConfiguration colconfig) throws EXistException, + private XMLReader getReader(DBBroker broker, boolean validation, CollectionConfiguration colconfig) throws EXistException, SAXException { // If user-defined Reader is set, return it; @@ -1662,7 +1662,9 @@ // If Collection configuration exists (try to) get validation mode // and setup reader with this information. - if( colconfig!=null ) { + if (!validation) + XMLReaderObjectFactory.setReaderValidationMode(XMLReaderObjectFactory.VALIDATION_DISABLED, reader); + else if( colconfig!=null ) { int mode=colconfig.getValidationMode(); XMLReaderObjectFactory.setReaderValidationMode(mode, reader); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <wol...@us...> - 2009-02-20 23:22:17
|
Revision: 8623 http://exist.svn.sourceforge.net/exist/?rev=8623&view=rev Author: wolfgang_m Date: 2009-02-20 21:54:24 +0000 (Fri, 20 Feb 2009) Log Message: ----------- [feature] WebDAV protocol implementation: applied patch 2526060, which changes the way in which entries are stored. Previously, all entries were added to the feed document .feed.atom in the feed collection. This had some disadvantages, mainly concerning access control and - to a smaller extent - performance. The patch keeps the feed document .feed.atom, but stores all entries as single documents into a special collection .feed.entry below the feed collection. This commit will break old feeds. To fix them, you need to run a query similar to the following once: import module namespace xdb="http://exist-db.org/xquery/xmldb"; declare namespace atom="http://www.w3.org/2005/Atom"; declare function atom:update-feeds() { for $feed in /atom:feed let $feedCol := util:collection-name($feed) return ( let $entryCol := xdb:create-collection($feedCol, '.feed.entry') for $entry in $feed/atom:entry let $id := replace($entry/atom:id/string(), '.*:([^:]+)$', '$1') return xdb:store($entryCol, concat($id, '.entry.atom'), $entry, 'application/atom+xml'), update delete $feed/atom:entry ) }; system:as-user("blogadmin", "atom", atom:update-feeds()) Modified Paths: -------------- trunk/eXist/src/org/exist/atom/http/AtomServlet.java trunk/eXist/src/org/exist/atom/modules/AtomFeeds.java trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java trunk/eXist/src/org/exist/atom/modules/entry-by-id.xq trunk/eXist/src/org/exist/atom/modules/topic.xq trunk/eXist/src/org/exist/xmldb/LocalUserManagementService.java Modified: trunk/eXist/src/org/exist/atom/http/AtomServlet.java =================================================================== --- trunk/eXist/src/org/exist/atom/http/AtomServlet.java 2009-02-20 21:16:51 UTC (rev 8622) +++ trunk/eXist/src/org/exist/atom/http/AtomServlet.java 2009-02-20 21:54:24 UTC (rev 8623) @@ -461,7 +461,7 @@ response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,"Service is not available."); } catch (Throwable e){ - LOG.error(e); + LOG.error(e.getMessage(), e); throw new ServletException("An error occurred: " + e.getMessage(), e); } finally { Modified: trunk/eXist/src/org/exist/atom/modules/AtomFeeds.java =================================================================== --- trunk/eXist/src/org/exist/atom/modules/AtomFeeds.java 2009-02-20 21:16:51 UTC (rev 8622) +++ trunk/eXist/src/org/exist/atom/modules/AtomFeeds.java 2009-02-20 21:54:24 UTC (rev 8623) @@ -52,10 +52,12 @@ static final String FEED_DOCUMENT_NAME = ".feed.atom"; static final XmldbURI FEED_DOCUMENT_URI = XmldbURI.create(FEED_DOCUMENT_NAME); URLSource entryByIdSource; + URLSource getFeedSource; /** Creates a new instance of AtomProtocol */ public AtomFeeds() { - entryByIdSource = new URLSource(this.getClass().getResource("entry-by-id.xq")); + entryByIdSource = new URLSource(this.getClass().getResource("entry-by-id.xq")); + getFeedSource = new URLSource(this.getClass().getResource("get-feed.xq")); } public void doGet(DBBroker broker,IncomingMessage request,OutgoingMessage response) @@ -104,24 +106,7 @@ if (returnContent) { if (id==null) { response.setStatusCode(200); - response.setContentType(Atom.MIME_TYPE+"; charset="+charset); - - Serializer serializer = broker.getSerializer(); - serializer.reset(); - - //Serialize the document - try { - Writer w = new OutputStreamWriter(response.getOutputStream(),charset); - serializer.serialize(feedDoc,w); - w.flush(); - w.close(); - } catch (IOException ex) { - LOG.fatal("Cannot read resource "+request.getPath(),ex); - throw new EXistException("I/O error on read of resource "+request.getPath(),ex); - } catch (SAXException saxe) { - LOG.warn(saxe); - throw new BadRequestException("Error while serializing XML: " + saxe.getMessage()); - } + getFeed(broker,request.getPath(),response); } else { response.setStatusCode(200); getEntryById(broker,request.getPath(),id,response); @@ -183,63 +168,122 @@ } public void getEntryById(DBBroker broker,String path,String id,OutgoingMessage response) - throws EXistException,BadRequestException - { - XQuery xquery = broker.getXQueryService(); - CompiledXQuery feedQuery = xquery.getXQueryPool().borrowCompiledXQuery(broker,entryByIdSource); + throws EXistException,BadRequestException +{ + XQuery xquery = broker.getXQueryService(); + CompiledXQuery feedQuery = xquery.getXQueryPool().borrowCompiledXQuery(broker,entryByIdSource); - XQueryContext context; - if (feedQuery==null) { - context = xquery.newContext(AccessContext.REST); - try { - feedQuery = xquery.compile(context, entryByIdSource); - } catch (XPathException ex) { - throw new EXistException("Cannot compile xquery "+entryByIdSource.getURL(),ex); - } catch (IOException ex) { - throw new EXistException("I/O exception while compiling xquery "+entryByIdSource.getURL(),ex); - } - } else { - context = feedQuery.getContext(); + XQueryContext context; + if (feedQuery==null) { + context = xquery.newContext(AccessContext.REST); + try { + feedQuery = xquery.compile(context, entryByIdSource); + } catch (XPathException ex) { + throw new EXistException("Cannot compile xquery "+entryByIdSource.getURL(),ex); + } catch (IOException ex) { + throw new EXistException("I/O exception while compiling xquery "+entryByIdSource.getURL(),ex); } - context.setStaticallyKnownDocuments(new XmldbURI[] { XmldbURI.create(path).append(AtomProtocol.FEED_DOCUMENT_NAME) }); + } else { + context = feedQuery.getContext(); + } + context.setStaticallyKnownDocuments(new XmldbURI[] { XmldbURI.create(path).append(AtomProtocol.FEED_DOCUMENT_NAME) }); + try { + context.declareVariable("id",id); + Sequence resultSequence = xquery.execute(feedQuery, null); + if (resultSequence.isEmpty()) { + throw new BadRequestException("No topic was found."); + } + String charset = getContext().getDefaultCharset(); + response.setContentType("application/atom+xml; charset="+charset); + Serializer serializer = broker.getSerializer(); + serializer.reset(); try { - context.declareVariable("id",id); - Sequence resultSequence = xquery.execute(feedQuery, null); - if (resultSequence.isEmpty()) { - throw new BadRequestException("No topic was found."); - } - String charset = getContext().getDefaultCharset(); - response.setContentType("application/atom+xml; charset="+charset); - Serializer serializer = broker.getSerializer(); - serializer.reset(); - try { - Writer w = new OutputStreamWriter(response.getOutputStream(),charset); - SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class); - Properties outputProperties = new Properties(); - sax.setOutput(w, outputProperties); - serializer.setProperties(outputProperties); - serializer.setSAXHandlers(sax, sax); + Writer w = new OutputStreamWriter(response.getOutputStream(),charset); + SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class); + Properties outputProperties = new Properties(); + sax.setOutput(w, outputProperties); + serializer.setProperties(outputProperties); + serializer.setSAXHandlers(sax, sax); - serializer.toSAX(resultSequence, 1, 1, false); + serializer.toSAX(resultSequence, 1, 1, false); - SerializerPool.getInstance().returnObject(sax); - w.flush(); - w.close(); - } catch (IOException ex) { - LOG.fatal("Cannot read resource "+path,ex); - throw new EXistException("I/O error on read of resource "+path,ex); - } catch (SAXException saxe) { - LOG.warn(saxe); - throw new BadRequestException("Error while serializing XML: " + saxe.getMessage()); - } - resultSequence.itemAt(0); + SerializerPool.getInstance().returnObject(sax); + w.flush(); + w.close(); + } catch (IOException ex) { + LOG.fatal("Cannot read resource "+path,ex); + throw new EXistException("I/O error on read of resource "+path,ex); + } catch (SAXException saxe) { + LOG.warn(saxe); + throw new BadRequestException("Error while serializing XML: " + saxe.getMessage()); + } + resultSequence.itemAt(0); + } catch (XPathException ex) { + throw new EXistException("Cannot execute xquery "+entryByIdSource.getURL(),ex); + } finally { + xquery.getXQueryPool().returnCompiledXQuery(entryByIdSource, feedQuery); + } + +} + + public void getFeed(DBBroker broker,String path,OutgoingMessage response) + throws EXistException,BadRequestException +{ + XQuery xquery = broker.getXQueryService(); + CompiledXQuery feedQuery = xquery.getXQueryPool().borrowCompiledXQuery(broker,getFeedSource); + + XQueryContext context; + if (feedQuery==null) { + context = xquery.newContext(AccessContext.REST); + try { + feedQuery = xquery.compile(context, getFeedSource); } catch (XPathException ex) { - throw new EXistException("Cannot execute xquery "+entryByIdSource.getURL(),ex); - } finally { - xquery.getXQueryPool().returnCompiledXQuery(entryByIdSource, feedQuery); + throw new EXistException("Cannot compile xquery "+getFeedSource.getURL(),ex); + } catch (IOException ex) { + throw new EXistException("I/O exception while compiling xquery "+getFeedSource.getURL(),ex); } - + } else { + context = feedQuery.getContext(); } + context.setStaticallyKnownDocuments(new XmldbURI[] { XmldbURI.create(path).append(AtomProtocol.FEED_DOCUMENT_NAME) }); + + try { + Sequence resultSequence = xquery.execute(feedQuery, null); + if (resultSequence.isEmpty()) { + throw new BadRequestException("No feed was found."); + } + String charset = getContext().getDefaultCharset(); + response.setContentType("application/atom+xml; charset="+charset); + Serializer serializer = broker.getSerializer(); + serializer.reset(); + try { + Writer w = new OutputStreamWriter(response.getOutputStream(),charset); + SAXSerializer sax = (SAXSerializer) SerializerPool.getInstance().borrowObject(SAXSerializer.class); + Properties outputProperties = new Properties(); + sax.setOutput(w, outputProperties); + serializer.setProperties(outputProperties); + serializer.setSAXHandlers(sax, sax); + + serializer.toSAX(resultSequence, 1, 1, false); + + SerializerPool.getInstance().returnObject(sax); + w.flush(); + w.close(); + } catch (IOException ex) { + LOG.fatal("Cannot read resource "+path,ex); + throw new EXistException("I/O error on read of resource "+path,ex); + } catch (SAXException saxe) { + LOG.warn(saxe); + throw new BadRequestException("Error while serializing XML: " + saxe.getMessage()); + } + resultSequence.itemAt(0); + } catch (XPathException ex) { + throw new EXistException("Cannot execute xquery "+getFeedSource.getURL(),ex); + } finally { + xquery.getXQueryPool().returnCompiledXQuery(getFeedSource, feedQuery); + } } + +} Modified: trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java =================================================================== --- trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java 2009-02-20 21:16:51 UTC (rev 8622) +++ trunk/eXist/src/org/exist/atom/modules/AtomProtocol.java 2009-02-20 21:54:24 UTC (rev 8623) @@ -10,6 +10,7 @@ import org.apache.log4j.Logger; import org.exist.EXistException; +import org.exist.Namespaces; import org.exist.atom.Atom; import org.exist.atom.IncomingMessage; import org.exist.atom.OutgoingMessage; @@ -23,13 +24,13 @@ import org.exist.dom.DocumentImpl; import org.exist.dom.ElementImpl; import org.exist.dom.NodeIndexListener; -import org.exist.dom.NodeListImpl; import org.exist.dom.StoredNode; import org.exist.http.BadRequestException; import org.exist.http.NotFoundException; import org.exist.security.Permission; import org.exist.security.PermissionDeniedException; import org.exist.security.UUIDGenerator; +import org.exist.security.User; import org.exist.storage.DBBroker; import org.exist.storage.StorageAddress; import org.exist.storage.lock.Lock; @@ -38,6 +39,7 @@ import org.exist.util.LockException; import org.exist.util.MimeTable; import org.exist.util.MimeType; +import org.exist.util.SyntaxException; import org.exist.xmldb.XmldbURI; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -75,7 +77,10 @@ protected final static Logger LOG = Logger.getLogger(AtomProtocol.class); public static final String FEED_DOCUMENT_NAME = ".feed.atom"; + public static final String ENTRY_COLLECTION_NAME = ".feed.entry"; public static final XmldbURI FEED_DOCUMENT_URI = XmldbURI.create(FEED_DOCUMENT_NAME); + public static final XmldbURI ENTRY_COLLECTION_URI = XmldbURI.create(ENTRY_COLLECTION_NAME); + private static final String ENTRY_XPOINTER = "xpointer(/entry)"; final static class NodeListener implements NodeIndexListener { @@ -93,29 +98,6 @@ } } - class FindEntry implements NodeHandler { - String id; - Element matching; - FindEntry(String id) { - this.id = id; - } - public void process(Node parent,Node child) { - Element entry = (Element)child; - NodeList nl = entry.getElementsByTagNameNS(Atom.NAMESPACE_STRING,"id"); - if (nl.getLength()!=0) { - String value = DOM.textContent(nl.item(0)); - if (value.equals(id)) { - matching = entry; - } - } - } - - public Element getEntry() { - return matching; - } - - } - /** Creates a new instance of AtomProtocol */ public AtomProtocol() { } @@ -134,6 +116,9 @@ contentType = contentType.substring(0,semicolon).trim(); } mime = MimeTable.getInstance().getContentType(contentType); + if (mime==null) { + mime = MimeType.BINARY_TYPE; + } int equals = contentType.indexOf('=',semicolon); if (equals>0) { String param = contentType.substring(semicolon+1,equals).trim(); @@ -141,11 +126,10 @@ charset = param.substring(equals+1).trim(); } } - if (mime==null) { - mime = MimeType.BINARY_TYPE; - } } + String currentDateTime = DateFormatter.toXSDDateTime(new Date()); + Collection collection = broker.getCollection(pathUri); if (mime.getName().equals(Atom.MIME_TYPE)) { @@ -172,141 +156,159 @@ if (ns==null || !ns.equals(Atom.NAMESPACE_STRING)) { throw new BadRequestException("Any content posted with the Atom mime type must be in the Atom namespace."); } - if (root.getLocalName().equals("entry")) { - if (collection == null) { - throw new BadRequestException("Collection "+request.getPath()+" does not exist."); - } - LOG.debug("Adding entry to "+request.getPath()); - DocumentImpl feedDoc = null; - TransactionManager transact = broker.getBrokerPool().getTransactionManager(); - Txn transaction = transact.beginTransaction(); - String id = "urn:uuid:"+UUIDGenerator.getUUID(); - String currentDateTime = DateFormatter.toXSDDateTime(new Date()); - Element publishedE = DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"published",currentDateTime,true,true); - DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"updated",currentDateTime,true,true); - DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"id",id,true,true); - Element editLink = findLink(root,"edit"); - Element editLinkSrc = findLink(root,"edit-media"); - if (editLink!=null || editLinkSrc!=null) { - throw new BadRequestException("An edit link relation cannot be specified in the entry."); - } - editLink = doc.createElementNS(Atom.NAMESPACE_STRING,"link"); - editLink.setAttribute("rel","edit"); - editLink.setAttribute("type",Atom.MIME_TYPE); - editLink.setAttribute("href","?id="+id); - Node next = publishedE.getNextSibling(); - if (next==null) { - root.appendChild(editLink); - } else { - root.insertBefore(editLink,next); - } - try { - // get the feed - LOG.debug("Acquiring lock on feed document..."); - feedDoc = collection.getDocument(broker,FEED_DOCUMENT_URI); - if (!feedDoc.getPermissions().validate(broker.getUser(), Permission.UPDATE)) - throw new PermissionDeniedException("Permission denied to update feed " + collection.getURI()); - ElementImpl feedRoot = (ElementImpl)feedDoc.getDocumentElement(); - - // Lock the feed - feedDoc.getUpdateLock().acquire(Lock.WRITE_LOCK); - - // Append the entry - NodeListImpl nl = new NodeListImpl(1); - nl.add(root); - feedRoot.appendChildren(transaction,nl,-1); - - // Update the updated element - DOMDB.replaceTextElement(transaction,feedRoot,Atom.NAMESPACE_STRING,"updated",currentDateTime,true); - - // Store the changes - LOG.debug("Storing change..."); - broker.storeXMLResource(transaction, feedDoc); - transact.commit(transaction); - - LOG.debug("Done!"); - - response.setStatusCode(201); - response.setHeader("Location",request.getModuleBase()+request.getPath()+"?id="+id); - getEntryById(broker,request.getPath(),id,response); - /* - response.setContentType(Atom.MIME_TYPE+"; charset="+charset); - OutputStreamWriter w = new OutputStreamWriter(response.getOutputStream(),charset); - Transformer identity = TransformerFactory.newInstance().newTransformer(); - identity.transform(new DOMSource(doc),new StreamResult(w)); - w.flush(); - w.close(); - */ - + if (root.getLocalName().equals("feed")) { + DocumentImpl feedDoc = null; + TransactionManager transact = broker.getBrokerPool().getTransactionManager(); + Txn transaction = transact.beginTransaction(); + try { + if (collection != null) { + feedDoc = collection.getDocument(broker,FEED_DOCUMENT_URI); + if (feedDoc!=null) { + throw new PermissionDeniedException("Collection at "+request.getPath()+" already exists."); + } + } else { + collection = broker.getOrCreateCollection(transaction,pathUri); + setPermissions(broker, root, collection); + broker.saveCollection(transaction, collection); + } + String id = UUIDGenerator.getUUID(); + DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"updated",currentDateTime,true); + DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"id","urn:uuid:"+id,true); + Element editLink = findLink(root,"edit"); + if (editLink!=null) { + throw new BadRequestException("An edit link relation cannot be specified in the feed."); + } + editLink = doc.createElementNS(Atom.NAMESPACE_STRING,"link"); + editLink.setAttribute("rel","edit"); + editLink.setAttribute("type",Atom.MIME_TYPE); + editLink.setAttribute("href","#"); + root.appendChild(editLink); + Element selfLink = findLink(root,"self"); + if (selfLink!=null) { + throw new BadRequestException("A self link relation cannot be specified in the feed."); + } + selfLink = doc.createElementNS(Atom.NAMESPACE_STRING,"link"); + selfLink.setAttribute("rel","self"); + selfLink.setAttribute("type",Atom.MIME_TYPE); + selfLink.setAttribute("href","#"); + root.appendChild(selfLink); + IndexInfo info = collection.validateXMLResource(transaction,broker,FEED_DOCUMENT_URI,doc); + setPermissions(broker, root, info.getDocument()); + //TODO : We should probably unlock the collection here + collection.store(transaction,broker,info,doc,false); + transact.commit(transaction); + response.setStatusCode(204); + response.setHeader("Location",request.getModuleBase()+request.getPath()); + } catch (IOException ex) { + transact.abort(transaction); + throw new EXistException("IO error: "+ex.getMessage(),ex); + } catch (TriggerException ex) { + transact.abort(transaction); + throw new EXistException("Trigger failed: "+ex.getMessage(),ex); + } catch (SAXException ex) { + transact.abort(transaction); + throw new EXistException("SAX error: "+ex.getMessage(),ex); } catch (LockException ex) { - transact.abort(transaction); - throw new EXistException("Cannot acquire write lock.",ex); - /* - } catch (IOException ex) { - throw new EXistException("Internal error while serializing result.",ex); - } catch (TransformerException ex) { - throw new EXistException("Serialization error.",ex); - */ - } finally { - if (feedDoc!=null) { - feedDoc.getUpdateLock().release(Lock.WRITE_LOCK); - } - } - } else if (root.getLocalName().equals("feed")) { - DocumentImpl feedDoc = null; - TransactionManager transact = broker.getBrokerPool().getTransactionManager(); - Txn transaction = transact.beginTransaction(); - try { - if (collection != null) { - feedDoc = collection.getDocument(broker,FEED_DOCUMENT_URI); - if (feedDoc!=null) { - throw new PermissionDeniedException("Collection at "+request.getPath()+" already exists."); + transact.abort(transaction); + throw new EXistException("Cannot acquire write lock.",ex); + } + } else if (root.getLocalName().equals("entry")) { + if (collection == null) { + throw new BadRequestException("Collection "+request.getPath()+" does not exist."); + } + LOG.debug("Adding entry to " + request.getPath()); + DocumentImpl feedDoc = null; + feedDoc = collection.getDocument(broker,FEED_DOCUMENT_URI); + if (!feedDoc.getPermissions().validate(broker.getUser(), Permission.UPDATE)) + throw new PermissionDeniedException("Permission denied to update feed " + collection.getURI()); + TransactionManager transact = broker.getBrokerPool().getTransactionManager(); + Txn transaction = transact.beginTransaction(); + String uuid = UUIDGenerator.getUUID(); + String id = "urn:uuid:"+uuid; + Element publishedE = DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"published",currentDateTime,true,true); + DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"updated",currentDateTime,true,true); + DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"id",id,true,true); + Element editLink = findLink(root,"edit"); + Element editLinkSrc = findLink(root,"edit-media"); + if (editLink!=null || editLinkSrc!=null) { + throw new BadRequestException("An edit link relation cannot be specified in the entry."); + } + editLink = doc.createElementNS(Atom.NAMESPACE_STRING,"link"); + editLink.setAttribute("rel","edit"); + editLink.setAttribute("type",Atom.MIME_TYPE); + editLink.setAttribute("href","?id="+id); + Node next = publishedE.getNextSibling(); + if (next==null) { + root.appendChild(editLink); + } else { + root.insertBefore(editLink,next); + } + try { + // get the feed + LOG.debug("Acquiring lock on feed document..."); + ElementImpl feedRoot = (ElementImpl)feedDoc.getDocumentElement(); + + // Lock the feed + feedDoc.getUpdateLock().acquire(Lock.WRITE_LOCK); + + // Append the entry + collection = broker.getOrCreateCollection(transaction,pathUri.append(ENTRY_COLLECTION_URI)); + setPermissions(broker, root, collection); + broker.saveCollection(transaction, collection); + XmldbURI entryURI = entryURI(uuid); + DocumentImpl entryDoc = collection.getDocument(broker,entryURI); + if (entryDoc!=null) { + throw new PermissionDeniedException("Entry with "+id+" already exists."); } - } else { - collection = broker.getOrCreateCollection(transaction,pathUri); - broker.saveCollection(transaction, collection); - } - String id = UUIDGenerator.getUUID(); - String currentDateTime = DateFormatter.toXSDDateTime(new Date()); - DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"updated",currentDateTime,true); - DOM.replaceTextElement(root,Atom.NAMESPACE_STRING,"id","urn:uuid:"+id,true); - Element editLink = findLink(root,"edit"); - if (editLink!=null) { - throw new BadRequestException("An edit link relation cannot be specified in the feed."); - } - editLink = doc.createElementNS(Atom.NAMESPACE_STRING,"link"); - editLink.setAttribute("rel","edit"); - editLink.setAttribute("type",Atom.MIME_TYPE); - editLink.setAttribute("href","#"); - root.appendChild(editLink); - Element selfLink = findLink(root,"self"); - if (selfLink!=null) { - throw new BadRequestException("A self link relation cannot be specified in the feed."); - } - selfLink = doc.createElementNS(Atom.NAMESPACE_STRING,"link"); - selfLink.setAttribute("rel","self"); - selfLink.setAttribute("type",Atom.MIME_TYPE); - selfLink.setAttribute("href","#"); - root.appendChild(selfLink); - IndexInfo info = collection.validateXMLResource(transaction,broker,FEED_DOCUMENT_URI,doc); - //TODO : We should probably unlock the collection here - collection.store(transaction,broker,info,doc,false); - transact.commit(transaction); - response.setStatusCode(204); - response.setHeader("Location",request.getModuleBase()+request.getPath()); - } catch (IOException ex) { - transact.abort(transaction); - throw new EXistException("IO error: "+ex.getMessage(),ex); - } catch (TriggerException ex) { - transact.abort(transaction); - throw new EXistException("Trigger failed: "+ex.getMessage(),ex); - } catch (SAXException ex) { - transact.abort(transaction); - throw new EXistException("SAX error: "+ex.getMessage(),ex); - } catch (LockException ex) { - transact.abort(transaction); - throw new EXistException("Cannot acquire write lock.",ex); - } + IndexInfo info = collection.validateXMLResource(transaction,broker,entryURI,doc); + setPermissions(broker, root, info.getDocument()); + //TODO : We should probably unlock the collection here + collection.store(transaction,broker,info,doc,false); + + // Update the updated element + DOMDB.replaceTextElement(transaction,feedRoot,Atom.NAMESPACE_STRING,"updated",currentDateTime,true); + + // Store the changes + LOG.debug("Storing change..."); + broker.storeXMLResource(transaction, feedDoc); + transact.commit(transaction); + + LOG.debug("Done!"); + + response.setStatusCode(201); + response.setHeader("Location",request.getModuleBase()+request.getPath()+"?id="+id); + getEntryById(broker,request.getPath(),id,response); + /* + response.setContentType(Atom.MIME_TYPE+"; charset="+charset); + OutputStreamWriter w = new OutputStreamWriter(response.getOutputStream(),charset); + Transformer identity = TransformerFactory.newInstance().newTransformer(); + identity.transform(new DOMSource(doc),new StreamResult(w)); + w.flush(); + w.close(); + */ + } catch (IOException ex) { + transact.abort(transaction); + throw new EXistException("IO error: "+ex.getMessage(),ex); + } catch (TriggerException ex) { + transact.abort(transaction); + throw new EXistException("Trigger failed: "+ex.getMessage(),ex); + } catch (SAXException ex) { + transact.abort(transaction); + throw new EXistException("SAX error: "+ex.getMessage(),ex); + } catch (LockException ex) { + transact.abort(transaction); + throw new EXistException("Cannot acquire write lock.",ex); + /* + } catch (IOException ex) { + throw new EXistException("Internal error while serializing result.",ex); + } catch (TransformerException ex) { + throw new EXistException("Serialization error.",ex); + */ + } finally { + if (feedDoc!=null) { + feedDoc.getUpdateLock().release(Lock.WRITE_LOCK); + } + } } else { throw new BadRequestException("Unexpected element: {http://www.w3.org/2005/Atom}"+root.getLocalName()); } @@ -318,6 +320,8 @@ if (feedDoc==null) { throw new BadRequestException("Feed at "+request.getPath()+" does not exist."); } + if (!feedDoc.getPermissions().validate(broker.getUser(), Permission.UPDATE)) + throw new PermissionDeniedException("Permission denied to update feed " + collection.getURI()); String filename = request.getHeader("Slug"); if (filename==null) { String ext = MimeTable.getInstance().getPreferredExtension(mime); @@ -364,9 +368,22 @@ String created = DateFormatter.toXSDDateTime(new Date()); ElementImpl feedRoot = (ElementImpl)feedDoc.getDocumentElement(); DOMDB.replaceTextElement(transaction,feedRoot,Atom.NAMESPACE_STRING,"updated",created,true); - String id = "urn:uuid:"+UUIDGenerator.getUUID(); + String uuid = UUIDGenerator.getUUID(); + String id = "urn:uuid:"+uuid; Element mediaEntry = generateMediaEntry(id,created,title,filename,mime.getName()); - DOMDB.appendChild(transaction,feedRoot,mediaEntry); + + collection = broker.getOrCreateCollection(transaction,pathUri.append(ENTRY_COLLECTION_URI)); + broker.saveCollection(transaction, collection); + XmldbURI entryURI = entryURI(uuid); + DocumentImpl entryDoc = collection.getDocument(broker,entryURI); + if (entryDoc!=null) { + throw new PermissionDeniedException("Entry with "+id+" already exists."); + } + IndexInfo info = collection.validateXMLResource(transaction,broker,entryURI,mediaEntry); + //TODO : We should probably unlock the collection here + collection.store(transaction,broker,info,mediaEntry,false); + // Update the updated element + DOMDB.replaceTextElement(transaction,feedRoot,Atom.NAMESPACE_STRING,"updated",currentDateTime,true); LOG.debug("Storing change..."); broker.storeXMLResource(transaction, feedDoc); transact.commit(transaction); @@ -443,6 +460,10 @@ } } + String currentDateTime = DateFormatter.toXSDDateTime(new Date()); + + Collection collection = broker.getCollection(pathUri); + if (mime.getName().equals(Atom.MIME_TYPE)) { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); @@ -468,11 +489,13 @@ throw new BadRequestException("Any content posted with the Atom mime type must be in the Atom namespace."); } if (root.getLocalName().equals("feed")) { - Collection collection = broker.getCollection(pathUri); DocumentImpl feedDoc = collection.getDocument(broker,FEED_DOCUMENT_URI); if (feedDoc==null) { throw new BadRequestException("Collection at "+request.getPath()+" does not exist."); } + feedDoc = collection.getDocument(broker,FEED_DOCUMENT_URI); + if (!feedDoc.getPermissions().validate(broker.getUser(), Permission.UPDATE)) + throw new PermissionDeniedException("Permission denied to update feed " + collection.getURI()); if (DOM.findChild(root,Atom.NAMESPACE_STRING,"title")==null) { throw new BadRequestException("The feed metadata sent does not contain a title."); @@ -506,7 +529,6 @@ } } } else if (root.getLocalName().equals("entry")) { - Collection collection = broker.getCollection(pathUri); if (collection == null) { throw new BadRequestException("Collection "+request.getPath()+" does not exist."); } @@ -516,29 +538,39 @@ } LOG.debug("Updating entry "+id+" in collection "+request.getPath()); DocumentImpl feedDoc = null; + DocumentImpl entryDoc = null; TransactionManager transact = broker.getBrokerPool().getTransactionManager(); Txn transaction = transact.beginTransaction(); - String currentDateTime = DateFormatter.toXSDDateTime(new Date()); try { // Get the feed LOG.debug("Acquiring lock on feed document..."); feedDoc = collection.getDocument(broker,FEED_DOCUMENT_URI); + if (!feedDoc.getPermissions().validate(broker.getUser(), Permission.UPDATE)) + throw new PermissionDeniedException("Permission denied to update feed " + collection.getURI()); feedDoc.getUpdateLock().acquire(Lock.WRITE_LOCK); // Find the entry - FindEntry finder = new FindEntry(id); - DOM.findChildren(feedDoc.getDocumentElement(),Atom.NAMESPACE_STRING,"entry",finder); - Element entry = finder.getEntry(); - if (entry==null) { - throw new BadRequestException("Cannot find entry with id "+id); - } + String uuid = id.substring(9); + collection = broker.getCollection(pathUri.append(ENTRY_COLLECTION_URI)); + XmldbURI entryURI = entryURI(uuid); + entryDoc = collection.getDocument(broker,entryURI); + if (entryDoc==null) { + throw new BadRequestException("Cannot find entry with id "+id); + } + + // Lock the entry + entryDoc.getUpdateLock().acquire(Lock.WRITE_LOCK); + + Element entry = entryDoc.getDocumentElement(); + mergeEntry(transaction,(ElementImpl)entry,root,currentDateTime); - + // Update the feed time DOMDB.replaceTextElement(transaction,(ElementImpl)feedDoc.getDocumentElement(),Atom.NAMESPACE_STRING,"updated",currentDateTime,true); // Store the feed broker.storeXMLResource(transaction, feedDoc); + broker.storeXMLResource(transaction, entryDoc); transact.commit(transaction); // Send back the changed entry @@ -563,9 +595,12 @@ throw new EXistException("Serialization error.",ex); */ } finally { - if (feedDoc!=null) { - feedDoc.getUpdateLock().release(Lock.WRITE_LOCK); + if (feedDoc!=null) { + feedDoc.getUpdateLock().release(Lock.WRITE_LOCK); } + if (entryDoc!=null) { + entryDoc.getUpdateLock().release(Lock.WRITE_LOCK); + } } } else { throw new BadRequestException("Unexpected element: {http://www.w3.org/2005/Atom}"+root.getLocalName()); @@ -581,7 +616,7 @@ transact.abort(transaction); throw new BadRequestException("The path is not valid: " + request.getPath()); } - Collection collection = broker.getCollection(collUri); + collection = broker.getCollection(collUri); if (collection == null) { transact.abort(transaction); throw new BadRequestException("The collection does not exist: " + collUri); @@ -602,7 +637,6 @@ collection.store(transaction, broker, info, new InputSource(new InputStreamReader(is,charset)), false); is.close(); } else { - FileInputStream is = new FileInputStream(tempFile); collection.addBinaryResource(transaction, broker, docUri, is, contentType, (int) tempFile.length()); is.close(); @@ -676,14 +710,15 @@ feedDoc.getUpdateLock().acquire(Lock.WRITE_LOCK); // Find the entry - FindEntry finder = new FindEntry(id); - DOM.findChildren(feedDoc.getDocumentElement(),Atom.NAMESPACE_STRING,"entry",finder); - Element entry = finder.getEntry(); + String uuid = id.substring(9); + Collection entryCollection = broker.getCollection(pathUri.append(ENTRY_COLLECTION_URI)); + XmldbURI entryURI = entryURI(uuid); + DocumentImpl entryDoc = entryCollection.getDocument(broker,entryURI); + if (entryDoc==null) { + throw new BadRequestException("Entry with id "+id+" cannot be found."); + } - if (entry==null) { - transact.abort(transaction); - throw new BadRequestException("Entry with id "+id+" cannot be found."); - } + Element entry = entryDoc.getDocumentElement(); // Remove the media resource if there is one Element content = DOM.findChild(entry,Atom.NAMESPACE_STRING,"content"); @@ -705,10 +740,10 @@ } // Remove the entry - ElementImpl feedRoot = (ElementImpl)feedDoc.getDocumentElement(); - feedRoot.removeChild(transaction,entry); + entryCollection.removeXMLResource(transaction, broker, entryURI); // Update the feed time + ElementImpl feedRoot = (ElementImpl)feedDoc.getDocumentElement(); DOMDB.replaceTextElement(transaction,feedRoot,Atom.NAMESPACE_STRING,"updated",currentDateTime,true); // Store the change on the feed @@ -765,7 +800,6 @@ Node child = (Node)childrenToRemove.next(); target.removeChild(transaction,child); } - final Document ownerDocument = target.getOwnerDocument(); DOM.forEachChild(source,new NodeHandler() { public void process(Node parent,Node child) { if (child.getNodeType()==Node.ELEMENT_NODE) { @@ -800,42 +834,45 @@ public void process(Node parent, Node child) { if (child.getNodeType()==Node.ELEMENT_NODE) { String ns = child.getNamespaceURI(); - if (ns!=null && ns.equals(Atom.NAMESPACE_STRING)) { - String lname = child.getLocalName(); - if (lname.equals("updated")) { - // Changed updated - DOMDB.replaceText(transaction,(ElementImpl)child,updated); - } else if (lname.equals("link")) { - Element echild = (Element)child; - String rel = echild.getAttribute("rel"); - if (!rel.equals("edit")) { - // remove it - toRemove.add(child); - } - } else if (!lname.equals("id") && !lname.equals("published") && !lname.equals("entry")) { - // remove it - toRemove.add(child); - } + if (ns!=null){ + String lname = child.getLocalName(); + if (ns.equals(Atom.NAMESPACE_STRING)) { + if (lname.equals("updated")) { + // Changed updated + DOMDB.replaceText(transaction,(ElementImpl)child,updated); + } else if (lname.equals("link")) { + Element echild = (Element)child; + String rel = echild.getAttribute("rel"); + if (!rel.equals("edit")) { + // remove it + toRemove.add(child); + } + } else if (!lname.equals("id") && !lname.equals("published")) { + // remove it + toRemove.add(child); + } + } else { + // remove it + toRemove.add(child); + } } else { - // remove it - toRemove.add(child); + // remove it + toRemove.add(child); } } else { + // remove it toRemove.add(child); } } }); + for (Iterator childrenToRemove = toRemove.iterator(); childrenToRemove.hasNext(); ) { Node child = (Node)childrenToRemove.next(); target.removeChild(transaction,child); } + NodeList nl = source.getChildNodes(); - NodeListener firstEntry = null; - Element theFirstEntry = DOM.findChild(target,Atom.NAMESPACE_STRING,"entry"); - if (theFirstEntry!=null) { - firstEntry = new NodeListener((StoredNode)theFirstEntry); - ownerDocument.getMetadata().setIndexListener(firstEntry); - } + for (int i=0; i<nl.getLength(); i++) { Node child = nl.item(i); if (child.getNodeType()==Node.ELEMENT_NODE) { @@ -857,17 +894,14 @@ } } } - if (firstEntry==null) { - DOMDB.appendChild(transaction,target,child); - } else { - DOMDB.insertBefore(transaction,target,child,firstEntry.node); - } + DOMDB.appendChild(transaction,target,child); } } ownerDocument.getMetadata().clearIndexListener(); ownerDocument.getMetadata().setLastModified(System.currentTimeMillis()); } - + + protected Element findLink(Element parent,String rel) { NodeList nl = parent.getElementsByTagNameNS(Atom.NAMESPACE_STRING,"link"); for (int i=0; i<nl.getLength(); i++) { @@ -878,12 +912,77 @@ } return null; } - - public static Element generateMediaEntry(String id,String created,String title,String filename,String mimeType) + + /** + * Apply permissions to a collection. Owner, owner group and access permissions + * can be set when creating a new feed by passing an element <exist:permissions> + * in the document, e.g.: + * + * <pre><exist:permissions mode="0775" owner="editor" group="users"/></pre> + */ + protected void setPermissions(DBBroker broker, Element parent, Collection collection) throws LockException, PermissionDeniedException { + Element element = DOM.findChild(parent, Namespaces.EXIST_NS, "permissions"); + if (element != null) { + String mode = element.getAttribute("mode"); + if (mode != null) { + try { + int permissions = Integer.parseInt(mode, 8); + collection.setPermissions(permissions); + } catch (NumberFormatException e) { + try { + collection.setPermissions(mode); + } catch (SyntaxException e1) { + throw new PermissionDeniedException("syntax error for mode attribute in exist:permissions element"); + } + } + } + String owner = element.getAttribute("owner"); + org.exist.security.SecurityManager securityMan = broker.getBrokerPool().getSecurityManager(); + if (!securityMan.hasUser(owner)) + throw new PermissionDeniedException("Failed to change feed owner: user " + owner + " does not exist."); + collection.getPermissions().setOwner(owner); + String group = element.getAttribute("group"); + if (!securityMan.hasGroup(group)) + securityMan.addGroup(group); + + parent.removeChild(element); + } + } + + protected void setPermissions(DBBroker broker, Element parent, DocumentImpl resource) throws LockException, PermissionDeniedException { + Element element = DOM.findChild(parent, Namespaces.EXIST_NS, "permissions"); + if (element != null) { + String mode = element.getAttribute("mode"); + try { + int permissions = Integer.parseInt(mode, 8); + resource.setPermissions(permissions); + } catch (NumberFormatException e) { + try { + resource.setPermissions(mode); + } catch (SyntaxException e1) { + throw new PermissionDeniedException("syntax error for mode attribute in exist:permissions element"); + } + } + String owner = element.getAttribute("owner"); + org.exist.security.SecurityManager securityMan = broker.getBrokerPool().getSecurityManager(); + if (!securityMan.hasUser(owner)) + throw new PermissionDeniedException("Failed to change feed owner: user " + owner + " does not exist."); + resource.getPermissions().setOwner(owner); + String group = element.getAttribute("group"); + if (!securityMan.hasGroup(group)) + securityMan.addGroup(group); + + parent.removeChild(element); + } + } + + protected XmldbURI entryURI(String uuid){ + return XmldbURI.create(uuid + ".entry.atom"); + } + + public static Element generateMediaEntry(String id, String created, String title, String filename, String mimeType) throws ParserConfigurationException { - - DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); Document owner = docFactory.newDocumentBuilder().getDOMImplementation().createDocument(Atom.NAMESPACE_STRING,"entry",null); Modified: trunk/eXist/src/org/exist/atom/modules/entry-by-id.xq =================================================================== --- trunk/eXist/src/org/exist/atom/modules/entry-by-id.xq 2009-02-20 21:16:51 UTC (rev 8622) +++ trunk/eXist/src/org/exist/atom/modules/entry-by-id.xq 2009-02-20 21:54:24 UTC (rev 8623) @@ -1,3 +1,3 @@ declare namespace atom="http://www.w3.org/2005/Atom"; declare variable $id external; -/atom:feed/atom:entry[atom:id=$id] \ No newline at end of file +collection(string-join((substring-before(base-uri(/atom:feed),'/.feed.atom'),".feed.entry"),"/"))/atom:entry[atom:id=$id] \ No newline at end of file Modified: trunk/eXist/src/org/exist/atom/modules/topic.xq =================================================================== --- trunk/eXist/src/org/exist/atom/modules/topic.xq 2009-02-20 21:16:51 UTC (rev 8622) +++ trunk/eXist/src/org/exist/atom/modules/topic.xq 2009-02-20 21:54:24 UTC (rev 8623) @@ -1,21 +1,20 @@ declare namespace atom="http://www.w3.org/2005/Atom"; <feed xmlns="http://www.w3.org/2005/Atom"> { - "
", - /atom:feed/atom:title, - "
", - /atom:feed/atom:id, - "
", - /atom:feed/atom:updated, - "
", - /atom:feed/atom:entry[atom:category[concat(@scheme,@term)='http://www.atomojo.org/ontology/relation/subtopic']], - "
", - /atom:feed/atom:link - } - { - let $current := substring-before(base-uri(/atom:feed),'/.feed.atom'), - $current-path := substring-after($current,'/db') - return ( + let $current := substring-before(base-uri(/atom:feed),'/.feed.atom'), + $current-path := substring-after($current,'/db') + return( + "
", + /atom:feed/atom:title, + "
", + /atom:feed/atom:id, + "
", + /atom:feed/atom:updated, + "
", + collection(string-join(($current,".feed.entry"),"/"))/atom:entry[atom:category[concat(@scheme,@term)='http://www.atomojo.org/ontology/relation/subtopic']], + "
", + /atom:feed/atom:link, + <link rel="alternate" href="/atom/content{substring-after($current,'/db')}" type="application/atom+xml"/>, "
", let $parts := tokenize($current-path,'/') Modified: trunk/eXist/src/org/exist/xmldb/LocalUserManagementService.java =================================================================== --- trunk/eXist/src/org/exist/xmldb/LocalUserManagementService.java 2009-02-20 21:16:51 UTC (rev 8622) +++ trunk/eXist/src/org/exist/xmldb/LocalUserManagementService.java 2009-02-20 21:54:24 UTC (rev 8623) @@ -154,9 +154,9 @@ " not found"); if (!coll.getPermissions().validate(user, Permission.WRITE) && !manager.hasAdminPrivileges(user)) { transact.abort(transaction); - throw new XMLDBException( - ErrorCodes.PERMISSION_DENIED, - "you are not the owner of this collection"); + throw new XMLDBException( + ErrorCodes.PERMISSION_DENIED, + "you are not the owner of this collection"); } coll.setPermissions(modeStr); broker.saveCollection(transaction, coll); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |