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    }