Package org.exist.xmldb

Source Code of org.exist.xmldb.LocalXMLResource

/*
* eXist Open Source Native XML Database
* Copyright (C) 2003-2007 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.xmldb;

import org.exist.EXistException;
import org.exist.dom.DocumentImpl;
import org.exist.dom.NodeProxy;
import org.exist.dom.XMLUtil;
import org.exist.memtree.AttributeImpl;
import org.exist.memtree.NodeImpl;
import org.exist.numbering.NodeId;
import org.exist.security.Permission;
import org.exist.security.Subject;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.lock.Lock;
import org.exist.storage.serializers.Serializer;
import org.exist.storage.txn.TransactionManager;
import org.exist.storage.txn.Txn;
import org.exist.util.LockException;
import org.exist.util.MimeType;
import org.exist.util.serializer.DOMSerializer;
import org.exist.util.serializer.DOMStreamer;
import org.exist.util.serializer.SAXSerializer;
import org.exist.util.serializer.SerializerPool;
import org.exist.xquery.XPathException;
import org.exist.xquery.value.AtomicValue;
import org.exist.xquery.value.NodeValue;
import org.exist.xquery.value.StringValue;
import org.exist.xquery.value.Type;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Node;
import org.xml.sax.*;
import org.xml.sax.ext.LexicalHandler;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ErrorCodes;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.XMLResource;

import javax.xml.transform.TransformerException;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Date;
import java.util.Properties;
import org.exist.security.PermissionDeniedException;

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

/**
* Local implementation of XMLResource.
*/
public class LocalXMLResource extends AbstractEXistResource implements XMLResource {

  //protected DocumentImpl document = null;
  protected NodeProxy proxy = null;
 
  protected Properties outputProperties = null;
  protected LexicalHandler lexicalHandler = null;
 
  // those are the different types of content this resource
  // may have to deal with
  protected String content = null;
  protected File file = null;
  protected InputSource inputSource = null;
  protected Node root = null;
  protected AtomicValue value = null;
 
  protected Date datecreated= null;
  protected Date datemodified= null;

  public LocalXMLResource(Subject user, BrokerPool pool, LocalCollection parent,
      XmldbURI did) throws XMLDBException {
    super(user, pool, parent, did, MimeType.XML_TYPE.getName());
  }

  public LocalXMLResource(Subject user, BrokerPool pool, LocalCollection parent,
      NodeProxy p) throws XMLDBException {
    this(user, pool, parent, p.getDocument().getFileURI());
    this.proxy = p;
  }

  public Object getContent() throws XMLDBException {
    if (content != null) {           
      return content;
        }

    // Case 1: content is an external DOM node
    else if (root != null && !(root instanceof NodeValue)) {
            final StringWriter writer = new StringWriter();
      final DOMSerializer serializer = new DOMSerializer(writer, getProperties());
      try {
        serializer.serialize(root);
        content = writer.toString();
      } catch (final TransformerException e) {
        throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, e
            .getMessage(), e);
      }
      return content;

      // Case 2: content is an atomic value
    } else if (value != null) {
      try {
                if (Type.subTypeOf(value.getType(),Type.STRING)) {
                    return ((StringValue)value).getStringValue(true);
                }
                else {
        return value.getStringValue();
                }



      } catch (final XPathException e) {
        throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, e
            .getMessage(), e);
      }

      // Case 3: content is a file
    } else if (file != null) {
      try {
        content = XMLUtil.readFile(file);
        return content;
      } catch (final IOException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
            "error while reading resource contents", e);
      }

      // Case 4: content is an input source
    } else if (inputSource != null) {
      try {
        content = XMLUtil.readFile(inputSource);
        return content;
      } catch (final IOException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
            "error while reading resource contents", e);
      }

      // Case 5: content is a document or internal node
    } else {
        DocumentImpl document = null;
      final Subject preserveSubject = pool.getSubject();
      DBBroker broker = null;
      try {
        broker = pool.get(user);
        final Serializer serializer = broker.getSerializer();
        serializer.setUser(user);
        serializer.setProperties(getProperties());
        if (root != null) {
          content = serializer.serialize((NodeValue) root);
                   
                } else if (proxy != null) {
                    content = serializer.serialize(proxy);
                   
                } else {
            document = openDocument(broker, Lock.READ_LOCK);
          if (!document.getPermissions().validate(user,
              Permission.READ))
            {throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
                "permission denied to read resource");}
          content = serializer.serialize(document);
                }
        return content;
      } catch (final SAXException saxe) {
        saxe.printStackTrace();
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, saxe
            .getMessage(), saxe);
      } catch (final EXistException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e
            .getMessage(), e);
      } catch (final Exception e) {
        e.printStackTrace();
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e
            .getMessage(), e);
      } finally {
          closeDocument(document, Lock.READ_LOCK);
        pool.release(broker);
        pool.setSubject(preserveSubject);
      }
    }
  }

  public Node getContentAsDOM() throws XMLDBException {
    if (root != null) {
            if(root instanceof NodeImpl) {
            final Subject preserveSubject = pool.getSubject();
          DBBroker broker = null;
          try {
            broker = pool.get(user);
           
            ((NodeImpl)root).expand();
          } catch (final EXistException e) {
            throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
          } finally {
            pool.release(broker);
            pool.setSubject(preserveSubject);
          }
            }
      return root;
        } else if (value != null) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
          "cannot return an atomic value as DOM node");
    } else {
        DocumentImpl document = null;
      final Subject preserveSubject = pool.getSubject();
      DBBroker broker = null;
      try {
        broker = pool.get(user);
        document = getDocument(broker, Lock.READ_LOCK);
        if (!document.getPermissions().validate(user, Permission.READ))
          {throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
              "permission denied to read resource");}
        if (proxy != null)
          {return document.getNode(proxy);}
                // <frederic.glorieux@ajlsm.com> return a full to get root PI and comments
                return document;
      } catch (final EXistException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e
            .getMessage(), e);
      } finally {
          parent.getCollection().releaseDocument(document, Lock.READ_LOCK);
        pool.release(broker);
        pool.setSubject(preserveSubject);
      }
    }
  }

  public void getContentAsSAX(ContentHandler handler) throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    // case 1: content is an external DOM node
    if (root != null && !(root instanceof NodeValue)) {
      try {
        final String option = parent.properties.getProperty(
            Serializer.GENERATE_DOC_EVENTS, "false");
                final DOMStreamer streamer = (DOMStreamer) SerializerPool.getInstance().borrowObject(DOMStreamer.class);
        streamer.setContentHandler(handler);
        streamer.setLexicalHandler(lexicalHandler);
        streamer.serialize(root, option.equalsIgnoreCase("true"));
        SerializerPool.getInstance().returnObject(streamer);
      } catch (final Exception e) {
        throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, e
            .getMessage(), e);
      }
     
    // case 2: content is an atomic value
    } else if (value != null) {
      try {
        broker = pool.get(user);
        value.toSAX(broker, handler, getProperties());
      } catch (final EXistException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e
            .getMessage(), e);
      } catch (final SAXException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e
            .getMessage(), e);
      } finally {
        pool.release(broker);
        pool.setSubject(preserveSubject);
      }
     
    // case 3: content is an internal node or a document
    } else {
      try {
        broker = pool.get(user);
        final Serializer serializer = broker.getSerializer();
        serializer.setUser(user);
        serializer.setProperties(getProperties());
        serializer.setSAXHandlers(handler, lexicalHandler);
        if (root != null) {
          serializer.toSAX((NodeValue) root);
                   
                } else if (proxy != null) {
                    serializer.toSAX(proxy);
                   
                } else {
          DocumentImpl document = null;
          try {
            document = openDocument(broker, Lock.READ_LOCK);
            if (!document.getPermissions().validate(user,
                Permission.READ))
              {throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
              "permission denied to read resource");}
            serializer.toSAX(document);
          } finally {
              closeDocument(document, Lock.READ_LOCK);
          }
        }
      } catch (final EXistException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e
            .getMessage(), e);
      } catch (final SAXException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e
            .getMessage(), e);
      } finally {
        pool.release(broker);
        pool.setSubject(preserveSubject);
      }
    }
  }

  //TODO: use xmldbURI?
  public String getDocumentId() throws XMLDBException {
    return docId.toString();
  }

  //TODO: use xmldbURI?
  public String getId() throws XMLDBException {
    return docId.toString();
  }

  public Collection getParentCollection() throws XMLDBException {
    if (parent == null)
      {throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
          "collection parent is null");}
    return parent;
  }

  public String getResourceType() throws XMLDBException {
    return "XMLResource";
  }

  public Date getCreationTime() throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    try {
      broker = pool.get(user);
      final DocumentImpl document = getDocument(broker, Lock.NO_LOCK);
      return new Date(document.getMetadata().getCreated());
    } catch (final EXistException e) {
      throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(),
          e);
    } finally {
      pool.release(broker);
      pool.setSubject(preserveSubject);
    }
  }

  public Date getLastModificationTime() throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    try {
      broker = pool.get(user);
      final DocumentImpl document = getDocument(broker, Lock.NO_LOCK);
      return new Date(document.getMetadata().getLastModified());
    } catch (final EXistException e) {
      throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(),
          e);
    } finally {
      pool.release(broker);
      pool.setSubject(preserveSubject);
    }
  }
 
  /* (non-Javadoc)
   * @see org.exist.xmldb.EXistResource#getContentLength()
   */
  public long getContentLength() throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    try {
      broker = pool.get(user);
      final DocumentImpl document = getDocument(broker, Lock.NO_LOCK);
      return document.getContentLength();
    } catch (final EXistException e) {
      throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(),
          e);
    } finally {
      pool.release(broker);
      pool.setSubject(preserveSubject);
    }
  }

  /**
   * Sets the content for this resource. If value is of type File, it is
   * directly passed to the parser when Collection.storeResource is called.
   * Otherwise the method tries to convert the value to String.
   *
   * Passing a File object should be preferred if the document is large. The
   * file's content will not be loaded into memory but directly passed to a
   * SAX parser.
   *
   * @param obj
   *                   the content value to set for the resource.
   * @exception XMLDBException
   *                         with expected error codes. <br /><code>ErrorCodes.VENDOR_ERROR</code>
   *                         for any vendor specific errors that occur. <br />
   */
  public void setContent(Object obj) throws XMLDBException {
    content = null;
    file = null;
    value = null;
    inputSource = null;
    root = null;
    if (obj instanceof File)
      {file = (File) obj;}

    else if (obj instanceof AtomicValue)
      {value = (AtomicValue) obj;}

    else if (obj instanceof InputSource)
      {inputSource=(InputSource) obj;}

        else if (obj instanceof byte[]){
            content = new String((byte[])obj, UTF_8);

        } else {
      content = obj.toString();
    }
  }

  public void setContentAsDOM(Node root) throws XMLDBException {
    if (root instanceof AttributeImpl)
      {throw new XMLDBException(ErrorCodes.WRONG_CONTENT_TYPE,
          "SENR0001: can not serialize a standalone attribute");}
    content = null;
    file = null;
    value = null;
    inputSource = null;
    this.root = root;
  }

  public ContentHandler setContentAsSAX() throws XMLDBException {
    file = null;
    value = null;
    inputSource = null;
    root = null;
    return new InternalXMLSerializer();
  }
       
        @Override
        public void freeResources() throws XMLDBException {
            //dO nothing
            //TODO consider unifying closeDocument() code into freeResources()
        }

  private class InternalXMLSerializer extends SAXSerializer {

    public InternalXMLSerializer() {
      super(new StringWriter(), null);
    }

    /**
     * @see org.xml.sax.DocumentHandler#endDocument()
     */
    public void endDocument() throws SAXException {
      super.endDocument();
      content = getWriter().toString();
    }
  }

  public boolean getSAXFeature(String arg0) throws SAXNotRecognizedException,
      SAXNotSupportedException {
    return false;
  }

  public void setSAXFeature(String arg0, boolean arg1)
      throws SAXNotRecognizedException, SAXNotSupportedException {
  }

  /*
   * (non-Javadoc)
   *
   * @see org.exist.xmldb.EXistResource#getMode()
   */
  public Permission getPermissions() throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
      DBBroker broker = null;
      try {
          broker = pool.get(user);
        final DocumentImpl document = getDocument(broker, Lock.NO_LOCK);
      return document != null ? document.getPermissions() : null;
      } catch (final EXistException e) {
            throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, e.getMessage(), e);
        } finally {
          pool.release(broker);
      pool.setSubject(preserveSubject);
      }
  }
 
  /* (non-Javadoc)
   * @see org.exist.xmldb.EXistResource#setLexicalHandler(org.xml.sax.ext.LexicalHandler)
   */
  public void setLexicalHandler(LexicalHandler handler) {
    lexicalHandler = handler;
  }
 
  protected void setProperties(Properties properties) {
    this.outputProperties = properties;
  }
 
  private Properties getProperties() {
    return outputProperties == null ? parent.properties : outputProperties;
  }

  protected DocumentImpl getDocument(DBBroker broker, int lock) throws XMLDBException {
      DocumentImpl document = null;
            try {
                if(lock != Lock.NO_LOCK) {
                    document = parent.getCollection().getDocumentWithLock(broker, docId, lock);
                 } else {
                    document = parent.getCollection().getDocument(broker, docId);
                }
            } catch (final LockException e) {
                throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
                        "Failed to acquire lock on document " + docId);
            } catch (final PermissionDeniedException pde) {
                throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
                        "Permission denied on document " + docId);
            }
    
      if (document == null) {
          throw new XMLDBException(ErrorCodes.INVALID_RESOURCE);
      }
      return document;
  }
 
  public NodeProxy getNode() throws XMLDBException {
      if(proxy != null)
          {return proxy;}
    final Subject preserveSubject = pool.getSubject();
      DBBroker broker = null;
      try {
          broker = pool.get(user);
          final DocumentImpl document = getDocument(broker, Lock.NO_LOCK);
          // this XMLResource represents a document
      return new NodeProxy(document, NodeId.DOCUMENT_NODE);
      } catch (final EXistException e) {
            throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, e.getMessage(), e);
        } finally {
          pool.release(broker);
      pool.setSubject(preserveSubject);
      }
  }

  public  DocumentType getDocType() throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    try {
      broker = pool.get(user);
      final DocumentImpl document = getDocument(broker, Lock.NO_LOCK);
      if (!document.getPermissions().validate(user, Permission.READ))
        {throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
            "permission denied to read resource");}

      return  document.getDoctype();     
    } catch (final EXistException e) {
      throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(),
          e);
    } finally {
      pool.release(broker);
      pool.setSubject(preserveSubject);
    }
}
 
  public void setDocType(DocumentType doctype) throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    DocumentImpl document = null;
     final TransactionManager transact = pool.getTransactionManager();
          final Txn transaction = transact.beginTransaction();
    try {
      broker = pool.get(user);
      document = openDocument(broker, Lock.WRITE_LOCK);
            
      if (document == null) {
                throw new EXistException("Resource "
                        + docId + " not found");
            }
     
      if (!document.getPermissions().validate(user, Permission.WRITE))
        {throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
            "User is not allowed to lock resource " + document.getFileURI());}
     
      document.setDocumentType(doctype);
           broker.storeXMLResource(transaction, document);
            transact.commit(transaction);


    } catch (final EXistException e) {
            transact.abort(transaction);
      throw new XMLDBException(ErrorCodes.UNKNOWN_ERROR, e.getMessage(),
          e);
    } finally {
            transact.close(transaction);
      closeDocument(document, Lock.WRITE_LOCK);
      pool.release(broker);
      pool.setSubject(preserveSubject);
    }
}
}
TOP

Related Classes of org.exist.xmldb.LocalXMLResource

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.