1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.myfaces.custom.outputlinkdynamic;
21
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.util.HashMap;
25 import java.util.Iterator;
26 import java.util.Map;
27
28 import javax.faces.FacesException;
29 import javax.faces.FactoryFinder;
30 import javax.faces.component.UIComponent;
31 import javax.faces.component.UIParameter;
32 import javax.faces.context.ExternalContext;
33 import javax.faces.context.FacesContext;
34 import javax.faces.context.FacesContextFactory;
35 import javax.faces.context.ResponseStream;
36 import javax.faces.context.ResponseWriter;
37 import javax.faces.lifecycle.Lifecycle;
38 import javax.faces.lifecycle.LifecycleFactory;
39 import javax.faces.webapp.FacesServlet;
40 import javax.servlet.ServletContext;
41 import javax.servlet.http.HttpServletRequest;
42 import javax.servlet.http.HttpServletResponse;
43
44 import org.apache.myfaces.component.html.util.ParameterResourceHandler;
45 import org.apache.myfaces.custom.dynamicResources.ResourceContext;
46 import org.apache.myfaces.custom.dynamicResources.ResourceRenderer;
47 import org.apache.myfaces.custom.dynamicResources.SimpleResourceContext;
48 import org.apache.myfaces.shared_tomahawk.renderkit.RendererUtils;
49 import org.apache.myfaces.renderkit.html.util.AddResource;
50 import org.apache.myfaces.shared_tomahawk.renderkit.html.HTML;
51 import org.apache.myfaces.shared_tomahawk.renderkit.html.HtmlRendererUtils;
52 import org.apache.myfaces.renderkit.html.ext.HtmlLinkRenderer;
53 import org.apache.myfaces.renderkit.html.util.AddResourceFactory;
54 import org.apache.myfaces.renderkit.html.util.ResourceLoader;
55 import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
56
57
58
59
60
61
62
63
64
65
66
67 public class OutputLinkDynamicRenderer extends HtmlLinkRenderer implements ResourceLoader
68 {
69 public static final String RENDERER_TYPE = "org.apache.myfaces.OutputLinkDynamicRenderer";
70
71 private static final class ResourceResponseStream extends ResponseStream
72 {
73 private final OutputStream _out;
74
75 private ResourceResponseStream(OutputStream out)
76 {
77 _out = out;
78 }
79
80 public void close() throws IOException
81 {
82 _out.flush();
83 _out.close();
84 }
85
86 public void flush() throws IOException
87 {
88 _out.flush();
89 }
90
91 public void write(byte[] b, int off, int len) throws IOException
92 {
93 _out.write(b, off, len);
94 }
95
96 public void write(byte[] b) throws IOException
97 {
98 _out.write(b);
99 }
100
101 public void write(int b) throws IOException
102 {
103 _out.write(b);
104 }
105 }
106
107 private static final String RENDERER_PARAM = "_renderer";
108
109 public void encodeBegin(FacesContext context, UIComponent component) throws IOException
110 {
111 RendererUtils.checkParamValidity(context, component, OutputLinkDynamic.class);
112
113 OutputLinkDynamic outputLinkDynamic = (OutputLinkDynamic) component;
114 ResponseWriter writer = context.getResponseWriter();
115
116 writer.startElement(HTML.ANCHOR_ELEM, outputLinkDynamic);
117 HtmlRendererUtils.writeIdIfNecessary(writer, outputLinkDynamic, context);
118 HtmlRendererUtils.renderHTMLAttributes(writer, outputLinkDynamic,
119 HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES);
120
121 Map params = getParameterMap(context, component);
122
123 Class resourceRendererClass = outputLinkDynamic.getResourceRendererClass();
124 if (resourceRendererClass == null)
125 {
126 throw new FacesException("No resourceRendererClass defined for component "
127 + component.getId());
128 }
129 params.put(RENDERER_PARAM, resourceRendererClass.getName());
130
131 AddResource addResource = AddResourceFactory.getInstance(context);
132 String url = addResource.getResourceUri(context, new ParameterResourceHandler(this
133 .getClass(), params));
134 writer.writeAttribute(HTML.HREF_ATTR, url, null);
135 }
136
137 public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
138 {
139 ResponseWriter writer = facesContext.getResponseWriter();
140
141 writer.writeText("", null);
142 writer.endElement(HTML.ANCHOR_ELEM);
143 }
144
145 protected Map getParameterMap(FacesContext context, UIComponent component)
146 {
147 Map result = new HashMap();
148 for (Iterator iter = component.getChildren().iterator(); iter.hasNext();)
149 {
150 UIComponent child = (UIComponent) iter.next();
151 if (child instanceof UIParameter)
152 {
153 UIParameter uiparam = (UIParameter) child;
154 Object value = uiparam.getValue();
155 if (value != null)
156 {
157 result.put(uiparam.getName(), value);
158 }
159 }
160 }
161 return result;
162 }
163
164 public void decode(FacesContext facesContext, UIComponent component)
165 {
166 super.decode(facesContext, component);
167 }
168
169
170
171
172
173 public void serveResource(ServletContext context, HttpServletRequest request,
174 HttpServletResponse response, String resourceUri) throws IOException
175 {
176 FacesContextFactory facesContextFactory = (FacesContextFactory) FactoryFinder
177 .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
178 LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
179 .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
180 Lifecycle lifecycle = lifecycleFactory.getLifecycle(getLifecycleId(context));
181 FacesContext facesContext = facesContextFactory.getFacesContext(context, request, response,
182 lifecycle);
183 facesContext.setResponseStream(new ResourceResponseStream(response.getOutputStream()));
184 try
185 {
186 Map requestMap = facesContext.getExternalContext().getRequestParameterMap();
187 Object rendererValue = requestMap.get(RENDERER_PARAM);
188 if (rendererValue == null)
189 {
190 throw new FacesException("no resource renderer defined.");
191 }
192 try
193 {
194 Class rendererClass = ClassUtils.classForName(rendererValue.toString());
195 if (!ResourceRenderer.class.isAssignableFrom(rendererClass))
196 {
197 throw new FacesException("Resource renderer class [" + rendererValue
198 + "] does not implement " + ResourceRenderer.class.getName());
199 }
200 try
201 {
202 ResourceRenderer resourceRenderer = (ResourceRenderer) rendererClass.newInstance();
203 renderResource(resourceRenderer, facesContext);
204 }
205 catch (InstantiationException e)
206 {
207 throw new FacesException("could not instantiate resource renderer class "
208 + rendererValue + " : " + e.getMessage(), e);
209 }
210 catch (IllegalAccessException e)
211 {
212 throw new FacesException("could not instantiate resource renderer class "
213 + rendererValue + " : " + e.getMessage(), e);
214 }
215 catch (Exception e)
216 {
217 throw new FacesException("could not renderer resource "
218 + rendererValue + " : " + e.getMessage(), e);
219 }
220 }
221 catch (ClassNotFoundException e)
222 {
223 throw new FacesException("image renderer class not found: " + e.getMessage(), e);
224 }
225 facesContext.getResponseStream().close();
226 }
227 finally
228 {
229 facesContext.release();
230 }
231 }
232
233 protected void renderResource(ResourceRenderer resourceRenderer, FacesContext facesContext)
234 throws Exception
235 {
236 ResourceContext resourceContext = createResourceContext(facesContext);
237
238 resourceRenderer.setContext(facesContext, resourceContext);
239
240 HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext()
241 .getResponse();
242
243
244 int contentLength = resourceRenderer.getContentLength();
245 if( contentLength >0 )
246 {
247 response.setContentLength(contentLength);
248 }
249
250 String contentType = resourceRenderer.getContentType();
251 if (contentType != null && contentType.length() > 0 )
252 {
253 response.setContentType(contentType);
254 }
255
256 ResponseStream out = facesContext.getResponseStream();
257 try
258 {
259 resourceRenderer.renderResource( out );
260 }
261 finally
262 {
263 out.close();
264 facesContext.responseComplete();
265 }
266 }
267
268 protected ResourceContext createResourceContext(FacesContext facesContext)
269 {
270 ExternalContext externalContext = facesContext.getExternalContext();
271 final Map requestMap = externalContext.getRequestParameterMap();
272 return new SimpleResourceContext(requestMap);
273 }
274
275 private String getLifecycleId(ServletContext context)
276 {
277 String lifecycleId = context.getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
278 return lifecycleId != null ? lifecycleId : LifecycleFactory.DEFAULT_LIFECYCLE;
279 }
280 }