org.apache.roller.weblogger.business.plugins.entry.BookmarkPlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.roller.weblogger.business.plugins.entry.BookmarkPlugin.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  The ASF licenses this file to You
 * under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.  For additional information regarding
 * copyright in this work, please see the NOTICE file in the top level
 * directory of this distribution.
 */

package org.apache.roller.weblogger.business.plugins.entry;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.BookmarkManager;
import org.apache.roller.weblogger.business.WebloggerFactory;
import org.apache.roller.weblogger.business.plugins.entry.WeblogEntryPlugin;
import org.apache.roller.weblogger.pojos.WeblogBookmark;
import org.apache.roller.weblogger.pojos.WeblogBookmarkFolder;
import org.apache.roller.weblogger.pojos.WeblogEntry;
import org.apache.roller.weblogger.pojos.Weblog;

/**
 * Automatically insert links into entry text based on users bookmarks.
 */
public class BookmarkPlugin implements WeblogEntryPlugin {

    private static Log mLogger = LogFactory.getLog(BookmarkPlugin.class);

    protected String name = "Bookmark Linker";
    protected String description = "Automatically uses your Bookmarks to "
            + "create links.  Simply use the Name of a Bookmark and it will be "
            + "converted into a hyperlink using the Bookmark's URL.";

    public BookmarkPlugin() {
        mLogger.debug("BookmarkPlugin instantiated.");
    }

    public String getName() {
        return name;
    }

    public String getDescription() {
        return StringEscapeUtils.escapeJavaScript(description);
    }

    public void init(Weblog website) throws WebloggerException {
    }

    public String render(WeblogEntry entry, String str) {
        String text = str;
        try {
            BookmarkManager bMgr = WebloggerFactory.getWeblogger().getBookmarkManager();
            WeblogBookmarkFolder rootFolder = bMgr.getRootFolder(entry.getWebsite());
            text = matchBookmarks(text, rootFolder);
            text = lookInFolders(text, rootFolder.getFolders());
        } catch (WebloggerException e) {
            // nothing much I can do, go with default "Weblog" value
            // could be WebloggerException or NullPointerException
            mLogger.warn(e);
        }
        return text;
    }

    /**
     * Recursively travel down Folder tree, attempting
     * to match up Bookmarks in each Folder.
     *
     * @param text
     * @param folders
     * @return
     */
    private String lookInFolders(String text, Collection folders) {

        Iterator it = folders.iterator();
        while (it.hasNext()) {
            WeblogBookmarkFolder folder = (WeblogBookmarkFolder) it.next();
            text = matchBookmarks(text, folder);

            if (!folder.getFolders().isEmpty()) {
                lookInFolders(text, folder.getFolders());
            }
        }

        return text;
    }

    private String matchBookmarks(String text, WeblogBookmarkFolder folder) {
        Iterator bookmarks = folder.getBookmarks().iterator();
        String workingText = text;
        while (bookmarks.hasNext()) {
            WeblogBookmark bookmark = (WeblogBookmark) bookmarks.next();
            String bkDescription = bookmark.getDescription();
            if (bkDescription == null)
                bkDescription = "";
            String bookmarkLink = "<a href=\"" + bookmark.getUrl() + "\" title=\"" + bkDescription + "\">"
                    + bookmark.getName() + "</a>";
            try {
                // Replace all occurrences of bookmark name that don't occur within the bounds of an anchor tag
                // Notes:
                // - use reluctant quantifiers on the tags to avoid gobbling more than desired
                // - use non-capturing groups for boundaries to avoid replacing the boundary as well as the bookmark name.
                // - we depend on the numbering of the specific groups in this expression in the replacement code below.
                // TODO: should escape the bookmark name
                String regEx = "(<a(?:\\s.*?)??/>)|(<a(?:\\s.*?)??>)|(</a(?:\\s.*?)??>)|(?:\\b)("
                        + bookmark.getName() + ")(?:\\b)";
                Matcher m = Pattern.compile(regEx).matcher(workingText);
                StringBuffer textBuf = new StringBuffer(workingText.length());
                int inLink = 0;
                while (m.find()) {
                    if (m.group(1) != null) {
                        // self-closed anchor tag <a  ... /> -- ignore
                    } else if (m.group(2) != null) {
                        // matched opening anchor tag <a ...>
                        inLink++;
                    } else if (m.group(3) != null) {
                        // closing anchor tag </a>, but ignore nonmatching ones
                        if (inLink > 0)
                            inLink--;
                    } else if (m.group(4) != null) {
                        // matched the bookmark -- replace, but only if not within a link tag.
                        if (inLink == 0)
                            m.appendReplacement(textBuf, bookmarkLink);
                    }
                    // Any remaining case indicates a bug.  One could add an else with assertion here.  Conservatively don't substitute.
                }
                m.appendTail(textBuf);
                workingText = textBuf.toString();
            } catch (PatternSyntaxException e) {
                // Can happen since we don't escape pattern the bookmark name to protect pattern characters.
                mLogger.warn("Failed to substitute for bookmark [" + bookmark.getName()
                        + "] due to regular expression characters.");
            }
        }
        return workingText.toString();
    }

}