View Javadoc

1   package org.whatsitcalled.webflange.webapp;
2   
3   import java.io.IOException;
4   import java.io.InputStream;
5   import java.util.List;
6   
7   import org.apache.commons.io.IOUtils;
8   import org.apache.log4j.Logger;
9   import org.apache.wicket.AttributeModifier;
10  import org.apache.wicket.Page;
11  import org.apache.wicket.PageParameters;
12  import org.apache.wicket.ajax.AjaxRequestTarget;
13  import org.apache.wicket.ajax.markup.html.AjaxLink;
14  import org.apache.wicket.behavior.SimpleAttributeModifier;
15  import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
16  import org.apache.wicket.markup.html.basic.Label;
17  import org.apache.wicket.markup.html.form.ChoiceRenderer;
18  import org.apache.wicket.markup.html.form.DropDownChoice;
19  import org.apache.wicket.markup.html.form.Form;
20  import org.apache.wicket.markup.html.form.RequiredTextField;
21  import org.apache.wicket.markup.html.form.TextArea;
22  import org.apache.wicket.markup.html.form.TextField;
23  import org.apache.wicket.markup.html.link.BookmarkablePageLink;
24  import org.apache.wicket.markup.html.link.Link;
25  import org.apache.wicket.markup.html.panel.Panel;
26  import org.apache.wicket.markup.repeater.Item;
27  import org.apache.wicket.markup.repeater.data.DataView;
28  import org.apache.wicket.markup.repeater.data.IDataProvider;
29  import org.apache.wicket.model.AbstractReadOnlyModel;
30  import org.apache.wicket.model.CompoundPropertyModel;
31  import org.apache.wicket.model.IModel;
32  import org.apache.wicket.model.Model;
33  import org.apache.wicket.model.PropertyModel;
34  import org.whatsitcalled.webflange.ResourceFactory;
35  import org.whatsitcalled.webflange.model.LoadTest;
36  import org.whatsitcalled.webflange.model.LoadTestDAO;
37  import org.whatsitcalled.webflange.model.ProjectDAO;
38  import org.whatsitcalled.webflange.model.Script;
39  import org.whatsitcalled.webflange.model.ScriptDAO;
40  import org.whatsitcalled.webflange.service.LoadTestRunningException;
41  import org.whatsitcalled.webflange.webapp.model.LoadTestDataProvider;
42  
43  public class TestPanel extends Panel {
44  	AddTestForm testForm;
45  
46  	private static final Logger LOGGER = Logger.getLogger(TestPanel.class);
47  
48  	public TestPanel(String id) {
49  		super(id);
50  		// Add the test list
51  		add(new Link("newTest") {
52  			public void onClick() {
53  				testForm.setVisible(true);
54  				setTest(getNewLoadTest());
55  			}
56  		});
57  
58  		add(new TestDataView("tests", new LoadTestDataProvider()));
59  
60  		// add the Test Form
61  		testForm = new AddTestForm("addTestForm", new CompoundPropertyModel(
62  				getTest()));
63  		testForm.setVisible(false);
64  		add(testForm);
65  	}
66  
67  	private LoadTest getTest() {
68  		LoadTest test = (LoadTest) getModelObject();
69  		if (test == null) {
70  			test = getNewLoadTest();
71  			setTest(test);
72  		}
73  		return test;
74  	}
75  
76  	private void setTest(LoadTest test) {
77  		setModel(new CompoundPropertyModel(test));
78  	}
79  
80  	public void onModelChanged() {
81  		if ((testForm != null) && this.getModel() != null) {
82  			testForm.setModel(this.getModel());
83  		}
84  	}
85  
86  	public static final LoadTest getLoadTestForEditing(LoadTest test) {
87  		LoadTest loadTest = ResourceFactory.getLoadTestDAO().getLoadTest(test.getId());
88  		loadTest.setEnabled(false);
89  		ResourceFactory.getLoadTestDAO().saveLoadTest(loadTest);
90  		
91  		return loadTest;
92  	}
93  	
94  	//TODO Need a RUNNING column, and auto refresh if not editing
95  	protected final class TestDataView extends DataView {
96  		protected TestDataView(String arg0, IDataProvider arg1) {
97  			super(arg0, arg1);
98  		}
99  
100 		protected void populateItem(final Item item) {
101 			final LoadTest test = (LoadTest) item.getModelObject();
102 			
103 			//Edit function
104 			item.add(new Link("edit") {
105 				public void onClick() {
106 					testForm.setVisible(true);
107 					LoadTest test = (LoadTest) getParent().getModelObject();
108 					setTest(getLoadTestForEditing(test));
109 					// refreshTests();
110 				}
111 			});
112 			
113 			//Enable/Diable function
114 			Link enableLink = new Link("enable") {
115 				public void onClick() {
116 					LoadTest test = (LoadTest) getParent().getModelObject();
117 					if (test.getEnabled()) {
118 						LOGGER.debug("Disabling LoadTest: " + test.getName());
119 						test.setEnabled(false);
120 					} else {
121 						LOGGER.debug("Enabling LoadTest: " + test.getName());
122 						test.setEnabled(true);
123 					}
124 					ResourceFactory.getLoadTestDAO().saveLoadTest(test);
125 				}
126 			};
127 			enableLink.add(new Label("enable/disable", new Model() {
128 				public Object getObject() {
129 					return test.getEnabled() ? "disable" : "enable";
130 				}
131 			}));
132 			item.add(enableLink);
133 
134 			//Delete Function
135 			Link deleteLink = new Link("delete") {
136 				public void onClick() {
137 					LoadTest test = (LoadTest) getParent().getModelObject();
138 					try {
139 						ResourceFactory.getLoadTestService().removeLoadTest(test.getId());
140 					} catch (LoadTestRunningException e) {
141 						LOGGER.error("Unable to delete test.");
142 						error(test.getName() + " is enabled or running and cannot be deleted!");
143 					}
144 				}
145 			};
146 			deleteLink.add(new SimpleAttributeModifier(
147 				      "onclick", "return confirm('Delete test " + test.getName() + "?');"));
148 			
149 			item.add(deleteLink);
150 			
151 			//Run now function
152 			Link runLink = new Link("runNow") {
153 				public void onClick() {
154 					LoadTest test = (LoadTest) getParent().getModelObject();
155 					ResourceFactory.getGrinderTestRunner().runAsThread(test);
156 				}
157 			};
158 			runLink.add(new SimpleAttributeModifier(
159 				      "onclick", "return confirm('Run test " + test.getName() + "?');"));
160 			item.add(runLink);
161 
162 			//Reports link
163 			item.add(new BookmarkablePageLink("results", HomePage.class, new PageParameters("testId=" + test.getId())));
164 			
165 			item.add(new Label("project", test.getProjectName()));
166 			item.add(new Label("test", test.getName()));
167 			item.add(new Label("script", test.getScriptName()));
168 			item.add(new Label("frequency", test.getFrequency()));
169 
170 			item.add(new AttributeModifier("class", true,
171 					new AbstractReadOnlyModel() {
172 						public Object getObject() {
173 							return (item.getIndex() % 2 == 1) ? "even" : "odd";
174 						}
175 					}));
176 		}
177 	}
178 
179 	protected final class AddTestForm extends Form {
180 		/**
181 		 * Constructor
182 		 * 
183 		 * @param id
184 		 *            The name of this component
185 		 */
186 		public AddTestForm(final String id, IModel model) {
187 			// Check if we have a LoadTest in the parents modelobject
188 			// Construct form with no validation listener
189 			super(id, model);
190 			add(getProjectChooser());
191 			add(new RequiredTextField("name"));
192 			addScriptView();
193 			add(getScriptChooser());
194 			TextField cronTextField = new TextField("frequency");
195 			//cronTextField.setRequired(true);
196 			cronTextField.add(new CronValidator("Invalid cron expression in Frequency field."));
197 			add(cronTextField);
198 			add(new Label("contextVars", getContextVars()));
199 			add(new TextArea("properties"));
200 			add(new TextArea("description"));
201 
202 			final ModalWindow cronHelp;
203 			add(cronHelp = new ModalWindow("cronHelp"));
204 
205 			cronHelp.setContent(new CronHelpPanel(cronHelp.getContentId()));
206 			cronHelp.setTitle("Cron Expressions");
207 			cronHelp.setCookieName("cronHelp");
208 
209 			add(new AjaxLink("showCronHelp") {
210 				public void onClick(AjaxRequestTarget target) {
211 					cronHelp.show(target);
212 				}
213 			});
214 
215 		}
216 
217 		private void addScriptView() {
218 			// View Script Modal Window stuff
219 			final ModalWindow viewScript = new ModalWindow("viewScript");
220 
221 			add(viewScript);
222 
223 			add(new AjaxLink("showScript") {
224 				public void onClick(AjaxRequestTarget target) {
225 					final Script script = getTest().getScript();
226 					viewScript.setTitle(script.getName());
227 					viewScript.setCookieName("viewScript");
228 					viewScript.setPageMapName("viewScript");
229 
230 					viewScript.setPageCreator(new ModalWindow.PageCreator() {
231 						public Page createPage() {
232 							return new ScriptViewPage(script, viewScript);
233 						}
234 					});
235 					viewScript.show(target);
236 				}
237 			});			
238 		}
239 
240 		private DropDownChoice getProjectChooser() {
241 			ProjectDAO dao = ResourceFactory.getProjectDAO();
242 			List projects = dao.getProjects();
243 			DropDownChoice ddc = new DropDownChoice("project",
244 					new PropertyModel(getModelObject(), "project"), projects,
245 					new ChoiceRenderer("name", "id"));
246 			ddc.add(new ChoiceRequiredValidator("You must select a project."));
247 			return ddc;
248 		}
249 
250 		private DropDownChoice getScriptChooser() {
251 			ScriptDAO dao = ResourceFactory.getScriptDAO();
252 			List scripts = dao.getScripts();
253 			DropDownChoice ddc = new DropDownChoice("script",
254 					new PropertyModel(getModelObject(), "script"), scripts,
255 					new ChoiceRenderer("name", "id"));
256 			ddc.add(new ChoiceRequiredValidator("You must select a script."));
257 			return ddc;
258 		}
259 
260 		/**
261 		 * Show the resulting valid edit
262 		 */
263 		public final void onSubmit() {
264 			final LoadTest test = (LoadTest) getModelObject();
265 			LoadTestDAO dao = ResourceFactory.getLoadTestDAO();
266 			dao.saveLoadTest(test);
267 			this.setModel(new CompoundPropertyModel(getNewLoadTest()));
268 			this.setVisible(false);
269 
270 		}
271 
272 		@Override
273 		protected void onModelChanged() {
274 			super.onModelChanged();
275 			// Dropdown choice acts funny unless we remove it and add it back
276 			
277 			remove("project");
278 			add(getProjectChooser());
279 			remove("script");
280 			add(getScriptChooser());
281 		}
282 		
283 		private String getContextVars() {
284 			List<String> vars = ResourceFactory.getGrinderTestRunner().getContextVars();
285 			StringBuffer buf = new StringBuffer();
286 			for(String var:vars) {
287 				buf.append("${");
288 				buf.append(var);
289 				buf.append("}\n");
290 			}
291 			//TODO It would be great to have a module for context variables that has defaults configured via spring, but allows other vars to be set at a global level
292 			
293 			return buf.toString();
294 		}
295 	}
296 
297 	protected class CronHelpPanel extends Panel {
298 
299 		public CronHelpPanel(String arg0) {
300 			super(arg0);
301 			// TODO Auto-generated constructor stub
302 		}
303 	}
304 	
305 	LoadTest getNewLoadTest() {
306 			return ResourceFactory.getLoadTestService().createLoadTest();
307 	}
308 	
309 }