001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. The ASF licenses this file to You
004: * under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License. For additional information regarding
015: * copyright in this work, please see the NOTICE file in the top level
016: * directory of this distribution.
017: */
018:
019: package org.apache.roller.ui.rendering.util;
020:
021: import java.util.ArrayList;
022: import java.util.Arrays;
023: import java.util.HashMap;
024: import java.util.List;
025: import java.util.Map;
026: import javax.servlet.http.HttpServletRequest;
027: import org.apache.commons.lang.StringUtils;
028: import org.apache.commons.logging.Log;
029: import org.apache.commons.logging.LogFactory;
030: import org.apache.roller.RollerException;
031: import org.apache.roller.config.RollerConfig;
032: import org.apache.roller.business.PropertiesManager;
033: import org.apache.roller.business.Roller;
034: import org.apache.roller.business.RollerFactory;
035: import org.apache.roller.business.UserManager;
036: import org.apache.roller.business.WeblogManager;
037: import org.apache.roller.pojos.Template;
038: import org.apache.roller.pojos.WeblogCategoryData;
039: import org.apache.roller.pojos.WeblogEntryData;
040: import org.apache.roller.pojos.WeblogTemplate;
041: import org.apache.roller.util.URLUtilities;
042: import org.apache.roller.util.Utilities;
043:
044: /**
045: * Represents a request for a Roller weblog page.
046: *
047: * any url from ... /roller-ui/rendering/page/*
048: *
049: * We use this class as a helper to parse an incoming url and sort out the
050: * information embedded in the url for later use.
051: */
052: public class WeblogPageRequest extends WeblogRequest {
053:
054: private static Log log = LogFactory.getLog(WeblogPageRequest.class);
055:
056: private static final String PAGE_SERVLET = "/roller-ui/rendering/page";
057:
058: // lightweight attributes
059: private String context = null;
060: private String weblogAnchor = null;
061: private String weblogPageName = null;
062: private String weblogCategoryName = null;
063: private String weblogDate = null;
064: private List tags = null;
065: private int pageNum = 0;
066: private Map customParams = new HashMap();
067:
068: // heavyweight attributes
069: private WeblogEntryData weblogEntry = null;
070: private Template weblogPage = null;
071: private WeblogCategoryData weblogCategory = null;
072:
073: public WeblogPageRequest() {
074: }
075:
076: /**
077: * Construct the WeblogPageRequest by parsing the incoming url
078: */
079: public WeblogPageRequest(HttpServletRequest request)
080: throws InvalidRequestException {
081:
082: // let our parent take care of their business first
083: // parent determines weblog handle and locale if specified
084: super (request);
085:
086: String servlet = request.getServletPath();
087:
088: // we only want the path info left over from after our parents parsing
089: String pathInfo = this .getPathInfo();
090:
091: // parse the request object and figure out what we've got
092: log.debug("parsing path " + pathInfo);
093:
094: // was this request bound for the right servlet?
095: if (!isValidDestination(servlet)) {
096: throw new InvalidRequestException(
097: "invalid destination for request, "
098: + request.getRequestURL());
099: }
100:
101: /*
102: * parse path info
103: *
104: * we expect one of the following forms of url ...
105: *
106: * /entry/<anchor> - permalink
107: * /date/<YYYYMMDD> - date collection view
108: * /category/<category> - category collection view
109: * /tags/spring+framework - tags
110: * /page/<pagelink> - custom page
111: *
112: * path info may be null, which indicates the weblog homepage
113: */
114: if (pathInfo != null && pathInfo.trim().length() > 0) {
115:
116: // all views use 2 path elements, except category
117: String[] pathElements = pathInfo.split("/");
118: if (pathElements.length > 1
119: && "category".equals(pathElements[0])) {
120:
121: // category may have multiple path elements, so re-split with max 2
122: pathElements = pathInfo.split("/", 2);
123: this .context = pathElements[0];
124: this .weblogCategoryName = "/"
125: + URLUtilities.decode(pathElements[1]);
126:
127: // all categories must start with a /
128: if (!this .weblogCategoryName.startsWith("/")) {
129: this .weblogCategoryName = "/"
130: + this .weblogCategoryName;
131: }
132:
133: } else if (pathElements.length == 2) {
134:
135: this .context = pathElements[0];
136: if ("entry".equals(this .context)) {
137: this .weblogAnchor = URLUtilities
138: .decode(pathElements[1]);
139:
140: } else if ("date".equals(this .context)) {
141: if (this .isValidDateString(pathElements[1])) {
142: this .weblogDate = pathElements[1];
143: } else {
144: throw new InvalidRequestException(
145: "invalid date, "
146: + request.getRequestURL());
147: }
148:
149: } else if ("page".equals(this .context)) {
150: this .weblogPageName = pathElements[1];
151:
152: } else if ("tags".equals(this .context)) {
153: String tagsString = pathElements[1].replace('+',
154: ' ');
155: this .tags = Utilities
156: .splitStringAsTags(URLUtilities
157: .decode(tagsString));
158: int maxSize = RollerConfig.getIntProperty(
159: "tags.queries.maxIntersectionSize", 3);
160: if (this .tags.size() > maxSize)
161: throw new InvalidRequestException(
162: "max number of tags allowed is "
163: + maxSize + ", "
164: + request.getRequestURL());
165:
166: } else {
167: throw new InvalidRequestException("context "
168: + this .context + "not supported, "
169: + request.getRequestURL());
170: }
171:
172: } else {
173: throw new InvalidRequestException("bad path info, "
174: + request.getRequestURL());
175: }
176:
177: } else {
178: // default view, weblog homepage
179: }
180:
181: /*
182: * parse request parameters
183: *
184: * the only params we currently allow are:
185: * date - specifies a weblog date string
186: * cat - specifies a weblog category
187: * anchor - specifies a weblog entry (old way)
188: * entry - specifies a weblog entry
189: *
190: * we only allow request params if the path info is null or on user
191: * defined pages (for backwards compatability). this way
192: * we prevent mixing of path based and query param style urls.
193: */
194: if (pathInfo == null || this .weblogPageName != null) {
195:
196: // check for entry/anchor params which indicate permalink
197: if (request.getParameter("entry") != null) {
198: String anchor = request.getParameter("entry");
199: if (StringUtils.isNotEmpty(anchor)) {
200: this .weblogAnchor = anchor;
201: }
202: } else if (request.getParameter("anchor") != null) {
203: String anchor = request.getParameter("anchor");
204: if (StringUtils.isNotEmpty(anchor)) {
205: this .weblogAnchor = anchor;
206: }
207: }
208:
209: // only check for other params if we didn't find an anchor above or tags
210: if (this .weblogAnchor == null && this .tags == null) {
211: if (request.getParameter("date") != null) {
212: String date = request.getParameter("date");
213: if (this .isValidDateString(date)) {
214: this .weblogDate = date;
215: } else {
216: throw new InvalidRequestException(
217: "invalid date, "
218: + request.getRequestURL());
219: }
220: }
221:
222: if (request.getParameter("cat") != null) {
223: this .weblogCategoryName = URLUtilities
224: .decode(request.getParameter("cat"));
225:
226: // all categories must start with a /
227: if (!this .weblogCategoryName.startsWith("/")) {
228: this .weblogCategoryName = "/"
229: + this .weblogCategoryName;
230: }
231: }
232: }
233: }
234:
235: // page request param is supported in all views
236: if (request.getParameter("page") != null) {
237: String pageInt = request.getParameter("page");
238: try {
239: this .pageNum = Integer.parseInt(pageInt);
240: } catch (NumberFormatException e) {
241: // ignored, bad input
242: }
243: }
244:
245: // build customParams Map, we remove built-in params because we only
246: // want this map to represent params defined by the template author
247: customParams = new HashMap(request.getParameterMap());
248: customParams.remove("entry");
249: customParams.remove("anchor");
250: customParams.remove("date");
251: customParams.remove("cat");
252: customParams.remove("page");
253: customParams.remove("tags");
254:
255: if (log.isDebugEnabled()) {
256: log.debug("context = " + this .context);
257: log.debug("weblogAnchor = " + this .weblogAnchor);
258: log.debug("weblogDate = " + this .weblogDate);
259: log.debug("weblogCategory = " + this .weblogCategoryName);
260: log.debug("tags = " + this .tags);
261: log.debug("weblogPage = " + this .weblogPageName);
262: log.debug("pageNum = " + this .pageNum);
263: }
264: }
265:
266: boolean isValidDestination(String servlet) {
267: return (servlet != null && PAGE_SERVLET.equals(servlet));
268: }
269:
270: private boolean isValidDateString(String dateString) {
271: // string must be all numeric and 6 or 8 characters
272: return (dateString != null && StringUtils.isNumeric(dateString) && (dateString
273: .length() == 6 || dateString.length() == 8));
274: }
275:
276: public String getContext() {
277: return context;
278: }
279:
280: public void setContext(String context) {
281: this .context = context;
282: }
283:
284: public String getWeblogAnchor() {
285: return weblogAnchor;
286: }
287:
288: public void setWeblogAnchor(String weblogAnchor) {
289: this .weblogAnchor = weblogAnchor;
290: }
291:
292: public String getWeblogPageName() {
293: return weblogPageName;
294: }
295:
296: public void setWeblogPageName(String weblogPage) {
297: this .weblogPageName = weblogPage;
298: }
299:
300: public String getWeblogCategoryName() {
301: return weblogCategoryName;
302: }
303:
304: public void setWeblogCategoryName(String weblogCategory) {
305: this .weblogCategoryName = weblogCategory;
306: }
307:
308: public String getWeblogDate() {
309: return weblogDate;
310: }
311:
312: public void setWeblogDate(String weblogDate) {
313: this .weblogDate = weblogDate;
314: }
315:
316: public int getPageNum() {
317: return pageNum;
318: }
319:
320: public void setPageNum(int pageNum) {
321: this .pageNum = pageNum;
322: }
323:
324: public Map getCustomParams() {
325: return customParams;
326: }
327:
328: public void setCustomParams(Map customParams) {
329: this .customParams = customParams;
330: }
331:
332: public List getTags() {
333: return tags;
334: }
335:
336: public void setTags(List tags) {
337: this .tags = tags;
338: }
339:
340: public WeblogEntryData getWeblogEntry() {
341:
342: if (weblogEntry == null && weblogAnchor != null) {
343: try {
344: WeblogManager wmgr = RollerFactory.getRoller()
345: .getWeblogManager();
346: weblogEntry = wmgr.getWeblogEntryByAnchor(getWeblog(),
347: weblogAnchor);
348: } catch (RollerException ex) {
349: log.error("Error getting weblog entry " + weblogAnchor,
350: ex);
351: }
352: }
353:
354: return weblogEntry;
355: }
356:
357: public void setWeblogEntry(WeblogEntryData weblogEntry) {
358: this .weblogEntry = weblogEntry;
359: }
360:
361: public Template getWeblogPage() {
362:
363: if (weblogPage == null && weblogPageName != null) {
364: try {
365: UserManager umgr = RollerFactory.getRoller()
366: .getUserManager();
367: weblogPage = getWeblog().getPageByLink(weblogPageName);
368: } catch (RollerException ex) {
369: log.error(
370: "Error getting weblog page " + weblogPageName,
371: ex);
372: }
373: }
374:
375: return weblogPage;
376: }
377:
378: public void setWeblogPage(WeblogTemplate weblogPage) {
379: this .weblogPage = weblogPage;
380: }
381:
382: public WeblogCategoryData getWeblogCategory() {
383:
384: if (weblogCategory == null && weblogCategoryName != null) {
385: try {
386: WeblogManager wmgr = RollerFactory.getRoller()
387: .getWeblogManager();
388: weblogCategory = wmgr.getWeblogCategoryByPath(
389: getWeblog(), weblogCategoryName);
390: } catch (RollerException ex) {
391: log.error("Error getting weblog category "
392: + weblogCategoryName, ex);
393: }
394: }
395:
396: return weblogCategory;
397: }
398:
399: public void setWeblogCategory(WeblogCategoryData weblogCategory) {
400: this.weblogCategory = weblogCategory;
401: }
402:
403: }
|