Package com.ettrema.json

Source Code of com.ettrema.json.PutJsonResource$NewFile

package com.ettrema.json;

import com.bradmcevoy.http.DeletableResource;
import com.bradmcevoy.http.FileItem;
import com.bradmcevoy.http.PostableResource;
import com.bradmcevoy.http.PutableResource;
import com.bradmcevoy.http.Range;
import com.bradmcevoy.http.ReplaceableResource;
import com.bradmcevoy.http.Request;
import com.bradmcevoy.http.Request.Method;
import com.bradmcevoy.http.Resource;
import com.bradmcevoy.http.Utils;
import com.bradmcevoy.http.exceptions.BadRequestException;
import com.bradmcevoy.http.exceptions.ConflictException;
import com.bradmcevoy.http.exceptions.NotAuthorizedException;
import com.bradmcevoy.io.FileUtils;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import net.sf.json.JSON;
import net.sf.json.JSONSerializer;
import net.sf.json.JsonConfig;
import net.sf.json.util.CycleDetectionStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Will use milton's PUT framework to support file uploads using POST and
* multipart encoding
*
* This will save the uploaded files with their given names into the parent
* collection resource.
*
* If a file already exists with the same name a ConflictException is thrown,
* unless you set the _autoname request parameter. If this parameter is present
* (ie with any value) the file will be saved with a non-conflicting file name
*
* Save file information is returned as JSON in the response content
*
* @author brad
*/
public class PutJsonResource extends JsonResource implements PostableResource {

    private static final Logger log = LoggerFactory.getLogger(PutJsonResource.class);
    public static final String PARAM_AUTONAME = "_autoname";
    public static final String PARAM_NAME = "name";
    public static final String PARAM_OVERWRITE = "overwrite";
    private final PutableResource wrapped;
    private final String href;
    private List<NewFile> newFiles;

    public PutJsonResource(PutableResource putableResource, String href) {
        super(putableResource, Request.Method.PUT.code, null);
        this.wrapped = putableResource;
        this.href = href;
    }

    @Override
    public String getContentType(String accepts) {
        String s = "application/x-javascript; charset=utf-8";
        s = "text/plain";
        return s;
        //return "application/json";
    }

    public String processForm(Map<String, String> parameters, Map<String, FileItem> files) throws ConflictException, NotAuthorizedException, BadRequestException {
        if (files.isEmpty()) {
            log.debug("no files uploaded");
            return null;
        }
        newFiles = new ArrayList<NewFile>();
        for (FileItem file : files.values()) {
            NewFile nf = new NewFile();
            String f = Utils.truncateFileName(file.getName());
            nf.setOriginalName(f);
            nf.setContentType(file.getContentType());
            nf.setLength(file.getSize());
            String newName = getName(f, parameters);
            String newHref = buildNewHref(href, newName);
            nf.setHref(newHref);
            newFiles.add(nf);
            log.debug("creating resource: " + newName + " size: " + file.getSize());
            InputStream in = null;
            Resource newResource;
            try {
                in = file.getInputStream();
                Resource existing = wrapped.child(newName);
                if( existing != null ) {
                    if( existing instanceof ReplaceableResource ) {
                        log.trace("existing resource is replaceable, so replace content");
                        ReplaceableResource rr = (ReplaceableResource) existing;
                        rr.replaceContent(in, null);
                    } else {
                        log.trace("existing resource is not replaceable, will be deleted");
                        if( existing instanceof DeletableResource ) {
                            DeletableResource dr = (DeletableResource) existing;
                            dr.delete();
                        } else {
                            log.trace("existing resource could not be deleted, is not deletable");
                        }
                    }
                } else {
                    log.trace("not overwriting");
                }
                newResource = wrapped.createNew(newName, in, file.getSize(), file.getContentType());
            } catch (NotAuthorizedException ex) {
                throw new RuntimeException(ex);
            } catch (BadRequestException ex) {
                throw new RuntimeException(ex);
            } catch (ConflictException ex) {
                throw new RuntimeException(ex);
            } catch (IOException ex) {
                throw new RuntimeException("Exception creating resource", ex);
            } finally {
                FileUtils.close(in);
            }
            log.trace("completed POST processing for file. Created: " + newResource.getName());
        }
        log.trace("completed all POST processing");
        return null;
    }

    /**
     * Returns a JSON representation of the newly created hrefs
     *
     * @param out
     * @param range
     * @param params
     * @param contentType
     * @throws IOException
     * @throws NotAuthorizedException
     */
    public void sendContent(OutputStream out, Range range, Map<String, String> params, String contentType) throws IOException, NotAuthorizedException {
        JsonConfig cfg = new JsonConfig();
        cfg.setIgnoreTransientFields(true);
        cfg.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);

        NewFile[] arr;
        if (newFiles != null) {
            arr = new NewFile[newFiles.size()];
        } else {
            arr = new NewFile[0];
        }
        arr = newFiles.toArray(arr);
        Writer writer = new PrintWriter(out);
        JSON json = JSONSerializer.toJSON(arr, cfg);
        json.write(writer);
        writer.flush();
    }

    @Override
    public Method applicableMethod() {
        return Method.PUT;
    }

    /**
     * We dont return anything, so best not use json
     *
     * @param accepts
     * @return
     */
//    @Override
//    public String getContentType(String accepts) {
//        return "text/html";
//    }
    private String getName(String filename, Map<String, String> parameters) throws ConflictException, NotAuthorizedException, BadRequestException {
        String initialName = filename;
        if( parameters.containsKey(PARAM_NAME)) {
            initialName = parameters.get(PARAM_NAME);
        }
        boolean nonBlankName = initialName != null && initialName.trim().length() > 0;
        boolean autoname = (parameters.get(PARAM_AUTONAME) != null);
        boolean overwrite = (parameters.get(PARAM_OVERWRITE) != null);
        if (nonBlankName) {
            Resource child = wrapped.child(initialName);
            if (child == null) {
                log.trace("no existing file with that name");
                return initialName;
            } else {
                if (overwrite) {
                    log.trace("file exists, and overwrite parameters is set, so allow overwrite: " + initialName);
                    return initialName;
                } else {
                    if (!autoname) {
                        log.warn("Conflict: Can't create resource with name " + initialName + " because it already exists. To rename automatically use request parameter: " + PARAM_AUTONAME + ", or to overwrite use " + PARAM_OVERWRITE);
                        throw new ConflictException(this);
                    } else {
                        log.trace("file exists and autoname is set, so will find acceptable name");
                    }
                }
            }
        } else {
            initialName = getDateAsName("upload");
            log.trace("no name given in request");
        }
        return findAcceptableName(initialName);
    }

    private String getDateAsName(String base) {
        Calendar cal = Calendar.getInstance();
        return base + "_" + cal.get(Calendar.YEAR) + "-" + cal.get(Calendar.MONTH) + "-" + cal.get(Calendar.DAY_OF_MONTH);
    }

    private String findAcceptableName(String initialName) throws ConflictException {
        String baseName = FileUtils.stripExtension(initialName);
        String ext = FileUtils.getExtension(initialName);
        return findAcceptableName(baseName, ext, 1);
    }

    private String findAcceptableName(String baseName, String ext, int i) throws ConflictException {
        String candidateName = baseName + "_" + i;
        if (ext != null && ext.length() > 0) {
            candidateName += "." + ext;
        }
        if (wrapped.child(candidateName) == null) {
            return candidateName;
        } else {
            if (i < 100) {
                return findAcceptableName(baseName, ext, i + 1);
            } else {
                log.warn("Too many files with similar names: " + candidateName);
                throw new ConflictException(this);
            }
        }
    }

    private String buildNewHref(String href, String newName) {
        String s = href;
        int pos = href.lastIndexOf("_DAV");
        s = s.substring(0, pos - 1);
        if (!s.endsWith("/")) {
            s += "/";
        }
        s += newName;
        return s;
    }

    public class NewFile {

        private String href;
        private String originalName;
        private long length;
        private String contentType;

        public String getHref() {
            return href;
        }

        public void setHref(String href) {
            this.href = href;
        }

        public String getOriginalName() {
            return originalName;
        }

        public void setOriginalName(String originalName) {
            this.originalName = originalName;
        }

        public long getLength() {
            return length;
        }

        public void setLength(long length) {
            this.length = length;
        }

        public String getContentType() {
            return contentType;
        }

        public void setContentType(String contentType) {
            this.contentType = contentType;
        }
    }
}
TOP

Related Classes of com.ettrema.json.PutJsonResource$NewFile

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.