1 17 package org.apache.jmeter.testbeans.gui; 18 19 import java.awt.Component ; 20 import java.awt.GridBagConstraints ; 21 import java.awt.GridBagLayout ; 22 import java.awt.Insets ; 23 24 import java.beans.BeanInfo ; 25 import java.beans.PropertyChangeEvent ; 26 import java.beans.PropertyChangeListener ; 27 import java.beans.PropertyDescriptor ; 28 import java.beans.PropertyEditor ; 29 import java.beans.PropertyEditorManager ; 30 31 import java.text.MessageFormat ; 32 import java.util.Arrays ; 33 import java.util.Comparator ; 34 import java.util.Map ; 35 import java.util.MissingResourceException ; 36 import java.util.ResourceBundle ; 37 38 import javax.swing.BorderFactory ; 39 import javax.swing.Box ; 40 import javax.swing.JLabel ; 41 import javax.swing.JPanel ; 42 43 import org.apache.jmeter.util.JMeterUtils; 44 import org.apache.jorphan.logging.LoggingManager; 45 import org.apache.log.Logger; 46 47 100 public class GenericTestBeanCustomizer extends JPanel 101 implements SharedCustomizer, PropertyChangeListener 102 { 103 private static Logger log = LoggingManager.getLoggerForClass(); 104 105 public static final String GROUP= "group"; 106 public static final String ORDER= "order"; 107 public static final String TAGS= "tags"; 108 public static final String NOT_UNDEFINED= "notUndefined"; 109 public static final String NOT_EXPRESSION= "notExpression"; 110 public static final String NOT_OTHER= "notOther"; 111 public static final String DEFAULT= "default"; 112 public static final String RESOURCE_BUNDLE= "resourceBundle"; 113 public static final String ORDER(String group) { 114 return "group."+group+".order"; 115 } 116 117 public static final String DEFAULT_GROUP= ""; 118 119 122 private BeanInfo beanInfo; 123 124 127 private PropertyDescriptor [] descriptors; 128 129 133 private PropertyEditor [] editors; 134 135 138 private MessageFormat propertyFieldLabelMessage; 139 140 143 private MessageFormat propertyToolTipMessage; 144 145 148 private Map propertyMap; 149 150 156 GenericTestBeanCustomizer(BeanInfo beanInfo) 157 { 158 super(); 159 160 this.beanInfo= beanInfo; 161 162 descriptors= beanInfo.getPropertyDescriptors(); 164 Arrays.sort(descriptors, new PropertyComparator()); 165 166 editors= new PropertyEditor [descriptors.length]; 168 for (int i=0; i<descriptors.length; i++) 169 { 170 String name= descriptors[i].getName(); 171 172 if (descriptors[i].isHidden() 174 || (descriptors[i].isExpert() && ! JMeterUtils.isExpertMode()) 175 || descriptors[i].getReadMethod() == null 176 || descriptors[i].getWriteMethod() == null) 177 { 178 log.debug("No editor for property "+name); 179 editors[i]= null; 180 continue; 181 } 182 183 PropertyEditor propertyEditor; 184 Class editorClass= descriptors[i].getPropertyEditorClass(); 185 186 if (log.isDebugEnabled()) 187 { 188 log.debug("Property "+name 189 +" has editor class "+editorClass); 190 } 191 192 if (editorClass != null) 193 { 194 try 195 { 196 propertyEditor= (PropertyEditor )editorClass.newInstance(); 197 } 198 catch (InstantiationException e) 199 { 200 log.error("Can't create property editor.", e); 201 throw new Error (e.toString()); 202 } 203 catch (IllegalAccessException e) 204 { 205 log.error("Can't create property editor.", e); 206 throw new Error (e.toString()); 207 } 208 } 209 else 210 { 211 Class c= descriptors[i].getPropertyType(); 212 propertyEditor= PropertyEditorManager.findEditor(c); 213 } 214 215 if (log.isDebugEnabled()) 216 { 217 log.debug("Property "+name 218 +" has property editor "+propertyEditor); 219 } 220 221 if (propertyEditor == null) 222 { 223 log.debug("No editor for property "+name); 224 editors[i]= null; 225 continue; 226 } 227 228 if (! propertyEditor.supportsCustomEditor()) 229 { 230 propertyEditor= createWrapperEditor( 231 propertyEditor, descriptors[i]); 232 233 if (log.isDebugEnabled()) 234 { 235 log.debug("Editor for property "+name 236 +" is wrapped in "+propertyEditor); 237 } 238 } 239 240 editors[i]= propertyEditor; 241 242 setEditorValue(i, descriptors[i].getValue(DEFAULT)); 244 245 propertyEditor.addPropertyChangeListener(this); 248 } 249 250 propertyFieldLabelMessage= new MessageFormat ( 252 JMeterUtils.getResString("property_as_field_label")); 253 propertyToolTipMessage= new MessageFormat ( 254 JMeterUtils.getResString("property_tool_tip")); 255 256 init(); 258 } 259 260 268 private WrapperEditor createWrapperEditor( 269 PropertyEditor typeEditor, PropertyDescriptor descriptor) 270 { 271 String [] editorTags= typeEditor.getTags(); 272 String [] additionalTags= (String [])descriptor.getValue(TAGS); 273 String [] tags= null; 274 if (editorTags == null) tags= additionalTags; 275 else if (additionalTags == null) tags= editorTags; 276 else { 277 tags= new String [editorTags.length+additionalTags.length]; 278 int j= 0; 279 for (int i=0; i<editorTags.length; i++) tags[j++]= editorTags[i]; 280 for (int i=0; i<additionalTags.length; i++) tags[j++]= additionalTags[i]; 281 } 282 283 boolean notNull= 284 Boolean.TRUE.equals(descriptor.getValue(NOT_UNDEFINED)); 285 boolean notExpression= 286 Boolean.TRUE.equals(descriptor.getValue(NOT_EXPRESSION)); 287 boolean notOther= 288 Boolean.TRUE.equals(descriptor.getValue(NOT_OTHER)); 289 290 PropertyEditor guiEditor; 291 if (notNull && tags==null) 292 { 293 guiEditor= new FieldStringEditor(); 294 } 295 else 296 { 297 ComboStringEditor e= new ComboStringEditor(); 298 e.setNoUndefined(notNull); 299 e.setNoEdit(notExpression && notOther); 300 e.setTags(tags); 301 302 guiEditor= e; 303 } 304 305 WrapperEditor wrapper= new WrapperEditor( 306 typeEditor, guiEditor, 307 !notNull, !notExpression, !notOther, descriptor.getValue(DEFAULT) 311 ); 312 313 return wrapper; 314 } 315 316 324 private void setEditorValue(int i, Object value) 325 throws IllegalArgumentException 326 { 327 try 328 { 329 editors[i].setValue(value); 330 } 331 catch (IllegalArgumentException e) 332 { 333 log.error("Could not set value " 334 + ( value == null ? "NULL" : value.getClass().getName() ) 335 + ":" + value 336 +" for property "+descriptors[i].getName()); 337 throw e; 338 } 339 } 340 341 344 public void setObject(Object map) 345 { 346 propertyMap= (Map )map; 347 348 if (propertyMap.size() == 0) 349 { 350 for (int i=0; i<editors.length; i++) 352 { 353 Object value= descriptors[i].getValue(DEFAULT); 354 String name= descriptors[i].getName(); 355 if (value != null) 356 { 357 propertyMap.put(name, value); 358 log.debug("Set "+name+"= "+value); 359 } 360 firePropertyChange(name, null, value); 361 } 362 } 363 364 for (int i=0; i<editors.length; i++) 366 { 367 if (editors[i] == null) continue; 368 try 369 { 370 setEditorValue(i, propertyMap.get(descriptors[i].getName())); 371 } 372 catch (IllegalArgumentException e) 373 { 374 throw new Error ("Bad property value."+e); 382 } 385 } 386 } 387 388 395 private int descriptorIndex(String name) { 397 for (int i=0; i<descriptors.length; i++) 398 { 399 if (descriptors[i].getName().equals(name)) 400 { 401 return i; 402 } 403 } 404 return -1; 405 } 406 407 410 private void init() 411 { 412 setLayout(new GridBagLayout ()); 413 414 GridBagConstraints cl= new GridBagConstraints (); cl.gridx= 0; 416 cl.anchor= GridBagConstraints.EAST; cl.insets= new Insets (0, 1, 0, 1); 418 419 GridBagConstraints ce= new GridBagConstraints (); ce.fill= GridBagConstraints.BOTH; 421 ce.gridx= 1; 422 ce.weightx= 1.0; 423 ce.insets= new Insets (0, 1, 0, 1); 424 425 GridBagConstraints cp= new GridBagConstraints (); cp.fill= GridBagConstraints.BOTH; 427 cp.gridx= 1; 428 cp.gridy= GridBagConstraints.RELATIVE; 429 cp.gridwidth= 2; 430 cp.weightx= 1.0; 431 432 JPanel currentPanel= this; 433 String currentGroup= DEFAULT_GROUP; 434 int y=0; 435 436 for (int i=0; i<editors.length; i++) 437 { 438 if (editors[i] == null) continue; 439 440 if (log.isDebugEnabled()) 441 { 442 log.debug("Laying property "+descriptors[i].getName()); 443 } 444 445 String g= group(descriptors[i]); 446 if (! currentGroup.equals(g)) 447 { 448 if (currentPanel != this) 449 { 450 add(currentPanel, cp); 451 } 452 currentGroup= g; 453 currentPanel= new JPanel (new GridBagLayout ()); 454 currentPanel.setBorder( 455 BorderFactory.createTitledBorder( 456 BorderFactory.createEtchedBorder(), 457 groupDisplayName(g))); 458 cp.weighty= 0.0; 459 y= 0; 460 } 461 462 Component customEditor= editors[i].getCustomEditor(); 463 464 boolean multiLineEditor= false; 465 if (customEditor.getPreferredSize().height > 50) 466 { 467 multiLineEditor= true; 472 } 473 474 JLabel label= createLabel(descriptors[i]); 475 label.setLabelFor(customEditor); 476 477 cl.gridy= y; 478 cl.gridwidth= multiLineEditor ? 2 : 1; 479 cl.anchor= multiLineEditor 480 ? GridBagConstraints.CENTER 481 : GridBagConstraints.EAST; currentPanel.add(label, cl); 483 484 ce.gridx= multiLineEditor ? 0 : 1; 485 ce.gridy= multiLineEditor ? ++y : y; 486 ce.gridwidth= multiLineEditor ? 2 : 1; 487 ce.weighty= multiLineEditor ? 1.0 : 0.0; 488 489 cp.weighty+= ce.weighty; 490 491 currentPanel.add(customEditor, ce); 492 493 y++; 494 } 495 if (currentPanel != this) 496 { 497 add(currentPanel, cp); 498 } 499 500 cp.weighty= 0.0001; 503 add(Box.createHorizontalStrut(0), cp); 504 } 505 506 private JLabel createLabel(PropertyDescriptor desc) 507 { 508 String text= desc.getDisplayName(); 509 if (! "".equals(text)) 510 { 511 text= propertyFieldLabelMessage.format( 512 new Object [] { desc.getDisplayName() } ); 513 } 514 JLabel label = new JLabel (text); 516 label.setHorizontalAlignment(JLabel.TRAILING); 517 text= propertyToolTipMessage.format( 518 new Object [] { desc.getName(), desc.getShortDescription() } ); 519 label.setToolTipText(text); 520 521 return label; 522 } 523 524 525 531 private String group(PropertyDescriptor d) 532 { 533 String group= (String )d.getValue(GROUP); 534 if (group == null) group= DEFAULT_GROUP; 535 return group; 536 } 537 538 541 private String groupDisplayName(String group) 542 { 543 try { 544 ResourceBundle b= (ResourceBundle ) 545 beanInfo.getBeanDescriptor().getValue(RESOURCE_BUNDLE); 546 if (b == null) return group; 547 else return b.getString(group+".displayName"); 548 } 549 catch (MissingResourceException e) 550 { 551 return group; 552 } 553 } 554 555 558 private class PropertyComparator implements Comparator 559 { 560 public int compare(Object o1, Object o2) 561 { 562 return compare((PropertyDescriptor )o1, (PropertyDescriptor )o2); 563 } 564 565 private int compare(PropertyDescriptor d1, PropertyDescriptor d2) 566 { 567 int result; 568 569 String g1= group(d1), g2= group(d2); 570 Integer go1= groupOrder(g1), go2= groupOrder(g2); 571 572 result= go1.compareTo(go2); 573 if (result != 0) return result; 574 575 result= g1.compareTo(g2); 576 if (result != 0) return result; 577 578 Integer po1= propertyOrder(d1), po2= propertyOrder(d2); 579 result= po1.compareTo(po2); 580 if (result != 0) return result; 581 582 return d1.getName().compareTo(d2.getName()); 583 } 584 585 591 private Integer groupOrder(String group) 592 { 593 Integer order= (Integer )beanInfo.getBeanDescriptor() 594 .getValue(ORDER(group)); 595 if (order == null) order= new Integer (0); 596 return order; 597 } 598 599 605 private Integer propertyOrder(PropertyDescriptor d) 606 { 607 Integer order= (Integer )d.getValue(ORDER); 608 if (order == null) order= new Integer (0); 609 return order; 610 } 611 } 612 613 616 public void propertyChange(PropertyChangeEvent evt) 617 { 618 for (int i=0; i<editors.length; i++) 619 { 620 if (editors[i] == evt.getSource()) 621 { 622 Object value= editors[i].getValue(); 623 String name= descriptors[i].getName(); 624 if (value == null) 625 { 626 propertyMap.remove(name); 627 log.debug("Unset "+name); 628 } 629 else { 630 propertyMap.put(name, value); 631 log.debug("Set "+name+"= "+value); 632 } 633 firePropertyChange(name, evt.getOldValue(), value); 634 return; 635 } 636 } 637 throw new Error ("Unexpected propertyChange event received: "+evt); 638 } 639 } 640 | Popular Tags |