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.commons.lang.StringUtils;
24  import org.apache.myfaces.tobago.ajax.AjaxUtils;
25  import org.apache.myfaces.tobago.compat.FacesUtils;
26  import org.apache.myfaces.tobago.internal.component.AbstractUIMessages;
27  import org.apache.myfaces.tobago.renderkit.RendererBase;
28  import org.apache.myfaces.tobago.util.ComponentUtils;
29  import org.slf4j.Logger;
30  import org.slf4j.LoggerFactory;
31  
32  import javax.faces.component.UIComponent;
33  import javax.faces.component.UIPanel;
34  import javax.faces.context.FacesContext;
35  import java.io.IOException;
36  import java.util.ArrayList;
37  import java.util.HashMap;
38  import java.util.List;
39  import java.util.Map;
40  import java.util.StringTokenizer;
41  
42  public class AjaxInternalUtils {
43  
44    private static final Logger LOG = LoggerFactory.getLogger(AjaxInternalUtils.class);
45  
46    public static final String AJAX_COMPONENTS = AjaxUtils.class.getName() + ".AJAX_COMPONENTS";
47  
48    private static final String TOBAGO_MESSAGES_CLIENT_IDS = "tobago.messages.clientIds";
49    public static final String TOBAGO_PARTIAL_IDS = "tobago::partialIds";
50  
51    public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass) {
52      if (facesContext == null) {
53        throw new NullPointerException("facesContext may not be null");
54      }
55      if (uiComponent == null) {
56        throw new NullPointerException("uiComponent may not be null");
57      }
58      //if (compClass != null && !(compClass.isAssignableFrom(uiComponent.getClass())))
59      // why isAssignableFrom with additional getClass method call if isInstance does the same?
60      if (compClass != null && !(compClass.isInstance(uiComponent))) {
61        throw new IllegalArgumentException("uiComponent : "
62            + uiComponent.getClass().getName() + " is not instance of "
63            + compClass.getName() + " as it should be");
64      }
65    }
66  
67    public static void encodeAjaxComponent(FacesContext facesContext, UIComponent component) throws IOException {
68      if (facesContext == null) {
69        throw new NullPointerException("facesContext");
70      }
71      if (!component.isRendered()) {
72        return;
73      }
74      RendererBase renderer = ComponentUtils.getRenderer(facesContext, component);
75      if (renderer != null && renderer instanceof AjaxRenderer) {
76        ((AjaxRenderer) renderer).encodeAjax(facesContext, component);
77      }
78    }
79  
80    public static void setRenderAllComponents(FacesContext facesContext) {
81      Map<String, UIComponent> ajaxComponents = new HashMap<String, UIComponent>();
82      facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents);
83      javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot();
84      UIComponent page = viewRoot.getChildren().get(0);
85      ajaxComponents.put(page.getClientId(facesContext), page);
86    }
87  
88    public static void storeMessagesClientIds(FacesContext facesContext, AbstractUIMessages messages) {
89      Map attributes = FacesUtils.getFacesContextAttributes(facesContext);
90      List<String> messageClientIds;
91      if (attributes.containsKey(TOBAGO_MESSAGES_CLIENT_IDS)) {
92        messageClientIds = (List<String>) attributes.get(TOBAGO_MESSAGES_CLIENT_IDS);
93      } else {
94        messageClientIds = new ArrayList<String>();
95        attributes.put(TOBAGO_MESSAGES_CLIENT_IDS, messageClientIds);
96      }
97      messageClientIds.add(messages.getClientId(facesContext));
98    }
99  
100   public static List<String> getMessagesClientIds(FacesContext facesContext) {
101      return (List<String>) FacesUtils.getFacesContextAttributes(facesContext).get(TOBAGO_MESSAGES_CLIENT_IDS);
102   }
103 
104   public static List<String> getMessagesComponentIds(FacesContext facesContext) {
105     Map parameterMap = facesContext.getExternalContext().getRequestParameterMap();
106     UIComponent component = facesContext.getViewRoot().getChildren().get(0);
107     String clientId = component.getClientId(facesContext);
108     String ids = (String) parameterMap.get(clientId + ComponentUtils.SUB_SEPARATOR + "messagesClientIds");
109     List<String> list = new ArrayList<String>();
110     if (ids != null) {
111       StringTokenizer tokenizer = new StringTokenizer(ids, ",");
112       while (tokenizer.hasMoreTokens()) {
113         String id = tokenizer.nextToken();
114         list.add(id);
115       }
116     }
117     return list;
118 
119   }
120 
121   public static Map<String, UIComponent> parseAndStoreComponents(FacesContext facesContext) {
122     Map parameterMap = facesContext.getExternalContext().getRequestParameterMap();
123     String ajaxComponentIds = (String) parameterMap.get(TOBAGO_PARTIAL_IDS);
124     if (ajaxComponentIds != null) {
125       if (LOG.isDebugEnabled()) {
126         LOG.debug("ajaxComponentIds = \"" + ajaxComponentIds + "\"");
127       }
128       StringTokenizer tokenizer = new StringTokenizer(ajaxComponentIds, ",");
129       Map<String, UIComponent> ajaxComponents = new HashMap<String, UIComponent>(tokenizer.countTokens());
130       //noinspection unchecked
131       facesContext.getExternalContext().getRequestMap().put(AJAX_COMPONENTS, ajaxComponents);
132       javax.faces.component.UIViewRoot viewRoot = facesContext.getViewRoot();
133       while (tokenizer.hasMoreTokens()) {
134         String ajaxId = tokenizer.nextToken();
135         UIComponent ajaxComponent = viewRoot.findComponent(ajaxId);
136         if (ajaxComponent != null) {
137           if (LOG.isDebugEnabled()) {
138             LOG.debug("ajaxComponent for \"" + ajaxId + "\" = \"" + ajaxComponent + "\"");
139           }
140           ajaxComponents.put(ajaxId, ajaxComponent);
141         }
142       }
143       return ajaxComponents;
144     }
145     return null;
146   }
147 
148   public static Map<String, UIComponent> getAjaxComponents(FacesContext facesContext) {
149     //noinspection unchecked
150     return (Map<String, UIComponent>)
151         facesContext.getExternalContext().getRequestMap().get(AJAX_COMPONENTS);
152   }
153 
154   public static void addAjaxComponent(FacesContext facesContext, UIComponent component) {
155     Map<String, UIComponent> ajaxComponents =
156         (Map<String, UIComponent>) facesContext.getExternalContext().getRequestMap().get(AJAX_COMPONENTS);
157     if (ajaxComponents != null) {
158       if (!alreadyContained(component, ajaxComponents)) {
159         ajaxComponents.put(component.getClientId(facesContext), component);
160       }
161     }
162   }
163 
164   public static String encodeJavaScriptString(String value) {
165     String result = StringUtils.replace(value, "\\", "\\\\");
166     result = StringUtils.replace(result, "\n", "\\n");
167     result = StringUtils.replace(result, "\r", "\\r");
168     return StringUtils.replace(result, "\"", "\\\"");
169   }
170 
171   public static boolean alreadyContained(UIComponent component, Map<String, UIComponent> ajaxComponents) {
172     for (UIComponent uiComponent : ajaxComponents.values()) {
173       // is component or a parent of it in the list?
174       UIComponent parent = component;
175       while (parent != null) {
176         if (component == uiComponent) {
177           // nothing to do, because it was already decoded (in the list)
178           return true;
179         }
180         parent = parent.getParent();
181       }
182     }
183     return false;
184   }
185 
186   public static boolean addNextPossibleAjaxComponent(FacesContext context, String componentClientId) {
187     UIComponent component = ComponentUtils.findComponent(context.getViewRoot(), componentClientId);
188     component = component.getParent();
189     if (component instanceof UIPanel) {
190       addAjaxComponent(context, component);
191       return true;
192     } else {
193       LOG.error("Ignore adding ajax component (no instance of UIPanel) id: " + componentClientId + " component: "
194           + component);
195       return false;
196     }
197   }
198 
199   public static void ensureDecoded(FacesContext facesContext, String clientId) {
200     ensureDecoded(facesContext, facesContext.getViewRoot().findComponent(clientId));
201   }
202 
203   public static void ensureDecoded(FacesContext facesContext, UIComponent component) {
204     if (component == null) {
205       LOG.warn("Ignore AjaxComponent: null");
206       return;
207     }
208     Map<String, UIComponent> ajaxComponents = getAjaxComponents(facesContext);
209     if (ajaxComponents != null) {
210       if (!alreadyContained(component, ajaxComponents)) {
211         component.processDecodes(facesContext);
212       }
213     }
214   }
215 }