001/*
002    Licensed to the Apache Software Foundation (ASF) under one
003    or more contributor license agreements.  See the NOTICE file
004    distributed with this work for additional information
005    regarding copyright ownership.  The ASF licenses this file
006    to you under the Apache License, Version 2.0 (the
007    "License"); you may not use this file except in compliance
008    with the License.  You may obtain a copy of the License at
009
010       http://www.apache.org/licenses/LICENSE-2.0
011
012    Unless required by applicable law or agreed to in writing,
013    software distributed under the License is distributed on an
014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015    KIND, either express or implied.  See the License for the
016    specific language governing permissions and limitations
017    under the License.
018 */
019package org.apache.wiki.plugin;
020
021import java.text.SimpleDateFormat;
022import java.util.Collection;
023import java.util.Date;
024import java.util.Iterator;
025import java.util.Map;
026import java.util.ResourceBundle;
027
028import org.apache.log4j.Logger;
029import org.apache.wiki.WikiContext;
030import org.apache.wiki.WikiEngine;
031import org.apache.wiki.WikiPage;
032import org.apache.wiki.api.exceptions.PluginException;
033import org.apache.wiki.api.exceptions.ProviderException;
034import org.apache.wiki.api.plugin.WikiPlugin;
035import org.apache.wiki.pages.PageLock;
036import org.apache.wiki.pages.PageManager;
037import org.apache.wiki.preferences.Preferences;
038import org.apache.wiki.util.TextUtil;
039
040/**
041 * Builds a simple weblog.
042 * <p/>
043 * <p>Parameters : </p>
044 * <ul>
045 * <li><b>entrytext</b> - text of the link </li>
046 * <li><b>page</b> - if set, the entry is added to the named blog page. The default is the current page. </li>
047 * </ul>
048 *
049 * @since 1.9.21
050 */
051public class WeblogEntryPlugin implements WikiPlugin {
052    private static Logger log = Logger.getLogger(WeblogEntryPlugin.class);
053
054    private static final int MAX_BLOG_ENTRIES = 10000; // Just a precaution.
055
056    /**
057     * Parameter name for setting the entrytext  Value is <tt>{@value}</tt>.
058     */
059    public static final String PARAM_ENTRYTEXT = "entrytext";
060    /**
061     * Optional parameter: page that actually contains the blog.
062     * This lets us provide a "new entry" link for a blog page
063     * somewhere else than on the page itself.
064     */
065    // "page" for uniform naming with WeblogPlugin...
066    /**
067     * Parameter name for setting the page Value is <tt>{@value}</tt>.
068     */
069    public static final String PARAM_BLOGNAME = "page";
070
071    /**
072     * Returns a new page name for entries.  It goes through the list of
073     * all blog pages, and finds out the next in line.
074     *
075     * @param engine   A WikiEngine
076     * @param blogName The page (or blog) name.
077     * @return A new name.
078     * @throws ProviderException If something goes wrong.
079     */
080    public String getNewEntryPage(WikiEngine engine, String blogName)
081            throws ProviderException {
082        SimpleDateFormat fmt = new SimpleDateFormat(WeblogPlugin.DEFAULT_DATEFORMAT);
083        String today = fmt.format(new Date());
084
085        int entryNum = findFreeEntry(engine.getPageManager(),
086                blogName,
087                today);
088
089
090        String blogPage = WeblogPlugin.makeEntryPage(blogName,
091                today,
092                "" + entryNum);
093
094        return blogPage;
095    }
096
097    /**
098     * {@inheritDoc}
099     */
100    public String execute(WikiContext context, Map<String, String> params)
101            throws PluginException {
102        ResourceBundle rb = Preferences.getBundle(context, WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE);
103
104        String weblogName = params.get(PARAM_BLOGNAME);
105        if (weblogName == null) {
106            weblogName = context.getPage().getName();
107        }
108        WikiEngine engine = context.getEngine();
109
110        StringBuilder sb = new StringBuilder();
111
112        String entryText = TextUtil.replaceEntities( params.get(PARAM_ENTRYTEXT) );
113        if (entryText == null) {
114            entryText = rb.getString("weblogentryplugin.newentry");
115        }
116
117        String url = context.getURL(WikiContext.NONE, "NewBlogEntry.jsp", "page=" + engine.encodeName(weblogName));
118
119        sb.append("<a href=\"" + url + "\">" + entryText + "</a>");
120
121        return sb.toString();
122    }
123
124    private int findFreeEntry(PageManager mgr,
125                              String baseName,
126                              String date)
127            throws ProviderException {
128        Collection< WikiPage > everyone = mgr.getAllPages();
129        int max = 0;
130
131        String startString = WeblogPlugin.makeEntryPage(baseName, date, "");
132
133        for (Iterator< WikiPage > i = everyone.iterator(); i.hasNext(); ) {
134            WikiPage p = i.next();
135
136            if (p.getName().startsWith(startString)) {
137                try {
138                    String probableId = p.getName().substring(startString.length());
139
140                    int id = Integer.parseInt(probableId);
141
142                    if (id > max) {
143                        max = id;
144                    }
145                } catch (NumberFormatException e) {
146                    log.debug("Was not a log entry: " + p.getName());
147                }
148            }
149        }
150
151        //
152        //  Find the first page that has no page lock.
153        //
154        int idx = max + 1;
155
156        while (idx < MAX_BLOG_ENTRIES) {
157            WikiPage page = new WikiPage(mgr.getEngine(),
158                    WeblogPlugin.makeEntryPage(baseName,
159                            date,
160                            Integer.toString(idx)));
161            PageLock lock = mgr.getCurrentLock(page);
162
163            if (lock == null) {
164                break;
165            }
166
167            idx++;
168        }
169
170        return idx;
171    }
172
173}