jp.co.opentone.bsol.framework.web.view.util.ViewHelper.java Source code

Java tutorial

Introduction

Here is the source code for jp.co.opentone.bsol.framework.web.view.util.ViewHelper.java

Source

/*
 * Copyright 2016 OPEN TONE Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package jp.co.opentone.bsol.framework.web.view.util;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.faces.application.FacesMessage;
import javax.faces.application.FacesMessage.Severity;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.mail.internet.MimeUtility;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import jp.co.opentone.bsol.framework.core.config.SystemConfig;
import jp.co.opentone.bsol.framework.core.dto.Code;
import jp.co.opentone.bsol.framework.core.dto.StringCode;
import jp.co.opentone.bsol.framework.core.exception.ApplicationFatalRuntimeException;
import jp.co.opentone.bsol.framework.core.message.Message;
import jp.co.opentone.bsol.framework.core.util.ArgumentValidator;

/**
 * View????.
 * @author opentone
 */
public class ViewHelper implements Serializable {

    /**
     * SerialVersionUID.
     */
    private static final long serialVersionUID = 8334223734895951826L;
    /** logger. */
    private static final Logger log = LoggerFactory.getLogger(ViewHelper.class);

    /**
     * ???????.
     */
    public static final String KEY_DOWNLOAD_HEADER_FILENAME_ENCODING = "download.header.filename.encoding";

    /** ???. */
    public static final String KEY_SERVER_NAME = "server.name";

    /**
     * .
     */
    public static final String BASE_PATH = "%s://%s%s%s";

    /**
     * ?OutputStream.
     * <p>
     * @see #getDownloadOutputStream(String)
     * @see #completeDownload()
     */
    private transient DownloadOutputStream out;

    /**
     * .
     */
    public ViewHelper() {
    }

    /**
     * ExternalContext?.
     * @return ExternalContext
     */
    public ExternalContext getExternalContext() {
        return FacesContext.getCurrentInstance().getExternalContext();
    }

    /**
     * request?????.
     * @param <T>
     *            ?
     * @param key
     *            ??
     * @return ?. ???null
     */
    @SuppressWarnings("unchecked")
    public <T> T getRequestValue(String key) {
        return (T) getExternalContext().getRequestMap().get(key);
    }

    /**
     * request??.
     * @param key
     *            
     * @param value
     *            
     */
    public void setRequestValue(String key, Object value) {
        getExternalContext().getRequestMap().put(key, value);
    }

    /**
     * request?????.
     * @param key
     *            
     */
    public void removeRequestValue(String key) {
        getExternalContext().getRequestMap().remove(key);
    }

    /**
     * session?????.
     * @param <T>
     *            ?
     * @param key
     *            ??
     * @return ?. ???null
     */
    @SuppressWarnings("unchecked")
    public <T> T getSessionValue(String key) {
        return (T) getExternalContext().getSessionMap().get(key);
    }

    /**
     * session??.
     * @param key
     *            
     * @param value
     *            
     */
    public void setSessionValue(String key, Object value) {
        getExternalContext().getSessionMap().put(key, value);
    }

    /**
     * HttpSession??.
     * @return session.
     */
    public HttpSession getHttpSession() {
        return (HttpSession) getExternalContext().getSession(true);
    }

    /**
     * session?????.
     * @param key
     *            
     */
    public void removeSessionValue(String key) {
        getExternalContext().getSessionMap().remove(key);
    }

    /**
     * application?????.
     * @param <T>
     *            ?
     * @param key
     *            ??
     * @return ?. ???null
     */
    @SuppressWarnings("unchecked")
    public <T> T getApplicationValue(String key) {
        return (T) getExternalContext().getApplicationMap().get(key);
    }

    /**
     * application??.
     * @param key
     *            
     * @param value
     *            
     */
    public void setApplicationValue(String key, Object value) {
        getExternalContext().getApplicationMap().put(key, value);
    }

    /**
     * application?????.
     * @param key
     *            
     */
    public void removeApplicationValue(String key) {
        getExternalContext().getApplicationMap().remove(key);
    }

    /**
     * Cookie?????.
     * @param key
     *            ??
     * @return ?. ???null
     */
    public String getCookieValue(String key) {
        String value = null;
        Cookie[] cookies = ((HttpServletRequest) getExternalContext().getRequest()).getCookies();
        if (cookies != null) {
            for (int i = 0; i < cookies.length; i++) {
                Cookie cookie = cookies[i];
                if (cookie.getName() != null && cookie.getName().equals(key)) {
                    value = cookie.getValue();
                }
            }
        }
        return value;
    }

    /**
     * request/session/application??????????. ???.
     * <ol>
     * <li>request</li>
     * <li>session</li>
     * <li>application</li>
     * </ol>
     * @param <T>
     *            ?
     * @param key
     *            ??
     * @return ?. ???null
     */
    @SuppressWarnings("unchecked")
    public <T> T getValue(String key) {
        // NOTE
        // T?????????
        // ???JDK?????
        // Eclipse????????????????
        T value = (T) getRequestValue(key);
        if (value == null) {
            value = (T) getSessionValue(key);
            if (value == null) {
                value = (T) getApplicationValue(key);
            }
        }
        return value;
    }

    /**
     * ?.
     * @param message
     *            
     */
    public void addMessage(Message message) {
        addMessage(null, message);
    }

    /**
     * ?.
     * @param clientId
     *            ???ID
     * @param message
     *            
     */
    public void addMessage(String clientId, Message message) {
        FacesContext context = FacesContext.getCurrentInstance();

        context.addMessage(clientId, createFacesMessage(message));
    }

    /**
     * ???????.
     * @param message
     *            
     * @return ???
     */
    protected Severity getSeverity(Message message) {
        String messageCode = message.getMessageCode();
        char mType = messageCode.charAt(0);
        switch (mType) {
        case 'I':
            return FacesMessage.SEVERITY_INFO;
        case 'E':
            return FacesMessage.SEVERITY_ERROR;
        case 'W':
            return FacesMessage.SEVERITY_WARN;
        case 'F':
            return FacesMessage.SEVERITY_FATAL;
        default:
            throw new IllegalArgumentException(String.format("Severity for %s is undefined.", messageCode));
        }
    }

    /**
     * Message?FacesMessage??.
     * @param message
     *            
     * @return FacesMessage
     */
    public FacesMessage createFacesMessage(Message message) {
        Severity severity = getSeverity(message);
        String summary = message.getSummary() != null ? message.getSummary() : severity.toString();

        FacesMessage fMessage = new FacesMessage(severity, summary, message.getMessage());

        return fMessage;
    }

    /**
     * dto??JSF?SelectItem?????.
     * dtoList?null???
     * @param dtoList
     *            SelectItem??
     * @param valuePropertyName
     *            SelectItem??????dtoList???????
     * @param labelPropertyName
     *            SelectItem??????dtoList???????
     * @return ??
     */
    public List<SelectItem> createSelectItem(List<?> dtoList, String valuePropertyName, String labelPropertyName) {
        ArgumentValidator.validateNotEmpty(valuePropertyName, "valuePropertyName");
        ArgumentValidator.validateNotEmpty(labelPropertyName, "labelPropertyName");

        List<SelectItem> result = new ArrayList<SelectItem>();
        try {
            if (dtoList == null) {
                return result;
            }
            for (Object item : dtoList) {
                Object val = PropertyUtils.getProperty(item, valuePropertyName);
                String label = BeanUtils.getProperty(item, labelPropertyName);
                if (isValidSelectItem(val, label)) {
                    result.add(new SelectItem(val, label));
                }
            }
            return result;

        } catch (IllegalAccessException e) {
            throw new ApplicationFatalRuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new ApplicationFatalRuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new ApplicationFatalRuntimeException(e);
        }
    }

    private boolean isValidSelectItem(Object val, String label) {
        if (val == null || label == null) {
            log.warn("Value or label is null. Maybe it's a bug. value={}, label={}", val, label);
            return false;
        }
        return true;
    }

    /**
     * Code??JSF?SelectItem?????.
     * Code??null???
     * @param codeList
     *            SelectItem??
     * @return ??
     */
    public List<SelectItem> createSelectItem(List<Code> codeList) {
        List<SelectItem> result = new ArrayList<SelectItem>();
        if (codeList == null) {
            return result;
        }
        for (Code ev : codeList) {
            Object val = ev.getValue();
            String label = ev.getLabel();
            if (isValidSelectItem(val, label)) {
                result.add(new SelectItem(val, label));
            }
        }
        return result;
    }

    /**
     * StringCode???JSF?SelectItem?????.
     * StringCode???null???
     * @param codes
     *            SelectItem??
     * @return ??
     */
    public List<SelectItem> createSelectItem(StringCode[] codes) {
        if (codes == null) {
            return new ArrayList<SelectItem>();
        }
        return createSelectStringItem(Arrays.asList(codes));
    }

    /**
     * StringCode??JSF?SelectItem?????.
     * StringCode??null???
     * @param codeList
     *            SelectItem??
     * @return ??
     */
    public List<SelectItem> createSelectStringItem(List<StringCode> codeList) {
        List<SelectItem> result = new ArrayList<SelectItem>();
        if (codeList == null) {
            return result;
        }
        for (StringCode ev : codeList) {
            Object val = ev.getValue();
            String label = ev.getLabel();
            if (isValidSelectItem(val, label)) {
                result.add(new SelectItem(val, label));
            }
        }
        return result;
    }

    /**
     * Code???JSF?SelectItem?????.
     * Code???null???
     * @param codes
     *            SelectItem??
     * @return ??
     */
    public List<SelectItem> createSelectItem(Code[] codes) {
        if (codes == null) {
            return new ArrayList<SelectItem>();
        }
        return createSelectItem(Arrays.asList(codes));
    }

    /**
     * StringCode???JSF?SelectItem?????.
     * StringCode???null???
     * @param codes
     *            SelectItem??
     * @return ??
     */
    public List<SelectItem> createSelectStringItem(StringCode[] codes) {
        if (codes == null) {
            return new ArrayList<SelectItem>();
        }
        return createSelectStringItem(Arrays.asList(codes));
    }

    /**
     * ????????.
     * <p>
     * {@link #completeDownload()}????????
     * ???.
     *
     * @see #completeDownload()
     * @param fileName ??
     * @param downloadByRealName ????????????true
     * @return ?
     * @throws IOException ???
     */
    public OutputStream getDownloadOutputStream(String fileName, boolean downloadByRealName) throws IOException {
        HttpServletRequest request = (HttpServletRequest) getExternalContext().getRequest();
        HttpServletResponse response = (HttpServletResponse) getExternalContext().getResponse();

        out = null;
        out = new DownloadOutputStream(request, response, fileName, downloadByRealName);

        return out;
    }

    /**
     * ????????.
     * <p>
     * {@link #completeDownload()}????????
     * ???.
     *
     * @see #completeDownload()
     * @param fileName ??
     * @return ?
     * @throws IOException ???
     */
    public OutputStream getDownloadOutputStream(String fileName) throws IOException {
        return getDownloadOutputStream(fileName, false);
    }

    /**
     * ???.
     * @param fileName
     *            ??
     * @param content
     *            ?
     * @throws IOException ?
     */
    public void download(String fileName, byte[] content) throws IOException {
        download(fileName, content, false);
    }

    /**
     * ???.
     * @param fileName
     *            ??
     * @param content
     *            ?
     * @param downloadByRealFileName ???????true
     * @throws IOException ?
     */
    public void download(String fileName, byte[] content, boolean downloadByRealFileName) throws IOException {

        HttpServletRequest request = (HttpServletRequest) getExternalContext().getRequest();
        HttpServletResponse response = (HttpServletResponse) getExternalContext().getResponse();

        setDownloadResponseHeader(request, response, fileName, downloadByRealFileName, content.length);

        doDownload(response, new ByteArrayInputStream(content));

        FacesContext.getCurrentInstance().responseComplete();
    }

    public void download(String fileName, InputStream in, int length) throws IOException {
        HttpServletRequest request = (HttpServletRequest) getExternalContext().getRequest();
        HttpServletResponse response = (HttpServletResponse) getExternalContext().getResponse();

        setDownloadResponseHeader(request, response, fileName, false, length);
        doDownload(response, in);

        FacesContext.getCurrentInstance().responseComplete();
    }

    protected void setDownloadResponseHeader(HttpServletRequest request, HttpServletResponse response,
            String fileName, boolean downloadByRealName, int length) {
        setContentType(response, fileName);
        setHeaderFileName(request, response, fileName, downloadByRealName);
        response.addHeader("Accept-Ranges", "none"); // For Acrobat Reader 7.0

        if (length > 0) {
            response.setContentLength(length);
        }
    }

    /**
    * ???actionId??????true?.
    * @param actionId
    *            ??. submit?id
    * @return ????????true
    */
    public boolean isActionInvoked(String actionId) {
        HttpServletRequest req = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
                .getRequest();
        if (isPartialAjax()) {
            return StringUtils.equals(actionId, req.getParameter("javax.faces.source"));
        } else {
            return StringUtils.isNotEmpty(req.getParameter(actionId));
        }
    }

    /**
    * ?????actionIds??????????true?.
    * @param actionIds
    *            ??. submit?id
    * @return ????????????true
    */
    public boolean isAnyActionsInvoked(String... actionIds) {
        for (String id : actionIds) {
            if (isActionInvoked(id)) {
                return true;
            }
        }
        return false;
    }

    /**
     * ???JSF2?Ajax?Partial Request???true?.
     * @return Partial Request???true
     */
    public boolean isPartialAjax() {
        String value = ((HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest())
                .getParameter("javax.faces.partial.ajax");

        return Boolean.parseBoolean(value);
    }

    private void setContentType(HttpServletResponse response, String fileName) {
        String extension = getExtension(fileName);
        if (".xls".equals(extension)) {
            response.setContentType("application/vnd.ms-excel");
        } else if (".word".equals(extension)) {
            response.setContentType("application/msword");
        } else if (".pdf".equals(extension)) {
            response.setContentType("application/pdf");
        } else if (".csv".equals(extension)) {
            response.setContentType("text/csv");
        } else {
            response.setContentType("application/octet-stream");
        }
    }

    /**
     * ???User-Agent???????.
     * <ul>
     * <li>IE????????????</li>
     * <li>User-Agent??????</li>
     * <li>?????256????????????????????</li>
     * </ul>
     * @param request 
     * @param response ?
     * @param fileName ???
     */
    private void setHeaderFileName(HttpServletRequest request, HttpServletResponse response, String fileName,
            boolean downloadByRealFileName) {
        String headerFileName;
        String userAgent = request.getHeader("User-Agent");
        try {
            if (userAgent.indexOf("MSIE") != -1) {
                //  IE??????????
                String enc = SystemConfig.getValue(KEY_DOWNLOAD_HEADER_FILENAME_ENCODING);
                headerFileName = new String(fileName.getBytes(enc), "iso-8859-1");
                //  ???????
                //  URL????? + ????256byte????????
                //  ???
                //                headerFileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                //  ???????MIME????
                //  see RFC2231
                headerFileName = MimeUtility.encodeWord(fileName, "ISO-2022-JP", "B");
            }
            //  SpreadsheetMLExcel 2007??????????
            //  *.xml?
            if (!downloadByRealFileName && headerFileName.endsWith(".xls")) {
                headerFileName = headerFileName.replaceAll("\\.xls$", ".xml");
            }
            response.addHeader("Content-Disposition", "attachment; filename=\"" + headerFileName + "\"");
        } catch (UnsupportedEncodingException ignore) {
            log.warn(String.format("failed to set filename to response header. %s", fileName), ignore);
        }
    }

    protected void doDownload(HttpServletResponse response, InputStream in) throws IOException {
        ServletOutputStream o = getServletOutputStream(response);
        try {
            final int bufLength = 4096;
            byte[] buf = new byte[bufLength];
            int i = 0;
            while ((i = in.read(buf, 0, buf.length)) != -1) {
                o.write(buf, 0, i);
            }

            o.flush();
            o.close();
        } catch (IOException e) {
            if (isDownloadCanceled(e)) {
                log.warn("Download canceled.");
            } else {
                throw e;
            }
        }
    }

    protected ServletOutputStream getServletOutputStream(HttpServletResponse response) throws IOException {
        ServletOutputStream o;
        if (response instanceof ServletResponseWrapper) {
            log.warn("Response is instance of ServletResponseWrapper");
            o = response.getOutputStream();
            /*
            HttpServletResponse rawResponse =
            (HttpServletResponse) ((ServletResponseWrapper) response).getResponse();
            o = rawResponse.getOutputStream();
            */
        } else {
            log.warn("Response is instance of ServletResponse");
            o = response.getOutputStream();
        }

        return o;
    }

    /**
     * ?.
     * {@link #getDownloadOutputStream(String)}???
     * ?????????????????.
     *
     * @see #getDownloadOutputStream(String)
     */
    public void completeDownload() {
        if (out.isOpen()) {
            FacesContext.getCurrentInstance().responseComplete();
            out = null;
        }
    }

    /**
     * ???IOException?????????true?.
     * @param e ???
     * @return ?????true
     */
    public boolean isDownloadCanceled(IOException e) {
        return e instanceof SocketException || (e.getCause() != null && e.getCause() instanceof SocketException);
    }

    /**
     * HTML???.
     * @param content
     *            ?
     * @param charset ???
     * @throws IOException ?
     */
    public void requestResponse(byte[] content, String charset) throws IOException {
        HttpServletResponse response = (HttpServletResponse) getExternalContext().getResponse();
        setHtmlResponseHeader(response, charset);

        doDownload(response, new ByteArrayInputStream(content));
        //        doWrite(response, content);

        FacesContext.getCurrentInstance().responseComplete();
    }

    protected void setHtmlResponseHeader(HttpServletResponse response, String charset) {
        response.setContentType(String.format("text/html; charset=%s", charset));
    }

    protected void doWrite(HttpServletResponse response, byte[] content) throws IOException {
        ServletOutputStream o = response.getOutputStream();
        o.write(content);
        o.flush();
        o.close();
    }

    private String getExtension(String fileName) {
        int i = fileName.lastIndexOf('.');
        if (i == -1) {
            return null;
        }
        String extension = fileName.substring(i);
        return extension;
    }

    /**
     * URL?.
     * @return URL
     */
    public String getBasePath() {
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
                .getRequest();
        return String.format(BASE_PATH, request.getScheme(), SystemConfig.getValue(KEY_SERVER_NAME),
                getPort(request), request.getContextPath());
    }

    /**
     * URL?.
     * @return URL
     */
    public String getContextPath() {
        HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext()
                .getRequest();
        return request.getContextPath();
    }

    private String getPort(HttpServletRequest request) {
        final int portHttp = 80;
        final int portHttps = 443;
        switch (request.getServerPort()) {
        case portHttp:
        case portHttps:
            return "";
        default:
            return String.format(":%s", request.getServerPort());
        }
    }

    /**
     * ???{@link OutputStream}.
     * <p>
     * ???????Open?????.
     * </p>
     */
    class DownloadOutputStream extends OutputStream {

        /** request. */
        private HttpServletRequest request;
        /** response. */
        private HttpServletResponse response;
        /** ???. */
        private String fileName;

        /** ????????????true. */
        private boolean downloadByRealName;

        /** ??{@link OutputStream}. */
        private OutputStream out;

        /**
         * ????????.
         * @param request HttpServletRequest
         * @param response HttpServletResponse
         * @param fileName ??
         */
        public DownloadOutputStream(HttpServletRequest request, HttpServletResponse response, String fileName) {
            this.request = request;
            this.response = response;
            this.fileName = fileName;
        }

        /**
         * ????????.
         * @param request HttpServletRequest
         * @param response HttpServletResponse
         * @param fileName ??
         * @param downloadByRealName ????????????true
         */
        public DownloadOutputStream(HttpServletRequest request, HttpServletResponse response, String fileName,
                boolean downloadByRealName) {
            this.request = request;
            this.response = response;
            this.fileName = fileName;
            this.downloadByRealName = downloadByRealName;
        }

        public boolean isOpen() {
            return out != null;
        }

        private OutputStream getOutputStream() throws IOException {
            if (!isOpen()) {
                setDownloadResponseHeader(request, response, fileName, downloadByRealName, -1);
                out = getServletOutputStream(response);
            }
            return out;
        }

        /* (non-Javadoc)
         * @see java.io.OutputStream#write(int)
         */
        @Override
        public void write(int b) throws IOException {
            getOutputStream().write(b);
        }

        /* (non-Javadoc)
         * @see java.io.OutputStream#write(byte[])
         */
        @Override
        public void write(byte[] b) throws IOException {
            getOutputStream().write(b);
        }

        /* (non-Javadoc)
         * @see java.io.OutputStream#write(byte[], int, int)
         */
        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            getOutputStream().write(b, off, len);
        }

        /* (non-Javadoc)
         * @see java.io.OutputStream#flush()
         */
        @Override
        public void flush() throws IOException {
            if (isOpen()) {
                getOutputStream().flush();
            }
        }

        /* (non-Javadoc)
         * @see java.io.OutputStream#close()
         */
        @Override
        public void close() throws IOException {
            if (isOpen()) {
                getOutputStream().close();
            }
        }
    }
}