Package org.exist.soap

Source Code of org.exist.soap.QuerySoapBindingImpl

package org.exist.soap;

import java.io.StringReader;
import java.net.URISyntaxException;
import java.rmi.RemoteException;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.TreeMap;

import javax.xml.transform.OutputKeys;

import org.apache.log4j.Logger;
import org.exist.EXistException;
import org.exist.dom.DocumentImpl;
import org.exist.dom.ExtArrayNodeSet;
import org.exist.dom.NodeProxy;
import org.exist.dom.NodeSet;
import org.exist.security.Permission;
import org.exist.security.PermissionDeniedException;
import org.exist.security.Subject;
import org.exist.security.xacml.AccessContext;
import org.exist.security.xacml.XACMLSource;
import org.exist.soap.Session.QueryResult;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.serializers.EXistOutputKeys;
import org.exist.storage.serializers.Serializer;
import org.exist.util.Configuration;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.AnalyzeContextInfo;
import org.exist.xquery.PathExpr;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.parser.XQueryLexer;
import org.exist.xquery.parser.XQueryParser;
import org.exist.xquery.parser.XQueryTreeParser;
import org.exist.xquery.util.ExpressionDumper;
import org.exist.xquery.value.Item;
import org.exist.xquery.value.NodeValue;
import org.exist.xquery.value.Sequence;
import org.exist.xquery.value.SequenceIterator;
import org.exist.xquery.value.Type;
import org.xml.sax.SAXException;

import antlr.collections.AST;

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

/**
*  Provides the actual implementations for the methods defined in
* {@link org.exist.soap.Query}.
*
*@author     Wolfgang Meier <wolfgang@exist-db.org>
*/
public class QuerySoapBindingImpl implements org.exist.soap.Query {
   
    private static Logger LOG = Logger.getLogger("QueryService");
   
    private BrokerPool pool;
   
    public QuerySoapBindingImpl() {
        try {
            if (!BrokerPool.isConfigured(BrokerPool.DEFAULT_INSTANCE_NAME))
                {configure();}
            pool = BrokerPool.getInstance();
        } catch (final Exception e) {
            throw new RuntimeException("failed to initialize broker pool");
        }
    }
   
    private QueryResponseCollection[] collectQueryInfo(TreeMap collections) {
        final QueryResponseCollection c[] = new QueryResponseCollection[collections.size()];
        QueryResponseDocument doc;
        QueryResponseDocument docs[];
        XmldbURI docId;
        int k = 0;
        int l;
        TreeMap documents;
        for (final Iterator i = collections.entrySet().iterator(); i.hasNext(); k++) {
            final Map.Entry entry = (Map.Entry) i.next();
            c[k] = new QueryResponseCollection();
            c[k].setCollectionName(((XmldbURI) entry.getKey()).toString());
            documents = (TreeMap) entry.getValue();
            docs = new QueryResponseDocument[documents.size()];
            c[k].setDocuments(new QueryResponseDocuments(docs));
            l = 0;
            for (final Iterator j = documents.entrySet().iterator(); j.hasNext(); l++) {
                final Map.Entry docEntry = (Map.Entry) j.next();
                doc = new QueryResponseDocument();
                docId = (XmldbURI) docEntry.getKey();
                //TODO: Unnecessary?
                docId = docId.lastSegment();
                doc.setDocumentName(docId.toString());
                doc.setHitCount(((Integer) docEntry.getValue()).intValue());
                docs[l] = doc;
            }
        }
        return c;
    }
   
    private void configure() throws Exception {
        final Configuration config = new Configuration();
        BrokerPool.configure(1, 5, config);
    }
   
    private Session getSession(String id) throws java.rmi.RemoteException {
        final Session session = SessionManager.getInstance().getSession(id);
        if (session == null)
            {throw new java.rmi.RemoteException("Session is invalid or timed out");}
        return session;
    }
   
    public java.lang.String connect(java.lang.String userId, java.lang.String password) throws java.rmi.RemoteException {
      try {
        final Subject u = pool.getSecurityManager().authenticate(userId, password);
     
            LOG.debug("user " + userId + " connected");
           
            return SessionManager.getInstance().createSession(u);
    } catch (final Exception e) {
            throw new RemoteException(e.getMessage());
    }
    }
   
    public void disconnect(java.lang.String sessionId) throws java.rmi.RemoteException {
        final SessionManager manager = SessionManager.getInstance();
        final Session session = manager.getSession(sessionId);
        if (session != null) {
            LOG.debug("disconnecting session " + sessionId);
            manager.disconnect(sessionId);
        }
    }
   
        /* (non-Javadoc)
         * @see org.exist.soap.Query#getResourceData(java.lang.String, byte[], boolean, boolean)
         */
    public byte[] getResourceData(java.lang.String sessionId, java.lang.String path, boolean indent, boolean xinclude, boolean processXSLPI) throws java.rmi.RemoteException {
        final Properties outputProperties = new Properties();
        outputProperties.setProperty(OutputKeys.INDENT, indent ? "yes" : "no");
        outputProperties.setProperty(EXistOutputKeys.EXPAND_XINCLUDES, xinclude ? "yes" : "no");
        outputProperties.setProperty(EXistOutputKeys.PROCESS_XSL_PI,
                processXSLPI ? "yes" : "no");
        final String xml = getResource(sessionId, path, outputProperties);
        return xml.getBytes(UTF_8);
    }
   
    public java.lang.String getResource(java.lang.String sessionId, java.lang.String name, boolean indent, boolean xinclude) throws java.rmi.RemoteException {
        final Properties outputProperties = new Properties();
        outputProperties.setProperty(OutputKeys.INDENT, indent ? "yes" : "no");
        outputProperties.setProperty(EXistOutputKeys.EXPAND_XINCLUDES, xinclude ? "yes" : "no");
        return getResource(sessionId, name, outputProperties);
    }
   
    protected String getResource(String sessionId, String name,
            Properties outputProperties) throws java.rmi.RemoteException {
      try {
        return getResource(sessionId,XmldbURI.xmldbUriFor(name),outputProperties);
      } catch(final URISyntaxException e) {
        throw new RemoteException("Invalid collection URI",e);
      }
    }
    protected String getResource(String sessionId, XmldbURI name,
            Properties outputProperties) throws java.rmi.RemoteException {
        final Session session = getSession(sessionId);
        DBBroker broker = null;
        try {
            broker = pool.get(session.getUser());
// TODO check XML/Binary resource
// DocumentImpl document = (DocumentImpl) broker.getDocument(name);
            final DocumentImpl document = broker.getResource(name, Permission.READ);
            if (document == null)
                {throw new RemoteException("resource " + name + " not found");}

            final Serializer serializer = broker.getSerializer();
            serializer.reset();
            serializer.setProperties(outputProperties);
            return serializer.serialize(document);
           
            //      if (xml != null)
            //        try {
            //          return xml.getBytes("UTF-8");
            //        } catch (java.io.UnsupportedEncodingException e) {
            //          LOG.warn(e);
            //          return xml.getBytes();
            //        }
            //
            //      return null;
        } catch (final SAXException saxe) {
            saxe.printStackTrace();
            throw new RemoteException(saxe.getMessage());
        } catch (final EXistException e) {
            throw new RemoteException(e.getMessage());
        } catch (final PermissionDeniedException e) {
            throw new RemoteException(e.getMessage());
        } finally {
            pool.release(broker);
        }
    }
   
    public org.exist.soap.Collection listCollection(java.lang.String sessionId, java.lang.String path) throws java.rmi.RemoteException {
      try {
        return listCollection(sessionId,XmldbURI.xmldbUriFor(path));
      } catch(final URISyntaxException e) {
        throw new RemoteException("Invalid collection URI",e);
      }
    }
    public org.exist.soap.Collection listCollection(java.lang.String sessionId, XmldbURI path) throws java.rmi.RemoteException {
        final Session session = getSession(sessionId);
        DBBroker broker = null;
        try {
            broker = pool.get(session.getUser());
            if (path == null)
                {path = XmldbURI.ROOT_COLLECTION_URI;}
            final org.exist.collections.Collection collection = broker.getCollection(path);
            if (collection == null)
                {throw new RemoteException("collection " + path + " not found");}
            if (!collection.getPermissionsNoLock().validate(session.getUser(), Permission.READ))
                {throw new RemoteException("permission denied");}
            final Collection c = new Collection();
           
            // Sub-collections
            final String childCollections[] = new String[collection.getChildCollectionCount(broker)];
            int j = 0;
            for (final Iterator i = collection.collectionIterator(broker); i.hasNext(); j++)
                childCollections[j] = ((XmldbURI) i.next()).toString();
           
            // Resources
            final String[] resources = new String[collection.getDocumentCount(broker)];
            j = 0;
            XmldbURI resource;
            for (final Iterator i = collection.iterator(broker); i.hasNext(); j++) {
                resource = ((DocumentImpl) i.next()).getFileURI();
                resources[j] = resource.lastSegment().toString();
            }
            c.setResources(new StringArray(resources));
            c.setCollections(new StringArray(childCollections));
            return c;
        } catch (final EXistException e) {
            throw new RemoteException(e.getMessage());
        } catch (final PermissionDeniedException pde) {
            throw new RemoteException(pde.getMessage());
        } finally {
            pool.release(broker);
        }
    }
   
        /* (non-Javadoc)
         * @see org.exist.soap.Query#xquery(java.lang.String, byte[])
         */
    @Override
    public org.exist.soap.QueryResponse xquery(java.lang.String sessionId, byte[] xquery) throws java.rmi.RemoteException {
        String query = new String(xquery, UTF_8);
        return query(sessionId, query);
    }

    /**  @deprecated use {@link #xquery(String, byte[])} instead. */
    @Override
    public org.exist.soap.QueryResponse query(java.lang.String sessionId, java.lang.String xpath) throws java.rmi.RemoteException {
        final Session session = getSession(sessionId);
       
        final QueryResponse resp = new QueryResponse();
        resp.setHits(0);
        DBBroker broker = null;
        try {
//            xpath = StringValue.expand(xpath);
            LOG.debug("query: " + xpath);
            broker = pool.get(session.getUser());
            final XQueryContext context = new XQueryContext(pool, AccessContext.SOAP);
            context.setXacmlSource(XACMLSource.getInstance(xpath));
           
            session.registerContext(context);
           
            // TODO(pkaminsk2): why replicate XQuery.compile here?
           
            final XQueryLexer lexer = new XQueryLexer(context, new StringReader(xpath));
            final XQueryParser parser = new XQueryParser(lexer);
            final XQueryTreeParser treeParser = new XQueryTreeParser(context);
            parser.xpath();
            if (parser.foundErrors()) {
                LOG.debug(parser.getErrorMessage());
                throw new RemoteException(parser.getErrorMessage());
            }
           
            final AST ast = parser.getAST();
           
            final PathExpr expr = new PathExpr(context);
            treeParser.xpath(ast, expr);
            if (treeParser.foundErrors()) {
                LOG.debug(treeParser.getErrorMessage());
                throw new EXistException(treeParser.getErrorMessage());
            }
            LOG.info("query: " + ExpressionDumper.dump(expr));
            final long start = System.currentTimeMillis();
            expr.analyze(new AnalyzeContextInfo());
            final Sequence seq= expr.eval(null, null);
           
            QueryResponseCollection[] collections = null;
            if (!seq.isEmpty() && Type.subTypeOf(seq.getItemType(), Type.NODE))
                {collections = collectQueryInfo(scanResults(seq));}
            session.addQueryResult(seq);
            resp.setCollections(new QueryResponseCollections(collections));
            resp.setHits(seq.getItemCount());
            resp.setQueryTime(System.currentTimeMillis() - start);
            expr.reset();
            context.reset();
        } catch (final Exception e) {
            LOG.debug(e.getMessage(), e);
            throw new RemoteException("query execution failed: " + e.getMessage());
        } finally {
            pool.release(broker);
        }
        return resp;
    }
   
        /* (non-Javadoc)
         * @see org.exist.soap.Query#retrieveData(java.lang.String, int, int, boolean, boolean, java.lang.String)
         */
    public org.exist.soap.Base64BinaryArray retrieveData(java.lang.String sessionId, int start, int howmany, boolean indent, boolean xinclude, java.lang.String highlight) throws java.rmi.RemoteException {
        final String[] results = retrieve(sessionId, start, howmany, indent, xinclude, highlight);
        final byte[][] data = new byte[results.length][];
        for(int i = 0; i < results.length; i++) {
            data[i] = results[i].getBytes(UTF_8);
        }
        return new Base64BinaryArray(data);
    }
   
    public java.lang.String[] retrieve(java.lang.String sessionId, int start, int howmany, boolean indent, boolean xinclude, java.lang.String highlight) throws java.rmi.RemoteException {
        final Session session = getSession(sessionId);
        DBBroker broker = null;
        try {
            broker = pool.get(session.getUser());
            final QueryResult queryResult = session.getQueryResult();
            if (queryResult == null)
                {throw new RemoteException("result set unknown or timed out");}
            final Sequence seq = (Sequence) queryResult.result;
            if (start < 1 || start > seq.getItemCount())
                {throw new RuntimeException(
                        "index " + start + " out of bounds (" + seq.getItemCount() + ")");}
            if (start + howmany > seq.getItemCount() || howmany == 0)
                {howmany = seq.getItemCount() - start + 1;}
           
            final String xml[] = new String[howmany];
            final Serializer serializer = broker.getSerializer();
            serializer.reset();
            serializer.setProperty(OutputKeys.INDENT, indent ? "yes" : "no");
            serializer.setProperty(EXistOutputKeys.EXPAND_XINCLUDES, xinclude ? "yes" : "no");
            serializer.setProperty(EXistOutputKeys.HIGHLIGHT_MATCHES, highlight);
           
            Item item;
            int j = 0;
            for (int i = --start; i < start + howmany; i++, j++) {
                item = seq.itemAt(i);
                if (item == null)
                    {continue;}
                if (item.getType() == Type.ELEMENT) {
                    final NodeValue node = (NodeValue) item;
                    xml[j] = serializer.serialize(node);
                } else {
                    xml[j] = item.getStringValue();
                }
            }
            return xml;
        } catch (final Exception e) {
            LOG.warn(e);
            e.printStackTrace();
            throw new RemoteException(e.getMessage(), e);
        } finally {
            pool.release(broker);
        }
    }
   
    public java.lang.String[] retrieveByDocument(java.lang.String sessionId, int start, int howmany, java.lang.String path, boolean indent, boolean xinclude, java.lang.String highlight) throws java.rmi.RemoteException {
        final Session session = getSession(sessionId);
        DBBroker broker = null;
        try {
            broker = pool.get(session.getUser());
            final Sequence qr = (Sequence) session.getQueryResult().result;
            if (qr == null)
                {throw new RemoteException("result set unknown or timed out");}
            String xml[] = null;
            if (Type.subTypeOf(qr.getItemType(), Type.NODE)) {
                // Fix typecast exception RMT
//        NodeList resultSet = (NodeSet)qr;
                final ExtArrayNodeSet hitsByDoc = new ExtArrayNodeSet();
                NodeProxy p;
                String ppath;
                for (final SequenceIterator i = qr.iterate(); i.hasNext(); ) {
//        for (Iterator i = ((NodeSet) resultSet).iterator(); i.hasNext();) {
                    p = (NodeProxy) i.nextItem();
                    ///TODO : use dedicated function in XmldbURI
                    ppath = p.getDocument().getCollection().getURI().toString() + '/' + p.getDocument().getFileURI();
                    if (ppath.equals(path))
                        {hitsByDoc.add(p);}
                }
                --start;
                if (start < 0 || start > hitsByDoc.getLength())
                    {throw new RemoteException(
                            "index " + start + "out of bounds (" + hitsByDoc.getLength() + ")");}
                if (start + howmany >= hitsByDoc.getLength())
                    {howmany = hitsByDoc.getLength() - start;}
                final Serializer serializer = broker.getSerializer();
                serializer.reset();
                serializer.setProperty(OutputKeys.INDENT, indent ? "yes" : "no");
                serializer.setProperty(EXistOutputKeys.EXPAND_XINCLUDES, xinclude ? "yes" : "no");
                serializer.setProperty(EXistOutputKeys.HIGHLIGHT_MATCHES, highlight);
               
                xml = new String[howmany];
                int j=0;
                for (int i = start; i < start + howmany; i++) {
                    final NodeProxy proxy = ((NodeSet) hitsByDoc).get(i);
                    if (proxy == null)
                        {throw new RuntimeException("not found: " + start);}
                    xml[j] = serializer.serialize(proxy);
                    j++; // update count number of results
                }
            } else
                {throw new RemoteException("result set is not a node list");}
            return xml;
        } catch (final Exception e) {
            LOG.warn(e);
            e.printStackTrace();
            throw new RemoteException(e.getMessage(), e);
        } finally {
            pool.release(broker);
        }
    }
   
    private TreeMap scanResults(Sequence results) throws RemoteException {
        final TreeMap collections = new TreeMap();
        TreeMap documents;
        Integer hits;
        try {
      for (final SequenceIterator i = results.iterate(); i.hasNext(); ) {
          final Item item = i.nextItem();
          if(Type.subTypeOf(item.getType(), Type.NODE)) {
              final NodeValue node = (NodeValue)item;
              if(node.getImplementationType() == NodeValue.PERSISTENT_NODE) {
                  final NodeProxy p = (NodeProxy)node;
                  if ((documents = (TreeMap) collections.get(p.getDocument().getCollection().getURI())) == null) {
                      documents = new TreeMap();
                      collections.put(p.getDocument().getCollection().getURI(), documents);
                  }
                  if ((hits = (Integer) documents.get(p.getDocument().getFileURI())) == null)
                      documents.put(p.getDocument().getFileURI(), Integer.valueOf(1));
                  else
                      documents.put(p.getDocument().getFileURI(), Integer.valueOf(hits.intValue() + 1));
              }
          }
      }
    } catch (final XPathException e) {
      throw new RemoteException(e.getMessage());
    }
        return collections;
    }
}
TOP

Related Classes of org.exist.soap.QuerySoapBindingImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.