Package com.bj58.argo.servlet

Source Code of com.bj58.argo.servlet.ArgoRequest$NullToEmptyMap

package com.bj58.argo.servlet;

import com.bj58.argo.Argo;
import com.bj58.argo.ArgoException;
import com.bj58.argo.client.SafeParameter;
import com.bj58.argo.client.Upload;
import com.bj58.argo.thirdparty.jetty.MultiMap;
import com.bj58.argo.thirdparty.jetty.MultiPartInputStreamParser;
import com.bj58.argo.thirdparty.jetty.UrlEncoded;
import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.*;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.io.CharStreams;

import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.Part;
import java.io.*;
import java.util.*;

/**
* 封装的request请求,包括参数处理,文件上传的
*
* @author renjun
*/
public class ArgoRequest extends HttpServletRequestWrapper implements Closeable {

    private final HttpServletRequest request;
    private final MultipartConfigElement config;


    private Type type = Type.UNKNOWN;
    private Map<String, Collection<String>> queryStrings = null;
    private Map<String, Collection<String>> forms = ImmutableMap.of();
    private Map<String, Collection<String>> params = ImmutableMap.of();
    private Map<String, Collection<Upload>> uploadMap = ImmutableMap.of();

    private Map<String, Collection<Upload>> originParts = ImmutableMap.of();

    private Collection<Upload> uploads = ImmutableSet.of();

    private MultiPartInputStreamParser multiParser;


    private int maxFormKeys = 1000// 最大的key数量
    private int maxFormContentSize = 200000; // post form数据的最大尺寸,jetty 200k, tomcat 2M
    public static int bufferSize = 64*1024;



    /**
     * Constructs a request object wrapping the given request.
     *
     * @throws IllegalArgumentException
     *          if the request is null
     */
    public ArgoRequest(HttpServletRequest request, MultipartConfigElement config) {
        super(request);

        this.request = request;
        this.config = config;

    }


    @Override
    public Collection<Part> getParts() throws IOException, ServletException {

        parsePost();
        // TODO:协变
        return Collections2.transform(uploads, new Function<Upload, Part>() {
            @Override
            public Part apply(Upload input) {
                return input;
            }
        });
    }

    @Override
    public Part getPart(String name) throws IOException, ServletException {
        return getUpload(name);
    }

    /* ------------------------------------------------------------------------------- */
    /**
     * @see javax.servlet.ServletRequest#getParameter(java.lang.String)
     */
    @Override
    public String getParameter(String name) {

        parsePost();

        return getParamsString(params, name, false);

    }


        /* ------------------------------------------------------------------------------- */
    /**
     * @see javax.servlet.ServletRequest#getParameterMap()
     */
    @Override
    public Map<String, String[]> getParameterMap()
    {
        parsePost();

        return Maps.transformValues(params, new Function<Collection<String>, String[]>() {
            @Override
            public String[] apply(Collection<String> input) {
                String[] values = new String[input.size()];
                return input.toArray(values);
            }
        });
    }

        /* ------------------------------------------------------------------------------- */
    /**
     * @see javax.servlet.ServletRequest#getParameterNames()
     */
    @Override
    public Enumeration<String> getParameterNames()
    {
        parsePost();

        return Collections.enumeration(params.keySet());
    }

        /* ------------------------------------------------------------------------------- */
    /**
     * @see javax.servlet.ServletRequest#getParameterValues(java.lang.String)
     */
    @Override
    public String[] getParameterValues(String name)
    {
        parsePost();

        Collection<String> vs = params.get(name);
        return vs == null ? new String[0]
                : vs.toArray(new String[vs.size()]);
    }

    @Override
    public void close() throws IOException {

        if (Type.MULTI != type)
            return;

        if (multiParser != null)
            multiParser.deleteParts();
    }



    public Map<String, Collection<String>> queryStrings() {

        if (queryStrings != null)
            return queryStrings;

        MultiMap<String> params = new MultiMap<String>();
        String originQueryString = super.getQueryString();
       
        if(queryStrings != null){
         
          UrlEncoded.decodeTo(originQueryString, params, "UTF-8", maxFormKeys);
 
          queryStrings = NullToEmptyMap.safeWrapper(params, getSafeParameter());
        }
        return queryStrings;

    }


    public String queryString(String name) {

        return getParamsString(queryStrings(), name, true);
    }

    public Map<String, Collection<String>> forms() {

        parsePost();

        return forms;
    }

    public String form(String name) {
        return getParamsString(forms(), name, true);
    }

    public Upload getUpload(String name) {

        parsePost();


        Collection<Upload> parts = uploadMap.get(name);
        return parts == null ? null
                : parts.size() == 0 ? null
                :  parts.iterator().next();
    }

    public Collection<Upload> uploads() {

        parsePost();
        return uploads;
    }


    private String getParamsString(Map<String, Collection<String>> params
            , String name, boolean nullToEmpty) {

        Collection<String> ps = params.get(name);
        return (ps == null || ps.size() == 0) ? nullToEmpty ? "" : null
                : ps.iterator().next();
    }



    private void parsePost() {
        if(Type.UNKNOWN != type)
            return;

        type = (!isPost(request)) ? Type.GET
                : isMultiPart(request) ? Type.MULTI : Type.POST;

        if (Type.GET == type)
            return;

        queryStrings();


        try {

            if (Type.MULTI == type)
                parsePostMulti();
            else
                parsePostUrlEncoded();

        } catch (Exception e) {
            throw ArgoException.raise(e);
        }

    }


    /**
     * application/x-www-form-urlencoded
     *
     */
    private void parsePostUrlEncoded() throws IOException {
        MultiMap<String> params = new MultiMap<String>();

        UrlEncoded.decodeTo(super.getInputStream(), params, "UTF-8", maxFormContentSize, maxFormKeys);

        forms = NullToEmptyMap.safeWrapper(params, getSafeParameter());
       
        Builder<String, Collection<String>> builder =  ImmutableMap.<String, Collection<String>>builder();
       
        if(queryStrings != null)
          builder.putAll(queryStrings);
       
        if(forms != null)
          builder.putAll(forms);
      
        this.params = builder.build();

    }

    private void parsePostMulti() throws IOException, ServletException {
        InputStream in = new BufferedInputStream(super.getInputStream());
        String content_type = super.getContentType();

        File tempDir = new File(config.getLocation());

        multiParser = new MultiPartInputStreamParser(in, content_type, config, tempDir);
        multiParser.setDeleteOnExit(true);

        Collection<Part> parts = multiParser.getParts();

        int keyCount = queryStrings.size();

        ImmutableMultimap.Builder<String, String> formMultiMapBuildBuilder = ImmutableMultimap.builder();
        ImmutableMultimap.Builder<String, Upload> partMultiMapBuilder = ImmutableMultimap.builder();
        ImmutableMultimap.Builder<String, Upload> originPartMultiMapBuilder = ImmutableMultimap.builder();
        ImmutableSet.Builder<Upload> partBuilder = ImmutableSet.builder();

        Iterator<Part> iterator = parts.iterator();
        while (iterator.hasNext() && (keyCount++) < maxFormKeys) {
            Part part = iterator.next();

            if (part == null)
                continue;
            MultiPartInputStreamParser.MultiPart mp = (MultiPartInputStreamParser.MultiPart) part;

            Upload upload = wrapPart(part, mp.getContentDispositionFilename());

            originPartMultiMapBuilder.put(part.getName(), upload);





            if (mp.getFile() != null) {
                partMultiMapBuilder.put(part.getName(), upload);
                partBuilder.add(upload);
            } else {
                String value = CharStreams.toString(
                        new InputStreamReader(part.getInputStream(), Charsets.UTF_8));

                formMultiMapBuildBuilder.put(part.getName(), value);
            }
        }

        this.forms = NullToEmptyMap.safeWrapper(
                formMultiMapBuildBuilder.build().asMap()
                , getSafeParameter());

        params = NullToEmptyMap.wrapper(
                ImmutableMap.<String, Collection<String>>builder()
                        .putAll(params)
                        .putAll(forms)
                        .build());

        this.uploadMap = NullToEmptyMap.wrapper(partMultiMapBuilder.build().asMap());
        this.originParts = NullToEmptyMap.wrapper(originPartMultiMapBuilder.build().asMap());
        this.uploads = partBuilder.build();

    }

    private boolean isPost(HttpServletRequest request) {
        return "post".equals(request.getMethod().toLowerCase());
    }

    private boolean isMultiPart(HttpServletRequest request) {

        String contentType = request.getContentType();

        return contentType != null
                && contentType.toLowerCase().startsWith("multipart/");

    }


        /* ------------------------------------------------------------------- */
    /** Copy Stream in to Stream out until EOF or exception.
     */
    private static void IoCopy(InputStream in, OutputStream out)
            throws IOException
    {
        IoCopy(in, out, -1);
    }

        /* ------------------------------------------------------------------- */
    /** Copy Stream in to Stream for byteCount bytes or until EOF or exception.
     */
    private static void IoCopy(InputStream in,
                              OutputStream out,
                              long byteCount)
            throws IOException
    {
        byte buffer[] = new byte[bufferSize];
        int len=bufferSize;

        if (byteCount>=0)
        {
            while (byteCount>0)
            {
                int max = byteCount<bufferSize?(int)byteCount:bufferSize;
                len=in.read(buffer,0,max);

                if (len==-1)
                    break;

                byteCount -= len;
                out.write(buffer,0,len);
            }
        }
        else
        {
            while (true)
            {
                len=in.read(buffer,0,bufferSize);
                if (len<0 )
                    break;
                out.write(buffer,0,len);
            }
        }
    }

    private SafeParameter safeParameter = null;
    private SafeParameter getSafeParameter() {
        if (safeParameter != null)
            return safeParameter;

        safeParameter = Argo.instance.getInstance(SafeParameter.class);

        return safeParameter;

    }

    private Upload wrapPart(final Part part, final String filename) {
        return new Upload() {
            @Override
            public String getFileName() {
                return filename; // header: filename
            }

            @Override
            public InputStream getInputStream() throws IOException {
                return part.getInputStream();
            }

            @Override
            public String getContentType() {
                return part.getContentType();
            }

            @Override
            public String getName() {
                return part.getName();
            }

            @Override
            public long getSize() {
                return part.getSize();
            }

            @Override
            public void write(String fileName) throws IOException {
                part.write(fileName);
            }

            @Override
            public void delete() throws IOException {
                part.delete();
            }

            @Override
            public String getHeader(String name) {
                return part.getHeader(name);
            }

            @Override
            public Collection<String> getHeaders(String name) {
                return part.getHeaders(name);
            }

            @Override
            public Collection<String> getHeaderNames() {
                return part.getHeaderNames();
            }
        };
    }

    private static enum Type {
        UNKNOWN,
        GET,
        POST,
        MULTI
    }



    private static class NullToEmptyMap<P, V extends Collection<P>>
            extends ForwardingMap<String, V>{

        public static NullToEmptyMap<String ,Collection<String>>
        safeWrapper(Map<String, ? extends Collection<String>> map , final SafeParameter safeParameter) {

            return wrapper(Maps.transformValues(map, new Function<Collection<String>, Collection<String>>() {
                @Override
                public Collection<String> apply(Collection<String> input) {
                    if (input == null)
                        return Collections.emptyList();

                    return Collections2.transform(input, new Function<String, String>() {
                        @Override
                        public String apply(String input) {
                            return safeParameter.encoding(input);
                        }
                    });
                }
            }));
        }

        public static <P, V extends Collection<P>> NullToEmptyMap<P, V>
        wrapper(Map<String, V> map) {
            return new NullToEmptyMap<P, V> (map);
        }

        private final Map<String, V> map;
        public NullToEmptyMap(Map<String, V> map) {
            this.map = map;
        }

        @Override
        protected Map<String, V> delegate() {
            return map;
        }

        @Override
        public V get(Object key) {
            V v = super.get(key);

            return v == null ? (V)Collections.emptyList() : v;
        }
    }

}
TOP

Related Classes of com.bj58.argo.servlet.ArgoRequest$NullToEmptyMap

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.