1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.renderkit.html;
20
21 import java.io.IOException;
22 import java.util.Map;
23 import java.util.logging.Logger;
24
25 import javax.faces.FacesException;
26 import javax.faces.application.FacesMessage;
27 import javax.faces.application.ProjectStage;
28 import javax.faces.application.Resource;
29 import javax.faces.component.UIComponent;
30 import javax.faces.context.FacesContext;
31 import javax.faces.context.ResponseWriter;
32 import javax.faces.event.ComponentSystemEvent;
33 import javax.faces.event.ComponentSystemEventListener;
34 import javax.faces.event.ListenerFor;
35 import javax.faces.event.PostAddToViewEvent;
36 import javax.faces.event.PreRenderViewEvent;
37 import javax.faces.render.Renderer;
38 import javax.faces.view.Location;
39
40 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFRenderer;
41 import org.apache.myfaces.context.RequestViewContext;
42 import org.apache.myfaces.shared.config.MyfacesConfig;
43 import org.apache.myfaces.shared.renderkit.JSFAttr;
44 import org.apache.myfaces.shared.renderkit.RendererUtils;
45 import org.apache.myfaces.shared.renderkit.html.HTML;
46 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
47 import org.apache.myfaces.shared.util.ExternalContextUtils;
48 import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
49 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
50 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
51
52
53
54
55
56
57
58
59 @JSFRenderer(renderKitId = "HTML_BASIC", family = "javax.faces.Output", type = "javax.faces.resource.Script")
60 @ListenerFor(systemEventClass = PostAddToViewEvent.class)
61 public class HtmlScriptRenderer extends Renderer implements ComponentSystemEventListener
62 {
63
64 private static final Logger log = Logger.getLogger(HtmlScriptRenderer.class.getName());
65
66 private static final String IS_BUILDING_INITIAL_STATE = "javax.faces.IS_BUILDING_INITIAL_STATE";
67
68 public void processEvent(ComponentSystemEvent event)
69 {
70 if (event instanceof PostAddToViewEvent)
71 {
72 UIComponent component = event.getComponent();
73 String target = (String) component.getAttributes().get(JSFAttr.TARGET_ATTR);
74 if (target != null)
75 {
76 FacesContext facesContext = FacesContext.getCurrentInstance();
77
78 Location location = (Location) component.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
79 if (location != null)
80 {
81 UIComponent ccParent
82 = CompositeComponentELUtils.getCompositeComponentBasedOnLocation(facesContext, location);
83 if (ccParent != null)
84 {
85 component.getAttributes().put(
86 CompositeComponentELUtils.CC_FIND_COMPONENT_EXPRESSION,
87 ComponentSupport.getFindComponentExpression(facesContext, ccParent));
88 }
89 }
90
91
92
93
94
95 if (!ExternalContextUtils.isPortlet(facesContext.getExternalContext()) &&
96 facesContext.getPartialViewContext().isAjaxRequest())
97 {
98 boolean isBuildingInitialState = facesContext.getAttributes().
99 containsKey(IS_BUILDING_INITIAL_STATE);
100
101 boolean isPostAddToViewEventAfterBuildInitialState =
102 !isBuildingInitialState ||
103 (isBuildingInitialState &&
104 FaceletViewDeclarationLanguage.isRefreshingTransientBuild(facesContext));
105 if (isPostAddToViewEventAfterBuildInitialState &&
106 MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).
107 isStrictJsf2RefreshTargetAjax())
108 {
109
110 RequestViewContext requestViewContext = RequestViewContext.getCurrentInstance(facesContext);
111 requestViewContext.setRenderTarget("head", true);
112 }
113 }
114
115 facesContext.getViewRoot().addComponentResource(facesContext,
116 component, target);
117 }
118 }
119
120 if (event instanceof PreRenderViewEvent)
121
122 {
123
124 UIComponent component = event.getComponent();
125 String target = (String) component.getAttributes().get(JSFAttr.TARGET_ATTR);
126 if (target != null)
127 {
128 FacesContext facesContext = FacesContext.getCurrentInstance();
129 UIComponent uiTarget = facesContext.getViewRoot().getFacet(target);
130 if (uiTarget == null)
131 {
132 throw new FacesException("Target for component not found");
133 }
134 }
135 }
136 }
137
138 @Override
139 public boolean getRendersChildren()
140 {
141 return true;
142 }
143
144 @Override
145 public void encodeChildren(FacesContext facesContext, UIComponent component)
146 throws IOException
147 {
148 if (facesContext == null)
149 {
150 throw new NullPointerException("context");
151 }
152 if (component == null)
153 {
154 throw new NullPointerException("component");
155 }
156
157 Map<String, Object> componentAttributesMap = component.getAttributes();
158 String resourceName = (String) componentAttributesMap.get(JSFAttr.NAME_ATTR);
159 boolean hasChildren = component.getChildCount() > 0;
160
161 if (resourceName != null && (!"".equals(resourceName)))
162 {
163 if (hasChildren)
164 {
165 log.info("Component with resourceName " + resourceName +
166 " and child components found. Child components will be ignored.");
167 }
168 }
169 else
170 {
171 if (hasChildren)
172 {
173
174
175
176
177 ResponseWriter writer = facesContext.getResponseWriter();
178 writer.startElement(HTML.SCRIPT_ELEM, component);
179 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
180 RendererUtils.renderChildren(facesContext, component);
181 writer.endElement(HTML.SCRIPT_ELEM);
182 }
183 else
184 {
185 if (!facesContext.getApplication().getProjectStage().equals(
186 ProjectStage.Production))
187 {
188 facesContext.addMessage(component.getClientId(facesContext),
189 new FacesMessage("Component with no name and no body content, so nothing rendered."));
190 }
191 }
192 }
193 }
194
195 @Override
196 public void encodeEnd(FacesContext facesContext, UIComponent component)
197 throws IOException
198 {
199 super.encodeEnd(facesContext, component);
200
201 Map<String, Object> componentAttributesMap = component.getAttributes();
202 String resourceName = (String) componentAttributesMap.get(JSFAttr.NAME_ATTR);
203 String libraryName = (String) componentAttributesMap.get(JSFAttr.LIBRARY_ATTR);
204
205 if (resourceName == null)
206 {
207
208
209
210 return;
211 }
212 if ("".equals(resourceName))
213 {
214 return;
215 }
216
217 String additionalQueryParams = null;
218 int index = resourceName.indexOf('?');
219 if (index >= 0)
220 {
221 additionalQueryParams = resourceName.substring(index + 1);
222 resourceName = resourceName.substring(0, index);
223 }
224
225 Resource resource;
226 if (libraryName == null)
227 {
228 if (ResourceUtils.isRenderedScript(facesContext, libraryName, resourceName))
229 {
230
231 return;
232 }
233 resource = facesContext.getApplication().getResourceHandler()
234 .createResource(resourceName);
235 }
236 else
237 {
238 if (ResourceUtils.isRenderedScript(facesContext, libraryName, resourceName))
239 {
240
241 return;
242 }
243 resource = facesContext.getApplication().getResourceHandler()
244 .createResource(resourceName, libraryName);
245
246 }
247
248 if (resource == null)
249 {
250
251 log.warning("Resource referenced by resourceName " + resourceName +
252 (libraryName == null ? "" : " and libraryName " + libraryName) +
253 " not found in call to ResourceHandler.createResource." +
254 " It will be silenty ignored.");
255 return;
256 }
257 else
258 {
259 if (ResourceUtils.isRenderedScript(facesContext, resource.getLibraryName(), resource.getResourceName()))
260 {
261
262 return;
263 }
264
265
266 ResourceUtils.markScriptAsRendered(facesContext, libraryName, resourceName);
267 ResourceUtils.markScriptAsRendered(facesContext, resource.getLibraryName(), resource.getResourceName());
268 ResponseWriter writer = facesContext.getResponseWriter();
269 writer.startElement(HTML.SCRIPT_ELEM, component);
270
271
272 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
273 String path = resource.getRequestPath();
274 if (additionalQueryParams != null)
275 {
276 path = path + ((path.indexOf('?') >= 0) ? "&" : "?") + additionalQueryParams;
277 }
278 writer.writeURIAttribute(HTML.SRC_ATTR, facesContext.getExternalContext().encodeResourceURL(path), null);
279 writer.endElement(HTML.SCRIPT_ELEM);
280 }
281 }
282
283 }