package jsystem.extensions.sourcecontrol; import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.JOptionPane; import jsystem.extensions.sourcecontrol.SourceControlI.Status; import jsystem.framework.FrameworkOptions; import jsystem.framework.JSystemProperties; import jsystem.framework.report.ListenerstManager; import jsystem.framework.scenario.Parameter; import jsystem.framework.scenario.Scenario; import jsystem.framework.scenario.ScenarioChangeType; import jsystem.framework.scenario.ScenarioListener; import jsystem.framework.scenario.ScenariosManager; import jsystem.framework.sut.SutFactory; import jsystem.framework.sut.SutListener; import jsystem.treeui.TestRunner; import jsystem.treeui.actionItems.IgnisAction; import jsystem.treeui.actionItems.SaveScenarioAction; import jsystem.treeui.actionItems.ScenarioSCStatusAction; import jsystem.treeui.actionItems.SutSCStatusAction; import jsystem.utils.FileUtils; public class SourceControlHandler implements ScenarioListener, SutListener { private static Logger log = Logger.getLogger(SourceControlHandler.class .getName()); private boolean enabled; IgnisAction scenarioStatusAction = null; IgnisAction sutStatusAction = null; private Status scenarioStatus = Status.NONE; private Status sutStatus = Status.NONE; private SourceControlI sourceControl; private String repository; private String user; private String password; /** * Get the required parameters, connect and init working copy. */ public void init() { enabled = true; fetchParameters(); if (!enabled) { JOptionPane .showConfirmDialog( TestRunner.treeView, "Please specify all required parameters in JSystem properties file", "Source Control Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE); return; } instantiateSourceControl(); connect(); initWorkingCopy(); if (!enabled) { JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to connect to repository", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); return; } ListenerstManager.getInstance().addListener(this); scenarioStatusAction = ScenarioSCStatusAction.getInstance(); updateScenarioStatus(ScenariosManager.getInstance() .getCurrentScenario()); sutStatusAction = SutSCStatusAction.getInstance(); updateSutStatus(SutFactory.getInstance().getSutFile().getName()); } /** * Get all the required parameters from the JSystem properties file. */ private void fetchParameters() { repository = JSystemProperties.getInstance().getPreference( FrameworkOptions.SCM_REPOSITORY); if (null == repository || repository.isEmpty()) { log.fine("No SVN repository was defined"); enabled = false; } user = JSystemProperties.getInstance().getPreference( FrameworkOptions.SCM_USER); if (null == user) { user = ""; } password = JSystemProperties.getInstance().getPreference( FrameworkOptions.SCM_PASSWORD); if (null == password) { password = ""; } } private void initWorkingCopy() { if (!enabled) { return; } if (!sourceControl.isWorkingCopyInitialize()) { try { int answer = JOptionPane .showConfirmDialog( TestRunner.treeView, "All scnearios and SUT files will be deleted and replaced with repository files", "Checkout warning", JOptionPane.YES_NO_OPTION); if (JOptionPane.NO_OPTION == answer) { log.fine("User select not to initialize working copy"); enabled = false; return; } sourceControl.initWorkingCopy(); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to initialize working copy", e); enabled = false; JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to initialize working copy", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } } } /** * Connect to the remote repository */ private void connect() { if (!enabled) { return; } try { sourceControl.connect(repository, user, password); } catch (SourceControlException e) { enabled = false; log.log(Level.WARNING, "Failed to connect to SCM repository", e); e.printStackTrace(); } } /** * Verifies that the JSystem is connected to the repository. If not, will * pop dialog that allows the user to connect to repository. * * @return If connected to repository. */ private boolean verifyEnabled() { if (!enabled) { int answer = JOptionPane .showConfirmDialog( TestRunner.treeView, "Source control connection is not enabled. Do you want to connect?", "Source Control Disabled", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE); if (answer == JOptionPane.YES_OPTION) { init(); return true; } } return enabled; } /** * Get the source control class name and instantiate it. */ private void instantiateSourceControl() { final String svnClass = JSystemProperties.getInstance().getPreference( FrameworkOptions.SCM_PLUGIN_CLASS); if (null == svnClass || svnClass.isEmpty()) { log.fine("No SVN class was defined"); enabled = false; return; } try { Class<?> myclass = Class.forName(svnClass); sourceControl = (SourceControlI) myclass.newInstance(); } catch (Exception e) { log.log(Level.WARNING, "Failed to instanciate source control", e); enabled = false; e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to instanciate source control", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } } // ********Scenario Handling*********** /** * Updates the current root scenario and all sub scenarios. */ public void updateCurrentScenario() { if (!verifyEnabled()) { return; } Scenario scenario = ScenariosManager.getInstance().getCurrentScenario(); try { sourceControl.updateScenario(scenario); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to update scenario", e); e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to update scenario", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } loadScenario(scenario); updateScenarioStatus(scenario); } /** * Update the scenarios file. * * @param scenario */ private void updateScenarioStatus(Scenario scenario) { if (!verifyEnabled()) { return; } try { scenarioStatus = sourceControl.getScenarioStatus(scenario); scenarioStatusAction.actionPerformed(null); } catch (SourceControlException e) { System.out.println("Failed to get status of scenario"); e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to update scenario status", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } } /** * Adds the root scenario and all sub scenarios to the repository */ public void addCurrentScenario() { if (!verifyEnabled()) { return; } Scenario scenario = ScenariosManager.getInstance().getCurrentScenario(); try { sourceControl.addScenario(scenario); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to add scenario", e); e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to add scenario", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } updateScenarioStatus(scenario); } /** * Commit current root scenarios and all sub scenarios to the repository. */ public void commitCurrentScenario() { if (!verifyEnabled()) { return; } Scenario scenario = ScenariosManager.getInstance().getCurrentScenario(); try { sourceControl.commitScenario(scenario); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to commit scenario", e); e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to commit scenario", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } updateScenarioStatus(scenario); } public void revertCurrentScenario() { if (!verifyEnabled()) { return; } if (!revertConfirmation()){ return; } final Scenario scenario = ScenariosManager.getInstance() .getCurrentScenario(); try { sourceControl.revertScenario(scenario); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to revert scenario", e); e.printStackTrace(); } loadScenario(scenario); updateScenarioStatus(scenario); if (Status.NORMAL != scenarioStatus) { JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to revert scenario", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } } private void loadScenario(final Scenario scenario) { TestRunner.treeView.getTableController() .clearExpandSelected(true, true); try { TestRunner.treeView.getTableController().selectScenario( scenario.getName()); } catch (Exception e) { log.log(Level.WARNING, "Failed to select scenario after reverting", e); e.printStackTrace(); } TestRunner.treeView.getTableController().expandAll(); TestRunner.treeView.getTableController() .updateEnabledAndDisabledActions(null); TestRunner.treeView.getTableController().loadScenario( scenario.getName(), false); ScenariosManager.setDirty(); try { SaveScenarioAction.getInstance().saveCurrentScenario(); } catch (Exception e) { log.log(Level.WARNING, "Failed to save scenario after change", e); e.printStackTrace(); } } // ********SUT Handling*********** private void updateSutStatus(String sutName) { if (!verifyEnabled()) { return; } try { sutStatus = sourceControl.getSutStatus(sutName); sutStatusAction.actionPerformed(null); } catch (SourceControlException e) { JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to update sut", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); System.out.println("Failed to get status of sut"); e.printStackTrace(); } } public void addCurrentSut() { if (!verifyEnabled()) { return; } final String sutName = SutFactory.getInstance().getSutFile().getName(); try { sourceControl.addSut(sutName); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to add sut", e); e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to add sut", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } updateSutStatus(sutName); } public void commitCurrentSut() { if (!verifyEnabled()) { return; } final String sutName = SutFactory.getInstance().getSutFile().getName(); try { sourceControl.commitSut(sutName); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to commit file", e); e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to commit scenario", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } updateSutStatus(sutName); } public void revertCurrentSut() { if (!verifyEnabled()) { return; } if (!revertConfirmation()){ return; } final File sutFile = SutFactory.getInstance().getSutFile(); try { sourceControl.revertSut(sutFile.getName()); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to revert sut", e); e.printStackTrace(); } updateSutStatus(sutFile.getName()); if (Status.NORMAL != sutStatus) { JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to revert sut", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } try { copySutToTestsFolder(sutFile); } catch (IOException e) { JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to copy SUT file to tests folder", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); log.severe("Failed to copy SUT file to tests folder"); e.printStackTrace(); } SutFactory.getInstance().setSut(sutFile.getName()); } public void updateCurrentSut() { if (!verifyEnabled()) { return; } final File sutFile = SutFactory.getInstance().getSutFile(); try { sourceControl.updateSut(sutFile.getName()); } catch (SourceControlException e) { log.log(Level.WARNING, "Failed to update sut", e); e.printStackTrace(); } updateSutStatus(sutFile.getName()); try { copySutToTestsFolder(sutFile); } catch (IOException e) { log.severe("Failed to copy SUT file to tests folder"); e.printStackTrace(); JOptionPane.showConfirmDialog(TestRunner.treeView, "Failed to copy SUT file to tests folder", "Source Control Failure", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); } SutFactory.getInstance().setSut(sutFile.getName()); } /** * Copies the SUT file from the classes folder to the source folder. * * @param sutFile * @throws IOException */ private void copySutToTestsFolder(File sutFile) throws IOException { File classDir = new File(JSystemProperties.getCurrentTestsPath()); if (sutFile.getAbsolutePath().startsWith(classDir.getAbsolutePath())) { File sutSrcFile = new File(JSystemProperties.getInstance() .getPreference(FrameworkOptions.RESOURCES_SOURCE_FOLDER) + sutFile.getAbsolutePath().substring( classDir.getAbsolutePath().length())); FileUtils.copyFile(sutFile, sutSrcFile); } } /** * Confirm that the user knows that the revert will cause the local files to * be deleted. * * @return true if user confirmed */ private static boolean revertConfirmation() { int answer = JOptionPane .showConfirmDialog( TestRunner.treeView, "Local files will be deleted, are you sure you want to proceed?", "Revert Warning", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE); if (answer == JOptionPane.NO_OPTION) { return false; } return true; } // ****** Events Handling************** /** * Will update the scenario state when scenario change event is triggered. */ @Override public void scenarioChanged(Scenario current, ScenarioChangeType changeType) { updateScenarioStatus(current); } @Override public void scenarioDirectoryChanged(File directory) { } /** * Will update the scenario state when scenario change event is triggered. */ @Override public void scenarioDirtyStateChanged(Scenario s, boolean isDirty) { updateScenarioStatus(s); } @Override public void testParametersChanged(String testIIUUD, Parameter[] oldValues, Parameter[] newValues) { } @Override public void sutChanged(String sutName) { updateSutStatus(sutName); } public Status getScenarioStatus() { return scenarioStatus; } public Status getSutStatus() { return sutStatus; } public boolean isEnabled() { return enabled; } }