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
020package org.apache.wiki.forms;
021
022import org.apache.wiki.WikiContext;
023import org.apache.wiki.api.engine.PluginManager;
024import org.apache.wiki.api.exceptions.PluginException;
025import org.apache.wiki.api.plugin.WikiPlugin;
026import org.apache.wiki.plugin.DefaultPluginManager;
027import org.apache.wiki.preferences.Preferences;
028import org.apache.wiki.util.FormUtil;
029
030import java.text.MessageFormat;
031import java.util.Map;
032import java.util.ResourceBundle;
033
034/**
035 */
036public class FormOutput
037        extends FormElement
038{
039    /**
040     * Executes the FormHandler specified in a Form 'output' plugin,
041     * using entries provided in the HttpRequest as FormHandler
042     * parameters.
043     * <p>
044     * If the parameter 'populate' was given, the WikiPlugin it names
045     * is used to get default values. (It probably makes a lot of
046     * sense for this to be the same plugin as the handler.) 
047     * Information for the populator can be given with the FormSet
048     * plugin. If 'populate' is not specified, the form is not
049     * displayed.
050     * <p>
051     * Should there be no HTTP request associated with this request,
052     * the method will return immediately with an empty string.
053     * 
054     * @param ctx {@inheritDoc}
055     * @param params {@inheritDoc}
056     * @return {@inheritDoc}
057     */
058    public String execute( WikiContext ctx, Map< String, String > params )
059        throws PluginException
060    {
061        //
062        //  If there is no HTTP request, returns immediately.
063        //
064        if( ctx.getHttpRequest() == null )
065        {
066            return "";
067        }
068        ResourceBundle rb = Preferences.getBundle( ctx, WikiPlugin.CORE_PLUGINS_RESOURCEBUNDLE );
069        
070        // If we are NOT here due to this form being submitted, we do nothing.
071        // The submitted form MUST have parameter 'formname' equal to the name
072        // parameter of this Form plugin.
073
074        String formName   = params.get( PARAM_FORM );
075        String submitForm = ctx.getHttpParameter( PARAM_FORMNAMEHIDDEN );
076        String populator  = params.get( PARAM_POPULATE );
077
078        if( submitForm == null || formName == null || 
079            !formName.equals( submitForm ) )
080        {
081            // No submitForm -> this was not a submission from the
082            // generated form.  If populate is specified, we'll go
083            // ahead and let the handler (populator) put stuff into
084            // the context, otherwise we'll just hide.
085            if( populator == null || !PARAM_HANDLER.equals( populator ) )
086                return "";
087            // If population was allowed, we should first  
088        }
089
090        String handler = params.get( PARAM_HANDLER );
091        if( handler == null || handler.length() == 0 )
092        {
093            // Need to print out an error here as this form is misconfigured
094            return "<p class=\"error\">" + MessageFormat.format( rb.getString( "formoutput.missingargument" ), PARAM_HANDLER ) + "</p>";
095        }
096
097        String sourcePage = ctx.getPage().getName();
098        String submitServlet = ctx.getURL( WikiContext.VIEW, sourcePage );
099
100        // If there is previous FormInfo available - say, from a
101        // FormSet plugin - use it.
102        FormInfo info = getFormInfo( ctx );
103        if( info == null )
104        {
105            // Reconstruct the form info from post data
106            info = new FormInfo();
107            info.setName( formName );
108        }
109        // Force override of handler and submit.
110        info.setHandler( handler );
111        info.setAction( submitServlet );
112
113        // Sift out all extra parameters, leaving only those submitted
114        // in the HTML FORM.
115        Map< String, String > handlerParams = FormUtil.requestToMap( ctx.getHttpRequest(), 
116                                                                     HANDLERPARAM_PREFIX );
117        // Previous submission info may be available from FormSet
118        // plugin - add, don't replace.
119        info.addSubmission( handlerParams );
120
121        // Pass the _body parameter from FormOutput on to the handler
122        info.getSubmission().put( DefaultPluginManager.PARAM_BODY, 
123                                  params.get(DefaultPluginManager.PARAM_BODY)); 
124
125        String handlerOutput = null;
126        String error = null;
127        try
128        {
129            // The plugin _can_ modify the parameters, so we make sure
130            // they stay with us.
131            PluginManager pm = ctx.getEngine().getPluginManager();
132            handlerOutput = pm.execute( ctx, handler, info.getSubmission() );
133            info.setResult( handlerOutput );
134            info.setStatus( FormInfo.EXECUTED );
135        }
136        catch( PluginException pe )
137        {
138            error = "<p class=\"error\">" + pe.getMessage() + "</p>";
139            info.setError( error );
140            info.setStatus( FormInfo.ERROR );
141        }
142
143        // We store the forminfo, so following Form plugin invocations on this
144        // page can decide what to do based on its values.
145        storeFormInfo( ctx, info );
146
147        if( error != null )
148            return error;
149
150        return handlerOutput != null ? handlerOutput : "";
151    }
152
153}