/*
* Copyright, Aspect Security, Inc.
*
* This file is part of JavaSnoop.
*
* JavaSnoop 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 3 of the License, or
* (at your option) any later version.
*
* JavaSnoop 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 JavaSnoop. If not, see <http://www.gnu.org/licenses/>.
*/
package com.aspect.snoop.ui.hook;
import com.aspect.snoop.MethodWrapper;
import com.aspect.snoop.agent.AgentLogger;
import com.aspect.snoop.agent.SnoopAgent;
import com.aspect.snoop.ui.choose.clazz.ChooseClassView;
import com.aspect.snoop.util.ReflectionUtil;
import com.aspect.snoop.util.UIUtil;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.util.List;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.ListCellRenderer;
import org.jdesktop.application.Action;
public class AddFunctionHookView extends javax.swing.JDialog {
private static AccessibleObject selectedMethod;
private static Class selectedClass;
private static Class[] parameterTypes;
private static Class returnType;
private static boolean shouldInherit;
private Class currentClass;
private Method[] loadedMethods;
private Constructor[] loadedConstructors;
public boolean getShouldInherit() {
return shouldInherit;
}
public Class getSelectedClass() {
return selectedClass;
}
public AccessibleObject getSelectedMethod() {
return selectedMethod;
}
public Class[] getParameterTypes() {
return parameterTypes;
}
public AddFunctionHookView(java.awt.Frame parent, boolean modal, String classpath) {
super(parent, modal);
initComponents();
lstMethods.setCellRenderer( new ListCellRenderer() {
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
JLabel lbl = new JLabel();
if ( isSelected ) {
lbl.setForeground(Color.white);
lbl.setBackground(Color.blue);
lbl.setOpaque(true);
}
Member m = (Member)value;
String toShow = ReflectionUtil.getMethodDescription(m);
lbl.setText(" " + toShow);
return lbl;
}
}
);
lstMethods.setListData(new Method[]{});
selectedClass = null;
selectedMethod = null;
parameterTypes = null;
returnType = null;
lstMethods.addMouseListener(
new MouseListener() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
// user double clicked an item selection
finalizeSelection();
dispose();
}
}
public void mousePressed(MouseEvent e) {
}
public void mouseReleased(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
});
}
/** 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" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
jLabel1 = new javax.swing.JLabel();
txtClass = new javax.swing.JTextField();
btnBrowseForClass = new javax.swing.JButton();
jLabel2 = new javax.swing.JLabel();
jScrollPane1 = new javax.swing.JScrollPane();
lstMethods = new javax.swing.JList();
btnAddWatch = new javax.swing.JButton();
chkShouldInherit = new javax.swing.JCheckBox();
btnSearchForFunction = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(com.aspect.snoop.JavaSnoop.class).getContext().getResourceMap(AddFunctionHookView.class);
setTitle(resourceMap.getString("Form.title")); // NOI18N
setModalityType(java.awt.Dialog.ModalityType.APPLICATION_MODAL);
setName("Form"); // NOI18N
jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
jLabel1.setName("jLabel1"); // NOI18N
txtClass.setText(resourceMap.getString("txtClass.text")); // NOI18N
txtClass.setToolTipText(resourceMap.getString("txtClass.toolTipText")); // NOI18N
txtClass.setName("txtClass"); // NOI18N
txtClass.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
txtClassActionPerformed(evt);
}
});
txtClass.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
txtClassKeyTyped(evt);
}
});
javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance(com.aspect.snoop.JavaSnoop.class).getContext().getActionMap(AddFunctionHookView.class, this);
btnBrowseForClass.setAction(actionMap.get("showChooseClassForm")); // NOI18N
btnBrowseForClass.setText(resourceMap.getString("btnBrowseForClass.text")); // NOI18N
btnBrowseForClass.setToolTipText(resourceMap.getString("btnBrowseForClass.toolTipText")); // NOI18N
btnBrowseForClass.setFocusable(false);
btnBrowseForClass.setName("btnBrowseForClass"); // NOI18N
btnBrowseForClass.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnBrowseForClassActionPerformed(evt);
}
});
jLabel2.setText(resourceMap.getString("jLabel2.text")); // NOI18N
jLabel2.setName("jLabel2"); // NOI18N
jScrollPane1.setName("jScrollPane1"); // NOI18N
lstMethods.setModel(new javax.swing.AbstractListModel() {
String[] strings = { "Item 1", "Item 2", "Item 3", "Item 4", "Item 5" };
public int getSize() { return strings.length; }
public Object getElementAt(int i) { return strings[i]; }
});
lstMethods.setName("lstMethods"); // NOI18N
lstMethods.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyTyped(java.awt.event.KeyEvent evt) {
lstMethodsKeyTyped(evt);
}
});
jScrollPane1.setViewportView(lstMethods);
btnAddWatch.setFont(resourceMap.getFont("btnAddWatch.font")); // NOI18N
btnAddWatch.setText(resourceMap.getString("btnAddWatch.text")); // NOI18N
btnAddWatch.setToolTipText(resourceMap.getString("btnAddWatch.toolTipText")); // NOI18N
btnAddWatch.setFocusable(false);
btnAddWatch.setName("btnAddWatch"); // NOI18N
btnAddWatch.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAddWatchActionPerformed(evt);
}
});
chkShouldInherit.setText(resourceMap.getString("chkShouldInherit.text")); // NOI18N
chkShouldInherit.setToolTipText(resourceMap.getString("chkShouldInherit.toolTipText")); // NOI18N
chkShouldInherit.setFocusable(false);
chkShouldInherit.setName("chkShouldInherit"); // NOI18N
btnSearchForFunction.setAction(actionMap.get("searchForFunction")); // NOI18N
btnSearchForFunction.setText(resourceMap.getString("btnSearchForFunction.text")); // NOI18N
btnSearchForFunction.setToolTipText(resourceMap.getString("btnSearchForFunction.toolTipText")); // NOI18N
btnSearchForFunction.setFocusable(false);
btnSearchForFunction.setName("btnSearchForFunction"); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jLabel1)
.addGap(15, 15, 15)
.addComponent(txtClass, javax.swing.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnBrowseForClass))
.addGroup(javax.swing.GroupLayout.Alignment.LEADING, layout.createSequentialGroup()
.addComponent(jLabel2)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGap(4, 4, 4)
.addComponent(chkShouldInherit)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnSearchForFunction)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnAddWatch))
.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 393, Short.MAX_VALUE))))
.addContainerGap())
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(jLabel1)
.addComponent(txtClass, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnBrowseForClass))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jLabel2)
.addGroup(layout.createSequentialGroup()
.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 91, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(btnSearchForFunction)
.addComponent(chkShouldInherit)
.addComponent(btnAddWatch))))
.addContainerGap())
);
pack();
}// </editor-fold>//GEN-END:initComponents
private void btnAddWatchActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnAddWatchActionPerformed
if (lstMethods.getSelectedIndex() != -1) {
finalizeSelection();
dispose();
} else {
JOptionPane.showMessageDialog(this, "Please select a method to hook!");
}
}//GEN-LAST:event_btnAddWatchActionPerformed
private void btnBrowseForClassActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_btnBrowseForClassActionPerformed
List<Class> classes = SnoopAgent.getAgentManager().getLoadedClasses();
ChooseClassView view = new ChooseClassView(this, classes);
view.setVisible(true);
UIUtil.waitForInput(view);
if (view.getChosenClass() != null) {
loadClassMethods(view.getChosenClass(), true);
}
}//GEN-LAST:event_btnBrowseForClassActionPerformed
private void txtClassKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_txtClassKeyTyped
String substring = txtClass.getText();
if ( evt.getKeyChar() != java.awt.event.KeyEvent.VK_ENTER &&
evt.getKeyChar() != java.awt.event.KeyEvent.VK_BACK_SPACE &&
evt.getKeyChar() != java.awt.event.KeyEvent.VK_ESCAPE) {
int pos = txtClass.getCaretPosition();
if ( pos != 0 ) {
String s1 = substring.substring(0, pos);
String s2 = substring.substring(pos,txtClass.getText().length());
substring = s1 + evt.getKeyChar() + s2;
} else {
substring += evt.getKeyChar();
}
}
try {
currentClass = SnoopAgent.getAgentManager().getFromAllClasses(substring);
loadClassMethods(currentClass,false);
} catch (ClassNotFoundException ex) {
lstMethods.setListData(new String[0]);
}
}//GEN-LAST:event_txtClassKeyTyped
private void txtClassActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_txtClassActionPerformed
if ( lstMethods.getModel().getSize() > 0 ) {
lstMethods.setSelectedIndex(0);
lstMethods.requestFocus();
}
}//GEN-LAST:event_txtClassActionPerformed
private void lstMethodsKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_lstMethodsKeyTyped
if ( evt.getKeyChar() == java.awt.event.KeyEvent.VK_ENTER ) {
if ( lstMethods.getSelectedIndex() != -1 ) {
btnAddWatch.doClick();
}
}
}//GEN-LAST:event_lstMethodsKeyTyped
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JButton btnAddWatch;
private javax.swing.JButton btnBrowseForClass;
private javax.swing.JButton btnSearchForFunction;
private javax.swing.JCheckBox chkShouldInherit;
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel2;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JList lstMethods;
private javax.swing.JTextField txtClass;
// End of variables declaration//GEN-END:variables
private void finalizeSelection() {
selectedClass = currentClass;
selectedMethod = (AccessibleObject)lstMethods.getSelectedValue();
parameterTypes = ReflectionUtil.getParameterTypes(selectedMethod);
returnType = ReflectionUtil.getReturnType(selectedMethod);
shouldInherit = chkShouldInherit.isSelected();
}
private void loadClassMethods(Class clazz, boolean setClassName) {
currentClass = clazz;
loadedMethods = currentClass.getDeclaredMethods();
loadedConstructors = currentClass.getDeclaredConstructors();
Member[] entries = new Member[loadedMethods.length + loadedConstructors.length];
System.arraycopy(loadedMethods, 0, entries, 0, loadedMethods.length);
System.arraycopy(loadedConstructors, 0, entries, loadedMethods.length, loadedConstructors.length);
lstMethods.setListData(entries);
if ( setClassName ) {
txtClass.setText(currentClass.getName());
}
if ( ReflectionUtil.isInterfaceOrAbstract(currentClass)) {
chkShouldInherit.setSelected(true);
chkShouldInherit.setEnabled(false);
} else {
chkShouldInherit.setSelected(false);
chkShouldInherit.setEnabled(true);
}
}
@Action
public void searchForFunction() {
List<Class> classes = SnoopAgent.getAgentManager().getLoadedClasses();
FunctionSearchView view = new FunctionSearchView(this, true, classes);
view.setVisible(true);
UIUtil.waitForInput(view);
AccessibleObject method = view.getMethodChosen();
if ( method == null ) // indicates the user cancelled
return;
selectedClass = ReflectionUtil.getDeclaringClass(method);
selectedMethod = method;
parameterTypes = ReflectionUtil.getParameterTypes(method);
shouldInherit = ReflectionUtil.isInterfaceOrAbstract(method);
returnType = ReflectionUtil.getReturnType(method);
dispose();
}
public Class getReturnType() {
return returnType;
}
}