You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jmeter-dev@jakarta.apache.org by se...@apache.org on 2009/09/07 22:55:40 UTC

svn commit: r812274 - in /jakarta/jmeter/trunk: src/core/org/apache/jmeter/testbeans/ src/core/org/apache/jmeter/testbeans/gui/ src/jorphan/org/apache/jorphan/gui/ xdocs/

Author: sebb
Date: Mon Sep  7 20:55:39 2009
New Revision: 812274

URL: http://svn.apache.org/viewvc?rev=812274&view=rev
Log:
Add TestBean Table Editor support.
[code copied from branches/java1.5_prototype-was_trunk]

Added:
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java   (with props)
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java   (with props)
Modified:
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java
    jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java
    jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java
    jakarta/jmeter/trunk/xdocs/changes.xml

Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/BeanInfoSupport.java Mon Sep  7 20:55:39 2009
@@ -72,6 +72,8 @@
 
     public static final String NOT_OTHER = GenericTestBeanCustomizer.NOT_OTHER;
 
+    public static final String MULTILINE = "multiline";
+
     public static final String DEFAULT = GenericTestBeanCustomizer.DEFAULT;
 
     public static final String RESOURCE_BUNDLE = GenericTestBeanCustomizer.RESOURCE_BUNDLE;

Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/TestBeanHelper.java Mon Sep  7 20:55:39 2009
@@ -22,9 +22,16 @@
 import java.beans.PropertyDescriptor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedList;
 
+import org.apache.jmeter.testbeans.gui.TableEditor;
 import org.apache.jmeter.testelement.TestElement;
+import org.apache.jmeter.testelement.property.CollectionProperty;
 import org.apache.jmeter.testelement.property.JMeterProperty;
+import org.apache.jmeter.testelement.property.MultiProperty;
+import org.apache.jmeter.testelement.property.PropertyIterator;
+import org.apache.jmeter.testelement.property.TestElementProperty;
 import org.apache.jorphan.logging.LoggingManager;
 import org.apache.jorphan.util.Converter;
 import org.apache.log.Logger;
@@ -67,7 +74,7 @@
                 // Obtain a value of the appropriate type for this property.
                 JMeterProperty jprop = el.getProperty(desc[x].getName());
                 Class<?> type = desc[x].getPropertyType();
-                Object value = Converter.convert(jprop.getStringValue(), type);
+                Object value = unwrapProperty(desc[x], jprop, type);
 
                 if (log.isDebugEnabled()) {
                     log.debug("Setting " + jprop.getName() + "=" + value);
@@ -90,6 +97,54 @@
     }
 
     /**
+     * @param desc
+     * @param x
+     * @param jprop
+     * @param type
+     * @return
+     */
+    private static Object unwrapProperty(PropertyDescriptor desc, JMeterProperty jprop, Class<?> type) {
+        Object value;
+        if(jprop instanceof TestElementProperty)
+        {
+            TestElement te = ((TestElementProperty)jprop).getElement();
+            if(te instanceof TestBean)
+            {
+                prepare(te);
+            }
+            value = te;
+        }
+        else if(jprop instanceof MultiProperty)
+        {
+            value = unwrapCollection((MultiProperty)jprop,(String)desc.getValue(TableEditor.CLASSNAME));
+        }
+        else value = Converter.convert(jprop.getStringValue(), type);
+        return value;
+    }
+    
+    private static Object unwrapCollection(MultiProperty prop,String type)
+    {
+        if(prop instanceof CollectionProperty)
+        {
+            Collection<Object> values = new LinkedList<Object>();
+            PropertyIterator iter = prop.iterator();
+            while(iter.hasNext())
+            {
+                try
+                {
+                    values.add(unwrapProperty(null,iter.next(),Class.forName(type)));
+                }
+                catch(Exception e)
+                {
+                    log.error("Couldn't convert object: " + prop.getObjectValue() + " to " + type,e);
+                }
+            }
+            return values;
+        }
+        return null;
+    }
+
+    /**
      * Utility method that invokes a method and does the error handling around
      * the invocation.
      *
@@ -101,7 +156,7 @@
         try {
             return method.invoke(invokee, params);
         } catch (IllegalArgumentException e) {
-            log.error("This should never happen.", e);
+            log.error("This should never happen. "+invokee.getClass().getName()+" "+method.getName()+" "+params.length+" "+params[0].getClass().getName(), e);
             throw new Error(e.toString()); // Programming error: bail out.
         } catch (IllegalAccessException e) {
             log.error("This should never happen.", e);

Modified: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java (original)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/GenericTestBeanCustomizer.java Mon Sep  7 20:55:39 2009
@@ -220,6 +220,10 @@
                     log.debug("Editor for property " + name + " is wrapped in " + propertyEditor);
                 }
             }
+            if(propertyEditor instanceof TestBeanPropertyEditor)
+            {
+                ((TestBeanPropertyEditor)propertyEditor).setDescriptor(descriptors[i]);
+            }
             if (propertyEditor.getCustomEditor() instanceof JScrollPane) {
                 scrollerCount++;
             }

Added: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java?rev=812274&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java (added)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java Mon Sep  7 20:55:39 2009
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.testbeans.gui;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.beans.PropertyDescriptor;
+import java.beans.PropertyEditorSupport;
+import java.lang.reflect.Method;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import javax.swing.CellEditor;
+import javax.swing.JButton;
+import javax.swing.JComponent;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.TableModelEvent;
+import javax.swing.event.TableModelListener;
+
+import org.apache.jmeter.testelement.property.TestElementProperty;
+import org.apache.jmeter.util.JMeterUtils;
+import org.apache.jorphan.gui.ObjectTableModel;
+import org.apache.jorphan.logging.LoggingManager;
+import org.apache.jorphan.reflect.Functor;
+import org.apache.log.Logger;
+
+public class TableEditor extends PropertyEditorSupport implements FocusListener,TestBeanPropertyEditor,TableModelListener {
+	private static final Logger log = LoggingManager.getLoggerForClass();
+	
+	public static final String CLASSNAME = "tableObject.classname"; // $NON-NLS-1$
+	public static final String HEADERS = "table.headers"; // $NON-NLS-1$
+	public static final String OBJECT_PROPERTIES = "tableObject.properties"; // $NON-NLS-1$
+	
+	private JTable table;
+	private ObjectTableModel model;
+	private Class<?> clazz;
+	private PropertyDescriptor descriptor;
+	private final JButton addButton,removeButton,clearButton;
+
+	public TableEditor() {
+		addButton = new JButton(JMeterUtils.getResString("add")); // $NON-NLS-1$
+		addButton.addActionListener(new AddListener());
+		removeButton = new JButton(JMeterUtils.getResString("remove")); // $NON-NLS-1$
+		removeButton.addActionListener(new RemoveListener());
+		clearButton = new JButton(JMeterUtils.getResString("clear")); // $NON-NLS-1$
+		clearButton.addActionListener(new ClearListener());
+	}
+
+	@Override
+    public String getAsText() {
+		return null;
+	}
+
+	@Override
+    public Component getCustomEditor() {
+		JComponent pane = makePanel();
+		pane.doLayout();
+		pane.validate();
+		return pane;
+	}
+	
+	private JComponent makePanel()
+	{
+		JPanel p = new JPanel(new BorderLayout());
+		JScrollPane scroller = new JScrollPane(table);
+		scroller.setPreferredSize(scroller.getMinimumSize());
+		p.add(scroller,BorderLayout.CENTER);
+		JPanel south = new JPanel();
+		south.add(addButton);
+		south.add(removeButton);
+		south.add(clearButton);
+		p.add(south,BorderLayout.SOUTH);
+		return p;
+	}
+
+	@Override
+    public Object getValue() {
+		return model.getObjectList();
+	}
+
+	@Override
+    public void setAsText(String text) throws IllegalArgumentException {
+		//not interested in this method.		
+	}
+
+	@Override
+    public void setValue(Object value) {
+		if(value != null)
+		{
+			model.setRows(convertCollection((Collection<?>)value));
+		}
+		else model.clearData();
+		this.firePropertyChange();
+	}
+	
+	private Collection<Object> convertCollection(Collection<?> values)
+	{
+		List<Object> l = new LinkedList<Object>();
+		for(Object obj : values)
+		{
+			if(obj instanceof TestElementProperty)
+			{
+				l.add(((TestElementProperty)obj).getElement());
+			}
+			else
+			{
+				l.add(obj);
+			}
+		}
+		return l;
+	}
+
+	@Override
+    public boolean supportsCustomEditor() {
+		return true;
+	}
+
+	/**
+	 * For the table editor, the tag must simply be the name of the class of object it will hold 
+	 * where each row holds one object. 
+	 */
+	public void setDescriptor(PropertyDescriptor descriptor) {
+		try {
+			this.descriptor = descriptor;
+			clazz = Class.forName((String)descriptor.getValue(CLASSNAME));
+			initializeModel();
+		} catch (ClassNotFoundException e) {
+			throw new RuntimeException("The Table Editor requires one TAG be set - the name of the object to represent a row",e);
+		}
+	}
+	
+	void initializeModel()
+	{
+		if(clazz == String.class)
+		{
+			model = new ObjectTableModel((String[])descriptor.getValue(HEADERS),new Functor[0],new Functor[0],new Class[]{String.class});
+			model.addTableModelListener(this);
+		}
+		else
+		{
+			String[] props = (String[])descriptor.getValue(OBJECT_PROPERTIES);
+			Functor[] writers = new Functor[props.length];
+			Functor[] readers = new Functor[props.length];
+			Class<?>[] editors = new Class[props.length];
+			int count = 0;
+			for(String propName : props)
+			{
+				propName = propName.substring(0,1).toUpperCase() + propName.substring(1);
+				writers[count] = createWriter(clazz,propName);
+				readers[count] = createReader(clazz,propName);
+				editors[count] = getArgForWriter(clazz,propName);
+				count++;
+			}
+			model = new ObjectTableModel((String[])descriptor.getValue(HEADERS),readers,writers,editors);
+			model.addTableModelListener(this);
+		}
+		table = new JTable(model);
+		table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		table.addFocusListener(this);
+	}
+	
+	Functor createWriter(Class<?> c,String propName)
+	{
+		String setter = "set" + propName; // $NON-NLS-1$
+		return new Functor(setter);
+	}
+	
+	Functor createReader(Class<?> c,String propName)
+	{
+		String getter = "get" + propName; // $NON-NLS-1$
+		try
+		{
+			c.getMethod(getter,new Class[0]);
+			return new Functor(getter);
+		}
+		catch(Exception e) { return new Functor("is" + propName); }
+	}
+	
+	Class<?> getArgForWriter(Class<?> c,String propName)
+	{
+		String setter = "set" + propName; // $NON-NLS-1$
+		for(Method m : c.getMethods())
+		{
+			if(m.getName().equals(setter))
+			{
+				return m.getParameterTypes()[0];
+			}
+		}
+		return null;
+	}
+
+	public void tableChanged(TableModelEvent e) {
+		this.firePropertyChange();		
+	}
+
+	public void focusGained(FocusEvent e) {
+		
+	}
+
+	public void focusLost(FocusEvent e) {
+		CellEditor ce = table.getCellEditor(table.getEditingRow(),table.getEditingColumn());
+		Component editor = table.getEditorComponent();
+		if(ce != null && (editor == null || editor != e.getOppositeComponent()))
+		{
+			ce.stopCellEditing();
+		}
+		else if(editor != null)
+		{
+			editor.addFocusListener(this);
+		}
+		this.firePropertyChange();
+	}
+	
+	private class AddListener implements ActionListener
+	{
+		public void actionPerformed(ActionEvent e)
+		{
+			try
+			{
+				model.addRow(clazz.newInstance());
+			}catch(Exception err)
+			{
+				log.error("The class type given to TableEditor was not instantiable. ",err);
+			}
+		}
+	}
+	
+	private class RemoveListener implements ActionListener
+	{
+		public void actionPerformed(ActionEvent e)
+		{
+			model.removeRow(table.getSelectedRow());
+		}
+	}
+	
+	private class ClearListener implements ActionListener
+	{
+		public void actionPerformed(ActionEvent e)
+		{
+			model.clearData();
+		}
+	}
+
+}

Propchange: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TableEditor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Added: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java?rev=812274&view=auto
==============================================================================
--- jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java (added)
+++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java Mon Sep  7 20:55:39 2009
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package org.apache.jmeter.testbeans.gui;
+
+import java.beans.PropertyDescriptor;
+import java.beans.PropertyEditor;
+
+public interface TestBeanPropertyEditor extends PropertyEditor {
+	
+	public void setDescriptor(PropertyDescriptor descriptor);
+
+}

Propchange: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jakarta/jmeter/trunk/src/core/org/apache/jmeter/testbeans/gui/TestBeanPropertyEditor.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Modified: jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java (original)
+++ jakarta/jmeter/trunk/src/jorphan/org/apache/jorphan/gui/ObjectTableModel.java Mon Sep  7 20:55:39 2009
@@ -235,6 +235,7 @@
      *
      * @return false if at least one Functor cannot be found.
      */
+    @SuppressWarnings("deprecation")
     public boolean checkFunctors(Object _value, Class<?> caller){
         Object value;
         if (_value == null && objectClass != null) {
@@ -270,4 +271,16 @@
         }
         return status;
     }
+
+    public Object getObjectList() { // used by TableEditor
+        return objects;
+    }
+
+    public void setRows(Iterable<?> rows) { // used by TableEditor
+        clearData();
+        for(Object val : rows)
+        {
+            addRow(val);
+        }
+    }
 }

Modified: jakarta/jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=812274&r1=812273&r2=812274&view=diff
==============================================================================
--- jakarta/jmeter/trunk/xdocs/changes.xml (original)
+++ jakarta/jmeter/trunk/xdocs/changes.xml Mon Sep  7 20:55:39 2009
@@ -147,6 +147,7 @@
 
 <h2>Non-functional changes</h2>
 <ul>
+<li>Add TestBean Table Editor support</li>
 </ul>
 
 </section> 



---------------------------------------------------------------------
To unsubscribe, e-mail: jmeter-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: jmeter-dev-help@jakarta.apache.org