Index: /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Command.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Command.java	(revision 22184)
+++ /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Command.java	(revision 22185)
@@ -32,5 +32,5 @@
 		}
 		else{
-		    _osCommands.put(os, ExtXMLHelper.getValueFromSingleElement(currentCommand, true));
+		    _osCommands.put(os, ExtXMLHelper.getValueFromSingleElement(currentCommand, false));
 		}
 	    }
Index: /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Option.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Option.java	(revision 22184)
+++ /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Option.java	(revision 22185)
@@ -1,3 +1,11 @@
 package org.greenstone.admin.guiext;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTable;
+
+import org.greenstone.admin.GAI;
 
 import org.w3c.dom.Element;
@@ -5,8 +13,21 @@
 public class Option
 {
-    String _name = null;
-    String _id = null;
-    String _value = null;    
-    OptionList _parent = null;
+    protected String _type = null;
+    protected String _name = null;
+    protected String _id = null;
+    protected String _value = null;    
+    protected OptionList _parent = null;
+    
+    protected Object _classObject = null;
+    protected Method _checkMethod = null;
+
+    protected ImageIcon _image = null;
+
+    private boolean _canCheck = false;
+    private int _checkResult = -1;
+
+    private final String GOOD_ICON = GAI.getGSDL3Home() + System.getProperty("file.separator") + "resources" + System.getProperty("file.separator") + "images" + System.getProperty("file.separator") + "icongreentick.png";
+    private final String BAD_ICON = GAI.getGSDL3Home() + System.getProperty("file.separator") + "resources" + System.getProperty("file.separator") + "images" + System.getProperty("file.separator") + "iconredexclamation.png";
+    private final String ERROR_ICON = GAI.getGSDL3Home() + System.getProperty("file.separator") + "resources" + System.getProperty("file.separator") + "images" + System.getProperty("file.separator") + "iconorangetriange.png";
 
     public Option(Element optionElement, OptionList parent)
@@ -30,4 +51,19 @@
 		_value = "";
 	    }
+
+	    String checkClass = optionElement.getAttribute("checkClass");
+	    String checkMethod = optionElement.getAttribute("checkMethod");
+
+	    if(!checkClass.equals("") && !checkMethod.equals("")){
+		loadCheckMethod(checkClass, checkMethod);
+	    }
+
+	    performCheck();
+
+	    _type = optionElement.getAttribute("type");
+	    
+	    if(!(_type.equals("") || _type.equals("password") || _type.equals("filebrowse") || _type.equals("folderbrowse"))){
+		System.err.println("This option element specifies a type that is not \"password\", \"filebrowse\" or \"folderbrowse\"");	    
+	    }
 	}
 	else{
@@ -35,4 +71,89 @@
 	}
     }
+
+    private void loadCheckMethod(String checkClassString, String checkMethodString)
+    {
+	_parent.getParent().getParent().getParent().loadGuiExtFile();
+	
+	Class checkClass = null;
+	try{
+	    checkClass = Class.forName(checkClassString);
+	}
+	catch(Exception ex){
+	    System.err.println("Could not get an instance of the check class, either the class name is incorrect or the class does not exist inside the guiext.jar file");
+	    return;
+	}
+	
+	try{
+	    Constructor classConstructor = checkClass.getConstructor(new Class[0]);
+	    _classObject = classConstructor.newInstance(new Object[0]);
+	}
+	catch(Exception ex){
+	    System.err.println("Could not instantiate the check class, either the class name is incorrect or the class does not exist inside the guiext.jar file");
+	    return;
+	}
+
+	try{
+	    _checkMethod = checkClass.getDeclaredMethod(checkMethodString, new Class[]{Object.class});
+	}
+	catch(Exception ex){
+	    System.err.println("Could not get the check method, either the method name is incorrect or the method does not take an Object as a parameter");
+	    return;
+	}
+	   
+	if(!(_checkMethod.getReturnType().equals(Boolean.TYPE))){
+	    System.err.println("The check method does not return a boolean value as is required");
+	    return;
+	}
+	_canCheck = true;
+    }
+
+    private void setImageFromCheck()
+    {
+	if(_canCheck){
+	    if(_checkResult == 0){
+		_image = new ImageIcon(GOOD_ICON);
+	    }
+	    else if(_checkResult == 1){
+		_image = new ImageIcon(BAD_ICON);
+	    }
+	    else{
+		_image = new ImageIcon(ERROR_ICON);
+	    }
+	}
+	else{
+	    _image = new ImageIcon(GOOD_ICON);
+	}
+    }
+    
+    private void performCheck()
+    {
+	if(_canCheck){
+	    Boolean result = null;
+	    try{
+		result = ((Boolean)_checkMethod.invoke(_classObject, new Object[]{_value}));
+	    }
+	    catch(Exception ex){
+		_checkResult = -1;
+	    }
+	    if(result){
+		_checkResult = 0;
+	    }
+	    else{
+		_checkResult = 1;
+	    }
+	}
+	setImageFromCheck();
+    }
+
+    public boolean isCheckable()
+    {
+	return _canCheck;
+    }
+
+    public int getCheckResult()
+    {
+	return _checkResult;
+    }
     
     public String getName()
@@ -49,4 +170,12 @@
     {
 	_value = value;
+	performCheck();
+
+	JTable table = _parent.getParent().getTableFromOptionList(_parent);
+	
+	if(table != null){
+	    table.repaint();
+	    table.revalidate();
+	}
     }
 
@@ -60,3 +189,13 @@
 	return _parent;
     }
+    
+    public String getType()
+    {
+	return _type;
+    }
+
+    public ImageIcon getImage()
+    {
+	return _image;
+    }
 }
Index: /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/PropertiesStep.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/PropertiesStep.java	(revision 22184)
+++ /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/PropertiesStep.java	(revision 22185)
@@ -1,15 +1,32 @@
 package org.greenstone.admin.guiext;
 
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+
+import javax.crypto.spec.SecretKeySpec;
+
+import javax.swing.AbstractCellEditor;
 import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
 import javax.swing.JLabel;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
-import javax.swing.JFrame;
-import javax.swing.JButton;
+import javax.swing.JPasswordField;
 import javax.swing.JScrollPane;
 import javax.swing.JTable;
+import javax.swing.JTextField;
 import javax.swing.SwingConstants;
+
+import javax.swing.event.DocumentListener;
+import javax.swing.event.DocumentEvent;
 
 import javax.swing.table.AbstractTableModel;
 import javax.swing.table.TableCellEditor;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableModel;
 
 import java.awt.event.ActionListener;
@@ -20,8 +37,11 @@
 import java.awt.BorderLayout;
 import java.awt.Color;
+import java.awt.Component;
 import java.awt.Font;
 import java.awt.GridLayout;
 
 import java.util.Properties;
+import java.util.Arrays;
+import java.util.HashMap;
 
 import java.io.File;
@@ -39,4 +59,6 @@
     JTable[] _tables = null;
     OptionList[] _modifiedOptionLists = null;
+    
+    HashMap _optionListTableMap = new HashMap();
 
     public PropertiesStep(Element propertiesStepElement, SequenceList parent)
@@ -80,4 +102,9 @@
 	    }
 	}
+    }
+
+    public JTable getTableFromOptionList(OptionList list)
+    {
+	return ((JTable)_optionListTableMap.get(list));
     }
 
@@ -114,5 +141,14 @@
 		Option[] options = currentList.getOptions();		
 
-		JTable propertiesTable = new JTable(new CustomTableModel(new String[]{"Setting", "Value"}, options));
+		CustomTableModel tableModel = new CustomTableModel(new String[]{"Setting", "Value", "Check"}, options);
+		PropertyTable propertiesTable = new PropertyTable(tableModel, currentList);
+		TableColumn column = propertiesTable.getColumnModel().getColumn(2);
+		column.setPreferredWidth(32);
+		column.setMinWidth(32);
+		column.setMaxWidth(32);
+		column.setResizable(false);
+
+		_optionListTableMap.put(currentList, propertiesTable);
+
 		//The line below is necessary as the default grid colour on mac is white, which makes the lines invisible.
 		propertiesTable.setGridColor(Color.BLACK);
@@ -148,4 +184,259 @@
 	    
 	    _parent.getParent().changeExtPane(mainPanel);
+	}
+    }
+
+    public class BrowseButtonListener implements ActionListener
+    {
+	Option _option = null;
+	JTextField _path = null;
+	JFileChooser _browser = null;
+	
+	public BrowseButtonListener(Option option, JTextField path)
+	{
+	    _option = option;
+	    _path = path;
+	    _browser = new JFileChooser();
+	}
+	
+	public void actionPerformed(ActionEvent e)
+	{
+	    if(e.getActionCommand().equals("edit")){
+		if(_option.getType().equalsIgnoreCase("folderbrowse")){
+		    _browser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+		}
+		int returnValue = _browser.showOpenDialog(null);
+
+		if(returnValue == JFileChooser.APPROVE_OPTION){
+		    _option.setValue(_browser.getSelectedFile().getAbsolutePath());
+		    _path.setText(_option.getValue());
+		}
+	    }
+	}
+    }
+
+    public class PathBoxListener implements DocumentListener
+    {
+	Option _option = null;
+	JTextField _path = null;
+
+	public PathBoxListener(Option option, JTextField path)
+	{
+	    _option = option;
+	    _path = path;
+	}
+	
+	public void changedUpdate(DocumentEvent e)
+	{
+	    _option.setValue(_path.getText());
+	}
+	
+	public void insertUpdate(DocumentEvent e)
+	{
+	    _option.setValue(_path.getText());
+	}
+
+	public void removeUpdate(DocumentEvent e)
+	{
+	    _option.setValue(_path.getText());
+	}
+    }
+
+    public class PasswordOKButtonListener implements ActionListener
+    {
+	JPasswordField _password = null;
+	JPasswordField _confirm = null;
+	Option _option = null;
+	JFrame _passwordFrame = null;
+
+	public PasswordOKButtonListener(JPasswordField password, JPasswordField confirm, Option option, JFrame passwordFrame)
+	{
+	    _password = password;
+	    _confirm = confirm;
+	    _option = option;
+	    _passwordFrame = passwordFrame;
+	}
+
+	public void actionPerformed(ActionEvent e)
+	{
+	    if(Arrays.equals(_password.getPassword(), _confirm.getPassword())){
+		try{
+		    _option.setValue(new String(encrypt(_password.getPassword())));
+		}
+		catch(Exception ex){
+		    System.err.println("Error encrypting password");
+		}
+		_passwordFrame.dispose();
+	    }
+	    else{
+		JOptionPane.showMessageDialog(null, "The passwords you entered do not match.");
+		_password.setText("");
+		_confirm.setText("");
+	    }
+	}
+    }  
+
+    public static char[] encrypt(char[] value) throws Exception
+    {
+	byte[] salt = {'T', 'p'};
+	int count = 20;
+
+	KeyGenerator keygen = KeyGenerator.getInstance("AES");
+        SecretKey secretKey = keygen.generateKey();
+        byte[] raw = secretKey.getEncoded();
+        SecretKeySpec secretKeySpec = new SecretKeySpec(raw, "AES");
+
+	Cipher cipher = Cipher.getInstance("AES");
+	cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);
+	
+	byte[] encryptedPassword = cipher.doFinal((new String(value)).getBytes("UTF-8"));
+
+	return new String(encryptedPassword).toCharArray();
+    }
+
+    public class PasswordCancelButtonListener implements ActionListener
+    {
+	JFrame _passwordFrame = new JFrame();
+
+	public PasswordCancelButtonListener(JFrame passwordFrame)
+	{
+	    _passwordFrame = passwordFrame;
+	}
+
+	public void actionPerformed(ActionEvent e)
+	{
+	    _passwordFrame.dispose();
+	}
+    }
+
+    public class PasswordFieldListener implements ActionListener
+    {
+	JPasswordField _password = new JPasswordField(10);
+	JPasswordField _confirm = new JPasswordField(10);
+	JFrame _passwordFrame = new JFrame("Enter password");
+
+	public PasswordFieldListener(Option option)
+	{
+	    JButton okButton = new JButton("Change");
+	    JButton cancelButton = new JButton("Cancel");
+	    
+	    okButton.addActionListener(new PasswordOKButtonListener(_password, _confirm, option, _passwordFrame));
+	    cancelButton.addActionListener(new PasswordCancelButtonListener(_passwordFrame));
+
+	    _passwordFrame.getContentPane().setLayout(new GridLayout(3,2));
+	    _passwordFrame.getContentPane().add(new JLabel("Password:"));
+	    _passwordFrame.getContentPane().add(_password);
+	    _passwordFrame.getContentPane().add(new JLabel("Confirm:"));
+	    _passwordFrame.getContentPane().add(_confirm);
+	    _passwordFrame.getContentPane().add(okButton);
+	    _passwordFrame.getContentPane().add(cancelButton);
+	    _passwordFrame.pack();
+	}
+	
+	public void actionPerformed(ActionEvent e)
+	{
+	    _password.setText("");
+	    _confirm.setText("");
+	    _passwordFrame.setLocationRelativeTo(null);
+	    _passwordFrame.setVisible(true);
+	}
+    }
+
+    public class PasswordEditor extends AbstractCellEditor implements TableCellEditor
+    {
+	JButton _onClickButton = new JButton("Change Password?");
+
+	public PasswordEditor(Option option)
+	{
+	    _onClickButton.addActionListener(new PasswordFieldListener(option));
+	}
+
+	public Object getCellEditorValue()
+	{
+	    return "";
+	}
+
+	public Component getTableCellEditorComponent(JTable table, Object path, boolean isSelected, int row, int column)
+	{
+	    return _onClickButton;
+	}
+    }
+
+    public class BrowseEditor extends AbstractCellEditor implements TableCellEditor
+    {
+	JPanel _browserPanel = null;
+	JTextField _path = null;
+	JButton _browserButton = null;
+	Option _option = null;
+	String _type = null;
+
+	public BrowseEditor(Option option, String type)
+	{
+	    _option = option;
+	    _type = type;
+	    
+	    _path = new JTextField(_option.getValue());
+	    _path.getDocument().addDocumentListener(new PathBoxListener(_option, _path));
+
+	    _browserButton = new JButton("Browse");
+	    _browserButton.setActionCommand("edit");
+	    _browserButton.addActionListener(new BrowseButtonListener(_option, _path));
+	    _browserButton.setBorderPainted(false);
+
+	    _browserPanel = new JPanel();
+	    _browserPanel.setLayout(new BorderLayout());
+	    _browserPanel.add(_path, BorderLayout.CENTER);
+	    _browserPanel.add(_browserButton, BorderLayout.EAST);
+	}
+
+	public Object getCellEditorValue()
+	{
+	    _path.setText(_option.getValue());
+	    return _option.getValue();
+	}
+
+	public Component getTableCellEditorComponent(JTable table, Object path, boolean isSelected, int row, int column)
+	{
+	    return _browserPanel;
+	}
+    }
+
+    public class PropertyTable extends JTable 
+    {
+	OptionList _properties = null;
+	TableCellEditor[] _editors = null;
+
+	public PropertyTable(TableModel tm, OptionList properties)
+	{
+	    super(tm);
+	    _properties = properties;
+	    
+	    Option[] options = _properties.getOptions();
+	    _editors = new TableCellEditor[options.length];
+
+	    for(int i = 0; i < options.length; i++){
+		Option currentOption = options[i];
+
+		if(currentOption.getType().equals("filebrowse")){
+		    _editors[i] = new BrowseEditor(currentOption, "file");
+		}
+		else if(currentOption.getType().equals("folderbrowse")){
+		    _editors[i] = new BrowseEditor(currentOption, "folder");
+		}
+		else if(currentOption.getType().equals("password")){
+		    _editors[i] = new PasswordEditor(currentOption);
+		}
+		else{
+		    _editors[i] = null;
+		}
+	    }
+	}
+
+	public TableCellEditor getCellEditor(int row, int column)
+	{
+	    if(column == 1 && row < _editors.length && _editors[row] != null){
+		return _editors[row];
+	    }
+	    return super.getCellEditor(row, column);
 	}
     }
@@ -225,10 +516,16 @@
     public class CustomTableModel extends AbstractTableModel
     {
-	private String[] _columnNames;
-    	private Option[] _data;
+	private String[] _columnNames = null;
+    	private Option[] _data = null;
+	private ImageIcon[] _images = null;
 	
     	public CustomTableModel(String[] columnNames, Option[] data){
 	    _columnNames = columnNames;
 	    _data = data;
+	    
+	    _images = new ImageIcon[_data.length];
+	    for(int i = 0; i < _data.length; i++){
+		_images[i] = _data[i].getImage();
+	    }
     	}
 	
@@ -246,10 +543,19 @@
 
         public Object getValueAt(int row, int col) {
-	    Option o = _data[row];
 	    if(col == 0){
-		return o.getName();
+		return _data[row].getName();
 	    }
 	    else if(col == 1){
-		return o.getValue();
+		if(_data[row].getType().equals("password") && !_data[row].getValue().equals("")){
+		    return "Password Set";
+		}
+		else if(_data[row].getType().equals("password") && _data[row].getValue().equals("")){
+		    return "No Password Set";
+		}
+		
+		return _data[row].getValue();
+	    }
+	    else if(col == 2){
+		return _data[row].getImage();
 	    }
             else{
@@ -264,14 +570,19 @@
 
 	public boolean isCellEditable(int row, int col) {
-	    if (col < 1) {
+	    if (col == 1) {
+                return true;
+            } else {
                 return false;
-            } else {
-                return true;
             }
         }
 	
         public void setValueAt(Object value, int row, int col) {
-	    if(isCellEditable(row, col)){
-		_data[row].setValue((String)value);
+	    Option o = _data[row];
+	    if(isCellEditable(row, col) && !o.getType().equals("password")){
+		o.setValue((String)value);
+		
+		if(o.isCheckable()){
+		    _images[row] = o.getImage();
+		}
 	    }
 	    fireTableDataChanged();
Index: /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/SequenceList.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/SequenceList.java	(revision 22184)
+++ /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/SequenceList.java	(revision 22185)
@@ -201,7 +201,12 @@
     {
 	loadExtensionStatesFromFile();
-	
+
 	ExtensionInformation currentExtension = _parent;
 	String fileStem = currentExtension.getFileStem();
+
+	File extDir = new File(currentExtension.getExtensionDirectory());
+	if(!extDir.exists()){
+	    rollbackTo("");
+	}
 	
 	for(int i = 0; i < _steps.size(); i++){
Index: /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Step.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Step.java	(revision 22184)
+++ /main/trunk/greenstone3/src/java/org/greenstone/admin/guiext/Step.java	(revision 22185)
@@ -9,15 +9,4 @@
 import javax.swing.JTextArea;
 import javax.swing.JPanel;
-
-/*
-if(_commonMessageArea == null){
-	    _commonMessageArea = new JTextArea();
-	    _commonMessageArea.setEditable(false);
-	    _commonMessageArea.setAutoscrolls(true);
-	    _commonMessageArea.setLineWrap(true);
-	    _commonMessageArea.setWrapStyleWord(true);
-	    _commonMessageArea.setMargin(new Insets(0,5,0,0));
-	}
-*/
 
 public class Step
