/*
* Zed Attack Proxy (ZAP) and its related class files.
*
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
*
* Copyright 2010 psiinon@gmail.com
*
* Licensed 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.zaproxy.zap.extension.brk;
import java.awt.CardLayout;
import java.awt.Event;
import java.awt.EventQueue;
import java.awt.GridBagConstraints;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import javax.swing.ImageIcon;
import javax.swing.JScrollPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.table.TableColumn;
import org.apache.log4j.Logger;
import org.jdesktop.swingx.JXTable;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.extension.AbstractPanel;
import org.parosproxy.paros.view.View;
public class BreakpointsPanel extends AbstractPanel {
private static final long serialVersionUID = 1L;
public static final String PANEL_NAME = "breakpoints";
private ExtensionBreak extension;
private javax.swing.JPanel panelCommand = null;
private javax.swing.JLabel jLabel = null;
private JScrollPane jScrollPane = null;
private JXTable breakpointsTable = null;
private BreakpointsTableModel model = new BreakpointsTableModel();
private static final String BRK_TABLE = "brk.table";
private static final String PREF_COLUMN_WIDTH = "column.width";
private final Preferences preferences;
private final String prefnzPrefix = this.getClass().getSimpleName()+".";
private static Logger log = Logger.getLogger(BreakpointsPanel.class);
public BreakpointsPanel(ExtensionBreak extension) {
super();
this.extension = extension;
this.preferences = Preferences.userNodeForPackage(getClass());
initialize();
}
private void initialize() {
this.setLayout(new CardLayout());
this.setSize(474, 251);
this.setName(Constant.messages.getString("brk.panel.title"));
this.setIcon(new ImageIcon(BreakpointsPanel.class.getResource("/resource/icon/16/101.png"))); // 'red X' icon
this.setDefaultAccelerator(KeyStroke.getKeyStroke(
KeyEvent.VK_B, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | Event.ALT_MASK | Event.SHIFT_MASK, false));
this.setMnemonic(Constant.messages.getChar("brk.panel.mnemonic"));
this.add(getPanelCommand(), getPanelCommand().getName());
}
private javax.swing.JPanel getPanelCommand() {
if (panelCommand == null) {
panelCommand = new javax.swing.JPanel();
panelCommand.setLayout(new java.awt.GridBagLayout());
panelCommand.setName(Constant.messages.getString("brk.panel.title"));
jLabel = getJLabel();
GridBagConstraints gridBagConstraints1 = new GridBagConstraints();
GridBagConstraints gridBagConstraints2 = new GridBagConstraints();
// Better without this?
//jLabel.setText("Break Points:");
gridBagConstraints1.gridx = 0;
gridBagConstraints1.gridy = 0;
gridBagConstraints1.insets = new java.awt.Insets(2,2,2,2);
gridBagConstraints1.anchor = java.awt.GridBagConstraints.NORTHWEST;
gridBagConstraints1.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints1.weightx = 1.0D;
gridBagConstraints2.gridx = 0;
gridBagConstraints2.gridy = 1;
gridBagConstraints2.weightx = 1.0;
gridBagConstraints2.weighty = 1.0;
gridBagConstraints2.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints2.insets = new java.awt.Insets(0,0,0,0);
gridBagConstraints2.anchor = java.awt.GridBagConstraints.NORTHWEST;
//panelCommand.add(jLabel, gridBagConstraints1);
panelCommand.add(getJScrollPane(), gridBagConstraints2);
}
return panelCommand;
}
private javax.swing.JLabel getJLabel() {
if (jLabel == null) {
jLabel = new javax.swing.JLabel();
jLabel.setText(" ");
}
return jLabel;
}
private JScrollPane getJScrollPane() {
if (jScrollPane == null) {
jScrollPane = new JScrollPane();
jScrollPane.setViewportView(getBreakpoints());
}
return jScrollPane;
}
protected JXTable getBreakpoints() {
if (breakpointsTable == null) {
breakpointsTable = new JXTable(model);
breakpointsTable.setColumnSelectionAllowed(false);
breakpointsTable.setCellSelectionEnabled(false);
breakpointsTable.setRowSelectionAllowed(true);
breakpointsTable.setColumnControlVisible(true);
breakpointsTable.getColumnModel().getColumn(0).setPreferredWidth(restoreColumnWidth(BRK_TABLE, 100));
breakpointsTable.getColumnModel().getColumn(0).addPropertyChangeListener(new ColumnResizedListener(BRK_TABLE));
breakpointsTable.getColumnModel().getColumn(0).setMaxWidth(250);
breakpointsTable.getTableHeader().setReorderingAllowed(false);
breakpointsTable.setName(PANEL_NAME);
breakpointsTable.setDoubleBuffered(true);
breakpointsTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
breakpointsTable.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mousePressed(java.awt.event.MouseEvent e) {
showPopupMenuIfTriggered(e);
}
@Override
public void mouseReleased(java.awt.event.MouseEvent e) {
showPopupMenuIfTriggered(e);
}
private void showPopupMenuIfTriggered(java.awt.event.MouseEvent e) {
if (e.isPopupTrigger()) {
// Select table item
int row = breakpointsTable.rowAtPoint( e.getPoint() );
if ( row < 0 || !breakpointsTable.getSelectionModel().isSelectedIndex( row ) ) {
breakpointsTable.getSelectionModel().clearSelection();
if ( row >= 0 ) {
breakpointsTable.getSelectionModel().setSelectionInterval( row, row );
}
}
View.getSingleton().getPopupMenu().show(e.getComponent(), e.getX(), e.getY());
}
}
@Override
public void mouseClicked(java.awt.event.MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e) && e.getClickCount() > 1) {
// Its a double click
extension.editUiSelectedBreakpoint();
}
}
});
}
return breakpointsTable;
}
public BreakpointMessageInterface getSelectedBreakpoint() {
int selectedRow = breakpointsTable.getSelectedRow();
if (selectedRow != -1) {
return model.getBreakpointAtRow(selectedRow);
}
return null;
}
private void selectRowAndEnsureVisible(int row) {
if (row != -1) {
breakpointsTable.getSelectionModel().setSelectionInterval(row, row);
breakpointsTable.scrollRectToVisible(breakpointsTable.getCellRect(row, 0, true));
}
}
private void addBreakpointModel(BreakpointMessageInterface breakpoint) {
model.addBreakpoint(breakpoint);
selectRowAndEnsureVisible(model.getLastAffectedRow());
}
void addBreakpoint(final BreakpointMessageInterface breakpoint) {
if (EventQueue.isDispatchThread()) {
addBreakpointModel(breakpoint);
return;
}
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
addBreakpointModel(breakpoint);
}
});
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
private void editBreakpointModel(BreakpointMessageInterface oldBreakpoint, BreakpointMessageInterface newBreakpoint) {
model.editBreakpoint(oldBreakpoint, newBreakpoint);
selectRowAndEnsureVisible(model.getLastAffectedRow());
}
void editBreakpoint(final BreakpointMessageInterface oldBreakpoint, final BreakpointMessageInterface newBreakpoint) {
if (EventQueue.isDispatchThread()) {
editBreakpointModel(oldBreakpoint, newBreakpoint);
return;
}
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
editBreakpointModel(oldBreakpoint, newBreakpoint);
}
});
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
private void removeBreakpointModel(BreakpointMessageInterface breakpoint) {
model.removeBreakpoint(breakpoint);
}
public void removeBreakpoint(final BreakpointMessageInterface breakpoint) {
if (EventQueue.isDispatchThread()) {
removeBreakpointModel(breakpoint);
return;
}
try {
EventQueue.invokeAndWait(new Runnable() {
@Override
public void run() {
removeBreakpointModel(breakpoint);
}
});
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
private void saveColumnWidth(String prefix, int width) {
if (width > 0) {
if (log.isDebugEnabled()) log.debug("Saving preference " + prefnzPrefix+prefix + "." + PREF_COLUMN_WIDTH + "=" + width);
this.preferences.put(prefnzPrefix+prefix + "." + PREF_COLUMN_WIDTH, Integer.toString(width));
// immediate flushing
try {
this.preferences.flush();
} catch (final BackingStoreException e) {
log.error("Error while saving the preferences", e);
}
}
}
private int restoreColumnWidth(String prefix, int fallback) {
int result = fallback;
final String sizestr = preferences.get(prefnzPrefix+prefix + "." + PREF_COLUMN_WIDTH, null);
if (sizestr != null) {
int width = 0;
try {
width = Integer.parseInt(sizestr.trim());
} catch (final Exception e) {
// ignoring, cause is prevented by default values;
}
if (width > 0 ) {
result = width;
if (log.isDebugEnabled()) log.debug("Restoring preference " + prefnzPrefix+prefix + "." + PREF_COLUMN_WIDTH + "=" + width);
}
}
return result;
}
private final class ColumnResizedListener implements PropertyChangeListener {
private final String prefix;
public ColumnResizedListener(String prefix) {
super();
assert prefix != null;
this.prefix = prefix;
}
@Override
public void propertyChange(PropertyChangeEvent evt) {
TableColumn column = (TableColumn) evt.getSource();
if (column != null) {
if (log.isDebugEnabled()) log.debug(prefnzPrefix+prefix + "." + PREF_COLUMN_WIDTH + "=" + column.getWidth());
saveColumnWidth(prefix, column.getWidth());
}
}
}
}