001 package org.apache.myfaces.tobago.ajax.api; 002 003 /* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020 import org.apache.commons.logging.Log; 021 import org.apache.commons.logging.LogFactory; 022 import org.apache.myfaces.tobago.component.ComponentUtil; 023 import org.apache.myfaces.tobago.component.UIViewRoot; 024 025 import javax.faces.component.UIComponent; 026 import javax.faces.context.FacesContext; 027 import javax.faces.event.PhaseId; 028 import javax.faces.render.Renderer; 029 import java.io.IOException; 030 import java.util.Iterator; 031 import java.util.Map; 032 import java.util.StringTokenizer; 033 import java.util.HashMap; 034 035 public class AjaxUtils { 036 037 private static final Log LOG = LogFactory.getLog(AjaxUtils.class); 038 039 public static final String AJAX_COMPONENTS = AjaxUtils.class.getName() + ".AJAX_COMPONENTS"; 040 041 public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass) { 042 if (facesContext == null) { 043 throw new NullPointerException("facesContext may not be null"); 044 } 045 if (uiComponent == null) { 046 throw new NullPointerException("uiComponent may not be null"); 047 } 048 //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass()))) 049 // why isAssignableFrom with additional getClass method call if isInstance does the same? 050 if (compClass != null && !(compClass.isInstance(uiComponent))) { 051 throw new IllegalArgumentException("uiComponent : " 052 + uiComponent.getClass().getName() + " is not instance of " 053 + compClass.getName() + " as it should be"); 054 } 055 } 056 057 058 public static void encodeAjaxComponent(FacesContext facesContext, UIComponent component) throws IOException { 059 if (facesContext == null) { 060 throw new NullPointerException("facesContext"); 061 } 062 if (!component.isRendered()) { 063 return; 064 } 065 Renderer renderer = ComponentUtil.getRenderer(facesContext, component); 066 if (renderer != null && renderer instanceof AjaxRenderer) { 067 ((AjaxRenderer) renderer).encodeAjax(facesContext, component); 068 } 069 } 070 071 072 public static void processAjax(FacesContext facesContext, UIComponent component) 073 throws IOException { 074 if (component instanceof AjaxComponent) { 075 ((AjaxComponent) component).processAjax(facesContext); 076 } else { 077 processAjaxOnChildren(facesContext, component); 078 } 079 } 080 081 public static void processActiveAjaxComponent(FacesContext facesContext, 082 UIComponent component) 083 throws IOException { 084 085 if (component instanceof AjaxComponent) { 086 final UIViewRoot viewRoot = (UIViewRoot) facesContext.getViewRoot(); 087 088 // TODO: handle phaseListeners ?? 089 090 if (!facesContext.getRenderResponse()) { 091 component.processValidators(facesContext); 092 viewRoot.broadcastEventsForPhase(facesContext, PhaseId.PROCESS_VALIDATIONS); 093 } else if (LOG.isDebugEnabled()) { 094 LOG.debug("Skipping validate"); 095 } 096 097 if (!facesContext.getRenderResponse()) { 098 component.processUpdates(facesContext); 099 viewRoot.broadcastEventsForPhase(facesContext, PhaseId.UPDATE_MODEL_VALUES); 100 } else if (LOG.isDebugEnabled()) { 101 LOG.debug("Skipping updates"); 102 } 103 104 if (!facesContext.getRenderResponse()) { 105 viewRoot.processApplication(facesContext); 106 } else if (LOG.isDebugEnabled()) { 107 LOG.debug("Skipping application"); 108 } 109 110 ((AjaxComponent) component).encodeAjax(facesContext); 111 } else { 112 LOG.error("Can't process non AjaxComponent : \"" 113 + component.getClientId(facesContext) + "\" = " 114 + component.getClass().getName()); 115 } 116 } 117 118 public static void processAjaxOnChildren(FacesContext facesContext, 119 UIComponent component) throws IOException { 120 121 final Iterator<UIComponent> facetsAndChildren = component.getFacetsAndChildren(); 122 while (facetsAndChildren.hasNext() && !facesContext.getResponseComplete()) { 123 AjaxUtils.processAjax(facesContext, facetsAndChildren.next()); 124 } 125 } 126 127 public static Map<String, UIComponent> parseAndStoreComponents(FacesContext facesContext) { 128 Map parameterMap = facesContext.getExternalContext().getRequestParameterMap(); 129 String ajaxComponentIds = (String) parameterMap.get(AjaxPhaseListener.AJAX_COMPONENT_ID); 130 if (ajaxComponentIds != null) { 131 LOG.info("ajaxComponentIds = \"" + ajaxComponentIds + "\""); 132 StringTokenizer tokenizer = new StringTokenizer(ajaxComponentIds, ","); 133 Map<String, UIComponent> ajaxComponents = new HashMap<String, UIComponent>(tokenizer.countTokens()); 134 //noinspection unchecked 135 facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents); 136 javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot(); 137 while (tokenizer.hasMoreTokens()) { 138 String ajaxId = tokenizer.nextToken(); 139 UIComponent ajaxComponent = viewRoot.findComponent(ajaxId); 140 if (ajaxComponent != null) { 141 LOG.info("ajaxComponent for \"" + ajaxId + "\" = \"" + ajaxComponent + "\""); 142 ajaxComponents.put(ajaxId, ajaxComponent); 143 } 144 } 145 return ajaxComponents; 146 } 147 return null; 148 } 149 150 public static Map<String, UIComponent> getAjaxComponents(FacesContext facesContext) { 151 //noinspection unchecked 152 return (Map<String, UIComponent>) 153 facesContext.getExternalContext().getRequestMap().get(AJAX_COMPONENTS); 154 } 155 156 public static void ensureDecoded(FacesContext facesContext, String clientId) { 157 ensureDecoded(facesContext, facesContext.getViewRoot().findComponent(clientId)); 158 } 159 160 public static void ensureDecoded(FacesContext facesContext, UIComponent component) { 161 Map<String, UIComponent> ajaxComponents = getAjaxComponents(facesContext); 162 if (ajaxComponents != null) { 163 for (UIComponent uiComponent : ajaxComponents.values()) { 164 UIComponent currentComponent = component; 165 while (currentComponent != null) { 166 if (component == uiComponent) { 167 return; 168 } 169 currentComponent = currentComponent.getParent(); 170 } 171 } 172 component.processDecodes(facesContext); 173 } 174 } 175 }