View Javadoc

1   /**
2    * Copyright 2005-2007 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.ResourceForm;
19  import org.figure8.join.core.InfrastructureException;
20  import org.figure8.join.core.DuplicateEntityException;
21  import org.figure8.join.businessobjects.environment.Resource;
22  import org.figure8.join.businessobjects.environment.AbstractResource;
23  import org.figure8.join.businessobjects.environment.AbstractResourceType;
24  import org.figure8.join.businessobjects.environment.Machine;
25  import org.figure8.join.businessfacades.environment.ResourceManager;
26  import org.figure8.join.util.LogUtil;
27  
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.beanutils.PropertyUtils;
30  import org.apache.struts.action.ActionForm;
31  import org.apache.struts.action.ActionMapping;
32  import org.apache.struts.action.ActionForward;
33  
34  import javax.servlet.http.HttpSession;
35  import javax.servlet.http.HttpServletRequest;
36  import javax.servlet.http.HttpServletResponse;
37  
38  import java.util.List;
39  import java.lang.reflect.Constructor;
40  /**
41   * This is a Struts action for managing all operations related to AbstractResource entities.
42   * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
43   * @version $Revision: 1.2 $
44   *
45   * @struts.action path="/resource" name="resourceForm"
46   *                scope="request" parameter="op" validate="true"
47   *                input="/pages/mainpage.jsp?body=/jsp/environment/resources.jsp"
48   * @struts.action-forward name="Resources" path="/jsp/environment/resources.jsp"
49   */
50  public class ResourceActions extends JoinAction{
51     
52     // Static -------------------------------------------------------------------
53     
54     /** Get a commons logger. */
55     private static final Log log = LogUtil.getLog(ResourceActions.class);
56  
57     /** Operation code for showing an empty resource creation form */
58     public static final String FORM_OP = "form";
59     /** Operation code for loading a specified Resource */
60     public static final String LOAD_OP = "load";
61     /** Operation code for saving (create or update) a specified Resource */
62     public static final String SAVE_OP = "save";
63     /** Operation code for searching resources using their type */
64     public static final String SEARCH_OP = "search";
65     /** Operation code for getting resource configuration details at specified date */
66     public static final String CONFIG_OP = "config";
67     /** Operation code for getting resource configuration changes for tracking period */
68     public static final String CHANGES_OP = "changes";
69  
70     /**
71      * The session scope attribute under which the Resource object
72      * currently selected by our logged-in User is stored.
73      */
74     public static final String RESOURCE_KEY = "resource";
75     /**
76      * The request scope attribute under which the retrieved Resources
77      * list is stored.
78      */
79     public static final String RESOURCES_KEY = "resources";
80     /**
81      * The request scope attribute under which is stored the Resource that
82      * has raised a DuplicateEntityException during save of another one.
83      */
84     public static final String DUPLICATE_RESOURCE_KEY = "duplicate";
85  
86  
87     // Attributes ---------------------------------------------------------------
88  
89     /** The ResourceManager to use */
90     private ResourceManager resourceManager = null;
91  
92  
93     // Constructors -------------------------------------------------------------
94     
95     /** Creates a new instance of ResourceActions */
96     public ResourceActions(){
97     }
98   
99     
100    // Public -------------------------------------------------------------------
101 
102    /** @param manager The ResourceManager to use */
103    public void setResourceManager(ResourceManager manager){
104       this.resourceManager = manager;
105    }
106 
107    /**
108     * Create a new resource instance from informations contained into ResourceForm.
109     * This is a hook to allow subclasses treating specific resource categories. This implementation
110     * maskes 1 assumption : Resource implementation needs to have a constructor with 2 parameters
111     * (the resource name and the resource type object).
112     * @param form The ResourceForm (or a subclass) to create persistent resource from
113     * @return The persistent AbstractResourceType corresponding to given form
114     */
115    public AbstractResource createResourceInstance(ResourceForm form){
116       String classStr = ResourceForm.getSupportedImplementation(form.getCategory());
117       AbstractResourceType type = (AbstractResourceType)resourceManager.getResourceType(form.getResourceTypeKey());
118 
119       try{
120          Class clazz = Thread.currentThread().getContextClassLoader().loadClass(classStr);
121          Class typeClazz = Thread.currentThread().getContextClassLoader().loadClass(classStr + "Type");
122          Constructor constructor = clazz.getDeclaredConstructor(new Class[]{String.class, typeClazz});
123          return (AbstractResource)constructor.newInstance(new Object[]{form.getName(), type});
124       }
125       catch (ClassNotFoundException cnfe){
126          // Log and wrap this into infrastructure exception.
127          log.error("ClassNotFoundException while trying to load " + classStr + " class");
128          log.error("Check your supported resource categories...");
129          throw new InfrastructureException("Unable to load specified resource category", cnfe);
130       }
131       catch (NoSuchMethodException nsme){
132          // Log and wrap this into infrastructure exception.
133          log.error("NoSuchMethodException while trying to get " + classStr + " constructor");
134          log.error("Check your supported resource categories...");
135          throw new InfrastructureException("Unable to create specified resource category", nsme);
136       }
137       catch (Exception e){
138          // Log and wrap this into infrastructure exception.
139          log.error("Unexpected exception while trying to create a " + classStr + " instance");
140          log.error("Here'svthe detailed error message: " + e.getMessage());
141          throw new InfrastructureException("Unexpected exception while trying to create a resource", e);
142       }
143    }
144 
145 
146    // Implementation of JoinAction ---------------------------------------------
147    
148    /**
149     *
150     * @param operation String representing the operation to invoke on Action
151     * @param mapping Mapping between forwards name and path for this action
152     * @param form The form object containing request parameters
153     * @param request The servlet container request wrapper
154     * @param response The servlet container response wrapper
155     * @return A forward to the next view to render and display
156     * @throws Exception such as InfrastructureExceptions...
157     */
158    public ActionForward doExecute(String operation, ActionMapping mapping, ActionForm form,
159                                   HttpServletRequest request, HttpServletResponse response) throws Exception{
160       // Trace operation to execute.
161       log.debug("doExecute() called for '" + operation + "' operation");
162 
163       // Common : we always need types list.
164       List resourceTypes = resourceManager.getResourceTypes(request.getParameter("category"));
165       request.setAttribute(ResourceTypeActions.RESOURCE_TYPES_KEY, resourceTypes);
166 
167       if (FORM_OP.equals(operation)){
168          return showResourceForm(mapping, form, request, response);
169       }
170       else if (LOAD_OP.equals(operation)){
171          return loadResource(mapping, form, request, response);
172       }
173       else if (SAVE_OP.equals(operation)){
174          return saveResource(mapping, form, request, response);
175       }
176       else if (SEARCH_OP.equals(operation)){
177          // Remove form and session attribute if present.
178          request.getSession().removeAttribute(RESOURCE_KEY);
179          removeObsoleteForm(mapping, request);
180          return searchResources(mapping, form, request, response);
181       }
182       else{
183          // Default : empty resources management page.
184          request.getSession().removeAttribute(RESOURCE_KEY);
185          return mapping.findForward("Resources");
186       }
187    }
188 
189 
190    // Protected ----------------------------------------------------------------
191 
192    /**
193     * Prepare all we need for displaying a resource creation form
194     * @return A forward to the next view to render and display
195     */
196    protected ActionForward showResourceForm(ActionMapping mapping, ActionForm form,
197                                             HttpServletRequest request, HttpServletResponse response) throws Exception{
198       // Store into requets the list of machines for hosting new resource.
199       request.setAttribute(MachineActions.MACHINES_KEY, resourceManager.getMachines());
200       return searchResources(mapping, form, request, response);
201    }
202 
203    /**
204     * Load a specified resource from datastore and fill form with it.
205     * @return A forward to the next view to render and display
206     */
207    protected ActionForward loadResource(ActionMapping mapping, ActionForm form,
208                                         HttpServletRequest request, HttpServletResponse response) throws Exception{
209       if (form instanceof ResourceForm){
210          // Get the request resource from manager.
211          ResourceForm rForm = (ResourceForm)form;
212          Resource resource = resourceManager.getResource(rForm.getId());
213 
214          // Store resource within session.
215          HttpSession session = request.getSession();
216          session.setAttribute(RESOURCE_KEY, resource);
217          // Copy resource into form proeprties.
218          PropertyUtils.copyProperties(rForm, resource);
219          rForm.setResourceTypeKey(resource.getResourceType().getKey());
220 
221          // Add machines and resources list before forwarding.
222          request.setAttribute(MachineActions.MACHINES_KEY, resourceManager.getMachines());
223          return searchResources(mapping, form, request, response);
224       }
225       // This should not happen...
226       return null;
227    }
228 
229    /**
230     * Save a resource into datastore. The resource may be an already existing
231     * one or a new one (this is indeed a create or update method).
232     * @return A forward to the next view to render and display
233     */
234    protected ActionForward saveResource(ActionMapping mapping, ActionForm form,
235                                         HttpServletRequest request, HttpServletResponse response) throws Exception{
236       if (form instanceof ResourceForm){
237          ResourceForm rForm = (ResourceForm)form;
238 
239          // Is there a resource to update in session ?
240          HttpSession session = request.getSession();
241          AbstractResource resource = (AbstractResource)session.getAttribute(RESOURCE_KEY);
242 
243          // Create a new resource or popultate existing with form.
244          if (resource == null){
245             log.info("Creation of a new Resource with name: " + rForm.getName());
246             resource = createResourceInstance(rForm);
247             resource.setLogDirPath(rForm.getLogDirPath());
248             resource.setLogFilePath(rForm.getLogFilePath());
249          }
250          else{
251             log.info("Update of existing Resource having name: " + rForm.getName());
252             PropertyUtils.copyProperties(resource, rForm);
253          }
254          // Care about hosting machine if specified.
255          if (rForm.getMachineId() != -1){
256             Machine machine = resourceManager.getMachine(rForm.getMachineId());
257             resource.setMachine(machine);
258             machine.addHostedResource(resource);
259          }
260          // Save resource using manager.
261          try {resourceManager.saveResource(resource);}
262          catch (DuplicateEntityException dee){
263             // Store exception within request.
264             request.setAttribute(DUPLICATE_RESOURCE_KEY, dee);
265             return searchResources(mapping, form, request, response);
266          }
267 
268          // Remove form and session attribute if present.
269          session.removeAttribute(RESOURCE_KEY);
270          removeObsoleteForm(mapping, request);
271 
272          // Add resources list before forwarding.
273          return searchResources(mapping, form, request, response);
274       }
275       // This should not happen...
276       return null;
277    }
278 
279    /**
280     * Retrieve a list of Resources using the resource type criteria.
281     * @return A forward to the next view to render and display
282     */
283    protected ActionForward searchResources(ActionMapping mapping, ActionForm form,
284                                            HttpServletRequest request, HttpServletResponse response) throws Exception{
285       if (form instanceof ResourceForm){
286          ResourceForm rForm = (ResourceForm)form;
287 
288          // Retrieve all the resources we need.
289          AbstractResourceType resourceType = (AbstractResourceType)resourceManager.getResourceType(
290                                                                                        rForm.getResourceTypeKey());
291          List resources = resourceManager.getResources(resourceType);
292 
293          // Store them into request attributes before forwarding.
294          request.setAttribute(RESOURCES_KEY, resources);
295          request.setAttribute("resourceTypeKey", rForm.getResourceTypeKey());
296          return mapping.findForward("Resources");
297       }
298       // This should not happen...
299       return null;
300    }
301 }