Package com.liferay.faces.alloy.component.inputfile

Source Code of com.liferay.faces.alloy.component.inputfile.InputFileRenderer

/**
* Copyright (c) 2000-2014 Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.faces.alloy.component.inputfile;

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.faces.application.Application;
import javax.faces.application.ProjectStage;
import javax.faces.application.ResourceDependencies;
import javax.faces.application.ResourceDependency;
import javax.faces.application.ViewHandler;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.convert.ConverterException;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import javax.faces.render.FacesRenderer;
import javax.faces.validator.Validator;

import com.liferay.faces.alloy.component.inputfile.internal.AjaxParameters;
import com.liferay.faces.alloy.component.inputfile.internal.InputFileDecoder;
import com.liferay.faces.alloy.component.inputfile.internal.InputFileDelegationResponseWriter;
import com.liferay.faces.alloy.component.inputfile.internal.PreviewTableTemplate;
import com.liferay.faces.alloy.component.inputfile.internal.ProgressTableTemplate;
import com.liferay.faces.util.component.ComponentUtil;
import com.liferay.faces.util.component.Styleable;
import com.liferay.faces.util.config.ApplicationConfig;
import com.liferay.faces.util.context.MessageContext;
import com.liferay.faces.util.context.MessageContextFactory;
import com.liferay.faces.util.context.map.MultiPartFormData;
import com.liferay.faces.util.factory.FactoryExtensionFinder;
import com.liferay.faces.util.js.JavaScriptArray;
import com.liferay.faces.util.js.JavaScriptFragment;
import com.liferay.faces.util.lang.StringPool;
import com.liferay.faces.util.logging.Logger;
import com.liferay.faces.util.logging.LoggerFactory;
import com.liferay.faces.util.model.UploadedFile;
import com.liferay.faces.util.product.ProductConstants;
import com.liferay.faces.util.product.ProductMap;
import com.liferay.faces.util.render.DelegationResponseWriter;
import com.liferay.faces.util.render.RendererUtil;


/**
* @author  Neil Griffin
*/
//J-
@FacesRenderer(componentFamily = InputFile.COMPONENT_FAMILY, rendererType = InputFile.RENDERER_TYPE)
@ResourceDependencies(
    {
      @ResourceDependency(library = "liferay-faces-alloy", name = "alloy.css"),
      @ResourceDependency(library = "liferay-faces-alloy", name = "alloy.js"),
      @ResourceDependency(library = "liferay-faces-reslib", name = "build/aui-css/css/bootstrap.min.css"),
      @ResourceDependency(library = "liferay-faces-reslib", name = "build/aui/aui-min.js"),
      @ResourceDependency(library = "liferay-faces-reslib", name = "liferay.js")
    }
  )
//J+
public class InputFileRenderer extends InputFileRendererCompat implements SystemEventListener {

  // Logger
  private static final Logger logger = LoggerFactory.getLogger(InputFileRenderer.class);

  // Private Constants
  private static final boolean LIFERAY_FACES_BRIDGE_DETECTED = ProductMap.getInstance().get(
      ProductConstants.LIFERAY_FACES_BRIDGE).isDetected();

  // Protected Constants
  protected static final String[] MODULES = { "uploader", "aui-datatable", "datatype-xml" };

  @Override
  public void decode(FacesContext facesContext, UIComponent uiComponent) {

    InputFile inputFile = (InputFile) uiComponent;

    Map<String, List<UploadedFile>> uploadedFileMap = getUploadedFileMap(facesContext, inputFile.getLocation());

    if (uploadedFileMap != null) {

      String clientId = uiComponent.getClientId(facesContext);
      List<UploadedFile> uploadedFiles = uploadedFileMap.get(clientId);

      if ((uploadedFiles != null) && (uploadedFiles.size() > 0)) {

        inputFile.setSubmittedValue(uploadedFiles);

        // Queue the FileUploadEvent so that each uploaded file can be handled individually with an
        // ActionListener.
        for (UploadedFile uploadedFile : uploadedFiles) {

          FileUploadEvent fileUploadEvent = new FileUploadEvent(uiComponent, uploadedFile);
          uiComponent.queueEvent(fileUploadEvent);
        }
      }
    }
  }

  @Override
  public void encodeJavaScriptCustom(FacesContext facesContext, UIComponent uiComponent) throws IOException {

    ResponseWriter responseWriter = facesContext.getResponseWriter();
    InputFile inputFile = (InputFile) uiComponent;
    String clientId = inputFile.getClientId(facesContext);

    // Determine the valid content-types and maximum file size from the validator (if specified).
    JavaScriptArray contentTypes = new JavaScriptArray();
    JavaScriptFragment alloyNamespace = new JavaScriptFragment("A");
    long maxFileSize = Long.MAX_VALUE;
    InputFileValidator inputFileValidator = getInputFileValidator(inputFile);

    if (inputFileValidator != null) {
      String validContentTypes = inputFileValidator.getContentTypes();

      if (validContentTypes != null) {
        contentTypes = new JavaScriptArray(validContentTypes.split(","));
      }

      maxFileSize = inputFileValidator.getMaxFileSize();
    }

    // If the component should render the upload progress table, then initialize the YUI progress uploader widget.
    if (inputFile.isShowProgress()) {

      String clientVarName = ComponentUtil.getClientVarName(facesContext, inputFile);
      String clientKey = inputFile.getClientKey();

      if (clientKey == null) {
        clientKey = clientVarName;
      }

      UIViewRoot viewRoot = facesContext.getViewRoot();
      Locale locale = viewRoot.getLocale();
      String formClientId = getParentFormClientId(inputFile);
      Application application = facesContext.getApplication();
      ViewHandler viewHandler = application.getViewHandler();
      String actionURL = viewHandler.getActionURL(facesContext, viewRoot.getViewId());
      String partialActionURL = facesContext.getExternalContext().encodePartialActionURL(actionURL);
      String namingContainerId = StringPool.BLANK;

      if (viewRoot instanceof NamingContainer) {
        namingContainerId = viewRoot.getContainerClientId(facesContext);
      }

      AjaxParameters ajaxParameters = new AjaxParameters(inputFile, clientId, formClientId);
      String execute = ajaxParameters.getExecute();
      String render = ajaxParameters.getRender();

      String notStartedMessage = getMessageContext().getMessage(locale, "not-started");
      JavaScriptFragment clientComponent = new JavaScriptFragment("Liferay.component('" + clientKey + "')");
      RendererUtil.encodeFunctionCall(responseWriter, "LFAI.initProgressUploader", alloyNamespace,
        clientComponent, contentTypes, clientId, formClientId, namingContainerId, inputFile.isAuto(), execute,
        render, partialActionURL, maxFileSize, notStartedMessage);
    }

    // Otherwise, if the component should render the upload preview table, then format the preview-uploader.js
    // template and write it to the response.
    else if (inputFile.isShowPreview()) {

      RendererUtil.encodeFunctionCall(responseWriter, "LFAI.initPreviewUploader", alloyNamespace, contentTypes,
        clientId, maxFileSize);
    }
  }

  @Override
  public void encodeMarkupBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException {
    ResponseWriter responseWriter = facesContext.getResponseWriter();

    InputFile inputFile = (InputFile) uiComponent;

    // If the component should render the preview table or the upload progress table, then
    if (inputFile.isShowPreview() || inputFile.isShowProgress()) {

      // Start encoding the outermost <div> element.
      responseWriter.startElement(StringPool.DIV, uiComponent);
      responseWriter.writeAttribute(StringPool.ID, uiComponent.getClientId(facesContext), StringPool.ID);
      RendererUtil.encodeStyleable(responseWriter, (Styleable) uiComponent);

      // If the component should render the upload progress table, then format the progress-table.html template
      // and write it to the response.
      String clientId = uiComponent.getClientId(facesContext);
      Locale locale = facesContext.getViewRoot().getLocale();

      if (inputFile.isShowProgress()) {
        ProgressTableTemplate progressTableTemplate = getProgressTableTemplate(facesContext);
        String progressTableHTML = progressTableTemplate.format(locale, clientId, inputFile.isAuto());
        responseWriter.write(progressTableHTML);
      }

      // Otherwise, delegate writing to the delegate renderer. Note that this effectively a no-op with Mojarra and
      // MyFaces, since they both delay writing of the entire <input type="file"...> ... </input> element until
      // encodeEnd.
      else {
        super.encodeMarkupBegin(facesContext, uiComponent);
      }
    }

    // Otherwise, delegate writing to the delegate renderer. Note that this effectively a no-op with Mojarra and
    // MyFaces, since they both delay writing of the entire <input type="file"...> ... </input> element until
    // encodeEnd.
    else {
      super.encodeMarkupBegin(facesContext, uiComponent);
    }
  }

  @Override
  public void encodeMarkupEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException {

    // If the component should show the progress table, then
    InputFile inputFile = (InputFile) uiComponent;
    ResponseWriter responseWriter = facesContext.getResponseWriter();

    if (inputFile.isShowProgress()) {

      // Finish encoding of the outermost <div> element. Since the template contains its own "Select Files"
      // button, delegation must not occur.
      responseWriter.endElement(StringPool.DIV);
    }

    // Otherwise, if the component should show the preview table, then
    else if (inputFile.isShowPreview()) {

      // Delegate writing of the entire <input type="file"...> ... </input> element to the delegate renderer.
      DelegationResponseWriter delegationResponseWriter = new InputFileDelegationResponseWriter(responseWriter,
          inputFile.isAuto());
      super.encodeMarkupEnd(facesContext, uiComponent, delegationResponseWriter);

      // Format the preview-table.html template and write it to the response.
      Locale locale = facesContext.getViewRoot().getLocale();
      String clientId = uiComponent.getClientId(facesContext);
      PreviewTableTemplate previewTableTemplate = getPreviewTableTemplate(facesContext);
      String previewTableHTML = previewTableTemplate.format(locale, clientId, false);
      responseWriter.write(previewTableHTML);

      // Finish encoding of the outermost <div> element.
      responseWriter.endElement(StringPool.DIV);
    }

    // Otherwise, delegate writing of the entire <input type="file"...> ... </input> element to the delegate
    // renderer.
    else {
      DelegationResponseWriter delegationResponseWriter = new InputFileDelegationResponseWriter(responseWriter,
          inputFile.isAuto());
      super.encodeMarkupEnd(facesContext, uiComponent, delegationResponseWriter);
    }
  }

  @Override
  public void processEvent(SystemEvent postConstructApplicationConfigEvent) throws AbortProcessingException {

    // Due to ClassLoader problems during static initialization, it is necessary to delay creation of singleton
    // instances of template classes until the PostConstructApplicationConfigEvent is sent. Although template text
    // is the same for each webapp context, the template must be stored as a ServletContext (application scoped)
    // attribute in order to avoid a race condition when contexts are started up in parallel. For example:
    // http://wiki.apache.org/tomcat/HowTo/FasterStartUp#Starting_several_web_applications_in_parallel
    try {
      FacesContext startupFacesContext = FacesContext.getCurrentInstance();
      ExternalContext externalContext = startupFacesContext.getExternalContext();
      Map<String, Object> applicationMap = externalContext.getApplicationMap();
      boolean minified = startupFacesContext.isProjectStage(ProjectStage.Production);
      applicationMap.put(PreviewTableTemplate.class.getName(), new PreviewTableTemplate(minified));
      applicationMap.put(ProgressTableTemplate.class.getName(), new ProgressTableTemplate(minified));
    }
    catch (Exception e) {
      logger.error(e);
    }
  }

  @Override
  protected void encodeHiddenAttributes(FacesContext facesContext, ResponseWriter responseWriter, InputFile inputFile,
    boolean first) throws IOException {

    // fileFieldName
    encodeString(responseWriter, "fileFieldName", inputFile.getClientId(), first);
    first = false;

    // multipleFiles
    String multiple = inputFile.getMultiple();
    boolean multipleFiles = "multiple".equalsIgnoreCase(multiple);
    encodeBoolean(responseWriter, "multipleFiles", multipleFiles, first);

    // selectFilesButton
    Locale locale = facesContext.getViewRoot().getLocale();
    String chooseFiles = getMessageContext().getMessage(locale, "choose-files");
    StringBuilder selectFilesButtonScript = new StringBuilder();
    selectFilesButtonScript.append(
      "A.Node.create(\"<button type='button' class='yui3-widget btn btn-content' role='button' aria-label='");
    selectFilesButtonScript.append(chooseFiles);
    selectFilesButtonScript.append("' tabindex='{tabIndex}'>");
    selectFilesButtonScript.append(chooseFiles);
    selectFilesButtonScript.append("</button>\")");
    encodeNonEscapedObject(responseWriter, "selectFilesButton", selectFilesButtonScript, first);
  }

  @Override
  public Object getConvertedValue(FacesContext facesContext, UIComponent uiComponent, Object submittedValue)
    throws ConverterException {
    return submittedValue;
  }

  @Override
  public String getDelegateComponentFamily() {
    return InputFile.DELEGATE_COMPONENT_FAMILY;
  }

  @Override
  public String getDelegateRendererType() {
    return InputFile.DELEGATE_RENDERER_TYPE;
  }

  @Override
  public boolean isListenerForSource(Object source) {
    return ((source != null) && (source instanceof ApplicationConfig));
  }

  protected InputFileValidator getInputFileValidator(InputFile inputFile) {

    InputFileValidator inputFileValidator = null;
    Validator[] validators = inputFile.getValidators();

    for (Validator validator : validators) {

      if (validator instanceof InputFileValidator) {
        inputFileValidator = (InputFileValidator) validator;

        break;
      }
    }

    return inputFileValidator;
  }

  protected MessageContext getMessageContext() {

    MessageContextFactory messageContextFactory = (MessageContextFactory) FactoryExtensionFinder.getFactory(
        MessageContextFactory.class);

    return messageContextFactory.getMessageContext();
  }

  @Override
  protected String[] getModules(FacesContext facesContext, UIComponent uiComponent) {
    return MODULES;
  }

  protected String getParentFormClientId(UIComponent uiComponent) {

    String parentFormClientId = null;

    if (uiComponent != null) {

      if (uiComponent instanceof UIForm) {
        parentFormClientId = uiComponent.getClientId();
      }
      else {
        parentFormClientId = getParentFormClientId(uiComponent.getParent());
      }
    }

    return parentFormClientId;
  }

  protected PreviewTableTemplate getPreviewTableTemplate(FacesContext facesContext) {
    ExternalContext externalContext = facesContext.getExternalContext();
    Map<String, Object> applicationMap = externalContext.getApplicationMap();

    return (PreviewTableTemplate) applicationMap.get(PreviewTableTemplate.class.getName());
  }

  protected ProgressTableTemplate getProgressTableTemplate(FacesContext facesContext) {
    ExternalContext externalContext = facesContext.getExternalContext();
    Map<String, Object> applicationMap = externalContext.getApplicationMap();

    return (ProgressTableTemplate) applicationMap.get(ProgressTableTemplate.class.getName());
  }

  protected Map<String, List<UploadedFile>> getUploadedFileMap(FacesContext facesContext, String location) {

    Map<String, List<UploadedFile>> uploadedFileMap;

    if (LIFERAY_FACES_BRIDGE_DETECTED) {
      Map<String, Object> requestAttributeMap = facesContext.getExternalContext().getRequestMap();
      MultiPartFormData multiPartFormData = (MultiPartFormData) requestAttributeMap.get(MultiPartFormData.class
          .getName());
      uploadedFileMap = multiPartFormData.getUploadedFileMap();
    }
    else {
      InputFileDecoder inputFileDecoder = getInputFileDecoder();
      uploadedFileMap = inputFileDecoder.decode(facesContext, location);
    }

    return uploadedFileMap;
  }
}
TOP

Related Classes of com.liferay.faces.alloy.component.inputfile.InputFileRenderer

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.