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