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 */
019 package org.apache.wiki.plugin;
020
021 import java.io.PrintWriter;
022 import java.io.StringWriter;
023 import java.security.Principal;
024 import java.text.MessageFormat;
025 import java.text.SimpleDateFormat;
026 import java.util.*;
027
028 import org.apache.log4j.Logger;
029 import org.apache.wiki.WikiContext;
030 import org.apache.wiki.WikiEngine;
031 import org.apache.wiki.WikiPage;
032 import org.apache.wiki.api.exceptions.PluginException;
033 import org.apache.wiki.api.exceptions.RedirectException;
034 import org.apache.wiki.api.exceptions.WikiException;
035 import org.apache.wiki.api.plugin.WikiPlugin;
036 import org.apache.wiki.parser.MarkupParser;
037 import org.apache.wiki.preferences.Preferences;
038
039 /**
040 * Provides a handler for bug reports. Still under construction.
041 *
042 * <p>Parameters : </p>
043 * <ul>
044 * <li><b>title</b> - title of the bug, this is required. If it is empty (as in "") it is a signal to the handler to return quietly.</li>
045 * <li><b>description</b> - description of the bug.</li>
046 * <li><b>version</b> - version</li>
047 * <li><b>map</b> - I have no idea </li>
048 * <li><b>page</b> - The name of the page to be created for this bug report </li>
049 * </ul>
050 *
051 */
052 public class BugReportHandler
053 implements WikiPlugin
054 {
055 private static Logger log = Logger.getLogger( BugReportHandler.class );
056
057 /** Parameter name for setting the title. Value is <tt>{@value}</tt>. */
058 public static final String PARAM_TITLE = "title";
059 /** Parameter name for setting the description. Value is <tt>{@value}</tt>. */
060 public static final String PARAM_DESCRIPTION = "description";
061 /** Parameter name for setting the version. Value is <tt>{@value}</tt>. */
062 public static final String PARAM_VERSION = "version";
063 /** Parameter name for setting the map. Value is <tt>{@value}</tt>. */
064 public static final String PARAM_MAPPINGS = "map";
065 /** Parameter name for setting the page. Value is <tt>{@value}</tt>. */
066 public static final String PARAM_PAGE = "page";
067
068 private static final String DEFAULT_DATEFORMAT = "dd-MMM-yyyy HH:mm:ss zzz";
069
070 /**
071 * {@inheritDoc}
072 */
073 public String execute( WikiContext context, Map<String, String> params )
074 throws PluginException
075 {
076 String title;
077 String description;
078 String version;
079 String submitter = null;
080 SimpleDateFormat format = new SimpleDateFormat( DEFAULT_DATEFORMAT );
081 ResourceBundle rb = Preferences.getBundle( context, WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE );
082
083 title = params.get( PARAM_TITLE );
084 description = params.get( PARAM_DESCRIPTION );
085 version = params.get( PARAM_VERSION );
086
087 Principal wup = context.getCurrentUser();
088
089 if( wup != null )
090 {
091 submitter = wup.getName();
092 }
093
094 if( title == null ) throw new PluginException(rb.getString("bugreporthandler.titlerequired"));
095 if( title.length() == 0 ) return "";
096
097 if( description == null ) description = "";
098 if( version == null ) version = "unknown";
099
100 Properties mappings = parseMappings( params.get( PARAM_MAPPINGS ) );
101
102 //
103 // Start things
104 //
105
106 try
107 {
108 StringWriter str = new StringWriter();
109 PrintWriter out = new PrintWriter( str );
110
111 Date d = new Date();
112
113 //
114 // Outputting of basic data
115 //
116 out.println("|"+mappings.getProperty(PARAM_TITLE,"Title")+"|"+title);
117 out.println("|"+mappings.getProperty("date","Date")+"|"+format.format(d));
118 out.println("|"+mappings.getProperty(PARAM_VERSION,"Version")+"|"+version);
119 if( submitter != null )
120 {
121 out.println("|"+mappings.getProperty("submitter","Submitter")+
122 "|"+submitter);
123 }
124
125 //
126 // Outputting the other parameters added to this.
127 //
128 for( Iterator<Map.Entry<String, String>> i = params.entrySet().iterator(); i.hasNext(); )
129 {
130 Map.Entry<String, String> entry = i.next();
131
132 if( entry.getKey().equals( PARAM_TITLE ) ||
133 entry.getKey().equals( PARAM_DESCRIPTION ) ||
134 entry.getKey().equals( PARAM_VERSION ) ||
135 entry.getKey().equals( PARAM_MAPPINGS ) ||
136 entry.getKey().equals( PARAM_PAGE ) ||
137 entry.getKey().startsWith("_") )
138 {
139 // Ignore this
140 }
141 else
142 {
143 //
144 // If no mapping has been defined, just ignore
145 // it.
146 //
147 String head = mappings.getProperty( entry.getKey(), entry.getKey() );
148 if( head.length() > 0 )
149 {
150 out.println("|"+head+
151 "|"+entry.getValue());
152 }
153 }
154 }
155
156 out.println();
157 out.println( description );
158
159 out.close();
160
161 //
162 // Now create a new page for this bug report
163 //
164 String pageName = findNextPage( context, title, params.get( PARAM_PAGE ) );
165
166 WikiPage newPage = new WikiPage( context.getEngine(), pageName );
167 WikiContext newContext = (WikiContext)context.clone();
168 newContext.setPage( newPage );
169
170 context.getEngine().saveText( newContext,
171 str.toString() );
172
173 MessageFormat formatter = new MessageFormat("");
174 formatter.applyPattern( rb.getString("bugreporthandler.new") );
175 String[] args = { "<a href=\""+context.getViewURL(pageName)+"\">"+pageName+"</a>" };
176
177 return formatter.format( args );
178 }
179 catch( RedirectException e )
180 {
181 log.info("Saving not allowed, reason: '"+e.getMessage()+"', can't redirect to "+e.getRedirect());
182
183 throw new PluginException("Saving not allowed, reason: "+e.getMessage());
184 }
185 catch( WikiException e )
186 {
187 log.error("Unable to save page!",e);
188
189 return rb.getString("bugreporthandler.unable");
190 }
191 }
192
193 /**
194 * Finds a free page name for adding the bug report. Tries to construct a page,
195 * and if it's found, adds a number to it and tries again.
196 */
197 private synchronized String findNextPage( WikiContext context,
198 String title,
199 String baseName )
200 {
201 String basicPageName = ((baseName != null)?baseName:"Bug")+MarkupParser.cleanLink(title);
202
203 WikiEngine engine = context.getEngine();
204
205 String pageName = basicPageName;
206 long lastbug = 2;
207
208 while( engine.pageExists( pageName ) )
209 {
210 pageName = basicPageName + lastbug++;
211 }
212
213 return pageName;
214 }
215
216 /**
217 * Just parses a mappings list in the form of "a=b;b=c;c=d".
218 * <p>
219 * FIXME: Should probably be in TextUtil or somewhere.
220 */
221 private Properties parseMappings( String mappings )
222 {
223 Properties props = new Properties();
224
225 if( mappings == null ) return props;
226
227 StringTokenizer tok = new StringTokenizer( mappings, ";" );
228
229 while( tok.hasMoreTokens() )
230 {
231 String t = tok.nextToken();
232
233 int colon = t.indexOf("=");
234
235 String key;
236 String value;
237
238 if( colon > 0 )
239 {
240 key = t.substring(0,colon);
241 value = t.substring(colon+1);
242 }
243 else
244 {
245 key = t;
246 value = "";
247 }
248
249 props.setProperty( key, value );
250 }
251
252 return props;
253 }
254 }