Package org.ajax4jsf.context

Source Code of org.ajax4jsf.context.AjaxContextImpl

/**
* License Agreement.
*
* Rich Faces - Natural Ajax for Java Server Faces (JSF)
*
* Copyright (C) 2007 Exadel, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation.
*
* 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.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
*/

package org.ajax4jsf.context;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.StateManager;
import javax.faces.application.ViewHandler;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.AbortProcessingException;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.ajax4jsf.Messages;
import org.ajax4jsf.application.AjaxViewHandler;
import org.ajax4jsf.renderkit.AjaxContainerRenderer;
import org.ajax4jsf.renderkit.AjaxRendererUtils;
import org.ajax4jsf.renderkit.RendererUtils;
import org.ajax4jsf.renderkit.RendererUtils.HTML;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* This class incapsulated
*
* @author asmirnov@exadel.com (latest modification by $Author: alexsmirnov $)
* @version $Revision: 1.1.2.7 $ $Date: 2007/02/08 19:07:16 $
*
*/
public class AjaxContextImpl extends AjaxContext {
 
  public static final String SERVLET_ERROR_EXCEPTION_ATTRIBUTE = "javax.servlet.error.exception";

  private static final Log log = LogFactory.getLog(AjaxContext.class);

  Set<String> ajaxAreasToRender = new HashSet<String>();

  Set<String> ajaxAreasToProcess = null;

  Set<String> ajaxRenderedAreas = new LinkedHashSet<String>();

  boolean ajaxRequest = false;

  boolean selfRender = false;

  Integer viewSequence = new Integer(1);

  String submittedRegionClientId = null;
 
  String ajaxSingleClientId = null;


  ViewIdHolder viewIdHolder = null;

  Map<String, Object> responseDataMap = new HashMap<String, Object> ();

  Map<String, Object>  commonAjaxParameters = new HashMap<String, Object> ();

  Object oncomplete = null;


 
  public void release() {

    ajaxAreasToRender = new HashSet<String>();
   
    ajaxAreasToProcess = null;

    ajaxRenderedAreas = new LinkedHashSet<String>();

    ajaxRequest = false;

    selfRender = false;

    viewSequence = new Integer(1);

    submittedRegionClientId = null;

    viewIdHolder = null;

    responseDataMap = new HashMap<String, Object>();

    commonAjaxParameters = new HashMap<String, Object>();

  }

  /* (non-Javadoc)
   * @see org.ajax4jsf.context.AjaxContext#decode(javax.faces.context.FacesContext)
   */
  @Override
  public void decode(FacesContext context) {
    ExternalContext externalContext = context.getExternalContext();
    if (null == externalContext.getRequestMap().get(
        SERVLET_ERROR_EXCEPTION_ATTRIBUTE)) {
      Map<String, String> requestParameterMap = externalContext
          .getRequestParameterMap();
      String ajaxRegionId = requestParameterMap
          .get(AjaxContainerRenderer.AJAX_PARAMETER_NAME);
      setSubmittedRegionClientId(ajaxRegionId);
      setAjaxRequest(null != ajaxRegionId);
      setAjaxSingleClientId(requestParameterMap.get(AjaxRendererUtils.AJAX_SINGLE_PARAMETER_NAME));
    } else {
      // Error page is always serviced as non-ajax.
      setAjaxRequest(false);
      setSubmittedRegionClientId(null);
      setAjaxSingleClientId(null);
    }
  }
 

  /**
   * @param context
   * @throws AbortProcessingException
   */
  public void renderAjax(FacesContext context) throws FacesException {
    if (log.isDebugEnabled()) {
      log.debug(Messages.getMessage(Messages.RENDER_AJAX_REQUEST,
          getSubmittedRegionClientId()));
    }
    try {
      // Just in case...
      setSelfRender(true);
      setAjaxRequest(true);
      // create response writer.
      ExternalContext extContext = context.getExternalContext();
      RenderKit renderKit = context.getRenderKit();
      String encoding;
      // Depends if we talk about servlets, portlets, ...
      if (extContext.getRequest() instanceof ServletRequest) {
        ServletRequest request = (ServletRequest) extContext
            .getRequest();
        ServletResponse response = (ServletResponse) extContext
            .getResponse();
        // Setup encoding and content type
        String contentType = "text/xml";
        // get the encoding - must be setup by faces context or filter.
        encoding = request.getCharacterEncoding();
        if (encoding == null) {
          encoding = "UTF-8";
        }
        response.setContentType(contentType + ";charset=" + encoding);
      } else
        encoding = "UTF-8";

      PrintWriter servletWriter;
        servletWriter = getWriter(extContext);
      ResponseWriter writer = renderKit.createResponseWriter(
          servletWriter, null, encoding);
      context.setResponseWriter(writer);
      // make response
      writer.startDocument();
      encodeAjaxBegin(context);
      context.getViewRoot().encodeAll(context);
      saveViewState(context);
      encodeAjaxEnd(context);
      writer.endDocument();
      writer.flush();
      writer.close();
      servletWriter.close();
      // Save tree state.
    } catch (IOException e) {
      throw new FacesException(Messages.getMessage(
          Messages.RENDERING_AJAX_REGION_ERROR, getSubmittedRegionClientId()), e);
    } finally {
      context.responseComplete();
      // component.setRendererType(defaultRenderer);
    }
  }

  /**
   * Encode declaration for AJAX response. Render &lt;html&gt;&lt;body&gt;
   *
   * @param context
   * @throws IOException
   */
  public void encodeAjaxBegin(FacesContext context)
      throws IOException {
    UIViewRoot viewRoot = context.getViewRoot();
    // AjaxContainer ajax = (AjaxContainer) component;
    ResponseWriter out = context.getResponseWriter();
    // DebugUtils.traceView("ViewRoot in AJAX Page encode begin");
    out.startElement(HTML.HTML_ELEMENT, viewRoot);
    Locale locale = viewRoot.getLocale();
    out.writeAttribute(HTML.lang_ATTRIBUTE, locale.toString(), "lang");
    out.startElement(HTML.BODY_ELEMENT, viewRoot);
  }

  /**
   * End encoding of AJAX response. Render tag with included areas and close
   * &lt;/body&gt;&lt;/html&gt;
   *
   * @param context
   * @throws IOException
   */
  public void encodeAjaxEnd(FacesContext context)
      throws IOException {
    // AjaxContainer ajax = (AjaxContainer) component;
    ResponseWriter out = context.getResponseWriter();
    // DebugUtils.traceView("ViewRoot in AJAX Page encode begin");
    out.endElement(HTML.BODY_ELEMENT);
    out.endElement(HTML.HTML_ELEMENT);
  }

  public void saveViewState(FacesContext context) throws IOException {
    ResponseWriter writer = context.getResponseWriter();
    StateManager stateManager = context.getApplication().getStateManager();
    Object serializedView = stateManager
        .saveView(context);
    if (null != serializedView && null != writer) {
      StringWriter bufWriter = new StringWriter();
      ResponseWriter tempWriter;
      tempWriter = writer.cloneWithWriter(bufWriter);
      context.setResponseWriter(tempWriter);
      stateManager.writeState(context, serializedView);
      tempWriter.flush();
      if (bufWriter.getBuffer().length() > 0) {
        context.getExternalContext().getRequestMap().put(
            AjaxViewHandler.SERIALIZED_STATE_KEY,
            bufWriter.toString());
      }
      context.setResponseWriter(writer);
    }
  }

  protected RenderKit getRenderKit(FacesContext context) {
    RenderKit renderKit = context.getRenderKit();
    if (null == renderKit) {
      String renderKitId = context.getApplication().getViewHandler().calculateRenderKitId(context);
      RenderKitFactory factory = (RenderKitFactory) FactoryFinder
          .getFactory(FactoryFinder.RENDER_KIT_FACTORY);
      renderKit = factory.getRenderKit(context, renderKitId);
    }
    return renderKit;
  }

  /**
   * @return Returns the ajaxRequest.
   */
  public boolean isAjaxRequest() {
    return ajaxRequest;
  }

  /**
   * @param ajaxRequest
   *            The ajaxRequest to set.
   */
  public void setAjaxRequest(boolean ajaxRequest) {
    this.ajaxRequest = ajaxRequest;
  }

  /**
   * @return Returns the ajaxAreasToRender.
   */
  public Set<String> getAjaxAreasToRender() {
    return this.ajaxAreasToRender;
  }

  /**
   * @return the ajaxAreasToProcess
   */
  @Override
  public Set<String> getAjaxAreasToProcess() {
    return ajaxAreasToProcess;
  }

  /**
   * @param ajaxAreasToProcess the ajaxAreasToProcess to set
   */
  @Override
  public void setAjaxAreasToProcess(Set<String> ajaxAreasToProcess) {
    this.ajaxAreasToProcess = ajaxAreasToProcess;
  }

  /**
   * Add affected regions's ID to ajaxView component.
   *
   * @param component
   */
  public void addRegionsFromComponent(UIComponent component) {
    // First step - find parent ajax view
    Set<String> ajaxRegions = AjaxRendererUtils.getAjaxAreas(component);
    // if (ajaxRegions == null){
    // FacesContext context = FacesContext.getCurrentInstance();
    // ajaxRegions = AjaxRendererUtils.getAbsoluteId(context,component);
    // }
    if (log.isDebugEnabled()) {
      log.debug(Messages.getMessage(Messages.INVOKE_AJAX_REGION_LISTENER,
          component.getId()));
    }
    if (ajaxRegions != null) {
      for (Iterator<String> iter = ajaxRegions.iterator(); iter.hasNext();) {
        String id = iter.next().toString();
        ajaxAreasToRender.add(convertId(component, id));
      }
    }
  }

  /**
   * Add IDs of regions to process
   *
   * @see org.ajax4jsf.context.AjaxContext#addAreasToProcessFromComponent(javax.faces.component.UIComponent)
   */
  @Override
  public void addAreasToProcessFromComponent(FacesContext context, UIComponent component) {
    RendererUtils rendererUtils = RendererUtils.getInstance();
   
    Set<String> areasToProcess = AjaxRendererUtils.getAjaxAreasToProcess(component);
    if (areasToProcess != null) {
      Set<String> convertedAreaIds = new HashSet<String>();

      for (String areaId : areasToProcess) {
        UIComponent areaComponent = rendererUtils.findComponentFor(component, areaId);
        if (areaComponent != null) {
          convertedAreaIds.add(areaComponent.getClientId(context));
        } else {
          convertedAreaIds.add(areaId);
        }
      }
   
      if (this.ajaxAreasToProcess == null) {
        this.ajaxAreasToProcess = convertedAreaIds;
      } else {
        this.ajaxAreasToProcess.addAll(convertedAreaIds);
      }
    }
  }
 
  public void addComponentToAjaxRender(UIComponent component) {
    this.ajaxAreasToRender.add(AjaxRendererUtils.getAbsoluteId(component));
  }

  public void addComponentToAjaxRender(UIComponent base, String id) {
    this.ajaxAreasToRender.add(convertId(base, id));
  }

  /**
   * Test for relative id of target components. Attempt convert to absolute.
   * For use as argument for
   * {@link RendererUtils#findComponentFor(UIComponent, String)}
   *
   * @param component
   * @param id
   * @return
   */
  private String convertId(UIComponent component, String id) {
    if (id.charAt(0) == NamingContainer.SEPARATOR_CHAR) {
      return id;
    }
    if (null == component) {
      throw new NullPointerException(
          "Base component for search re-rendered compnnent is null");
    }
    UIComponent target = RendererUtils.getInstance().findComponentFor(
        component, id);
    if (null != target) {
      return AjaxRendererUtils.getAbsoluteId(target);
    }
    log.warn("Target component for id " + id + " not found");
    return id;
  }

  /**
   * @return Returns the ajaxRenderedAreas.
   */
  public Set<String> getAjaxRenderedAreas() {
    return ajaxRenderedAreas;
  }

  public void addRenderedArea(String id) {
    ajaxRenderedAreas.add(id);
  }

  public boolean removeRenderedArea(String id) {
    return ajaxRenderedAreas.remove(id);
  }

  /**
   * @return Returns the submittedClientId.
   */
  public String getSubmittedRegionClientId() {
    return this.submittedRegionClientId;
  }

  /**
   * @param submittedClientId
   *            The submittedClientId to set.
   */
  @Override
  public void setSubmittedRegionClientId(String submittedClientId) {
    this.submittedRegionClientId = submittedClientId;
  }

  /**
   * @return the ajaxSingleClientId
   */
  @Override
  public String getAjaxSingleClientId() {
    return ajaxSingleClientId;
  }

  /**
   * @param ajaxSingleClientId the ajaxSingleClientId to set
   */
  @Override
  public void setAjaxSingleClientId(String ajaxSingleClientId) {
    this.ajaxSingleClientId = ajaxSingleClientId;
  }

  /**
   * @return Returns the selfRender.
   */
  public boolean isSelfRender() {
    return selfRender;
  }

  /**
   * @param selfRender
   *            The selfRender to set.
   */
  public void setSelfRender(boolean selfRender) {
    this.selfRender = selfRender;
  }

  /**
   * @return the vievIdHolder
   */
  public ViewIdHolder getViewIdHolder() {
    return viewIdHolder;
  }

  /**
   * @param viewIdHolder
   *            the vievIdHolder to set
   */
  public void setViewIdHolder(ViewIdHolder viewIdHolder) {
    this.viewIdHolder = viewIdHolder;
  }

  /**
   * @return the responseData
   */
  public Object getResponseData() {
    return responseDataMap.get(RESPONSE_DATA_KEY);
  }

  /**
   * @param responseData
   *            the responseData to set
   */
  public void setResponseData(Object responseData) {
    this.responseDataMap.put(RESPONSE_DATA_KEY, responseData);
  }

  /**
   * @return the responseDataMap
   */
  public Map<String, Object> getResponseDataMap() {
    return responseDataMap;
  }

  /**
   * Gives back the writer of a Response object.
   *
   * @param extContext
   *            The external context.
   * @return The writer of the response.
   * @throws FacesException
   *             If the response object has no getWriter() method.
   */
  protected PrintWriter getWriter(ExternalContext extContext)
      throws FacesException {
    PrintWriter writer = null;
    Object response = extContext.getResponse();
    try {
      Method gW = response.getClass()
          .getMethod("getWriter", new Class[0]);
      writer = (PrintWriter) gW.invoke(response, new Object[0]);
    } catch (Exception e) {
      throw new FacesException(e);
    }
    return writer;
  }


  public String getAjaxActionURL(FacesContext context) {
    // Check arguments
    if (null == context) {
      throw new NullPointerException(
          "Faces context for build AJAX Action URL is null");
    }
    UIViewRoot viewRoot = context.getViewRoot();
    if (null == viewRoot) {
      throw new NullPointerException(
          "Faces view tree for build AJAX Action URL is null");
    }
    String viewId = viewRoot.getViewId();
    if (null == viewId) {
      throw new NullPointerException(
          "View id for build AJAX Action URL is null");
    }
    if (!viewId.startsWith("/")) {
      throw new IllegalArgumentException(
          "Illegal view Id for build AJAX Action URL: " + viewId);
    }
    ViewHandler viewHandler = context.getApplication().getViewHandler();
    String actionURL = viewHandler.getActionURL(context, viewId);
    // HACK - check for a Jboss PortletBridge implementation. If present, append DirectLink attribute to url.
    // TODO - how to detect portlet application ?
    if (null != context.getExternalContext().getApplicationMap().get(
        "org.jboss.portletbridge.application.PortletStateHolder")) {
      // Mark Ajax action url as transparent with jsf-portlet bridge.
      actionURL = actionURL
          + ((actionURL.lastIndexOf('?') > 0) ? "&" : "?")
          + "javax.portlet.faces.DirectLink=true";

    }
    return context.getExternalContext().encodeActionURL(actionURL);
  }

  /**
   * @return the commonAjaxParameters
   */
  public Map<String, Object> getCommonAjaxParameters() {
    return commonAjaxParameters;
  }

  /**
   * @return the oncomplete
   */
  public Object getOncomplete() {
    return oncomplete;
  }

  /**
   * @param oncomplete
   *            the oncomplete to set
   */
  public void setOncomplete(Object oncomplete) {
    this.oncomplete = oncomplete;
  }

}
TOP

Related Classes of org.ajax4jsf.context.AjaxContextImpl

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.