File Source: BookmarkPlugin.java
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.weblogger.business.plugins.entry;
20
21 import java.util.Collection;
22 import java.util.Iterator;
23 import java.util.Map;
24 import java.util.regex.Matcher;
25 import java.util.regex.Pattern;
26 import java.util.regex.PatternSyntaxException;
27 import org.apache.commons.lang.StringEscapeUtils;
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.roller.weblogger.WebloggerException;
31 import org.apache.roller.weblogger.business.BookmarkManager;
32 import org.apache.roller.weblogger.business.WebloggerFactory;
33 import org.apache.roller.weblogger.business.plugins.entry.WeblogEntryPlugin;
34 import org.apache.roller.weblogger.pojos.WeblogBookmark;
35 import org.apache.roller.weblogger.pojos.WeblogBookmarkFolder;
36 import org.apache.roller.weblogger.pojos.WeblogEntry;
37 import org.apache.roller.weblogger.pojos.Weblog;
38
39
40 /**
41 * Automatically insert links into entry text based on users bookmarks.
42 */
43 public class BookmarkPlugin implements WeblogEntryPlugin {
44
/*
P/P * Method: org.apache.roller.weblogger.business.plugins.entry.BookmarkPlugin__static_init
*
* Postconditions:
* init'ed(mLogger)
*/
45 private static Log mLogger = LogFactory.getLog(BookmarkPlugin.class);
46
47 protected String name = "Bookmark Linker";
48 protected String description = "Automatically uses your Bookmarks to " +
49 "create links. Simply use the Name of a Bookmark and it will be " +
50 "converted into a hyperlink using the Bookmark's URL.";
51
52
/*
P/P * Method: void org.apache.roller.weblogger.business.plugins.entry.BookmarkPlugin()
*
* Preconditions:
* mLogger != null
*
* Postconditions:
* this.description == &"Automatically uses your Bookmarks to create links. Simply use the Nam ... rk and it will be converted into a hyperlink using the Bookmark's URL."
* this.name == &"Bookmark Linker"
*/
53 public BookmarkPlugin() {
54 mLogger.debug("BookmarkPlugin instantiated.");
55 }
56
57
58 public String getName() {
/*
P/P * Method: String getName()
*
* Preconditions:
* init'ed(this.name)
*
* Postconditions:
* return_value == this.name
* init'ed(return_value)
*/
59 return name;
60 }
61
62
63 public String getDescription() {
/*
P/P * Method: String getDescription()
*
* Preconditions:
* init'ed(this.description)
*
* Postconditions:
* init'ed(return_value)
*/
64 return StringEscapeUtils.escapeJavaScript(description);
65 }
66
67
/*
P/P * Method: void init(Weblog)
*/
68 public void init(Weblog website) throws WebloggerException {}
69
70
71 public String render(WeblogEntry entry, String str) {
/*
P/P * Method: String render(WeblogEntry, String)
*
* Preconditions:
* (soft) entry != null
* (soft) mLogger != null
* (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider != null
* (soft) org/apache/roller/weblogger/business/WebloggerFactory.webloggerProvider.webloggerInstance != null
* (soft) str != null
*
* Presumptions:
* bMgr.strategy != null
* bMgr.strategy.emf != null
* bMgr.strategy.threadLocalEntityManager != null
* getWeblogger(...).bookmarkManager != null
* org.apache.roller.weblogger.pojos.WeblogBookmarkFolder:getFolders(...)@77 != null
* ...
*
* Postconditions:
* init'ed(java.lang.String:toString(...)._tainted)
* return_value != null
*/
72 String text = str;
73 try {
74 BookmarkManager bMgr = WebloggerFactory.getWeblogger().getBookmarkManager();
75 WeblogBookmarkFolder rootFolder = bMgr.getRootFolder(entry.getWebsite());
+ 76 text = matchBookmarks(text, rootFolder);
77 text = lookInFolders(text, rootFolder.getFolders());
78 } catch (WebloggerException e) {
79 // nothing much I can do, go with default "Weblog" value
80 // could be WebloggerException or NullPointerException
81 mLogger.warn(e);
82 }
83 return text;
84 }
85
86
87 /**
88 * Recursively travel down Folder tree, attempting
89 * to match up Bookmarks in each Folder.
90 *
91 * @param text
92 * @param folders
93 * @return
94 */
95 private String lookInFolders(String text, Collection folders) {
96
/*
P/P * Method: String lookInFolders(String, Collection)
*
* Preconditions:
* folders != null
* (soft) mLogger != null
* (soft) text != null
*
* Presumptions:
* java.util.Iterator:next(...)@99 != null
* org.apache.roller.weblogger.pojos.WeblogBookmarkFolder:getFolders(...)@102 != null
* org.apache.roller.weblogger.pojos.WeblogBookmarkFolder:getFolders(...)@103 != null
*
* Postconditions:
* init'ed(java.lang.String:toString(...)._tainted)
* (soft) return_value != null
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@98: {0}, {1}
* java.util.Set:isEmpty(...)@102: {1}, {0}
*/
97 Iterator it = folders.iterator();
98 while (it.hasNext()) {
99 WeblogBookmarkFolder folder = (WeblogBookmarkFolder)it.next();
100 text = matchBookmarks(text, folder);
101
102 if (!folder.getFolders().isEmpty()) {
103 lookInFolders(text, folder.getFolders());
104 }
105 }
106
107 return text;
108 }
109
110
111 private String matchBookmarks(String text,WeblogBookmarkFolder folder) {
/*
P/P * Method: String matchBookmarks(String, WeblogBookmarkFolder)
*
* Preconditions:
* folder != null
* (soft) mLogger != null
* (soft) text != null
*
* Presumptions:
* java.util.Iterator:next(...)@115 != null
* java.util.regex.Pattern:compile(...)@130 != null
* java.util.regex.Pattern:matcher(...)@130 != null
* org.apache.roller.weblogger.pojos.WeblogBookmarkFolder:getBookmarks(...)@112 != null
*
* Postconditions:
* init'ed(java.lang.String:toString(...)._tainted)
* return_value == &java.lang.String:toString(...)
*
* Test Vectors:
* java.util.Iterator:hasNext(...)@114: {0}, {1}
* java.util.regex.Matcher:find(...)@133: {0}, {1}
* java.util.regex.Matcher:group(...)@134: Addr_Set{null}, Inverse{null}
* java.util.regex.Matcher:group(...)@136: Addr_Set{null}, Inverse{null}
* java.util.regex.Matcher:group(...)@139: Addr_Set{null}, Inverse{null}
* java.util.regex.Matcher:group(...)@142: Addr_Set{null}, Inverse{null}
* org.apache.roller.weblogger.pojos.WeblogBookmark:getDescription(...)@116: Inverse{null}, Addr_Set{null}
*/
112 Iterator bookmarks = folder.getBookmarks().iterator();
113 String workingText = text;
114 while (bookmarks.hasNext()) {
115 WeblogBookmark bookmark = (WeblogBookmark)bookmarks.next();
116 String bkDescription = bookmark.getDescription();
117 if (bkDescription == null) bkDescription = "";
118 String bookmarkLink = "<a href=\"" +
119 bookmark.getUrl() + "\" title=\"" +
120 bkDescription + "\">" +
121 bookmark.getName() + "</a>";
122 try {
123 // Replace all occurrences of bookmark name that don't occur within the bounds of an anchor tag
124 // Notes:
125 // - use reluctant quantifiers on the tags to avoid gobbling more than desired
126 // - use non-capturing groups for boundaries to avoid replacing the boundary as well as the bookmark name.
127 // - we depend on the numbering of the specific groups in this expression in the replacement code below.
128 // TODO: should escape the bookmark name
129 String regEx = "(<a(?:\\s.*?)??/>)|(<a(?:\\s.*?)??>)|(</a(?:\\s.*?)??>)|(?:\\b)(" + bookmark.getName() + ")(?:\\b)";
130 Matcher m = Pattern.compile(regEx).matcher(workingText);
131 StringBuffer textBuf = new StringBuffer(workingText.length());
132 int inLink = 0;
133 while (m.find()) {
134 if (m.group(1) != null) {
135 // self-closed anchor tag <a ... /> -- ignore
136 } else if (m.group(2) != null) {
137 // matched opening anchor tag <a ...>
+ 138 inLink++;
139 } else if (m.group(3) != null) {
140 // closing anchor tag </a>, but ignore nonmatching ones
141 if (inLink > 0) inLink--;
142 } else if (m.group(4) != null) {
143 // matched the bookmark -- replace, but only if not within a link tag.
144 if (inLink == 0) m.appendReplacement(textBuf, bookmarkLink);
145 }
146 // Any remaining case indicates a bug. One could add an else with assertion here. Conservatively don't substitute.
147 }
148 m.appendTail(textBuf);
149 workingText = textBuf.toString();
150 } catch (PatternSyntaxException e) {
151 // Can happen since we don't escape pattern the bookmark name to protect pattern characters.
152 mLogger.warn("Failed to substitute for bookmark [" + bookmark.getName() + "] due to regular expression characters.");
153 }
154 }
155 return workingText.toString();
156 }
157
158 }
SofCheck Inspector Build Version : 2.18479
| BookmarkPlugin.java |
2009-Jan-02 14:25:22 |
| BookmarkPlugin.class |
2009-Sep-04 03:12:31 |