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.util;
020:
021: import java.io.UnsupportedEncodingException;
022: import java.net.URLDecoder;
023: import java.net.URLEncoder;
024: import java.util.HashMap;
025: import java.util.Iterator;
026: import java.util.List;
027: import java.util.Map;
028: import org.apache.roller.config.RollerRuntimeConfig;
029: import org.apache.roller.pojos.Theme;
030: import org.apache.roller.pojos.WebsiteData;
031:
032: /**
033: * Utilities class for building urls. This class is meant to centralize the
034: * logic behind building urls so that logic isn't duplicated throughout the
035: * code.
036: */
037: public final class URLUtilities {
038:
039: // non-intantiable
040: private URLUtilities() {
041: }
042:
043: public static final String getXmlrpcURL(boolean absolute) {
044:
045: StringBuffer url = new StringBuffer();
046:
047: if (absolute) {
048: url.append(RollerRuntimeConfig.getAbsoluteContextURL());
049: } else {
050: url.append(RollerRuntimeConfig.getRelativeContextURL());
051: }
052:
053: url.append("/roller-services/xmlrpc");
054:
055: return url.toString();
056: }
057:
058: public static final String getAtomProtocolURL(boolean absolute) {
059:
060: StringBuffer url = new StringBuffer();
061:
062: if (absolute) {
063: url.append(RollerRuntimeConfig.getAbsoluteContextURL());
064: } else {
065: url.append(RollerRuntimeConfig.getRelativeContextURL());
066: }
067:
068: url.append("/roller-services/app");
069:
070: return url.toString();
071: }
072:
073: /**
074: * Get root url for a given weblog. Optionally for a certain locale.
075: */
076: public static final String getWeblogURL(WebsiteData weblog,
077: String locale, boolean absolute) {
078:
079: if (weblog == null) {
080: return null;
081: }
082:
083: StringBuffer url = new StringBuffer();
084:
085: if (absolute) {
086: url.append(RollerRuntimeConfig.getAbsoluteContextURL());
087: } else {
088: url.append(RollerRuntimeConfig.getRelativeContextURL());
089: }
090:
091: url.append("/").append(weblog.getHandle()).append("/");
092:
093: if (locale != null) {
094: url.append(locale).append("/");
095: }
096:
097: return url.toString();
098: }
099:
100: /**
101: * Get url for a single weblog entry on a given weblog.
102: */
103: public static final String getWeblogEntryURL(WebsiteData weblog,
104: String locale, String entryAnchor, boolean absolute) {
105:
106: if (weblog == null || entryAnchor == null) {
107: return null;
108: }
109:
110: StringBuffer url = new StringBuffer();
111:
112: url.append(getWeblogURL(weblog, locale, absolute));
113: url.append("entry/").append(encode(entryAnchor));
114:
115: return url.toString();
116: }
117:
118: /**
119: * Get url for a single weblog entry comments on a given weblog.
120: */
121: public static final String getWeblogCommentsURL(WebsiteData weblog,
122: String locale, String entryAnchor, boolean absolute) {
123:
124: return getWeblogEntryURL(weblog, locale, entryAnchor, absolute)
125: + "#comments";
126: }
127:
128: /**
129: * Get url for a single weblog entry comment on a given weblog.
130: */
131: public static final String getWeblogCommentURL(WebsiteData weblog,
132: String locale, String entryAnchor, String timeStamp,
133: boolean absolute) {
134:
135: return getWeblogEntryURL(weblog, locale, entryAnchor, absolute)
136: + "#comment-" + timeStamp;
137: }
138:
139: /**
140: * Get url for a collection of entries on a given weblog.
141: */
142: public static final String getWeblogCollectionURL(
143: WebsiteData weblog, String locale, String category,
144: String dateString, List tags, int pageNum, boolean absolute) {
145:
146: if (weblog == null) {
147: return null;
148: }
149:
150: StringBuffer pathinfo = new StringBuffer();
151: Map params = new HashMap();
152:
153: pathinfo.append(getWeblogURL(weblog, locale, absolute));
154:
155: String cat = null;
156: if (category != null && "/".equals(category)) {
157: cat = null;
158: } else if (category != null && category.startsWith("/")) {
159: cat = category.substring(1);
160: }
161:
162: if (cat != null && dateString == null) {
163: pathinfo.append("category/").append(encode(cat));
164:
165: } else if (dateString != null && cat == null) {
166: pathinfo.append("date/").append(dateString);
167:
168: } else if (tags != null && tags.size() > 0) {
169: pathinfo.append("tags/").append(getEncodedTagsString(tags));
170: } else {
171: if (dateString != null)
172: params.put("date", dateString);
173: if (cat != null)
174: params.put("cat", encode(cat));
175: }
176:
177: if (pageNum > 0) {
178: params.put("page", Integer.toString(pageNum));
179: }
180:
181: return pathinfo.toString() + getQueryString(params);
182: }
183:
184: /**
185: * Get url for a custom page on a given weblog.
186: */
187: public static final String getWeblogPageURL(WebsiteData weblog,
188: String locale, String pageLink, String entryAnchor,
189: String category, String dateString, List tags, int pageNum,
190: boolean absolute) {
191:
192: if (weblog == null) {
193: return null;
194: }
195:
196: StringBuffer pathinfo = new StringBuffer();
197: Map params = new HashMap();
198:
199: pathinfo.append(getWeblogURL(weblog, locale, absolute));
200:
201: if (pageLink != null) {
202: pathinfo.append("page/").append(pageLink);
203:
204: // for custom pages we only allow query params
205: if (dateString != null) {
206: params.put("date", dateString);
207: }
208: if (category != null) {
209: params.put("cat", encode(category));
210: }
211: if (tags != null && tags.size() > 0) {
212: params.put("tags", getEncodedTagsString(tags));
213: }
214: if (pageNum > 0) {
215: params.put("page", Integer.toString(pageNum));
216: }
217: } else {
218: // if there is no page link then this is just a typical collection url
219: return getWeblogCollectionURL(weblog, locale, category,
220: dateString, tags, pageNum, absolute);
221: }
222:
223: return pathinfo.toString() + getQueryString(params);
224: }
225:
226: /**
227: * Get url for a feed on a given weblog.
228: */
229: public static final String getWeblogFeedURL(WebsiteData weblog,
230: String locale, String type, String format, String category,
231: List tags, boolean excerpts, boolean absolute) {
232:
233: if (weblog == null) {
234: return null;
235: }
236:
237: StringBuffer url = new StringBuffer();
238:
239: url.append(getWeblogURL(weblog, locale, absolute));
240: url.append("feed/").append(type).append("/").append(format);
241:
242: Map params = new HashMap();
243: if (category != null && category.trim().length() > 0) {
244: params.put("cat", encode(category));
245: }
246: if (tags != null && tags.size() > 0) {
247: params.put("tags", getEncodedTagsString(tags));
248: }
249: if (excerpts) {
250: params.put("excerpts", "true");
251: }
252:
253: return url.toString() + getQueryString(params);
254: }
255:
256: /**
257: * Get url to search endpoint on a given weblog.
258: */
259: public static final String getWeblogSearchURL(WebsiteData weblog,
260: String locale, String query, String category, int pageNum,
261: boolean absolute) {
262:
263: if (weblog == null) {
264: return null;
265: }
266:
267: StringBuffer url = new StringBuffer();
268:
269: url.append(getWeblogURL(weblog, locale, absolute));
270: url.append("search");
271:
272: Map params = new HashMap();
273: if (query != null) {
274: params.put("q", encode(query));
275:
276: // other stuff only makes sense if there is a query
277: if (category != null) {
278: params.put("cat", encode(category));
279: }
280: if (pageNum > 0) {
281: params.put("page", Integer.toString(pageNum));
282: }
283: }
284:
285: return url.toString() + getQueryString(params);
286: }
287:
288: /**
289: * Get url to a resource on a given weblog.
290: */
291: public static final String getWeblogResourceURL(WebsiteData weblog,
292: String filePath, boolean absolute) {
293:
294: if (weblog == null) {
295: return null;
296: }
297:
298: StringBuffer url = new StringBuffer();
299:
300: url.append(getWeblogURL(weblog, null, absolute));
301: url.append("resource/");
302:
303: if (filePath.startsWith("/")) {
304: url.append(filePath.substring(1));
305: } else {
306: url.append(filePath);
307: }
308:
309: return url.toString();
310: }
311:
312: /**
313: * Get url to rsd file on a given weblog.
314: */
315: public static final String getWeblogRsdURL(WebsiteData weblog,
316: boolean absolute) {
317:
318: if (weblog == null) {
319: return null;
320: }
321:
322: return getWeblogURL(weblog, null, absolute) + "rsd";
323: }
324:
325: /**
326: * Get url to JSON tags service url, optionally for a given weblog.
327: */
328: public static final String getWeblogTagsJsonURL(WebsiteData weblog,
329: boolean absolute) {
330:
331: StringBuffer url = new StringBuffer();
332:
333: if (absolute) {
334: url.append(RollerRuntimeConfig.getAbsoluteContextURL());
335: } else {
336: url.append(RollerRuntimeConfig.getRelativeContextURL());
337: }
338:
339: // json tags service base
340: url.append("/roller-services/json/tags/");
341:
342: // is this for a specific weblog or site-wide?
343: if (weblog != null) {
344: url.append(weblog.getHandle()).append("/");
345: }
346:
347: return url.toString();
348: }
349:
350: /**
351: * Get root url for a given *preview* weblog.
352: * Optionally for a certain locale.
353: */
354: public static final String getPreviewWeblogURL(String previewTheme,
355: WebsiteData weblog, String locale, boolean absolute) {
356:
357: if (weblog == null) {
358: return null;
359: }
360:
361: StringBuffer url = new StringBuffer();
362:
363: if (absolute) {
364: url.append(RollerRuntimeConfig.getAbsoluteContextURL());
365: } else {
366: url.append(RollerRuntimeConfig.getRelativeContextURL());
367: }
368:
369: url.append("/roller-ui/authoring/preview/").append(
370: weblog.getHandle()).append("/");
371:
372: if (locale != null) {
373: url.append(locale).append("/");
374: }
375:
376: Map params = new HashMap();
377: if (previewTheme != null) {
378: params.put("theme", encode(previewTheme));
379: }
380:
381: return url.toString() + getQueryString(params);
382: }
383:
384: /**
385: * Get url for a given *preview* weblog entry.
386: * Optionally for a certain locale.
387: */
388: public static final String getPreviewWeblogEntryURL(
389: String previewAnchor, WebsiteData weblog, String locale,
390: boolean absolute) {
391:
392: if (weblog == null) {
393: return null;
394: }
395:
396: StringBuffer url = new StringBuffer();
397:
398: if (absolute) {
399: url.append(RollerRuntimeConfig.getAbsoluteContextURL());
400: } else {
401: url.append(RollerRuntimeConfig.getRelativeContextURL());
402: }
403:
404: url.append("/roller-ui/authoring/preview/").append(
405: weblog.getHandle()).append("/");
406:
407: if (locale != null) {
408: url.append(locale).append("/");
409: }
410:
411: Map params = new HashMap();
412: if (previewAnchor != null) {
413: params.put("previewEntry", encode(previewAnchor));
414: }
415:
416: return url.toString() + getQueryString(params);
417: }
418:
419: /**
420: * Get a url to a *preview* resource on a given weblog.
421: */
422: public static final String getPreviewWeblogResourceURL(
423: String previewTheme, WebsiteData weblog, String filePath,
424: boolean absolute) {
425:
426: if (weblog == null) {
427: return null;
428: }
429:
430: StringBuffer url = new StringBuffer();
431:
432: if (absolute) {
433: url.append(RollerRuntimeConfig.getAbsoluteContextURL());
434: } else {
435: url.append(RollerRuntimeConfig.getRelativeContextURL());
436: }
437:
438: url.append("/roller-ui/authoring/previewresource/").append(
439: weblog.getHandle()).append("/");
440:
441: if (filePath.startsWith("/")) {
442: url.append(filePath.substring(1));
443: } else {
444: url.append(filePath);
445: }
446:
447: Map params = new HashMap();
448: if (previewTheme != null && !Theme.CUSTOM.equals(previewTheme)) {
449: params.put("theme", encode(previewTheme));
450: }
451:
452: return url.toString() + getQueryString(params);
453: }
454:
455: /**
456: * Compose a map of key=value params into a query string.
457: */
458: public static final String getQueryString(Map params) {
459:
460: if (params == null) {
461: return null;
462: }
463:
464: StringBuffer queryString = new StringBuffer();
465:
466: for (Iterator keys = params.keySet().iterator(); keys.hasNext();) {
467: String key = (String) keys.next();
468: String value = (String) params.get(key);
469:
470: if (queryString.length() == 0) {
471: queryString.append("?");
472: } else {
473: queryString.append("&");
474: }
475:
476: queryString.append(key);
477: queryString.append("=");
478: queryString.append(value);
479: }
480:
481: return queryString.toString();
482: }
483:
484: /**
485: * URL encode a string using UTF-8.
486: */
487: public static final String encode(String str) {
488: String encodedStr = str;
489: try {
490: encodedStr = URLEncoder.encode(str, "UTF-8");
491: } catch (UnsupportedEncodingException ex) {
492: // ignored
493: }
494: return encodedStr;
495: }
496:
497: /**
498: * URL decode a string using UTF-8.
499: */
500: public static final String decode(String str) {
501: String decodedStr = str;
502: try {
503: decodedStr = URLDecoder.decode(str, "UTF-8");
504: } catch (UnsupportedEncodingException ex) {
505: // ignored
506: }
507: return decodedStr;
508: }
509:
510: public static final String getEncodedTagsString(List tags) {
511: StringBuffer tagsString = new StringBuffer();
512: if (tags != null && tags.size() > 0) {
513: String tag = null;
514: Iterator tagsIT = tags.iterator();
515:
516: // do first tag
517: tag = (String) tagsIT.next();
518: tagsString.append(encode(tag));
519:
520: // do rest of tags, joining them with a '+'
521: while (tagsIT.hasNext()) {
522: tag = (String) tagsIT.next();
523: tagsString.append("+");
524: tagsString.append(encode(tag));
525: }
526: }
527: return tagsString.toString();
528: }
529: }
|