package eu.doppel_helix.netbeans.mantisintegration.repository;
import biz.futureware.mantisconnect.ObjectRef;
import eu.doppel_helix.netbeans.mantisintegration.MantisConnector;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigInteger;
import java.net.MalformedURLException;
import java.net.URI;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.SwingWorker;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.xml.rpc.ServiceException;
import org.netbeans.modules.bugtracking.spi.RepositoryController;
import org.netbeans.modules.bugtracking.spi.RepositoryInfo;
import org.openide.util.ChangeSupport;
import org.openide.util.HelpCtx;
import org.openide.util.Mutex;
public class MantisRepositoryController implements RepositoryController, DocumentListener, ChangeListener, ActionListener {
private final static Logger logger = Logger.getLogger(MantisRepositoryController.class.getName());
private final static String COMMAND_CHECKCONNECTION = "checkConnection";
private final static String COMMAND_SELECTSTATUS = "selectStatus";
private final static String COMMAND_SELECTRESOLUTION = "selectResolution";
private final static Color errorColor = new Color( 205, 0, 0);
private final static Color goodColor = new Color( 7, 155, 0);
private final MantisRepository repository;
private MantisRepositoryPanel panel;
private final List<String> errorMessages = new ArrayList<>();
private final ChangeSupport cs = new ChangeSupport(this);
private boolean checking = false;
private final DefaultComboBoxModel<ObjectRef> resolutionModel = new DefaultComboBoxModel<>();
private final DefaultComboBoxModel<ObjectRef> statusModel = new DefaultComboBoxModel<>();
private ObjectRef resolution = null;
private ObjectRef status = null;
public MantisRepositoryController(MantisRepository repository) {
this.repository = repository;
}
@Override
public JComponent getComponent() {
if(panel == null) {
panel = new MantisRepositoryPanel();
panel.nameTextField.getDocument().addDocumentListener(this);
panel.urlTextField.getDocument().addDocumentListener(this);
panel.usernameTextField.getDocument().addDocumentListener(this);
panel.passwordTextField.getDocument().addDocumentListener(this);
panel.httpAuthEnabled.addActionListener(this);
panel.httpUserField.getDocument().addDocumentListener(this);
panel.httpPwdField.getDocument().addDocumentListener(this);
cs.addChangeListener(this);
panel.checkButton.addActionListener(this);
panel.checkButton.setActionCommand(COMMAND_CHECKCONNECTION);
panel.resolutionComboBox.setModel(resolutionModel);
panel.resolutionComboBox.setActionCommand(COMMAND_SELECTRESOLUTION);
panel.resolutionComboBox.addActionListener(this);
panel.statusComboBox.setModel(statusModel);
panel.statusComboBox.setActionCommand(COMMAND_SELECTSTATUS);
panel.statusComboBox.addActionListener(this);
populate();
}
return panel;
}
@Override
public HelpCtx getHelpCtx() {
return new HelpCtx(getClass().getName());
}
@Override
public boolean isValid() {
errorMessages.clear();
String name = panel.nameTextField.getText();
String url = panel.urlTextField.getText();
String username = panel.usernameTextField.getText();
String password = panel.passwordTextField.getText();
if(name.isEmpty()) {
errorMessages.add("No name specified");
}
try {
URI.create(url).toURL();
} catch (IllegalArgumentException | MalformedURLException ex) {
errorMessages.add("Invalid URL provided");
}
if(username.trim().isEmpty() || password.trim().isEmpty()) {
errorMessages.add("Username or password empty");
}
return errorMessages.isEmpty() && (! checking);
}
@Override
public void populate() {
RepositoryInfo ri = repository.getInfo();
if(panel != null && ri != null) {
panel.nameTextField.setText(ri.getDisplayName());
panel.urlTextField.setText(ri.getUrl());
panel.usernameTextField.setText(ri.getUsername());
panel.passwordTextField.setText(new String(ri.getPassword()));
if(ri.getValue(MantisRepository.PROP_SCHEDULE_DATE_FIELD) != null) {
panel.scheduleDateFieldCustom.setSelected(true);
panel.scheduleDateFieldCustomName.setText(ri.getValue(MantisRepository.PROP_SCHEDULE_DATE_FIELD));
} else {
panel.scheduleDateFieldBuiltIn.setSelected(true);
panel.scheduleDateFieldCustomName.setText("");
}
if(ri.getValue(MantisRepository.PROP_SCHEDULE_LENGTH_FIELD) != null) {
panel.scheduleLengthFieldCustom.setSelected(true);
panel.scheduleLengthFieldCustomName.setText(ri.getValue(MantisRepository.PROP_SCHEDULE_LENGTH_FIELD));
} else {
panel.scheduleLengthFieldBuiltIn.setSelected(true);
panel.scheduleLengthFieldCustomName.setText("");
}
if(ri.getHttpUsername() != null && (! ri.getHttpUsername().isEmpty())
&& ri.getHttpPassword() != null && ri.getHttpPassword().length > 0) {
panel.httpAuthEnabled.setSelected(true);
} else {
panel.httpAuthEnabled.setSelected(false);
}
panel.httpPwdField.setEnabled((! checking) && panel.httpAuthEnabled.isSelected());
panel.httpUserField.setEnabled((! checking) && panel.httpAuthEnabled.isSelected());
panel.httpUserField.setText(ri.getHttpUsername());
panel.httpPwdField.setText(new String(ri.getHttpPassword()));
status = MantisRepository.readObjectRef(ri, MantisRepository.PROP_COMMIT_STATUS_FIELD);
resolution = MantisRepository.readObjectRef(ri, MantisRepository.PROP_COMMIT_RESOLUTION_FIELD);
updateModel(statusModel, status);
updateModel(resolutionModel, resolution);
}
}
@Override
public String getErrorMessage() {
StringBuilder message = new StringBuilder();
for(String m: errorMessages) {
if(message.length() != 0) {
message.append(", ");
}
message.append(m);
}
return message.toString();
}
@Override
public void addChangeListener(ChangeListener l) {
cs.addChangeListener(l);
}
@Override
public void removeChangeListener(ChangeListener l) {
cs.removeChangeListener(l);
}
@Override
public void insertUpdate(DocumentEvent e) {
cs.fireChange();
}
@Override
public void removeUpdate(DocumentEvent e) {
cs.fireChange();
}
@Override
public void changedUpdate(DocumentEvent e) {
cs.fireChange();
}
public boolean isChecking() {
return checking;
}
public void setChecking(boolean checking) {
this.checking = checking;
cs.fireChange();
}
@Override
public void stateChanged(ChangeEvent e) {
Mutex.EVENT.readAccess(new Runnable() {
@Override
public void run() {
panel.checkButton.setEnabled(! checking);
panel.nameTextField.setEnabled(! checking);
panel.urlTextField.setEnabled(! checking);
panel.usernameTextField.setEnabled(! checking);
panel.passwordTextField.setEnabled(! checking);
panel.httpAuthEnabled.setEnabled(! checking);
panel.httpPwdField.setEnabled((! checking) && panel.httpAuthEnabled.isSelected());
panel.httpUserField.setEnabled((! checking) && panel.httpAuthEnabled.isSelected());
}
});
if(isValid()) {
panel.checkButton.setEnabled(true);
} else {
panel.checkButton.setEnabled(false);
}
}
@Override
public void actionPerformed(ActionEvent e) {
switch (e.getActionCommand()) {
case COMMAND_SELECTRESOLUTION:
ObjectRef selectedRes = (ObjectRef) panel.resolutionComboBox.getSelectedItem();
if(selectedRes == null) {
resolution = null;
} else if (selectedRes.getId().compareTo(BigInteger.ZERO) >= 0) {
resolution = selectedRes;
} else {
checkConnection();
}
break;
case COMMAND_SELECTSTATUS:
ObjectRef selectedStatus = (ObjectRef) panel.statusComboBox.getSelectedItem();
if(selectedStatus == null) {
status = null;
} else if (selectedStatus.getId().compareTo(BigInteger.ZERO) >= 0) {
status = selectedStatus;
} else {
checkConnection();
}
break;
case COMMAND_CHECKCONNECTION:
checkConnection();
break;
case "httpAuth":
if (!panel.httpAuthEnabled.isSelected()) {
panel.httpUserField.setText("");
panel.httpPwdField.setText("");
}
cs.fireChange();
break;
}
}
private void checkConnection() {
setChecking(true);
final String httpUsername;
final String httpPassword;
if (panel.httpAuthEnabled.isSelected()) {
httpUsername = panel.httpUserField.getText();
httpPassword = panel.httpPwdField.getText();
} else {
httpUsername = "";
httpPassword = "";
}
new SwingWorker<Object, Object>() {
private String result = "";
private Color resultColor = null;
ConnectionCheckResult ccr = null;
@Override
protected Object doInBackground() throws Exception {
try {
ccr = MantisRepository.checkConnection(
panel.urlTextField.getText(),
panel.usernameTextField.getText(),
panel.passwordTextField.getText(),
httpUsername,
httpPassword
);
result = "Successfully connected (version: "
+ ccr.getVersion().getVersionString() + ")";
resultColor = goodColor;
} catch (ServiceException ex) {
logger.log(Level.INFO, "", ex);
result = "Failed create client - check URL";
resultColor = errorColor;
} catch (RemoteException ex) {
logger.log(Level.INFO, "", ex);
result = "Failed request - check username/password";
resultColor = errorColor;
}
return null;
}
@Override
protected void done() {
panel.checkResult.setText(result);
panel.checkResult.setForeground(resultColor);
if (ccr != null) {
updateModel(statusModel, status, ccr.getStatusList());
updateModel(resolutionModel, resolution, ccr.getResolutionList());
}
setChecking(false);
}
}.execute();
}
private static void updateModel(DefaultComboBoxModel<ObjectRef> targetModel, ObjectRef currentValue, ObjectRef... values) {
targetModel.removeAllElements();
targetModel.addElement(null);
ObjectRef selectedValue = null;
for (ObjectRef or : values) {
if(or == null) {
continue;
}
targetModel.addElement(or);
if(currentValue != null && currentValue.getId().equals(or.getId())) {
selectedValue = or;
}
}
if(currentValue != null && selectedValue == null) {
targetModel.addElement(currentValue);
selectedValue = currentValue;
}
targetModel.addElement(new ObjectRef(new BigInteger("0"), "--------"));
targetModel.addElement(new ObjectRef(new BigInteger("-1"), "Refresh"));
targetModel.setSelectedItem(selectedValue);
}
@Override
public void cancelChanges() {
this.populate();
}
@Override
public void applyChanges() {
String name = panel.nameTextField.getText();
String url = panel.urlTextField.getText();
String username = panel.usernameTextField.getText();
String password = panel.passwordTextField.getText();
RepositoryInfo ri = repository.getInfo();
String id = null;
if( ri != null && ri.getID() != null) {
id = ri.getID();
}
if(id == null) {
id = MantisConnector.ID + System.currentTimeMillis();
}
String httpUsername = "";
String httpPassword = "";
if(panel.httpAuthEnabled.isSelected()) {
httpUsername = panel.httpUserField.getText();
httpPassword = panel.httpPwdField.getText();
}
ri = new RepositoryInfo(id,
MantisConnector.ID,
url,
name,
"",
username,
httpUsername,
password.toCharArray(),
httpPassword.toCharArray());
if (panel.scheduleDateFieldCustom.isSelected()) {
ri.putValue(MantisRepository.PROP_SCHEDULE_DATE_FIELD,
panel.scheduleDateFieldCustomName.getText());
}
if (panel.scheduleLengthFieldCustom.isSelected()) {
ri.putValue(MantisRepository.PROP_SCHEDULE_LENGTH_FIELD,
panel.scheduleLengthFieldCustomName.getText());
}
MantisRepository.writeObjectRef(ri, MantisRepository.PROP_COMMIT_STATUS_FIELD, status);
MantisRepository.writeObjectRef(ri, MantisRepository.PROP_COMMIT_RESOLUTION_FIELD, resolution);
repository.setInfo(ri);
}
}