edu.harvard.med.screensaver.ui.arch.util.JSFUtils.java Source code

Java tutorial

Introduction

Here is the source code for edu.harvard.med.screensaver.ui.arch.util.JSFUtils.java

Source

// $HeadURL$
// $Id$
//
// Copyright  2006, 2010, 2011, 2012 by the President and Fellows of Harvard College.
//
// Screensaver is an open-source project developed by the ICCB-L and NSRB labs
// at Harvard Medical School. This software is distributed under the terms of
// the GNU General Public License.

package edu.harvard.med.screensaver.ui.arch.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import javax.activation.MimetypesFileTypeMap;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.servlet.http.HttpServletResponse;

import com.google.common.base.Function;
import com.google.common.base.Functions;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;

public class JSFUtils {
    private static Logger log = Logger.getLogger(JSFUtils.class);

    /**
     * Performs the necessary steps to return a server-side file to an HTTP
     * client. Must be called within a JSF-enabled servlet environment.
     *
     * @param facesContext the JSF FacesContext
     * @param file the File to send to the HTTP client
     * @param mimeType the MIME type of the file being sent
     * @throws IOException
     */
    public static void handleUserFileDownloadRequest(FacesContext facesContext, File file, String mimeType)
            throws IOException {
        InputStream in = new FileInputStream(file);
        handleUserDownloadRequest(facesContext, in, file.getName(), mimeType);
    }

    public static void handleUserFileDownloadRequest(FacesContext facesContext, File file, String suggestedFileName,
            String mimeType) throws IOException {
        InputStream in = new FileInputStream(file);
        handleUserDownloadRequest(facesContext, in, suggestedFileName, mimeType);
    }

    /**
     * Performs the necessary steps to return server-side data, provided as an
     * InputStream, to an HTTP client. Must be called within a JSF-enabled servlet
     * environment.
     *
     * @param facesContext the JSF FacesContext
     * @param dataInputStream an InputStream containing the data to send to the HTTP client
     * @param contentLocation set the "content-location" HTTP header to this value, allowing the downloaded file to be named
     * @param mimeType the MIME type of the file being sent
     * @throws IOException
     */
    public static void handleUserDownloadRequest(FacesContext facesContext, InputStream dataInputStream,
            String contentLocation, String mimeType) throws IOException {
        HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
        if (mimeType == null && contentLocation != null) {
            mimeType = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(contentLocation);
        }
        if (mimeType != null) {
            response.setContentType(mimeType);
        }

        // NOTE: the second line does the trick with the filename. leaving first line in for posterity
        response.setHeader("Content-Location", contentLocation);
        response.setHeader("Content-disposition", "attachment; filename=\"" + contentLocation + "\"");

        OutputStream out = response.getOutputStream();
        IOUtils.copy(dataInputStream, out);
        out.close();

        // skip Render-Response JSF lifecycle phase, since we're generating a
        // non-Faces response
        facesContext.responseComplete();
    }

    /**
     * Creates a UISelectItems object that can be assigned to the "value"
     * attribute of a UISelectItems JSF component.
     */
    public static List<SelectItem> createUISelectItems(Collection items) {
        return createUISelectItems(items, false, null, Functions.toStringFunction());
    }

    /**
     * Creates a UISelectItems object that can be assigned to the "value"
     * attribute of a UISelectItems JSF component. Adds an additional
     * "empty selection" item, whose value is an empty string and label is as
     * specified (empty string if null).
     */
    public static List<SelectItem> createUISelectItemsWithEmptySelection(Collection<?> items,
            String emptySelectionLabel) {
        return createUISelectItems(items, true, emptySelectionLabel, Functions.toStringFunction());
    }

    public static <E> List<SelectItem> createUISelectItemsWithEmptySelection(Collection<? extends E> items,
            String emptySelectionLabel, Function<E, String> toDisplayString) {
        return createUISelectItems(items, true, emptySelectionLabel, toDisplayString);
    }

    private static <E> List<SelectItem> createUISelectItems(Collection<? extends E> items, boolean addEmptyItem,
            String emptyItemLabel, Function<E, String> toDisplayString) {
        List<SelectItem> result = new ArrayList<SelectItem>();
        if (addEmptyItem) {
            result.add(new SelectItem("", emptyItemLabel == null ? "" : emptyItemLabel));
        }
        for (E item : items) {
            result.add(new SelectItem(item, toDisplayString.apply(item)));
        }
        return result;
    }

    /**
     * Output the names of all registered JSF components to the logger, as debug output.
     *
     * @motivation allows developer to determine the valid set of JSF component
     *             names that can be passed to Application.createComponent();
     * @param component
     * @param level
     */
    private void logComponentNames() {
        log.debug("JSF registered component names:");
        Iterator iter = FacesContext.getCurrentInstance().getApplication().getComponentTypes();
        while (iter.hasNext()) {
            log.debug("component name: " + iter.next().toString());
        }
    }

    /**
     * Output the hierarchical structure of a JSF component with nested children.
     */
    private void logComponentStructure(UIComponent component, int level) {
        char[] indent = new char[level];
        Arrays.fill(indent, ' ');
        log.debug(new String(indent) + component.getClass() + ": " + component.getId());
        for (Iterator iter = component.getChildren().iterator(); iter.hasNext();) {
            UIComponent child = (UIComponent) iter.next();
            logComponentStructure(child, level + 1);
        }
    }

}