/** * WS-Attacker - A Modular Web Services Penetration Testing Framework Copyright * (C) 2010 Christian Mainka * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package wsattacker.gui.component.pluginconfiguration.subcomponent; import java.awt.Component; import java.awt.Dimension; import java.beans.IndexedPropertyChangeEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collections; import java.util.List; import javax.swing.JPanel; import org.apache.log4j.Logger; import org.jdesktop.beansbinding.PropertyResolutionException; import org.jdesktop.el.ELException; import wsattacker.gui.component.pluginconfiguration.composition.OptionGUI; import wsattacker.gui.component.pluginconfiguration.controller.SelectedPluginController; import wsattacker.main.composition.plugin.AbstractPlugin; import wsattacker.main.composition.plugin.option.AbstractOption; import wsattacker.main.plugin.PluginOptionContainer; /** * @author christian */ public class SelectedPlugin extends javax.swing.JPanel implements PropertyChangeListener { final private static Logger LOG = Logger.getLogger( SelectedPlugin.class ); /** * Creates new form SelectedPlugin */ public SelectedPlugin() { initComponents(); selectedPluginController.addPropertyChangeListener( this ); } /** * This method is called from within the constructor to initialize the form. WARNING: Do NOT modify this code. The * content of this method is always regenerated by the Form Editor. */ @SuppressWarnings( "unchecked" ) // <editor-fold defaultstate="collapsed" // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents private void initComponents() { bindingGroup = new org.jdesktop.beansbinding.BindingGroup(); selectedPluginController = new wsattacker.gui.component.pluginconfiguration.controller.SelectedPluginController(); nameLabel = new javax.swing.JLabel(); authorLabel = new javax.swing.JLabel(); versionLabel = new javax.swing.JLabel(); versionValue = new javax.swing.JLabel(); authorValue = new javax.swing.JLabel(); descriptionLabel = new javax.swing.JLabel(); descriptionScrollPane = new javax.swing.JScrollPane(); descriptionValue = new javax.swing.JTextPane(); optionLabel = new javax.swing.JLabel(); optionScrollPane = new javax.swing.JScrollPane(); optionPanel = new javax.swing.JPanel(); pluginIcon = new javax.swing.JLabel(); nameLabel.setFont( new java.awt.Font( "Dialog", 1, 18 ) ); // NOI18N org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding( org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, selectedPluginController, org.jdesktop.beansbinding.ELProperty.create( "${selectedPlugin.name}" ), nameLabel, org.jdesktop.beansbinding.BeanProperty.create( "text" ), "pluginName" ); bindingGroup.addBinding( binding ); authorLabel.setText( "Author:" ); versionLabel.setText( "Version:" ); versionValue.setFont( new java.awt.Font( "Dialog", 0, 12 ) ); // NOI18N binding = org.jdesktop.beansbinding.Bindings.createAutoBinding( org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, selectedPluginController, org.jdesktop.beansbinding.ELProperty.create( "${selectedPlugin.version}" ), versionValue, org.jdesktop.beansbinding.BeanProperty.create( "text" ) ); bindingGroup.addBinding( binding ); authorValue.setFont( new java.awt.Font( "Dialog", 0, 12 ) ); // NOI18N binding = org.jdesktop.beansbinding.Bindings.createAutoBinding( org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, selectedPluginController, org.jdesktop.beansbinding.ELProperty.create( "${selectedPlugin.author}" ), authorValue, org.jdesktop.beansbinding.BeanProperty.create( "text" ) ); bindingGroup.addBinding( binding ); descriptionLabel.setText( "Description:" ); descriptionValue.setEditable( false ); descriptionValue.setBackground( new java.awt.Color( 238, 238, 238 ) ); descriptionValue.setContentType( "text/html" ); // NOI18N binding = org.jdesktop.beansbinding.Bindings.createAutoBinding( org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, selectedPluginController, org.jdesktop.beansbinding.ELProperty.create( "${selectedPlugin.description}" ), descriptionValue, org.jdesktop.beansbinding.BeanProperty.create( "text" ) ); bindingGroup.addBinding( binding ); descriptionScrollPane.setViewportView( descriptionValue ); optionLabel.setText( "Options:" ); optionScrollPane.setMaximumSize( new java.awt.Dimension( 200, 32767 ) ); optionPanel.setCursor( new java.awt.Cursor( java.awt.Cursor.DEFAULT_CURSOR ) ); optionPanel.setLayout( new javax.swing.BoxLayout( optionPanel, javax.swing.BoxLayout.Y_AXIS ) ); optionScrollPane.setViewportView( optionPanel ); pluginIcon.setHorizontalAlignment( javax.swing.SwingConstants.TRAILING ); pluginIcon.setIconTextGap( 0 ); binding = org.jdesktop.beansbinding.Bindings.createAutoBinding( org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ, selectedPluginController, org.jdesktop.beansbinding.ELProperty.create( "${selectedPlugin.icon}" ), pluginIcon, org.jdesktop.beansbinding.BeanProperty.create( "icon" ), "iconBinding" ); binding.setSourceNullValue( null ); binding.setSourceUnreadableValue( null ); bindingGroup.addBinding( binding ); binding = org.jdesktop.beansbinding.Bindings.createAutoBinding( org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, selectedPluginController, org.jdesktop.beansbinding.ELProperty.create( "${selectedPlugin.name}" ), pluginIcon, org.jdesktop.beansbinding.BeanProperty.create( "toolTipText" ) ); bindingGroup.addBinding( binding ); javax.swing.GroupLayout layout = new javax.swing.GroupLayout( this ); this.setLayout( layout ); layout.setHorizontalGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addGroup( layout.createSequentialGroup().addContainerGap().addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addComponent( optionScrollPane, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE ).addComponent( descriptionScrollPane ).addGroup( layout.createSequentialGroup().addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addComponent( nameLabel ).addComponent( optionLabel ) ).addGap( 0, 0, Short.MAX_VALUE ) ).addGroup( layout.createSequentialGroup().addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addComponent( descriptionLabel ).addGroup( layout.createSequentialGroup().addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addComponent( authorLabel ).addComponent( versionLabel ) ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED ).addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addComponent( versionValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE ).addComponent( authorValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE ) ) ) ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED ).addComponent( pluginIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 107, javax.swing.GroupLayout.PREFERRED_SIZE ) ) ).addContainerGap() ) ); layout.setVerticalGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addGroup( layout.createSequentialGroup().addContainerGap().addComponent( nameLabel ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED ).addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING ).addGroup( layout.createSequentialGroup().addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.BASELINE ).addComponent( authorLabel ).addComponent( authorValue, javax.swing.GroupLayout.PREFERRED_SIZE, 15, javax.swing.GroupLayout.PREFERRED_SIZE ) ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED ).addGroup( layout.createParallelGroup( javax.swing.GroupLayout.Alignment.LEADING, false ).addComponent( versionLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE ).addComponent( versionValue, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE ) ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED ).addComponent( descriptionLabel ) ).addComponent( pluginIcon, javax.swing.GroupLayout.PREFERRED_SIZE, 57, javax.swing.GroupLayout.PREFERRED_SIZE ) ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.UNRELATED ).addComponent( descriptionScrollPane, javax.swing.GroupLayout.PREFERRED_SIZE, 149, javax.swing.GroupLayout.PREFERRED_SIZE ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED ).addComponent( optionLabel ).addPreferredGap( javax.swing.LayoutStyle.ComponentPlacement.RELATED ).addComponent( optionScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 1108, Short.MAX_VALUE ) ) ); bindingGroup.bind(); }// </editor-fold>//GEN-END:initComponents // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JLabel authorLabel; private javax.swing.JLabel authorValue; private javax.swing.JLabel descriptionLabel; private javax.swing.JScrollPane descriptionScrollPane; private javax.swing.JTextPane descriptionValue; private javax.swing.JLabel nameLabel; private javax.swing.JLabel optionLabel; private javax.swing.JPanel optionPanel; private javax.swing.JScrollPane optionScrollPane; private javax.swing.JLabel pluginIcon; private wsattacker.gui.component.pluginconfiguration.controller.SelectedPluginController selectedPluginController; private javax.swing.JLabel versionLabel; private javax.swing.JLabel versionValue; private org.jdesktop.beansbinding.BindingGroup bindingGroup; // End of variables declaration//GEN-END:variables public SelectedPluginController getSelectedPluginController() { return selectedPluginController; } @Override public void propertyChange( PropertyChangeEvent pce ) { String propertyName = pce.getPropertyName(); if ( SelectedPluginController.PROP_SELECTEDPLUGIN.equals( propertyName ) ) { List<AbstractOption> newOptions = ( (AbstractPlugin) pce.getNewValue() ).getPluginOptions().getOptions(); removeAndUnbindAllComponents(); handleMultipleNewOptions( 0, Collections.<AbstractOption> emptyList(), newOptions ); adjustingOptionPanelSize(); handleOptionContainerChangeListener( pce ); } else if ( pce instanceof IndexedPropertyChangeEvent && PluginOptionContainer.PROP_OPTIONS.equals( pce.getPropertyName() ) ) { IndexedPropertyChangeEvent ipce = (IndexedPropertyChangeEvent) pce; int index = ipce.getIndex(); if ( ipce.getNewValue() instanceof List ) { // multiple changes List<AbstractOption> oldValue = (List<AbstractOption>) ipce.getOldValue(); List<AbstractOption> newValue = (List<AbstractOption>) ipce.getNewValue(); handleMultipleNewOptions( index, oldValue, newValue ); } else if ( ipce.getNewValue() instanceof AbstractOption ) { handleReplacedOption( index, ipce ); } } } private OptionGUI createOption( AbstractOption option ) { return option.createOptionGUI(); } private void handleOptionContainerChangeListener( PropertyChangeEvent pce ) { AbstractPlugin oldPlugin = (AbstractPlugin) pce.getOldValue(); AbstractPlugin newPlugin = (AbstractPlugin) pce.getNewValue(); if ( oldPlugin != null ) { oldPlugin.getPluginOptions().removePropertyChangeListener( this ); } if ( newPlugin != null ) { newPlugin.getPluginOptions().addPropertyChangeListener( this ); } } private void handleMultipleNewOptions( int index, List<AbstractOption> oldValue, List<AbstractOption> newValue ) { List<AbstractOption> oldOptions = new ArrayList<AbstractOption>( oldValue ); removeNoLongerUsedOptions( oldOptions, newValue ); // insert new options for ( int newIndex = 0; newIndex < newValue.size(); ++newIndex ) { AbstractOption newOption = newValue.get( newIndex ); int oldIndex = oldOptions.indexOf( newOption ); if ( oldIndex == newIndex ) { // nothing to do continue; } else if ( oldIndex < 0 ) { insertOptionAtPosition( newOption, newIndex, oldOptions ); } else { moveOption( oldIndex, newIndex, oldOptions ); } } } private void handleReplacedOption( int index, IndexedPropertyChangeEvent ipce ) { // single change try { optionPanel.remove( index ); AbstractOption option = (AbstractOption) ipce.getNewValue(); LOG.debug( "Created Option " + option.getName() ); OptionGUI optionGUI = createOption( option ); optionPanel.add( optionGUI, index ); } catch ( Exception e ) { LOG.warn( e ); } } private void removeAndUnbind( int index ) { if ( optionPanel.getComponent( index ) instanceof OptionGUI ) { OptionGUI option = (OptionGUI) optionPanel.getComponent( index ); try { option.bindingDoUnbind(); } catch ( ELException e ) { LOG.warn( e ); } catch ( PropertyResolutionException e ) { LOG.warn( e ); } } optionPanel.remove( index ); } private void removeAndUnbindAllComponents() { int max = optionPanel.getComponentCount(); for ( int i = 0; i < max; ++i ) { removeAndUnbind( 0 ); } } JPanel getOptionPanel() { return optionPanel; } private void removeNoLongerUsedOptions( List<AbstractOption> oldOptions, List<AbstractOption> newOptions ) { int end = oldOptions.size() - 1; for ( int oldIndex = end; oldIndex >= 0; --oldIndex ) { AbstractOption o = oldOptions.get( oldIndex ); if ( !newOptions.contains( o ) ) { removeAndUnbind( oldIndex ); oldOptions.remove( oldIndex ); } } } private void insertOptionAtPosition( AbstractOption newOption, int newIndex, List<AbstractOption> oldOptions ) { // insert at correct position; try { LOG.debug( "Created Option " + newOption.getName() ); OptionGUI optionGUI = createOption( newOption ); optionPanel.add( optionGUI, newIndex ); oldOptions.add( newIndex, newOption ); } catch ( Exception e ) { LOG.warn( e ); } } private void moveOption( int oldIndex, int newIndex, List<AbstractOption> oldOptions ) { // move to corect position Component component = optionPanel.getComponent( oldIndex ); optionPanel.remove( component ); // TODO: This is wrong optionPanel.add( component, newIndex ); oldOptions.add( newIndex, oldOptions.remove( oldIndex ) ); } private void adjustingOptionPanelSize() { int width = optionScrollPane.getSize().width - 20; for ( int i = 0; i < optionPanel.getComponentCount(); ++i ) { Component c = optionPanel.getComponent( i ); int height = c.getPreferredSize().height; c.setPreferredSize( new Dimension( width, height ) ); } optionPanel.setSize( optionPanel.getPreferredSize() ); } }