/* This file is part of SlumDroid <https://code.google.com/p/slumdroid/>.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
*
* 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 <http://www.gnu.org/licenses/gpl-3.0.txt>
* for more details.
*
* Copyright (C) 2013-2015 Gennaro Imparato
*/
package it.slumdroid.utilities.module;
import it.slumdroid.droidmodels.model.WidgetState;
import it.slumdroid.utilities.module.guianalyzer.ComboBoxRenderer;
import it.slumdroid.utilities.module.guianalyzer.ImagePanel;
import it.slumdroid.utilities.module.guianalyzer.Perturbations;
import it.slumdroid.utilities.module.guianalyzer.ProcessGuiTree;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import javax.swing.BorderFactory;
import javax.swing.DefaultCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.KeyStroke;
import javax.swing.WindowConstants;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.table.DefaultTableModel;
import net.iharder.dnd.FileDrop;
// TODO: Auto-generated Javadoc
/**
* The Class GuiAnalyzer.
*/
public class GuiAnalyzer extends JFrame {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = 1L;
/** The ProcessGuiTree object. */
private ProcessGuiTree processGuiTree;
/** The current directory. */
private String currentDirectory = new String();
/** The first path. */
private String firstPath = new String();
/** The screenshots directory. */
private String screenshotsDirectory = "\\..\\screenshots\\";
/** The preferences path. */
private String preferencesPath = "\\..\\data\\preferences.xml";
/** The combo values. */
private String[] comboValues = {
"",
"Generic",
"Number",
"Url",
"EMail",
"Zip Code",
"ISBN",
"Credit Card",
"Exclude"
};
/** The file. */
private File theFile;
/** The tabel model. */
private DefaultTableModel tabelModel;
/** The j panel widgets. */
private JPanel jPanelWidgets;
/** The j panel image. */
private JPanel jPanelImage;
/** The j table info. */
private JTable jTableInfo;
/** The col type. */
private Object[] colType;
/** The col id. */
private Object[] colId;
/**
* Instantiates a new gui analyzer.
*/
public GuiAnalyzer() {
setResizable(false);
initComponents();
new FileDrop (null, jPanelWidgets, new FileDrop.Listener() {
public void filesDropped(File[] files ) {
if (files.length == 0) {
return;
}
theFile = files[0];
currentDirectory = files[0].getPath().replace(files[0].getName(), "");
createLayout();
}
});
}
/**
* Instantiates a new gui analyzer.
*
* @param expPath the exp path
*/
public GuiAnalyzer(String expPath) {
this.firstPath = new String(expPath);
setResizable(false);
initComponents();
new FileDrop (null, jPanelWidgets, new FileDrop.Listener() {
public void filesDropped(File[] files ) {
if (files.length == 0) {
return;
}
theFile = files[0];
currentDirectory = files[0].getPath().replace(files[0].getName(), "");
createLayout();
}
});
}
/**
* Inits the components.
*/
private void initComponents() {
JTabbedPane jTabbedWidget = new JTabbedPane();
jPanelWidgets = new JPanel();
jPanelWidgets.setLayout(new BorderLayout());
jTableInfo = new JTable();
JMenuBar jMenuBar = new JMenuBar();
JMenu jMenuFile = new JMenu();
jMenuFile.setText("File");
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
setTitle("GUI Analyzer");
setPreferredSize(new Dimension(960, 513));
getContentPane().setLayout(new GridLayout(1, 0));
JScrollPane jScrollPane = new JScrollPane();
jScrollPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
jScrollPane.setViewportView(jTableInfo);
jPanelWidgets.add(jScrollPane, BorderLayout.CENTER);
jPanelImage = new ImagePanel("");
jPanelWidgets.add(jPanelImage, BorderLayout.LINE_END);
jTabbedWidget.addTab("Widgets", jPanelWidgets);
getContentPane().add(jTabbedWidget);
JMenuItem jMenuOpen = new javax.swing.JMenuItem();
jMenuOpen.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_MASK));
jMenuOpen.setIcon(new ImageIcon(getClass().getResource("/open.png")));
jMenuOpen.setText("Open");
jMenuOpen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
open();
}
});
jMenuFile.add(jMenuOpen);
JMenuItem jMenuSave = new JMenuItem();
jMenuSave.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_MASK));
jMenuSave.setIcon(new ImageIcon(getClass().getResource("/save.png")));
jMenuSave.setText("Save");
jMenuSave.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
if (!save()) {
JOptionPane.showMessageDialog(null, "Error\nPreferences.xml was not created");
} else {
System.exit(NORMAL);
}
}
});
jMenuFile.add(jMenuSave);
JMenuItem jMenuExit = new JMenuItem();
jMenuExit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_MASK));
jMenuExit.setIcon(new ImageIcon(getClass().getResource("/exit.png")));
jMenuExit.setText("Exit");
jMenuExit.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
System.exit(0);
}
});
jMenuFile.add(jMenuExit);
jMenuBar.add(jMenuFile);
setJMenuBar(jMenuBar);
pack();
}
/**
* Creates the layout.
*/
private void createLayout() {
this.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
resetAll();
try {
processGuiTree = new ProcessGuiTree(theFile.toString());
} catch (Exception e) {
e.printStackTrace();
} finally {
this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
}
int numWidgets = processGuiTree.getNumWidgets();
colId = new Object[numWidgets];
Object[] colWidgets = new Object[numWidgets];
Object[] colName = new Object[numWidgets];
Object[] colValue = new Object[numWidgets];
colType = new Object[numWidgets];
Object[] colScreen = new Object[numWidgets];
Object[] colInteraction = new Object[numWidgets];
Object[] colSimpleType = new Object[numWidgets];
int item = 0;
Collection<WidgetState> WidgetsColl = processGuiTree.getWidgets().values();
for (WidgetState widget: WidgetsColl) {
colId[item] = widget.getId();
colWidgets[item] = widget.getType();
colName[item] = widget.getName();
colValue[item] = widget.getValue();
colType[item] = widget.getTextType();
colInteraction[item] = processGuiTree.getInteractions().get(widget.getId());
colSimpleType[item] = widget.getSimpleType();
colScreen[item] = new JButton(processGuiTree.getScreens().get(widget.getId()));
item++;
}
tabelModel.addColumn("Id", colId);
tabelModel.addColumn("Widgets Type", colWidgets);
tabelModel.addColumn("Simple Type", colSimpleType);
tabelModel.addColumn("Name", colName);
tabelModel.addColumn("Valid Input", colValue);
tabelModel.addColumn("Text Type", colType);
tabelModel.addColumn("Interactions", colInteraction);
tabelModel.addColumn("Perturbation", new String[]{""});
tabelModel.addColumn("Screenshot", colScreen);
// ComboBox
JComboBox<String> comboBox = new JComboBox<String>(comboValues);
jTableInfo.getColumnModel().getColumn(7).setCellEditor(new DefaultCellEditor(comboBox));
jTableInfo.getColumnModel().getColumn(7).setCellRenderer(new ComboBoxRenderer(comboValues));
comboBox.addItemListener(new ItemListener() {
@Override
public void itemStateChanged (ItemEvent event) {
changeWidgetInfo();
}
});
jTableInfo.setRowHeight(20);
jTableInfo.getColumnModel().getColumn(8).setMinWidth(0);
jTableInfo.getColumnModel().getColumn(8).setMaxWidth(0);
jTableInfo.getColumnModel().getColumn(8).setWidth(0);
jTableInfo.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked (MouseEvent e) {
changeWidgetInfo();
}
});
firstImage();
}
/**
* Reset all.
*/
private void resetAll() {
tabelModel = (DefaultTableModel) jTableInfo.getModel();
tabelModel.setRowCount(0);
tabelModel.setColumnCount(0);
}
/**
* Change widget info.
*/
private void changeWidgetInfo() {
int row = jTableInfo.getSelectedRow();
Object value = ((JButton) jTableInfo.getValueAt(row, 8)).getText();
addImage(currentDirectory + screenshotsDirectory + value);
}
/**
* First image.
*/
private void firstImage() {
if (processGuiTree.getNumWidgets() != 0) {
Object value = ((JButton) jTableInfo.getValueAt(0, 8)).getText();
addImage(currentDirectory + screenshotsDirectory + value);
}
}
/**
* Adds the image.
*
* @param image the image
*/
private void addImage(String image) {
try{
jPanelWidgets.remove(jPanelImage);
}catch (Exception e){
e.printStackTrace();
}
jPanelImage = new ImagePanel(image);
jPanelImage.setBackground(new Color(255, 255, 255));
jPanelImage.setBorder(BorderFactory.createLineBorder(new Color(0, 0, 0)));
jPanelWidgets.add(jPanelImage, BorderLayout.LINE_END);
jPanelWidgets.revalidate();
}
/**
* Open.
*/
private void open() {
JFileChooser toLoad = new JFileChooser();
toLoad.setFileFilter(new FileNameExtensionFilter("XML GUI Tree", "xml"));
toLoad.setCurrentDirectory(new File(System.getProperty("user.dir")));
int code = toLoad.showOpenDialog(this);
if (code == JFileChooser.APPROVE_OPTION) {
theFile = toLoad.getSelectedFile();
currentDirectory = toLoad.getCurrentDirectory().toString();
createLayout();
}
}
/**
* Save.
*
* @return true, if successful
*/
private boolean save() {
try {
String place = System.getProperty("user.dir");
createXml(place + preferencesPath);
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* Creates the xml.
*
* @param preferencesFile the preferences file
*/
private void createXml(String preferencesFile) {
StringBuilder builder = new StringBuilder();
String line = new String();
boolean interact = false;
BufferedReader inputStream1 = null;
PrintWriter outputStream1 = null;
try{
inputStream1 = new BufferedReader (new FileReader (preferencesFile));
while ((line = inputStream1.readLine()) != null ) {
if (line.contains("<node name=\"interactions\">")) {
interact = true;
}
if (line.contains("</map>") && interact) {
interact = false;
addPerturbations(builder);
}
builder.append("<"+ line.split("<")[1]);
}
inputStream1.close();
new Tools().xmlWriter(preferencesFile, builder);
if (!firstPath.equals("")) {
if (!new File(firstPath).exists()) {
new File(firstPath).mkdir();
}
outputStream1 = new PrintWriter (firstPath.concat("/firstboot.txt"));
outputStream1.write("firstboot");
outputStream1.close();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
inputStream1.close();
outputStream1.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* Adds the perturbations.
*
* @param builder the builder
*/
private void addPerturbations(StringBuilder builder) {
String data = "<entry key=\"EXTRA_INPUTS[INDEX]\" value=\"writeText,ID,PERTUBATIONS\"/>";
int countInput = 0;
int countEvent = 0;
for (int index = 0; index < processGuiTree.getNumWidgets(); index++) {
String control = (String) jTableInfo.getValueAt(index, 7);
if (control != null) {
try{
if (!control.equals("exclude")) {
String pertubedInput = new Perturbations(colType[index], (String) jTableInfo.getValueAt(index, 4)).perturbe(control);
if (!pertubedInput.equals("")) {
if (jTableInfo.getValueAt(index, 6).equals("Input")) {
builder.append(data
.replace("INDEX", String.valueOf(countInput))
.replace("ID", String.valueOf(colId[index]))
.replace("PERTUBATIONS", pertubedInput));
countInput++;
} else if (jTableInfo.getValueAt(index, 6).equals("Event")) {
if (((String) jTableInfo.getValueAt(index, 5)).endsWith("SearchAutoComplete")) {
builder.append(data
.replace("EXTRA_INPUTS", "EXTRA_EVENTS")
.replace("INDEX", String.valueOf(countEvent))
.replace("ID", String.valueOf(colId[index]))
.replace("writeText", "enterText")
.replace("PERTUBATIONS", pertubedInput));
} else {
builder.append(data
.replace("EXTRA_INPUTS", "EXTRA_EVENTS")
.replace("INDEX", String.valueOf(countEvent))
.replace("ID", String.valueOf(colId[index]))
.replace("PERTUBATIONS", pertubedInput));
}
countEvent++;
} else if (jTableInfo.getValueAt(index, 6).equals("Input & Event")) {
builder.append(data
.replace("INDEX", String.valueOf(countInput))
.replace("ID", String.valueOf(colId[index]))
.replace("PERTUBATIONS", pertubedInput));
countInput++;
builder.append(data
.replace("EXTRA_INPUTS", "EXTRA_EVENTS")
.replace("INDEX", String.valueOf(countEvent))
.replace("ID", String.valueOf(colId[index]))
.replace("PERTUBATIONS", pertubedInput));
countEvent++;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}