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.shared.renderkit.JSFAttr;
42 import org.apache.myfaces.shared.renderkit.RendererUtils;
43 import org.apache.myfaces.shared.renderkit.html.HTML;
44 import org.apache.myfaces.shared.renderkit.html.util.ResourceUtils;
45 import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
46 import org.apache.myfaces.view.facelets.tag.jsf.ComponentSupport;
47
48
49
50
51
52
53
54
55 @JSFRenderer(renderKitId = "HTML_BASIC", family = "javax.faces.Output", type = "javax.faces.resource.Script")
56 @ListenerFor(systemEventClass = PostAddToViewEvent.class)
57 public class HtmlScriptRenderer extends Renderer implements ComponentSystemEventListener
58 {
59 private static final Logger log = Logger.getLogger(HtmlScriptRenderer.class.getName());
60
61 @Override
62 public void processEvent(ComponentSystemEvent event)
63 {
64 if (event instanceof PostAddToViewEvent)
65 {
66 UIComponent component = event.getComponent();
67 String target = (String) component.getAttributes().get(JSFAttr.TARGET_ATTR);
68 if (target != null)
69 {
70 FacesContext facesContext = FacesContext.getCurrentInstance();
71
72 Location location = (Location) component.getAttributes().get(CompositeComponentELUtils.LOCATION_KEY);
73 if (location != null)
74 {
75 UIComponent ccParent
76 = CompositeComponentELUtils.getCompositeComponentBasedOnLocation(facesContext, location);
77 if (ccParent != null)
78 {
79 component.getAttributes().put(
80 CompositeComponentELUtils.CC_FIND_COMPONENT_EXPRESSION,
81 ComponentSupport.getFindComponentExpression(facesContext, ccParent));
82 }
83 }
84
85 facesContext.getViewRoot().addComponentResource(facesContext, component, target);
86 }
87 }
88
89 if (event instanceof PreRenderViewEvent)
90 {
91
92 UIComponent component = event.getComponent();
93 String target = (String) component.getAttributes().get(JSFAttr.TARGET_ATTR);
94 if (target != null)
95 {
96 FacesContext facesContext = FacesContext.getCurrentInstance();
97 UIComponent uiTarget = facesContext.getViewRoot().getFacet(target);
98 if (uiTarget == null)
99 {
100 throw new FacesException("Target for component not found");
101 }
102 }
103 }
104 }
105
106 @Override
107 public boolean getRendersChildren()
108 {
109 return true;
110 }
111
112 @Override
113 public void encodeChildren(FacesContext facesContext, UIComponent component)
114 throws IOException
115 {
116 if (facesContext == null)
117 {
118 throw new NullPointerException("context");
119 }
120 if (component == null)
121 {
122 throw new NullPointerException("component");
123 }
124
125 Map<String, Object> componentAttributesMap = component.getAttributes();
126 String resourceName = (String) componentAttributesMap.get(JSFAttr.NAME_ATTR);
127 boolean hasChildren = component.getChildCount() > 0;
128
129 if (resourceName != null && (!"".equals(resourceName)))
130 {
131 if (hasChildren)
132 {
133 log.info("Component with resourceName " + resourceName +
134 " and child components found. Child components will be ignored.");
135 }
136 }
137 else
138 {
139 if (hasChildren)
140 {
141
142
143
144
145 ResponseWriter writer = facesContext.getResponseWriter();
146 writer.startElement(HTML.SCRIPT_ELEM, component);
147 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
148 RendererUtils.renderChildren(facesContext, component);
149 writer.endElement(HTML.SCRIPT_ELEM);
150 }
151 else
152 {
153 if (!facesContext.getApplication().getProjectStage().equals(
154 ProjectStage.Production))
155 {
156 facesContext.addMessage(component.getClientId(facesContext),
157 new FacesMessage("Component with no name and no body content, so nothing rendered."));
158 }
159 }
160 }
161 }
162
163 @Override
164 public void encodeEnd(FacesContext facesContext, UIComponent component)
165 throws IOException
166 {
167 super.encodeEnd(facesContext, component);
168
169 Map<String, Object> componentAttributesMap = component.getAttributes();
170 String resourceName = (String) componentAttributesMap.get(JSFAttr.NAME_ATTR);
171 String libraryName = (String) componentAttributesMap.get(JSFAttr.LIBRARY_ATTR);
172
173 if (resourceName == null)
174 {
175
176
177
178 return;
179 }
180 if ("".equals(resourceName))
181 {
182 return;
183 }
184
185 String additionalQueryParams = null;
186 int index = resourceName.indexOf('?');
187 if (index >= 0)
188 {
189 additionalQueryParams = resourceName.substring(index + 1);
190 resourceName = resourceName.substring(0, index);
191 }
192
193 Resource resource;
194 if (libraryName == null)
195 {
196 if (ResourceUtils.isRenderedScript(facesContext, libraryName, resourceName))
197 {
198
199 return;
200 }
201 resource = facesContext.getApplication().getResourceHandler()
202 .createResource(resourceName);
203 }
204 else
205 {
206 if (ResourceUtils.isRenderedScript(facesContext, libraryName, resourceName))
207 {
208
209 return;
210 }
211 resource = facesContext.getApplication().getResourceHandler()
212 .createResource(resourceName, libraryName);
213
214 }
215
216 if (resource == null)
217 {
218
219 log.warning("Resource referenced by resourceName " + resourceName +
220 (libraryName == null ? "" : " and libraryName " + libraryName) +
221 " not found in call to ResourceHandler.createResource." +
222 " It will be silenty ignored.");
223 return;
224 }
225 else
226 {
227 if (ResourceUtils.isRenderedScript(facesContext, resource.getLibraryName(), resource.getResourceName()))
228 {
229
230 return;
231 }
232
233
234 ResourceUtils.markScriptAsRendered(facesContext, libraryName, resourceName);
235 ResourceUtils.markScriptAsRendered(facesContext, resource.getLibraryName(), resource.getResourceName());
236 ResponseWriter writer = facesContext.getResponseWriter();
237 writer.startElement(HTML.SCRIPT_ELEM, component);
238
239
240 writer.writeAttribute(HTML.SCRIPT_TYPE_ATTR, HTML.SCRIPT_TYPE_TEXT_JAVASCRIPT, null);
241 String path = resource.getRequestPath();
242 if (additionalQueryParams != null)
243 {
244 path = path + ((path.indexOf('?') >= 0) ? "&" : "?") + additionalQueryParams;
245 }
246 writer.writeURIAttribute(HTML.SRC_ATTR, facesContext.getExternalContext().encodeResourceURL(path), null);
247 writer.endElement(HTML.SCRIPT_ELEM);
248 }
249 }
250
251 }