<commit_before>/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-06 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.webdav.methods;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

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;
import org.exist.collections.triggers.TriggerException;
import org.exist.dom.DocumentImpl;
import org.exist.dom.LockToken;
import org.exist.security.PermissionDeniedException;
import org.exist.security.User;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.lock.Lock;
import org.exist.storage.txn.TransactionManager;
import org.exist.storage.txn.Txn;
import org.exist.util.LockException;
import org.exist.util.MimeTable;
import org.exist.util.MimeType;
import org.exist.xmldb.XmldbURI;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Implements the WebDAV PUT method.
 *
 * @author wolf
 * @author dizzz
 */
public class Put extends AbstractWebDAVMethod {
    
    public Put(BrokerPool pool) {
        super(pool);
    }
    
        /* (non-Javadoc)
         * @see org.exist.http.webdav.WebDAVMethod#process(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.exist.collections.Collection, org.exist.dom.DocumentImpl)
         */
    public void process(User user, HttpServletRequest request,
            HttpServletResponse response, XmldbURI path) throws ServletException, IOException {
        LOG.debug("PUT start");
        File tempFile = saveRequestContent(request);
        
        String url = tempFile.toURI().toASCIIString();
        String contentType = request.getContentType();
        DBBroker broker = null;
        Collection collection = null;
        
        boolean collectionLocked = true;
        TransactionManager transact = pool.getTransactionManager();
        Txn txn = transact.beginTransaction();
        try {
            broker = pool.get(user);
            
        	XmldbURI pathUri = path.lastSegment();
        	XmldbURI collUri = path.removeLastSegment();
            
            LOG.debug("collUri='"+collUri+"';  path="+pathUri+"';" );
            
            collection = broker.openCollection(collUri, Lock.READ_LOCK);
            // TODO check why not use WRITE_LOCK here?
            if(collection == null) {
                transact.abort(txn);
                response.sendError(HttpServletResponse.SC_CONFLICT,
                        "Parent collection " + collUri + " not found");
                return;
            }
            if(collection.hasChildCollection(pathUri)) {
                transact.abort(txn);
                response.sendError(HttpServletResponse.SC_CONFLICT,
                        "Cannot overwrite an existing collection with a resource");
                return;
            }
            
//            MimeType mime = MimeTable.getInstance().getContentTypeFor(path);
//            if (mime == null){
//                mime = MimeType.BINARY_TYPE;
//            }
            
            // TODO why is content type involved here? would not like to use it,
            // as it seems to block binary file upload by MS office.
            
            MimeType mime;
            if(contentType == null) {
                mime = MimeTable.getInstance().getContentTypeFor(pathUri);
                if (mime != null)
                    contentType = mime.getName();
            } else {
                mime = MimeTable.getInstance().getContentType(contentType);
            }
            
            if (mime == null)
                mime = MimeType.BINARY_TYPE;
            
            
            LOG.debug("storing document " + pathUri
                    + "; content-type='" + contentType+"'");
            
            DocumentImpl doc = null;
            if(mime.isXMLType()) {
                LOG.debug("storing XML resource");
                InputSource is = new InputSource(url);
                IndexInfo info = collection.validateXMLResource(txn, broker, pathUri, is);
                doc = info.getDocument();
                doc.getMetadata().setMimeType(contentType);
                collection.release();
                collectionLocked = false;
                collection.store(txn, broker, info, is, false);
                LOG.debug("done");
            } else {
                LOG.debug("storing Binary resource");
                byte[] chunk = new byte[4096];
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                FileInputStream is = new FileInputStream(tempFile);
                int l;
                while((l = is.read(chunk)) > -1) {
                    os.write(chunk, 0, l);
                }
                
                doc = collection.addBinaryResource(txn, broker,
                		pathUri, os.toByteArray(), contentType);
                
                LOG.debug("done");
            }
            
            // Remove Null Resource flag
            LockToken token = doc.getMetadata().getLockToken();
            if(token!=null){
                token.setResourceType(LockToken.RESOURCE_TYPE_NOT_SPECIFIED);
            } else {
                LOG.debug("token==null");
            }
            
            transact.commit(txn);
            
            LOG.debug("PUT ready");
        } catch (EXistException e) {
            transact.abort(txn);<commit_msg>Mark work to do. In webDAV (REST too?) binary files are written into database as a blob. This can result into a "java.lang.OutOfMemoryError: Java heap space"<commit_after>/*
 *  eXist Open Source Native XML Database
 *  Copyright (C) 2001-06 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.webdav.methods;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

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;
import org.exist.collections.triggers.TriggerException;
import org.exist.dom.DocumentImpl;
import org.exist.dom.LockToken;
import org.exist.security.PermissionDeniedException;
import org.exist.security.User;
import org.exist.storage.BrokerPool;
import org.exist.storage.DBBroker;
import org.exist.storage.lock.Lock;
import org.exist.storage.txn.TransactionManager;
import org.exist.storage.txn.Txn;
import org.exist.util.LockException;
import org.exist.util.MimeTable;
import org.exist.util.MimeType;
import org.exist.xmldb.XmldbURI;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 * Implements the WebDAV PUT method.
 *
 * @author wolf
 * @author dizzz
 */
public class Put extends AbstractWebDAVMethod {
    
    public Put(BrokerPool pool) {
        super(pool);
    }
    
        /* (non-Javadoc)
         * @see org.exist.http.webdav.WebDAVMethod#process(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, org.exist.collections.Collection, org.exist.dom.DocumentImpl)
         */
    public void process(User user, HttpServletRequest request,
            HttpServletResponse response, XmldbURI path) throws ServletException, IOException {
        LOG.debug("PUT start");
        File tempFile = saveRequestContent(request);
        
        String url = tempFile.toURI().toASCIIString();
        String contentType = request.getContentType();
        DBBroker broker = null;
        Collection collection = null;
        
        boolean collectionLocked = true;
        TransactionManager transact = pool.getTransactionManager();
        Txn txn = transact.beginTransaction();
        try {
            broker = pool.get(user);
            
        	XmldbURI pathUri = path.lastSegment();
        	XmldbURI collUri = path.removeLastSegment();
            
            LOG.debug("collUri='"+collUri+"';  path="+pathUri+"';" );
            
            collection = broker.openCollection(collUri, Lock.READ_LOCK);
            // TODO check why not use WRITE_LOCK here?
            if(collection == null) {
                transact.abort(txn);
                response.sendError(HttpServletResponse.SC_CONFLICT,
                        "Parent collection " + collUri + " not found");
                return;
            }
            if(collection.hasChildCollection(pathUri)) {
                transact.abort(txn);
                response.sendError(HttpServletResponse.SC_CONFLICT,
                        "Cannot overwrite an existing collection with a resource");
                return;
            }
            
//            MimeType mime = MimeTable.getInstance().getContentTypeFor(path);
//            if (mime == null){
//                mime = MimeType.BINARY_TYPE;
//            }
            
            // TODO why is content type involved here? would not like to use it,
            // as it seems to block binary file upload by MS office.
            
            MimeType mime;
            if(contentType == null) {
                mime = MimeTable.getInstance().getContentTypeFor(pathUri);
                if (mime != null)
                    contentType = mime.getName();
            } else {
                mime = MimeTable.getInstance().getContentType(contentType);
            }
            
            if (mime == null)
                mime = MimeType.BINARY_TYPE;
            
            
            LOG.debug("storing document " + pathUri
                    + "; content-type='" + contentType+"'");
            
            DocumentImpl doc = null;
            if(mime.isXMLType()) {
                LOG.debug("storing XML resource");
                InputSource is = new InputSource(url);
                IndexInfo info = collection.validateXMLResource(txn, broker, pathUri, is);
                doc = info.getDocument();
                doc.getMetadata().setMimeType(contentType);
                collection.release();
                collectionLocked = false;
                collection.store(txn, broker, info, is, false);
                LOG.debug("done");
            } else {
                LOG.debug("storing Binary resource");
                
                // TODO Here binary data is written as a blob
                // into the database. This can cause Out of (heapsize) memory
                // exceptions
                
                // Write content of file into ByteArray
                byte[] chunk = new byte[4096];
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                FileInputStream is = new FileInputStream(tempFile);
                int l;
                while((l = is.read(chunk)) > -1) {
                    os.write(chunk, 0, l);
                }
                
                // Pass ByteArray in one step to collection
                doc = collection.addBinaryResource(txn, broker,
                		pathUri, os.toByteArray(), contentType);
                
                LOG.debug("done");
            }
            
            // Remove Null Resource flag
            LockToken token = doc.getMetadata().getLockToken();
            if(token!=null){
                token.setResourceType(LockToken.RESOURCE_TYPE_NOT_SPECIFIED);
            } else {
                LOG.debug("token==null");
            }
            
            transact.commit(txn);
            
            LOG.debug("PUT ready");
        } catch (EXistException e) {
            transact.abort(txn);
{'fraction_non_alphanumeric': 0.09302497413920496, 'fraction_numerical': 0.0035466233190483225, 'mean_word_length': 1.9964578259907018, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2262001', 'n_tokens_mistral': 3596, 'n_tokens_neox': 3482, 'n_words': 921}