/* Soot - a J*va Optimization Framework
* Copyright (C) 2003 Jennifer Lhotak
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
package ca.mcgill.sable.soot.ui;
import java.util.*;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.jface.dialogs.*;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.*;
import ca.mcgill.sable.soot.SootPlugin;
import ca.mcgill.sable.soot.launching.*;
import ca.mcgill.sable.soot.ui.PhaseOptionsDialog;
public class SootConfigManagerDialog extends TitleAreaDialog implements ISelectionChangedListener {
private SashForm sashForm;
private Composite selectionArea;
private TreeViewer treeViewer;
private String selected;
private Composite buttonPanel;
private SootConfiguration treeRoot;
private HashMap editDefs;
private SootLauncher launcher;
private void addEclipseDefsToDialog(PhaseOptionsDialog dialog) {
if (getEclipseDefList() == null) return;
Iterator it = getEclipseDefList().keySet().iterator();
while (it.hasNext()) {
String key = (String)it.next();
dialog.addToEclipseDefList(key, getEclipseDefList().get(key));
}
}
private void setMainClassInDialog(PhaseOptionsDialog dialog, String mainClass){
String mainProject;
String realMainClass;
if(mainClass.contains(":")) {
String[] split = mainClass.split(":");
mainProject = split[0];
realMainClass = split[1];
} else {
mainProject = null;
realMainClass = mainClass;
}
dialog.addToEclipseDefList("sootMainClass", realMainClass);
dialog.addToEclipseDefList("sootMainProject", mainProject);
}
private HashMap eclipseDefList;
/**
* Returns the eclipseDefList.
* @return HashMap
*/
public HashMap getEclipseDefList() {
return eclipseDefList;
}
/**
* Sets the eclipseDefList.
* @param eclipseDefList The eclipseDefList to set
*/
public void setEclipseDefList(HashMap eclipseDefList) {
this.eclipseDefList = eclipseDefList;
}
public SootConfigManagerDialog(Shell parentShell) {
super(parentShell);
this.setShellStyle(SWT.RESIZE);
}
protected void configureShell(Shell shell){
super.configureShell(shell);
shell.setText(Messages.getString("SootConfigManagerDialog.Manage_Configurations")); //$NON-NLS-1$
}
/**
* creates a sash form - one side for a selection tree
* and the other for the options
*/
protected Control createDialogArea(Composite parent) {
GridData gd;
Composite dialogComp = (Composite)super.createDialogArea(parent);
Composite topComp = new Composite(dialogComp, SWT.NONE);
gd = new GridData(GridData.FILL_BOTH);
topComp.setLayoutData(gd);
GridLayout topLayout = new GridLayout();
topLayout.numColumns = 2;
topComp.setLayout(topLayout);
// Set the things that TitleAreaDialog takes care of
setTitle(Messages.getString("SootConfigManagerDialog.Soot_Configurations_Manager")); //$NON-NLS-1$
setMessage(""); //$NON-NLS-1$
Composite selection = createSelectionArea(topComp);
gd = new GridData(GridData.FILL_BOTH);
gd.horizontalSpan = 1;
selection.setLayoutData(gd);
Control specialButtons = createSpecialButtonBar(topComp);
gd = new GridData(GridData.FILL_BOTH);
specialButtons.setLayoutData(gd);
Label separator = new Label(topComp, SWT.HORIZONTAL | SWT.SEPARATOR);
gd = new GridData(GridData.FILL_HORIZONTAL);
gd.horizontalSpan = 2;
separator.setLayoutData(gd);
dialogComp.layout(true);
return dialogComp;
}
/**
* creates the tree of options sections
*/
private Composite createSelectionArea(Composite parent) {
Composite comp = new Composite(parent, SWT.NONE);
setSelectionArea(comp);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
comp.setLayout(layout);
GridData gd = new GridData();
TreeViewer tree = new TreeViewer(comp);
gd = new GridData(GridData.FILL_BOTH);
tree.getControl().setLayoutData(gd);
tree.setContentProvider(new SootConfigContentProvider());
tree.setLabelProvider(new SootConfigLabelProvider());
tree.setInput(getInitialInput());
setTreeViewer(tree);
tree.addSelectionChangedListener(this);
tree.expandAll();
tree.getControl().addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
handleKeyPressed(e);
}
});
return comp;
}
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection)event.getSelection();
if (!selection.isEmpty()) {
Object elem = selection.getFirstElement();
if (elem instanceof SootConfiguration) {
SootConfiguration sel = (SootConfiguration)elem;
setSelected(sel.getLabel());
}
enableButtons();
}
}
private void enableButtons(){
Iterator it = specialButtonList.iterator();
while (it.hasNext()){
((Button)it.next()).setEnabled(true);
}
}
protected void handleKeyPressed(KeyEvent e) {
}
private SootConfiguration getInitialInput() {
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
int numConfig = 0;
try {
numConfig = settings.getInt(Messages.getString("SootConfigManagerDialog.config_count")); //$NON-NLS-1$
}
catch(NumberFormatException e) {
}
SootConfiguration root = new SootConfiguration(""); //$NON-NLS-1$
if (numConfig != 0) {
String [] configNames = new String[numConfig];
for (int i = 0; i < numConfig; i++) {
configNames[i] = settings.get(Messages.getString("SootConfigManagerDialog.soot_run_config")+(i+1)); //$NON-NLS-1$
root.addChild(new SootConfiguration(configNames[i]));
}
}
setTreeRoot(root);
return root;
}
/*
* @see Dialog#createButtonBar(Composite)
*/
protected Control createSpecialButtonBar(Composite parent) {
Composite composite= new Composite(parent, SWT.NULL);
GridLayout layout= new GridLayout();
layout.numColumns= 1;
composite.setLayout(layout);
composite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
applyDialogFont(composite);
composite.setLayout(layout);
GridData data =
new GridData(
GridData.VERTICAL_ALIGN_END | GridData.HORIZONTAL_ALIGN_CENTER);
composite.setLayoutData(data);
// Add the buttons to the button bar.
createSpecialButtonsForButtonBar(composite);
return composite;
}
ArrayList specialButtonList = new ArrayList();
protected Button createSpecialButton(
Composite parent,
int id,
String label,
boolean defaultButton, boolean enabled) {
Button button = new Button(parent, SWT.PUSH);
button.setText(label);
button.setData(new Integer(id));
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent event) {
buttonPressed(((Integer) event.widget.getData()).intValue());
}
});
if (defaultButton) {
Shell shell = parent.getShell();
if (shell != null) {
shell.setDefaultButton(button);
}
}
button.setFont(parent.getFont());
if (!enabled){
button.setEnabled(false);
}
setButtonLayoutData(button);
specialButtonList.add(button);
return button;
}
protected void createButtonsForButtonBar(Composite parent){
//run and close will close dialog
Button runButton = createButton(parent, 5, Messages.getString("SootConfigManagerDialog.Run"), false); //$NON-NLS-1$
runButton.setEnabled(false);
specialButtonList.add(runButton);
createButton(parent, 6, Messages.getString("SootConfigManagerDialog.Close"), true); //$NON-NLS-1$
}
protected void createSpecialButtonsForButtonBar(Composite parent) {
createSpecialButton(parent, 0, Messages.getString("SootConfigManagerDialog.New"), false, true); //$NON-NLS-1$
createSpecialButton(parent, 1, Messages.getString("SootConfigManagerDialog.Edit"), false, false); //$NON-NLS-1$
createSpecialButton(parent, 2, Messages.getString("SootConfigManagerDialog.Delete"), false, false); //$NON-NLS-1$
createSpecialButton(parent, 3, Messages.getString("SootConfigManagerDialog.Rename"), false, false); //$NON-NLS-1$
createSpecialButton(parent, 4, Messages.getString("SootConfigManagerDialog.Clone"), false, false); //$NON-NLS-1$
}
protected void buttonPressed(int id) {
switch (id) {
case 0: {
newPressed();
break;
}
case 1: {
editPressed();
break;
}
case 2: {
deletePressed();
break;
}
case 3: {
renamePressed();
break;
}
case 4: {
clonePressed();
break;
}
case 5: {
runPressed();
break;
}
case 6: {
cancelPressed();
break;
}
case 7: {
break;
}
case 8: {
break;
}
}
}
// shows a phaseOptionsDialog with save and close buttons
// only and asks for a name first
private void newPressed() {
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
// gets current number of configurations before adding any
int config_count = 0;
try {
config_count = settings.getInt(Messages.getString("SootConfigManagerDialog.config_count")); //$NON-NLS-1$
}
catch (NumberFormatException e) {
}
ArrayList currentNames = new ArrayList();
for (int i = 1; i <= config_count; i++) {
currentNames.add(settings.get(Messages.getString("SootConfigManagerDialog.soot_run_config")+i)); //$NON-NLS-1$
}
// sets validator to know about already used names - but it doesn't use
// them because then editing a file cannot use same file name
SootConfigNameInputValidator validator = new SootConfigNameInputValidator();
validator.setAlreadyUsed(currentNames);
// create dialog to get name
InputDialog nameDialog = new InputDialog(this.getShell(), Messages.getString("SootConfigManagerDialog.Saving_Configuration_Name"), Messages.getString("SootConfigManagerDialog.Enter_name_to_save_configuration_with"), "", validator); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
nameDialog.open();
if (nameDialog.getReturnCode() == Dialog.OK) {
setEditDefs(null);
int returnCode = displayOptions(nameDialog.getValue(), "soot.Main");
//handle selection of main class here
if (returnCode != Dialog.CANCEL) {
getTreeRoot().addChild(new SootConfiguration(nameDialog.getValue()));
refreshTree();
}
}
else {
// cancel and do nothing
}
}
// saves the main class to run with this configuration
private void saveMainClass(String configName, String mainClass){
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
settings.put(configName+"_mainClass", mainClass);
}
// returns the main class to run with this configuration
private String getMainClass(String configName){
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
String mainClass = settings.get(configName+"_mainClass");
if ((mainClass == null) || (mainClass.length() == 0)){
return "soot.Main";
}
else {
return mainClass;
}
}
private ArrayList stringToList(String string){
StringTokenizer st = new StringTokenizer(string, ",");
ArrayList list = new ArrayList();
while (st.hasMoreTokens()){
list.add(st.nextToken());
}
return list;
}
private void refreshTree() {
getTreeViewer().setInput(getTreeRoot());
getTreeViewer().setExpandedState(getTreeRoot(), true);
getTreeViewer().refresh(getTreeRoot(), false);
}
private int displayOptions(String name) {
return displayOptions(name, "soot.Main");
}
private int displayOptions(String name, String mainClass) {
PhaseOptionsDialog dialog = new PhaseOptionsDialog(getShell());
addEclipseDefsToDialog(dialog);
setMainClassInDialog(dialog, mainClass);
if (getEditDefs() != null) {
Iterator it = getEditDefs().keySet().iterator();
while (it.hasNext()) {
Object next = it.next();
String key = (String)next;
String val = (String)getEditDefs().get(key);
if ((val.equals("true")) || (val.equals("false"))) { //$NON-NLS-1$ //$NON-NLS-2$
dialog.addToDefList(key, new Boolean(val));
}
else {
dialog.addToDefList(key, val);
}
}
}
dialog.setConfigName(name);
dialog.setCanRun(false);
dialog.open();
if (dialog.getReturnCode() == Dialog.OK){
//save main class
saveMainClass(name, dialog.getSootMainClass());
}
return dialog.getReturnCode();
// saved - should show up in tree
}
// same as newPressed except does not ask for name
private void editPressed() {
if (getSelected() == null) return;
String result = this.getSelected();
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
String [] saveArray = settings.getArray(result);
SootSavedConfiguration ssc = new SootSavedConfiguration(result, saveArray);
setEditDefs(ssc.toHashMapFromArray());
displayOptions(result, getMainClass(result));
}
// removes form tree
private void deletePressed() {
if (getSelected() == null) return;
String result = this.getSelected();
// maybe ask if they are sure here first
MessageDialog msgDialog = new MessageDialog(this.getShell(), Messages.getString("SootConfigManagerDialog.Soot_Configuration_Remove_Message"), null, Messages.getString("SootConfigManagerDialog.Are_you_sure_you_want_to_remove_this_configuration"), 0, new String [] {Messages.getString("SootConfigManagerDialog.Yes"), Messages.getString("SootConfigManagerDialog.No")}, 0); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
msgDialog.open();
if (msgDialog.getReturnCode() == 0) {
// do the delete
ArrayList toRemove = new ArrayList();
toRemove.add(result);
SavedConfigManager scm = new SavedConfigManager();
scm.setDeleteList(toRemove);
scm.handleDeletes();
// remove also from tree
getTreeRoot().removeChild(result);
refreshTree();
}
}
private void renamePressed(){
if (getSelected() == null) return;
String result = this.getSelected();
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
// gets current number of configurations
int config_count = 0;
int oldNameCount = 0;
try {
config_count = settings.getInt(Messages.getString("SootConfigManagerDialog.config_count")); //$NON-NLS-1$
}
catch (NumberFormatException e) {
}
ArrayList currentNames = new ArrayList();
for (int i = 1; i <= config_count; i++) {
currentNames.add(settings.get(Messages.getString("SootConfigManagerDialog.soot_run_config")+i)); //$NON-NLS-1$
if (((String)currentNames.get(i-1)).equals(result)){
oldNameCount = i;
}
}
// sets validator to know about already used names
SootConfigNameInputValidator validator = new SootConfigNameInputValidator();
validator.setAlreadyUsed(currentNames);
InputDialog nameDialog = new InputDialog(this.getShell(), Messages.getString("SootConfigManagerDialog.Rename_Saved_Configuration"), Messages.getString("SootConfigManagerDialog.Enter_new_name"), "", validator); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
nameDialog.open();
if (nameDialog.getReturnCode() == Dialog.OK){
settings.put(Messages.getString("SootConfigManagerDialog.soot_run_config")+oldNameCount, nameDialog.getValue()); //$NON-NLS-1$
settings.put(nameDialog.getValue(), settings.getArray(result));
getTreeRoot().renameChild(result, nameDialog.getValue());
saveMainClass(nameDialog.getValue(), settings.get(result+"_mainClass"));
}
refreshTree();
}
private void clonePressed(){
if (getSelected() == null) return;
String result = this.getSelected();
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
// gets current number of configurations
int config_count = 0;
try {
config_count = settings.getInt(Messages.getString("SootConfigManagerDialog.config_count")); //$NON-NLS-1$
}
catch (NumberFormatException e) {
}
ArrayList currentNames = new ArrayList();
for (int i = 1; i <= config_count; i++) {
currentNames.add(settings.get(Messages.getString("SootConfigManagerDialog.soot_run_config")+i)); //$NON-NLS-1$
}
// sets validator to know about already used names
SootConfigNameInputValidator validator = new SootConfigNameInputValidator();
validator.setAlreadyUsed(currentNames);
InputDialog nameDialog = new InputDialog(this.getShell(), Messages.getString("SootConfigManagerDialog.Clone_Saved_Configuration"), Messages.getString("SootConfigManagerDialog.Enter_new_name"), result, validator); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
nameDialog.open();
if (nameDialog.getReturnCode() == Dialog.OK){
config_count++;
settings.put(Messages.getString("SootConfigManagerDialog.soot_run_config")+config_count, nameDialog.getValue()); //$NON-NLS-1$
settings.put(nameDialog.getValue(), settings.getArray(result));
settings.put(Messages.getString("SootConfigManagerDialog.config_count"), config_count); //$NON-NLS-1$
getTreeRoot().addChild(new SootConfiguration(nameDialog.getValue()));
saveMainClass(nameDialog.getValue(), settings.get(result+"_mainClass"));
}
refreshTree();
}
// runs the config
private void runPressed() {
super.okPressed();
if (getSelected() == null) return;
IDialogSettings settings = SootPlugin.getDefault().getDialogSettings();
String mainClass = settings.get(getSelected()+"_mainClass");
if (getLauncher() instanceof SootConfigProjectLauncher) {
((SootConfigProjectLauncher)getLauncher()).launch(getSelected(), mainClass);
}
else if (getLauncher() instanceof SootConfigJavaProjectLauncher){
((SootConfigJavaProjectLauncher)getLauncher()).launch(getSelected(), mainClass);
}
else if (getLauncher() instanceof SootConfigFileLauncher) {
((SootConfigFileLauncher)getLauncher()).launch(getSelected(), mainClass);
}
else if (getLauncher() instanceof SootConfigFromJavaFileLauncher){
((SootConfigFromJavaFileLauncher)getLauncher()).launch(getSelected(), mainClass);
}
}
private void importPressed(){
}
/**
* Returns the sashForm.
* @return SashForm
*/
public SashForm getSashForm() {
return sashForm;
}
/**
* Sets the sashForm.
* @param sashForm The sashForm to set
*/
public void setSashForm(SashForm sashForm) {
this.sashForm = sashForm;
}
/**
* Returns the selectionArea.
* @return Composite
*/
public Composite getSelectionArea() {
return selectionArea;
}
/**
* Returns the treeViewer.
* @return TreeViewer
*/
public TreeViewer getTreeViewer() {
return treeViewer;
}
/**
* Sets the selectionArea.
* @param selectionArea The selectionArea to set
*/
public void setSelectionArea(Composite selectionArea) {
this.selectionArea = selectionArea;
}
/**
* Sets the treeViewer.
* @param treeViewer The treeViewer to set
*/
public void setTreeViewer(TreeViewer treeViewer) {
this.treeViewer = treeViewer;
}
/**
* Returns the selected.
* @return String
*/
public String getSelected() {
return selected;
}
/**
* Sets the selected.
* @param selected The selected to set
*/
public void setSelected(String selected) {
this.selected = selected;
}
/**
* Returns the buttonPanel.
* @return Composite
*/
public Composite getButtonPanel() {
return buttonPanel;
}
/**
* Sets the buttonPanel.
* @param buttonPanel The buttonPanel to set
*/
public void setButtonPanel(Composite buttonPanel) {
this.buttonPanel = buttonPanel;
}
/**
* Returns the treeRoot.
* @return SootConfiguration
*/
public SootConfiguration getTreeRoot() {
return treeRoot;
}
/**
* Sets the treeRoot.
* @param treeRoot The treeRoot to set
*/
public void setTreeRoot(SootConfiguration treeRoot) {
this.treeRoot = treeRoot;
}
/**
* Returns the editDefs.
* @return HashMap
*/
public HashMap getEditDefs() {
return editDefs;
}
/**
* Sets the editDefs.
* @param editDefs The editDefs to set
*/
public void setEditDefs(HashMap editDefs) {
this.editDefs = editDefs;
}
/**
* Returns the launcher.
* @return SootLauncher
*/
public SootLauncher getLauncher() {
return launcher;
}
/**
* Sets the launcher.
* @param launcher The launcher to set
*/
public void setLauncher(SootLauncher launcher) {
this.launcher = launcher;
}
}