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 org.apache.log4j.Logger;
022import org.apache.wiki.api.core.Context;
023import org.apache.wiki.api.core.ContextEnum;
024import org.apache.wiki.api.core.Engine;
025import org.apache.wiki.api.core.Page;
026import org.apache.wiki.api.exceptions.PluginException;
027import org.apache.wiki.api.exceptions.ProviderException;
028import org.apache.wiki.api.plugin.Plugin;
029import org.apache.wiki.api.spi.Wiki;
030import org.apache.wiki.pages.PageLock;
031import org.apache.wiki.pages.PageManager;
032import org.apache.wiki.preferences.Preferences;
033import org.apache.wiki.util.TextUtil;
034
035import java.text.SimpleDateFormat;
036import java.util.Collection;
037import java.util.Date;
038import java.util.Map;
039import java.util.ResourceBundle;
040
041/**
042 * Builds a simple weblog.
043 * <p/>
044 * <p>Parameters : </p>
045 * <ul>
046 * <li><b>entrytext</b> - text of the link </li>
047 * <li><b>page</b> - if set, the entry is added to the named blog page. The default is the current page. </li>
048 * </ul>
049 *
050 * @since 1.9.21
051 */
052public class WeblogEntryPlugin implements Plugin {
053
054    private static final Logger log = Logger.getLogger(WeblogEntryPlugin.class);
055    private static final int MAX_BLOG_ENTRIES = 10_000; // Just a precaution.
056
057    /**
058     * Parameter name for setting the entrytext  Value is <tt>{@value}</tt>.
059     */
060    public static final String PARAM_ENTRYTEXT = "entrytext";
061
062    /*
063     * Optional parameter: page that actually contains the blog. This lets us provide a "new entry" link for a blog page
064     * somewhere else than on the page itself.
065     */
066    // "page" for uniform naming with WeblogPlugin...
067    
068    /**
069     * Parameter name for setting the page Value is <tt>{@value}</tt>.
070     */
071    public static final String PARAM_BLOGNAME = "page";
072
073    /**
074     * Returns a new page name for entries.  It goes through the list of all blog pages, and finds out the next in line.
075     *
076     * @param engine   A Engine
077     * @param blogName The page (or blog) name.
078     * @return A new name.
079     * @throws ProviderException If something goes wrong.
080     */
081    public String getNewEntryPage( final Engine engine, final String blogName ) throws ProviderException {
082        final SimpleDateFormat fmt = new SimpleDateFormat(WeblogPlugin.DEFAULT_DATEFORMAT);
083        final String today = fmt.format(new Date());
084        final int entryNum = findFreeEntry( engine, blogName, today );
085
086        return WeblogPlugin.makeEntryPage( blogName, today,"" + entryNum );
087    }
088
089    /**
090     * {@inheritDoc}
091     */
092    @Override
093    public String execute( final Context context, final Map< String, String > params ) throws PluginException {
094        final ResourceBundle rb = Preferences.getBundle(context, Plugin.CORE_PLUGINS_RESOURCEBUNDLE);
095        final Engine engine = context.getEngine();
096
097        String weblogName = params.get(PARAM_BLOGNAME);
098        if (weblogName == null) {
099            weblogName = context.getPage().getName();
100        }
101
102        String entryText = TextUtil.replaceEntities( params.get( PARAM_ENTRYTEXT ) );
103        if (entryText == null) {
104            entryText = rb.getString("weblogentryplugin.newentry");
105        }
106
107        final String url = context.getURL( ContextEnum.PAGE_NONE.getRequestContext(), "NewBlogEntry.jsp", "page=" + engine.encodeName( weblogName ) );
108        return "<a href=\"" + url + "\">" + entryText + "</a>";
109    }
110
111    private int findFreeEntry( final Engine engine, final String baseName, final String date ) throws ProviderException {
112        final Collection< Page > everyone = engine.getManager( PageManager.class ).getAllPages();
113        final String startString = WeblogPlugin.makeEntryPage(baseName, date, "");
114        int max = 0;
115
116        for( final Page p : everyone ) {
117            if( p.getName().startsWith( startString ) ) {
118                try {
119                    final String probableId = p.getName().substring( startString.length() );
120                    final int id = Integer.parseInt( probableId );
121                    if( id > max ) {
122                        max = id;
123                    }
124                } catch( final NumberFormatException e ) {
125                    log.debug( "Was not a log entry: " + p.getName() );
126                }
127            }
128        }
129
130        //  Find the first page that has no page lock.
131        int idx = max + 1;
132        while( idx < MAX_BLOG_ENTRIES ) {
133            final Page page = Wiki.contents().page( engine, WeblogPlugin.makeEntryPage( baseName, date, Integer.toString( idx ) ) );
134            final PageLock lock = engine.getManager( PageManager.class ).getCurrentLock(page);
135            if (lock == null) {
136                break;
137            }
138
139            idx++;
140        }
141
142        return idx;
143    }
144
145}