KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jmeter > testbeans > gui > TestBeanGUI


1 // $Header: /home/cvs/jakarta-jmeter/src/core/org/apache/jmeter/testbeans/gui/TestBeanGUI.java,v 1.14.2.1 2004/09/26 14:48:41 sebb Exp $
2
/*
3  * Copyright 2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.jmeter.testbeans.gui;
18
19 import java.awt.BorderLayout JavaDoc;
20 import java.awt.Component JavaDoc;
21 import java.beans.BeanInfo JavaDoc;
22 import java.beans.Customizer JavaDoc;
23 import java.beans.IntrospectionException JavaDoc;
24 import java.beans.Introspector JavaDoc;
25 import java.beans.PropertyDescriptor JavaDoc;
26 import java.beans.PropertyEditorManager JavaDoc;
27 import java.util.Arrays JavaDoc;
28 import java.util.Collection JavaDoc;
29 import java.util.HashMap JavaDoc;
30 import java.util.LinkedList JavaDoc;
31 import java.util.List JavaDoc;
32 import java.util.Map JavaDoc;
33
34 import javax.swing.JPopupMenu JavaDoc;
35
36 import org.apache.commons.collections.LRUMap;
37 import org.apache.jmeter.assertions.Assertion;
38 import org.apache.jmeter.config.ConfigElement;
39 import org.apache.jmeter.control.Controller;
40 import org.apache.jmeter.gui.AbstractJMeterGuiComponent;
41 import org.apache.jmeter.gui.JMeterGUIComponent;
42 import org.apache.jmeter.gui.util.MenuFactory;
43 import org.apache.jmeter.processor.PostProcessor;
44 import org.apache.jmeter.processor.PreProcessor;
45 import org.apache.jmeter.samplers.Sampler;
46 import org.apache.jmeter.testbeans.TestBean;
47 import org.apache.jmeter.testelement.TestElement;
48 import org.apache.jmeter.testelement.property.BooleanProperty;
49 import org.apache.jmeter.testelement.property.DoubleProperty;
50 import org.apache.jmeter.testelement.property.FloatProperty;
51 import org.apache.jmeter.testelement.property.IntegerProperty;
52 import org.apache.jmeter.testelement.property.JMeterProperty;
53 import org.apache.jmeter.testelement.property.LongProperty;
54 import org.apache.jmeter.testelement.property.NullProperty;
55 import org.apache.jmeter.testelement.property.PropertyIterator;
56 import org.apache.jmeter.testelement.property.StringProperty;
57 import org.apache.jmeter.testelement.property.TestElementProperty;
58 import org.apache.jmeter.timers.Timer;
59 import org.apache.jmeter.util.JMeterUtils;
60 import org.apache.jmeter.visualizers.Visualizer;
61 import org.apache.jorphan.logging.LoggingManager;
62 import org.apache.log.Logger;
63
64 /**
65  * JMeter GUI element editing for TestBean elements.
66  * <p>
67  * The actual GUI is always a bean customizer: if the bean descriptor provides
68  * one, it will be used; otherwise, a GenericTestBeanCustomizer will be
69  * created for this purpose.
70  * <p>
71  * Those customizers deviate from the standards only in that, instead of a
72  * bean, they will receive a Map in the setObject call. This will be a property
73  * name to value Map. The customizer is also in charge of initializing empty
74  * Maps with sensible initial values.
75  * <p>
76  * If the provided Customizer class implements the SharedCustomizer
77  * interface, the same instance of the customizer will be reused for all
78  * beans of the type: setObject(map) can then be called multiple times.
79  * Otherwise, one separate instance will be used for each element.
80  * For efficiency reasons, most customizers should implement
81  * SharedCustomizer.
82  *
83  * @version $Revision: 1.14.2.1 $ updated on $Date: 2004/09/26 14:48:41 $
84  */

85 public class TestBeanGUI
86     extends AbstractJMeterGuiComponent
87     implements JMeterGUIComponent
88 {
89     private static Logger log = LoggingManager.getLoggerForClass();
90
91     private Class JavaDoc testBeanClass;
92     
93     private BeanInfo JavaDoc beanInfo;
94
95     private Class JavaDoc customizerClass;
96
97     /**
98      * The single customizer if the customizer class implements
99      * SharedCustomizer, null otherwise.
100      */

101     private Customizer JavaDoc customizer= null;
102
103     /**
104      * TestElement to Customizer map if customizer is null. This is necessary to avoid
105      * the cost of creating a new customizer on each edit. The cache size needs to be
106      * limited, though, to avoid memory issues when editing very large test plans.
107      */

108     private Map JavaDoc customizers= new LRUMap(20);
109
110     /**
111      * Index of the customizer in the JPanel's child component list:
112      */

113     private int customizerIndexInPanel;
114     
115     /**
116      * The property name to value map that the active customizer
117      * edits:
118      */

119     private Map JavaDoc propertyMap= new HashMap JavaDoc();
120
121     /**
122      * Whether the GUI components have been created.
123      */

124     private boolean initialized= false;
125
126     static
127     {
128         List JavaDoc paths= new LinkedList JavaDoc();
129         paths.add("org.apache.jmeter.testbeans.gui");
130         paths.addAll(Arrays.asList(PropertyEditorManager.getEditorSearchPath()));
131         String JavaDoc s= JMeterUtils.getPropDefault("propertyEditorSearchPath", null) ;
132         if (s != null)
133         {
134             paths.addAll(Arrays.asList(JMeterUtils.split(s, ",", "")));
135         }
136         PropertyEditorManager.setEditorSearchPath((String JavaDoc[])paths.toArray(new String JavaDoc[0]));
137     }
138
139     // Dummy for JUnit test
140
public TestBeanGUI()
141     {
142         log.warn("Only for use in testing");
143     }
144     
145     public TestBeanGUI(Class JavaDoc testBeanClass)
146     {
147         super();
148         
149         // A quick verification, just in case:
150
if (! TestBean.class.isAssignableFrom(testBeanClass))
151         {
152             Error JavaDoc e= new Error JavaDoc();
153             log.error("This should never happen!", e);
154             throw e; // Programming error: bail out.
155
}
156
157         this.testBeanClass= testBeanClass;
158                 
159         // Get the beanInfo:
160
try
161         {
162             beanInfo= Introspector.getBeanInfo(testBeanClass);
163         }
164         catch (IntrospectionException JavaDoc e)
165         {
166             log.error("Can't get beanInfo for "+testBeanClass.getName(),
167                 e);
168             throw new Error JavaDoc(e.toString()); // Programming error. Don't continue.
169
}
170
171         customizerClass= beanInfo.getBeanDescriptor().getCustomizerClass();
172
173         // Creation of the customizer and GUI initialization is delayed until the first
174
// configure call. We don't need all that just to find out the static label, menu
175
// categories, etc!
176
initialized= false;
177     }
178
179     private Customizer JavaDoc createCustomizer()
180     {
181         try
182         {
183             return (Customizer JavaDoc)customizerClass.newInstance();
184         }
185         catch (InstantiationException JavaDoc e)
186         {
187             log.error("Could not instantiate customizer of class "+customizerClass, e);
188             throw new Error JavaDoc(e.toString());
189         }
190         catch (IllegalAccessException JavaDoc e)
191         {
192             log.error("Could not instantiate customizer of class "+customizerClass, e);
193             throw new Error JavaDoc(e.toString());
194         }
195     }
196
197     /* (non-Javadoc)
198      * @see org.apache.jmeter.gui.JMeterGUIComponent#getStaticLabel()
199      */

200     public String JavaDoc getStaticLabel()
201     {
202         if (beanInfo == null) return "null";
203         return beanInfo.getBeanDescriptor().getDisplayName();
204     }
205
206     /* (non-Javadoc)
207      * @see org.apache.jmeter.gui.JMeterGUIComponent#createTestElement()
208      */

209     public TestElement createTestElement()
210     {
211         try
212         {
213             TestElement element= (TestElement)testBeanClass.newInstance();
214             configure(element);
215             super.clear(); // set name, enabled.
216
configureTestElement(element);
217             modifyTestElement(element); // put the default values back into the new element
218
return element;
219         }
220         catch (InstantiationException JavaDoc e)
221         {
222             log.error("Can't create test element", e);
223             throw new Error JavaDoc(e.toString()); // Programming error. Don't continue.
224
}
225         catch (IllegalAccessException JavaDoc e)
226         {
227             log.error("Can't create test element", e);
228             throw new Error JavaDoc(e.toString()); // Programming error. Don't continue.
229
}
230     }
231
232     /* (non-Javadoc)
233      * @see org.apache.jmeter.gui.JMeterGUIComponent#modifyTestElement(org.apache.jmeter.testelement.TestElement)
234      */

235     public void modifyTestElement(TestElement element)
236     {
237         configureTestElement(element);
238         
239         // Copy all property values from the map into the element:
240
PropertyDescriptor JavaDoc[] props= beanInfo.getPropertyDescriptors();
241         for (int i=0; i<props.length; i++)
242         {
243             String JavaDoc name= props[i].getName();
244             Object JavaDoc value= propertyMap.get(name);
245             log.debug("Modify "+name+" to "+value);
246             if (value == null)
247             {
248                 element.removeProperty(name);
249             }
250             else
251             {
252                 JMeterProperty jprop= wrapInProperty(propertyMap.get(name));
253                 jprop.setName(name);
254                 element.setProperty(jprop);
255             }
256         }
257     }
258
259     /**
260      * Utility method to wrap an object in a property of an appropriate type.
261      * <p>
262      * I plan to get rid of this sooner than later, so please don't use it much.
263      *
264      * @param value Object to be wrapped.
265      * @return an unnamed property holding the provided value.
266      * @deprecated
267      */

268     private static JMeterProperty wrapInProperty(Object JavaDoc value)
269     {
270         // TODO: Awful, again...
271

272         if (value instanceof JMeterProperty)
273         {
274             return (JMeterProperty)value;
275         }
276         
277         JMeterProperty property;
278         if (value == null)
279         {
280             property= new NullProperty();
281         }
282         else if (value instanceof Boolean JavaDoc)
283         {
284             property= new BooleanProperty();
285         }
286         else if (value instanceof Double JavaDoc)
287         {
288             property= new DoubleProperty();
289         }
290         else if (value instanceof Float JavaDoc)
291         {
292             property= new FloatProperty();
293         }
294         else if (value instanceof Integer JavaDoc)
295         {
296             property= new IntegerProperty();
297         }
298         else if (value instanceof Long JavaDoc)
299         {
300             property= new LongProperty();
301         }
302         else if (value instanceof String JavaDoc)
303         {
304             property= new StringProperty();
305         }
306         else if (value instanceof TestElement)
307         {
308             property= new TestElementProperty();
309         }
310         else throw new Error JavaDoc("Ouch!");
311
312         property.setObjectValue(value);
313
314         return property;
315     }
316
317     /* (non-Javadoc)
318      * @see org.apache.jmeter.gui.JMeterGUIComponent#createPopupMenu()
319      */

320     public JPopupMenu JavaDoc createPopupMenu()
321     {
322         // TODO: this menu is too wide (allows, e.g. to add controllers, no matter the
323
// type of the element). Change to match the actual bean's capabilities.
324
if (Timer.class.isAssignableFrom(testBeanClass))//HACK: Fix one such problem
325
{
326             return MenuFactory.getDefaultTimerMenu();
327         }
328         return MenuFactory.getDefaultControllerMenu();
329     }
330
331     /* (non-Javadoc)
332      * @see org.apache.jmeter.gui.JMeterGUIComponent#configure(org.apache.jmeter.testelement.TestElement)
333      */

334     public void configure(TestElement element)
335     {
336         if (! initialized) init();
337
338         super.configure(element);
339
340         // Copy all property values into the map:
341
propertyMap.clear();
342         for (PropertyIterator jprops= element.propertyIterator(); jprops.hasNext(); )
343         {
344             JMeterProperty jprop= jprops.next();
345             propertyMap.put(jprop.getName(), jprop.getObjectValue());
346         }
347
348         if (customizer != null)
349         {
350             customizer.setObject(propertyMap);
351         }
352         else
353         {
354             if (initialized) remove(customizerIndexInPanel);
355             Customizer JavaDoc c= (Customizer JavaDoc)customizers.get(element);
356             if (c == null)
357             {
358                 c= createCustomizer();
359                 c.setObject(propertyMap);
360                 customizers.put(element, c);
361             }
362             add((Component JavaDoc)c, BorderLayout.CENTER);
363         }
364
365         initialized= true;
366     }
367
368     /* (non-Javadoc)
369      * @see org.apache.jmeter.gui.JMeterGUIComponent#getMenuCategories()
370      */

371     public Collection JavaDoc getMenuCategories()
372     {
373         List JavaDoc menuCategories= new LinkedList JavaDoc();
374
375         // We don't want to show expert beans in the menus unless we're
376
// in expert mode:
377
if (beanInfo.getBeanDescriptor().isExpert()
378             && ! JMeterUtils.isExpertMode())
379         {
380             return null;
381         }
382         
383         // TODO: there must be a nicer way...
384
if (Assertion.class.isAssignableFrom(testBeanClass))
385         {
386             menuCategories.add(MenuFactory.ASSERTIONS);
387         }
388         if (ConfigElement.class.isAssignableFrom(testBeanClass))
389         {
390             menuCategories.add(MenuFactory.CONFIG_ELEMENTS);
391         }
392         if (Controller.class.isAssignableFrom(testBeanClass))
393         {
394             menuCategories.add(MenuFactory.CONTROLLERS);
395         }
396         if (Visualizer.class.isAssignableFrom(testBeanClass))
397         {
398             menuCategories.add(MenuFactory.LISTENERS);
399         }
400         if (PostProcessor.class.isAssignableFrom(testBeanClass))
401         {
402             menuCategories.add(MenuFactory.POST_PROCESSORS);
403         }
404         if (PreProcessor.class.isAssignableFrom(testBeanClass))
405         {
406             menuCategories.add(MenuFactory.PRE_PROCESSORS);
407         }
408         if (Sampler.class.isAssignableFrom(testBeanClass))
409         {
410             menuCategories.add(MenuFactory.SAMPLERS);
411         }
412         if (Timer.class.isAssignableFrom(testBeanClass))
413         {
414             menuCategories.add(MenuFactory.TIMERS);
415         }
416         return menuCategories;
417     }
418     
419     private void init()
420     {
421         setLayout(new BorderLayout JavaDoc(0, 5));
422
423         setBorder(makeBorder());
424         add(makeTitlePanel(), BorderLayout.NORTH);
425
426         customizerIndexInPanel= getComponentCount();
427
428         if (customizerClass == null)
429         {
430             customizer= new GenericTestBeanCustomizer(beanInfo);
431         }
432         else if (SharedCustomizer.class.isAssignableFrom(customizerClass))
433         {
434             customizer= createCustomizer();
435         }
436         
437         if (customizer != null) add((Component JavaDoc)customizer, BorderLayout.CENTER);
438     }
439
440     /* (non-Javadoc)
441      * @see org.apache.jmeter.gui.JMeterGUIComponent#getLabelResource()
442      */

443     public String JavaDoc getLabelResource() {
444         // TODO Auto-generated method stub
445
return null;
446     }
447 }
448
Popular Tags