View Javadoc

1   /**
2    * Copyright 2005-2008 the original author or authors.
3    *
4    * Licensed under the Gnu General Pubic License, Version 2.0 (the
5    * "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    *
8    *      http://www.opensource.org/licenses/gpl-license.php
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13   * See the Gnu General Public License for more details.
14   */
15  package org.figure8.join.control.action;
16  
17  import org.figure8.join.control.JoinAction;
18  import org.figure8.join.control.form.ConsumerForm;
19  import org.figure8.join.core.Configurable;
20  import org.figure8.join.core.ContainerContextHandler;
21  import org.figure8.join.core.setup.BootstrapUtil;
22  import org.figure8.join.core.setup.BootstrapManager;
23  import org.figure8.join.core.messaging.JMSConsumerBeanInfo;
24  import org.figure8.join.core.messaging.JMSConsumerBeanManager;
25  import org.figure8.join.core.messaging.JMSConsumerBeanParameterInfo;
26  import org.figure8.join.services.remoting.MessagingService;
27  import org.figure8.join.services.remoting.services.BeansHelper;
28  import org.figure8.join.services.remoting.beans.RemoteJMSConsumerBeanInfo;
29  import org.figure8.join.services.security.InvalidLoginException;
30  import org.figure8.join.businessobjects.security.User;
31  import org.figure8.join.util.ScriptLogAccessorProxy;
32  import org.figure8.join.util.LogUtil;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.beanutils.PropertyUtils;
36  import org.apache.struts.action.ActionForm;
37  import org.apache.struts.action.ActionForward;
38  import org.apache.struts.action.ActionMapping;
39  
40  import com.caucho.hessian.client.HessianProxyFactory;
41  
42  import javax.servlet.http.HttpSession;
43  import javax.servlet.http.HttpServletRequest;
44  import javax.servlet.http.HttpServletResponse;
45  
46  import java.rmi.RemoteException;
47  import java.util.List;
48  import java.util.Iterator;
49  /**
50   * This is a Struts action for managing the event consumers in Join application.
51   * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
52   * @version $Revision: 1.4 $
53   *
54   * @struts.action path="/consumer" name="consumerForm"
55   *                scope="request" parameter="op" validate="true"
56   *                input="/pages/mainpage.jsp?body=/jsp/consumers.jsp"
57   * @struts.action-forward name="Consumers" path="/jsp/consumers.jsp"
58   * @struts.action-forward name="Details" path="/jsp/consumerdetails.jsp"
59   * @struts.action-forward name="Parameters" path="/jsp/configurableparameters.jsp"
60   */
61  public class ConsumerActions extends JoinAction{
62  
63     // Static -------------------------------------------------------------------
64  
65     /** Get a commons logger. */
66     private static final Log log = LogUtil.getLog(ConsumerActions.class);
67  
68     /** Operation code for loading a message consumer infos */
69     public static final String LOAD_OP = "load";
70     /** Operation code for saving a message consumer infos */
71     public static final String SAVE_OP = "save";
72     /** Operation code for saving a message consumer parameters infos */
73     public static final String SAVE_PARAM_OP = "saveParameters";
74     /** Operation code for getting details on a message consumer infos */
75     public static final String DETAILS_OP = "details";
76  
77     /**
78      * The session scope attribute under which the consumer object
79      * currently selected by our logged-in User is stored.
80      */
81     public static final String CONSUMER_KEY = "consumer";
82     /**
83      * The session scope attribute under which the retrieved consumers
84      * list is stored.
85      */
86     public static final String CONSUMERS_KEY = "consumers";
87     /**
88      * The request scope attribute under which is stored the Consumer that
89      * has raised a DuplicateEntityException during save of another one.
90      */
91     public static final String DUPLICATE_CONSUMER_KEY = "duplicate";
92  
93  
94     // Attributes ---------------------------------------------------------------
95  
96     /** The remote messaging service to use if setup is dissociated */
97     protected MessagingService service = null;
98     /** The local consumers manager to use if setup is simple */
99     protected JMSConsumerBeanManager manager = null;
100 
101 
102    // Constructors -------------------------------------------------------------
103 
104    /** Creates a new instance of ConsumerActions. */
105    public ConsumerActions(){
106    }
107 
108 
109    // Override of JoinAction ---------------------------------------------------
110 
111    /**
112     * 
113     * @param operation String representing the operation to invoke on Action
114     * @param mapping Mapping between forwards name and path for this action
115     * @param form The form object containing request parameters
116     * @param request The servlet container request wrapper
117     * @param response The servlet container response wrapper
118     * @return A forward to the next view to render and display
119     * @throws Exception such as InfraStructureExceptions ...
120     */
121    public ActionForward doExecute(String operation, ActionMapping mapping, ActionForm form,
122                                   HttpServletRequest request, HttpServletResponse response)
123            throws Exception{
124       // Trace operation to execute.
125       log.debug("doExecute() called for '" + operation + "' operation");
126 
127       // References cannot be injected so retrieve them.
128       initializeManagerOrService();
129       // If not specify, set the default display type.
130       if (request.getParameter("displayType") == null)
131          request.setAttribute("displayType", "all");
132 
133       try{
134          if (LOAD_OP.equals(operation)){
135             return loadConsumer(mapping, form, request, response);
136          }
137          else if (SAVE_OP.equals(operation)){
138             return saveConsumer(mapping, form, request, response);
139          }
140          else if (SAVE_PARAM_OP.equals(operation)){
141             return saveConsumerParameters(mapping, form, request, response);
142          }
143          else if (DETAILS_OP.equals(operation)){
144             return getConsumerDetails(mapping, form, request, response);
145          }
146          else{
147             // Default : empty consumers management page.
148             request.getSession().removeAttribute(CONSUMER_KEY);
149             updateConsumersInRequest(request);
150             return mapping.findForward("Consumers");
151          }
152       }
153       catch (InvalidLoginException ile){
154          log.error("");
155          return mapping.findForward("");
156       }
157       catch (RemoteException re){
158          log.error("");
159          return mapping.findForward("");
160       }
161    }
162 
163 
164    // Protected ----------------------------------------------------------------
165 
166    /**
167     * Load a specified consumer info from datastore and fill form with it.
168     * @return A forward to the next view to render and display
169     */
170    protected ActionForward loadConsumer(ActionMapping mapping, ActionForm form,
171                                         HttpServletRequest request, HttpServletResponse response)
172          throws Exception{
173 
174       if (form instanceof ConsumerForm){
175          // Get the consumer form & session for storing consumer.
176          ConsumerForm cForm = (ConsumerForm)form;
177          HttpSession session = request.getSession();
178 
179          // Get the requested consumer, from local manager or remote service.
180          if (manager != null){
181             log.debug("Retrieving consumer '" + cForm.getName() + "' from local manager");
182             // Use local manager.
183             JMSConsumerBeanInfo consumer = manager.getConsumerBeanInfo(cForm.getName());
184             session.setAttribute(CONSUMER_KEY, consumer);
185             // Copy consumer into the form properties.
186             PropertyUtils.copyProperties(cForm, consumer);
187          }
188          else if (service != null){
189             log.debug("Retrieving consumer '" + cForm.getName() + "' from remote service");
190             // Use remote service (require login, logout).
191             String token = loginToRemoteService(request);
192             RemoteJMSConsumerBeanInfo remoteConsumer = service.getConsumerBeanInfo(token, cForm.getName());
193             logoutFromRemoteService(token);
194             // Create a local consumer for storing in session.
195             JMSConsumerBeanInfo consumer = BeansHelper.getLocalObject(remoteConsumer);
196             session.setAttribute(CONSUMER_KEY, consumer);
197             // Copy consumer into the form properties.
198             PropertyUtils.copyProperties(cForm, consumer);
199          }
200 
201          // Forward after having filled request with consumers.
202          updateConsumersInRequest(request);
203          return mapping.findForward("Consumers");
204       }
205       // This should not happen...
206       return null;
207    }
208 
209    /**
210     * Save a consumer into datastore. The consumer may be an already existing one or a
211     * new one (this is indeed a create or update method).
212     * @return A forward to the next view to render and display
213     */
214    protected ActionForward saveConsumer(ActionMapping mapping, ActionForm form,
215                                         HttpServletRequest request, HttpServletResponse response)
216          throws Exception{
217 
218       if (form instanceof ConsumerForm){
219          // Get the consumer form.
220          ConsumerForm cForm = (ConsumerForm)form;
221          // Is there a consumer to update in session ?
222          HttpSession session = request.getSession();
223          JMSConsumerBeanInfo consumer = (JMSConsumerBeanInfo)session.getAttribute(CONSUMER_KEY);
224 
225          // Create a new consumer or populate existing with form.
226          if (consumer == null){
227             log.info("Creation of a new JMSConsumerBeanInfo with name: " + cForm.getName());
228             consumer = new JMSConsumerBeanInfo(cForm.getName(), cForm.getSelector(), cForm.getDestination(),
229                     cForm.getConsumerBeanClass());
230             consumer.setActive(cForm.isActive());
231             consumer.setThreadSafe(cForm.isThreadSafe());
232          }
233          else{
234             log.info("Update of existing JMSConsumerBeanInfo having name: " + cForm.getName());
235             PropertyUtils.copyProperties(consumer, cForm);
236          }
237 
238          // Save the consumer, using local manager or remote service.
239          if (manager != null){
240             log.debug("Saving consumer '" + cForm.getName() + "' using local manager");
241             // Use local manager.
242             manager.saveConsumerBeanInfo(consumer);
243          }
244          else if (service != null){
245             log.debug("Saving consumer '" + cForm.getName() + "' using remote service");
246             // Use remote service (require login, logout).
247             String token = loginToRemoteService(request);
248             service.saveConsumerBeanInfo(token, BeansHelper.getRemoteObject(consumer));
249             logoutFromRemoteService(token);
250          }
251 
252          // Forward depending of configurable nature of consumer class.
253          if (consumer.getJMSConsumerBean() instanceof Configurable){
254             session.setAttribute(CONSUMER_KEY, consumer);
255             // Give the configurable form what it need.
256             request.setAttribute(OP_PARAMETER, SAVE_PARAM_OP);
257             request.setAttribute("configurableId", consumer.getName());
258             request.setAttribute("configurable", consumer.getJMSConsumerBean());
259             request.setAttribute("action", "consumer");
260 
261             // Retrieve consumer's parameters and fill form.
262             List parameters = consumer.getConsumerParameterInfos();
263             for (int i=0; i < parameters.size(); i++)
264                cForm.addParameter((JMSConsumerBeanParameterInfo)parameters.get(i));
265 
266             return mapping.findForward("Parameters");
267          }
268 
269          // Remove form and session attribute if present.
270          session.removeAttribute(CONSUMER_KEY);
271          updateConsumersInRequest(request);
272          removeObsoleteForm(mapping, request);
273          return mapping.findForward("Consumers");
274       }
275       // This should not happen...
276       return null;
277    }
278 
279    /**
280     * Save a consumer parameters into datastore. The consumer is an already existing one.
281     * @return A forward to the next view to render and display
282     */
283    protected ActionForward saveConsumerParameters(ActionMapping mapping, ActionForm form,
284                                                   HttpServletRequest request, HttpServletResponse response)
285          throws Exception{
286 
287       if (form instanceof ConsumerForm){
288          // Get the consumer form.
289          ConsumerForm cForm = (ConsumerForm)form;
290          // Is there a consumer to update in session ?
291          HttpSession session = request.getSession();
292          JMSConsumerBeanInfo consumer = (JMSConsumerBeanInfo)session.getAttribute(CONSUMER_KEY);
293 
294          if (consumer != null){
295             log.info("Adding JMSConsumerBeanParameterInfo to consumer: " + consumer.getName());
296             // Remove all existing parameters.
297             consumer.getConsumerParameterInfos().clear();
298 
299             // Browse parameters present in form.
300             Iterator parameters = cForm.getParameters().keySet().iterator();
301             while (parameters != null && parameters.hasNext()){
302                // Retrieve name, value pairs.
303                String name = (String)parameters.next();
304                String value = (String)cForm.getMappedParameter(name);
305                if (log.isDebugEnabled())
306                   log.debug("Adding a consumer parameter: " + name + "=" + value);
307                // Add a new parameter info to consume.
308                JMSConsumerBeanParameterInfo paramInfo = new JMSConsumerBeanParameterInfo(name, value);
309                consumer.addConsumerParameterInfo(paramInfo);
310             }
311 
312             // Update the consumer, using local manager or remote service.
313             if (manager != null){
314                log.debug("Saving consumer '" + cForm.getName() + "' parameters using local manager");
315                // Use local manager.
316                manager.saveConsumerBeanInfo(consumer);
317             }
318             else if (service != null){
319                log.debug("Saving consumer '" + cForm.getName() + "' parameters using remote service");
320                // Use remote service (require login, logout).
321                String token = loginToRemoteService(request);
322                service.saveConsumerBeanInfo(token, BeansHelper.getRemoteObject(consumer));
323                logoutFromRemoteService(token);
324             }
325          }
326 
327          // Forward after having updated consumers in request.
328          updateConsumersInRequest(request);
329          // Remove form and session attribute if present.
330          session.removeAttribute(CONSUMER_KEY);
331          removeObsoleteForm(mapping, request);
332          return mapping.findForward("Consumers");
333       }
334       // This should not happen...
335       return null;
336    }
337 
338    /**
339     * Get all the details from registered consumer, including its parameters and execution log files
340     * @return A forward to the next view to render and display
341     */
342    protected ActionForward getConsumerDetails(ActionMapping mapping, ActionForm form,
343                                               HttpServletRequest request, HttpServletResponse response)
344          throws Exception{
345 
346       if (form instanceof ConsumerForm){
347          ConsumerForm cForm = (ConsumerForm)form;
348 
349          // Get the requested consumer, from local manager or remote service.
350          if (manager != null){
351             JMSConsumerBeanInfo consumer = manager.getConsumerBeanInfo(cForm.getName());
352             request.setAttribute(CONSUMER_KEY, consumer);
353          }
354          else if (service != null){
355             String token = loginToRemoteService(request);
356             RemoteJMSConsumerBeanInfo consumer = service.getConsumerBeanInfo(token, cForm.getName());
357             logoutFromRemoteService(token);
358             request.setAttribute(CONSUMER_KEY, consumer);
359          }
360          // Get information on execution logs.
361          ScriptLogAccessorProxy proxy = ScriptLogAccessorProxy.getInstance();
362          List logInfos = proxy.getScriptLogInfos(cForm.getName(), "JMSAdapter");
363          request.setAttribute("scriptLogInfos", logInfos);
364 
365          // Forward to details.
366          return mapping.findForward("Details");
367       }
368       // This should not happen...
369       return null;
370    }
371 
372    /**
373     * Update the consumers definitions collection within request.
374     * @param request The servlet container request wrapper
375     * @throws Exception if consumers cannot be refreshed
376     */
377    protected void updateConsumersInRequest(HttpServletRequest request) throws Exception{
378       if (manager != null){
379          // Use local manager.
380          request.setAttribute(CONSUMERS_KEY, manager.getConsumerBeanInfos());
381       }
382       else if (service != null){
383          // Use remote service (require login, logout).
384          String token = loginToRemoteService(request);
385          request.setAttribute(CONSUMERS_KEY, service.getConsumerBeanInfos(token));
386          logoutFromRemoteService(token);
387       }
388    }
389 
390    /**
391     * Initialize the local consumer manager or the remote service depending
392     * on the application setup and the application side we are on.
393     * @throws Exception if manager cannot be found or remote service is not available
394     */
395    protected void initializeManagerOrService() throws Exception{
396       if (manager == null && service == null){
397          BootstrapManager bootstrapManager = BootstrapUtil.getBootstrapManager();
398          // Use remote service only if we are on synchronous side of a dissociate setup.
399          if (bootstrapManager.isDissociatedSetup() && bootstrapManager.isSynchronousSide()){
400             String url = bootstrapManager.getOtherSideUrl() + "/remoting/hessian/MessagingService";
401             log.info("Connecting to remote MessagingService using url: " + url);
402             HessianProxyFactory proxyFactory = new HessianProxyFactory();
403             service = (MessagingService)proxyFactory.create(MessagingService.class, url);
404          }
405          else{
406             // Use local manager provided by container facility.
407             log.info("Looking up local JMSConsumerBeanManager using 'jmsConsumerBeanManager' component");
408             ContainerContextHandler handler = ContainerContextHandler.getInstance();
409             manager = (JMSConsumerBeanManager)handler.getComponent("jmsConsumerBeanManager");
410          }
411       }
412    }
413 
414 
415    // Private ------------------------------------------------------------------
416 
417    /** Login for using remote service. */
418    private String loginToRemoteService(HttpServletRequest request) throws InvalidLoginException, RemoteException{
419       // Extract user and its clear password from request.
420       User user = getUserContainer(request).getView().getUser();
421       String pwd = getUserContainer(request).getView().getClearPassword();
422       // Logon to remote service, get a token.
423       String token = service.login(user.getLogin(), pwd);
424       return token;
425    }
426 
427    /** Logout from remote service. */
428    private void logoutFromRemoteService(String token) throws RemoteException{
429       service.logout(token);
430    }
431 }