KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > velocity > tools > struts > SecureLinkTool


1 /*
2  * Copyright 2003-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.velocity.tools.struts;
18
19 import java.util.Iterator JavaDoc;
20 import javax.servlet.ServletContext JavaDoc;
21 import javax.servlet.http.HttpServletRequest JavaDoc;
22
23 import org.apache.velocity.tools.view.tools.LinkTool;
24 import org.apache.velocity.tools.struts.StrutsUtils;
25
26 import org.apache.struts.config.ModuleConfig;
27 import org.apache.struts.config.SecureActionConfig;
28 import org.apache.struts.action.SecurePlugInInterface;
29 import org.apache.struts.Globals;
30
31 /**
32  * Tool to be able to use Struts SSL Extensions with Velocity.
33  * <p>It has the same interface as StrutsLinkTool and can function as a
34  * substitute if Struts 1.1 and SSL Ext are installed. </p>
35  * <p>Usage:
36  * <pre>
37  * Template example:
38  * &lt;!-- Use just like a regular StrutsLinkTool --&gt;
39  * $link.setAction("nameOfAction")
40  * $link.setForward("nameOfForward")
41  *
42  * If the action or forward is marked as secure, or not,
43  * in your struts-config then the link will be rendered
44  * with https or http accordingly.
45  *
46  * Toolbox configuration:
47  * &lt;tool&gt;
48  * &lt;key&gt;link&lt;/key&gt;
49  * &lt;scope&gt;request&lt;/scope&gt;
50  * &lt;class&gt;org.apache.velocity.tools.struts.SecureLinkTool&lt;/class&gt;
51  * &lt;/tool&gt;
52  * </pre>
53  * </p>
54  * @since VelocityTools 1.1
55  * @author <a HREF="mailto:marinoj@centrum.is">Marino A. Jonsson</a>
56  * @version $Revision: 1.9.2.1 $ $Date: 2004/03/12 20:16:27 $
57  */

58 public class SecureLinkTool extends LinkTool
59 {
60
61     private static final String JavaDoc HTTP = "http";
62     private static final String JavaDoc HTTPS = "https";
63     private static final String JavaDoc STD_HTTP_PORT = "80";
64     private static final String JavaDoc STD_HTTPS_PORT = "443";
65
66
67     /**
68      * <p>Returns a copy of the link with the given action name
69      * converted into a server-relative URI reference. This method
70      * does not check if the specified action really is defined.
71      * This method will overwrite any previous URI reference settings
72      * but will copy the query string.</p>
73      *
74      * @param action an action path as defined in struts-config.xml
75      *
76      * @return a new instance of StrutsLinkTool
77      */

78     public SecureLinkTool setAction(String JavaDoc action)
79     {
80         String JavaDoc link = StrutsUtils.getActionMappingURL(application, request, action);
81         return (SecureLinkTool)copyWith(computeURL(request, application, link));
82     }
83
84     /**
85      * <p>Returns a copy of the link with the given global forward name
86      * converted into a server-relative URI reference. If the parameter
87      * does not map to an existing global forward name, <code>null</code>
88      * is returned. This method will overwrite any previous URI reference
89      * settings but will copy the query string.</p>
90      *
91      * @param forward a global forward name as defined in struts-config.xml
92      *
93      * @return a new instance of StrutsLinkTool
94      */

95     public SecureLinkTool setForward(String JavaDoc forward)
96     {
97         String JavaDoc url = StrutsUtils.getForwardURL(request, application, forward);
98         if (url == null)
99         {
100             return null;
101         }
102         return (SecureLinkTool)copyWith(url);
103     }
104
105     /**
106      * Compute a hyperlink URL based on the specified action link.
107      * The returned URL will have already been passed to
108      * <code>response.encodeURL()</code> for adding a session identifier.
109      *
110      * @param request the current request.
111      * @param app the current ServletContext.
112      * @param link the action that is to be converted to a hyperlink URL
113      * @return the computed hyperlink URL
114      */

115     public String JavaDoc computeURL(HttpServletRequest JavaDoc request,
116                              ServletContext JavaDoc app, String JavaDoc link)
117     {
118         StringBuffer JavaDoc url = new StringBuffer JavaDoc(link);
119
120         String JavaDoc contextPath = request.getContextPath();
121
122         SecurePlugInInterface securePlugin = (SecurePlugInInterface)app.getAttribute(SecurePlugInInterface.SECURE_PLUGIN);
123
124         if (securePlugin.getSslExtEnable() &&
125             url.toString().startsWith(contextPath))
126         {
127             // Initialize the scheme and ports we are using
128
String JavaDoc usingScheme = request.getScheme();
129             String JavaDoc usingPort = String.valueOf(request.getServerPort());
130
131             // Get the servlet context relative link URL
132
String JavaDoc linkString = url.toString().substring(contextPath.length());
133
134             // See if link references an action somewhere in our app
135
SecureActionConfig secureConfig = getActionConfig(request, app, linkString);
136
137             // If link is an action, find the desired port and scheme
138
if (secureConfig != null &&
139                 !SecureActionConfig.ANY.equalsIgnoreCase(secureConfig.getSecure()))
140             {
141                 String JavaDoc desiredScheme = Boolean.valueOf(secureConfig.getSecure()).booleanValue() ?
142                     HTTPS : HTTP;
143                 String JavaDoc desiredPort = Boolean.valueOf(secureConfig.getSecure()).booleanValue() ?
144                     securePlugin.getHttpsPort() : securePlugin.getHttpPort();
145
146                 // If scheme and port we are using do not match the ones we want
147
if (!desiredScheme.equals(usingScheme) ||
148                     !desiredPort.equals(usingPort))
149                 {
150                     url.insert(0, startNewUrlString(request, desiredScheme, desiredPort));
151
152                     // This is a hack to help us overcome the problem that some
153
// older browsers do not share sessions between http & https
154
// If this feature is diabled, session ID could still be added
155
// the previous call to the RequestUtils.computeURL() method,
156
// but only if needed due to cookies disabled, etc.
157
if (securePlugin.getSslExtAddSession() && url.toString().indexOf(";jsessionid=") < 0)
158                     {
159                         // Add the session identifier
160
url = new StringBuffer JavaDoc(toEncoded(url.toString(),
161                                                request.getSession().getId()));
162                     }
163                 }
164             }
165         }
166         return url.toString();
167     }
168
169     /**
170      * Finds the configuration definition for the specified action link
171      *
172      * @param request the current request.
173      * @param app the current ServletContext.
174      * @param linkString The action we are searching for, specified as a
175      * link. (i.e. may include "..")
176      * @return The SecureActionConfig object entry for this action,
177      * or null if not found
178      */

179     private static SecureActionConfig getActionConfig(HttpServletRequest JavaDoc
180             request,
181             ServletContext JavaDoc app,
182             String JavaDoc linkString)
183     {
184         ModuleConfig moduleConfig = StrutsUtils.selectModule(linkString, app);
185
186         // Strip off the subapp path, if any
187
linkString = linkString.substring(moduleConfig.getPrefix().length());
188
189         // Use our servlet mapping, if one is specified
190
//String servletMapping = (String)app.getAttribute(Globals.SERVLET_KEY);
191

192         SecurePlugInInterface spi = (SecurePlugInInterface)app.getAttribute(
193                 SecurePlugInInterface.SECURE_PLUGIN);
194         Iterator JavaDoc mappingItr = spi.getServletMappings().iterator();
195         while (mappingItr.hasNext())
196         {
197             String JavaDoc servletMapping = (String JavaDoc)mappingItr.next();
198
199             int starIndex = servletMapping != null ? servletMapping.indexOf('*')
200                             : -1;
201             if (starIndex == -1)
202             {
203                 continue;
204             } // No servlet mapping or no usable pattern defined, short circuit
205

206             String JavaDoc prefix = servletMapping.substring(0, starIndex);
207             String JavaDoc suffix = servletMapping.substring(starIndex + 1);
208
209             // Strip off the jsessionid, if any
210
int jsession = linkString.indexOf(";jsessionid=");
211             if (jsession >= 0)
212             {
213                 linkString = linkString.substring(0, jsession);
214             }
215
216             // Strip off the query string, if any
217
// (differs from the SSL Ext. version - query string before anchor)
218
int question = linkString.indexOf("?");
219             if (question >= 0)
220             {
221                 linkString = linkString.substring(0, question);
222             }
223
224             // Strip off the anchor, if any
225
int anchor = linkString.indexOf("#");
226             if (anchor >= 0)
227             {
228                 linkString = linkString.substring(0, anchor);
229             }
230
231
232             // Unable to establish this link as an action, short circuit
233
if (!(linkString.startsWith(prefix) && linkString.endsWith(suffix)))
234             {
235                 continue;
236             }
237
238             // Chop off prefix and suffix
239
linkString = linkString.substring(prefix.length());
240             linkString = linkString.substring(0,
241                                               linkString.length()
242                                               - suffix.length());
243             if (!linkString.startsWith("/"))
244             {
245                 linkString = "/" + linkString;
246             }
247
248             SecureActionConfig secureConfig = (SecureActionConfig)moduleConfig.
249                                               findActionConfig(linkString);
250
251             return secureConfig;
252         }
253         return null;
254
255     }
256
257     /**
258      * Builds the protocol, server name, and port portion of the new URL
259      * @param request The current request
260      * @param desiredScheme The scheme (http or https) to be used in the new URL
261      * @param desiredPort The port number to be used in th enew URL
262      * @return The new URL as a StringBuffer
263      */

264     private static StringBuffer JavaDoc startNewUrlString(HttpServletRequest JavaDoc request,
265                                                   String JavaDoc desiredScheme,
266                                                   String JavaDoc desiredPort)
267     {
268         StringBuffer JavaDoc url = new StringBuffer JavaDoc();
269         String JavaDoc serverName = request.getServerName();
270         url.append(desiredScheme).append("://").append(serverName);
271
272         if ((HTTP.equals(desiredScheme) && !STD_HTTP_PORT.equals(desiredPort)) ||
273             (HTTPS.equals(desiredScheme) && !STD_HTTPS_PORT.equals(desiredPort)))
274         {
275             url.append(":").append(desiredPort);
276         }
277         return url;
278     }
279
280     /**
281      * Return the specified URL with the specified session identifier
282      * suitably encoded.
283      *
284      * @param url URL to be encoded with the session id
285      * @param sessionId Session id to be included in the encoded URL
286      * @return the specified URL with the specified session identifier suitably encoded
287      */

288     public String JavaDoc toEncoded(String JavaDoc url, String JavaDoc sessionId)
289     {
290         if (url == null || sessionId == null)
291         {
292             return (url);
293         }
294
295         String JavaDoc path = url;
296         String JavaDoc query = "";
297         String JavaDoc anchor = "";
298
299         // (differs from the SSL Ext. version - anchor before query string)
300
int pound = url.indexOf('#');
301         if (pound >= 0)
302         {
303             path = url.substring(0, pound);
304             anchor = url.substring(pound);
305         }
306         int question = path.indexOf('?');
307         if (question >= 0)
308         {
309             query = path.substring(question);
310             path = path.substring(0, question);
311         }
312         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(path);
313         // jsessionid can't be first.
314
if (sb.length() > 0)
315         {
316             sb.append(";jsessionid=");
317             sb.append(sessionId);
318         }
319         sb.append(query);
320         sb.append(anchor);
321         return sb.toString();
322     }
323
324 }
325
Popular Tags