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