Package org.exist.xmldb

Source Code of org.exist.xmldb.LocalBinaryResource

/*
*  eXist Open Source Native XML Database
*  Copyright (C) 2001-06 Wolfgang M. Meier
*  wolfgang@exist-db.org
*  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.xmldb;

import org.exist.EXistException;
import org.exist.dom.BinaryDocument;
import org.exist.dom.DocumentImpl;
import org.apache.commons.io.output.ByteArrayOutputStream;
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.util.EXistInputSource;
import org.exist.util.LockException;
import org.xml.sax.InputSource;
import org.xmldb.api.base.Collection;
import org.xmldb.api.base.ErrorCodes;
import org.xmldb.api.base.XMLDBException;
import org.xmldb.api.modules.BinaryResource;

import java.io.*;
import java.util.Date;
import org.exist.security.PermissionDeniedException;

/**
* @author wolf
*/
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;
 
  /**
   *
   */
  public LocalBinaryResource(Subject user, BrokerPool pool, LocalCollection collection, XmldbURI docId) {
    super(user, pool, collection, docId, null);
  }
 
  /* (non-Javadoc)
   * @see org.xmldb.api.base.Resource#getParentCollection()
   */
  public Collection getParentCollection() throws XMLDBException {
    return parent;
  }
 
  /* (non-Javadoc)
   * @see org.xmldb.api.base.Resource#getId()
   */
  public String getId() throws XMLDBException {
    return docId.toString();
  }

  /* (non-Javadoc)
   * @see org.xmldb.api.base.Resource#getResourceType()
   */
  public String getResourceType() throws XMLDBException {
    return "BinaryResource";
  }

  public Object getExtendedContent() throws XMLDBException {
    if(file!=null)
      {return file;}
    if(inputSource!=null)
      {return inputSource;}

    final Subject preserveSubject = pool.getSubject();
    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(final EXistException e) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
        "error while loading binary resource " + getId(), e);
    } catch(final 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);}
     
      pool.setSubject(preserveSubject);
    }
   
    return rawDataStream;
  }
 
  /* (non-Javadoc)
   * @see org.xmldb.api.base.Resource#getContent()
   */
  public Object getContent() throws XMLDBException {
    final 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 res;
  }

  /* (non-Javadoc)
   * @see org.xmldb.api.base.Resource#setContent(java.lang.Object)
   */
  public void setContent(Object value) throws XMLDBException {
    if(value instanceof File) {
      file=(File)value;
      isExternal=true;
    } else if(value instanceof InputSource) {
      inputSource=(InputSource)value;
      isExternal=true;
    } else if(value instanceof byte[]) {
      rawData = (byte[])value;
      isExternal=true;
    } else if(value instanceof String) {
      rawData = ((String)value).getBytes();
      isExternal=true;
    } else
      {throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
        "don't know how to handle value of type " + value.getClass().getName());}
  }
 
  public InputStream getStreamContent() throws XMLDBException {
    InputStream retval=null;
    if(file!=null) {
      try {
        retval=new FileInputStream(file);
      } catch(final 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 {
      final Subject preserveSubject = pool.getSubject();
      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(final EXistException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
          "error while loading binary resource " + getId(), e);
      } catch(final 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);}
       
        pool.setSubject(preserveSubject);
      }
    }
   
    return retval;
  }
 
  public void getContentIntoAFile(File tmpfile) throws XMLDBException {
    try {
      final FileOutputStream fos=new FileOutputStream(tmpfile);
      final BufferedOutputStream bos=new BufferedOutputStream(fos);
      getContentIntoAStream(bos);
      bos.close();
      fos.close();
    } catch(final IOException ioe) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
          "error while loading binary resource " + getId(), ioe);
    }
  }
 
  public void getContentIntoAStream(OutputStream os) throws XMLDBException {
    final Subject preserveSubject = pool.getSubject();
    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(final EXistException e) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
        "error while loading binary resource " + getId(), e);
    } catch(final 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);}
     
      pool.setSubject(preserveSubject);
      if(doClose) {
        try {
          os.close();
        } catch(final IOException ioe) {
          // IgnoreIT(R)
        }
      }
    }
  }
 
        @Override
  public void freeResources()
  {
    if(!isExternal && file!=null) {
      file=null;
    }
  }
 
  public long getStreamLength() throws XMLDBException {
    long retval=-1;
    if(file!=null) {
      retval=file.length();
    } else if(inputSource!=null && inputSource instanceof EXistInputSource) {
      retval=((EXistInputSource)inputSource).getByteStreamLength();
    } else if(rawData!=null) {
      retval=rawData.length;
    } else {
      final Subject preserveSubject = pool.getSubject();
      DBBroker broker = null;
      BinaryDocument blob = null;
      try {
        broker = pool.get(user);
        blob = (BinaryDocument)getDocument(broker, Lock.READ_LOCK);
        retval=blob.getContentLength();
      } catch(final 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);}
       
        pool.setSubject(preserveSubject);
      }
    }
   
    return retval;
  }
 
  private byte[] readFile(File file) throws XMLDBException {
    try {
      return readFile(new FileInputStream(file));
    } catch (final FileNotFoundException e) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
        "file " + file.getAbsolutePath() + " could not be found", e);
    }
  }

  private byte[] readFile(InputSource is) throws XMLDBException {
    return readFile(is.getByteStream());
  }

  private byte[] readFile(InputStream is) throws XMLDBException {
    try {
      final ByteArrayOutputStream bos = new ByteArrayOutputStream(2048);
      final byte[] temp = new byte[1024];
      int count = 0;
      while((count = is.read(temp)) > -1) {
        bos.write(temp, 0, count);
      }
      return bos.toByteArray();
    } catch (final FileNotFoundException e) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
        "file " + file.getAbsolutePath() + " could not be found", e);
    } catch (final IOException e) {
      throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
        "IO exception while reading file " + file.getAbsolutePath(), e);
    } finally {
      try {
        is.close();
      } catch (final IOException e) {
        throw new XMLDBException(ErrorCodes.VENDOR_ERROR,
            "IO exception while closing stream of file " + file.getAbsolutePath(), e);
      }
    }
  }

  /* (non-Javadoc)
   * @see org.exist.xmldb.EXistResource#getCreationTime()
   */
  public Date getCreationTime() throws XMLDBException {
        if (isNewResource)
            {throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, "The resource has not yet been stored");}
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    try {
      broker = pool.get(user);
      final BinaryDocument blob = (BinaryDocument)getDocument(broker, Lock.NO_LOCK);
      return new Date(blob.getMetadata().getCreated());
    } 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#getLastModificationTime()
   */
  public Date getLastModificationTime() throws XMLDBException {
        if (isNewResource)
            {throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, "The resource has not yet been stored");}
    final Subject preserveSubject = pool.getSubject();
    DBBroker broker = null;
    try {
      broker = pool.get(user);
      final BinaryDocument blob = (BinaryDocument)getDocument(broker, Lock.NO_LOCK);
      return new Date(blob.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.AbstractEXistResource#getMimeType()
     */
    public String getMimeType() throws XMLDBException {
        if (isNewResource)
            {return mimeType;}
    final Subject preserveSubject = pool.getSubject();
        DBBroker broker = null;
        try {
            broker = pool.get(user);
            final BinaryDocument blob = (BinaryDocument)getDocument(broker, Lock.NO_LOCK);
            mimeType = blob.getMetadata().getMimeType();
            return mimeType;
        } 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#getMode()
   */
  public Permission getPermissions() throws XMLDBException {
        if (isNewResource)
            {throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, "The resource has not yet been stored");}
    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#getContentLength()
   */
  public long getContentLength() throws XMLDBException {
        if (isNewResource)
            {throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, "The resource has not yet been stored");}
    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);
    }
  }
 
  protected DocumentImpl getDocument(DBBroker broker, int lock) throws XMLDBException {
      DocumentImpl document = null;
      if(lock != Lock.NO_LOCK) {
                try {
                    document = parent.getCollection().getDocumentWithLock(broker, docId, lock);
                } catch (final PermissionDeniedException e) {
                    throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
                            "Permission denied for document " + docId + ": " + e.getMessage());
                } catch (final LockException e) {
                    throw new XMLDBException(ErrorCodes.PERMISSION_DENIED,
                            "Failed to acquire lock on document " + docId);
                }
            } else {
                try {
                    document = parent.getCollection().getDocument(broker, docId);
                } catch (final PermissionDeniedException e) {
                    throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "Permission denied for document " + docId + ": " + e.getMessage());
                }
            }
     
            if (document == null) {
          throw new XMLDBException(ErrorCodes.INVALID_RESOURCE);
            }
     
            if (document.getResourceType() != DocumentImpl.BINARY_FILE) {
          throw new XMLDBException(ErrorCodes.WRONG_CONTENT_TYPE, "Document " + docId +
                  " is not a binary resource");
            }
           
      return document;
  }
 
  protected DocumentImpl openDocument(DBBroker broker, int lockMode) throws XMLDBException {
      final DocumentImpl document = super.openDocument(broker, lockMode);
      if (document.getResourceType() != DocumentImpl.BINARY_FILE) {
        closeDocument(document, lockMode);
          throw new XMLDBException(ErrorCodes.WRONG_CONTENT_TYPE, "Document " + docId +
                  " is not a binary resource");
      }
      return document;
  }
}
TOP

Related Classes of org.exist.xmldb.LocalBinaryResource

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.