KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > roller > ui > rendering > WeblogRequestMapper


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. The ASF licenses this file to You
4  * under the Apache License, Version 2.0 (the "License"); you may not
5  * 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. For additional information regarding
15  * copyright in this work, please see the NOTICE file in the top level
16  * directory of this distribution.
17  */

18
19 package org.apache.roller.ui.rendering;
20
21 import java.io.IOException JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Set JavaDoc;
24 import javax.servlet.RequestDispatcher JavaDoc;
25 import javax.servlet.ServletException JavaDoc;
26 import javax.servlet.http.HttpServletRequest JavaDoc;
27 import javax.servlet.http.HttpServletResponse JavaDoc;
28 import org.apache.commons.lang.StringUtils;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.apache.roller.config.RollerConfig;
32 import org.apache.roller.model.RollerFactory;
33 import org.apache.roller.model.UserManager;
34 import org.apache.roller.pojos.WebsiteData;
35
36
37 /**
38  * Roller's weblog request mapper.
39  *
40  * This request mapper is used to map all weblog specific urls of the form
41  * /<weblog handle>/* to the appropriate servlet for handling the actual
42  * request.
43  *
44  * TODO: we should try and make this class easier to extend and build upon
45  */

46 public class WeblogRequestMapper implements RequestMapper {
47     
48     private static Log log = LogFactory.getLog(WeblogRequestMapper.class);
49     
50     private static final String JavaDoc PAGE_SERVLET = "/roller-ui/rendering/page";
51     private static final String JavaDoc FEED_SERVLET = "/roller-ui/rendering/feed";
52     private static final String JavaDoc RESOURCE_SERVLET = "/roller-ui/rendering/resources";
53     private static final String JavaDoc SEARCH_SERVLET = "/roller-ui/rendering/search";
54     private static final String JavaDoc RSD_SERVLET = "/roller-ui/rendering/rsd";
55     
56     private static final String JavaDoc COMMENT_SERVLET = "/roller-ui/rendering/comment";
57     private static final String JavaDoc TRACKBACK_SERVLET = "/roller-ui/rendering/trackback";
58     
59     
60     // url patterns that are not allowed to be considered weblog handles
61
Set JavaDoc restricted = null;
62     
63     
64     public WeblogRequestMapper() {
65         
66         this.restricted = new HashSet JavaDoc();
67         
68         // build roller restricted list
69
String JavaDoc restrictList =
70                 RollerConfig.getProperty("rendering.weblogMapper.rollerProtectedUrls");
71         if(restrictList != null && restrictList.trim().length() > 0) {
72             String JavaDoc[] restrict = restrictList.split(",");
73             for(int i=0; i < restrict.length; i++) {
74                 this.restricted.add(restrict[i]);
75             }
76         }
77         
78         // add user restricted list
79
restrictList =
80                 RollerConfig.getProperty("rendering.weblogMapper.userProtectedUrls");
81         if(restrictList != null && restrictList.trim().length() > 0) {
82             String JavaDoc[] restrict = restrictList.split(",");
83             for(int i=0; i < restrict.length; i++) {
84                 this.restricted.add(restrict[i]);
85             }
86         }
87     }
88     
89     
90     public boolean handleRequest(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response)
91             throws ServletException JavaDoc, IOException JavaDoc {
92         
93         // kinda silly, but we need to keep track of whether or not the url had
94
// a trailing slash so that we can act accordingly
95
boolean trailingSlash = false;
96         
97         String JavaDoc weblogHandle = null;
98         String JavaDoc weblogLocale = null;
99         String JavaDoc weblogRequestContext = null;
100         String JavaDoc weblogRequestData = null;
101         
102         log.debug("evaluating ["+request.getServletPath()+"]");
103         
104         // figure out potential weblog handle
105
String JavaDoc servlet = request.getServletPath();
106         String JavaDoc pathInfo = null;
107         
108         // WAS6.1 returns "" for servletPath use pathInfo instead
109
if (StringUtils.isEmpty(request.getServletPath())) {
110             servlet = request.getPathInfo();
111         }
112         
113         if(servlet != null && servlet.trim().length() > 1) {
114             
115             // strip off the leading slash
116
servlet = servlet.substring(1);
117             
118             // strip off trailing slash if needed
119
if(servlet.endsWith("/")) {
120                 servlet = servlet.substring(0, servlet.length() - 1);
121                 trailingSlash = true;
122             }
123             
124             if(servlet.indexOf("/") != -1) {
125                 weblogHandle = servlet.substring(0, servlet.indexOf("/"));
126                 pathInfo = servlet.substring(servlet.indexOf("/")+1);
127             } else {
128                 weblogHandle = servlet;
129             }
130         }
131         
132         log.debug("potential weblog handle = "+weblogHandle);
133         
134         // check if it's a valid weblog handle
135
if(restricted.contains(weblogHandle) || !this.isWeblog(weblogHandle)) {
136             log.debug("SKIPPED "+weblogHandle);
137             return false;
138         }
139         
140         log.debug("WEBLOG_URL "+request.getServletPath());
141         
142         // parse the rest of the url and build forward url
143
if(pathInfo != null) {
144             
145             // parse the next portion of the url
146
// we expect [locale/]<context>/<extra>/<info>
147
String JavaDoc[] urlPath = pathInfo.split("/", 3);
148             
149             // if we have a locale, deal with it
150
if(this.isLocale(urlPath[0])) {
151                 weblogLocale = urlPath[0];
152                 
153                 // no extra path info specified
154
if(urlPath.length == 2) {
155                     weblogRequestContext = urlPath[1];
156                     weblogRequestData = null;
157                     
158                 // request contains extra path info
159
} else if(urlPath.length == 3) {
160                     weblogRequestContext = urlPath[1];
161                     weblogRequestData = urlPath[2];
162                 }
163             
164             // otherwise locale is empty
165
} else {
166                 weblogLocale = null;
167                 weblogRequestContext = urlPath[0];
168                 
169                 // last part of request is extra path info
170
if(urlPath.length == 2) {
171                     weblogRequestData = urlPath[1];
172                     
173                 // if we didn't have a locale then we have split too much
174
// so we reassemble the last 2 path elements together
175
} else if(urlPath.length == 3) {
176                     weblogRequestData = urlPath[1] + "/" + urlPath[2];
177                 }
178             }
179             
180         }
181         
182         // special handling for trailing slash issue
183
// we need this because by http standards the urls /foo and /foo/ are
184
// supposed to be considered different, so we must enforce that
185
if(weblogRequestContext == null && !trailingSlash) {
186             // this means someone referred to a weblog index page with the
187
// shortest form of url /<weblog> or /<weblog>/<locale> and we need
188
// to do a redirect to /<weblog>/ or /<weblog>/<locale>/
189
String JavaDoc redirectUrl = request.getRequestURI() + "/";
190             if(request.getQueryString() != null) {
191                 redirectUrl += "?"+request.getQueryString();
192             }
193             
194             response.sendRedirect(redirectUrl);
195             return true;
196             
197         } else if(weblogRequestContext != null && trailingSlash) {
198             // this means that someone has accessed a weblog url and included
199
// a trailing slash, like /<weblog>/entry/<anchor>/ which is not
200
// supported, so we need to offer up a 404 Not Found
201
response.sendError(HttpServletResponse.SC_NOT_FOUND);
202             return true;
203         }
204         
205         // calculate forward url
206
String JavaDoc forwardUrl = calculateForwardUrl(request, weblogHandle, weblogLocale,
207                 weblogRequestContext, weblogRequestData);
208         
209         // if we don't have a forward url then the request was invalid somehow
210
if(forwardUrl == null) {
211             return false;
212         }
213         
214         // dispatch to forward url
215
log.debug("forwarding to "+forwardUrl);
216         RequestDispatcher JavaDoc dispatch = request.getRequestDispatcher(forwardUrl);
217         dispatch.forward(request, response);
218         
219         // we dealt with this request ourselves, so return "true"
220
return true;
221     }
222
223     
224     /**
225      * Convenience method for caculating the servlet forward url given a set
226      * of information to make the decision with.
227      *
228      * handle is always assumed valid, all other params may be null.
229      */

230     private String JavaDoc calculateForwardUrl(HttpServletRequest JavaDoc request,
231                                        String JavaDoc handle, String JavaDoc locale,
232                                        String JavaDoc context, String JavaDoc data) {
233         
234         log.debug(handle+","+locale+","+context+","+data);
235         
236         StringBuffer JavaDoc forwardUrl = new StringBuffer JavaDoc();
237         
238         // POST urls, like comment and trackback servlets
239
if("POST".equals(request.getMethod())) {
240             // posting to permalink, this means comment or trackback
241
if(context.equals("entry")) {
242                 // trackback requests are required to have an "excerpt" param
243
if(request.getParameter("excerpt") != null) {
244                     
245                     forwardUrl.append(TRACKBACK_SERVLET);
246                     forwardUrl.append("/");
247                     forwardUrl.append(handle);
248                     if(locale != null) {
249                         forwardUrl.append("/");
250                         forwardUrl.append(locale);
251                     }
252                     forwardUrl.append("/");
253                     forwardUrl.append(context);
254                     if(data != null) {
255                         forwardUrl.append("/");
256                         forwardUrl.append(data);
257                     }
258                     
259                 // comment requests are required to have a "content" param
260
} else if(request.getParameter("content") != null) {
261                     
262                     forwardUrl.append(COMMENT_SERVLET);
263                     forwardUrl.append("/");
264                     forwardUrl.append(handle);
265                     if(locale != null) {
266                         forwardUrl.append("/");
267                         forwardUrl.append(locale);
268                     }
269                     forwardUrl.append("/");
270                     forwardUrl.append(context);
271                     if(data != null) {
272                         forwardUrl.append("/");
273                         forwardUrl.append(data);
274                     }
275                 }
276                 
277             } else {
278                 // someone posting data where they aren't supposed to
279
return null;
280             }
281             
282         } else {
283             // no context means weblog homepage
284
if(context == null) {
285                 
286                 forwardUrl.append(PAGE_SERVLET);
287                 forwardUrl.append("/");
288                 forwardUrl.append(handle);
289                 if(locale != null) {
290                     forwardUrl.append("/");
291                     forwardUrl.append(locale);
292                 }
293                 
294                 // requests handled by PageServlet
295
} else if(context.equals("page") || context.equals("entry") ||
296                     context.equals("date") || context.equals("category")) {
297                 
298                 forwardUrl.append(PAGE_SERVLET);
299                 forwardUrl.append("/");
300                 forwardUrl.append(handle);
301                 if(locale != null) {
302                     forwardUrl.append("/");
303                     forwardUrl.append(locale);
304                 }
305                 forwardUrl.append("/");
306                 forwardUrl.append(context);
307                 if(data != null) {
308                     forwardUrl.append("/");
309                     forwardUrl.append(data);
310                 }
311                 
312                 // requests handled by FeedServlet
313
} else if(context.equals("feed")) {
314                 
315                 forwardUrl.append(FEED_SERVLET);
316                 forwardUrl.append("/");
317                 forwardUrl.append(handle);
318                 if(locale != null) {
319                     forwardUrl.append("/");
320                     forwardUrl.append(locale);
321                 }
322                 if(data != null) {
323                     forwardUrl.append("/");
324                     forwardUrl.append(data);
325                 }
326                 
327                 // requests handled by ResourceServlet
328
} else if(context.equals("resource")) {
329                 
330                 forwardUrl.append(RESOURCE_SERVLET);
331                 forwardUrl.append("/");
332                 forwardUrl.append(handle);
333                 if(data != null) {
334                     forwardUrl.append("/");
335                     forwardUrl.append(data);
336                 }
337                 
338                 // requests handled by SearchServlet
339
} else if(context.equals("search")) {
340                 
341                 forwardUrl.append(SEARCH_SERVLET);
342                 forwardUrl.append("/");
343                 forwardUrl.append(handle);
344                 
345                 // requests handled by RSDServlet
346
} else if(context.equals("rsd")) {
347                 
348                 forwardUrl.append(RSD_SERVLET);
349                 forwardUrl.append("/");
350                 forwardUrl.append(handle);
351                 
352                 // unsupported url
353
} else {
354                 return null;
355             }
356         }
357         
358         log.debug("FORWARD_URL "+forwardUrl.toString());
359         
360         return forwardUrl.toString();
361     }
362     
363     
364     /**
365      * convenience method which determines if the given string is a valid
366      * weblog handle.
367      *
368      * TODO 3.0: some kind of caching
369      */

370     private boolean isWeblog(String JavaDoc potentialHandle) {
371         
372         log.debug("checking weblog handle "+potentialHandle);
373         
374         boolean isWeblog = false;
375         
376         try {
377             UserManager mgr = RollerFactory.getRoller().getUserManager();
378             WebsiteData weblog = mgr.getWebsiteByHandle(potentialHandle);
379             
380             if(weblog != null) {
381                 isWeblog = true;
382             }
383         } catch(Exception JavaDoc ex) {
384             // doesn't really matter to us why it's not a valid website
385
}
386         
387         return isWeblog;
388     }
389     
390     
391     /**
392      * Convenience method which determines if the given string is a valid
393      * locale string.
394      */

395     private boolean isLocale(String JavaDoc potentialLocale) {
396         
397         boolean isLocale = false;
398         
399         // we only support 2 or 5 character locale strings, so check that first
400
if(potentialLocale != null &&
401                 (potentialLocale.length() == 2 || potentialLocale.length() == 5)) {
402             
403             // now make sure that the format is proper ... e.g. "en_US"
404
// we are not going to be picky about capitalization
405
String JavaDoc[] langCountry = potentialLocale.split("_");
406             if(langCountry.length == 1 &&
407                     langCountry[0] != null && langCountry[0].length() == 2) {
408                 isLocale = true;
409                 
410             } else if(langCountry.length == 2 &&
411                     langCountry[0] != null && langCountry[0].length() == 2 &&
412                     langCountry[1] != null && langCountry[1].length() == 2) {
413                 
414                 isLocale = true;
415             }
416         }
417         
418         return isLocale;
419     }
420     
421 }
422
Popular Tags