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}