PrimeFacesのファイルアップロードでパラメータが文字化けする件

(2013/4/6 追記:PrimeFaces3.5では、そのままFileUploadFilterを使ってよいようです)


PrimeFacesでファイルアップロードするときは、FileUploadFilterというのを組み込まないといけないのだけど、それだけだとファイル以外のパラメータでの日本語が文字化けしてしまう。
ファイル名は化けないのだけど。


同じことで悩んでる人もいた。報告をしてるっぽい。
http://stackoverflow.com/questions/11190081/primefaces-fileupload-filter-with-utf8-characters-filter


Commons FileUploadがファイル以外のパラメータの値でエンコード変換してくれないのが悪いのだけど、そうも言ってられないので、対策する。
FileUploadFilterをまるっとコピーして、エンコード変換したMultipartRequestを渡すという作戦。ただ、ここでMultipartRequestのaddFormParamがprivateなので、publicになってる値の取得メソッドに細工した。
このフィルタの前に、SetCharacterEncodingFilterっぽいものでエンコーディング指定しておく必要がある。
とりあえずGlassFish3.1.2.2+PrimeFaces3.4.2で確認。

public class UtfFileUploadFilter implements Filter {
    private final static Logger logger = Logger.getLogger(FileUploadFilter.class.getName());

    private final static String THRESHOLD_SIZE_PARAM = "thresholdSize";
    private final static String UPLOAD_DIRECTORY_PARAM = "uploadDirectory";
    private String thresholdSize;
    private String uploadDir;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
            thresholdSize = filterConfig.getInitParameter(THRESHOLD_SIZE_PARAM);
            uploadDir = filterConfig.getInitParameter(UPLOAD_DIRECTORY_PARAM);

            if(logger.isLoggable(Level.FINE))
                    logger.fine("UtfFileUploadFilter initiated successfully");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) 
            throws IOException, ServletException 
    {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        
        String enc = httpServletRequest.getCharacterEncoding();
        if(enc == null){
            enc = "utf-8";
        }
        final String encoding = enc;
        
        boolean isMultipart = ServletFileUpload.isMultipartContent(httpServletRequest);

        if(isMultipart) {
            if(logger.isLoggable(Level.FINE))
                logger.fine("Parsing utf file upload request");

            DiskFileItemFactory diskFileItemFactory = new DiskFileItemFactory();
            if(thresholdSize != null) {
                diskFileItemFactory.setSizeThreshold(Integer.valueOf(thresholdSize));
            }
            if(uploadDir != null) {
                diskFileItemFactory.setRepository(new File(uploadDir));
            }

            ServletFileUpload servletFileUpload = new ServletFileUpload(diskFileItemFactory);
            MultipartRequest multipartRequest;
            multipartRequest = new MultipartRequest(httpServletRequest, servletFileUpload){
                String convert(String result){
                   if(result == null){
                       return result;
                   }
                   try {
                       return new String(result.getBytes("8859_1"), encoding);
                   } catch (UnsupportedEncodingException ex) {
                       return result;
                   }
                }
                @Override
                public String getParameter(String name) {
                   return convert(super.getParameter(name));
                }

                @Override
                public String[] getParameterValues(String name) {
                   String[] values = super.getParameterValues(name);
                   String[] result = new String[values.length];
                   for(int i = 0; i < values.length; ++i){
                       result[i] = convert(values[i]);
                   }
                   return result;
                }

                @Override
                public Map getParameterMap() {
                   Map<String, String[]> params = super.getParameterMap(); 
                   Map<String, String[]> result = new HashMap<>();
                   for(Map.Entry<String, String[]> me : params.entrySet()){
                       String[] values = me.getValue();
                       String[] convvalues = new String[values.length];
                       for(int i = 0; i < values.length; ++i){
                           convvalues[i] = convert(values[i]);
                       }
                       result.put(me.getKey(), convvalues);
                   }
                   return result;
                }

            };

            if(logger.isLoggable(Level.FINE))
                logger.fine("File upload request parsed succesfully, "
                        + "continuing with filter chain with a wrapped utf multipart request");

            filterChain.doFilter(multipartRequest, response);
        } else {
            filterChain.doFilter(request, response);
        }
    }

    @Override
    public void destroy() {
        if(logger.isLoggable(Level.FINE))
            logger.fine("Destroying utf FileUploadFilter");
    }

}