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