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