Package org.exist.xquery.util

Source Code of org.exist.xquery.util.DocUtils

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

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URISyntaxException;

import org.exist.Namespaces;
import org.exist.dom.DocumentImpl;
import org.exist.dom.NodeProxy;
import org.exist.memtree.SAXAdapter;
import org.exist.security.Permission;
import org.exist.security.PermissionDeniedException;
import org.exist.storage.BrokerPool;
import org.exist.storage.lock.Lock;
import org.exist.xmldb.XmldbURI;
import org.exist.xquery.XPathException;
import org.exist.xquery.XQueryContext;
import org.exist.xquery.value.Sequence;
import org.exist.source.Source;
import org.exist.source.SourceFactory;
import org.exist.source.URLSource;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;

/**
* Utilities for XPath doc related functions
*
* @author wolf
* @author Pierrick Brihaye <pierrick.brihaye@free.fr>
*/
//TODO : many more improvements to handle efficiently any URI
public class DocUtils
 
  public static Sequence getDocument(XQueryContext context, String path) throws XPathException, PermissionDeniedException {
    return getDocumentByPath(context, path);
  }
 
  public static boolean isDocumentAvailable(XQueryContext context, String path) throws XPathException {
    try {
      final Sequence seq = getDocumentByPath(context, path);
      return (seq != null && seq.effectiveBooleanValue());
    }
    catch (final PermissionDeniedException e) {
      return false;
    }
   
  } 

  private static Sequence getDocumentByPath(XQueryContext context, String path) throws XPathException, PermissionDeniedException
  {  
    Sequence document = Sequence.EMPTY_SEQUENCE; 

    if(path.matches("^[a-z]+:.*") && !path.startsWith("xmldb:"))
    {
            XMLReader reader = null;
      /* URL */
            try {
                final Source source = SourceFactory.getSource(context.getBroker(), "", path, false);
                final InputStream istream = source.getInputStream();
                if (source instanceof URLSource) {
                    final int responseCode = ((URLSource) source).getResponseCode();
                    if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
                        // Special case: '404'
                        return Sequence.EMPTY_SEQUENCE;
                    } else if (responseCode != HttpURLConnection.HTTP_OK) {
                        throw new PermissionDeniedException("Server returned code " + responseCode);
                    }
                }

                //TODO : process pseudo-protocols URLs more efficiently.
                org.exist.memtree.DocumentImpl memtreeDoc = null;
                // we use eXist's in-memory DOM implementation
                reader = context.getBroker().getBrokerPool().getParserPool().borrowXMLReader();
                //TODO : we should be able to cope with context.getBaseURI()
                final InputSource src = new InputSource(istream);
                final SAXAdapter adapter = new SAXAdapter();
                reader.setContentHandler(adapter);
                reader.parse(src);
                final Document doc = adapter.getDocument();
                memtreeDoc = (org.exist.memtree.DocumentImpl)doc;
                memtreeDoc.setContext(context);
                memtreeDoc.setDocumentURI(path);
                document = memtreeDoc;

            } catch(final ConnectException e) {
                // prevent long stacktraces
                throw new XPathException(e.getMessage()+ " ("+path+")");

            } catch(final MalformedURLException e) {
                throw new XPathException(e.getMessage(), e);

            } catch(final SAXException e) {
                throw new XPathException("An error occurred while parsing " + path + ": " + e.getMessage(), e);
            }
            catch(final IOException e) {
                // Special case: FileNotFoundException
                if(e instanceof FileNotFoundException)
                {
                    return Sequence.EMPTY_SEQUENCE;
                }
                else
                {
                    throw new XPathException("An error occurred while parsing " + path + ": " + e.getMessage(), e);
                }
            } finally {
                if (reader != null)
                    {context.getBroker().getBrokerPool().getParserPool().returnXMLReader(reader);}
            }
    }
    else
    {
      /* Database documents */

      // check if the loaded documents should remain locked
      boolean lockOnLoad = context.lockDocumentsOnLoad();
            final int lockType = lockOnLoad ? Lock.WRITE_LOCK : Lock.READ_LOCK;
      DocumentImpl doc = null;
      try
      {
        XmldbURI pathUri = XmldbURI.xmldbUriFor(path, false);
       
        final XmldbURI baseURI = context.getBaseURI().toXmldbURI();
        if (baseURI != null && !(baseURI.equals("") || baseURI.equals("/db"))) {
          // relative collection Path: add the current base URI
          pathUri = baseURI.resolveCollectionPath(pathUri);
        }

        // relative collection Path: add the current module call URI
        try {
          pathUri = XmldbURI.xmldbUriFor(context.getModuleLoadPath()).resolveCollectionPath(pathUri);
        } catch (final Exception e) {
          //workaround: ignore Windows issue
        }

        // try to open the document and acquire a lock
        doc = context.getBroker().getXMLResource(pathUri, lockType);
        if(doc != null)
        {
          if(!doc.getPermissions().validate(context.getSubject(), Permission.READ))
          {
            doc.getUpdateLock().release(lockType);
            throw new PermissionDeniedException("Insufficient privileges to read resource " + path);
          }
         
                    if(doc.getResourceType() == DocumentImpl.BINARY_FILE)
                    {
                        throw new XPathException("Document " + path + " is a binary resource, not an XML document. Please consider using the function util:binary-doc() to retrieve a reference to it.");
                    }

                    if(lockOnLoad)
                    {
            // add the document to the list of locked documents
            context.addLockedDocument(doc);
          }
          document = new NodeProxy(doc);
        }
      }
      catch(final PermissionDeniedException e)
      {
        throw e;
      }
      catch(final URISyntaxException e)
      {
        throw new XPathException(e);
      }
      finally
      {
        // release all locks unless lockOnLoad is true
        if(!lockOnLoad && doc != null)
          {doc.getUpdateLock().release(lockType);}
      }
    }      
    return document;
  }

    public static org.exist.memtree.DocumentImpl parse(XQueryContext context, InputStream istream) throws XPathException {
        return parse(context.getBroker().getBrokerPool(), context, istream);
    }

  /**
   * Utility function to parse an input stream into an in-memory DOM document.
   *
   * @param pool
   * @param istream
   * @return document
   * @throws XPathException
   */
  public static org.exist.memtree.DocumentImpl parse(BrokerPool pool, XQueryContext context, InputStream istream) throws XPathException {
    // we use eXist's in-memory DOM implementation
        final XMLReader reader = pool.getParserPool().borrowXMLReader();
        final InputSource src = new InputSource(istream);
        final SAXAdapter adapter = new SAXAdapter(context);
        reader.setContentHandler(adapter);
        try {
      reader.setProperty(Namespaces.SAX_LEXICAL_HANDLER, adapter);
      reader.parse(src);
    } catch (final SAXNotRecognizedException e) {
      throw new XPathException("Error creating XML parser: " + e.getMessage(), e);
    } catch (final SAXNotSupportedException e) {
      throw new XPathException("Error creating XML parser: " + e.getMessage(), e);
    } catch (final IOException e) {
      throw new XPathException("Error while parsing XML: " + e.getMessage(), e);
    } catch (final SAXException e) {
      throw new XPathException("Error while parsing XML: " + e.getMessage(), e);
    }
        return (org.exist.memtree.DocumentImpl) adapter.getDocument();
  }
}
TOP

Related Classes of org.exist.xquery.util.DocUtils

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.