    001    package org.apache.turbine.util.velocity;
    002
    003
    004    /*
    005     * Licensed to the Apache Software Foundation (ASF) under one
    006     * or more contributor license agreements.  See the NOTICE file
    007     * distributed with this work for additional information
    008     * regarding copyright ownership.  The ASF licenses this file
    009     * to you under the Apache License, Version 2.0 (the
    010     * "License"); you may not use this file except in compliance
    011     * with the License.  You may obtain a copy of the License at
    012     *
    013     *   http://www.apache.org/licenses/LICENSE-2.0
    014     *
    015     * Unless required by applicable law or agreed to in writing,
    016     * software distributed under the License is distributed on an
    017     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    018     * KIND, either express or implied.  See the License for the
    019     * specific language governing permissions and limitations
    020     * under the License.
    021     */
    022
    023
    024    import java.lang.reflect.InvocationTargetException;
    025    import java.lang.reflect.Method;
    026    import java.util.Iterator;
    027
    028    import org.apache.fulcrum.parser.ParameterParser;
    029    import org.apache.turbine.modules.ActionEvent;
    030    import org.apache.turbine.pipeline.PipelineData;
    031    import org.apache.turbine.services.velocity.TurbineVelocity;
    032    import org.apache.turbine.util.RunData;
    033    import org.apache.velocity.context.Context;
    034
    035    /**
    036     * If you are using VelocitySite stuff, then your Action's should
    037     * extend this class instead of extending the ActionEvent class.  The
    038     * difference between this class and the ActionEvent class is that
    039     * this class will first attempt to execute one of your doMethod's
    040     * with a constructor like this:
    041     *
    042     * <p><code>doEvent(RunData data, Context context)</code></p>
    043     *
    044     * <p>It gets the context from the TemplateInfo.getTemplateContext()
    045     * method. If it can't find a method like that, then it will try to
    046     * execute the method without the Context in it.</p>
    047     *
    048     * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
    049     * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
    050     * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
    051     * @author <a href="mailto:peter@courcoux.biz">Peter Courcoux</a>
    052     * @version $Id: VelocityActionEvent.java 1073174 2011-02-21 22:18:45Z tv $
    053     */
    054    public abstract class VelocityActionEvent extends ActionEvent
    055    {
    056        /** Constant needed for Reflection */
    057        private static final Class [] methodParams
    058                = new Class [] { RunData.class, Context.class };
    059
    060        /** Indicates whether or not this module has been initialized. */
    061        protected boolean initialized = false;
    062
    063        /**
    064         * You need to implement this in your classes that extend this
    065         * class.
    066         *
    067         * @deprecated Use PipelineData version instead.
    068         * @param data A Turbine RunData object.
    069         * @exception Exception a generic exception.
    070         */
    071        @Deprecated
    072        @Override
    073        public abstract void doPerform(RunData data)
    074                throws Exception;
    075
    076            /**
    077             * You need to implement this in your classes that extend this class.
    078             * Should revert to abstract once RunData is gone.
    079             * @param data Turbine information.
    080             * @exception Exception a generic exception.
    081             */
    082            @Override
    083        public void doPerform(PipelineData pipelineData)
    084                            throws Exception
    085            {
    086                  RunData data = getRunData(pipelineData);
    087                  doPerform(data);
    088            }
    089        /**
    090         * Provides a means of initializing the module.
    091         *
    092         * @throws Exception a generic exception.
    093         */
    094        protected abstract void initialize()
    095            throws Exception;
    096
    097        /**
    098         * This overrides the default Action.perform() to execute the
    099         * doEvent() method.  If that fails, then it will execute the
    100         * doPerform() method instead.
    101         *
    102         * @deprecated Use PipelineData version instead.
    103         * @param data A Turbine RunData object.
    104         * @exception Exception a generic exception.
    105         */
    106        @Deprecated
    107        @Override
    108        protected void perform(RunData data)
    109                throws Exception
    110        {
    111            try
    112            {
    113                if (!initialized)
    114                {
    115                    initialize();
    116                }
    117                executeEvents(data, TurbineVelocity.getContext(data));
    118            }
    119            catch (NoSuchMethodException e)
    120            {
    121                doPerform(data);
    122            }
    123        }
    124
    125        /**
    126         * This overrides the default Action.perform() to execute the
    127         * doEvent() method.  If that fails, then it will execute the
    128         * doPerform() method instead.
    129         *
    130         * @param data A Turbine RunData object.
    131         * @exception Exception a generic exception.
    132         */
    133        @Override
    134        protected void perform(PipelineData pipelineData)
    135                throws Exception
    136        {
    137            try
    138            {
    139                if (!initialized)
    140                {
    141                    initialize();
    142                }
    143
    144                executeEvents(pipelineData, TurbineVelocity.getContext(pipelineData));
    145            }
    146            catch (NoSuchMethodException e)
    147            {
    148                doPerform(pipelineData);
    149            }
    150        }
    151        /**
    152         * This method should be called to execute the event based system.
    153         * @deprecated Use PipelineData version instead.
    154         * @param data A Turbine RunData object.
    155         * @param context Velocity context information.
    156         * @exception Exception a generic exception.
    157         */
    158        @Deprecated
    159        public void executeEvents(RunData data, Context context)
    160                throws Exception
    161        {
    162            // Name of the button.
    163            String theButton = null;
    164
    165            // ParameterParser.
    166            ParameterParser pp = data.getParameters();
    167
    168            String button = pp.convert(BUTTON);
    169            String key = null;
    170
    171            // Loop through and find the button.
    172            for (Iterator it = pp.keySet().iterator(); it.hasNext();)
    173            {
    174                key = (String) it.next();
    175                if (key.startsWith(button))
    176                {
    177                    if (considerKey(key, pp))
    178                    {
    179                        theButton = formatString(key, pp);
    180                        break;
    181                    }
    182                }
    183            }
    184
    185            if (theButton == null)
    186            {
    187                throw new NoSuchMethodException(
    188                        "ActionEvent: The button was null");
    189            }
    190
    191            Method method = null;
    192            try
    193            {
    194                method = getClass().getMethod(theButton, methodParams);
    195                Object[] methodArgs = new Object[] { data, context };
    196
    197                if (log.isDebugEnabled())
    198                {
    199                    log.debug("Invoking " + method);
    200                }
    201
    202                method.invoke(this, methodArgs);
    203            }
    204            catch (NoSuchMethodException nsme)
    205            {
    206                // Attempt to execute things the old way..
    207                if (log.isDebugEnabled())
    208                {
    209                    log.debug("Couldn't locate the Event ( " + theButton
    210                            + "), running executeEvents() in "
    211                            + super.getClass().getName());
    212                }
    213
    214                super.executeEvents(data);
    215            }
    216            catch (InvocationTargetException ite)
    217            {
    218                Throwable t = ite.getTargetException();
    219                log.error("Invokation of " + method , t);
    220                throw ite;
    221            }
    222            finally
    223            {
    224                pp.remove(key);
    225            }
    226        }
    227
    228        /**
    229         * This method should be called to execute the event based system.
    230         *
    231         * @param data A Turbine RunData object.
    232         * @param context Velocity context information.
    233         * @exception Exception a generic exception.
    234         */
    235        public void executeEvents(PipelineData pipelineData, Context context)
    236                throws Exception
    237        {
    238                RunData data = getRunData(pipelineData);
    239            // Name of the button.
    240            String theButton = null;
    241
    242            // ParameterParser.
    243            ParameterParser pp = data.getParameters();
    244
    245            String button = pp.convert(BUTTON);
    246            String key = null;
    247
    248            // Loop through and find the button.
    249            for (Iterator it = pp.keySet().iterator(); it.hasNext();)
    250            {
    251                key = (String) it.next();
    252                if (key.startsWith(button))
    253                {
    254                    if (considerKey(key, pp))
    255                    {
    256                        theButton = formatString(key, pp);
    257                        break;
    258                    }
    259                }
    260            }
    261
    262            if (theButton == null)
    263            {
    264                throw new NoSuchMethodException(
    265                        "ActionEvent: The button was null");
    266            }
    267
    268            Method method = null;
    269            try
    270            {
    271                method = getClass().getMethod(theButton, methodParams);
    272                Object[] methodArgs = new Object[] { pipelineData, context };
    273
    274                if (log.isDebugEnabled())
    275                {
    276                    log.debug("Invoking " + method);
    277                }
    278
    279                method.invoke(this, methodArgs);
    280            }
    281            catch (NoSuchMethodException nsme)
    282            {
    283                // Attempt to execute things the old way..
    284                if (log.isDebugEnabled())
    285                {
    286                    log.debug("Couldn't locate the Event ( " + theButton
    287                            + "), running executeEvents() in "
    288                            + super.getClass().getName());
    289                }
    290
    291                super.executeEvents(pipelineData);
    292            }
    293            catch (InvocationTargetException ite)
    294            {
    295                Throwable t = ite.getTargetException();
    296                log.error("Invokation of " + method , t);
    297                throw ite;
    298            }
    299            finally
    300            {
    301                pp.remove(key);
    302            }
    303        }
    304
    305    }