1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.apache.struts2.components;
23
24 import com.opensymphony.xwork2.inject.Inject;
25 import com.opensymphony.xwork2.util.ValueStack;
26 import com.opensymphony.xwork2.util.logging.Logger;
27 import com.opensymphony.xwork2.util.logging.LoggerFactory;
28 import org.apache.struts2.StrutsConstants;
29 import org.apache.struts2.views.annotations.StrutsTag;
30 import org.apache.struts2.views.annotations.StrutsTagAttribute;
31 import org.apache.commons.lang.xwork.StringUtils;
32
33 import javax.servlet.http.HttpServletRequest;
34 import javax.servlet.http.HttpServletResponse;
35 import java.io.StringWriter;
36 import java.io.Writer;
37 import java.util.Map;
38 import java.util.LinkedHashMap;
39
40 /***
41 * <!-- START SNIPPET: javadoc -->
42 * <p/>
43 * A tag that creates a HTML <a >.This tag supports the same attributes as the "url" tag,
44 * including nested parameters using the "param" tag.<p/>
45 * <!-- END SNIPPET: javadoc -->
46 * <p/>
47 * <p/> <b>Examples</b>
48 * <p/>
49 * <pre>
50 * <!-- START SNIPPET: example1 -->
51 * <s:a id="link1" theme="ajax" href="/DoIt.action">
52 * <img border="none" src="<%=request.getContextPath()%>/images/delete.gif"/>
53 * <s:param name="id" value="1"/>
54 * </s:a>
55 * <!-- END SNIPPET: example1 -->
56 * </pre>
57 */
58 @StrutsTag(
59 name = "a",
60 tldTagClass = "org.apache.struts2.views.jsp.ui.AnchorTag",
61 description = "Render a HTML href element that when clicked can optionally call a URL via remote XMLHttpRequest and updates its targets",
62 allowDynamicAttributes = true)
63 public class Anchor extends ClosingUIBean {
64 private static final Logger LOG = LoggerFactory.getLogger(Anchor.class);
65
66 public static final String OPEN_TEMPLATE = "a";
67 public static final String TEMPLATE = "a-close";
68 public static final String COMPONENT_NAME = Anchor.class.getName();
69
70 protected String href;
71 protected UrlProvider urlProvider;
72 protected UrlRenderer urlRenderer;
73 protected boolean processingTagBody = false;
74
75
76 protected Map urlParameters = new LinkedHashMap();
77
78 public Anchor(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
79 super(stack, request, response);
80 urlProvider = new ComponentUrlProvider(this, this.urlParameters);
81 urlProvider.setHttpServletRequest(request);
82 urlProvider.setHttpServletResponse(response);
83 }
84
85 public String getDefaultOpenTemplate() {
86 return OPEN_TEMPLATE;
87 }
88
89 protected String getDefaultTemplate() {
90 return TEMPLATE;
91 }
92
93 public boolean usesBody() {
94 return true;
95 }
96
97 @Override
98 protected void evaluateExtraParams() {
99 super.evaluateExtraParams();
100
101 if (href != null)
102 addParameter("href", ensureAttributeSafelyNotEscaped(findString(href)));
103 else {
104
105 StringWriter sw = new StringWriter();
106 urlRenderer.beforeRenderUrl(urlProvider);
107 urlRenderer.renderUrl(sw, urlProvider);
108 String builtHref = sw.toString();
109 if (StringUtils.isNotEmpty(builtHref))
110 addParameter("href", ensureAttributeSafelyNotEscaped(builtHref));
111 }
112 }
113
114 @Inject(StrutsConstants.STRUTS_URL_INCLUDEPARAMS)
115 public void setUrlIncludeParams(String urlIncludeParams) {
116 urlProvider.setUrlIncludeParams(urlIncludeParams);
117 }
118
119 @Inject
120 public void setUrlRenderer(UrlRenderer urlRenderer) {
121 urlProvider.setUrlRenderer(urlRenderer);
122 this.urlRenderer = urlRenderer;
123 }
124
125 @Inject(required=false)
126 public void setExtraParameterProvider(ExtraParameterProvider provider) {
127 urlProvider.setExtraParameterProvider(provider);
128 }
129
130 @Override
131 public boolean start(Writer writer) {
132 boolean result = super.start(writer);
133 this.processingTagBody = true;
134 return result;
135 }
136
137 /***
138 * Overrides to be able to render body in a template rather than always before the template
139 */
140 public boolean end(Writer writer, String body) {
141 this.processingTagBody = false;
142 evaluateParams();
143 try {
144 addParameter("body", body);
145 mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate()));
146 } catch (Exception e) {
147 LOG.error("error when rendering", e);
148 }
149 finally {
150 popComponentStack();
151 }
152
153 return false;
154 }
155
156
157 public void addParameter(String key, Object value) {
158
159
160
161
162
163 if (processingTagBody) {
164 this.urlParameters.put(key, value);
165 } else
166 super.addParameter(key, value);
167 }
168
169 @Override
170 public void addAllParameters(Map params) {
171
172
173
174
175
176 if (processingTagBody) {
177 this.urlParameters.putAll(params);
178 } else
179 super.addAllParameters(params);
180 }
181
182 public UrlProvider getUrlProvider() {
183 return urlProvider;
184 }
185
186 @StrutsTagAttribute(description = "The URL.")
187 public void setHref(String href) {
188 this.href = href;
189 }
190
191 @StrutsTagAttribute(description = "The includeParams attribute may have the value 'none', 'get' or 'all'", defaultValue = "none")
192 public void setIncludeParams(String includeParams) {
193 urlProvider.setIncludeParams(includeParams);
194 }
195
196 @StrutsTagAttribute(description = "Set scheme attribute")
197 public void setScheme(String scheme) {
198 urlProvider.setScheme(scheme);
199 }
200
201 @StrutsTagAttribute(description = "The target value to use, if not using action")
202 public void setValue(String value) {
203 urlProvider.setValue(value);
204 }
205
206 @StrutsTagAttribute(description = "The action to generate the URL for, if not using value")
207 public void setAction(String action) {
208 urlProvider.setAction(action);
209 }
210
211 @StrutsTagAttribute(description = "The namespace to use")
212 public void setNamespace(String namespace) {
213 urlProvider.setNamespace(namespace);
214 }
215
216 @StrutsTagAttribute(description = "The method of action to use")
217 public void setMethod(String method) {
218 urlProvider.setMethod(method);
219 }
220
221 @StrutsTagAttribute(description = "Whether to encode parameters", type = "Boolean", defaultValue = "true")
222 public void setEncode(boolean encode) {
223 urlProvider.setEncode(encode);
224 }
225
226 @StrutsTagAttribute(description = "Whether actual context should be included in URL", type = "Boolean", defaultValue = "true")
227 public void setIncludeContext(boolean includeContext) {
228 urlProvider.setIncludeContext(includeContext);
229 }
230
231 @StrutsTagAttribute(description = "The resulting portlet mode")
232 public void setPortletMode(String portletMode) {
233 urlProvider.setPortletMode(portletMode);
234 }
235
236 @StrutsTagAttribute(description = "The resulting portlet window state")
237 public void setWindowState(String windowState) {
238 urlProvider.setWindowState(windowState);
239 }
240
241 @StrutsTagAttribute(description = "Specifies if this should be a portlet render or action URL. Default is \"render\". To create an action URL, use \"action\".")
242 public void setPortletUrlType(String portletUrlType) {
243 urlProvider.setPortletUrlType(portletUrlType);
244 }
245
246 @StrutsTagAttribute(description = "The anchor for this URL")
247 public void setAnchor(String anchor) {
248 urlProvider.setAnchor(anchor);
249 }
250
251 @StrutsTagAttribute(description = "Specifies whether to escape ampersand (&) to (&amp;) or not", type = "Boolean", defaultValue = "true")
252 public void setEscapeAmp(boolean escapeAmp) {
253 urlProvider.setEscapeAmp(escapeAmp);
254 }
255
256 @StrutsTagAttribute(description = "Specifies whether to force the addition of scheme, host and port or not", type = "Boolean", defaultValue = "false")
257 public void setForceAddSchemeHostAndPort(boolean forceAddSchemeHostAndPort) {
258 urlProvider.setForceAddSchemeHostAndPort(forceAddSchemeHostAndPort);
259 }
260 }