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.HashMap; 031 import java.util.Iterator; 032 import java.util.Map; 033 import java.util.StringTokenizer; 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 boolean isAjaxRequest(FacesContext facesContext) { 042 return facesContext.getExternalContext().getRequestMap().containsKey(AJAX_COMPONENTS); 043 } 044 045 public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass) { 046 if (facesContext == null) { 047 throw new NullPointerException("facesContext may not be null"); 048 } 049 if (uiComponent == null) { 050 throw new NullPointerException("uiComponent may not be null"); 051 } 052 //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass()))) 053 // why isAssignableFrom with additional getClass method call if isInstance does the same? 054 if (compClass != null && !(compClass.isInstance(uiComponent))) { 055 throw new IllegalArgumentException("uiComponent : " 056 + uiComponent.getClass().getName() + " is not instance of " 057 + compClass.getName() + " as it should be"); 058 } 059 } 060 061 public static void encodeAjaxComponent(FacesContext facesContext, UIComponent component) throws IOException { 062 if (facesContext == null) { 063 throw new NullPointerException("facesContext"); 064 } 065 if (!component.isRendered()) { 066 return; 067 } 068 Renderer renderer = ComponentUtil.getRenderer(facesContext, component); 069 if (renderer != null && renderer instanceof AjaxRenderer) { 070 ((AjaxRenderer) renderer).encodeAjax(facesContext, component); 071 } 072 } 073 074 public static void processAjax(FacesContext facesContext, UIComponent component) 075 throws IOException { 076 if (component instanceof AjaxComponent) { 077 ((AjaxComponent) component).processAjax(facesContext); 078 } else { 079 processAjaxOnChildren(facesContext, component); 080 } 081 } 082 083 public static void processActiveAjaxComponent(FacesContext facesContext, 084 UIComponent component) 085 throws IOException { 086 087 if (component instanceof AjaxComponent) { 088 final UIViewRoot viewRoot = (UIViewRoot) facesContext.getViewRoot(); 089 090 // TODO: handle phaseListeners ?? 091 092 if (!facesContext.getRenderResponse()) { 093 component.processValidators(facesContext); 094 viewRoot.broadcastEventsForPhase(facesContext, PhaseId.PROCESS_VALIDATIONS); 095 } else if (LOG.isDebugEnabled()) { 096 LOG.debug("Skipping validate"); 097 } 098 099 if (!facesContext.getRenderResponse()) { 100 component.processUpdates(facesContext); 101 viewRoot.broadcastEventsForPhase(facesContext, PhaseId.UPDATE_MODEL_VALUES); 102 } else if (LOG.isDebugEnabled()) { 103 LOG.debug("Skipping updates"); 104 } 105 106 if (!facesContext.getRenderResponse()) { 107 viewRoot.processApplication(facesContext); 108 } else if (LOG.isDebugEnabled()) { 109 LOG.debug("Skipping application"); 110 } 111 112 ((AjaxComponent) component).encodeAjax(facesContext); 113 } else { 114 LOG.error("Can't process non AjaxComponent : \"" 115 + component.getClientId(facesContext) + "\" = " 116 + component.getClass().getName()); 117 } 118 } 119 120 public static void processAjaxOnChildren(FacesContext facesContext, 121 UIComponent component) throws IOException { 122 123 final Iterator<UIComponent> facetsAndChildren = component.getFacetsAndChildren(); 124 while (facetsAndChildren.hasNext() && !facesContext.getResponseComplete()) { 125 AjaxUtils.processAjax(facesContext, facetsAndChildren.next()); 126 } 127 } 128 129 public static Map<String, UIComponent> parseAndStoreComponents(FacesContext facesContext) { 130 Map parameterMap = facesContext.getExternalContext().getRequestParameterMap(); 131 String ajaxComponentIds = (String) parameterMap.get(AjaxPhaseListener.AJAX_COMPONENT_ID); 132 if (ajaxComponentIds != null) { 133 if (LOG.isDebugEnabled()) { 134 LOG.debug("ajaxComponentIds = \"" + ajaxComponentIds + "\""); 135 } 136 StringTokenizer tokenizer = new StringTokenizer(ajaxComponentIds, ","); 137 Map<String, UIComponent> ajaxComponents = new HashMap<String, UIComponent>(tokenizer.countTokens()); 138 //noinspection unchecked 139 facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents); 140 javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot(); 141 while (tokenizer.hasMoreTokens()) { 142 String ajaxId = tokenizer.nextToken(); 143 UIComponent ajaxComponent = viewRoot.findComponent(ajaxId); 144 if (ajaxComponent != null) { 145 if (LOG.isDebugEnabled()) { 146 LOG.debug("ajaxComponent for \"" + ajaxId + "\" = \"" + ajaxComponent + "\""); 147 } 148 ajaxComponents.put(ajaxId, ajaxComponent); 149 } 150 } 151 return ajaxComponents; 152 } 153 return null; 154 } 155 156 public static Map<String, UIComponent> getAjaxComponents(FacesContext facesContext) { 157 //noinspection unchecked 158 return (Map<String, UIComponent>) 159 facesContext.getExternalContext().getRequestMap().get(AJAX_COMPONENTS); 160 } 161 162 public static void ensureDecoded(FacesContext facesContext, String clientId) { 163 ensureDecoded(facesContext, facesContext.getViewRoot().findComponent(clientId)); 164 } 165 166 public static void ensureDecoded(FacesContext facesContext, UIComponent component) { 167 if (component == null) { 168 LOG.warn("Ignore AjaxComponent: null"); 169 return; 170 } 171 Map<String, UIComponent> ajaxComponents = getAjaxComponents(facesContext); 172 if (ajaxComponents != null) { 173 for (UIComponent uiComponent : ajaxComponents.values()) { 174 // is component or a parent of it in the list? 175 UIComponent parent = component; 176 while (parent != null) { 177 if (component == uiComponent) { 178 // nothing to do, because it was already decoded (in the list) 179 return; 180 } 181 parent = parent.getParent(); 182 } 183 } 184 component.processDecodes(facesContext); 185 } 186 } 187 }