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.custom.graphicimagedynamic;
21
22 import org.apache.myfaces.component.html.ext.HtmlGraphicImage;
23 import org.apache.myfaces.custom.graphicimagedynamic.util.ImageRenderer;
24 import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
25
26 import javax.faces.context.FacesContext;
27 import javax.faces.el.EvaluationException;
28 import javax.faces.el.ValueBinding;
29
30 /**
31 * Extends standard graphicImage.
32 * <p>
33 * This tag renders a html img tag and can be used to render dynamic images.
34 * </p>
35 * <p>
36 * Embedding images into html pages requires a second request to get the binary data
37 * stream of the image. The result is that the state of the view including the state of request
38 * scoped beans will not be available when the image is requested.
39 * </p>
40 * <p>
41 * The image data is written by an image renderer which can be defined by the
42 * imageRendererClass attribute.
43 * </p>
44 * <p>
45 * This component is able to use nested f:param elements to pass parameters to the image renderer.
46 * </p>
47 *
48 * @JSFComponent
49 * name = "s:graphicImageDynamic"
50 * tagClass = "org.apache.myfaces.custom.graphicimagedynamic.GraphicImageDynamicTag"
51 *
52 * @author Sylvain Vieujot (latest modification by $Author: skitching $)
53 *
54 * @version $Revision: 673833 $ $Date: 2005-05-11 19:57:24 +0200 (Wed, 11 May 2005) $
55 *
56 * Warning, this component is far from ready.
57 * It's more a proof of concept right now.
58 * TODO : Remove the need to include .get for the last part of the method expressions : getBytesMethod="#{graphicImageDynamicBean.upImage.getBytes}"
59 * TODO : Make a similar download component to download files
60 * TODO : Use shorter URLs
61 */
62
63 public class GraphicImageDynamic extends HtmlGraphicImage
64 {
65 public static final String COMPONENT_TYPE = "org.apache.myfaces.GraphicImageDynamic";
66 public static final String COMPONENT_FAMILY = "javax.faces.Graphic";
67 public static final String RENDERER_PARAM = "_renderer";
68 public static final String VALUE_PARAM = "_value";
69 public static final String WIDTH_PARAM = "_width";
70 public static final String HEIGHT_PARAM = "_height";
71 private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.GraphicImageDynamicRenderer";
72
73
74 public GraphicImageDynamic()
75 {
76 setRendererType(DEFAULT_RENDERER_TYPE);
77 }
78
79 private Class _imageRendererClass;
80
81 public Object saveState(FacesContext context)
82 {
83 Object[] values = new Object[2];
84 values[0] = super.saveState(context);
85 values[1] = _imageRendererClass;
86 return values;
87 }
88
89 public void restoreState(FacesContext context, Object state)
90 {
91 Object values[] = (Object[]) state;
92 super.restoreState(context, values[0]);
93 _imageRendererClass = (Class) values[1];
94 }
95
96 /**
97 * The class which implements
98 * org.apache.myfaces.custom.graphicimagedynamic.ImageRenderer.
99 * The image renderer is responsible for loading the image.
100 * The class must have a default constructor.
101 * Any request scoped attribute or managed bean is not available
102 * when this image renderer is instantiated and used.
103 * The image renderer must render the binary data for the image by
104 * using the parameters passed by nested f:param elements and/or
105 * using session or application scoped beans.
106 *
107 * @JSFProperty
108 */
109 public void setImageRendererClass(Class imageRendererClass)
110 {
111 if (imageRendererClass != null && !ImageRenderer.class.isAssignableFrom(imageRendererClass))
112 {
113 throw new IllegalArgumentException(
114 "imageRendererClass must be null or a class which implements "
115 + ImageRenderer.class.getName());
116 }
117 _imageRendererClass = imageRendererClass;
118 }
119
120 public Class getImageRendererClass()
121 {
122 if (_imageRendererClass != null)
123 {
124 return _imageRendererClass;
125 }
126 ValueBinding vb = getValueBinding("imageRendererClass");
127 if (vb != null)
128 {
129 Object value = vb.getValue(getFacesContext());
130 if (value == null)
131 {
132 return null;
133 }
134 Class clazz;
135 if (value instanceof Class)
136 {
137 clazz = (Class) value;
138 }
139 else
140 {
141 try
142 {
143 clazz = ClassUtils.classForName(value.toString());
144 }
145 catch (ClassNotFoundException e)
146 {
147 throw new EvaluationException("Could not load imageRendererClass for "
148 + vb.getExpressionString(), e);
149 }
150 }
151 if (!ImageRenderer.class.isAssignableFrom(clazz))
152 {
153 throw new EvaluationException("Expected value for " + vb.getExpressionString()
154 + " must be one of null, a fully qualified class name or "
155 + "an instance of a class which implements "
156 + ImageRenderer.class.getName());
157 }
158 return clazz;
159 }
160 return null;
161 }
162
163 /**
164 * A value binding which will be called to get the instance of an
165 * org.apache.myfaces.custom.graphicimagedynamic.ImageRenderer.
166 *
167 * @JSFProperty
168 */
169 public Object getValue()
170 {
171 return super.getValue();
172 }
173 }