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 package org.apache.myfaces.custom.outputlinkdynamic;
20
21 import javax.faces.component.html.HtmlOutputLink;
22 import javax.faces.context.FacesContext;
23 import javax.faces.el.EvaluationException;
24 import javax.faces.el.ValueBinding;
25
26 import org.apache.myfaces.component.ForceIdAware;
27 import org.apache.myfaces.component.UserRoleAware;
28 import org.apache.myfaces.custom.dynamicResources.ResourceRenderer;
29 import org.apache.myfaces.shared_tomahawk.util.ClassUtils;
30
31 /**
32 * Extends standard outputLink but links to a dynamically rendered resource (image, file, ...).
33 *
34 * @JSFComponent
35 * name = "s:outputLinkDynamic"
36 * class = "org.apache.myfaces.custom.outputlinkdynamic.OutputLinkDynamic"
37 * tagClass = "org.apache.myfaces.custom.outputlinkdynamic.OutputLinkDynamicTag"
38 *
39 * @author Sylvain Vieujot (latest modification by $Author: lu4242 $)
40 *
41 * @version $Revision: 691856 $ $Date: 2008-09-03 21:40:30 -0500 (Wed, 03 Sep 2008) $
42 *
43 * Warning, this component is far from ready.
44 * It's more a proof of concept right now.
45 * TODO : Remove the need to include .get for the last part of the method expressions : getBytesMethod="#{graphicImageDynamicBean.upImage.getBytes}"
46 * TODO : Make a similar download component to download files
47 * TODO : Use shorter URLs
48 */
49
50 public abstract class AbstractOutputLinkDynamic extends HtmlOutputLink
51 implements UserRoleAware, ForceIdAware
52 {
53
54 public static final String COMPONENT_TYPE = "org.apache.myfaces.OutputLinkDynamic";
55 private static final String DEFAULT_RENDERER_TYPE = "org.apache.myfaces.OutputLinkDynamicRenderer";
56
57 public AbstractOutputLinkDynamic()
58 {
59 setRendererType(DEFAULT_RENDERER_TYPE);
60 }
61
62 private Class _resourceRendererClass;
63
64 public Object saveState(FacesContext context)
65 {
66 Object[] values = new Object[2];
67 values[0] = super.saveState(context);
68 values[1] = _resourceRendererClass;
69 return values;
70 }
71
72 public void restoreState(FacesContext context, Object state)
73 {
74 Object values[] = (Object[]) state;
75 super.restoreState(context, values[0]);
76 _resourceRendererClass = (Class) values[1];
77 }
78
79 public void setImageRendererClass(Class resourceRendererClass)
80 {
81 if (resourceRendererClass != null && !ResourceRenderer.class.isAssignableFrom(resourceRendererClass))
82 {
83 throw new IllegalArgumentException(
84 "resourceRendererClass must be null or a class which implements "
85 + ResourceRenderer.class.getName());
86 }
87 _resourceRendererClass = resourceRendererClass;
88 }
89
90 /**
91 * The class which implements
92 * org.apache.myfaces.custom.dynamicResources.ResourceRenderer. The resource
93 * renderer is responsible for resource the image. The class must have a
94 * default constructor. Any request scoped attribute or managed bean is
95 * not available when this resource renderer is instantiated and used.
96 * The resource renderer must render the binary data for the resource
97 * by using the parameters passed by nested f:param elements and/or
98 * using session or application scoped beans.
99 *
100 * @JSFProperty
101 * @return
102 */
103 public Class getResourceRendererClass()
104 {
105 if (_resourceRendererClass != null)
106 {
107 return _resourceRendererClass;
108 }
109 ValueBinding vb = getValueBinding("resourceRendererClass");
110 if (vb != null)
111 {
112 Object value = vb.getValue(getFacesContext());
113 if (value == null)
114 {
115 return null;
116 }
117 Class clazz;
118 if (value instanceof Class)
119 {
120 clazz = (Class) value;
121 }
122 else
123 {
124 try
125 {
126 clazz = ClassUtils.classForName(value.toString());
127 }
128 catch (ClassNotFoundException e)
129 {
130 throw new EvaluationException("Could not load resourceRendererClass for "
131 + vb.getExpressionString(), e);
132 }
133 }
134 if (!ResourceRenderer.class.isAssignableFrom(clazz))
135 {
136 throw new EvaluationException("Expected value for " + vb.getExpressionString()
137 + " must be one of null, a fully qualified class name or "
138 + "an instance of a class which implements "
139 + ResourceRenderer.class.getName());
140 }
141 return clazz;
142 }
143 return null;
144 }
145
146 /**
147 * If user is in given role, this component will be rendered
148 * normally. If not, no hyperlink is rendered but all nested
149 * tags (=body) are rendered.
150 *
151 * @JSFProperty
152 * @return
153 */
154 public abstract String getEnabledOnUserRole();
155
156 public abstract void setEnabledOnUserRole(String userRole);
157
158 /**
159 * If user is in given role, this component will be rendered
160 * normally. If not, nothing is rendered and the body of this
161 * tag will be skipped.
162 *
163 * @JSFProperty
164 * @return
165 */
166 public abstract String getVisibleOnUserRole();
167
168 public abstract void setVisibleOnUserRole(String userRole);
169
170 /**
171 * If true, this component will force the use of the specified id when rendering.
172 *
173 * @JSFProperty
174 * literalOnly = "true"
175 * defaultValue = "false"
176 *
177 * @return
178 */
179 public abstract boolean isForceId();
180
181 public abstract void setForceId(boolean forceId);
182
183 /**
184 * If false, this component will not append a '[n]' suffix
185 * (where 'n' is the row index) to components that are
186 * contained within a "list." This value will be true by
187 * default and the value will be ignored if the value of
188 * forceId is false (or not specified.)
189 *
190 * @JSFProperty
191 * literalOnly = "true"
192 * defaultValue = "true"
193 *
194 * @return
195 */
196 public abstract boolean isForceIdIndex();
197
198 public abstract void setForceIdIndex(boolean forceIdIndex);
199
200 }