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