View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.tobago.internal.ajax;
21  
22  
23  import org.apache.myfaces.tobago.ajax.AjaxUtils;
24  import org.apache.myfaces.tobago.internal.component.AbstractUIMessages;
25  import org.apache.myfaces.tobago.internal.util.StringUtils;
26  import org.apache.myfaces.tobago.renderkit.RendererBase;
27  import org.apache.myfaces.tobago.util.ComponentUtils;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  
31  import javax.faces.component.UIComponent;
32  import javax.faces.component.UIPanel;
33  import javax.faces.context.FacesContext;
34  import java.io.IOException;
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.StringTokenizer;
40  
41  public final class AjaxInternalUtils {
42  
43    private static final Logger LOG = LoggerFactory.getLogger(AjaxInternalUtils.class);
44  
45    public static final String AJAX_COMPONENTS = AjaxUtils.class.getName() + ".AJAX_COMPONENTS";
46  
47    private static final String TOBAGO_MESSAGES_CLIENT_IDS = "tobago.messages.clientIds";
48    public static final String TOBAGO_PARTIAL_IDS = "tobago::partialIds";
49  
50    private AjaxInternalUtils() {
51    }
52  
53    public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass) {
54      if (facesContext == null) {
55        throw new NullPointerException("facesContext may not be null");
56      }
57      if (uiComponent == null) {
58        throw new NullPointerException("uiComponent may not be null");
59      }
60      //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass())))
61      // why isAssignableFrom with additional getClass method call if isInstance does the same?
62      if (compClass != null && !(compClass.isInstance(uiComponent))) {
63        throw new IllegalArgumentException("uiComponent : "
64            + uiComponent.getClass().getName() + " is not instance of "
65            + compClass.getName() + " as it should be");
66      }
67    }
68  
69    public static void encodeAjaxComponent(FacesContext facesContext, UIComponent component) throws IOException {
70      if (facesContext == null) {
71        throw new NullPointerException("facesContext");
72      }
73      if (!component.isRendered()) {
74        return;
75      }
76      RendererBase renderer = ComponentUtils.getRenderer(facesContext, component);
77      if (renderer != null && renderer instanceof AjaxRenderer) {
78        ((AjaxRenderer) renderer).encodeAjax(facesContext, component);
79      }
80    }
81  
82    public static void setRenderAllComponents(FacesContext facesContext) {
83      Map<String, UIComponent> ajaxComponents = new HashMap<String, UIComponent>();
84      facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents);
85      javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot();
86      UIComponent page = viewRoot.getChildren().get(0);
87      ajaxComponents.put(page.getClientId(facesContext), page);
88    }
89  
90    public static void storeMessagesClientIds(FacesContext facesContext, AbstractUIMessages messages) {
91      Map attributes = facesContext.getAttributes();
92      List<String> messageClientIds;
93      if (attributes.containsKey(TOBAGO_MESSAGES_CLIENT_IDS)) {
94        messageClientIds = (List<String>) attributes.get(TOBAGO_MESSAGES_CLIENT_IDS);
95      } else {
96        messageClientIds = new ArrayList<String>();
97        attributes.put(TOBAGO_MESSAGES_CLIENT_IDS, messageClientIds);
98      }
99      messageClientIds.add(messages.getClientId(facesContext));
100   }
101 
102   public static List<String> getMessagesClientIds(FacesContext facesContext) {
103      return (List<String>) facesContext.getAttributes().get(TOBAGO_MESSAGES_CLIENT_IDS);
104   }
105 
106   public static List<String> getMessagesComponentIds(FacesContext facesContext) {
107     Map parameterMap = facesContext.getExternalContext().getRequestParameterMap();
108     UIComponent component = facesContext.getViewRoot().getChildren().get(0);
109     String clientId = component.getClientId(facesContext);
110     String ids = (String) parameterMap.get(clientId + ComponentUtils.SUB_SEPARATOR + "messagesClientIds");
111     List<String> list = new ArrayList<String>();
112     if (ids != null) {
113       StringTokenizer tokenizer = new StringTokenizer(ids, ",");
114       while (tokenizer.hasMoreTokens()) {
115         String id = tokenizer.nextToken();
116         list.add(id);
117       }
118     }
119     return list;
120 
121   }
122 
123   public static Map<String, UIComponent> parseAndStoreComponents(FacesContext facesContext) {
124     Map parameterMap = facesContext.getExternalContext().getRequestParameterMap();
125     String ajaxComponentIds = (String) parameterMap.get(TOBAGO_PARTIAL_IDS);
126     if (ajaxComponentIds != null) {
127       if (LOG.isDebugEnabled()) {
128         LOG.debug("ajaxComponentIds = \"" + ajaxComponentIds + "\"");
129       }
130       StringTokenizer tokenizer = new StringTokenizer(ajaxComponentIds, ",");
131       Map<String, UIComponent> ajaxComponents = new HashMap<String, UIComponent>(tokenizer.countTokens());
132       //noinspection unchecked
133       facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents);
134       javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot();
135       while (tokenizer.hasMoreTokens()) {
136         String ajaxId = tokenizer.nextToken();
137         UIComponent ajaxComponent = viewRoot.findComponent(ajaxId);
138         if (ajaxComponent != null) {
139           if (LOG.isDebugEnabled()) {
140             LOG.debug("ajaxComponent for \"" + ajaxId + "\" = \"" + ajaxComponent + "\"");
141           }
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 addAjaxComponent(FacesContext facesContext, UIComponent component) {
157     Map<String, UIComponent> ajaxComponents =
158         (Map<String, UIComponent>) facesContext.getExternalContext().getRequestMap().get(AJAX_COMPONENTS);
159     if (ajaxComponents != null) {
160       if (!alreadyContained(component, ajaxComponents)) {
161         ajaxComponents.put(component.getClientId(facesContext), component);
162       }
163     }
164   }
165 
166   public static String encodeJavaScriptString(String value) {
167     String result = StringUtils.replace(value, "\\", "\\\\");
168     result = StringUtils.replace(result, "\n", "\\n");
169     result = StringUtils.replace(result, "\r", "\\r");
170     return StringUtils.replace(result, "\"", "\\\"");
171   }
172 
173   public static boolean alreadyContained(UIComponent component, Map<String, UIComponent> ajaxComponents) {
174     for (UIComponent uiComponent : ajaxComponents.values()) {
175       // is component or a parent of it in the list?
176       UIComponent parent = component;
177       while (parent != null) {
178         if (component == uiComponent) {
179           // nothing to do, because it was already decoded (in the list)
180           return true;
181         }
182         parent = parent.getParent();
183       }
184     }
185     return false;
186   }
187 
188   public static boolean addNextPossibleAjaxComponent(FacesContext context, String componentClientId) {
189     UIComponent component = ComponentUtils.findComponent(context.getViewRoot(), componentClientId);
190     component = component.getParent();
191     if (component instanceof UIPanel) {
192       addAjaxComponent(context, component);
193       return true;
194     } else {
195       LOG.error("Ignore adding ajax component (no instance of UIPanel) id: " + componentClientId + " component: "
196           + component);
197       return false;
198     }
199   }
200 
201   public static void ensureDecoded(FacesContext facesContext, String clientId) {
202     ensureDecoded(facesContext, facesContext.getViewRoot().findComponent(clientId));
203   }
204 
205   public static void ensureDecoded(FacesContext facesContext, UIComponent component) {
206     if (component == null) {
207       LOG.warn("Ignore AjaxComponent: null");
208       return;
209     }
210     Map<String, UIComponent> ajaxComponents = getAjaxComponents(facesContext);
211     if (ajaxComponents != null) {
212       if (!alreadyContained(component, ajaxComponents)) {
213         component.processDecodes(facesContext);
214       }
215     }
216   }
217 }