From cdf26ddb39752ed49b1735695ef1a42637a3ca5f Mon Sep 17 00:00:00 2001 From: vlambat Date: Tue, 10 Nov 2015 17:25:23 +0530 Subject: [PATCH 1/6] Initial commit of junit infrastructure Change-Id: I33d37543f3c44c87d9e886ba661ddee4f4afc54b --- src/main/java/hudson/scm/APISession.java | 2 +- src/main/java/hudson/scm/ISession.java | 11 + .../java/hudson/scm/IntegrityCMMember.java | 4 +- .../scm/test/AbstractIntegrityTestCase.java | 171 +++++++++ .../java/hudson/scm/test/FakeAPISession.java | 352 ++++++++++++++++++ .../java/hudson/scm/test/FakeCmdRunner.java | 205 ++++++++++ .../hudson/scm/test/FakeIntegrationPoint.java | 105 ++++++ src/test/java/hudson/scm/test/FakeObject.java | 58 +++ .../java/hudson/scm/test/FakeResponse.java | 242 ++++++++++++ .../java/hudson/scm/test/FakeSession.java | 199 ++++++++++ .../hudson/scm/test/IntegritySCMTest.java | 77 ++++ .../test/IntegrityTestParametersAction.java | 19 + .../hudson/scm/test/TestIntegrityRepo.java | 63 ++++ 13 files changed, 1505 insertions(+), 3 deletions(-) create mode 100644 src/main/java/hudson/scm/ISession.java create mode 100644 src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java create mode 100644 src/test/java/hudson/scm/test/FakeAPISession.java create mode 100644 src/test/java/hudson/scm/test/FakeCmdRunner.java create mode 100644 src/test/java/hudson/scm/test/FakeIntegrationPoint.java create mode 100644 src/test/java/hudson/scm/test/FakeObject.java create mode 100644 src/test/java/hudson/scm/test/FakeResponse.java create mode 100644 src/test/java/hudson/scm/test/FakeSession.java create mode 100644 src/test/java/hudson/scm/test/IntegritySCMTest.java create mode 100644 src/test/java/hudson/scm/test/IntegrityTestParametersAction.java create mode 100644 src/test/java/hudson/scm/test/TestIntegrityRepo.java diff --git a/src/main/java/hudson/scm/APISession.java b/src/main/java/hudson/scm/APISession.java index a737b8e..9b665f1 100644 --- a/src/main/java/hudson/scm/APISession.java +++ b/src/main/java/hudson/scm/APISession.java @@ -16,7 +16,7 @@ * This class represents an Integration Point to a server. * It also contains a Session object */ -public class APISession +public class APISession implements ISession { // Initialize our logger private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); diff --git a/src/main/java/hudson/scm/ISession.java b/src/main/java/hudson/scm/ISession.java new file mode 100644 index 0000000..59ecd60 --- /dev/null +++ b/src/main/java/hudson/scm/ISession.java @@ -0,0 +1,11 @@ +package hudson.scm; + +import com.mks.api.Command; +import com.mks.api.response.APIException; +import com.mks.api.response.Response; + +public interface ISession { + + public Response runCommand(Command cmd) throws APIException; + +} diff --git a/src/main/java/hudson/scm/IntegrityCMMember.java b/src/main/java/hudson/scm/IntegrityCMMember.java index b510e0b..3e5d1a1 100644 --- a/src/main/java/hudson/scm/IntegrityCMMember.java +++ b/src/main/java/hudson/scm/IntegrityCMMember.java @@ -108,7 +108,7 @@ public static final String getDifferencesLink(String configPath, String memberID * @return true if the operation succeeded or false if failed * @throws APIException */ - public static final boolean checkout(APISession api, String configPath, String memberID, String memberRev, Timestamp memberTimestamp, + public static final boolean checkout(ISession api, String configPath, String memberID, String memberRev, Timestamp memberTimestamp, File targetFile, boolean restoreTimestamp, String lineTerminator) throws APIException { // Make sure the directory is created @@ -305,7 +305,7 @@ public static final void updateMember(APISession api, String configPath, FilePat * @param api Integrity API Session * @param configPath Full project configuration path */ - public static final void unlockMembers(APISession api, String configPath) + public static final void unlockMembers(ISession api, String configPath) { // Construct the unlock command Command unlock = new Command(Command.SI, "unlock"); diff --git a/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java b/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java new file mode 100644 index 0000000..229761f --- /dev/null +++ b/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java @@ -0,0 +1,171 @@ +package hudson.scm.test; + +import hudson.EnvVars; +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.BuildListener; +import hudson.model.FreeStyleBuild; +import hudson.model.Result; +import hudson.model.StreamBuildListener; +import hudson.model.TaskListener; +import hudson.model.AbstractBuild; +import hudson.model.Cause; +import hudson.model.FreeStyleProject; +import hudson.scm.IntegrityCMMember; +import hudson.scm.IntegrityCheckinTask; +import hudson.scm.IntegrityConfigurable; +import hudson.scm.IntegrityItemAction; +import hudson.scm.IntegritySCM; +import hudson.scm.IntegritySCM.DescriptorImpl; +import hudson.util.StreamTaskListener; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.rules.TemporaryFolder; +import org.jvnet.hudson.test.JenkinsRule; +//import org.mockito.Mockito; + +import rpc.IntegrityException; + +public abstract class AbstractIntegrityTestCase extends JenkinsRule{ + + protected TaskListener listener; + protected BuildListener buildListener; + protected TestIntegrityRepo testRepo; + protected File workDir; + protected FilePath workspace; + protected String name1; + protected String name2; + + + String serverConfig="developer@ppumsv-ipdc16d.ptcnet.ptc.com:7001"; + String userName="developer"; + String password="password"; + String configPath="#/Vipin"; + @Rule public JenkinsRule jenkinsRule = new JenkinsRule(); + @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Before + public void setUp() throws Exception { + try { + listener = StreamTaskListener.fromStderr(); + File file = temporaryFolder.getRoot(); + testRepo = new TestIntegrityRepo("unnamed", file, listener); + name1=testRepo.userName1; + name2=testRepo.userName2; + workDir = testRepo.IntegrityDir; + workspace = testRepo.IntegrityDirPath; + } + catch (Throwable e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + protected void tearDown() throws Exception{ + try{ + super.after();} + catch (Exception e) { + e.printStackTrace(); + } + } + + protected void commit(final String fileName,final String fileContent, final String User1, final String message) + throws IntegrityException, InterruptedException { + testRepo.commit(fileName, fileContent,User1, message); + } + protected void commit(final String fileName, final String User2, final String message) + throws IntegrityException, InterruptedException { + testRepo.commit(fileName, User2, message); + } + + protected void setupIntegrityConfigurable() + { + IntegrityConfigurable configObj= new IntegrityConfigurable("server1", "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, false, "developer", "password"); + FakeAPISession api = FakeAPISession.create(configObj); + List configurations = new ArrayList(); + configurations.add(configObj); + DescriptorImpl.INTEGRITY_DESCRIPTOR.setConfigurations(configurations); + } + + protected FreeStyleProject setupProject() throws Exception + { + IntegritySCM scm = new IntegritySCM("server1", configPath, "devjob"); + FreeStyleProject project = jenkinsRule.createFreeStyleProject(); + project.setScm(scm); + project.save(); + return project; + } + + protected FreeStyleProject setupIntegrityProject() throws Exception + { + setupIntegrityConfigurable(); + FreeStyleProject project = setupProject(); + return project; + } + + protected void setupPostBuildCheckIn(AbstractBuild build) throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + buildListener = new StreamBuildListener(out); + IntegrityConfigurable configObj = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfigurations().get(0); + IntegrityCheckinTask ciTask = new IntegrityCheckinTask("#/Vipin_main", ".", "*.*", "", build, buildListener, configObj); + build.getWorkspace().act(ciTask); + } + + protected void setupPostBuildBuildItem(AbstractBuild build, boolean query) throws Exception + { + String fieldQuery = ""; + if (query == true) + { + fieldQuery = "(field[ID]=852)"; + } + else + { + EnvVars env = new EnvVars(); + env = build.getEnvironment(listener); + IntegrityTestParametersAction act = new IntegrityTestParametersAction("852"); + act.buildEnvVars(build, env); + build.addAction(act); + } + + IntegrityItemAction itemAction = new IntegrityItemAction(); + itemAction.setServerConfig("server1"); + itemAction.setQueryDefinition(fieldQuery); + itemAction.setStateField("Assigned User"); + itemAction.setSuccessValue("developer"); + itemAction.setFailureValue("administrator"); + itemAction.setLogField("Description"); + + Launcher launcher = workspace.createLauncher(listener); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + buildListener = new StreamBuildListener(out); + itemAction.perform(build, launcher, buildListener); + } + + protected FreeStyleBuild build(final FreeStyleProject project, final Result expectedResult, final String...expectedNewlyCommittedFiles) throws Exception { + final FreeStyleBuild build = project.scheduleBuild2(0, new Cause.UserIdCause()).get(); + + System.out.println(build.getLog(50)); +// for(final String expectedNewlyCommittedFile : expectedNewlyCommittedFiles) { +// assertTrue(expectedNewlyCommittedFile + " file not found in workspace", build.getWorkspace().child(expectedNewlyCommittedFile).exists()); +// } +// if(expectedResult != null) { +// assertBuildStatus(expectedResult, build); +// } + return build; + } + + protected void testUnlockMembers() throws Exception + { + IntegrityConfigurable configObj= new IntegrityConfigurable("server1", "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, false, "developer", "password"); + FakeAPISession api = FakeAPISession.create(configObj); + IntegrityCMMember.unlockMembers(api, configPath); + } + +} diff --git a/src/test/java/hudson/scm/test/FakeAPISession.java b/src/test/java/hudson/scm/test/FakeAPISession.java new file mode 100644 index 0000000..7caa923 --- /dev/null +++ b/src/test/java/hudson/scm/test/FakeAPISession.java @@ -0,0 +1,352 @@ +// +// $Id: FakeAPISession.java 1.8 2014/09/24 01:08:32IST gisraeli Exp $ +// +// Copyright 2011 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software +// without the express written permission of PTC Inc. +// is strictly prohibited. +// + +package hudson.scm.test; + +import hudson.scm.APISession; +import hudson.scm.ExceptionHandler; +import hudson.scm.IntegrityConfigurable; +import hudson.scm.ISession; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import com.mks.api.CmdRunner; +import com.mks.api.Command; +import com.mks.api.IntegrationPoint; +import com.mks.api.IntegrationPointFactory; +import com.mks.api.Session; +import com.mks.api.response.APIException; +import com.mks.api.response.Response; +import com.mks.api.util.APIVersion; + +/** + * Allows for testing of an APISession + * + * @since Red + * @version $Revision: 1.8 $ + */ +public class FakeAPISession implements ISession +{ + // Initialize our logger + private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + + // Store the API Version + public static final String VERSION = "4.13"; + public static final int MAJOR_VERSION = 4; + public static final int MINOR_VERSION = 13; + + // Class variables used to create an API Session + private String ipHostName; + private int ipPort = 0; + private String hostName; + private int port; + private String userName; + private String password; + + // API Specific Objects + private FakeIntegrationPoint ip; + private FakeSession session; + private FakeCmdRunner icr; + private boolean terminated; + private boolean secure; + + /** + * Creates an authenticated API Session against the Integrity Server + * @return An authenticated API Session + */ + public static synchronized FakeAPISession create(IntegrityConfigurable settings) + { + // Attempt to open a connection to the Integrity Server + try + { + LOGGER.fine("Creating Integrity API Session..."); + return new FakeAPISession( + settings.getIpHostName(), + settings.getIpPort(), + settings.getHostName(), + settings.getPort(), + settings.getUserName(), + settings.getPasswordInPlainText(), + settings.getSecure() + ); + } + catch(APIException aex) + { + LOGGER.severe("API Exception caught..."); + ExceptionHandler eh = new ExceptionHandler(aex); + LOGGER.severe(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + LOGGER.log(Level.SEVERE, "APIException", aex); + return null; + } + } + + /** + * Constructor for the API Session Object + * @throws APIException + */ + private FakeAPISession(String ipHost, int ipPortNum, + String host, int portNum, String user, String paswd, boolean secure) throws APIException + { + + ipHostName = ipHost; + ipPort = ipPortNum; + hostName = host; + port = portNum; + userName = user; + password = paswd; + this.secure = secure; + initAPI(); + } + + private void initAPI() throws APIException + { + // Initialize our termination flag... + terminated = false; + ip = new FakeIntegrationPoint(); + session = new FakeSession(); + ip.put(FakeIntegrationPoint.COMMON_SESSION, session); + // Test the connection to the Integrity Server + Command ping = new Command("api", "ping"); + FakeCmdRunner cmdRunner = new FakeCmdRunner(); + cmdRunner.setDefaultHostname(hostName); + cmdRunner.setDefaultPort(port); + cmdRunner.setDefaultUsername(userName); + cmdRunner.setDefaultPassword(password); + // Execute the connection + FakeResponse res = new FakeResponse(); + cmdRunner.put("api.ping", res); + //Response res = cmdRunner.execute(ping); + LOGGER.fine(ping.getCommandName() + " returned exit code " + res.getExitCode()); + // Initialize class variables + cmdRunner.release(); + LOGGER.fine("Successfully established connection " + userName + "@" + hostName + ":" + port); + } + + /** + * This function executes a generic API/CLI Command + * @param cmd Integrity API Command Object representing a CLI command + * @return Integrity API Response Object + * @throws APIException + */ + public Response runCommand(Command cmd) throws APIException + { + FakeCmdRunner cmdRunner = new FakeCmdRunner(); + cmdRunner.setDefaultHostname(hostName); + cmdRunner.setDefaultPort(port); + cmdRunner.setDefaultUsername(userName); + cmdRunner.setDefaultPassword(password); + FakeResponse res = new FakeResponse(); + cmdRunner.put(cmd.getCommandName(), res); + LOGGER.fine(cmd.getCommandName() + " returned exit code " + res.getExitCode()); + cmdRunner.release(); + return res; + } + + /** + * This function executes a generic API/CLI Command with interim + * @param cmd Integrity API Command Object representing a CLI command + * @return Integrity API Response Object + * @throws APIException + */ + public Response runCommandWithInterim(Command cmd) throws APIException + { + // Terminate the previous command runner, if applicable + if( null != icr ) + { + if( !icr.isFinished() ) + { + icr.interrupt(); + } + icr.release(); + } + + icr = new FakeCmdRunner(); + icr.setDefaultHostname(hostName); + icr.setDefaultPort(port); + icr.setDefaultUsername(userName); + icr.setDefaultPassword(password); + //Response res = icr.executeWithInterim(cmd, false); + FakeResponse res = new FakeResponse(); + icr.put(cmd.getCommandName(), res); + LOGGER.fine("Executed " + cmd.getCommandName() + " with interim"); + return res; + } + + /** + * This function executes a generic API/CLI Command impersonating another user + * @param cmd Integrity API Command Object representing a CLI command + * @param impersonateUser The user to impersonate + * @return Integrity API Response Object + * @throws APIException + */ + public Response runCommandAs(Command cmd, String impersonateUser) throws APIException + { + FakeCmdRunner cmdRunner = new FakeCmdRunner(); + cmdRunner.setDefaultHostname(hostName); + cmdRunner.setDefaultPort(port); + cmdRunner.setDefaultUsername(userName); + cmdRunner.setDefaultPassword(password); + cmdRunner.setDefaultImpersonationUser(impersonateUser); + //Response res = cmdRunner.execute(cmd); + FakeResponse res = new FakeResponse(); + icr.put(cmd.getCommandName(), res); + LOGGER.fine(cmd.getCommandName() + " returned exit code " + res.getExitCode()); + cmdRunner.release(); + return res; + } + + public void refreshAPISession() throws APIException + { + Terminate(); + initAPI(); + } + + /** + * Terminate the API Session and Integration Point + */ + public void Terminate() + { + boolean cmdRunnerKilled = false; + boolean sessionKilled = false; + boolean intPointKilled = false; + + // Terminate only if not already terminated! + if( ! terminated ) + { + try + { + if( null != icr ) + { + if( !icr.isFinished() ) + { + icr.interrupt(); + } + + icr.release(); + cmdRunnerKilled = true; + } + else + { + cmdRunnerKilled = true; + } + + } + catch( APIException aex ) + { + LOGGER.fine("Caught API Exception when releasing Command Runner!"); + LOGGER.log(Level.SEVERE, "APIException", aex); + } + catch( Exception ex ) + { + LOGGER.fine("Caught Exception when releasing Command Runner!"); + LOGGER.log(Level.SEVERE, "Exception", ex); + } + + // Separate try-block to ensure this code is executed even it the previous try-block threw an exception + try + { + if( null != session ) + { + // force the termination of an running command + session.release(true); + sessionKilled = true; + } + else + { + sessionKilled = true; + } + + } + catch(APIException aex) + { + LOGGER.fine("Caught API Exception when releasing session!"); + LOGGER.log(Level.SEVERE, "APIException", aex); + } + catch(IOException ioe) + { + LOGGER.fine("Caught IO Exception when releasing session!"); + LOGGER.log(Level.SEVERE, "IOException", ioe); + } + + + if( null != ip ) + { + ip.release(); + intPointKilled = true; + } + else + { + intPointKilled = true; + } + + if( cmdRunnerKilled && sessionKilled && intPointKilled ) + { + terminated = true; + LOGGER.fine("Successfully disconnected connection " + userName + "@" + hostName + ":" + port); + } + else + { + LOGGER.warning("Failed to disconnect connection " + userName + "@" + hostName + ":" + port); + } + } + } + + /** + * Returns the Integrity Integration Point Hostname for this APISession + * @return + */ + public String getIPHostName() + { + return ipHostName; + } + + /** + * Returns the Integrity Integration Point Port for this APISession + * @return + */ + public String getIPPort() + { + return String.valueOf(ipPort); + } + + /** + * Returns the Integrity Hostname for this APISession + * @return + */ + public String getHostName() + { + return hostName; + } + + /** + * Returns the Integrity Port for this APISession + * @return + */ + public String getPort() + { + return String.valueOf(port); + } + + /** + * Returns the Integrity User for this APISession + * @return + */ + public String getUserName() + { + return userName; + } +} + diff --git a/src/test/java/hudson/scm/test/FakeCmdRunner.java b/src/test/java/hudson/scm/test/FakeCmdRunner.java new file mode 100644 index 0000000..0106b59 --- /dev/null +++ b/src/test/java/hudson/scm/test/FakeCmdRunner.java @@ -0,0 +1,205 @@ +// +// $Id: FakeCmdRunner.java 1.7 2015/05/13 05:52:21IST Reid, Randall (rreid) Exp $ +// +// Copyright 2011 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software +// without the express written permission of PTC Inc. +// is strictly prohibited. +// + +package hudson.scm.test; + +import com.mks.api.CmdRunner; +import com.mks.api.Command; +import com.mks.api.Session; +import com.mks.api.response.APIException; +import com.mks.api.response.Response; + +/** + * Allows for testing classes that use a command runner + * + * @since Red + * @version $Revision: 1.7 $ + */ +public class FakeCmdRunner extends FakeObject implements CmdRunner +{ + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#getSession() + */ + public Session getSession() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#getInvocationID() + */ + public String getInvocationID() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#setInvocationID(java.lang.String) + */ + public void setInvocationID(String invocationID) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#interrupt() + */ + public void interrupt() throws APIException + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#setDefaultImpersonationUser(java.lang.String) + */ + public void setDefaultImpersonationUser(String impUser) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#getDefaultImpersonationUser() + */ + public String getDefaultImpersonationUser() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#getDefaultHostname() + */ + public String getDefaultHostname() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#getDefaultPort() + */ + public int getDefaultPort() + { + return 0; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#setDefaultHostname(java.lang.String) + */ + public void setDefaultHostname(String host) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#setDefaultPort(int) + */ + public void setDefaultPort(int port) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#getDefaultUsername() + */ + public String getDefaultUsername() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#getDefaultPassword() + */ + public String getDefaultPassword() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#setDefaultUsername(java.lang.String) + */ + public void setDefaultUsername(String user) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#setDefaultPassword(java.lang.String) + */ + public void setDefaultPassword(String pass) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#execute(java.lang.String[]) + */ + public Response execute(String[] args) throws APIException + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#execute(com.mks.api.Command) + */ + public Response execute(Command cmd) throws APIException + { + put(cmd.getCommandName(),cmd); + Response r = (Response) getValueByKey( cmd.getApp() + "." + cmd.getCommandName() ); + if ( r != null && r.getAPIException() != null ) + throw r.getAPIException(); + return r; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#executeWithInterim(java.lang.String[], boolean) + */ + public Response executeWithInterim(String[] args, boolean enableCache) + throws APIException + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#executeWithInterim(com.mks.api.Command, boolean) + */ + public Response executeWithInterim(Command cmd, boolean enableCache) + throws APIException + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#release() + */ + public void release() throws APIException + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunner#isFinished() + */ + public boolean isFinished() + { + return false; + } + + /* + * (non-Javadoc) + * @see com.mks.api.CmdRunner#execute(java.lang.String[], java.lang.String) + */ + public Response execute(String[] args, String vendorName) + throws APIException + { + return null; + } + + /* + * (non-Javadoc) + * @see com.mks.api.CmdRunner#executeWithInterim(java.lang.String[], boolean, java.lang.String) + */ + public Response executeWithInterim(String[] args, boolean enableCache, + String vendorName) throws APIException + { + return null; + } +} diff --git a/src/test/java/hudson/scm/test/FakeIntegrationPoint.java b/src/test/java/hudson/scm/test/FakeIntegrationPoint.java new file mode 100644 index 0000000..bac8810 --- /dev/null +++ b/src/test/java/hudson/scm/test/FakeIntegrationPoint.java @@ -0,0 +1,105 @@ +// $Id: FakeIntegrationPoint.java 1.2 2015/03/30 20:19:12IST Reid, Randall (rreid) Exp $ +// (c) Copyright 2014 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.test; + +import java.util.Iterator; + +import com.mks.api.IntegrationPoint; +import com.mks.api.Session; +import com.mks.api.VersionNumber; +import com.mks.api.response.APIException; + +public class FakeIntegrationPoint extends FakeObject implements IntegrationPoint { + + public static final String COMMON_SESSION = "COMMON_SESSION"; + + public VersionNumber getAPIRequestVersion() + { + return null; + } + + public String getHostname() + { + return ""; + } + + public int getPort() + { + return 0; + } + + public boolean isClientIntegrationPoint() + { + return false; + } + + public boolean isSecure() + { + return false; + } + + public Session createNamedSession(String integrationID, + VersionNumber overrideRequestVersion) throws APIException + { + return null; + } + + public Session createNamedSession(String integrationID, + VersionNumber overrideRequestVersion, String username, + String password) throws APIException + { + return null; + } + + public Session createSession() throws APIException + { + return null; + } + + public Session createSession(String username, String password) + throws APIException + { + return null; + } + + public Session createSession(String username, String password, + int apiMajorVersion, int apiMinorVersion) throws APIException + { + return null; + } + + public Session getCommonSession() throws APIException + { + return (Session) getValueByKey(COMMON_SESSION); + } + + public Session getCommonSession(String username, String password) + throws APIException + { + return null; + } + + public Iterator getSessions() + { + return null; + } + + public boolean getAutoStartIntegrityClient() + { + return false; + } + + public void setAutoStartIntegrityClient(boolean autoStartIC) + { + } + + public void release() + { + } + +} \ No newline at end of file diff --git a/src/test/java/hudson/scm/test/FakeObject.java b/src/test/java/hudson/scm/test/FakeObject.java new file mode 100644 index 0000000..b1f6124 --- /dev/null +++ b/src/test/java/hudson/scm/test/FakeObject.java @@ -0,0 +1,58 @@ +// +// $Id: FakeObject.java 1.4 2013/02/27 19:49:45IST alivogiannis Exp $ +// +// Copyright 2011 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software +// without the express written permission of PTC Inc. +// is strictly prohibited. +// + +package hudson.scm.test; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Base class for all Fake objects used for testing. + * + * @since Purple + * @version $Revision: 1.4 $ + */ +public class FakeObject +{ + private Map values = new LinkedHashMap(); + + public void put(String key, Object value) + { + values.put(key,value); + } + + public Object getValueByKey(String key) + { + Object value = getValues().get(key); + return value; + } + + public Map getValues() + { + return values; + } + + public Exception getException(String key) + { + Object value = getValueByKey( key ); + if (value instanceof Exception) + return (Exception)value; + return null; + } + + protected boolean getBooleanValueByKey(String key) + { + Boolean value = (Boolean)getValueByKey(key); + if (value == null) + return false; + return value.booleanValue(); + } +} diff --git a/src/test/java/hudson/scm/test/FakeResponse.java b/src/test/java/hudson/scm/test/FakeResponse.java new file mode 100644 index 0000000..b976d4c --- /dev/null +++ b/src/test/java/hudson/scm/test/FakeResponse.java @@ -0,0 +1,242 @@ +// +// $Id: FakeResponse.java 1.6 2015/03/30 20:19:13IST Reid, Randall (rreid) Exp $ +// +// Copyright 2011 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software +// without the express written permission of PTC Inc. +// is strictly prohibited. +// + +package hudson.scm.test; + +import com.mks.api.VersionNumber; +import com.mks.api.response.*; +import com.mks.api.response.InterruptedException; + +/** + * This class allows for a Api Response object to be used when testing. + * + * @since Purple + * @version $Revision: 1.6 $ + */ +public class FakeResponse extends FakeObject implements Response +{ + public final static String GET_API_EXCEPTION = "getApiException"; + public final static String GET_RESULT = "getResult"; + public final static String GET_WORKITEMS = "getWorkItems"; + public final static String GET_EXITCODE = "getExitCode"; + public final static String GET_WORKITEM_LIST_SIZE = "getWorkItemListSize"; + + public FakeResponse() + { + setExitCode( 0 ); + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getAPIVersion() + */ + public VersionNumber getAPIVersion() + { + return null; + } + + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getInvocationID() + */ + public String getInvocationID() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.WorkItemContainer#getWorkItemListSize() + */ + public int getWorkItemListSize() + { + return (Integer) getValueByKey( GET_WORKITEM_LIST_SIZE ); + } + + /* (non-Javadoc) + * @see com.mks.api.response.WorkItemContainer#getWorkItems() + */ + public WorkItemIterator getWorkItems() + { + WorkItemIterator it = (WorkItemIterator) getValueByKey(GET_WORKITEMS); + return it; + } + + /* (non-Javadoc) + * @see com.mks.api.response.WorkItemContainer#getWorkItem(java.lang.String) + */ + public WorkItem getWorkItem(String id) + { + return (WorkItem) getValueByKey( id ); + } + + /* (non-Javadoc) + * @see com.mks.api.response.WorkItemContainer#getWorkItem(java.lang.String, java.lang.String) + */ + public WorkItem getWorkItem(String id, String context) + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.WorkItemContainer#containsWorkItem(java.lang.String) + */ + public boolean containsWorkItem(String id) + { + return false; + } + + /* (non-Javadoc) + * @see com.mks.api.response.WorkItemContainer#containsWorkItem(java.lang.String, java.lang.String) + */ + public boolean containsWorkItem(String id, String context) + { + return false; + } + + /* (non-Javadoc) + * @see com.mks.api.response.SubRoutineContainer#getSubRoutineListSize() + */ + public int getSubRoutineListSize() + { + return 0; + } + + /* (non-Javadoc) + * @see com.mks.api.response.SubRoutineContainer#getSubRoutines() + */ + public SubRoutineIterator getSubRoutines() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.SubRoutineContainer#getSubRoutine(java.lang.String) + */ + public SubRoutine getSubRoutine(String name) + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.SubRoutineContainer#containsSubRoutine(java.lang.String) + */ + public boolean containsSubRoutine(String name) + { + return false; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getExitCode() + */ + public int getExitCode() throws InterruptedException + { + Object value = getValueByKey(GET_EXITCODE); + if (value instanceof Exception) + throw (com.mks.api.response.InterruptedException)value; + return (Integer) value; + } + + public void setExitCode(int exitCode) + { + put(GET_EXITCODE,exitCode); + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getApplicationName() + */ + public String getApplicationName() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getCommandName() + */ + public String getCommandName() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getCommandString() + */ + public String getCommandString() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getConnectionHostname() + */ + public String getConnectionHostname() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getConnectionPort() + */ + public int getConnectionPort() + { + return 0; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getConnectionUsername() + */ + public String getConnectionUsername() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getResult() + */ + public Result getResult() throws InterruptedException + { + Object result = getValueByKey(GET_RESULT); + if (result instanceof Exception) + throw (InterruptedException)result; + return (Result) result; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getCacheContents() + */ + public boolean getCacheContents() + { + return false; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#interrupt() + */ + public void interrupt() + { + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#getAPIException() + */ + public APIException getAPIException() throws InterruptedException + { + Object object = getValueByKey(GET_API_EXCEPTION); + if (object instanceof InterruptedException) + throw (InterruptedException)object; + return (APIException) object; + } + + /* (non-Javadoc) + * @see com.mks.api.response.Response#release() + */ + public void release() throws APIException + { + } +} diff --git a/src/test/java/hudson/scm/test/FakeSession.java b/src/test/java/hudson/scm/test/FakeSession.java new file mode 100644 index 0000000..88c2fbf --- /dev/null +++ b/src/test/java/hudson/scm/test/FakeSession.java @@ -0,0 +1,199 @@ +// +// $Id: FakeSession.java 1.7 2015/03/30 20:19:12IST Reid, Randall (rreid) Exp $ +// +// Copyright 2011 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software +// without the express written permission of PTC Inc. +// is strictly prohibited. +// + +package hudson.scm.test; + +import java.io.IOException; +import java.util.Iterator; + +import com.mks.api.*; +import com.mks.api.response.APIException; + +/** + * Allows for testing classes that use a Session. + * + * @since Red + * @version $Revision: 1.7 $ + */ +public class FakeSession extends FakeObject implements Session +{ + public static final String CREATE_CMD_RUNNER = "createCmdRunner"; + public static final String AUTO_RECONNECT = "autoReconnect"; + + /* (non-Javadoc) + * @see com.mks.api.Session#getIntegrationID() + */ + public String getIntegrationID() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#createCmdRunner() + */ + public CmdRunner createCmdRunner() throws APIException + { + return (CmdRunner) getValueByKey( CREATE_CMD_RUNNER ); + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#getCmdRunners() + */ + public Iterator getCmdRunners() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#release() + */ + public void release() throws IOException, APIException + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#release(boolean) + */ + public void release(boolean force) throws IOException, APIException + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#setDefaultImpersonationUser(java.lang.String) + */ + public void setDefaultImpersonationUser(String impUser) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#getDefaultImpersonationUser() + */ + public String getDefaultImpersonationUser() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#getDefaultHostname() + */ + public String getDefaultHostname() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#getDefaultPort() + */ + public int getDefaultPort() + { + return 0; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#setDefaultHostname(java.lang.String) + */ + public void setDefaultHostname(String host) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#setDefaultPort(int) + */ + public void setDefaultPort(int port) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#getDefaultUsername() + */ + public String getDefaultUsername() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#getDefaultPassword() + */ + public String getDefaultPassword() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#setDefaultUsername(java.lang.String) + */ + public void setDefaultUsername(String user) + { + } + + /* (non-Javadoc) + * @see com.mks.api.CmdRunnerCreator#setDefaultPassword(java.lang.String) + */ + public void setDefaultPassword(String pass) + { + } + + /* (non-Javadoc) + * @see com.mks.api.IntegrationVersionRequest#getAPIRequestVersion() + */ + public VersionNumber getAPIRequestVersion() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.Session#getIntegrationPoint() + */ + public IntegrationPoint getIntegrationPoint() + { + return null; + } + + /* (non-Javadoc) + * @see com.mks.api.Session#setAutoReconnect(boolean) + */ + public void setAutoReconnect(boolean flag) + { + put(AUTO_RECONNECT, flag); + } + + /* (non-Javadoc) + * @see com.mks.api.Session#getAutoReconnect() + */ + public boolean getAutoReconnect() + { + return getBooleanValueByKey(AUTO_RECONNECT); + } + + /* (non-Javadoc) + * @see com.mks.api.Session#getTimeout() + */ + public int getTimeout() + { + return 0; + } + + /* (non-Javadoc) + * @see com.mks.api.Session#setTimeout(int) + */ + public void setTimeout(int timeout) + { + } + + /* (non-Javadoc) + * @see com.mks.api.Session#isCommon() + */ + public boolean isCommon() + { + return false; + } + +} diff --git a/src/test/java/hudson/scm/test/IntegritySCMTest.java b/src/test/java/hudson/scm/test/IntegritySCMTest.java new file mode 100644 index 0000000..878fa83 --- /dev/null +++ b/src/test/java/hudson/scm/test/IntegritySCMTest.java @@ -0,0 +1,77 @@ +package hudson.scm.test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import hudson.model.FreeStyleBuild; +import hudson.model.Result; +import hudson.model.FreeStyleProject; +import hudson.model.ParametersDefinitionProperty; +import hudson.model.StringParameterDefinition; +import hudson.model.User; +import hudson.scm.IntegrityCMMember; + +import java.util.Set; + +import org.junit.Rule; +import org.junit.Test; +import org.jvnet.hudson.test.JenkinsRule; + + +public class IntegritySCMTest extends AbstractIntegrityTestCase +{ + + @Test + public void testProjectUnlockMembers() throws Exception + { + testUnlockMembers(); + } + + @Test + public void testProjectSetup() throws Exception + { + FreeStyleProject project = setupIntegrityProject(); + + // create initial commit and then run the build against it: + final String commitFile1 = "commitFile1"; + final String fielcontent = "commitFile1"; + commit(commitFile1,fielcontent, name1, "Commit number 1"); + } + + @Test + public void testPostBuildCheckin() throws Exception + { + FreeStyleProject project = setupIntegrityProject(); + // create initial commit and then run the build against it: + final String commitFile1 = "commitFile1"; + final String fielcontent = "Testing post build Check in action."; + commit(commitFile1,fielcontent, name1, "Commit number 1"); + + FreeStyleBuild build = build(project, Result.SUCCESS, commitFile1); + setupPostBuildCheckIn(build); + } + + @Test + public void testPostBuildWithItemIDFieldQuery() throws Exception + { + FreeStyleProject project = setupIntegrityProject(); + // create initial commit and then run the build against it: + final String commitFile1 = "commitFile1"; + final String fielcontent = "Testing post build with ItemID(Integrity-Workflow Item) as field query."; + commit(commitFile1,fielcontent, name1, "Commit number 1"); + FreeStyleBuild build = build(project, Result.SUCCESS, commitFile1); + setupPostBuildBuildItem(build, true); + } + + @Test + public void testPostBuildWithParameterizedItemID() throws Exception + { + FreeStyleProject project = setupIntegrityProject(); + // create initial commit and then run the build against it: + final String commitFile1 = "commitFile1"; + final String fielcontent = "Testing post build with parameterized ItemID(Integrity-Workflow Item)."; + commit(commitFile1,fielcontent, name1, "Commit number 1"); + FreeStyleBuild build = build(project, Result.SUCCESS, commitFile1); + setupPostBuildBuildItem(build, false); + } + +} \ No newline at end of file diff --git a/src/test/java/hudson/scm/test/IntegrityTestParametersAction.java b/src/test/java/hudson/scm/test/IntegrityTestParametersAction.java new file mode 100644 index 0000000..492fb1b --- /dev/null +++ b/src/test/java/hudson/scm/test/IntegrityTestParametersAction.java @@ -0,0 +1,19 @@ +package hudson.scm.test; +import hudson.EnvVars; +import hudson.model.EnvironmentContributingAction; +import hudson.model.InvisibleAction; +import hudson.model.AbstractBuild; + +public class IntegrityTestParametersAction extends InvisibleAction implements EnvironmentContributingAction{ + private String value; + + public IntegrityTestParametersAction(String value) + { + this.value = value; + } + + /* from EnvironmentContributingAction */ + public void buildEnvVars(AbstractBuild build, EnvVars env) { + env.put("ItemID", value); + } +} diff --git a/src/test/java/hudson/scm/test/TestIntegrityRepo.java b/src/test/java/hudson/scm/test/TestIntegrityRepo.java new file mode 100644 index 0000000..e1d1af6 --- /dev/null +++ b/src/test/java/hudson/scm/test/TestIntegrityRepo.java @@ -0,0 +1,63 @@ +package hudson.scm.test; + +import hudson.FilePath; +import hudson.model.TaskListener; + +import java.io.File; +import java.io.IOException; + +import rpc.IntegrityException; + +public class TestIntegrityRepo { + protected String name; // The name of this repository. + protected TaskListener listener; + + /** + * This is where the commit commands create a Git repository. + */ + public File IntegrityDir; // was "workDir" + public FilePath IntegrityDirPath; // was "workspace" + public final String userName1="john"; + public String userName2="johnny"; + + public TestIntegrityRepo(String name, File tmpDir, TaskListener listener) throws IOException, InterruptedException + { + this.name = name; + this.listener = listener; + IntegrityDir = tmpDir; + + // initialize the git interface. + IntegrityDirPath = new FilePath(IntegrityDir); + //git = Git.with(listener, envVars).in(gitDir).getClient(); + + // finally: initialize the repo + //git.init(); + } + + /** + * Creates a commit in current repo. + * @param fileName relative path to the file to be commited with the given content + * @param fileContent content of the commit + * @param author author of the commit + * @param committer committer of this commit + * @param message commit message + * @return SHA1 of latest commit + * @throws GitException + * @throws InterruptedException + */ + public String commit(final String fileName, final String User1, final String message) + throws IntegrityException, InterruptedException { + return commit(fileName,User1, message); + } + public String commit(final String fileName, final String fileContent, final String User1, + final String message) throws IntegrityException, InterruptedException { + FilePath file = IntegrityDirPath.child(fileName); + try { + file.write(fileContent, null); + } catch (Exception e) { + throw new IntegrityException("unable to write file"); + } + return fileName; + } + +} From 1f0d8c67811056bf5b1f121aa6ef6269f35ce049 Mon Sep 17 00:00:00 2001 From: anuragsen Date: Wed, 11 Nov 2015 22:21:33 +0530 Subject: [PATCH 2/6] Refactoring code changes Change-Id: I716a8121d37492887b2b72a37a07f2c4aac75152 --- .gitignore | 2 + src/main/java/hudson/scm/DerbyUtils.java | 11 +- .../java/hudson/scm/IntegrityCMMember.java | 244 ++++++++---------- .../java/hudson/scm/IntegrityCMProject.java | 50 ++-- .../hudson/scm/IntegrityCheckoutTask.java | 20 +- .../hudson/scm/IntegrityConfigurable.java | 14 + src/main/java/hudson/scm/IntegritySCM.java | 138 +++++----- .../scm/IntegritySCMChkptNotifierStep.java | 47 ++-- .../scm/IntegritySCMLabelNotifierStep.java | 39 +-- .../java/hudson/scm/{ => api}/APISession.java | 5 +- src/main/java/hudson/scm/api/APIUtils.java | 79 ++++++ .../scm/{ => api}/ExceptionHandler.java | 10 +- .../java/hudson/scm/{ => api}/ISession.java | 2 +- .../scm/api/command/APICommandException.java | 31 +++ .../api/command/AddProjectLabelCommand.java | 30 +++ .../scm/api/command/BasicAPICommand.java | 119 +++++++++ .../scm/api/command/CheckPointCommand.java | 52 ++++ .../scm/api/command/CloseCPCommand.java | 29 +++ .../scm/api/command/CreateCPCommand.java | 24 ++ .../hudson/scm/api/command/IAPICommand.java | 80 ++++++ .../hudson/scm/api/command/LockCommand.java | 23 ++ .../scm/api/command/ProjectAddCommand.java | 31 +++ .../api/command/ProjectCheckinCommand.java | 33 +++ .../api/command/ProjectCheckoutCommand.java | 55 ++++ .../scm/api/command/ProjectInfoCommand.java | 25 ++ .../scm/api/command/RevisionInfoCommand.java | 25 ++ .../scm/api/command/SubmitCPCommand.java | 30 +++ .../hudson/scm/api/command/UnlockCommand.java | 31 +++ .../scm/api/command/ViewProjectCommand.java | 23 ++ .../java/hudson/scm/api/option/APIOption.java | 36 +++ .../hudson/scm/api/option/FileAPIOption.java | 27 ++ .../hudson/scm/api/option/IAPIOption.java | 56 ++++ .../java/hudson/scm/test/FakeAPISession.java | 16 +- 33 files changed, 1125 insertions(+), 312 deletions(-) rename src/main/java/hudson/scm/{ => api}/APISession.java (95%) create mode 100644 src/main/java/hudson/scm/api/APIUtils.java rename src/main/java/hudson/scm/{ => api}/ExceptionHandler.java (90%) rename src/main/java/hudson/scm/{ => api}/ISession.java (85%) create mode 100644 src/main/java/hudson/scm/api/command/APICommandException.java create mode 100644 src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java create mode 100644 src/main/java/hudson/scm/api/command/BasicAPICommand.java create mode 100644 src/main/java/hudson/scm/api/command/CheckPointCommand.java create mode 100644 src/main/java/hudson/scm/api/command/CloseCPCommand.java create mode 100644 src/main/java/hudson/scm/api/command/CreateCPCommand.java create mode 100644 src/main/java/hudson/scm/api/command/IAPICommand.java create mode 100644 src/main/java/hudson/scm/api/command/LockCommand.java create mode 100644 src/main/java/hudson/scm/api/command/ProjectAddCommand.java create mode 100644 src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java create mode 100644 src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java create mode 100644 src/main/java/hudson/scm/api/command/ProjectInfoCommand.java create mode 100644 src/main/java/hudson/scm/api/command/RevisionInfoCommand.java create mode 100644 src/main/java/hudson/scm/api/command/SubmitCPCommand.java create mode 100644 src/main/java/hudson/scm/api/command/UnlockCommand.java create mode 100644 src/main/java/hudson/scm/api/command/ViewProjectCommand.java create mode 100644 src/main/java/hudson/scm/api/option/APIOption.java create mode 100644 src/main/java/hudson/scm/api/option/FileAPIOption.java create mode 100644 src/main/java/hudson/scm/api/option/IAPIOption.java diff --git a/.gitignore b/.gitignore index 838fe1b..92567d9 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ release.txt executeBuild.js .idea/ .iml +/.classpath +/work/ diff --git a/src/main/java/hudson/scm/DerbyUtils.java b/src/main/java/hudson/scm/DerbyUtils.java index e43d823..8db0181 100644 --- a/src/main/java/hudson/scm/DerbyUtils.java +++ b/src/main/java/hudson/scm/DerbyUtils.java @@ -1,7 +1,5 @@ package hudson.scm; -import hudson.scm.IntegritySCM.DescriptorImpl; - import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -37,6 +35,9 @@ import com.mks.api.response.WorkItemIterator; import com.mks.api.si.SIModelTypeName; +import hudson.scm.IntegritySCM.DescriptorImpl; +import hudson.scm.api.APISession; + /** * This class provides certain utility functions for working with the embedded derby database */ @@ -793,7 +794,7 @@ public static synchronized int compareBaseline(String baselineProjectCache, Stri rs.updateString(CM_PROJECT.OLD_REVISION.toString(), oldRevision); // Initialize the author information as requested if( ! skipAuthorInfo ){ rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthor(api, + IntegrityCMMember.getAuthorFromRevisionInfo(api, rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); } @@ -825,7 +826,7 @@ public static synchronized int compareBaseline(String baselineProjectCache, Stri { // Initialize the author information as requested if( ! skipAuthorInfo ){ rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthor(api, + IntegrityCMMember.getAuthorFromRevisionInfo(api, rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); } @@ -1084,7 +1085,7 @@ public static synchronized void primeAuthorInformation(String projectCacheTable, { Hashtable rowHash = DerbyUtils.getRowData(rs); rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthor(api, + IntegrityCMMember.getAuthorFromRevisionInfo(api, rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); diff --git a/src/main/java/hudson/scm/IntegrityCMMember.java b/src/main/java/hudson/scm/IntegrityCMMember.java index 3e5d1a1..93a6d47 100644 --- a/src/main/java/hudson/scm/IntegrityCMMember.java +++ b/src/main/java/hudson/scm/IntegrityCMMember.java @@ -1,7 +1,5 @@ package hudson.scm; -import hudson.FilePath; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -13,13 +11,32 @@ import java.util.logging.Logger; import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang.BooleanUtils; -import com.mks.api.Command; -import com.mks.api.Option; -import com.mks.api.FileOption; import com.mks.api.response.APIException; +import com.mks.api.response.InterruptedException; import com.mks.api.response.Response; +import hudson.FilePath; +import hudson.scm.api.APISession; +import hudson.scm.api.APIUtils; +import hudson.scm.api.ExceptionHandler; +import hudson.scm.api.ISession; +import hudson.scm.api.command.APICommandException; +import hudson.scm.api.command.CloseCPCommand; +import hudson.scm.api.command.CreateCPCommand; +import hudson.scm.api.command.IAPICommand; +import hudson.scm.api.command.LockCommand; +import hudson.scm.api.command.ProjectAddCommand; +import hudson.scm.api.command.ProjectCheckinCommand; +import hudson.scm.api.command.ProjectCheckoutCommand; +import hudson.scm.api.command.RevisionInfoCommand; +import hudson.scm.api.command.SubmitCPCommand; +import hudson.scm.api.command.UnlockCommand; +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.FileAPIOption; +import hudson.scm.api.option.IAPIOption; + /** * This class is intended to represent an Integrity CM Member * However, due to scalability constraints, the bulk of the member metadata @@ -106,48 +123,29 @@ public static final String getDifferencesLink(String configPath, String memberID * @param restoreTimestamp Toggles whether or not the original timestamp should be used * @param lineTerminator Sets the line terminator for this file (native, crlf, or lf) * @return true if the operation succeeded or false if failed + * @throws InterruptedException * @throws APIException */ - public static final boolean checkout(ISession api, String configPath, String memberID, String memberRev, Timestamp memberTimestamp, - File targetFile, boolean restoreTimestamp, String lineTerminator) throws APIException + public static final boolean checkout(APISession api, String configPath, String memberID, String memberRev, Timestamp memberTimestamp, + File targetFile, boolean restoreTimestamp, String lineTerminator) throws APICommandException { - // Make sure the directory is created - if( ! targetFile.getParentFile().isDirectory() ) - { - targetFile.getParentFile().mkdirs(); - } - // Construct the project check-co command - Command coCMD = new Command(Command.SI, "projectco"); - coCMD.addOption(new Option("overwriteExisting")); - coCMD.addOption(new Option("nolock")); - coCMD.addOption(new Option("project", configPath)); - coCMD.addOption(new FileOption("targetFile", targetFile)); - coCMD.addOption(new Option(restoreTimestamp ? "restoreTimestamp" : "norestoreTimestamp")); - coCMD.addOption(new Option("lineTerminator", lineTerminator)); - coCMD.addOption(new Option("revision", memberRev)); + IAPICommand command = new ProjectCheckoutCommand(); + + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + command.addOption(new FileAPIOption(IAPIOption.TARGET_FILE, targetFile)); + command.addOption(new APIOption(restoreTimestamp ? IAPIOption.RESTORE_TIMESTAMP : IAPIOption.NORESTORE_TIMESTAMP)); + command.addOption(new APIOption(IAPIOption.LINE_TERMINATOR, lineTerminator)); + command.addOption(new APIOption(IAPIOption.REVISION, memberRev)); // Add the member selection - coCMD.addSelection(memberID); + command.addSelection(memberID); - // Execute the checkout command - Response res = api.runCommand(coCMD); - LOGGER.fine("Command: " + res.getCommandString() + " completed with exit code " + res.getExitCode()); + command.addAdditionalParameters(IAPIOption.MEMBER_TIMESTAMP,memberTimestamp); + command.addAdditionalParameters(IAPIOption.RESTORE_TIMESTAMP,restoreTimestamp); + command.addAdditionalParameters(IAPIOption.TARGET_FILE,targetFile); - // Return true if we were successful - if( res.getExitCode() == 0 ) - { - // Per JENKINS-13765 - providing a workaround due to API bug - // Update the timestamp for the file, if appropriate - if( restoreTimestamp ) - { - targetFile.setLastModified(memberTimestamp.getTime()); - } - return true; - } - // Otherwise return false... - else - { - return false; - } + Response response = command.execute(api); + int resCode = APIUtils.getResponseExitCode(response); + return BooleanUtils.toBoolean(resCode, 0, 1); } /** @@ -157,37 +155,30 @@ public static final boolean checkout(ISession api, String configPath, String mem * @param memberID Member ID for this file * @param memberRev Member Revision for this file * @return User responsible for making this change + * @throws APICommandException */ - public static String getAuthor(APISession api, String configPath, String memberID, String memberRev) + public static String getAuthorFromRevisionInfo(APISession api, String configPath, String memberID, String memberRev) { - // Initialize the return value String author = "unknown"; // Construct the revision-info command - Command revInfoCMD = new Command(Command.SI, "revisioninfo"); - revInfoCMD.addOption(new Option("project", configPath)); - revInfoCMD.addOption(new Option("revision", memberRev)); - // Add the member selection - revInfoCMD.addSelection(memberID); - try - { - // Execute the revision-info command - Response res = api.runCommand(revInfoCMD); - LOGGER.fine("Command: " + res.getCommandString() + " completed with exit code " + res.getExitCode()); - // Return the author associated with this update - if( res.getExitCode() == 0 ) - { - author = res.getWorkItem(memberID).getField("author").getValueAsString(); - } + IAPICommand command = new RevisionInfoCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + command.addOption(new APIOption(IAPIOption.REVISION, memberRev)); + command.addSelection(memberID); + + Response response; + try { + response = command.execute(api); + author = APIUtils.getAuthorInfo(response,memberID); + + } catch (APICommandException aex) { + ExceptionHandler eh = new ExceptionHandler(aex); + LOGGER.severe("API Exception caught..."); + LOGGER.severe(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + aex.printStackTrace(); } - catch(APIException aex) - { - ExceptionHandler eh = new ExceptionHandler(aex); - LOGGER.severe("API Exception caught..."); - LOGGER.severe(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); - aex.printStackTrace(); - } return author; } @@ -232,39 +223,29 @@ public static final String getMD5Checksum(File targetFile) throws IOException public static final void updateMember(APISession api, String configPath, FilePath member, String relativePath, String cpid, String desc) throws APIException { // Construct the lock command - Command lock = new Command(Command.SI, "lock"); - lock.addOption(new Option("cpid", cpid)); - lock.addOption(new Option("project", configPath)); - // Add the member selection - lock.addSelection(relativePath); + IAPICommand command = new LockCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + command.addOption(new APIOption(IAPIOption.CP_ID, cpid)); + command.addSelection(relativePath); try { // Execute the lock command - api.runCommand(lock); + command.execute(api); // If the lock was successful, check-in the updates LOGGER.fine("Attempting to checkin file: " + member); - // Construct the project check-in command - Command ci = new Command(Command.SI, "projectci"); - ci.addOption(new Option("cpid", cpid)); - ci.addOption(new Option("project", configPath)); - ci.addOption(new FileOption("sourceFile", new File(""+member))); - ci.addOption(new Option("saveTimestamp")); - ci.addOption(new Option("nocloseCP")); - ci.addOption(new Option("nodifferentNames")); - ci.addOption(new Option("branchVariant")); - ci.addOption(new Option("nocheckinUnchanged")); - ci.addOption(new Option("description", desc)); - - // Add the member selection - ci.addSelection(relativePath); - - // Execute the check-in command - api.runCommand(ci); + IAPICommand cmd = new ProjectCheckinCommand(); + cmd.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + cmd.addOption(new APIOption(IAPIOption.CP_ID, cpid)); + cmd.addOption(new FileAPIOption(IAPIOption.SOURCE_FILE, new File(""+member))); + cmd.addOption(new APIOption(IAPIOption.DESCRIPTION, desc)); + cmd.addSelection(relativePath); + + cmd.execute(api); } - catch( APIException ae ) + catch( APICommandException ae ) { // If the command fails, add only if the error indicates a missing member ExceptionHandler eh = new ExceptionHandler(ae); @@ -277,20 +258,15 @@ public static final void updateMember(APISession api, String configPath, FilePat LOGGER.fine("Attempting to add file: " + member); // Construct the project add command - Command add = new Command(Command.SI, "projectadd"); - add.addOption(new Option("cpid", cpid)); - add.addOption(new Option("project", configPath)); - add.addOption(new FileOption("sourceFile", new File(""+member))); - add.addOption(new Option("onExistingArchive", "sharearchive")); - add.addOption(new Option("saveTimestamp")); - add.addOption(new Option("nocloseCP")); - add.addOption(new Option("description", desc)); - - // Add the member selection - add.addSelection(relativePath); - + IAPICommand addCommand = new ProjectAddCommand(); + addCommand.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + addCommand.addOption(new APIOption(IAPIOption.CP_ID, cpid)); + addCommand.addOption(new FileAPIOption(IAPIOption.SOURCE_FILE, new File(""+member))); + addCommand.addOption(new APIOption(IAPIOption.DESCRIPTION, desc)); + + addCommand.addSelection(relativePath); // Execute the add command - api.runCommand(add); + addCommand.execute(api); } else { @@ -308,22 +284,15 @@ public static final void updateMember(APISession api, String configPath, FilePat public static final void unlockMembers(ISession api, String configPath) { // Construct the unlock command - Command unlock = new Command(Command.SI, "unlock"); - unlock.addOption(new Option("project", configPath)); - unlock.addOption(new Option("action", "remove")); - unlock.addOption(new Option("recurse")); - unlock.addOption(new Option("yes")); + IAPICommand command = new UnlockCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); - // Execute the unlock command - try - { - api.runCommand(unlock); - } - catch( APIException ae ) - { - ExceptionHandler eh = new ExceptionHandler(ae); - LOGGER.severe(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + try { + command.execute(api); + } catch (APICommandException e) { + ExceptionHandler eh = new ExceptionHandler(e); + LOGGER.severe(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); } } @@ -362,14 +331,12 @@ public static final String createCP(APISession api, String itemID, String desc) return cpid; } - // Construct the create cp command - Command cmd = new Command(Command.SI, "createcp"); - cmd.addOption(new Option("summary", desc)); - cmd.addOption(new Option("description", desc)); - cmd.addOption(new Option("issueId", itemID)); - - // Execute the command - Response res = api.runCommand(cmd); + IAPICommand command = new CreateCPCommand(); + command.addOption(new APIOption(IAPIOption.DESCRIPTION,desc)); + command.addOption(new APIOption(IAPIOption.SUMMARY,desc)); + command.addOption(new APIOption(IAPIOption.ITEM_ID,itemID)); + + Response res = command.execute(api); // Process the response object if( null != res ) @@ -398,23 +365,21 @@ public static final String createCP(APISession api, String itemID, String desc) * @param cpid Change Package ID * @throws APIException */ - public static final void submitCP(APISession api, String cpid) throws APIException + public static final void submitCP(APISession api, String cpid) throws APICommandException { LOGGER.fine("Submitting Change Package: " + cpid); - // Construct the close cp command - Command closecp = new Command(Command.SI, "closecp"); - closecp.addOption(new Option("releaseLocks")); - closecp.addSelection(cpid); + IAPICommand command = new CloseCPCommand(); + command.addSelection(cpid); // First we'll attempt to close the cp to release locks on files that haven't changed, // next we will submit the cp which will submit it for review or // it will get automatically closed in the case of transactional cps try { - api.runCommand(closecp); + command.execute(api); } - catch( APIException ae ) + catch( APICommandException ae ) { ExceptionHandler eh = new ExceptionHandler(ae); String exceptionString = eh.getMessage(); @@ -426,15 +391,10 @@ public static final void submitCP(APISession api, String cpid) throws APIExcepti LOGGER.fine("Attempting to submit cp: " + cpid); // Construct the submit cp command - Command submitcp = new Command(Command.SI, "submitcp"); - submitcp.addOption(new Option("closeCP")); - submitcp.addOption(new Option("commit")); - - // Add the cpid selection - submitcp.addSelection(cpid); - - // Execute the submit cp command - api.runCommand(submitcp); + IAPICommand submitcpcmd = new SubmitCPCommand(); + submitcpcmd.addSelection(cpid); + + submitcpcmd.execute(api); } else { diff --git a/src/main/java/hudson/scm/IntegrityCMProject.java b/src/main/java/hudson/scm/IntegrityCMProject.java index 13deb53..9384528 100644 --- a/src/main/java/hudson/scm/IntegrityCMProject.java +++ b/src/main/java/hudson/scm/IntegrityCMProject.java @@ -27,13 +27,19 @@ import org.w3c.dom.Document; import org.w3c.dom.Element; -import com.mks.api.Command; -import com.mks.api.Option; import com.mks.api.response.APIException; import com.mks.api.response.Field; import com.mks.api.response.Response; import com.mks.api.response.WorkItem; +import hudson.scm.api.APISession; +import hudson.scm.api.command.APICommandException; +import hudson.scm.api.command.AddProjectLabelCommand; +import hudson.scm.api.command.CheckPointCommand; +import hudson.scm.api.command.IAPICommand; +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + /** * This class represents an Integrity Configuration Management Project * Provides metadata information about a SCM Project @@ -361,23 +367,17 @@ private Element writeChangeLog(Element item, Hashtable membe * @param api Authenticated Integrity API Session * @param chkptLabel Checkpoint label string * @return Integrity API Response object - * @throws APIException + * @throws APICommandException */ - public Response checkpoint(APISession api, String chkptLabel) throws APIException + public Response checkpoint(APISession api, String chkptLabel) throws APICommandException { - // Construct the checkpoint command - Command siCheckpoint = new Command(Command.SI, "checkpoint"); - // Set the project name - siCheckpoint.addOption(new Option("project", fullConfigSyntax)); - // Set the label and description if applicable - if( null != chkptLabel && chkptLabel.length() > 0 ) - { - // Set the label - siCheckpoint.addOption(new Option("label", chkptLabel)); - // Set the description - siCheckpoint.addOption(new Option("description", chkptLabel)); - } - return api.runCommand(siCheckpoint); + // Construct the checkpoint command + IAPICommand command = new CheckPointCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, fullConfigSyntax)); + // Set the label and description if applicable + command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, chkptLabel); + + return command.execute(api); } /** @@ -390,16 +390,12 @@ public Response checkpoint(APISession api, String chkptLabel) throws APIExceptio public Response addProjectLabel(APISession api, String chkptLabel, String projectName, String projectRevision) throws APIException { // Construct the addprojectlabel command - Command siAddProjectLabel = new Command(Command.SI, "addprojectlabel"); - // Set the project name - siAddProjectLabel.addOption(new Option("project", projectName)); - // Set the project revision - siAddProjectLabel.addOption(new Option("projectRevision", projectRevision)); - // Set the label - siAddProjectLabel.addOption(new Option("label", chkptLabel)); - // Move the label, if a previous one was applied - siAddProjectLabel.addOption(new Option("moveLabel")); - return api.runCommand(siAddProjectLabel); + IAPICommand command = new AddProjectLabelCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, projectName)); + command.addOption(new APIOption(IAPIOption.LABEL, chkptLabel)); + command.addOption(new APIOption(IAPIOption.PROJECT_REVISION, projectRevision)); + + return command.execute(api); } /** diff --git a/src/main/java/hudson/scm/IntegrityCheckoutTask.java b/src/main/java/hudson/scm/IntegrityCheckoutTask.java index 147d935..de810b8 100644 --- a/src/main/java/hudson/scm/IntegrityCheckoutTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckoutTask.java @@ -1,10 +1,5 @@ package hudson.scm; -import hudson.FilePath; -import hudson.FilePath.FileCallable; -import hudson.model.TaskListener; -import hudson.remoting.VirtualChannel; - import java.io.File; import java.io.IOException; import java.sql.Timestamp; @@ -23,12 +18,17 @@ import java.util.logging.Level; import java.util.logging.Logger; -import jenkins.security.Roles; - import org.jenkinsci.remoting.RoleChecker; import org.jenkinsci.remoting.RoleSensitive; -import com.mks.api.response.APIException; +import hudson.FilePath; +import hudson.FilePath.FileCallable; +import hudson.model.TaskListener; +import hudson.remoting.VirtualChannel; +import hudson.scm.api.APISession; +import hudson.scm.api.ExceptionHandler; +import hudson.scm.api.command.APICommandException; +import jenkins.security.Roles; public class IntegrityCheckoutTask implements FileCallable { @@ -242,9 +242,9 @@ public Void call() throws Exception { IntegrityCMMember.checkout(api, configPath, memberID, memberRev, memberTimestamp, targetFile, restoreTimestamp, lineTerminator); } - catch( APIException aex ) + catch(APICommandException aex) { - LOGGER.severe("API Exception caught..."); + LOGGER.severe("API Command Exception caught."); ExceptionHandler eh = new ExceptionHandler(aex); LOGGER.severe(eh.getMessage()); LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); diff --git a/src/main/java/hudson/scm/IntegrityConfigurable.java b/src/main/java/hudson/scm/IntegrityConfigurable.java index a7bc8bc..a783df8 100644 --- a/src/main/java/hudson/scm/IntegrityConfigurable.java +++ b/src/main/java/hudson/scm/IntegrityConfigurable.java @@ -225,4 +225,18 @@ public boolean equals(Object o) return false; } } + + /* (non-Javadoc) + * @see java.lang.Object#hashCode() + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + + result = prime * result + + ((hostName == null) ? 0 : hostName.hashCode()) + ((password == null) ? 0 : password.hashCode()); + + return result; + } } diff --git a/src/main/java/hudson/scm/IntegritySCM.java b/src/main/java/hudson/scm/IntegritySCM.java index d457124..7f54d61 100644 --- a/src/main/java/hudson/scm/IntegritySCM.java +++ b/src/main/java/hudson/scm/IntegritySCM.java @@ -1,20 +1,5 @@ package hudson.scm; -import hudson.AbortException; -import hudson.Extension; -import hudson.FilePath; -import hudson.Launcher; -import hudson.model.ModelObject; -import hudson.model.TaskListener; -import hudson.model.AbstractBuild; -import hudson.model.Job; -import hudson.model.Run; -import hudson.scm.IntegrityCheckpointAction.IntegrityCheckpointDescriptorImpl; -import hudson.scm.browsers.IntegrityWebUI; -import hudson.util.FormValidation; -import hudson.util.Secret; -import hudson.util.ListBoxModel; - import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -23,34 +8,60 @@ import java.io.Serializable; import java.sql.SQLException; import java.text.SimpleDateFormat; -import java.util.logging.Logger; -import java.util.logging.Level; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; import javax.servlet.ServletException; import javax.sql.ConnectionPoolDataSource; -import jenkins.model.Jenkins; -import net.sf.json.JSONObject; - import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; import org.kohsuke.stapler.export.Exported; -import com.mks.api.Command; -import com.mks.api.MultiValue; -import com.mks.api.Option; import com.mks.api.response.APIException; import com.mks.api.response.Response; import com.mks.api.response.WorkItem; +import hudson.AbortException; +import hudson.Extension; +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.AbstractBuild; +import hudson.model.Job; +import hudson.model.ModelObject; +import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.scm.ChangeLogParser; +import hudson.scm.PollingResult; +import hudson.scm.RepositoryBrowsers; +import hudson.scm.SCM; +import hudson.scm.SCMDescriptor; +import hudson.scm.SCMRevisionState; +import hudson.scm.IntegrityCheckpointAction.IntegrityCheckpointDescriptorImpl; +import hudson.scm.api.APISession; +import hudson.scm.api.APIUtils; +import hudson.scm.api.ExceptionHandler; +import hudson.scm.api.command.APICommandException; +import hudson.scm.api.command.IAPICommand; +import hudson.scm.api.command.ProjectInfoCommand; +import hudson.scm.api.command.ViewProjectCommand; +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; +import hudson.scm.browsers.IntegrityWebUI; +import hudson.util.FormValidation; +import hudson.util.ListBoxModel; +import hudson.util.Secret; +import jenkins.model.Jenkins; +import net.sf.json.JSONObject; + /** * This class provides an integration between Hudson/Jenkins for Continuous Builds and * PTC Integrity for Configuration Management @@ -639,16 +650,18 @@ public SCMRevisionState calcRevisionsFromBuild(Run run, FilePath workspace * @return response Integrity API Response * @throws APIException */ - private Response initializeCMProject(APISession api, String projectCacheTable, String resolvedConfigPath) throws APIException + private Response initializeCMProject(APISession api, String projectCacheTable, String resolvedConfigPath) throws APICommandException { // Get the project information for this project - Command siProjectInfoCmd = new Command(Command.SI, "projectinfo"); - siProjectInfoCmd.addOption(new Option("project", resolvedConfigPath)); - LOGGER.fine("Preparing to execute si projectinfo for " + resolvedConfigPath); - Response infoRes = api.runCommand(siProjectInfoCmd); - LOGGER.fine(infoRes.getCommandString() + " returned " + infoRes.getExitCode()); + + IAPICommand command = new ProjectInfoCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, resolvedConfigPath)); + + Response infoRes = command.execute(api); + + LOGGER.fine(infoRes.getCommandString() + " returned " + APIUtils.getResponseExitCode(infoRes)); // Initialize our siProject class variable - IntegrityCMProject siProject = new IntegrityCMProject(infoRes.getWorkItems().next(), projectCacheTable); + IntegrityCMProject siProject = new IntegrityCMProject(APIUtils.getWorkItem(infoRes), projectCacheTable); // Set the project options siProject.setLineTerminator(lineTerminator); siProject.setRestoreTimestamp(restoreTimestamp); @@ -660,10 +673,10 @@ private Response initializeCMProject(APISession api, String projectCacheTable, S /** * Utility function to parse the include/exclude filter - * @param siViewProjectCmd API Command for the 'si viewproject' command + * @param command API Command for the 'si viewproject' command * @return */ - private void applyMemberFilters(Command siViewProjectCmd) + private void applyMemberFilters(IAPICommand command) { // Checking if our include list has any entries if( null != includeList && includeList.length() > 0 ) @@ -677,7 +690,7 @@ private void applyMemberFilters(Command siViewProjectCmd) filterString.append("file:"); filterString.append(filterTokens[i]); } - siViewProjectCmd.addOption(new Option("filter", filterString.toString())); + command.addOption(new APIOption(IAPIOption.FILTER, filterString.toString())); } // Checking if our exclude list has any entries @@ -689,7 +702,7 @@ private void applyMemberFilters(Command siViewProjectCmd) { if (filterTokens[i]!= null) { - siViewProjectCmd.addOption(new Option("filter", "!file:"+filterTokens[i])); + command.addOption(new APIOption(IAPIOption.FILTER, "!file:"+filterTokens[i])); } } } @@ -706,24 +719,20 @@ private Response initializeCMProjectMembers(APISession api) throws APIException, { IntegrityCMProject siProject = getIntegrityProject(); // Lets parse this project - Command siViewProjectCmd = new Command(Command.SI, "viewproject"); - siViewProjectCmd.addOption(new Option("recurse")); - siViewProjectCmd.addOption(new Option("project", siProject.getConfigurationPath())); - MultiValue mvFields = new MultiValue(","); - mvFields.add("name"); - mvFields.add("context"); - mvFields.add("cpid"); - mvFields.add("memberrev"); - mvFields.add("membertimestamp"); - mvFields.add("memberdescription"); - mvFields.add("type"); - siViewProjectCmd.addOption(new Option("fields", mvFields)); + + IAPICommand command = new ViewProjectCommand(); + + command.addOption(new APIOption(IAPIOption.RECURSE)); + command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath())); + APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"); + command.addOption(new APIOption(IAPIOption.FIELDS, APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"))); // Apply our include/exclude filters - applyMemberFilters(siViewProjectCmd); - + applyMemberFilters(command); + LOGGER.fine("Preparing to execute si viewproject for " + siProject.getConfigurationPath()); - Response viewRes = api.runCommandWithInterim(siViewProjectCmd); + Response viewRes = command.execute(api); + DerbyUtils.parseProject(siProject, viewRes.getWorkItems()); return viewRes; } @@ -803,20 +812,20 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, // Make sure we don't have a build project configuration if( ! siProject.isBuild() ) { - // Execute a pre-build checkpoint... - listener.getLogger().println("Preparing to execute pre-build si checkpoint for " + siProject.getConfigurationPath()); - Response res = siProject.checkpoint(api, IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), checkpointLabel)); - LOGGER.fine(res.getCommandString() + " returned " + res.getExitCode()); - WorkItem wi = res.getWorkItem(siProject.getConfigurationPath()); - String chkpt = wi.getResult().getField("resultant").getItem().getId(); - listener.getLogger().println("Successfully executed pre-build checkpoint for project " + - siProject.getConfigurationPath() + ", new revision is " + chkpt); - // Update the siProject to use the new checkpoint as the basis for this build - Command siProjectInfoCmd = new Command(Command.SI, "projectinfo"); - siProjectInfoCmd.addOption(new Option("project", siProject.getConfigurationPath() + "#forceJump=#b=" + chkpt)); - - Response infoRes = api.runCommand(siProjectInfoCmd); - siProject.initializeProject(infoRes.getWorkItems().next()); + // Execute a pre-build checkpoint... + listener.getLogger().println("Preparing to execute pre-build si checkpoint for " + siProject.getConfigurationPath()); + Response res = siProject.checkpoint(api, IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), checkpointLabel)); + LOGGER.fine(res.getCommandString() + " returned " + res.getExitCode()); + WorkItem wi = res.getWorkItem(siProject.getConfigurationPath()); + String chkpt = wi.getResult().getField("resultant").getItem().getId(); + listener.getLogger().println("Successfully executed pre-build checkpoint for project " + + siProject.getConfigurationPath() + ", new revision is " + chkpt); + // Update the siProject to use the new checkpoint as the basis for this build + IAPICommand command = new ProjectInfoCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath() + "#forceJump=#b=" + chkpt)); + + Response infoRes = command.execute(api); + siProject.initializeProject(infoRes.getWorkItems().next()); } else { @@ -856,6 +865,9 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, String resolvedAltWkspace = IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), alternateWorkspace); // If we we were not able to establish the previous project state, then always do full checkout. cleanCopy = true // Otherwise, update the workspace in accordance with the user's cleanCopy option + + // ANURAG : construct command objects in this class and pass them below + IntegrityCheckoutTask coTask = new IntegrityCheckoutTask(projectMembersList, dirList, resolvedAltWkspace, lineTerminator, restoreTimestamp, ((null == prevProjectCache || prevProjectCache.length() == 0) ? true : cleanCopy), fetchChangedWorkspaceFiles,checkoutThreadPoolSize, listener, coSettings); diff --git a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java index 03709cd..8b93f6d 100644 --- a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java @@ -3,14 +3,17 @@ import java.io.IOException; import java.util.logging.Logger; -import com.mks.api.Command; -import com.mks.api.Option; -import com.mks.api.response.APIException; - import hudson.FilePath; import hudson.Launcher; -import hudson.model.TaskListener; import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.scm.api.APISession; +import hudson.scm.api.ExceptionHandler; +import hudson.scm.api.command.APICommandException; +import hudson.scm.api.command.CheckPointCommand; +import hudson.scm.api.command.IAPICommand; +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; import jenkins.tasks.SimpleBuildStep; @@ -46,32 +49,22 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi try { // Construct the checkpoint command - Command siCheckpoint = new Command(Command.SI, "checkpoint"); - // Set the project name - siCheckpoint.addOption(new Option("project", configPath)); - // Set the label and description if applicable - if( null != checkpointLabel && checkpointLabel.length() > 0 ) - { - // Set the label - siCheckpoint.addOption(new Option("label", checkpointLabel)); - } + IAPICommand command = new CheckPointCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, checkpointLabel); + command.addAdditionalParameters(IAPIOption.CHECKPOINT_DESCRIPTION, checkpointDesc); + + command.execute(api); - if( null != checkpointDesc && checkpointDesc.length() > 0 ) - { - // Set the description - siCheckpoint.addOption(new Option("description", checkpointDesc)); - } - - api.runCommand(siCheckpoint); listener.getLogger().println("Successfully checkpointed project " + configPath); } - catch (APIException aex) + catch (APICommandException aex) { - LOGGER.severe("API Exception caught..."); - ExceptionHandler eh = new ExceptionHandler(aex); - aex.printStackTrace(listener.fatalError(eh.getMessage())); - LOGGER.severe(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + LOGGER.severe("API Exception caught..."); + ExceptionHandler eh = new ExceptionHandler(aex); + aex.printStackTrace(listener.fatalError(eh.getMessage())); + LOGGER.severe(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); } finally { diff --git a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java index bf04535..e9e2fb3 100644 --- a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java @@ -3,14 +3,17 @@ import java.io.IOException; import java.util.logging.Logger; -import com.mks.api.Command; -import com.mks.api.Option; -import com.mks.api.response.APIException; - import hudson.FilePath; import hudson.Launcher; -import hudson.model.TaskListener; import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.scm.api.APISession; +import hudson.scm.api.ExceptionHandler; +import hudson.scm.api.command.APICommandException; +import hudson.scm.api.command.AddProjectLabelCommand; +import hudson.scm.api.command.IAPICommand; +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; import jenkins.tasks.SimpleBuildStep; @@ -44,23 +47,21 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi try { // Assumes the checkpoint was done before the build, so lets apply the label now - Command siAddProjectLabel = new Command(Command.SI, "addprojectlabel"); - // Set the project name - siAddProjectLabel.addOption(new Option("project", configPath)); - // Set the label - siAddProjectLabel.addOption(new Option("label", checkpointLabel)); - // Move the label, if a previous one was applied - siAddProjectLabel.addOption(new Option("moveLabel")); - api.runCommand(siAddProjectLabel); + IAPICommand command = new AddProjectLabelCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + command.addOption(new APIOption(IAPIOption.LABEL, checkpointLabel)); + + command.execute(api); + listener.getLogger().println("Successfully added label " + checkpointLabel); } - catch (APIException aex) + catch (APICommandException aex) { - LOGGER.severe("API Exception caught..."); - ExceptionHandler eh = new ExceptionHandler(aex); - aex.printStackTrace(listener.fatalError(eh.getMessage())); - LOGGER.severe(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + LOGGER.severe("API Exception caught..."); + ExceptionHandler eh = new ExceptionHandler(aex); + aex.printStackTrace(listener.fatalError(eh.getMessage())); + LOGGER.severe(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); } finally { diff --git a/src/main/java/hudson/scm/APISession.java b/src/main/java/hudson/scm/api/APISession.java similarity index 95% rename from src/main/java/hudson/scm/APISession.java rename to src/main/java/hudson/scm/api/APISession.java index 9b665f1..6145244 100644 --- a/src/main/java/hudson/scm/APISession.java +++ b/src/main/java/hudson/scm/api/APISession.java @@ -1,4 +1,4 @@ -package hudson.scm; +package hudson.scm.api; import com.mks.api.CmdRunner; import com.mks.api.Command; @@ -6,6 +6,9 @@ import com.mks.api.IntegrationPointFactory; import com.mks.api.response.APIException; import com.mks.api.response.Response; + +import hudson.scm.IntegrityConfigurable; + import com.mks.api.Session; import java.io.IOException; diff --git a/src/main/java/hudson/scm/api/APIUtils.java b/src/main/java/hudson/scm/api/APIUtils.java new file mode 100644 index 0000000..0f47d19 --- /dev/null +++ b/src/main/java/hudson/scm/api/APIUtils.java @@ -0,0 +1,79 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api; + +import com.mks.api.MultiValue; +import com.mks.api.response.APIException; +import com.mks.api.response.InterruptedException; +import com.mks.api.response.Response; +import com.mks.api.response.WorkItem; + +import hudson.scm.api.command.APICommandException; +import hudson.scm.api.option.IAPIOption; + +/** + * Utility class for common Integrity API utilities + * + * @author Author: asen + * @version $Revision: $ + */ +public class APIUtils +{ + + /** + * Utility method to create a multi value field object + * + * @param separator + * @param params + * @return + */ + public static MultiValue createMultiValueField(String separator, String... params) + { + MultiValue mvFields = new MultiValue(separator); + for (String param : params){ + mvFields.add(param); + } + + return mvFields; + } + + + /** + * @param response + * @return + * @throws APICommandException + */ + public static int getResponseExitCode(Response response) throws APICommandException + { + try { + return response.getExitCode(); + } catch (InterruptedException e) { + throw new APICommandException(e); + } + } + + public static WorkItem getWorkItem(Response response) throws APICommandException + { + try { + return response.getWorkItems().next(); + } catch (APIException e) { + throw new APICommandException(e); + } + } + + /** + * @param response + * @param memberID + * @return + */ + public static String getAuthorInfo(Response response, String memberID) + { + String author = response.getWorkItem(memberID).getField(IAPIOption.AUTHOR).getValueAsString(); + return author; + } +} diff --git a/src/main/java/hudson/scm/ExceptionHandler.java b/src/main/java/hudson/scm/api/ExceptionHandler.java similarity index 90% rename from src/main/java/hudson/scm/ExceptionHandler.java rename to src/main/java/hudson/scm/api/ExceptionHandler.java index 6799b32..f743004 100644 --- a/src/main/java/hudson/scm/ExceptionHandler.java +++ b/src/main/java/hudson/scm/api/ExceptionHandler.java @@ -1,4 +1,4 @@ -package hudson.scm; +package hudson.scm.api; import com.mks.api.response.APIException; import com.mks.api.response.Response; @@ -21,10 +21,10 @@ public ExceptionHandler(APIException ex) // API Exceptions can be nested. Hence we will need to recurse the // exception hierarchy to dig for a conclusive message - Response response = ex.getResponse(); - - // Print the stack trace to standard out for debugging purposes - ex.printStackTrace(); + Response response = ex.getResponse(); + + // Print the stack trace to standard out for debugging purposes + ex.printStackTrace(); // The API failed to execute the command (i.e. a real API error) if( null == response) diff --git a/src/main/java/hudson/scm/ISession.java b/src/main/java/hudson/scm/api/ISession.java similarity index 85% rename from src/main/java/hudson/scm/ISession.java rename to src/main/java/hudson/scm/api/ISession.java index 59ecd60..d97dc05 100644 --- a/src/main/java/hudson/scm/ISession.java +++ b/src/main/java/hudson/scm/api/ISession.java @@ -1,4 +1,4 @@ -package hudson.scm; +package hudson.scm.api; import com.mks.api.Command; import com.mks.api.response.APIException; diff --git a/src/main/java/hudson/scm/api/command/APICommandException.java b/src/main/java/hudson/scm/api/command/APICommandException.java new file mode 100644 index 0000000..c5e8525 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/APICommandException.java @@ -0,0 +1,31 @@ +/** + * + */ +package hudson.scm.api.command; + +import com.mks.api.response.APIException; + +/** + * @author asen + * + */ +public class APICommandException extends APIException { + + private static final long serialVersionUID = -7355644672829917075L; + + public APICommandException() + { + super(); + } + + public APICommandException(final String message) + { + super(message); + } + + public APICommandException(final Throwable error) + { + super(error); + } + +} diff --git a/src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java b/src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java new file mode 100644 index 0000000..c39f99b --- /dev/null +++ b/src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java @@ -0,0 +1,30 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class AddProjectLabelCommand extends BasicAPICommand +{ + public AddProjectLabelCommand() + { + cmd = new Command(Command.SI, ADD_PROJECT_LABEL_COMMAND); + + // Initialize defaults + // Move the label, if a previous one was applied + cmd.addOption(new APIOption(IAPIOption.MOVE_LABEL)); + } +} diff --git a/src/main/java/hudson/scm/api/command/BasicAPICommand.java b/src/main/java/hudson/scm/api/command/BasicAPICommand.java new file mode 100644 index 0000000..771fc32 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/BasicAPICommand.java @@ -0,0 +1,119 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import java.util.Map; + +import com.mks.api.Command; +import com.mks.api.Option; +import com.mks.api.response.APIException; +import com.mks.api.response.Response; + +import hudson.scm.api.ISession; +import hudson.scm.api.option.IAPIOption; + +/** + * All Jenkins Integrity API Commands have to extend this class in order to execute Integrity API calls using the default method + * + * @author Author: asen + * @version $Revision: $ + */ +public abstract class BasicAPICommand implements IAPICommand +{ + protected Command cmd; + protected Map commandHelperObjects; + + protected Response res; + + + /* (non-Javadoc) + * @see hudson.scm.api.APICommand#execute(hudson.scm.api.APISession) + */ + @Override + public Response execute(ISession api) throws APICommandException + { + if(null == cmd) + throw new APICommandException("Integration API Command cannot be null"); + + try { + + doPreAction(); + + res = api.runCommand(getMKSAPICommand()); + if(null != res){ + int resCode = res.getExitCode(); + + if(resCode == 0){ + // execute post action only on success response + doPostAction(); + } + } + + } catch (APIException e) { + throw new APICommandException(e); + } + + return res; + } + + @Override + public boolean execute() throws APICommandException + { + //TODO Initialize API session here using an "IntegrityConfigurable.java" object + return false; + } + + /* (non-Javadoc) + * @see hudson.scm.api.command.APICommand#getMKSAPICommand() + */ + @Override + public Command getMKSAPICommand() + { + return cmd; + } + + @Override + public void addOption(IAPIOption option) + { + cmd.addOption((Option) option); + } + + @Override + public void addSelection(String param) + { + cmd.addSelection(param); + } + + /* (non-Javadoc) + * @see hudson.scm.api.command.APICommand#doPostAction() + */ + @Override + public void doPostAction() + { + // do nothing + } + + /* (non-Javadoc) + * @see hudson.scm.api.command.APICommand#doPreAction() + */ + @Override + public void doPreAction() + { + // do nothing + } + + /* (non-Javadoc) + * @see hudson.scm.api.command.APICommand#addAdditionalParameters(java.lang.String, java.lang.Object) + */ + @Override + public void addAdditionalParameters(String paramName, Object param) + { + commandHelperObjects.put(paramName, param); + } + +} diff --git a/src/main/java/hudson/scm/api/command/CheckPointCommand.java b/src/main/java/hudson/scm/api/command/CheckPointCommand.java new file mode 100644 index 0000000..8a2e59a --- /dev/null +++ b/src/main/java/hudson/scm/api/command/CheckPointCommand.java @@ -0,0 +1,52 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import java.util.HashMap; + +import org.apache.commons.lang.StringUtils; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class CheckPointCommand extends BasicAPICommand +{ + public CheckPointCommand() + { + cmd = new Command(Command.SI, CHECKPOINT_COMMAND); + commandHelperObjects = new HashMap(); + } + + @Override + public void doPreAction() + { + String chkptLabel = (String) commandHelperObjects.get(IAPIOption.CHECKPOINT_LABEL); + String checkpointDesc = (String) commandHelperObjects.get(IAPIOption.CHECKPOINT_DESCRIPTION); + if(StringUtils.isNotBlank(chkptLabel)) + { + // Set the label + cmd.addOption(new APIOption(IAPIOption.LABEL, chkptLabel)); + } + + // Set the description + if(StringUtils.isNotBlank(checkpointDesc)){ + cmd.addOption(new APIOption(IAPIOption.DESCRIPTION, checkpointDesc)); + } + else if(StringUtils.isNotBlank(chkptLabel)){ // Set the label instead as description + cmd.addOption(new APIOption(IAPIOption.DESCRIPTION, chkptLabel)); + } + + } +} diff --git a/src/main/java/hudson/scm/api/command/CloseCPCommand.java b/src/main/java/hudson/scm/api/command/CloseCPCommand.java new file mode 100644 index 0000000..bef393a --- /dev/null +++ b/src/main/java/hudson/scm/api/command/CloseCPCommand.java @@ -0,0 +1,29 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class CloseCPCommand extends BasicAPICommand +{ + public CloseCPCommand() + { + cmd = new Command(Command.SI, CLOSE_CP_COMMAND); + + // Initialize defaults + cmd.addOption(new APIOption(IAPIOption.RELEASE_LOCKS)); + } +} diff --git a/src/main/java/hudson/scm/api/command/CreateCPCommand.java b/src/main/java/hudson/scm/api/command/CreateCPCommand.java new file mode 100644 index 0000000..de54633 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/CreateCPCommand.java @@ -0,0 +1,24 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class CreateCPCommand extends BasicAPICommand +{ + public CreateCPCommand() + { + cmd = new Command(Command.SI, CREATE_CP_COMMAND); + } + +} diff --git a/src/main/java/hudson/scm/api/command/IAPICommand.java b/src/main/java/hudson/scm/api/command/IAPICommand.java new file mode 100644 index 0000000..322c5cb --- /dev/null +++ b/src/main/java/hudson/scm/api/command/IAPICommand.java @@ -0,0 +1,80 @@ +package hudson.scm.api.command; + +import com.mks.api.Command; +import com.mks.api.response.Response; + +import hudson.scm.api.ISession; +import hudson.scm.api.option.IAPIOption; + +/** + * All Jenkins Integrity API command calls must extend this interface. A command is essentially a + * request that makes up what is logically an Integrity API call. + * Commands correspond to operations the user can perform with + * Integrity, for example checking out a project or applying a change package etc. + * + * @author asen + * +**/ + +public interface IAPICommand +{ + + static String PROJECT_CHECKOUT_COMMAND = "projectco"; + static String PROJECT_CHECKIN_COMMAND = "projectci"; + static String PROJECT_INFO_COMMAND = "projectinfo"; + static String VIEW_PROJECT_COMMAND = "viewproject"; + static String REVISION_INFO_COMMAND = "revisioninfo"; + static String LOCK_COMMAND = "lock"; + static String PROJECT_ADD_COMMAND = "projectadd"; + static String UNLOCK_COMMAND = "unlock"; + static String CREATE_CP_COMMAND = "createcp"; + static String CLOSE_CP_COMMAND = "closecp"; + static String SUBMIT_CP_COMMAND = "submitcp"; + static String CHECKPOINT_COMMAND = "checkpoint"; + static String ADD_PROJECT_LABEL_COMMAND = "addprojectlabel"; + + /** + * Execute the command using Integrity Session API + * @param api + */ + public Response execute(ISession api) throws APICommandException; + + /** + * Execute the command using an auto-generated Integrity Session API + * @return + * @throws APICommandException + */ + public boolean execute() throws APICommandException; + + /** + * @return + */ + public Command getMKSAPICommand(); + + /** + * Do actions post the Integrity API call specifically for Jenkins functionality + */ + public void doPostAction(); + + /** + * Do actions pre the Integrity API call specifically for Jenkins functionality + */ + public void doPreAction(); + + /** + * Objects required for command pre and post processing. + * @param objects + */ + public void addAdditionalParameters(String paramName, Object param); + + /** + * @param option + */ + public void addOption(IAPIOption option); + + /** + * @param param + */ + public void addSelection(String param); + +} diff --git a/src/main/java/hudson/scm/api/command/LockCommand.java b/src/main/java/hudson/scm/api/command/LockCommand.java new file mode 100644 index 0000000..ce8080f --- /dev/null +++ b/src/main/java/hudson/scm/api/command/LockCommand.java @@ -0,0 +1,23 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class LockCommand extends BasicAPICommand +{ + public LockCommand() + { + cmd = new Command(Command.SI, LOCK_COMMAND); + } +} diff --git a/src/main/java/hudson/scm/api/command/ProjectAddCommand.java b/src/main/java/hudson/scm/api/command/ProjectAddCommand.java new file mode 100644 index 0000000..fd1df1b --- /dev/null +++ b/src/main/java/hudson/scm/api/command/ProjectAddCommand.java @@ -0,0 +1,31 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class ProjectAddCommand extends BasicAPICommand +{ + public ProjectAddCommand() + { + cmd = new Command(Command.SI, PROJECT_ADD_COMMAND); + + // Initialize defaults + cmd.addOption(new APIOption(IAPIOption.SAVE_TIMESTAMP)); + cmd.addOption(new APIOption(IAPIOption.NO_CLOSE_CP)); + cmd.addOption(new APIOption(IAPIOption.ON_EXISTING_ARCHIVE, IAPIOption.SHARE_ARCHIVE)); + } +} diff --git a/src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java b/src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java new file mode 100644 index 0000000..ca1f86b --- /dev/null +++ b/src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java @@ -0,0 +1,33 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class ProjectCheckinCommand extends BasicAPICommand +{ + public ProjectCheckinCommand() + { + cmd = new Command(Command.SI, PROJECT_CHECKIN_COMMAND); + + // Initialize defaults + cmd.addOption(new APIOption(IAPIOption.SAVE_TIMESTAMP)); + cmd.addOption(new APIOption(IAPIOption.NO_CLOSE_CP)); + cmd.addOption(new APIOption(IAPIOption.NO_DIFFERENT_NAMES)); + cmd.addOption(new APIOption(IAPIOption.BRANCH_VARIANT)); + cmd.addOption(new APIOption(IAPIOption.NO_CHECKIN_UNCHANGED)); + } +} diff --git a/src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java b/src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java new file mode 100644 index 0000000..bd46843 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java @@ -0,0 +1,55 @@ +package hudson.scm.api.command; + +import java.io.File; +import java.sql.Timestamp; +import java.util.HashMap; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * Project Checkout command for the Integrity Jenkins Plugin + * + * @author Author: asen + * @version $Revision: $ + */ +public class ProjectCheckoutCommand extends BasicAPICommand +{ + + public ProjectCheckoutCommand() + { + cmd = new Command(Command.SI, PROJECT_CHECKOUT_COMMAND); + commandHelperObjects = new HashMap(); + + // Initialize defaults + cmd.addOption(new APIOption(IAPIOption.OVER_WRITE_EXISTING)); + cmd.addOption(new APIOption(IAPIOption.NO_LOCK)); + } + + @Override + public void doPostAction() + { + boolean restoreTimestamp = Boolean.valueOf(commandHelperObjects.get(IAPIOption.RESTORE_TIMESTAMP).toString()); + File targetFile = (File)commandHelperObjects.get(IAPIOption.TARGET_FILE); + Timestamp memberTimestamp = (Timestamp)commandHelperObjects.get(IAPIOption.MEMBER_TIMESTAMP); + if(restoreTimestamp) + { + targetFile.setLastModified(memberTimestamp.getTime()); + } + } + + @Override + public void doPreAction() + { + // Make sure the directory is created + File targetFile = (File)commandHelperObjects.get(IAPIOption.TARGET_FILE); + + if( ! targetFile.getParentFile().isDirectory() ) + { + targetFile.getParentFile().mkdirs(); + } + } + +} diff --git a/src/main/java/hudson/scm/api/command/ProjectInfoCommand.java b/src/main/java/hudson/scm/api/command/ProjectInfoCommand.java new file mode 100644 index 0000000..3f652ee --- /dev/null +++ b/src/main/java/hudson/scm/api/command/ProjectInfoCommand.java @@ -0,0 +1,25 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +/** + * Project Info command for the Integrity Jenkins Plugin + * @author Author: asen + * @version $Revision: $ + */ +public class ProjectInfoCommand extends BasicAPICommand +{ + + public ProjectInfoCommand() + { + cmd = new Command(Command.SI, PROJECT_INFO_COMMAND); + } + +} diff --git a/src/main/java/hudson/scm/api/command/RevisionInfoCommand.java b/src/main/java/hudson/scm/api/command/RevisionInfoCommand.java new file mode 100644 index 0000000..7ef38a8 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/RevisionInfoCommand.java @@ -0,0 +1,25 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +/** + * Revision Info command for the Integrity Jenkins Plugin + * + * @author Author: asen + * @version $Revision: $ + */ +public class RevisionInfoCommand extends BasicAPICommand +{ + public RevisionInfoCommand() + { + cmd = new Command(Command.SI, REVISION_INFO_COMMAND); + } + +} diff --git a/src/main/java/hudson/scm/api/command/SubmitCPCommand.java b/src/main/java/hudson/scm/api/command/SubmitCPCommand.java new file mode 100644 index 0000000..3e30c50 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/SubmitCPCommand.java @@ -0,0 +1,30 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class SubmitCPCommand extends BasicAPICommand +{ + public SubmitCPCommand() + { + cmd = new Command(Command.SI, SUBMIT_CP_COMMAND); + + // Initialize defaults + cmd.addOption(new APIOption(IAPIOption.CLOSE_CP)); + cmd.addOption(new APIOption(IAPIOption.COMMIT)); + } +} diff --git a/src/main/java/hudson/scm/api/command/UnlockCommand.java b/src/main/java/hudson/scm/api/command/UnlockCommand.java new file mode 100644 index 0000000..5672e96 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/UnlockCommand.java @@ -0,0 +1,31 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class UnlockCommand extends BasicAPICommand +{ + public UnlockCommand() + { + cmd = new Command(Command.SI, UNLOCK_COMMAND); + + // Initialize defaults + cmd.addOption(new APIOption(IAPIOption.ACTION, IAPIOption.REMOVE)); + cmd.addOption(new APIOption(IAPIOption.RECURSE)); + cmd.addOption(new APIOption(IAPIOption.YES)); + } +} diff --git a/src/main/java/hudson/scm/api/command/ViewProjectCommand.java b/src/main/java/hudson/scm/api/command/ViewProjectCommand.java new file mode 100644 index 0000000..e6e7e49 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/ViewProjectCommand.java @@ -0,0 +1,23 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import com.mks.api.Command; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class ViewProjectCommand extends BasicAPICommand +{ + public ViewProjectCommand() + { + cmd = new Command(Command.SI, VIEW_PROJECT_COMMAND); + } +} diff --git a/src/main/java/hudson/scm/api/option/APIOption.java b/src/main/java/hudson/scm/api/option/APIOption.java new file mode 100644 index 0000000..6a0c89e --- /dev/null +++ b/src/main/java/hudson/scm/api/option/APIOption.java @@ -0,0 +1,36 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.option; + +import com.mks.api.MultiValue; +import com.mks.api.Option; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class APIOption extends Option implements IAPIOption +{ + + public APIOption(String name) + { + super(name); + } + + public APIOption(String param1, String param2) + { + super(param1, param2); + } + + public APIOption(String string, MultiValue mvFields) + { + super(string, mvFields); + } + +} diff --git a/src/main/java/hudson/scm/api/option/FileAPIOption.java b/src/main/java/hudson/scm/api/option/FileAPIOption.java new file mode 100644 index 0000000..ca1249b --- /dev/null +++ b/src/main/java/hudson/scm/api/option/FileAPIOption.java @@ -0,0 +1,27 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.option; + +import java.io.File; + +import com.mks.api.FileOption; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class FileAPIOption extends FileOption implements IAPIOption +{ + + public FileAPIOption(String name, File value) + { + super(name, value); + } + +} diff --git a/src/main/java/hudson/scm/api/option/IAPIOption.java b/src/main/java/hudson/scm/api/option/IAPIOption.java new file mode 100644 index 0000000..a4e5c5f --- /dev/null +++ b/src/main/java/hudson/scm/api/option/IAPIOption.java @@ -0,0 +1,56 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.option; + +/** + * Constants interface + * + * @author Author: asen + * @version $Revision: $ + */ +public interface IAPIOption +{ + public final String OVER_WRITE_EXISTING = "overwriteExisting"; + public final String NO_LOCK = "nolock"; + public final String PROJECT = "project"; + public final String TARGET_FILE = "targetFile"; + public final String LINE_TERMINATOR = "lineTerminator"; + public final String REVISION = "revision"; + public final String RESTORE_TIMESTAMP = "restoreTimestamp"; + public final String NORESTORE_TIMESTAMP = "norestoreTimestamp"; + public final String MEMBER_TIMESTAMP = "memberTimestamp"; + public final String RECURSE = "recurse"; + public final String FIELDS = "fields"; + public final String FILTER = "filter"; + public final String MEMBER_ID = "memberID"; + public final String AUTHOR = "author"; + public final String CP_ID = "cpid"; + public final String SOURCE_FILE = "sourceFile"; + public final String DESCRIPTION = "description"; + public final String SAVE_TIMESTAMP = "saveTimestamp"; + public final String NO_CLOSE_CP = "nocloseCP"; + public final String NO_DIFFERENT_NAMES = "nodifferentNames"; + public final String BRANCH_VARIANT = "branchVariant"; + public final String NO_CHECKIN_UNCHANGED = "nocheckinUnchanged"; + public final String ON_EXISTING_ARCHIVE = "onExistingArchive"; + public final String SHARE_ARCHIVE = "sharearchive"; + public final String YES = "yes"; + public final String ACTION = "action"; + public final String REMOVE = "remove"; + public final String SUMMARY = "summary"; + public final String ITEM_ID = "issueId"; + public final String RELEASE_LOCKS = "releaseLocks"; + public final String CLOSE_CP = "closeCP"; + public final String COMMIT = "commit"; + public final String CHECKPOINT_LABEL = "chkptLabel"; + public final String LABEL = "label"; + public final String PROJECT_REVISION = "projectRevision"; + public final String MOVE_LABEL = "moveLabel"; + public final String CHECKPOINT_DESCRIPTION = "checkpointDesc"; + +} diff --git a/src/test/java/hudson/scm/test/FakeAPISession.java b/src/test/java/hudson/scm/test/FakeAPISession.java index 7caa923..f7a8f92 100644 --- a/src/test/java/hudson/scm/test/FakeAPISession.java +++ b/src/test/java/hudson/scm/test/FakeAPISession.java @@ -11,25 +11,17 @@ package hudson.scm.test; -import hudson.scm.APISession; -import hudson.scm.ExceptionHandler; -import hudson.scm.IntegrityConfigurable; -import hudson.scm.ISession; - import java.io.IOException; -import java.util.LinkedHashMap; -import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; -import com.mks.api.CmdRunner; import com.mks.api.Command; -import com.mks.api.IntegrationPoint; -import com.mks.api.IntegrationPointFactory; -import com.mks.api.Session; import com.mks.api.response.APIException; import com.mks.api.response.Response; -import com.mks.api.util.APIVersion; + +import hudson.scm.IntegrityConfigurable; +import hudson.scm.api.ExceptionHandler; +import hudson.scm.api.ISession; /** * Allows for testing of an APISession From 2154d5291c119f85112edcc9b03be1a5ba127aef Mon Sep 17 00:00:00 2001 From: anuragsen Date: Wed, 11 Nov 2015 22:26:17 +0530 Subject: [PATCH 3/6] Compilation fix Change-Id: I3533518fac200eb4f3ed723c7f919db59d1d14fd --- .../java/hudson/scm/IntegrityCheckinTask.java | 19 ++++----- .../hudson/scm/IntegrityCheckpointAction.java | 39 ++++++++++--------- .../java/hudson/scm/IntegrityItemAction.java | 37 +++++++++--------- .../scm/IntegritySCMCheckinNotifierStep.java | 4 +- 4 files changed, 52 insertions(+), 47 deletions(-) diff --git a/src/main/java/hudson/scm/IntegrityCheckinTask.java b/src/main/java/hudson/scm/IntegrityCheckinTask.java index 74d0088..66a6719 100644 --- a/src/main/java/hudson/scm/IntegrityCheckinTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckinTask.java @@ -1,23 +1,24 @@ package hudson.scm; -import hudson.FilePath; -import hudson.FilePath.FileCallable; -import hudson.model.AbstractBuild; -import hudson.model.BuildListener; -import hudson.remoting.VirtualChannel; - import java.io.File; import java.io.IOException; -import java.util.logging.Logger; import java.util.logging.Level; - -import jenkins.security.Roles; +import java.util.logging.Logger; import org.jenkinsci.remoting.RoleChecker; import org.jenkinsci.remoting.RoleSensitive; import com.mks.api.response.APIException; +import hudson.FilePath; +import hudson.FilePath.FileCallable; +import hudson.model.AbstractBuild; +import hudson.model.BuildListener; +import hudson.remoting.VirtualChannel; +import hudson.scm.api.APISession; +import hudson.scm.api.ExceptionHandler; +import jenkins.security.Roles; + public class IntegrityCheckinTask implements FileCallable { private static final long serialVersionUID = 4165773747683187630L; diff --git a/src/main/java/hudson/scm/IntegrityCheckpointAction.java b/src/main/java/hudson/scm/IntegrityCheckpointAction.java index 580aaea..b12f9e9 100644 --- a/src/main/java/hudson/scm/IntegrityCheckpointAction.java +++ b/src/main/java/hudson/scm/IntegrityCheckpointAction.java @@ -1,22 +1,5 @@ package hudson.scm; -import groovy.lang.Binding; -import groovy.lang.GroovyShell; -import hudson.Extension; -import hudson.Launcher; -import hudson.model.BuildListener; -import hudson.model.Result; -import hudson.model.AbstractBuild; -import hudson.model.AbstractProject; -import hudson.scm.IntegritySCM.DescriptorImpl; -import hudson.tasks.BuildStepDescriptor; -import hudson.tasks.BuildStepMonitor; -import hudson.tasks.Notifier; -import hudson.tasks.Publisher; -import hudson.util.FormValidation; -import hudson.util.ListBoxModel; -import hudson.util.Secret; - import java.io.IOException; import java.io.Serializable; import java.sql.SQLException; @@ -28,8 +11,6 @@ import javax.servlet.ServletException; -import net.sf.json.JSONObject; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.codehaus.groovy.control.CompilationFailedException; @@ -42,6 +23,26 @@ import com.mks.api.response.Response; import com.mks.api.response.WorkItem; +import groovy.lang.Binding; +import groovy.lang.GroovyShell; +import hudson.Extension; +import hudson.Launcher; +import hudson.model.AbstractBuild; +import hudson.model.AbstractProject; +import hudson.model.BuildListener; +import hudson.model.Result; +import hudson.scm.IntegritySCM.DescriptorImpl; +import hudson.scm.api.APISession; +import hudson.scm.api.ExceptionHandler; +import hudson.tasks.BuildStepDescriptor; +import hudson.tasks.BuildStepMonitor; +import hudson.tasks.Notifier; +import hudson.tasks.Publisher; +import hudson.util.FormValidation; +import hudson.util.ListBoxModel; +import hudson.util.Secret; +import net.sf.json.JSONObject; + public class IntegrityCheckpointAction extends Notifier implements Serializable { diff --git a/src/main/java/hudson/scm/IntegrityItemAction.java b/src/main/java/hudson/scm/IntegrityItemAction.java index 79af272..9299d04 100644 --- a/src/main/java/hudson/scm/IntegrityItemAction.java +++ b/src/main/java/hudson/scm/IntegrityItemAction.java @@ -9,38 +9,39 @@ import java.util.logging.Level; import java.util.logging.Logger; -import hudson.scm.IntegritySCM.DescriptorImpl; -import hudson.tasks.Publisher; +import org.kohsuke.stapler.QueryParameter; +import org.kohsuke.stapler.StaplerRequest; + +import com.mks.api.Command; +import com.mks.api.MultiValue; +import com.mks.api.Option; +import com.mks.api.response.APIException; +import com.mks.api.response.Field; +import com.mks.api.response.Item; +import com.mks.api.response.Response; +import com.mks.api.response.WorkItemIterator; + +import hudson.Extension; +import hudson.Launcher; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.Result; -import hudson.Extension; -import hudson.Launcher; +import hudson.scm.IntegritySCM.DescriptorImpl; +import hudson.scm.api.APISession; +import hudson.scm.api.ExceptionHandler; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; -import hudson.tasks.test.TestResult; +import hudson.tasks.Publisher; import hudson.tasks.test.AbstractTestResultAction; import hudson.tasks.test.AggregatedTestResultAction; +import hudson.tasks.test.TestResult; import hudson.tasks.test.AggregatedTestResultAction.ChildReport; import hudson.util.ListBoxModel; import hudson.util.Secret; - -import org.kohsuke.stapler.QueryParameter; -import org.kohsuke.stapler.StaplerRequest; - import net.sf.json.JSONObject; -import com.mks.api.Command; -import com.mks.api.MultiValue; -import com.mks.api.Option; -import com.mks.api.response.APIException; -import com.mks.api.response.Field; -import com.mks.api.response.Item; -import com.mks.api.response.Response; -import com.mks.api.response.WorkItemIterator; - public class IntegrityItemAction extends Notifier implements Serializable { private static final long serialVersionUID = 7067049279037277420L; diff --git a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java index 78d1961..cae8240 100644 --- a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java @@ -8,8 +8,10 @@ import hudson.FilePath; import hudson.Launcher; -import hudson.model.TaskListener; import hudson.model.Run; +import hudson.model.TaskListener; +import hudson.scm.api.APISession; +import hudson.scm.api.ExceptionHandler; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; import jenkins.tasks.SimpleBuildStep; From 748e46da1977b7ededa642beea64af7eecc26b32 Mon Sep 17 00:00:00 2001 From: anuragsen Date: Fri, 13 Nov 2015 15:08:55 +0530 Subject: [PATCH 4/6] Removing APISession from API command calls Change-Id: Iae40bd2efcb8ab6d7e43f6899c9f37b7364f290f --- src/main/java/hudson/scm/DerbyUtils.java | 14 ++--- .../java/hudson/scm/IntegrityCMMember.java | 7 +-- .../java/hudson/scm/IntegrityCMProject.java | 27 +++++++++- .../hudson/scm/IntegrityChangeLogSet.java | 5 +- .../java/hudson/scm/IntegrityCheckinTask.java | 2 +- .../hudson/scm/IntegrityCheckoutTask.java | 2 +- .../hudson/scm/IntegrityCheckpointAction.java | 2 +- .../java/hudson/scm/IntegrityItemAction.java | 2 +- src/main/java/hudson/scm/IntegritySCM.java | 52 ++++++++----------- .../scm/IntegritySCMCheckinNotifierStep.java | 2 +- .../scm/IntegritySCMChkptNotifierStep.java | 2 +- .../scm/IntegritySCMLabelNotifierStep.java | 2 +- src/main/java/hudson/scm/api/APISession.java | 5 +- src/main/java/hudson/scm/api/ISession.java | 4 ++ .../scm/api/command/BasicAPICommand.java | 45 ++++++++++++---- .../hudson/scm/api/command/IAPICommand.java | 12 ++--- .../scm/api/command/ViewProjectCommand.java | 9 ++++ .../java/hudson/scm/test/FakeAPISession.java | 4 +- 18 files changed, 125 insertions(+), 73 deletions(-) diff --git a/src/main/java/hudson/scm/DerbyUtils.java b/src/main/java/hudson/scm/DerbyUtils.java index 8db0181..45e62ff 100644 --- a/src/main/java/hudson/scm/DerbyUtils.java +++ b/src/main/java/hudson/scm/DerbyUtils.java @@ -36,7 +36,6 @@ import com.mks.api.si.SIModelTypeName; import hudson.scm.IntegritySCM.DescriptorImpl; -import hudson.scm.api.APISession; /** * This class provides certain utility functions for working with the embedded derby database @@ -723,12 +722,11 @@ public static String fixDescription(String desc) /** * Compares this version of the project to a previous/new version to determine what are the updates and what was deleted * @param baselineProjectCache The previous baseline (build) for this Integrity CM Project - * @param api The current Integrity API Session to obtain the author information * @param return The total number of changes found in the comparison * @throws SQLException * @throws IOException */ - public static synchronized int compareBaseline(String baselineProjectCache, String projectCacheTable, boolean skipAuthorInfo, APISession api) throws SQLException, IOException + public static synchronized int compareBaseline(String baselineProjectCache, String projectCacheTable, boolean skipAuthorInfo) throws SQLException, IOException { // Re-initialize our return variable int changeCount = 0; @@ -794,7 +792,7 @@ public static synchronized int compareBaseline(String baselineProjectCache, Stri rs.updateString(CM_PROJECT.OLD_REVISION.toString(), oldRevision); // Initialize the author information as requested if( ! skipAuthorInfo ){ rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthorFromRevisionInfo(api, + IntegrityCMMember.getAuthorFromRevisionInfo( rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); } @@ -826,7 +824,7 @@ public static synchronized int compareBaseline(String baselineProjectCache, Stri { // Initialize the author information as requested if( ! skipAuthorInfo ){ rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthorFromRevisionInfo(api, + IntegrityCMMember.getAuthorFromRevisionInfo( rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); } @@ -1065,11 +1063,10 @@ else if( wi.getModelType().equals(SIModelTypeName.MEMBER) ) /** * Updates the author information for all the members in the project - * @param api * @throws SQLException * @throws IOException */ - public static synchronized void primeAuthorInformation(String projectCacheTable, APISession api) throws SQLException, IOException + public static synchronized void primeAuthorInformation(String projectCacheTable) throws SQLException, IOException { Connection db = null; Statement authSelect = null; @@ -1085,8 +1082,7 @@ public static synchronized void primeAuthorInformation(String projectCacheTable, { Hashtable rowHash = DerbyUtils.getRowData(rs); rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthorFromRevisionInfo(api, - rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), + IntegrityCMMember.getAuthorFromRevisionInfo(rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); rs.updateRow(); diff --git a/src/main/java/hudson/scm/IntegrityCMMember.java b/src/main/java/hudson/scm/IntegrityCMMember.java index 93a6d47..1920aa2 100644 --- a/src/main/java/hudson/scm/IntegrityCMMember.java +++ b/src/main/java/hudson/scm/IntegrityCMMember.java @@ -17,6 +17,7 @@ import com.mks.api.response.InterruptedException; import com.mks.api.response.Response; +import hudson.AbortException; import hudson.FilePath; import hudson.scm.api.APISession; import hudson.scm.api.APIUtils; @@ -150,14 +151,14 @@ public static final boolean checkout(APISession api, String configPath, String m /** * Performs a revision info on this Integrity Source File - * @param api Integrity API Session * @param configPath Full project configuration path * @param memberID Member ID for this file * @param memberRev Member Revision for this file * @return User responsible for making this change + * @throws AbortException * @throws APICommandException */ - public static String getAuthorFromRevisionInfo(APISession api, String configPath, String memberID, String memberRev) + public static String getAuthorFromRevisionInfo(String configPath, String memberID, String memberRev) throws AbortException { String author = "unknown"; @@ -169,7 +170,7 @@ public static String getAuthorFromRevisionInfo(APISession api, String configPath Response response; try { - response = command.execute(api); + response = command.execute(); author = APIUtils.getAuthorInfo(response,memberID); } catch (APICommandException aex) { diff --git a/src/main/java/hudson/scm/IntegrityCMProject.java b/src/main/java/hudson/scm/IntegrityCMProject.java index 9384528..564528b 100644 --- a/src/main/java/hudson/scm/IntegrityCMProject.java +++ b/src/main/java/hudson/scm/IntegrityCMProject.java @@ -32,6 +32,7 @@ import com.mks.api.response.Response; import com.mks.api.response.WorkItem; +import hudson.AbortException; import hudson.scm.api.APISession; import hudson.scm.api.command.APICommandException; import hudson.scm.api.command.AddProjectLabelCommand; @@ -324,7 +325,10 @@ private Element writeChangeLog(Element item, Hashtable membe item.appendChild(revision); // Create and append the element Element date = xmlDoc.createElement("date"); - date.appendChild(xmlDoc.createTextNode(IntegritySCM.SDF.format((Timestamp)memberInfo.get(CM_PROJECT.TIMESTAMP)))); + synchronized (IntegritySCM.SDF) + { + date.appendChild(xmlDoc.createTextNode(IntegritySCM.SDF.format((Timestamp)memberInfo.get(CM_PROJECT.TIMESTAMP)))); + } item.appendChild(date); // Create and append the annotation and differences links try @@ -363,6 +367,8 @@ private Element writeChangeLog(Element item, Hashtable membe } /** + * TODO deprecate this method in later iteration + * * Performs a checkpoint on this Integrity CM Project * @param api Authenticated Integrity API Session * @param chkptLabel Checkpoint label string @@ -380,6 +386,25 @@ public Response checkpoint(APISession api, String chkptLabel) throws APICommandE return command.execute(api); } + /** + * Performs a checkpoint on this Integrity CM Project + * @param api Authenticated Integrity API Session + * @param chkptLabel Checkpoint label string + * @return Integrity API Response object + * @throws APICommandException + * @throws AbortException + */ + public Response checkpoint(String chkptLabel) throws APICommandException, AbortException + { + // Construct the checkpoint command + IAPICommand command = new CheckPointCommand(); + command.addOption(new APIOption(IAPIOption.PROJECT, fullConfigSyntax)); + // Set the label and description if applicable + command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, chkptLabel); + + return command.execute(); + } + /** * Applies a Project Label on this Integrity CM Project * @param api Authenticated Integrity API Session diff --git a/src/main/java/hudson/scm/IntegrityChangeLogSet.java b/src/main/java/hudson/scm/IntegrityChangeLogSet.java index 23bafdb..bf8d28d 100644 --- a/src/main/java/hudson/scm/IntegrityChangeLogSet.java +++ b/src/main/java/hudson/scm/IntegrityChangeLogSet.java @@ -43,7 +43,10 @@ public IntegrityChangeLogSet(Run run, RepositoryBrowser browser, this.url = integrityURL; this.version = String.valueOf(run.getNumber()); this.author = "user"; - this.date = IntegritySCM.SDF.format(new Date()); + synchronized (IntegritySCM.SDF) + { + this.date = IntegritySCM.SDF.format(new Date()); + } this.msg = "Integrity Change Log"; for (IntegrityChangeLog log : logs) { diff --git a/src/main/java/hudson/scm/IntegrityCheckinTask.java b/src/main/java/hudson/scm/IntegrityCheckinTask.java index 66a6719..0ce92c1 100644 --- a/src/main/java/hudson/scm/IntegrityCheckinTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckinTask.java @@ -145,7 +145,7 @@ public Boolean invoke(File workspaceFile, VirtualChannel channel) throws IOExcep { if( null != api ) { - api.Terminate(); + api.terminate(); } } } diff --git a/src/main/java/hudson/scm/IntegrityCheckoutTask.java b/src/main/java/hudson/scm/IntegrityCheckoutTask.java index de810b8..cf5d2bb 100644 --- a/src/main/java/hudson/scm/IntegrityCheckoutTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckoutTask.java @@ -166,7 +166,7 @@ public void remove() try { LOGGER.fine("Terminating threaded API Sessions..."); - session.Terminate(); + session.terminate(); } catch(Exception ex) { diff --git a/src/main/java/hudson/scm/IntegrityCheckpointAction.java b/src/main/java/hudson/scm/IntegrityCheckpointAction.java index b12f9e9..b91e6a7 100644 --- a/src/main/java/hudson/scm/IntegrityCheckpointAction.java +++ b/src/main/java/hudson/scm/IntegrityCheckpointAction.java @@ -324,7 +324,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen } finally { - api.Terminate(); + api.terminate(); } } diff --git a/src/main/java/hudson/scm/IntegrityItemAction.java b/src/main/java/hudson/scm/IntegrityItemAction.java index 9299d04..c808eba 100644 --- a/src/main/java/hudson/scm/IntegrityItemAction.java +++ b/src/main/java/hudson/scm/IntegrityItemAction.java @@ -792,7 +792,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen } finally { - api.Terminate(); + api.terminate(); } } else diff --git a/src/main/java/hudson/scm/IntegritySCM.java b/src/main/java/hudson/scm/IntegritySCM.java index 7f54d61..a709c47 100644 --- a/src/main/java/hudson/scm/IntegritySCM.java +++ b/src/main/java/hudson/scm/IntegritySCM.java @@ -50,6 +50,7 @@ import hudson.scm.api.APIUtils; import hudson.scm.api.ExceptionHandler; import hudson.scm.api.command.APICommandException; +import hudson.scm.api.command.BasicAPICommand; import hudson.scm.api.command.IAPICommand; import hudson.scm.api.command.ProjectInfoCommand; import hudson.scm.api.command.ViewProjectCommand; @@ -646,18 +647,17 @@ public SCMRevisionState calcRevisionsFromBuild(Run run, FilePath workspace /** * Primes the Integrity Project metadata information - * @param api Integrity API Session * @return response Integrity API Response + * @throws AbortException * @throws APIException */ - private Response initializeCMProject(APISession api, String projectCacheTable, String resolvedConfigPath) throws APICommandException + private Response initializeCMProject(String projectCacheTable, String resolvedConfigPath) throws APICommandException, AbortException { // Get the project information for this project - IAPICommand command = new ProjectInfoCommand(); command.addOption(new APIOption(IAPIOption.PROJECT, resolvedConfigPath)); - Response infoRes = command.execute(api); + Response infoRes = command.execute(); LOGGER.fine(infoRes.getCommandString() + " returned " + APIUtils.getResponseExitCode(infoRes)); // Initialize our siProject class variable @@ -710,19 +710,18 @@ private void applyMemberFilters(IAPICommand command) /** * Primes the Integrity Project Member metadata information - * @param api Integrity API Session * @return response Integrity API Response * @throws APIException * @throws SQLException + * @throws AbortException */ - private Response initializeCMProjectMembers(APISession api) throws APIException, SQLException + private Response initializeCMProjectMembers() throws APIException, SQLException, AbortException { IntegrityCMProject siProject = getIntegrityProject(); // Lets parse this project IAPICommand command = new ViewProjectCommand(); - command.addOption(new APIOption(IAPIOption.RECURSE)); command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath())); APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"); command.addOption(new APIOption(IAPIOption.FIELDS, APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"))); @@ -731,7 +730,7 @@ private Response initializeCMProjectMembers(APISession api) throws APIException, applyMemberFilters(command); LOGGER.fine("Preparing to execute si viewproject for " + siProject.getConfigurationPath()); - Response viewRes = command.execute(api); + Response viewRes = command.execute(); DerbyUtils.parseProject(siProject, viewRes.getWorkItems()); return viewRes; @@ -784,14 +783,10 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, IntegrityConfigurable desSettings = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig); IntegrityConfigurable coSettings = new IntegrityConfigurable("TEMP_ID", desSettings.getIpHostName(), desSettings.getIpPort(), desSettings.getHostName(), desSettings.getPort(), desSettings.getSecure(), userName, password.getPlainText()); - APISession api = APISession.create(coSettings); - // Ensure we've successfully created an API Session - if( null == api ) - { - listener.getLogger().println("Failed to establish an API connection to the Integrity Server!"); - throw new AbortException("Connection Failed!"); - } + // Initialize the API command framework + BasicAPICommand.setIntegritySettings(desSettings); + // Lets also open the change log file for writing... // Override file.encoding property so that we write as UTF-8 and do not have problems with special characters PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(changeLogFile),"UTF-8")); @@ -799,12 +794,12 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, { // Register the project cache for this build Job job = run.getParent(); - String projectCacheTable = DerbyUtils.registerProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), - job.getName(), configurationName, run.getNumber()); + String projectCacheTable = DerbyUtils.registerProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), + job.getName(), configurationName, run.getNumber()); // Next, load up the information for this Integrity Project's configuration listener.getLogger().println("Preparing to execute si projectinfo for " + resolvedConfigPath); - initializeCMProject(api, projectCacheTable, resolvedConfigPath); + initializeCMProject(projectCacheTable, resolvedConfigPath); IntegrityCMProject siProject = getIntegrityProject(); // Check to see we need to checkpoint before the build if( checkpointBeforeBuild ) @@ -814,7 +809,7 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, { // Execute a pre-build checkpoint... listener.getLogger().println("Preparing to execute pre-build si checkpoint for " + siProject.getConfigurationPath()); - Response res = siProject.checkpoint(api, IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), checkpointLabel)); + Response res = siProject.checkpoint(IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), checkpointLabel)); LOGGER.fine(res.getCommandString() + " returned " + res.getExitCode()); WorkItem wi = res.getWorkItem(siProject.getConfigurationPath()); String chkpt = wi.getResult().getField("resultant").getItem().getId(); @@ -824,7 +819,7 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, IAPICommand command = new ProjectInfoCommand(); command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath() + "#forceJump=#b=" + chkpt)); - Response infoRes = command.execute(api); + Response infoRes = command.execute(); siProject.initializeProject(infoRes.getWorkItems().next()); } else @@ -833,7 +828,7 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, } } listener.getLogger().println("Preparing to execute si viewproject for " + siProject.getConfigurationPath()); - initializeCMProjectMembers(api); + initializeCMProjectMembers(); // Now, we need to find the project state from the previous build. String prevProjectCache = null; @@ -846,7 +841,7 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, { // Compare the current project with the old revision state LOGGER.fine("Found previous project state " + prevProjectCache); - DerbyUtils.compareBaseline(prevProjectCache, projectCacheTable, skipAuthorInfo, api); + DerbyUtils.compareBaseline(prevProjectCache, projectCacheTable, skipAuthorInfo); } } else @@ -854,7 +849,7 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, // We don't have the previous Integrity Revision State! LOGGER.fine("Cannot construct previous Integrity Revision State!"); // Prime the author information for the current build as this could be the first build - if( ! skipAuthorInfo ){ DerbyUtils.primeAuthorInformation(projectCacheTable, api); } + if( ! skipAuthorInfo ){ DerbyUtils.primeAuthorInformation(projectCacheTable); } } // After all that insane interrogation, we have the current Project state that is @@ -926,7 +921,6 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, { writer.close(); } - api.Terminate(); } // Log the completion... @@ -972,12 +966,12 @@ public PollingResult compareRemoteRevisionWith(Job job, Launcher launcher, // Re-evaluate the config path to resolve any groovy expressions... String resolvedConfigPath = IntegrityCheckpointAction.evalGroovyExpression(job.getCharacteristicEnvVars(), configPath); listener.getLogger().println("Preparing to execute si projectinfo for " + resolvedConfigPath); - initializeCMProject(api, projectCacheTable, resolvedConfigPath); + initializeCMProject(projectCacheTable, resolvedConfigPath); listener.getLogger().println("Preparing to execute si viewproject for " + resolvedConfigPath); - initializeCMProjectMembers(api); + initializeCMProjectMembers(); // Compare this project with the old project - int changeCount = DerbyUtils.compareBaseline(prevProjectCache, projectCacheTable, skipAuthorInfo, api); + int changeCount = DerbyUtils.compareBaseline(prevProjectCache, projectCacheTable, skipAuthorInfo); // Finally decide whether or not we need to build again if( changeCount > 0 ) { @@ -1012,7 +1006,7 @@ public PollingResult compareRemoteRevisionWith(Job job, Launcher launcher, } finally { - api.Terminate(); + api.terminate(); } } else @@ -1269,7 +1263,7 @@ public FormValidation doTestConnection(@QueryParameter("serverConfig.hostName") APISession api = APISession.create(ic); if( null != api ) { - api.Terminate(); + api.terminate(); return FormValidation.ok("Connection successful!"); } else diff --git a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java index cae8240..618087f 100644 --- a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java @@ -108,7 +108,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi { if( null != api ) { - api.Terminate(); + api.terminate(); } } } diff --git a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java index 8b93f6d..3e0a70a 100644 --- a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java @@ -68,7 +68,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi } finally { - api.Terminate(); + api.terminate(); } } else diff --git a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java index e9e2fb3..7209dcc 100644 --- a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java @@ -65,7 +65,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi } finally { - api.Terminate(); + api.terminate(); } } else diff --git a/src/main/java/hudson/scm/api/APISession.java b/src/main/java/hudson/scm/api/APISession.java index 6145244..f48fb19 100644 --- a/src/main/java/hudson/scm/api/APISession.java +++ b/src/main/java/hudson/scm/api/APISession.java @@ -195,14 +195,15 @@ public Response runCommandAs(Command cmd, String impersonateUser) throws APIExce public void refreshAPISession() throws APIException { - Terminate(); + terminate(); initAPI(); } /** * Terminate the API Session and Integration Point */ - public void Terminate() + @Override + public void terminate() { boolean cmdRunnerKilled = false; boolean sessionKilled = false; diff --git a/src/main/java/hudson/scm/api/ISession.java b/src/main/java/hudson/scm/api/ISession.java index d97dc05..8d55e0a 100644 --- a/src/main/java/hudson/scm/api/ISession.java +++ b/src/main/java/hudson/scm/api/ISession.java @@ -7,5 +7,9 @@ public interface ISession { public Response runCommand(Command cmd) throws APIException; + + public Response runCommandWithInterim(Command cmd) throws APIException; + + public void terminate(); } diff --git a/src/main/java/hudson/scm/api/command/BasicAPICommand.java b/src/main/java/hudson/scm/api/command/BasicAPICommand.java index 771fc32..c69b026 100644 --- a/src/main/java/hudson/scm/api/command/BasicAPICommand.java +++ b/src/main/java/hudson/scm/api/command/BasicAPICommand.java @@ -14,8 +14,12 @@ import com.mks.api.response.APIException; import com.mks.api.response.Response; +import hudson.AbortException; +import hudson.scm.IntegrityConfigurable; +import hudson.scm.api.APISession; import hudson.scm.api.ISession; import hudson.scm.api.option.IAPIOption; +import hudson.util.StreamTaskListener; /** * All Jenkins Integrity API Commands have to extend this class in order to execute Integrity API calls using the default method @@ -29,6 +33,8 @@ public abstract class BasicAPICommand implements IAPICommand protected Map commandHelperObjects; protected Response res; + protected boolean runCommandWithInterim = false; + private static IntegrityConfigurable icSettings; /* (non-Javadoc) @@ -44,7 +50,11 @@ public Response execute(ISession api) throws APICommandException doPreAction(); - res = api.runCommand(getMKSAPICommand()); + if(runCommandWithInterim) + res = api.runCommandWithInterim(cmd); + else + res = api.runCommand(cmd); + if(null != res){ int resCode = res.getExitCode(); @@ -56,25 +66,33 @@ public Response execute(ISession api) throws APICommandException } catch (APIException e) { throw new APICommandException(e); + } finally { + api.terminate(); } return res; } - @Override - public boolean execute() throws APICommandException - { - //TODO Initialize API session here using an "IntegrityConfigurable.java" object - return false; - } - /* (non-Javadoc) - * @see hudson.scm.api.command.APICommand#getMKSAPICommand() + * @see hudson.scm.api.command.IAPICommand#execute() */ @Override - public Command getMKSAPICommand() + public Response execute() throws APICommandException, AbortException { - return cmd; + IntegrityConfigurable coSettings = new IntegrityConfigurable("TEMP_ID", icSettings.getIpHostName(), icSettings.getIpPort(), icSettings.getHostName(), + icSettings.getPort(), icSettings.getSecure(), icSettings.getUserName(), icSettings.getPasswordInPlainText()); + + ISession api = APISession.create(coSettings); + + // Ensure we've successfully created an API Session + if( null == api ) + { + StreamTaskListener task = StreamTaskListener.fromStdout(); + task.getLogger().println("Failed to establish an API connection to the Integrity Server!"); + throw new AbortException("Connection Failed!"); + } + + return execute(api); } @Override @@ -115,5 +133,10 @@ public void addAdditionalParameters(String paramName, Object param) { commandHelperObjects.put(paramName, param); } + + public static void setIntegritySettings(IntegrityConfigurable desSettings) + { + icSettings = desSettings; + } } diff --git a/src/main/java/hudson/scm/api/command/IAPICommand.java b/src/main/java/hudson/scm/api/command/IAPICommand.java index 322c5cb..bdcb510 100644 --- a/src/main/java/hudson/scm/api/command/IAPICommand.java +++ b/src/main/java/hudson/scm/api/command/IAPICommand.java @@ -1,8 +1,8 @@ package hudson.scm.api.command; -import com.mks.api.Command; import com.mks.api.response.Response; +import hudson.AbortException; import hudson.scm.api.ISession; import hudson.scm.api.option.IAPIOption; @@ -18,7 +18,7 @@ public interface IAPICommand { - + // List of commonly used plugin API commands static String PROJECT_CHECKOUT_COMMAND = "projectco"; static String PROJECT_CHECKIN_COMMAND = "projectci"; static String PROJECT_INFO_COMMAND = "projectinfo"; @@ -43,13 +43,9 @@ public interface IAPICommand * Execute the command using an auto-generated Integrity Session API * @return * @throws APICommandException + * @throws AbortException */ - public boolean execute() throws APICommandException; - - /** - * @return - */ - public Command getMKSAPICommand(); + public Response execute() throws APICommandException, AbortException; /** * Do actions post the Integrity API call specifically for Jenkins functionality diff --git a/src/main/java/hudson/scm/api/command/ViewProjectCommand.java b/src/main/java/hudson/scm/api/command/ViewProjectCommand.java index e6e7e49..12b6861 100644 --- a/src/main/java/hudson/scm/api/command/ViewProjectCommand.java +++ b/src/main/java/hudson/scm/api/command/ViewProjectCommand.java @@ -9,6 +9,9 @@ import com.mks.api.Command; +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; + /** * * @author Author: asen @@ -19,5 +22,11 @@ public class ViewProjectCommand extends BasicAPICommand public ViewProjectCommand() { cmd = new Command(Command.SI, VIEW_PROJECT_COMMAND); + + // TODO: this is a bug. This command should be run with interim = true as per original code, but this fails somehow + //runCommandWithInterim = true; + + // Initialize defaults + cmd.addOption(new APIOption(IAPIOption.RECURSE)); } } diff --git a/src/test/java/hudson/scm/test/FakeAPISession.java b/src/test/java/hudson/scm/test/FakeAPISession.java index f7a8f92..f563b0d 100644 --- a/src/test/java/hudson/scm/test/FakeAPISession.java +++ b/src/test/java/hudson/scm/test/FakeAPISession.java @@ -202,14 +202,14 @@ public Response runCommandAs(Command cmd, String impersonateUser) throws APIExce public void refreshAPISession() throws APIException { - Terminate(); + terminate(); initAPI(); } /** * Terminate the API Session and Integration Point */ - public void Terminate() + public void terminate() { boolean cmdRunnerKilled = false; boolean sessionKilled = false; From 9c2440979697a36d59aca4ffeb46bebfad5dd4db Mon Sep 17 00:00:00 2001 From: anuragsen Date: Fri, 13 Nov 2015 22:16:38 +0530 Subject: [PATCH 5/6] Binding API inside command hierarchy + IntegritySCM class refactoring Change-Id: I7b4fbd53df0b958a82f1f482f2d7711ea0985dc5 --- .../java/hudson/scm/AbstractIntegritySCM.java | 548 ++++++ src/main/java/hudson/scm/DerbyUtils.java | 10 +- .../java/hudson/scm/IntegrityCMMember.java | 85 +- .../java/hudson/scm/IntegrityCMProject.java | 37 +- .../java/hudson/scm/IntegrityCheckinTask.java | 33 +- .../hudson/scm/IntegrityCheckoutTask.java | 5 +- .../hudson/scm/IntegrityCheckpointAction.java | 65 +- src/main/java/hudson/scm/IntegritySCM.java | 1687 ++++++----------- .../scm/IntegritySCMCheckinNotifierStep.java | 26 +- .../scm/IntegritySCMChkptNotifierStep.java | 19 +- .../scm/IntegritySCMLabelNotifierStep.java | 59 +- src/main/java/hudson/scm/api/APIUtils.java | 25 +- .../scm/api/command/APICommandException.java | 31 - .../api/command/AddProjectLabelCommand.java | 4 +- .../scm/api/command/BasicAPICommand.java | 56 +- .../scm/api/command/CheckPointCommand.java | 4 +- .../scm/api/command/CloseCPCommand.java | 4 +- .../scm/api/command/CreateCPCommand.java | 5 +- .../hudson/scm/api/command/IAPICommand.java | 5 +- .../hudson/scm/api/command/LockCommand.java | 5 +- .../scm/api/command/ProjectAddCommand.java | 4 +- .../api/command/ProjectCheckinCommand.java | 4 +- .../api/command/ProjectCheckoutCommand.java | 1 + .../scm/api/command/ProjectInfoCommand.java | 5 +- .../scm/api/command/RevisionInfoCommand.java | 5 +- .../scm/api/command/SubmitCPCommand.java | 4 +- .../hudson/scm/api/command/UnlockCommand.java | 4 +- .../scm/api/command/ViewProjectCommand.java | 4 +- .../scm/test/AbstractIntegrityTestCase.java | 2 +- 29 files changed, 1361 insertions(+), 1385 deletions(-) create mode 100644 src/main/java/hudson/scm/AbstractIntegritySCM.java delete mode 100644 src/main/java/hudson/scm/api/command/APICommandException.java diff --git a/src/main/java/hudson/scm/AbstractIntegritySCM.java b/src/main/java/hudson/scm/AbstractIntegritySCM.java new file mode 100644 index 0000000..9a8651f --- /dev/null +++ b/src/main/java/hudson/scm/AbstractIntegritySCM.java @@ -0,0 +1,548 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. +package hudson.scm; + +import java.io.Serializable; +import java.text.SimpleDateFormat; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.logging.Logger; + +import org.kohsuke.stapler.DataBoundSetter; +import org.kohsuke.stapler.export.Exported; + +import hudson.scm.IntegrityCheckpointAction.IntegrityCheckpointDescriptorImpl; +import hudson.scm.IntegritySCM.DescriptorImpl; +import hudson.scm.browsers.IntegrityWebUI; +import hudson.util.Secret; +import jenkins.model.Jenkins; + +/** + * @author Author: asen + * @version $Revision: $ + */ +public abstract class AbstractIntegritySCM extends SCM implements Serializable +{ + private static final long serialVersionUID = 7559894846609712683L; + + protected static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); + protected static final Map projects = new ConcurrentHashMap(); + public static final String NL = System.getProperty("line.separator"); + public static final String FS = System.getProperty("file.separator"); + public static final int MIN_PORT_VALUE = 1; + public static final int MAX_PORT_VALUE = 65535; + public static final int DEFAULT_THREAD_POOL_SIZE = 5; + public static final SimpleDateFormat SDF = new SimpleDateFormat( + "MMM dd, yyyy h:mm:ss a"); + protected final String ciServerURL = (null == Jenkins.getInstance() + .getRootUrl() ? "" : Jenkins.getInstance().getRootUrl()); + protected String integrityURL; + protected IntegrityRepositoryBrowser browser; + protected String serverConfig; + protected String userName; + protected Secret password; + protected String configPath; + protected String includeList; + protected String excludeList; + protected String checkpointLabel; + protected String configurationName; + protected boolean cleanCopy; + protected boolean skipAuthorInfo = true; + protected String lineTerminator = "native"; + protected boolean restoreTimestamp = true; + protected boolean checkpointBeforeBuild = false; + protected String alternateWorkspace; + protected boolean fetchChangedWorkspaceFiles = false; + protected boolean deleteNonMembers = false; + protected int checkoutThreadPoolSize = DEFAULT_THREAD_POOL_SIZE; + + public AbstractIntegritySCM() + { + super(); + } + + @Override + @Exported + public IntegrityRepositoryBrowser getBrowser() + { + return browser == null ? new IntegrityWebUI(null) : browser; + } + + /** + * Returns the simple server configuration name + * + * @return + */ + public String getServerConfig() + { + return serverConfig; + } + + /** + * Returns the project specific User connecting to the Integrity Server + * + * @return + */ + public String getUserName() + { + return this.userName; + } + + /** + * Returns the project specific encrypted password of the user connecting to + * the Integrity Server + * + * @return + */ + public String getPassword() + { + return this.password.getEncryptedValue(); + } + + /** + * Returns the project specific Secret password of the user connecting to + * the Integrity Server + * + * @return + */ + public Secret getSecretPassword() + { + return this.password; + } + + /** + * Returns the Project or Configuration Path for a Integrity Source Project + * + * @return + */ + public String getConfigPath() + { + return configPath; + } + + /** + * Returns the files that will be excluded + * + * @return + */ + public String getIncludeList() + { + return includeList; + } + + /** + * Returns the files that will be included + * + * @return + */ + public String getExcludeList() + { + return excludeList; + } + + /** + * Returns true/false depending on whether or not the workspace is required + * to be cleaned + * + * @return + */ + public boolean getCleanCopy() + { + return cleanCopy; + } + + /** + * Returns the line terminator to apply when obtaining files from the + * Integrity Server + * + * @return + */ + public String getLineTerminator() + { + return lineTerminator; + } + + /** + * Returns true/false depending on whether or not the restore timestamp + * option is in effect + * + * @return + */ + public boolean getRestoreTimestamp() + { + return restoreTimestamp; + } + + /** + * Returns true/false depending on whether or not to use 'si revisioninfo' + * to determine author information + * + * @return + */ + public boolean getSkipAuthorInfo() + { + return skipAuthorInfo; + } + + /** + * Returns true/false depending on whether or not perform a checkpoint + * before the build + * + * @return + */ + public boolean getCheckpointBeforeBuild() + { + return checkpointBeforeBuild; + } + + /** + * Returns the label string for the checkpoint performed before the build + * + * @return + */ + public String getCheckpointLabel() + { + if (checkpointLabel == null || checkpointLabel.length() == 0) { + return IntegrityCheckpointDescriptorImpl.defaultCheckpointLabel; + } + return checkpointLabel; + } + + /** + * Returns the alternate workspace directory + * + * @return + */ + public String getAlternateWorkspace() + { + return alternateWorkspace; + } + + /** + * Returns the true/false depending on whether or not to synchronize changed + * workspace files + * + * @return + */ + public boolean getFetchChangedWorkspaceFiles() + { + return fetchChangedWorkspaceFiles; + } + + /** + * Returns the true/false depending on whether non members should be deleted + * before the build + * + * @return + */ + public boolean getDeleteNonMembers() + { + return deleteNonMembers; + } + + /** + * Returns the size of the thread pool for parallel checkouts + * + * @return + */ + public int getCheckoutThreadPoolSize() + { + return checkoutThreadPoolSize; + } + + /** + * Returns the configuration name for this project Required when working + * with Multiple SCMs plug-in + */ + public String getConfigurationName() + { + return configurationName; + } + + /** + * Sets the Integrity SCM web browser + * + * @param browser + */ + @DataBoundSetter + public final void setBrowser(IntegrityRepositoryBrowser browser) + { + this.browser = browser; + } + + /** + * Sets the server configuration name for this project + * + * @param serverConfig + */ + public void setServerConfig(String serverConfig) + { + this.serverConfig = serverConfig; + IntegrityConfigurable ic = ((DescriptorImpl) this.getDescriptor()) + .getConfiguration(serverConfig); + integrityURL = (ic.getSecure() ? "https://" : "http://") + + ic.getHostName() + ":" + String.valueOf(ic.getPort()); + + } + + /** + * Sets the project specific User connecting to the Integrity Server + * + * @return + */ + @DataBoundSetter + public final void setUserName(String userName) + { + if (null != userName && userName.length() > 0) { + this.userName = userName; + } + } + + /** + * Sets the project specific encrypted Password of the user connecting to + * the Integrity Server + * + * @param password - The clear password + */ + @DataBoundSetter + public final void setPassword(String password) + { + if (null != password && password.length() > 0) { + this.password = Secret.fromString(password); + } + } + + /** + * Sets the Project or Configuration Path for an Integrity Source Project + * + * @return + */ + public void setConfigPath(String configPath) + { + this.configPath = configPath; + } + + /** + * Sets the files that will be not be included + * + * @return + */ + @DataBoundSetter + public final void setIncludeList(String includeList) + { + this.includeList = includeList; + } + + /** + * Sets the files that will be not be included + * + * @return + */ + @DataBoundSetter + public final void setExcludeList(String excludeList) + { + this.excludeList = excludeList; + } + + /** + * Toggles whether or not the workspace is required to be cleaned + * + * @return + */ + @DataBoundSetter + public final void setCleanCopy(boolean cleanCopy) + { + this.cleanCopy = cleanCopy; + } + + /** + * Sets the line terminator to apply when obtaining files from the Integrity + * Server + * + * @return + */ + @DataBoundSetter + public final void setLineTerminator(String lineTerminator) + { + this.lineTerminator = lineTerminator; + } + + /** + * Toggles whether or not to restore the timestamp for individual files + * + * @return + */ + @DataBoundSetter + public final void setRestoreTimestamp(boolean restoreTimestamp) + { + this.restoreTimestamp = restoreTimestamp; + } + + /** + * Toggles whether or not to use 'si revisioninfo' to determine author + * information + * + * @return + */ + @DataBoundSetter + public final void setSkipAuthorInfo(boolean skipAuthorInfo) + { + this.skipAuthorInfo = skipAuthorInfo; + } + + /** + * Toggles whether or not a checkpoint should be performed before the build + * + * @param checkpointBeforeBuild + */ + @DataBoundSetter + public final void setCheckpointBeforeBuild(boolean checkpointBeforeBuild) + { + this.checkpointBeforeBuild = checkpointBeforeBuild; + } + + /** + * Sets the label string for the checkpoint performed before the build + * + * @param checkpointLabel + */ + @DataBoundSetter + public final void setCheckpointLabel(String checkpointLabel) + { + this.checkpointLabel = checkpointLabel; + } + + /** + * Sets an alternate workspace for the checkout directory + * + * @param alternateWorkspace + */ + @DataBoundSetter + public final void setAlternateWorkspace(String alternateWorkspace) + { + this.alternateWorkspace = alternateWorkspace; + } + + /** + * Toggles whether or not changed workspace files should be synchronized + * + * @param fetchChangedWorkspaceFiles + */ + @DataBoundSetter + public final void setFetchChangedWorkspaceFiles( + boolean fetchChangedWorkspaceFiles) + { + this.fetchChangedWorkspaceFiles = fetchChangedWorkspaceFiles; + } + + /** + * Toggles whether or not non members should be deleted + * + * @param deleteNonMembers + */ + @DataBoundSetter + public final void setDeleteNonMembers(boolean deleteNonMembers) + { + this.deleteNonMembers = deleteNonMembers; + } + + /** + * Sets the thread pool size of parallel checkout threads + * + * @param checkoutThreadPoolSize + */ + @DataBoundSetter + public final void setCheckoutThreadPoolSize(int checkoutThreadPoolSize) + { + this.checkoutThreadPoolSize = checkoutThreadPoolSize; + } + + /** + * Sets the configuration name for this project + * + * @param configurationName Name for this project configuration + */ + public void setConfigurationName(String configurationName) + { + this.configurationName = configurationName; + } + + /** + * Toggles whether or not the Integrity SCM plugin can be used for polling + */ + @Override + public boolean supportsPolling() + { + return true; + } + + /** + * Toggles whether or not a workspace is required for polling Since, we're + * using a Server Integration Point in the Integrity API, we do not require + * a workspace. + */ + @Override + public boolean requiresWorkspaceForPolling() + { + return false; + } + + /** + * Overridden createChangeLogParser function Creates a custom Integrity + * Change Log Parser, which compares two view project outputs + * + * @see hudson.scm.SCM#createChangeLogParser() + */ + @Override + public ChangeLogParser createChangeLogParser() + { + // Log the call + LOGGER.fine("createChangeLogParser() invoked...!"); + return new IntegrityChangeLogParser(integrityURL); + } + + /** + * Returns the Integrity Configuration Management Project + * + * @return + */ + public IntegrityCMProject getIntegrityProject() + { + return findProject(configurationName); + } + + /** + * @param configurationName + * @return + */ + public static IntegrityCMProject findProject(String configurationName) + { + return hasProject(configurationName) + ? projects.get(configurationName) + : null; + } + + /** + * @param configurationName + * @return + */ + public static boolean hasProject(String configurationName) + { + return projects.containsKey(configurationName); + } + + /** + * Returns the SCMDescriptor for the SCM object. The SCMDescriptor is + * used to create new instances of the SCM. + */ + @Override + public DescriptorImpl getDescriptor() + { + return DescriptorImpl.INTEGRITY_DESCRIPTOR; + } + +} diff --git a/src/main/java/hudson/scm/DerbyUtils.java b/src/main/java/hudson/scm/DerbyUtils.java index 45e62ff..7a87b5f 100644 --- a/src/main/java/hudson/scm/DerbyUtils.java +++ b/src/main/java/hudson/scm/DerbyUtils.java @@ -726,7 +726,7 @@ public static String fixDescription(String desc) * @throws SQLException * @throws IOException */ - public static synchronized int compareBaseline(String baselineProjectCache, String projectCacheTable, boolean skipAuthorInfo) throws SQLException, IOException + public static synchronized int compareBaseline(String serverConfigId, String baselineProjectCache, String projectCacheTable, boolean skipAuthorInfo) throws SQLException, IOException { // Re-initialize our return variable int changeCount = 0; @@ -792,7 +792,7 @@ public static synchronized int compareBaseline(String baselineProjectCache, Stri rs.updateString(CM_PROJECT.OLD_REVISION.toString(), oldRevision); // Initialize the author information as requested if( ! skipAuthorInfo ){ rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthorFromRevisionInfo( + IntegrityCMMember.getAuthorFromRevisionInfo(serverConfigId, rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); } @@ -824,7 +824,7 @@ public static synchronized int compareBaseline(String baselineProjectCache, Stri { // Initialize the author information as requested if( ! skipAuthorInfo ){ rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthorFromRevisionInfo( + IntegrityCMMember.getAuthorFromRevisionInfo(serverConfigId, rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); } @@ -1066,7 +1066,7 @@ else if( wi.getModelType().equals(SIModelTypeName.MEMBER) ) * @throws SQLException * @throws IOException */ - public static synchronized void primeAuthorInformation(String projectCacheTable) throws SQLException, IOException + public static synchronized void primeAuthorInformation(String serverConfigId, String projectCacheTable) throws SQLException, IOException { Connection db = null; Statement authSelect = null; @@ -1082,7 +1082,7 @@ public static synchronized void primeAuthorInformation(String projectCacheTable) { Hashtable rowHash = DerbyUtils.getRowData(rs); rs.updateString(CM_PROJECT.AUTHOR.toString(), - IntegrityCMMember.getAuthorFromRevisionInfo(rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), + IntegrityCMMember.getAuthorFromRevisionInfo(serverConfigId, rowHash.get(CM_PROJECT.CONFIG_PATH).toString(), rowHash.get(CM_PROJECT.MEMBER_ID).toString(), rowHash.get(CM_PROJECT.REVISION).toString())); rs.updateRow(); diff --git a/src/main/java/hudson/scm/IntegrityCMMember.java b/src/main/java/hudson/scm/IntegrityCMMember.java index 1920aa2..71076cf 100644 --- a/src/main/java/hudson/scm/IntegrityCMMember.java +++ b/src/main/java/hudson/scm/IntegrityCMMember.java @@ -19,11 +19,10 @@ import hudson.AbortException; import hudson.FilePath; +import hudson.scm.IntegritySCM.DescriptorImpl; import hudson.scm.api.APISession; import hudson.scm.api.APIUtils; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.ISession; -import hudson.scm.api.command.APICommandException; import hudson.scm.api.command.CloseCPCommand; import hudson.scm.api.command.CreateCPCommand; import hudson.scm.api.command.IAPICommand; @@ -128,7 +127,7 @@ public static final String getDifferencesLink(String configPath, String memberID * @throws APIException */ public static final boolean checkout(APISession api, String configPath, String memberID, String memberRev, Timestamp memberTimestamp, - File targetFile, boolean restoreTimestamp, String lineTerminator) throws APICommandException + File targetFile, boolean restoreTimestamp, String lineTerminator) throws APIException { IAPICommand command = new ProjectCheckoutCommand(); @@ -145,8 +144,7 @@ public static final boolean checkout(APISession api, String configPath, String m command.addAdditionalParameters(IAPIOption.TARGET_FILE,targetFile); Response response = command.execute(api); - int resCode = APIUtils.getResponseExitCode(response); - return BooleanUtils.toBoolean(resCode, 0, 1); + return BooleanUtils.toBoolean(response.getExitCode(), 0, 1); } /** @@ -158,12 +156,12 @@ public static final boolean checkout(APISession api, String configPath, String m * @throws AbortException * @throws APICommandException */ - public static String getAuthorFromRevisionInfo(String configPath, String memberID, String memberRev) throws AbortException + public static String getAuthorFromRevisionInfo(String serverConfigId, String configPath, String memberID, String memberRev) throws AbortException { String author = "unknown"; // Construct the revision-info command - IAPICommand command = new RevisionInfoCommand(); + IAPICommand command = new RevisionInfoCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfigId)); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addOption(new APIOption(IAPIOption.REVISION, memberRev)); command.addSelection(memberID); @@ -173,7 +171,7 @@ public static String getAuthorFromRevisionInfo(String configPath, String memberI response = command.execute(); author = APIUtils.getAuthorInfo(response,memberID); - } catch (APICommandException aex) { + } catch (APIException aex) { ExceptionHandler eh = new ExceptionHandler(aex); LOGGER.severe("API Exception caught..."); LOGGER.severe(eh.getMessage()); @@ -213,18 +211,19 @@ public static final String getMD5Checksum(File targetFile) throws IOException /** * Performs a lock and subsequent project checkin for the specified member - * @param api Integrity API Session + * @param ciSettings Integrity API Session * @param configPath Full project configuration path * @param member Member name for this file * @param relativePath Workspace relative file path * @param cpid Change Package ID * @param desc Checkin description + * @throws AbortException * @throws APIException */ - public static final void updateMember(APISession api, String configPath, FilePath member, String relativePath, String cpid, String desc) throws APIException + public static final void updateMember(IntegrityConfigurable ciSettings, String configPath, FilePath member, String relativePath, String cpid, String desc) throws AbortException, APIException { // Construct the lock command - IAPICommand command = new LockCommand(); + IAPICommand command = new LockCommand(ciSettings); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addOption(new APIOption(IAPIOption.CP_ID, cpid)); command.addSelection(relativePath); @@ -232,11 +231,11 @@ public static final void updateMember(APISession api, String configPath, FilePat try { // Execute the lock command - command.execute(api); + command.execute(); // If the lock was successful, check-in the updates LOGGER.fine("Attempting to checkin file: " + member); - IAPICommand cmd = new ProjectCheckinCommand(); + IAPICommand cmd = new ProjectCheckinCommand(ciSettings); cmd.addOption(new APIOption(IAPIOption.PROJECT, configPath)); cmd.addOption(new APIOption(IAPIOption.CP_ID, cpid)); cmd.addOption(new FileAPIOption(IAPIOption.SOURCE_FILE, new File(""+member))); @@ -244,9 +243,9 @@ public static final void updateMember(APISession api, String configPath, FilePat cmd.addSelection(relativePath); - cmd.execute(api); + cmd.execute(); } - catch( APICommandException ae ) + catch( APIException ae ) { // If the command fails, add only if the error indicates a missing member ExceptionHandler eh = new ExceptionHandler(ae); @@ -259,7 +258,7 @@ public static final void updateMember(APISession api, String configPath, FilePat LOGGER.fine("Attempting to add file: " + member); // Construct the project add command - IAPICommand addCommand = new ProjectAddCommand(); + IAPICommand addCommand = new ProjectAddCommand(ciSettings); addCommand.addOption(new APIOption(IAPIOption.PROJECT, configPath)); addCommand.addOption(new APIOption(IAPIOption.CP_ID, cpid)); addCommand.addOption(new FileAPIOption(IAPIOption.SOURCE_FILE, new File(""+member))); @@ -267,7 +266,7 @@ public static final void updateMember(APISession api, String configPath, FilePat addCommand.addSelection(relativePath); // Execute the add command - addCommand.execute(api); + addCommand.execute(); } else { @@ -279,42 +278,39 @@ public static final void updateMember(APISession api, String configPath, FilePat /** * Performs a recursive unlock on all current user's locked members - * @param api Integrity API Session + * @param integrityConfig * @param configPath Full project configuration path + * @throws AbortException + * @throws APIException */ - public static final void unlockMembers(ISession api, String configPath) + public static final void unlockMembers(IntegrityConfigurable integrityConfig, String configPath) throws AbortException, APIException { // Construct the unlock command - IAPICommand command = new UnlockCommand(); + IAPICommand command = new UnlockCommand(integrityConfig); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); - - try { - command.execute(api); - } catch (APICommandException e) { - ExceptionHandler eh = new ExceptionHandler(e); - LOGGER.severe(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); - } + command.execute(); } /** * Creates a Change Package for updating Integrity SCM projects - * @param api Integrity API Session + * @param Integrity API Session * @param itemID Integrity Lifecycle Manager Item ID * @param desc Change Package Description * @return * @throws APIException + * @throws AbortException + * @throws InterruptedException */ - public static final String createCP(APISession api, String itemID, String desc) throws APIException + public static final String createCP(IntegrityConfigurable ciSettings, String itemID, String desc) throws APIException, AbortException, InterruptedException { // Return the generated CP ID String cpid = ":none"; - // Check to see if the Item ID contains the magic keyword - if( ":bypass".equalsIgnoreCase(itemID) || "bypass".equalsIgnoreCase(itemID) ) - { - return ":bypass"; - } + // Check to see if the Item ID contains the magic keyword + if( ":bypass".equalsIgnoreCase(itemID) || "bypass".equalsIgnoreCase(itemID) ) + { + return ":bypass"; + } // First figure out what Integrity Item to use for the Change Package try @@ -332,12 +328,12 @@ public static final String createCP(APISession api, String itemID, String desc) return cpid; } - IAPICommand command = new CreateCPCommand(); + IAPICommand command = new CreateCPCommand(ciSettings); command.addOption(new APIOption(IAPIOption.DESCRIPTION,desc)); command.addOption(new APIOption(IAPIOption.SUMMARY,desc)); command.addOption(new APIOption(IAPIOption.ITEM_ID,itemID)); - Response res = command.execute(api); + Response res = command.execute(); // Process the response object if( null != res ) @@ -362,15 +358,16 @@ public static final String createCP(APISession api, String itemID, String desc) /** * Submits the change package used for updating the Integrity SCM project - * @param api Integrity API Session + * @param ciSettings Integrity API Session * @param cpid Change Package ID + * @throws AbortException * @throws APIException */ - public static final void submitCP(APISession api, String cpid) throws APICommandException + public static final void submitCP(IntegrityConfigurable ciSettings, String cpid) throws APIException, AbortException { LOGGER.fine("Submitting Change Package: " + cpid); - IAPICommand command = new CloseCPCommand(); + IAPICommand command = new CloseCPCommand(ciSettings); command.addSelection(cpid); // First we'll attempt to close the cp to release locks on files that haven't changed, @@ -378,9 +375,9 @@ public static final void submitCP(APISession api, String cpid) throws APICommand // it will get automatically closed in the case of transactional cps try { - command.execute(api); + command.execute(); } - catch( APICommandException ae ) + catch( APIException ae ) { ExceptionHandler eh = new ExceptionHandler(ae); String exceptionString = eh.getMessage(); @@ -392,10 +389,10 @@ public static final void submitCP(APISession api, String cpid) throws APICommand LOGGER.fine("Attempting to submit cp: " + cpid); // Construct the submit cp command - IAPICommand submitcpcmd = new SubmitCPCommand(); + IAPICommand submitcpcmd = new SubmitCPCommand(ciSettings); submitcpcmd.addSelection(cpid); - submitcpcmd.execute(api); + submitcpcmd.execute(); } else { diff --git a/src/main/java/hudson/scm/IntegrityCMProject.java b/src/main/java/hudson/scm/IntegrityCMProject.java index 564528b..1b471dc 100644 --- a/src/main/java/hudson/scm/IntegrityCMProject.java +++ b/src/main/java/hudson/scm/IntegrityCMProject.java @@ -33,8 +33,6 @@ import com.mks.api.response.WorkItem; import hudson.AbortException; -import hudson.scm.api.APISession; -import hudson.scm.api.command.APICommandException; import hudson.scm.api.command.AddProjectLabelCommand; import hudson.scm.api.command.CheckPointCommand; import hudson.scm.api.command.IAPICommand; @@ -370,34 +368,16 @@ private Element writeChangeLog(Element item, Hashtable membe * TODO deprecate this method in later iteration * * Performs a checkpoint on this Integrity CM Project - * @param api Authenticated Integrity API Session + * @param integrityConfigurable Authenticated Integrity API Session * @param chkptLabel Checkpoint label string * @return Integrity API Response object - * @throws APICommandException - */ - public Response checkpoint(APISession api, String chkptLabel) throws APICommandException - { - // Construct the checkpoint command - IAPICommand command = new CheckPointCommand(); - command.addOption(new APIOption(IAPIOption.PROJECT, fullConfigSyntax)); - // Set the label and description if applicable - command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, chkptLabel); - - return command.execute(api); - } - - /** - * Performs a checkpoint on this Integrity CM Project - * @param api Authenticated Integrity API Session - * @param chkptLabel Checkpoint label string - * @return Integrity API Response object - * @throws APICommandException + * @throws APIException * @throws AbortException */ - public Response checkpoint(String chkptLabel) throws APICommandException, AbortException + public Response checkpoint(IntegrityConfigurable integrityConfigurable, String chkptLabel) throws APIException, AbortException { // Construct the checkpoint command - IAPICommand command = new CheckPointCommand(); + IAPICommand command = new CheckPointCommand(integrityConfigurable); command.addOption(new APIOption(IAPIOption.PROJECT, fullConfigSyntax)); // Set the label and description if applicable command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, chkptLabel); @@ -407,20 +387,21 @@ public Response checkpoint(String chkptLabel) throws APICommandException, AbortE /** * Applies a Project Label on this Integrity CM Project - * @param api Authenticated Integrity API Session + * @param serverConf Authenticated Integrity API Session * @param chkptLabel Checkpoint label string * @return Integrity API Response object * @throws APIException + * @throws AbortException */ - public Response addProjectLabel(APISession api, String chkptLabel, String projectName, String projectRevision) throws APIException + public Response addProjectLabel(IntegrityConfigurable serverConf, String chkptLabel, String projectName, String projectRevision) throws APIException, AbortException { // Construct the addprojectlabel command - IAPICommand command = new AddProjectLabelCommand(); + IAPICommand command = new AddProjectLabelCommand(serverConf); command.addOption(new APIOption(IAPIOption.PROJECT, projectName)); command.addOption(new APIOption(IAPIOption.LABEL, chkptLabel)); command.addOption(new APIOption(IAPIOption.PROJECT_REVISION, projectRevision)); - return command.execute(api); + return command.execute(); } /** diff --git a/src/main/java/hudson/scm/IntegrityCheckinTask.java b/src/main/java/hudson/scm/IntegrityCheckinTask.java index 0ce92c1..7cb7444 100644 --- a/src/main/java/hudson/scm/IntegrityCheckinTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckinTask.java @@ -15,7 +15,6 @@ import hudson.model.AbstractBuild; import hudson.model.BuildListener; import hudson.remoting.VirtualChannel; -import hudson.scm.api.APISession; import hudson.scm.api.ExceptionHandler; import jenkins.security.Roles; @@ -81,10 +80,6 @@ public Boolean invoke(File workspaceFile, VirtualChannel channel) throws IOExcep listener.getLogger().println("Integrity project '" + ciConfigPath + "' will be updated from directory " + workspace); - // Open our connection to the Integrity Server - APISession api = APISession.create(integrityConfig); - if( null != api ) - { try { // Determine what files need to be checked-in @@ -92,7 +87,7 @@ public Boolean invoke(File workspaceFile, VirtualChannel channel) throws IOExcep if( artifacts.length > 0 ) { // Create our Change Package for the supplied itemID - String cpid = IntegrityCMMember.createCP(api, itemID, "Build updates from " + buildID); + String cpid = IntegrityCMMember.createCP(integrityConfig, itemID, "Build updates from " + buildID); for( int i = 0; i < artifacts.length; i++ ) { FilePath member = artifacts[i]; @@ -101,18 +96,18 @@ public Boolean invoke(File workspaceFile, VirtualChannel channel) throws IOExcep // This is not a recursive directory tree check-in, only process files found if( !member.isDirectory() ) { - IntegrityCMMember.updateMember(api, ciConfigPath, member, relativePath, cpid, "Build updates from " + buildID); + IntegrityCMMember.updateMember(integrityConfig, ciConfigPath, member, relativePath, cpid, "Build updates from " + buildID); } } // Finally submit the build updates Change Package if its not :none or :bypass if( !cpid.equals(":none") && !cpid.equals(":bypass") ) { - IntegrityCMMember.submitCP(api, cpid); + IntegrityCMMember.submitCP(integrityConfig, cpid); } else { - IntegrityCMMember.unlockMembers(api, ciConfigPath); + IntegrityCMMember.unlockMembers(integrityConfig, ciConfigPath); } // Log the success @@ -140,23 +135,9 @@ public Boolean invoke(File workspaceFile, VirtualChannel channel) throws IOExcep LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); LOGGER.log(Level.SEVERE, "APIException", aex); return false; - } - finally - { - if( null != api ) - { - api.terminate(); - } - } - } - else - { - listener.getLogger().println("Couldn't create API Session for check-in task!"); - listener.getLogger().println("Failed to update Integrity project '" + ciConfigPath + "' with contents of workspace (" + workspace + ")!"); - return false; - } - - // If we got here, everything is good on the check-in... + } + + // If we got here, everything is good on the check-in... return true; } } diff --git a/src/main/java/hudson/scm/IntegrityCheckoutTask.java b/src/main/java/hudson/scm/IntegrityCheckoutTask.java index cf5d2bb..725d52a 100644 --- a/src/main/java/hudson/scm/IntegrityCheckoutTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckoutTask.java @@ -21,13 +21,14 @@ import org.jenkinsci.remoting.RoleChecker; import org.jenkinsci.remoting.RoleSensitive; +import com.mks.api.response.APIException; + import hudson.FilePath; import hudson.FilePath.FileCallable; import hudson.model.TaskListener; import hudson.remoting.VirtualChannel; import hudson.scm.api.APISession; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.command.APICommandException; import jenkins.security.Roles; public class IntegrityCheckoutTask implements FileCallable @@ -242,7 +243,7 @@ public Void call() throws Exception { IntegrityCMMember.checkout(api, configPath, memberID, memberRev, memberTimestamp, targetFile, restoreTimestamp, lineTerminator); } - catch(APICommandException aex) + catch(APIException aex) { LOGGER.severe("API Command Exception caught."); ExceptionHandler eh = new ExceptionHandler(aex); diff --git a/src/main/java/hudson/scm/IntegrityCheckpointAction.java b/src/main/java/hudson/scm/IntegrityCheckpointAction.java index b91e6a7..ae6ab3f 100644 --- a/src/main/java/hudson/scm/IntegrityCheckpointAction.java +++ b/src/main/java/hudson/scm/IntegrityCheckpointAction.java @@ -25,6 +25,7 @@ import groovy.lang.Binding; import groovy.lang.GroovyShell; +import hudson.AbortException; import hudson.Extension; import hudson.Launcher; import hudson.model.AbstractBuild; @@ -32,7 +33,6 @@ import hudson.model.BuildListener; import hudson.model.Result; import hudson.scm.IntegritySCM.DescriptorImpl; -import hudson.scm.api.APISession; import hudson.scm.api.ExceptionHandler; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; @@ -47,7 +47,7 @@ public class IntegrityCheckpointAction extends Notifier implements Serializable { private static final long serialVersionUID = 3344676447487492553L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private String checkpointLabel; private final Log logger = LogFactory.getLog(getClass()); private String serverConfig; @@ -188,7 +188,7 @@ private void setConfigurationName(AbstractBuild thisBuild) /** * Applies a project label to a project or subproject - * @param api Integrity API Session wrapper + * @param serverConf Integrity API Session wrapper * @param listener Jenkins build listener * @param siProject IntegrityCMProject object * @param fullConfigPath Integrity project configuration path @@ -196,13 +196,14 @@ private void setConfigurationName(AbstractBuild thisBuild) * @param revision Integrity project/subproject revision * @param chkptLabel Checkpoint label string * @throws APIException + * @throws AbortException */ - private void applyProjectLabel(APISession api, BuildListener listener, IntegrityCMProject siProject, String fullConfigPath, String projectName, String revision, String chkptLabel) throws APIException + private void applyProjectLabel(IntegrityConfigurable serverConf, BuildListener listener, IntegrityCMProject siProject, String fullConfigPath, String projectName, String revision, String chkptLabel) throws APIException, AbortException { // Looks like the checkpoint was done before the build, so lets apply the label now listener.getLogger().println("Preparing to execute si addprojectlabel for " + fullConfigPath); listener.getLogger().println(" (" + projectName + ", " + revision + ")"); - Response res = siProject.addProjectLabel(api, chkptLabel, projectName, revision); + Response res = siProject.addProjectLabel(serverConf, chkptLabel, projectName, revision); logger.debug(res.getCommandString() + " returned " + res.getExitCode()); listener.getLogger().println("Successfully added label '" + chkptLabel + "' to revision " + revision); @@ -243,21 +244,19 @@ private IntegrityConfigurable getProjectSettings(AbstractBuild thisBuild) */ public boolean perform(AbstractBuild build, Launcher launcher, BuildListener listener) throws InterruptedException, IOException { - // Set the configuration name for this build + // Set the configuration name for this build setConfigurationName(build); if( ! Result.SUCCESS.equals(build.getResult()) ) { - listener.getLogger().println("Build failed! Skipping Integrity Checkpoint step!"); - return true; + listener.getLogger().println("Build failed! Skipping Integrity Checkpoint step!"); + return true; } - APISession api = APISession.create(getProjectSettings(build)); - if( null != api ) - { - // Evaluate the groovy tag name - Map env = build.getEnvironment(listener); - String chkptLabel = IntegrityCheckpointAction.evalGroovyExpression(env, checkpointLabel); + IntegrityConfigurable serverConf = getProjectSettings(build); + // Evaluate the groovy tag name + Map env = build.getEnvironment(listener); + String chkptLabel = IntegrityCheckpointAction.evalGroovyExpression(env, checkpointLabel); try { // Get information about the project @@ -269,7 +268,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen { // A checkpoint wasn't done before the build, so lets checkpoint this build now... listener.getLogger().println("Preparing to execute si checkpoint for " + siProject.getConfigurationPath()); - Response res = siProject.checkpoint(api, chkptLabel); + Response res = siProject.checkpoint(serverConf, chkptLabel); logger.debug(res.getCommandString() + " returned " + res.getExitCode()); WorkItem wi = res.getWorkItem(siProject.getConfigurationPath()); String chkpt = wi.getResult().getField("resultant").getItem().getId(); @@ -282,7 +281,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen if( siProject.getCheckpointBeforeBuild() ) { // Attach label to 'main' project - applyProjectLabel(api, listener, siProject, siProject.getConfigurationPath(), siProject.getProjectName(), siProject.getProjectRevision(), chkptLabel); + applyProjectLabel(serverConf, listener, siProject, siProject.getConfigurationPath(), siProject.getProjectName(), siProject.getProjectRevision(), chkptLabel); // Attach label to 'subProjects' for (Hashtable memberInfo: DerbyUtils.viewSubProjects(siProject.getProjectCacheTable())) @@ -290,7 +289,7 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen String fullConfigPath = String.class.cast(memberInfo.get(CM_PROJECT.CONFIG_PATH)); String projectName = String.class.cast(memberInfo.get(CM_PROJECT.NAME)); String revision = String.class.cast(memberInfo.get(CM_PROJECT.REVISION)); - applyProjectLabel(api, listener, siProject, fullConfigPath, projectName, revision, chkptLabel); + applyProjectLabel(serverConf, listener, siProject, fullConfigPath, projectName, revision, chkptLabel); } } else @@ -302,12 +301,12 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen else { LOGGER.severe("Cannot find Integrity CM Project information for configuration '" + getConfigurationName() + "'"); - listener.getLogger().println("ERROR: Cannot find Integrity CM Project information for configuration '" + getConfigurationName() + "'!"); - } - } - catch( APIException aex ) - { - LOGGER.severe("API Exception caught..."); + listener.getLogger().println("ERROR: Cannot find Integrity CM Project information for configuration '" + getConfigurationName() + "'!"); + } + } + catch( APIException aex ) + { + LOGGER.severe("API Exception caught..."); ExceptionHandler eh = new ExceptionHandler(aex); aex.printStackTrace(listener.fatalError(eh.getMessage())); LOGGER.severe(eh.getMessage()); @@ -320,22 +319,10 @@ public boolean perform(AbstractBuild build, Launcher launcher, BuildListen listener.getLogger().println("A SQL Exception was caught!"); listener.getLogger().println(sqlex.getMessage()); LOGGER.log(Level.SEVERE, "SQLException", sqlex); - return false; - } - finally - { - api.terminate(); - } - - } - else - { - LOGGER.severe("An API Session could not be established! Cannot perform checkpoint operation!"); - listener.getLogger().println("An API Session could not be established! Cannot perform checkpoint operation!"); - return false; - } - - return true; + return false; + } + + return true; } /** diff --git a/src/main/java/hudson/scm/IntegritySCM.java b/src/main/java/hudson/scm/IntegritySCM.java index a709c47..3ad97c6 100644 --- a/src/main/java/hudson/scm/IntegritySCM.java +++ b/src/main/java/hudson/scm/IntegritySCM.java @@ -7,30 +7,26 @@ import java.io.PrintWriter; import java.io.Serializable; import java.sql.SQLException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.Map; import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; -import java.util.logging.Logger; import javax.servlet.ServletException; import javax.sql.ConnectionPoolDataSource; import org.kohsuke.stapler.DataBoundConstructor; -import org.kohsuke.stapler.DataBoundSetter; import org.kohsuke.stapler.QueryParameter; import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.export.Exported; import com.mks.api.response.APIException; import com.mks.api.response.Response; import com.mks.api.response.WorkItem; import hudson.AbortException; +import hudson.EnvVars; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; @@ -39,18 +35,10 @@ import hudson.model.ModelObject; import hudson.model.Run; import hudson.model.TaskListener; -import hudson.scm.ChangeLogParser; -import hudson.scm.PollingResult; -import hudson.scm.RepositoryBrowsers; -import hudson.scm.SCM; -import hudson.scm.SCMDescriptor; -import hudson.scm.SCMRevisionState; import hudson.scm.IntegrityCheckpointAction.IntegrityCheckpointDescriptorImpl; import hudson.scm.api.APISession; import hudson.scm.api.APIUtils; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.command.APICommandException; -import hudson.scm.api.command.BasicAPICommand; import hudson.scm.api.command.IAPICommand; import hudson.scm.api.command.ProjectInfoCommand; import hudson.scm.api.command.ViewProjectCommand; @@ -67,1024 +55,573 @@ * This class provides an integration between Hudson/Jenkins for Continuous Builds and * PTC Integrity for Configuration Management */ -public class IntegritySCM extends SCM implements Serializable +public class IntegritySCM extends AbstractIntegritySCM implements Serializable { - private static final long serialVersionUID = 7559894846609712683L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); - private static final Map projects = new ConcurrentHashMap(); - public static final String NL = System.getProperty("line.separator"); - public static final String FS = System.getProperty("file.separator"); - public static final int MIN_PORT_VALUE = 1; - public static final int MAX_PORT_VALUE = 65535; - public static final int DEFAULT_THREAD_POOL_SIZE = 5; - public static final SimpleDateFormat SDF = new SimpleDateFormat("MMM dd, yyyy h:mm:ss a"); - private final String ciServerURL = (null == Jenkins.getInstance().getRootUrl() ? "" : Jenkins.getInstance().getRootUrl()); - private String integrityURL; - private IntegrityRepositoryBrowser browser; - private String serverConfig; - private String userName; - private Secret password; - private String configPath; - private String includeList; - private String excludeList; - private String checkpointLabel; - private String configurationName; - private boolean cleanCopy; - private boolean skipAuthorInfo = true; - private String lineTerminator = "native"; - private boolean restoreTimestamp = true; - private boolean checkpointBeforeBuild = false; - private String alternateWorkspace; - private boolean fetchChangedWorkspaceFiles = false; - private boolean deleteNonMembers = false; - private int checkoutThreadPoolSize = DEFAULT_THREAD_POOL_SIZE; - - /** - * Create a constructor that takes non-transient fields, and add the annotation @DataBoundConstructor to it. - * Using the annotation helps the Stapler class to find which constructor that should be used when - * automatically copying values from a web form to a class. - */ - @Deprecated - public IntegritySCM(IntegrityRepositoryBrowser browser, String serverConfig, String userName, String password, String configPath, - String includeList, String excludeList, boolean cleanCopy, String lineTerminator, boolean restoreTimestamp, - boolean skipAuthorInfo, boolean checkpointBeforeBuild, String checkpointLabel, String alternateWorkspace, - boolean fetchChangedWorkspaceFiles, boolean deleteNonMembers, int checkoutThreadPoolSize, String configurationName) - { - // Log the construction - LOGGER.fine("IntegritySCM constructor (deprecated) has been invoked!"); - // Initialize the class variables - this.browser = browser; - this.serverConfig = serverConfig; - if( null != userName && userName.length() > 0 ) - { - this.userName = userName; - } - else - { - this.userName = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig).getUserName(); - } - if( null != password && password.length() > 0 ) - { - this.password = Secret.fromString(password); - } - else - { - this.password = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig).getSecretPassword(); - } - - this.configPath = configPath; - this.includeList = includeList; - this.excludeList = excludeList; - this.cleanCopy = cleanCopy; - this.lineTerminator = lineTerminator; - this.restoreTimestamp = restoreTimestamp; - this.skipAuthorInfo = skipAuthorInfo; - this.checkpointBeforeBuild = checkpointBeforeBuild; - this.checkpointLabel = checkpointLabel; - this.alternateWorkspace = alternateWorkspace; - this.fetchChangedWorkspaceFiles = fetchChangedWorkspaceFiles; - this.deleteNonMembers = deleteNonMembers; - this.checkoutThreadPoolSize = (checkoutThreadPoolSize > 0 ? checkoutThreadPoolSize : DEFAULT_THREAD_POOL_SIZE); - this.configurationName = configurationName; - - // Initialize the Integrity URL - initIntegrityURL(); - - LOGGER.fine("CI Server URL: " + this.ciServerURL); - LOGGER.fine("URL: " + this.integrityURL); - LOGGER.fine("Server Configuration: " + this.serverConfig); - LOGGER.fine("Project User: " + this.userName); - LOGGER.fine("Project User Password: " + this.password); - LOGGER.fine("Configuration Name: " + this.configurationName); - LOGGER.fine("Configuration Path: " + this.configPath); - LOGGER.fine("Include Filter: " + this.includeList); - LOGGER.fine("Exclude Filter: " + this.excludeList); - LOGGER.fine("Line Terminator: " + this.lineTerminator); - LOGGER.fine("Restore Timestamp: " + this.restoreTimestamp); - LOGGER.fine("Clean: " + this.cleanCopy); - LOGGER.fine("Skip Author Info: " + this.skipAuthorInfo); - LOGGER.fine("Checkpoint Before Build: " + this.checkpointBeforeBuild); - LOGGER.fine("Tag Name: " + this.checkpointLabel); - LOGGER.fine("Alternate Workspace Directory: " + this.alternateWorkspace); - LOGGER.fine("Fetch Changed Workspace Files: " + this.fetchChangedWorkspaceFiles); - LOGGER.fine("Delete Non Members: " + this.deleteNonMembers); - LOGGER.fine("Checkout Thread Pool Size: " + this.checkoutThreadPoolSize); - } - - @DataBoundConstructor - public IntegritySCM(String serverConfig, String configPath, String configurationName) - { - // Log the construction - LOGGER.fine("IntegritySCM constructor has been invoked!"); - // Initialize the class variables - this.serverConfig = serverConfig; - IntegrityConfigurable desSettings = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig); - this.userName = desSettings.getUserName(); - this.password = desSettings.getSecretPassword(); - this.configPath = configPath; - this.includeList = ""; - this.excludeList = ""; - this.cleanCopy = false; - this.lineTerminator = "native"; - this.restoreTimestamp = true; - this.skipAuthorInfo = true; - this.checkpointBeforeBuild = true; - this.checkpointLabel = ""; - this.alternateWorkspace = ""; - this.fetchChangedWorkspaceFiles = true; - this.deleteNonMembers = true; - this.checkoutThreadPoolSize = DEFAULT_THREAD_POOL_SIZE; - this.configurationName = configurationName; - - // Initialize the Integrity URL - initIntegrityURL(); - - LOGGER.fine("IntegritySCM constructed!"); - } - - @Override - @Exported /** - * Returns the Integrity Repository Browser - */ - public IntegrityRepositoryBrowser getBrowser() - { - return browser == null ? new IntegrityWebUI(null) : browser; - } - - /** - * Returns the simple server configuration name - * @return - */ - public String getServerConfig() - { - return serverConfig; - } - - /** - * Returns the project specific User connecting to the Integrity Server - * @return - */ - public String getUserName() - { - return this.userName; - } - - /** - * Returns the project specific encrypted password of the user connecting to the Integrity Server - * @return + * Create a constructor that takes non-transient fields, and add the annotation @DataBoundConstructor to it. + * Using the annotation helps the Stapler class to find which constructor that should be used when + * automatically copying values from a web form to a class. */ - public String getPassword() - { - return this.password.getEncryptedValue(); - } - - /** - * Returns the project specific Secret password of the user connecting to the Integrity Server - * @return - */ - public Secret getSecretPassword() - { - return this.password; - } - - /** - * Returns the Project or Configuration Path for a Integrity Source Project - * @return - */ - public String getConfigPath() - { - return configPath; - } - - /** - * Returns the files that will be excluded - * @return - */ - public String getIncludeList() - { - return includeList; - } - - /** - * Returns the files that will be included - * @return - */ - public String getExcludeList() + @Deprecated + public IntegritySCM(IntegrityRepositoryBrowser browser, String serverConfig, String userName, String password, String configPath, + String includeList, String excludeList, boolean cleanCopy, String lineTerminator, boolean restoreTimestamp, + boolean skipAuthorInfo, boolean checkpointBeforeBuild, String checkpointLabel, String alternateWorkspace, + boolean fetchChangedWorkspaceFiles, boolean deleteNonMembers, int checkoutThreadPoolSize, String configurationName) { - return excludeList; - } - - /** - * Returns true/false depending on whether or not the workspace is required to be cleaned - * @return - */ - public boolean getCleanCopy() - { - return cleanCopy; + super(); + // Log the construction + LOGGER.fine("IntegritySCM constructor (deprecated) has been invoked!"); + // Initialize the class variables + this.browser = browser; + this.serverConfig = serverConfig; + if( null != userName && userName.length() > 0 ) + { + this.userName = userName; + } + else + { + this.userName = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig).getUserName(); + } + if( null != password && password.length() > 0 ) + { + this.password = Secret.fromString(password); + } + else + { + this.password = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig).getSecretPassword(); + } + + this.configPath = configPath; + this.includeList = includeList; + this.excludeList = excludeList; + this.cleanCopy = cleanCopy; + this.lineTerminator = lineTerminator; + this.restoreTimestamp = restoreTimestamp; + this.skipAuthorInfo = skipAuthorInfo; + this.checkpointBeforeBuild = checkpointBeforeBuild; + this.checkpointLabel = checkpointLabel; + this.alternateWorkspace = alternateWorkspace; + this.fetchChangedWorkspaceFiles = fetchChangedWorkspaceFiles; + this.deleteNonMembers = deleteNonMembers; + this.checkoutThreadPoolSize = (checkoutThreadPoolSize > 0 ? checkoutThreadPoolSize : DEFAULT_THREAD_POOL_SIZE); + this.configurationName = configurationName; + + // Initialize the Integrity URL + initIntegrityURL(); + + LOGGER.fine("CI Server URL: " + this.ciServerURL); + LOGGER.fine("URL: " + this.integrityURL); + LOGGER.fine("Server Configuration: " + this.serverConfig); + LOGGER.fine("Project User: " + this.userName); + LOGGER.fine("Project User Password: " + this.password); + LOGGER.fine("Configuration Name: " + this.configurationName); + LOGGER.fine("Configuration Path: " + this.configPath); + LOGGER.fine("Include Filter: " + this.includeList); + LOGGER.fine("Exclude Filter: " + this.excludeList); + LOGGER.fine("Line Terminator: " + this.lineTerminator); + LOGGER.fine("Restore Timestamp: " + this.restoreTimestamp); + LOGGER.fine("Clean: " + this.cleanCopy); + LOGGER.fine("Skip Author Info: " + this.skipAuthorInfo); + LOGGER.fine("Checkpoint Before Build: " + this.checkpointBeforeBuild); + LOGGER.fine("Tag Name: " + this.checkpointLabel); + LOGGER.fine("Alternate Workspace Directory: " + this.alternateWorkspace); + LOGGER.fine("Fetch Changed Workspace Files: " + this.fetchChangedWorkspaceFiles); + LOGGER.fine("Delete Non Members: " + this.deleteNonMembers); + LOGGER.fine("Checkout Thread Pool Size: " + this.checkoutThreadPoolSize); } - /** - * Returns the line terminator to apply when obtaining files from the Integrity Server - * @return - */ - public String getLineTerminator() - { - return lineTerminator; + @DataBoundConstructor + public IntegritySCM(String serverConfig, String configPath, String configurationName) + { + super(); + // Log the construction + LOGGER.fine("IntegritySCM constructor has been invoked!"); + // Initialize the class variables + this.serverConfig = serverConfig; + IntegrityConfigurable desSettings = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig); + this.userName = desSettings.getUserName(); + this.password = desSettings.getSecretPassword(); + this.configPath = configPath; + this.includeList = ""; + this.excludeList = ""; + this.cleanCopy = false; + this.lineTerminator = "native"; + this.restoreTimestamp = true; + this.skipAuthorInfo = true; + this.checkpointBeforeBuild = true; + this.checkpointLabel = ""; + this.alternateWorkspace = ""; + this.fetchChangedWorkspaceFiles = true; + this.deleteNonMembers = true; + this.checkoutThreadPoolSize = DEFAULT_THREAD_POOL_SIZE; + this.configurationName = configurationName; + + // Initialize the Integrity URL + initIntegrityURL(); + + LOGGER.fine("IntegritySCM constructed!"); } - + /** - * Returns true/false depending on whether or not the restore timestamp option is in effect - * @return - */ - public boolean getRestoreTimestamp() + * Provides a mechanism to update the Integrity URL, based on updates + * to the hostName/port/secure variables + */ + private void initIntegrityURL() { - return restoreTimestamp; + // Initialize the Integrity URL + IntegrityConfigurable ic = ((DescriptorImpl)this.getDescriptor()).getConfiguration(serverConfig); + integrityURL = (ic.getSecure() ? "https://" : "http://") + ic.getHostName() + ":" + String.valueOf(ic.getPort()); } - - /** - * Returns true/false depending on whether or not to use 'si revisioninfo' to determine author information - * @return - */ - public boolean getSkipAuthorInfo() - { - return skipAuthorInfo; - } /** - * Returns true/false depending on whether or not perform a checkpoint before the build - * @return + * Adds Integrity CM Project info to the build variables */ - public boolean getCheckpointBeforeBuild() - { - return checkpointBeforeBuild; - } + @Override + public void buildEnvVars(AbstractBuild build, Map env) + { + super.buildEnvVars(build, env); + LOGGER.fine("buildEnvVars() invoked...!"); + IntegrityConfigurable ic = ((DescriptorImpl)this.getDescriptor()).getConfiguration(serverConfig); - /** - * Returns the label string for the checkpoint performed before the build - * @return - */ - public String getCheckpointLabel() - { - if( checkpointLabel == null || checkpointLabel.length() == 0 ) - { - return IntegrityCheckpointDescriptorImpl.defaultCheckpointLabel; - } - return checkpointLabel; - } + env.put("MKSSI_HOST", ic.getHostName()); + env.put("MKSSI_PORT", String.valueOf(ic.getPort())); + env.put("MKSSI_USER", userName); - /** - * Returns the alternate workspace directory - * @return - */ - public String getAlternateWorkspace() - { - return alternateWorkspace; - } - - /** - * Returns the true/false depending on whether or not to synchronize changed workspace files - * @return - */ - public boolean getFetchChangedWorkspaceFiles() - { - return fetchChangedWorkspaceFiles; + // Populate with information about the most recent checkpoint + IntegrityCMProject siProject = getIntegrityProject(); + if( null != siProject && siProject.isBuild() ) + { + env.put("MKSSI_PROJECT", siProject.getConfigurationPath()); + env.put("MKSSI_BUILD", siProject.getProjectRevision()); + } } - - /** - * Returns the true/false depending on whether non members should be deleted before the build - * @return - */ - public boolean getDeleteNonMembers() - { - return deleteNonMembers; - } - /** - * Returns the size of the thread pool for parallel checkouts - * @return - */ - public int getCheckoutThreadPoolSize() - { - return checkoutThreadPoolSize; - } - /** - * Returns the configuration name for this project - * Required when working with Multiple SCMs plug-in - */ - public String getConfigurationName() - { - return configurationName; - } - - /** - * Sets the Integrity SCM web browser - * @param browser - */ - @DataBoundSetter - public final void setBrowser(IntegrityRepositoryBrowser browser) - { - this.browser = browser; - } - - /** - * Sets the server configuration name for this project - * @param serverConfig - */ - public void setServerConfig(String serverConfig) - { - this.serverConfig = serverConfig; - IntegrityConfigurable ic = ((DescriptorImpl)this.getDescriptor()).getConfiguration(serverConfig); - integrityURL = (ic.getSecure() ? "https://" : "http://") + ic.getHostName() + ":" + String.valueOf(ic.getPort()); - } - - /** - * Sets the project specific User connecting to the Integrity Server - * @return + * Overridden calcRevisionsFromBuild function + * Returns the current project configuration which can be used to difference any future configurations */ - @DataBoundSetter - public final void setUserName(String userName) - { - if( null != userName && userName.length() > 0 ) + @Override + public SCMRevisionState calcRevisionsFromBuild(Run run, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException + { + // Log the call for debug purposes + LOGGER.fine("calcRevisionsFromBuild() invoked...!"); + // Get the project cache table name for this build + String projectCacheTable = null; + Job job = run.getParent(); + String jobName = job.getName(); + + try { - this.userName = userName; + projectCacheTable = DerbyUtils.getProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), + jobName, configurationName, run.getNumber()); } - } - - /** - * Sets the project specific encrypted Password of the user connecting to the Integrity Server - * @param password - The clear password - */ - @DataBoundSetter - public final void setPassword(String password) - { - if( null != password && password.length() > 0 ) + catch (SQLException sqlex) { - this.password = Secret.fromString(password); - } - } - - /** - * Sets the Project or Configuration Path for an Integrity Source Project - * @return - */ - public void setConfigPath(String configPath) - { - this.configPath = configPath; + LOGGER.severe("SQL Exception caught..."); + listener.getLogger().println("A SQL Exception was caught!"); + listener.getLogger().println(sqlex.getMessage()); + LOGGER.log(Level.SEVERE, "SQLException", sqlex); + } + return new IntegrityRevisionState(jobName, configurationName, projectCacheTable); } /** - * Sets the files that will be not be included - * @return - */ - @DataBoundSetter - public final void setIncludeList(String includeList) - { - this.includeList = includeList; - } - - /** - * Sets the files that will be not be included - * @return - */ - @DataBoundSetter - public final void setExcludeList(String excludeList) - { - this.excludeList = excludeList; - } - - /** - * Toggles whether or not the workspace is required to be cleaned - * @return - */ - @DataBoundSetter - public final void setCleanCopy(boolean cleanCopy) - { - this.cleanCopy = cleanCopy; - } - - /** - * Sets the line terminator to apply when obtaining files from the Integrity Server - * @return - */ - @DataBoundSetter - public final void setLineTerminator(String lineTerminator) - { - this.lineTerminator = lineTerminator; - } - - /** - * Toggles whether or not to restore the timestamp for individual files - * @return - */ - @DataBoundSetter - public final void setRestoreTimestamp(boolean restoreTimestamp) + * Primes the Integrity Project metadata information + * @param run + * @param listener + * @return response Integrity API Response + * @throws InterruptedException + * @throws IOException + * @throws APIException + */ + private Response initializeCMProject(EnvVars environment, String projectCacheTable) throws APIException, IOException, InterruptedException { - this.restoreTimestamp = restoreTimestamp; + String resolvedConfigPath = IntegrityCheckpointAction.evalGroovyExpression(environment, configPath); + + // Get the project information for this project + IAPICommand command = new ProjectInfoCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); + command.addOption(new APIOption(IAPIOption.PROJECT, resolvedConfigPath)); + + Response infoRes = command.execute(); + + LOGGER.fine(infoRes.getCommandString() + " returned " + infoRes.getExitCode()); + // Initialize our siProject class variable + IntegrityCMProject siProject = new IntegrityCMProject(APIUtils.getWorkItem(infoRes), projectCacheTable); + // Set the project options + siProject.setLineTerminator(lineTerminator); + siProject.setRestoreTimestamp(restoreTimestamp); + siProject.setSkipAuthorInfo(skipAuthorInfo); + siProject.setCheckpointBeforeBuild(checkpointBeforeBuild); + projects.put(configurationName, siProject); + return infoRes; } /** - * Toggles whether or not to use 'si revisioninfo' to determine author information + * Utility function to parse the include/exclude filter + * @param command API Command for the 'si viewproject' command * @return - */ - @DataBoundSetter - public final void setSkipAuthorInfo(boolean skipAuthorInfo) - { - this.skipAuthorInfo = skipAuthorInfo; - } - - /** - * Toggles whether or not a checkpoint should be performed before the build - * @param checkpointBeforeBuild */ - @DataBoundSetter - public final void setCheckpointBeforeBuild(boolean checkpointBeforeBuild) - { - this.checkpointBeforeBuild = checkpointBeforeBuild; + private void applyMemberFilters(IAPICommand command) + { + // Checking if our include list has any entries + if( null != includeList && includeList.length() > 0 ) + { + StringBuilder filterString = new StringBuilder(); + String[] filterTokens = includeList.split(",|;"); + // prepare a OR combination of include filters (all in one filter, separated by comma if needed) + for( int i = 0; i < filterTokens.length; i++ ) + { + filterString.append(i > 0 ? "," : ""); + filterString.append("file:"); + filterString.append(filterTokens[i]); + } + command.addOption(new APIOption(IAPIOption.FILTER, filterString.toString())); + } + + // Checking if our exclude list has any entries + if( null != excludeList && excludeList.length() > 0 ) + { + String[] filterTokens = excludeList.split(",|;"); + // prepare a AND combination of exclude filters (one filter each filter) + for( int i = 0; i < filterTokens.length; i++ ) + { + if (filterTokens[i]!= null) + { + command.addOption(new APIOption(IAPIOption.FILTER, "!file:"+filterTokens[i])); + } + } + } } /** - * Sets the label string for the checkpoint performed before the build - * @param checkpointLabel + * Primes the Integrity Project Member metadata information + * @return response Integrity API Response + * @throws APIException + * @throws SQLException + * @throws AbortException */ - @DataBoundSetter - public final void setCheckpointLabel(String checkpointLabel) + private Response initializeCMProjectMembers() throws APIException, SQLException, AbortException { - this.checkpointLabel = checkpointLabel; - } + IntegrityCMProject siProject = getIntegrityProject(); - /** - * Sets an alternate workspace for the checkout directory - * @param alternateWorkspace - */ - @DataBoundSetter - public final void setAlternateWorkspace(String alternateWorkspace) - { - this.alternateWorkspace = alternateWorkspace; + // Lets parse this project + IAPICommand command = new ViewProjectCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); + + command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath())); + APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"); + command.addOption(new APIOption(IAPIOption.FIELDS, APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"))); + + // Apply our include/exclude filters + applyMemberFilters(command); + + LOGGER.fine("Preparing to execute si viewproject for " + siProject.getConfigurationPath()); + Response viewRes = command.execute(); + + DerbyUtils.parseProject(siProject, viewRes.getWorkItems()); + return viewRes; } - + /** - * Toggles whether or not changed workspace files should be synchronized - * @param fetchChangedWorkspaceFiles + * Overridden checkout function + * This is the real invocation of this plugin. + * Currently, we will do a project info and determine the true nature of the project + * Subsequent to that we will run a view project command and cache the information + * on each member, so that we can execute project checkout commands. This obviously + * eliminates the need for a sandbox and can wily nilly delete the workspace directory as needed */ - @DataBoundSetter - public final void setFetchChangedWorkspaceFiles(boolean fetchChangedWorkspaceFiles) + @Override + public void checkout(Run run, Launcher launcher, FilePath workspace, + TaskListener listener, File changeLogFile, + SCMRevisionState baseline) throws IOException, InterruptedException { - this.fetchChangedWorkspaceFiles = fetchChangedWorkspaceFiles; - } + // Log the invocation... + LOGGER.fine("Start execution of checkout() routine...!"); + + // Re-evaluate the config path to resolve any groovy expressions... + //String resolvedConfigPath = IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), configPath); + + // Provide links to the Change and Build logs for easy access from Integrity + listener.getLogger().println("Change Log: " + ciServerURL + run.getUrl() + "changes"); + listener.getLogger().println("Build Log: " + ciServerURL + run.getUrl() + "console"); + + // Lets start with creating an authenticated Integrity API Session for various parts of this operation... + IntegrityConfigurable desSettings = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig); + IntegrityConfigurable coSettings = new IntegrityConfigurable("TEMP_ID", desSettings.getIpHostName(), desSettings.getIpPort(), desSettings.getHostName(), + desSettings.getPort(), desSettings.getSecure(), userName, password.getPlainText()); + + // Lets also open the change log file for writing... + // Override file.encoding property so that we write as UTF-8 and do not have problems with special characters + PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(changeLogFile),"UTF-8")); + try + { + // Register the project cache for this build + Job job = run.getParent(); + String projectCacheTable = DerbyUtils.registerProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), + job.getName(), configurationName, run.getNumber()); + + // Next, load up the information for this Integrity Project's configuration + //listener.getLogger().println("Preparing to execute si projectinfo for " + resolvedConfigPath); + listener.getLogger().println("Preparing to execute si projectinfo for " + configPath); + initializeCMProject(run.getEnvironment(listener), projectCacheTable); + IntegrityCMProject siProject = getIntegrityProject(); + + // Check to see we need to checkpoint before the build + if( checkpointBeforeBuild ) + { + checkPointBeforeBuild(run, listener, siProject); + } + + listener.getLogger().println("Preparing to execute si viewproject for " + siProject.getConfigurationPath()); + initializeCMProjectMembers(); + + // Now, we need to find the project state from the previous build. + String prevProjectCache = null; + if( null != baseline && baseline instanceof IntegrityRevisionState ) + { + IntegrityRevisionState irs = (IntegrityRevisionState)baseline; + prevProjectCache = irs.getProjectCache(); + + if( null != prevProjectCache && prevProjectCache.length() > 0 ) + { + // Compare the current project with the old revision state + LOGGER.fine("Found previous project state " + prevProjectCache); + DerbyUtils.compareBaseline(serverConfig, prevProjectCache, projectCacheTable, skipAuthorInfo); + } + } + else + { + // We don't have the previous Integrity Revision State! + LOGGER.fine("Cannot construct previous Integrity Revision State!"); + // Prime the author information for the current build as this could be the first build + if( ! skipAuthorInfo ){ DerbyUtils.primeAuthorInformation(serverConfig, projectCacheTable); } + } + + // After all that insane interrogation, we have the current Project state that is + // correctly initialized and either compared against its baseline or is a fresh baseline itself + // Now, lets figure out how to populate the workspace... + List> projectMembersList = DerbyUtils.viewProject(projectCacheTable); + List dirList = DerbyUtils.getDirList(projectCacheTable); + String resolvedAltWkspace = IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), alternateWorkspace); + // If we we were not able to establish the previous project state, then always do full checkout. cleanCopy = true + // Otherwise, update the workspace in accordance with the user's cleanCopy option + + IntegrityCheckoutTask coTask = new IntegrityCheckoutTask(projectMembersList, dirList, resolvedAltWkspace, lineTerminator, restoreTimestamp, + ((null == prevProjectCache || prevProjectCache.length() == 0) ? true : cleanCopy), + fetchChangedWorkspaceFiles,checkoutThreadPoolSize, listener, coSettings); + + // Execute the IntegrityCheckoutTask.invoke() method to do the actual synchronization... + if( workspace.act(coTask) ) + { + // Now that the workspace is updated, lets save the current project state for future comparisons + listener.getLogger().println("Saving current Integrity Project configuration..."); + if( fetchChangedWorkspaceFiles ){ DerbyUtils.updateChecksum(projectCacheTable, coTask.getChecksumUpdates()); } + // Write out the change log file, which will be used by the parser to report the updates + listener.getLogger().println("Writing build change log..."); + writer.println(siProject.getChangeLog(String.valueOf(run.getNumber()), projectMembersList)); + listener.getLogger().println("Change log successfully generated: " + changeLogFile.getAbsolutePath()); + // Delete non-members in this workspace, if appropriate... + if( deleteNonMembers ) + { + + IntegrityDeleteNonMembersTask deleteNonMembers = new IntegrityDeleteNonMembersTask(listener, resolvedAltWkspace, projectMembersList, dirList); + if( ! workspace.act(deleteNonMembers) ) + { + throw new AbortException("Failed to delete non-members!"); + } + } + } + else + { + // Checkout failed! Returning false... + throw new AbortException("Failed to synchronize workspace!"); + } + } + catch(APIException aex) + { + LOGGER.severe("API Exception caught..."); + listener.getLogger().println("An API Exception was caught!"); + ExceptionHandler eh = new ExceptionHandler(aex); + LOGGER.severe(eh.getMessage()); + listener.getLogger().println(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + listener.getLogger().println(eh.getCommand() + " returned exit code " + eh.getExitCode()); + + throw new AbortException("Caught Integrity APIException!"); + } + catch(SQLException sqlex) + { + LOGGER.severe("SQL Exception caught..."); + listener.getLogger().println("A SQL Exception was caught!"); + listener.getLogger().println(sqlex.getMessage()); + LOGGER.log(Level.SEVERE, "SQLException", sqlex); + + throw new AbortException("Caught Derby SQLException!"); + } + finally + { + if( writer != null ) + { + writer.close(); + } + } - /** - * Toggles whether or not non members should be deleted - * @param deleteNonMembers - */ - @DataBoundSetter - public final void setDeleteNonMembers(boolean deleteNonMembers) - { - this.deleteNonMembers = deleteNonMembers; - } - - /** - * Sets the thread pool size of parallel checkout threads - * @param checkoutThreadPoolSize - */ - @DataBoundSetter - public final void setCheckoutThreadPoolSize(int checkoutThreadPoolSize) - { - this.checkoutThreadPoolSize = checkoutThreadPoolSize; + // Log the completion... + LOGGER.fine("Completed execution of checkout() routine...!"); } /** - * Sets the configuration name for this project - * @param configurationName Name for this project configuration - */ - public void setConfigurationName(String configurationName) - { - this.configurationName = configurationName; - } - - /** - * Provides a mechanism to update the Integrity URL, based on updates - * to the hostName/port/secure variables + * @param run + * @param listener + * @param siProject + * @throws APIException + * @throws AbortException + * @throws IOException + * @throws InterruptedException + * @throws InterruptedException */ - private void initIntegrityURL() + private void checkPointBeforeBuild(Run run, TaskListener listener, + IntegrityCMProject siProject) throws + AbortException, IOException, InterruptedException, + com.mks.api.response.InterruptedException, APIException { - // Initialize the Integrity URL - IntegrityConfigurable ic = ((DescriptorImpl)this.getDescriptor()).getConfiguration(serverConfig); - integrityURL = (ic.getSecure() ? "https://" : "http://") + ic.getHostName() + ":" + String.valueOf(ic.getPort()); + // Make sure we don't have a build project configuration + if( ! siProject.isBuild() ) + { + // Execute a pre-build checkpoint... + listener.getLogger().println("Preparing to execute pre-build si checkpoint for " + siProject.getConfigurationPath()); + Response res = siProject.checkpoint(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig), IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), checkpointLabel)); + LOGGER.fine(res.getCommandString() + " returned " + res.getExitCode()); + WorkItem wi = res.getWorkItem(siProject.getConfigurationPath()); + String chkpt = wi.getResult().getField("resultant").getItem().getId(); + listener.getLogger().println("Successfully executed pre-build checkpoint for project " + + siProject.getConfigurationPath() + ", new revision is " + chkpt); + // Update the siProject to use the new checkpoint as the basis for this build + IAPICommand command = new ProjectInfoCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); + command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath() + "#forceJump=#b=" + chkpt)); + + Response infoRes = command.execute(); + siProject.initializeProject(infoRes.getWorkItems().next()); + } + else + { + listener.getLogger().println("Cannot perform a pre-build checkpoint for build project configuration!"); + } } - + /** - * Returns the Integrity Configuration Management Project - * @return + * Overridden compareRemoteRevisionWith function + * that against the current to determine if the project has changed + * Loads up the previous project configuration and compares */ - public IntegrityCMProject getIntegrityProject() + @Override + public PollingResult compareRemoteRevisionWith(Job job, Launcher launcher, FilePath workspace, + TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException { - return findProject(configurationName); - } + // Log the call for now... + LOGGER.fine("compareRemoteRevisionWith() invoked...!"); - public static IntegrityCMProject findProject(String configurationName) - { - return hasProject(configurationName) ? projects.get(configurationName) : null; - } + // Lets get the baseline from our last build + if( null != baseline && baseline instanceof IntegrityRevisionState ) + { + IntegrityRevisionState irs = (IntegrityRevisionState) baseline; + String prevProjectCache = irs.getProjectCache(); + if( null != prevProjectCache && prevProjectCache.length() > 0 ) + { + // Compare the current project with the old revision state + LOGGER.fine("Found previous project state " + prevProjectCache); - public static boolean hasProject(String configurationName) - { - return projects.containsKey(configurationName); + // Next, load up the information for the current Integrity Project + // Lets start with creating an authenticated Integrity API Session for various parts of this operation... + try + { + // Get the project cache table name + String projectCacheTable = DerbyUtils.registerProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), job.getName(), configurationName, 0); + // Re-evaluate the config path to resolve any groovy expressions... + //listener.getLogger().println("Preparing to execute si projectinfo for " + resolvedConfigPath); + initializeCMProject(job.getCharacteristicEnvVars(), configPath); + //listener.getLogger().println("Preparing to execute si viewproject for " + resolvedConfigPath); + initializeCMProjectMembers(); + + // Compare this project with the old project + int changeCount = DerbyUtils.compareBaseline(serverConfig, prevProjectCache, projectCacheTable, skipAuthorInfo); + // Finally decide whether or not we need to build again + if( changeCount > 0 ) + { + listener.getLogger().println("Project contains changes a total of " + changeCount + " changes!"); + return PollingResult.SIGNIFICANT; + } + else + { + listener.getLogger().println("No new changes detected in project!"); + return PollingResult.NO_CHANGES; + } + } + catch(APIException aex) + { + LOGGER.severe("API Exception caught..."); + listener.getLogger().println("An API Exception was caught!"); + ExceptionHandler eh = new ExceptionHandler(aex); + LOGGER.severe(eh.getMessage()); + listener.getLogger().println(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + listener.getLogger().println(eh.getCommand() + " returned exit code " + eh.getExitCode()); + aex.printStackTrace(); + return PollingResult.NO_CHANGES; + } + catch(SQLException sqlex) + { + LOGGER.severe("SQL Exception caught..."); + listener.getLogger().println("A SQL Exception was caught!"); + listener.getLogger().println(sqlex.getMessage()); + LOGGER.log(Level.SEVERE, "SQLException", sqlex); + return PollingResult.NO_CHANGES; + } + } + else + { + // We've got no previous builds, build now! + LOGGER.fine("No prior Integrity Project state can be found! Advice to build now!"); + return PollingResult.BUILD_NOW; + } + } + else + { + // We've got no previous builds, build now! + LOGGER.fine("No prior Integrity Project state can be found! Advice to build now!"); + return PollingResult.BUILD_NOW; + } } - /** - * Adds Integrity CM Project info to the build variables - */ - @Override - public void buildEnvVars(AbstractBuild build, Map env) - { - super.buildEnvVars(build, env); - LOGGER.fine("buildEnvVars() invoked...!"); - IntegrityConfigurable ic = ((DescriptorImpl)this.getDescriptor()).getConfiguration(serverConfig); - - env.put("MKSSI_HOST", ic.getHostName()); - env.put("MKSSI_PORT", String.valueOf(ic.getPort())); - env.put("MKSSI_USER", userName); - - // Populate with information about the most recent checkpoint - IntegrityCMProject siProject = getIntegrityProject(); - if( null != siProject && siProject.isBuild() ) - { - env.put("MKSSI_PROJECT", siProject.getConfigurationPath()); - env.put("MKSSI_BUILD", siProject.getProjectRevision()); - } - } - - /** - * Overridden calcRevisionsFromBuild function - * Returns the current project configuration which can be used to difference any future configurations - */ - @Override - public SCMRevisionState calcRevisionsFromBuild(Run run, FilePath workspace, Launcher launcher, TaskListener listener) throws IOException, InterruptedException - { - // Log the call for debug purposes - LOGGER.fine("calcRevisionsFromBuild() invoked...!"); - // Get the project cache table name for this build - String projectCacheTable = null; - Job job = run.getParent(); - String jobName = job.getName(); - - try - { - projectCacheTable = DerbyUtils.getProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), - jobName, configurationName, run.getNumber()); - } - catch (SQLException sqlex) - { - LOGGER.severe("SQL Exception caught..."); - listener.getLogger().println("A SQL Exception was caught!"); - listener.getLogger().println(sqlex.getMessage()); - LOGGER.log(Level.SEVERE, "SQLException", sqlex); - } - return new IntegrityRevisionState(jobName, configurationName, projectCacheTable); - } - - /** - * Primes the Integrity Project metadata information - * @return response Integrity API Response - * @throws AbortException - * @throws APIException - */ - private Response initializeCMProject(String projectCacheTable, String resolvedConfigPath) throws APICommandException, AbortException - { - // Get the project information for this project - IAPICommand command = new ProjectInfoCommand(); - command.addOption(new APIOption(IAPIOption.PROJECT, resolvedConfigPath)); - - Response infoRes = command.execute(); - - LOGGER.fine(infoRes.getCommandString() + " returned " + APIUtils.getResponseExitCode(infoRes)); - // Initialize our siProject class variable - IntegrityCMProject siProject = new IntegrityCMProject(APIUtils.getWorkItem(infoRes), projectCacheTable); - // Set the project options - siProject.setLineTerminator(lineTerminator); - siProject.setRestoreTimestamp(restoreTimestamp); - siProject.setSkipAuthorInfo(skipAuthorInfo); - siProject.setCheckpointBeforeBuild(checkpointBeforeBuild); - projects.put(configurationName, siProject); - return infoRes; - } - - /** - * Utility function to parse the include/exclude filter - * @param command API Command for the 'si viewproject' command - * @return - */ - private void applyMemberFilters(IAPICommand command) - { - // Checking if our include list has any entries - if( null != includeList && includeList.length() > 0 ) - { - StringBuilder filterString = new StringBuilder(); - String[] filterTokens = includeList.split(",|;"); - // prepare a OR combination of include filters (all in one filter, separated by comma if needed) - for( int i = 0; i < filterTokens.length; i++ ) - { - filterString.append(i > 0 ? "," : ""); - filterString.append("file:"); - filterString.append(filterTokens[i]); - } - command.addOption(new APIOption(IAPIOption.FILTER, filterString.toString())); - } - - // Checking if our exclude list has any entries - if( null != excludeList && excludeList.length() > 0 ) - { - String[] filterTokens = excludeList.split(",|;"); - // prepare a AND combination of exclude filters (one filter each filter) - for( int i = 0; i < filterTokens.length; i++ ) - { - if (filterTokens[i]!= null) - { - command.addOption(new APIOption(IAPIOption.FILTER, "!file:"+filterTokens[i])); - } - } - } - } - - /** - * Primes the Integrity Project Member metadata information - * @return response Integrity API Response - * @throws APIException - * @throws SQLException - * @throws AbortException - */ - private Response initializeCMProjectMembers() throws APIException, SQLException, AbortException - { - IntegrityCMProject siProject = getIntegrityProject(); - // Lets parse this project - - IAPICommand command = new ViewProjectCommand(); - - command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath())); - APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"); - command.addOption(new APIOption(IAPIOption.FIELDS, APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"))); - - // Apply our include/exclude filters - applyMemberFilters(command); - - LOGGER.fine("Preparing to execute si viewproject for " + siProject.getConfigurationPath()); - Response viewRes = command.execute(); - - DerbyUtils.parseProject(siProject, viewRes.getWorkItems()); - return viewRes; - } - - /** - * Toggles whether or not the Integrity SCM plugin can be used for polling - */ - @Override - public boolean supportsPolling() - { - return true; - } - /** - * Toggles whether or not a workspace is required for polling - * Since, we're using a Server Integration Point in the Integrity API, - * we do not require a workspace. + * The relationship of Descriptor and SCM (the describable) is akin to class and object. + * This means the descriptor is used to create instances of the describable. + * Usually the Descriptor is an internal class in the SCM class named DescriptorImpl. + * The Descriptor should also contain the global configuration options as fields, + * just like the SCM class contains the configurations options for a job. */ - @Override - public boolean requiresWorkspaceForPolling() - { - return false; - } - - /** - * Overridden checkout function - * This is the real invocation of this plugin. - * Currently, we will do a project info and determine the true nature of the project - * Subsequent to that we will run a view project command and cache the information - * on each member, so that we can execute project checkout commands. This obviously - * eliminates the need for a sandbox and can wily nilly delete the workspace directory as needed - */ - @Override - public void checkout(Run run, Launcher launcher, FilePath workspace, - TaskListener listener, File changeLogFile, - SCMRevisionState baseline) throws IOException, InterruptedException - { - // Log the invocation... - LOGGER.fine("Start execution of checkout() routine...!"); - - // Re-evaluate the config path to resolve any groovy expressions... - String resolvedConfigPath = IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), configPath); - - // Provide links to the Change and Build logs for easy access from Integrity - listener.getLogger().println("Change Log: " + ciServerURL + run.getUrl() + "changes"); - listener.getLogger().println("Build Log: " + ciServerURL + run.getUrl() + "console"); - - // Lets start with creating an authenticated Integrity API Session for various parts of this operation... - IntegrityConfigurable desSettings = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig); - IntegrityConfigurable coSettings = new IntegrityConfigurable("TEMP_ID", desSettings.getIpHostName(), desSettings.getIpPort(), desSettings.getHostName(), - desSettings.getPort(), desSettings.getSecure(), userName, password.getPlainText()); - - // Initialize the API command framework - BasicAPICommand.setIntegritySettings(desSettings); - - // Lets also open the change log file for writing... - // Override file.encoding property so that we write as UTF-8 and do not have problems with special characters - PrintWriter writer = new PrintWriter(new OutputStreamWriter(new FileOutputStream(changeLogFile),"UTF-8")); - try - { - // Register the project cache for this build - Job job = run.getParent(); - String projectCacheTable = DerbyUtils.registerProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), - job.getName(), configurationName, run.getNumber()); - - // Next, load up the information for this Integrity Project's configuration - listener.getLogger().println("Preparing to execute si projectinfo for " + resolvedConfigPath); - initializeCMProject(projectCacheTable, resolvedConfigPath); - IntegrityCMProject siProject = getIntegrityProject(); - // Check to see we need to checkpoint before the build - if( checkpointBeforeBuild ) - { - // Make sure we don't have a build project configuration - if( ! siProject.isBuild() ) - { - // Execute a pre-build checkpoint... - listener.getLogger().println("Preparing to execute pre-build si checkpoint for " + siProject.getConfigurationPath()); - Response res = siProject.checkpoint(IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), checkpointLabel)); - LOGGER.fine(res.getCommandString() + " returned " + res.getExitCode()); - WorkItem wi = res.getWorkItem(siProject.getConfigurationPath()); - String chkpt = wi.getResult().getField("resultant").getItem().getId(); - listener.getLogger().println("Successfully executed pre-build checkpoint for project " + - siProject.getConfigurationPath() + ", new revision is " + chkpt); - // Update the siProject to use the new checkpoint as the basis for this build - IAPICommand command = new ProjectInfoCommand(); - command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath() + "#forceJump=#b=" + chkpt)); - - Response infoRes = command.execute(); - siProject.initializeProject(infoRes.getWorkItems().next()); - } - else - { - listener.getLogger().println("Cannot perform a pre-build checkpoint for build project configuration!"); - } - } - listener.getLogger().println("Preparing to execute si viewproject for " + siProject.getConfigurationPath()); - initializeCMProjectMembers(); - - // Now, we need to find the project state from the previous build. - String prevProjectCache = null; - if( null != baseline && baseline instanceof IntegrityRevisionState ) - { - IntegrityRevisionState irs = (IntegrityRevisionState)baseline; - prevProjectCache = irs.getProjectCache(); - - if( null != prevProjectCache && prevProjectCache.length() > 0 ) - { - // Compare the current project with the old revision state - LOGGER.fine("Found previous project state " + prevProjectCache); - DerbyUtils.compareBaseline(prevProjectCache, projectCacheTable, skipAuthorInfo); - } - } - else - { - // We don't have the previous Integrity Revision State! - LOGGER.fine("Cannot construct previous Integrity Revision State!"); - // Prime the author information for the current build as this could be the first build - if( ! skipAuthorInfo ){ DerbyUtils.primeAuthorInformation(projectCacheTable); } - } - - // After all that insane interrogation, we have the current Project state that is - // correctly initialized and either compared against its baseline or is a fresh baseline itself - // Now, lets figure out how to populate the workspace... - List> projectMembersList = DerbyUtils.viewProject(projectCacheTable); - List dirList = DerbyUtils.getDirList(projectCacheTable); - String resolvedAltWkspace = IntegrityCheckpointAction.evalGroovyExpression(run.getEnvironment(listener), alternateWorkspace); - // If we we were not able to establish the previous project state, then always do full checkout. cleanCopy = true - // Otherwise, update the workspace in accordance with the user's cleanCopy option - - // ANURAG : construct command objects in this class and pass them below - - IntegrityCheckoutTask coTask = new IntegrityCheckoutTask(projectMembersList, dirList, resolvedAltWkspace, lineTerminator, restoreTimestamp, - ((null == prevProjectCache || prevProjectCache.length() == 0) ? true : cleanCopy), - fetchChangedWorkspaceFiles,checkoutThreadPoolSize, listener, coSettings); - - // Execute the IntegrityCheckoutTask.invoke() method to do the actual synchronization... - if( workspace.act(coTask) ) - { - // Now that the workspace is updated, lets save the current project state for future comparisons - listener.getLogger().println("Saving current Integrity Project configuration..."); - if( fetchChangedWorkspaceFiles ){ DerbyUtils.updateChecksum(projectCacheTable, coTask.getChecksumUpdates()); } - // Write out the change log file, which will be used by the parser to report the updates - listener.getLogger().println("Writing build change log..."); - writer.println(siProject.getChangeLog(String.valueOf(run.getNumber()), projectMembersList)); - listener.getLogger().println("Change log successfully generated: " + changeLogFile.getAbsolutePath()); - // Delete non-members in this workspace, if appropriate... - if( deleteNonMembers ) - { - - IntegrityDeleteNonMembersTask deleteNonMembers = new IntegrityDeleteNonMembersTask(listener, resolvedAltWkspace, projectMembersList, dirList); - if( ! workspace.act(deleteNonMembers) ) - { - throw new AbortException("Failed to delete non-members!"); - } - } - } - else - { - // Checkout failed! Returning false... - throw new AbortException("Failed to synchronize workspace!"); - } - } - catch(APIException aex) - { - LOGGER.severe("API Exception caught..."); - listener.getLogger().println("An API Exception was caught!"); - ExceptionHandler eh = new ExceptionHandler(aex); - LOGGER.severe(eh.getMessage()); - listener.getLogger().println(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); - listener.getLogger().println(eh.getCommand() + " returned exit code " + eh.getExitCode()); - - throw new AbortException("Caught Integrity APIException!"); - } - catch(SQLException sqlex) - { - LOGGER.severe("SQL Exception caught..."); - listener.getLogger().println("A SQL Exception was caught!"); - listener.getLogger().println(sqlex.getMessage()); - LOGGER.log(Level.SEVERE, "SQLException", sqlex); - - throw new AbortException("Caught Derby SQLException!"); - } - finally - { - if( writer != null ) - { - writer.close(); - } - } - - // Log the completion... - LOGGER.fine("Completed execution of checkout() routine...!"); - } - - - - /** - * Overridden compareRemoteRevisionWith function - * Loads up the previous project configuration and compares - * that against the current to determine if the project has changed - */ - @Override - public PollingResult compareRemoteRevisionWith(Job job, Launcher launcher, FilePath workspace, - TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException - { - // Log the call for now... - LOGGER.fine("compareRemoteRevisionWith() invoked...!"); - - // Lets get the baseline from our last build - if( null != baseline && baseline instanceof IntegrityRevisionState ) - { - IntegrityRevisionState irs = (IntegrityRevisionState) baseline; - String prevProjectCache = irs.getProjectCache(); - if( null != prevProjectCache && prevProjectCache.length() > 0 ) - { - // Compare the current project with the old revision state - LOGGER.fine("Found previous project state " + prevProjectCache); - - // Next, load up the information for the current Integrity Project - // Lets start with creating an authenticated Integrity API Session for various parts of this operation... - IntegrityConfigurable desSettings = DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig); - IntegrityConfigurable coSettings = new IntegrityConfigurable("TEMP_ID", desSettings.getIpHostName(), desSettings.getIpPort(), desSettings.getHostName(), - desSettings.getPort(), desSettings.getSecure(), userName, password.getPlainText()); - APISession api = APISession.create(coSettings); - if( null != api ) - { - try - { - // Get the project cache table name - String projectCacheTable = DerbyUtils.registerProjectCache(((DescriptorImpl)this.getDescriptor()).getDataSource(), job.getName(), configurationName, 0); - // Re-evaluate the config path to resolve any groovy expressions... - String resolvedConfigPath = IntegrityCheckpointAction.evalGroovyExpression(job.getCharacteristicEnvVars(), configPath); - listener.getLogger().println("Preparing to execute si projectinfo for " + resolvedConfigPath); - initializeCMProject(projectCacheTable, resolvedConfigPath); - listener.getLogger().println("Preparing to execute si viewproject for " + resolvedConfigPath); - initializeCMProjectMembers(); - - // Compare this project with the old project - int changeCount = DerbyUtils.compareBaseline(prevProjectCache, projectCacheTable, skipAuthorInfo); - // Finally decide whether or not we need to build again - if( changeCount > 0 ) - { - listener.getLogger().println("Project contains changes a total of " + changeCount + " changes!"); - return PollingResult.SIGNIFICANT; - } - else - { - listener.getLogger().println("No new changes detected in project!"); - return PollingResult.NO_CHANGES; - } - } - catch(APIException aex) - { - LOGGER.severe("API Exception caught..."); - listener.getLogger().println("An API Exception was caught!"); - ExceptionHandler eh = new ExceptionHandler(aex); - LOGGER.severe(eh.getMessage()); - listener.getLogger().println(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); - listener.getLogger().println(eh.getCommand() + " returned exit code " + eh.getExitCode()); - aex.printStackTrace(); - return PollingResult.NO_CHANGES; - } - catch(SQLException sqlex) - { - LOGGER.severe("SQL Exception caught..."); - listener.getLogger().println("A SQL Exception was caught!"); - listener.getLogger().println(sqlex.getMessage()); - LOGGER.log(Level.SEVERE, "SQLException", sqlex); - return PollingResult.NO_CHANGES; - } - finally - { - api.terminate(); - } - } - else - { - listener.getLogger().println("Failed to establish an API connection to the Integrity Server!"); - return PollingResult.NO_CHANGES; - } - } - else - { - // We've got no previous builds, build now! - LOGGER.fine("No prior Integrity Project state can be found! Advice to build now!"); - return PollingResult.BUILD_NOW; - } - } - else - { - // We've got no previous builds, build now! - LOGGER.fine("No prior Integrity Project state can be found! Advice to build now!"); - return PollingResult.BUILD_NOW; - } - } - - /** - * Overridden createChangeLogParser function - * Creates a custom Integrity Change Log Parser, which compares two view project outputs - * @see hudson.scm.SCM#createChangeLogParser() - */ - @Override - public ChangeLogParser createChangeLogParser() - { - // Log the call - LOGGER.fine("createChangeLogParser() invoked...!"); - return new IntegrityChangeLogParser(integrityURL); - } - - /** - * Returns the SCMDescriptor for the SCM object. - * The SCMDescriptor is used to create new instances of the SCM. - */ - @Override - public DescriptorImpl getDescriptor() - { - // Log the call - LOGGER.fine("IntegritySCM.getDescriptor() invoked...!"); - return DescriptorImpl.INTEGRITY_DESCRIPTOR; - } - - /** - * The relationship of Descriptor and SCM (the describable) is akin to class and object. - * This means the descriptor is used to create instances of the describable. - * Usually the Descriptor is an internal class in the SCM class named DescriptorImpl. - * The Descriptor should also contain the global configuration options as fields, - * just like the SCM class contains the configurations options for a job. - */ - public static final class DescriptorImpl extends SCMDescriptor implements ModelObject - { - @Extension - public static final DescriptorImpl INTEGRITY_DESCRIPTOR = new DescriptorImpl(); - private ConnectionPoolDataSource dataSource; - private List configurations; - + public static final class DescriptorImpl extends SCMDescriptor implements ModelObject + { + @Extension + public static final DescriptorImpl INTEGRITY_DESCRIPTOR = new DescriptorImpl(); + private ConnectionPoolDataSource dataSource; + private List configurations; + public DescriptorImpl() { - super(IntegritySCM.class, IntegrityWebUI.class); - configurations = new ArrayList(); - load(); - - // Initialize our derby environment - System.setProperty(DerbyUtils.DERBY_SYS_HOME_PROPERTY, Jenkins.getInstance().getRootDir().getAbsolutePath());; - DerbyUtils.loadDerbyDriver(); - LOGGER.info("Creating Integrity SCM cache db connection..."); - dataSource = DerbyUtils.createConnectionPoolDataSource(Jenkins.getInstance().getRootDir().getAbsolutePath()); - LOGGER.info("Creating Integrity SCM cache registry..."); - DerbyUtils.createRegistry(dataSource); - - // Log the construction... - LOGGER.fine("IntegritySCM DescriptorImpl() constructed!"); + super(IntegritySCM.class, IntegrityWebUI.class); + configurations = new ArrayList(); + load(); + + // Initialize our derby environment + System.setProperty(DerbyUtils.DERBY_SYS_HOME_PROPERTY, Jenkins.getInstance().getRootDir().getAbsolutePath());; + DerbyUtils.loadDerbyDriver(); + LOGGER.info("Creating Integrity SCM cache db connection..."); + dataSource = DerbyUtils.createConnectionPoolDataSource(Jenkins.getInstance().getRootDir().getAbsolutePath()); + LOGGER.info("Creating Integrity SCM cache registry..."); + DerbyUtils.createRegistry(dataSource); + + // Log the construction... + LOGGER.fine("IntegritySCM DescriptorImpl() constructed!"); } @Override @@ -1105,29 +642,29 @@ public SCM newInstance(StaplerRequest req, JSONObject formData) throws FormExcep * Returns the name of the SCM, this is the name that will show up next to * CVS, Subversion, etc. when configuring a job. */ - @Override - public String getDisplayName() - { - return "Integrity"; - } - - /** - * This method is invoked when the global configuration page is submitted. - * In the method the data in the web form should be copied to the Descriptor's fields. - * To persist the fields to the global configuration XML file, the save() method must be called. - * Data is defined in the global.jelly page. - */ + @Override + public String getDisplayName() + { + return "Integrity"; + } + + /** + * This method is invoked when the global configuration page is submitted. + * In the method the data in the web form should be copied to the Descriptor's fields. + * To persist the fields to the global configuration XML file, the save() method must be called. + * Data is defined in the global.jelly page. + */ @Override public boolean configure(StaplerRequest req, JSONObject formData) throws FormException { - // Log the request to configure - LOGGER.fine("Request to configure IntegritySCM (SCMDescriptor) invoked..."); - this.configurations = req.bindJSONToList(IntegrityConfigurable.class, formData.get("serverConfig")); - save(); + // Log the request to configure + LOGGER.fine("Request to configure IntegritySCM (SCMDescriptor) invoked..."); + this.configurations = req.bindJSONToList(IntegrityConfigurable.class, formData.get("serverConfig")); + save(); return true; } - @Override + @Override public boolean isApplicable(@SuppressWarnings("rawtypes") Job project) { return true; @@ -1169,79 +706,79 @@ public String getConfigurationName() return UUID.randomUUID().toString(); } - /** - * Returns the list of Integrity Server connections. - * @return A list of IntegrityConfigurable objects. - */ - public List getConfigurations() + /** + * Returns the list of Integrity Server connections. + * @return A list of IntegrityConfigurable objects. + */ + public List getConfigurations() + { + if( null == this.configurations ) { - if( null == this.configurations ) - { - this.configurations = new ArrayList(); - } - - return this.configurations; + this.configurations = new ArrayList(); } + + return this.configurations; + } - /** - * Sets the list of Integrity Server connections. - * @param configurations A list of IntegrityConfigurable objects. - */ - public void setConfigurations(List configurations) - { - this.configurations = configurations; - } + /** + * Sets the list of Integrity Server connections. + * @param configurations A list of IntegrityConfigurable objects. + */ + public void setConfigurations(List configurations) + { + this.configurations = configurations; + } - /** - * Return the IntegrityConfigurable object for the specified simple name - * @param name - * @return - */ - public IntegrityConfigurable getConfiguration(String name) + /** + * Return the IntegrityConfigurable object for the specified simple name + * @param name + * @return + */ + public IntegrityConfigurable getConfiguration(String name) + { + for(IntegrityConfigurable configuration : this.configurations ) { - for(IntegrityConfigurable configuration : this.configurations ) - { - if( name.equals(configuration.getConfigId()) ) - { - return configuration; - } + if( name.equals(configuration.getConfigId()) ) + { + return configuration; } - - return null; } - - /** - * Provides a list box for users to choose from a list of Integrity Server configurations - * @param configuration Simple configuration name - * @return - */ - public ListBoxModel doFillServerConfigItems(@QueryParameter String serverConfig) - { - ListBoxModel listBox = new ListBoxModel(); - - if( null != this.configurations && this.configurations.size() > 0 ) - { - for( IntegrityConfigurable config : this.configurations ) - { - listBox.add(config.getName(), config.getConfigId()); - } - } - return listBox; - } - /** - * A credentials validation helper - * @param hostName - * @param port - * @param userName - * @param password - * @param secure - * @param ipHostName - * @param ipPort - * @return - * @throws IOException - * @throws ServletException - */ + return null; + } + + /** + * Provides a list box for users to choose from a list of Integrity Server configurations + * @param configuration Simple configuration name + * @return + */ + public ListBoxModel doFillServerConfigItems(@QueryParameter String serverConfig) + { + ListBoxModel listBox = new ListBoxModel(); + + if( null != this.configurations && this.configurations.size() > 0 ) + { + for( IntegrityConfigurable config : this.configurations ) + { + listBox.add(config.getName(), config.getConfigId()); + } + } + return listBox; + } + + /** + * A credentials validation helper + * @param hostName + * @param port + * @param userName + * @param password + * @param secure + * @param ipHostName + * @param ipPort + * @return + * @throws IOException + * @throws ServletException + */ public FormValidation doTestConnection(@QueryParameter("serverConfig.hostName") final String hostName, @QueryParameter("serverConfig.port") final int port, @QueryParameter("serverConfig.userName") final String userName, @@ -1249,7 +786,7 @@ public FormValidation doTestConnection(@QueryParameter("serverConfig.hostName") @QueryParameter("serverConfig.secure") final boolean secure, @QueryParameter("serverConfig.ipHostName") final String ipHostName, @QueryParameter("serverConfig.ipPort") final int ipPort) throws IOException, ServletException - { + { LOGGER.fine("Testing Integrity API Connection..."); LOGGER.fine("hostName: " + hostName); LOGGER.fine("port: " + port); @@ -1259,25 +796,25 @@ public FormValidation doTestConnection(@QueryParameter("serverConfig.hostName") LOGGER.fine("ipHostName: " + ipHostName); LOGGER.fine("ipPort: " + ipPort); - IntegrityConfigurable ic = new IntegrityConfigurable("TEMP_ID", ipHostName, ipPort, hostName, port, secure, userName, password); - APISession api = APISession.create(ic); - if( null != api ) - { - api.terminate(); - return FormValidation.ok("Connection successful!"); - } - else - { - return FormValidation.error("Failed to establish connection!"); - } - } - - /** - * Validates that the thread pool size is numeric and within a valid range - * @param value Integer value for Thread Pool Size - * @return - */ - public FormValidation doValidCheckoutThreadPoolSizeCheck(@QueryParameter String value) + IntegrityConfigurable ic = new IntegrityConfigurable("TEMP_ID", ipHostName, ipPort, hostName, port, secure, userName, password); + APISession api = APISession.create(ic); + if( null != api ) + { + api.terminate(); + return FormValidation.ok("Connection successful!"); + } + else + { + return FormValidation.error("Failed to establish connection!"); + } + } + + /** + * Validates that the thread pool size is numeric and within a valid range + * @param value Integer value for Thread Pool Size + * @return + */ + public FormValidation doValidCheckoutThreadPoolSizeCheck(@QueryParameter String value) { // The field checkoutThreadPoolSize will be validated through the checkUrl. // When the user has entered some information and moves the focus away from field, @@ -1286,7 +823,7 @@ public FormValidation doValidCheckoutThreadPoolSizeCheck(@QueryParameter String { int intValue = Integer.parseInt(value); if(intValue < 1 || intValue > 10) - { + { return FormValidation.error("Thread pool size must be between 1 an 10"); } } diff --git a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java index 618087f..ba724ea 100644 --- a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java @@ -10,7 +10,6 @@ import hudson.Launcher; import hudson.model.Run; import hudson.model.TaskListener; -import hudson.scm.api.APISession; import hudson.scm.api.ExceptionHandler; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; @@ -46,10 +45,6 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi listener.getLogger().println("Change Package ID will be derived from '" + itemID + "' supplied..."); String buildID = run.getFullDisplayName(); - // Open our connection to the Integrity Server - APISession api = APISession.create(ciSettings); - if( null != api ) - { try { // Determine what files need to be checked-in @@ -57,7 +52,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi if( artifacts.length > 0 ) { // Create our Change Package for the supplied itemID - String cpid = IntegrityCMMember.createCP(api, itemID, "Build updates from " + buildID); + String cpid = IntegrityCMMember.createCP(ciSettings, itemID, "Build updates from " + buildID); for( int i = 0; i < artifacts.length; i++ ) { FilePath member = artifacts[i]; @@ -66,18 +61,18 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi // This is not a recursive directory tree check-in, only process files found if( !member.isDirectory() ) { - IntegrityCMMember.updateMember(api, configPath, member, relativePath, cpid, "Build updates from " + buildID); + IntegrityCMMember.updateMember(ciSettings, configPath, member, relativePath, cpid, "Build updates from " + buildID); } } // Finally submit the build updates Change Package if its not :none or :bypass if( !cpid.equals(":none") && !cpid.equals(":bypass") ) { - IntegrityCMMember.submitCP(api, cpid); + IntegrityCMMember.submitCP(ciSettings, cpid); } else { - IntegrityCMMember.unlockMembers(api, configPath); + IntegrityCMMember.unlockMembers(ciSettings, configPath); } // Log the success @@ -104,18 +99,5 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); LOGGER.log(Level.SEVERE, "APIException", aex); } - finally - { - if( null != api ) - { - api.terminate(); - } - } - } - else - { - listener.getLogger().println("Failed to establish connection with Integrity for check-in step!"); - listener.getLogger().println("Failed to update Integrity project '" + configPath + "' with contents of workspace (" + workspace + ")!"); - } } } diff --git a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java index 3e0a70a..5b3a992 100644 --- a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java @@ -3,13 +3,14 @@ import java.io.IOException; import java.util.logging.Logger; +import com.mks.api.response.APIException; + import hudson.FilePath; import hudson.Launcher; import hudson.model.Run; import hudson.model.TaskListener; import hudson.scm.api.APISession; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.command.APICommandException; import hudson.scm.api.command.CheckPointCommand; import hudson.scm.api.command.IAPICommand; import hudson.scm.api.option.APIOption; @@ -42,23 +43,21 @@ public BuildStepMonitor getRequiredMonitorService() public void perform(Run run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { - APISession api = APISession.create(ciSettings); - if( null != api ) { listener.getLogger().println("Preparing to execute si checkpoint for project " + configPath); try { // Construct the checkpoint command - IAPICommand command = new CheckPointCommand(); + IAPICommand command = new CheckPointCommand(ciSettings); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, checkpointLabel); command.addAdditionalParameters(IAPIOption.CHECKPOINT_DESCRIPTION, checkpointDesc); - command.execute(api); + command.execute(); listener.getLogger().println("Successfully checkpointed project " + configPath); } - catch (APICommandException aex) + catch (APIException aex) { LOGGER.severe("API Exception caught..."); ExceptionHandler eh = new ExceptionHandler(aex); @@ -66,14 +65,6 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi LOGGER.severe(eh.getMessage()); LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); } - finally - { - api.terminate(); - } - } - else - { - listener.getLogger().println("Failed to establish connection with Integrity!"); } } } diff --git a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java index 7209dcc..6d47c8e 100644 --- a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java @@ -3,13 +3,13 @@ import java.io.IOException; import java.util.logging.Logger; +import com.mks.api.response.APIException; + import hudson.FilePath; import hudson.Launcher; import hudson.model.Run; import hudson.model.TaskListener; -import hudson.scm.api.APISession; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.command.APICommandException; import hudson.scm.api.command.AddProjectLabelCommand; import hudson.scm.api.command.IAPICommand; import hudson.scm.api.option.APIOption; @@ -21,7 +21,7 @@ @SuppressWarnings("unchecked") public class IntegritySCMLabelNotifierStep extends Notifier implements SimpleBuildStep { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private final IntegrityConfigurable ciSettings; private final String configPath; private final String checkpointLabel; @@ -40,37 +40,26 @@ public BuildStepMonitor getRequiredMonitorService() public void perform(Run run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException { - APISession api = APISession.create(ciSettings); - if( null != api ) - { - listener.getLogger().println("Preparing to execute si addprojectlabel for " + configPath); - try - { - // Assumes the checkpoint was done before the build, so lets apply the label now - IAPICommand command = new AddProjectLabelCommand(); - command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); - command.addOption(new APIOption(IAPIOption.LABEL, checkpointLabel)); - - command.execute(api); - - listener.getLogger().println("Successfully added label " + checkpointLabel); - } - catch (APICommandException aex) - { - LOGGER.severe("API Exception caught..."); - ExceptionHandler eh = new ExceptionHandler(aex); - aex.printStackTrace(listener.fatalError(eh.getMessage())); - LOGGER.severe(eh.getMessage()); - LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); - } - finally - { - api.terminate(); - } - } - else - { - listener.getLogger().println("Failed to establish connection with Integrity!"); - } + listener.getLogger().println("Preparing to execute si addprojectlabel for " + configPath); + try + { + // Assumes the checkpoint was done before the build, so lets apply the label now + IAPICommand command = new AddProjectLabelCommand(ciSettings); + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + command.addOption(new APIOption(IAPIOption.LABEL, checkpointLabel)); + + command.execute(); + + listener.getLogger().println("Successfully added label " + checkpointLabel); + } + catch (APIException aex) + { + LOGGER.severe("API Exception caught..."); + ExceptionHandler eh = new ExceptionHandler(aex); + aex.printStackTrace(listener.fatalError(eh.getMessage())); + LOGGER.severe(eh.getMessage()); + LOGGER.fine(eh.getCommand() + " returned exit code " + eh.getExitCode()); + } + } } diff --git a/src/main/java/hudson/scm/api/APIUtils.java b/src/main/java/hudson/scm/api/APIUtils.java index 0f47d19..62296e5 100644 --- a/src/main/java/hudson/scm/api/APIUtils.java +++ b/src/main/java/hudson/scm/api/APIUtils.java @@ -9,11 +9,9 @@ import com.mks.api.MultiValue; import com.mks.api.response.APIException; -import com.mks.api.response.InterruptedException; import com.mks.api.response.Response; import com.mks.api.response.WorkItem; -import hudson.scm.api.command.APICommandException; import hudson.scm.api.option.IAPIOption; /** @@ -42,28 +40,9 @@ public static MultiValue createMultiValueField(String separator, String... param return mvFields; } - - /** - * @param response - * @return - * @throws APICommandException - */ - public static int getResponseExitCode(Response response) throws APICommandException - { - try { - return response.getExitCode(); - } catch (InterruptedException e) { - throw new APICommandException(e); - } - } - - public static WorkItem getWorkItem(Response response) throws APICommandException + public static WorkItem getWorkItem(Response response) throws APIException { - try { - return response.getWorkItems().next(); - } catch (APIException e) { - throw new APICommandException(e); - } + return response.getWorkItems().next(); } /** diff --git a/src/main/java/hudson/scm/api/command/APICommandException.java b/src/main/java/hudson/scm/api/command/APICommandException.java deleted file mode 100644 index c5e8525..0000000 --- a/src/main/java/hudson/scm/api/command/APICommandException.java +++ /dev/null @@ -1,31 +0,0 @@ -/** - * - */ -package hudson.scm.api.command; - -import com.mks.api.response.APIException; - -/** - * @author asen - * - */ -public class APICommandException extends APIException { - - private static final long serialVersionUID = -7355644672829917075L; - - public APICommandException() - { - super(); - } - - public APICommandException(final String message) - { - super(message); - } - - public APICommandException(final Throwable error) - { - super(error); - } - -} diff --git a/src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java b/src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java index c39f99b..3b78713 100644 --- a/src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java +++ b/src/main/java/hudson/scm/api/command/AddProjectLabelCommand.java @@ -9,6 +9,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -19,8 +20,9 @@ */ public class AddProjectLabelCommand extends BasicAPICommand { - public AddProjectLabelCommand() + public AddProjectLabelCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, ADD_PROJECT_LABEL_COMMAND); // Initialize defaults diff --git a/src/main/java/hudson/scm/api/command/BasicAPICommand.java b/src/main/java/hudson/scm/api/command/BasicAPICommand.java index c69b026..87dafb3 100644 --- a/src/main/java/hudson/scm/api/command/BasicAPICommand.java +++ b/src/main/java/hudson/scm/api/command/BasicAPICommand.java @@ -8,6 +8,7 @@ package hudson.scm.api.command; import java.util.Map; +import java.util.logging.Logger; import com.mks.api.Command; import com.mks.api.Option; @@ -16,10 +17,10 @@ import hudson.AbortException; import hudson.scm.IntegrityConfigurable; +import hudson.scm.IntegritySCM; import hudson.scm.api.APISession; import hudson.scm.api.ISession; import hudson.scm.api.option.IAPIOption; -import hudson.util.StreamTaskListener; /** * All Jenkins Integrity API Commands have to extend this class in order to execute Integrity API calls using the default method @@ -29,22 +30,36 @@ */ public abstract class BasicAPICommand implements IAPICommand { + protected static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); protected Command cmd; protected Map commandHelperObjects; protected Response res; protected boolean runCommandWithInterim = false; - private static IntegrityConfigurable icSettings; + private IntegrityConfigurable serverConfig; + /** + * Constructor initialized with serverconfig id for commands to fire to a particular Integrity server + * @param serverConfig + */ + public BasicAPICommand(IntegrityConfigurable serverConfig) + { + this.serverConfig = serverConfig; + } + + public BasicAPICommand() + { + // Do Nothing + } /* (non-Javadoc) * @see hudson.scm.api.APICommand#execute(hudson.scm.api.APISession) */ @Override - public Response execute(ISession api) throws APICommandException + public Response execute(ISession api) throws APIException { if(null == cmd) - throw new APICommandException("Integration API Command cannot be null"); + throw new APIException("Integration API Command cannot be null"); try { @@ -64,8 +79,6 @@ public Response execute(ISession api) throws APICommandException } } - } catch (APIException e) { - throw new APICommandException(e); } finally { api.terminate(); } @@ -77,22 +90,18 @@ public Response execute(ISession api) throws APICommandException * @see hudson.scm.api.command.IAPICommand#execute() */ @Override - public Response execute() throws APICommandException, AbortException + public Response execute() throws APIException, AbortException { - IntegrityConfigurable coSettings = new IntegrityConfigurable("TEMP_ID", icSettings.getIpHostName(), icSettings.getIpPort(), icSettings.getHostName(), - icSettings.getPort(), icSettings.getSecure(), icSettings.getUserName(), icSettings.getPasswordInPlainText()); - - ISession api = APISession.create(coSettings); - - // Ensure we've successfully created an API Session - if( null == api ) - { - StreamTaskListener task = StreamTaskListener.fromStdout(); - task.getLogger().println("Failed to establish an API connection to the Integrity Server!"); - throw new AbortException("Connection Failed!"); - } - - return execute(api); + ISession api = APISession.create(serverConfig); + + // Ensure we've successfully created an API Session + if( null == api ) + { + LOGGER.severe("An Integrity API Session could not be established! Cannot perform "+cmd.getCommandName()+" operation"); + throw new AbortException("An Integrity API Session could not be established! Cannot perform "+cmd.getCommandName()+" operation"); + } + + return execute(api); } @Override @@ -134,9 +143,4 @@ public void addAdditionalParameters(String paramName, Object param) commandHelperObjects.put(paramName, param); } - public static void setIntegritySettings(IntegrityConfigurable desSettings) - { - icSettings = desSettings; - } - } diff --git a/src/main/java/hudson/scm/api/command/CheckPointCommand.java b/src/main/java/hudson/scm/api/command/CheckPointCommand.java index 8a2e59a..0155623 100644 --- a/src/main/java/hudson/scm/api/command/CheckPointCommand.java +++ b/src/main/java/hudson/scm/api/command/CheckPointCommand.java @@ -13,6 +13,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -23,8 +24,9 @@ */ public class CheckPointCommand extends BasicAPICommand { - public CheckPointCommand() + public CheckPointCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, CHECKPOINT_COMMAND); commandHelperObjects = new HashMap(); } diff --git a/src/main/java/hudson/scm/api/command/CloseCPCommand.java b/src/main/java/hudson/scm/api/command/CloseCPCommand.java index bef393a..b2f604c 100644 --- a/src/main/java/hudson/scm/api/command/CloseCPCommand.java +++ b/src/main/java/hudson/scm/api/command/CloseCPCommand.java @@ -9,6 +9,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -19,8 +20,9 @@ */ public class CloseCPCommand extends BasicAPICommand { - public CloseCPCommand() + public CloseCPCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, CLOSE_CP_COMMAND); // Initialize defaults diff --git a/src/main/java/hudson/scm/api/command/CreateCPCommand.java b/src/main/java/hudson/scm/api/command/CreateCPCommand.java index de54633..f9c3294 100644 --- a/src/main/java/hudson/scm/api/command/CreateCPCommand.java +++ b/src/main/java/hudson/scm/api/command/CreateCPCommand.java @@ -9,6 +9,8 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; + /** * * @author Author: asen @@ -16,8 +18,9 @@ */ public class CreateCPCommand extends BasicAPICommand { - public CreateCPCommand() + public CreateCPCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, CREATE_CP_COMMAND); } diff --git a/src/main/java/hudson/scm/api/command/IAPICommand.java b/src/main/java/hudson/scm/api/command/IAPICommand.java index bdcb510..9e02c31 100644 --- a/src/main/java/hudson/scm/api/command/IAPICommand.java +++ b/src/main/java/hudson/scm/api/command/IAPICommand.java @@ -1,5 +1,6 @@ package hudson.scm.api.command; +import com.mks.api.response.APIException; import com.mks.api.response.Response; import hudson.AbortException; @@ -37,7 +38,7 @@ public interface IAPICommand * Execute the command using Integrity Session API * @param api */ - public Response execute(ISession api) throws APICommandException; + public Response execute(ISession api) throws APIException; /** * Execute the command using an auto-generated Integrity Session API @@ -45,7 +46,7 @@ public interface IAPICommand * @throws APICommandException * @throws AbortException */ - public Response execute() throws APICommandException, AbortException; + public Response execute() throws APIException, AbortException; /** * Do actions post the Integrity API call specifically for Jenkins functionality diff --git a/src/main/java/hudson/scm/api/command/LockCommand.java b/src/main/java/hudson/scm/api/command/LockCommand.java index ce8080f..efa29ec 100644 --- a/src/main/java/hudson/scm/api/command/LockCommand.java +++ b/src/main/java/hudson/scm/api/command/LockCommand.java @@ -9,6 +9,8 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; + /** * * @author Author: asen @@ -16,8 +18,9 @@ */ public class LockCommand extends BasicAPICommand { - public LockCommand() + public LockCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, LOCK_COMMAND); } } diff --git a/src/main/java/hudson/scm/api/command/ProjectAddCommand.java b/src/main/java/hudson/scm/api/command/ProjectAddCommand.java index fd1df1b..8c7e3dc 100644 --- a/src/main/java/hudson/scm/api/command/ProjectAddCommand.java +++ b/src/main/java/hudson/scm/api/command/ProjectAddCommand.java @@ -9,6 +9,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -19,8 +20,9 @@ */ public class ProjectAddCommand extends BasicAPICommand { - public ProjectAddCommand() + public ProjectAddCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, PROJECT_ADD_COMMAND); // Initialize defaults diff --git a/src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java b/src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java index ca1f86b..f1a635a 100644 --- a/src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java +++ b/src/main/java/hudson/scm/api/command/ProjectCheckinCommand.java @@ -9,6 +9,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -19,8 +20,9 @@ */ public class ProjectCheckinCommand extends BasicAPICommand { - public ProjectCheckinCommand() + public ProjectCheckinCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, PROJECT_CHECKIN_COMMAND); // Initialize defaults diff --git a/src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java b/src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java index bd46843..b7c2bee 100644 --- a/src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java +++ b/src/main/java/hudson/scm/api/command/ProjectCheckoutCommand.java @@ -20,6 +20,7 @@ public class ProjectCheckoutCommand extends BasicAPICommand public ProjectCheckoutCommand() { + //super(serverConfig); cmd = new Command(Command.SI, PROJECT_CHECKOUT_COMMAND); commandHelperObjects = new HashMap(); diff --git a/src/main/java/hudson/scm/api/command/ProjectInfoCommand.java b/src/main/java/hudson/scm/api/command/ProjectInfoCommand.java index 3f652ee..acaeb6e 100644 --- a/src/main/java/hudson/scm/api/command/ProjectInfoCommand.java +++ b/src/main/java/hudson/scm/api/command/ProjectInfoCommand.java @@ -9,6 +9,8 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; + /** * Project Info command for the Integrity Jenkins Plugin * @author Author: asen @@ -17,8 +19,9 @@ public class ProjectInfoCommand extends BasicAPICommand { - public ProjectInfoCommand() + public ProjectInfoCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, PROJECT_INFO_COMMAND); } diff --git a/src/main/java/hudson/scm/api/command/RevisionInfoCommand.java b/src/main/java/hudson/scm/api/command/RevisionInfoCommand.java index 7ef38a8..0c0970d 100644 --- a/src/main/java/hudson/scm/api/command/RevisionInfoCommand.java +++ b/src/main/java/hudson/scm/api/command/RevisionInfoCommand.java @@ -9,6 +9,8 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; + /** * Revision Info command for the Integrity Jenkins Plugin * @@ -17,8 +19,9 @@ */ public class RevisionInfoCommand extends BasicAPICommand { - public RevisionInfoCommand() + public RevisionInfoCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, REVISION_INFO_COMMAND); } diff --git a/src/main/java/hudson/scm/api/command/SubmitCPCommand.java b/src/main/java/hudson/scm/api/command/SubmitCPCommand.java index 3e30c50..f5f7c3a 100644 --- a/src/main/java/hudson/scm/api/command/SubmitCPCommand.java +++ b/src/main/java/hudson/scm/api/command/SubmitCPCommand.java @@ -9,6 +9,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -19,8 +20,9 @@ */ public class SubmitCPCommand extends BasicAPICommand { - public SubmitCPCommand() + public SubmitCPCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, SUBMIT_CP_COMMAND); // Initialize defaults diff --git a/src/main/java/hudson/scm/api/command/UnlockCommand.java b/src/main/java/hudson/scm/api/command/UnlockCommand.java index 5672e96..70fbd2a 100644 --- a/src/main/java/hudson/scm/api/command/UnlockCommand.java +++ b/src/main/java/hudson/scm/api/command/UnlockCommand.java @@ -9,6 +9,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -19,8 +20,9 @@ */ public class UnlockCommand extends BasicAPICommand { - public UnlockCommand() + public UnlockCommand(final IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, UNLOCK_COMMAND); // Initialize defaults diff --git a/src/main/java/hudson/scm/api/command/ViewProjectCommand.java b/src/main/java/hudson/scm/api/command/ViewProjectCommand.java index 12b6861..175ef6c 100644 --- a/src/main/java/hudson/scm/api/command/ViewProjectCommand.java +++ b/src/main/java/hudson/scm/api/command/ViewProjectCommand.java @@ -9,6 +9,7 @@ import com.mks.api.Command; +import hudson.scm.IntegrityConfigurable; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -19,8 +20,9 @@ */ public class ViewProjectCommand extends BasicAPICommand { - public ViewProjectCommand() + public ViewProjectCommand(IntegrityConfigurable serverConfig) { + super(serverConfig); cmd = new Command(Command.SI, VIEW_PROJECT_COMMAND); // TODO: this is a bug. This command should be run with interim = true as per original code, but this fails somehow diff --git a/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java b/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java index 229761f..ea3aba2 100644 --- a/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java +++ b/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java @@ -165,7 +165,7 @@ protected void testUnlockMembers() throws Exception { IntegrityConfigurable configObj= new IntegrityConfigurable("server1", "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, false, "developer", "password"); FakeAPISession api = FakeAPISession.create(configObj); - IntegrityCMMember.unlockMembers(api, configPath); + IntegrityCMMember.unlockMembers(configObj, configPath); } } From 0091674ab85b47e79d688d9d29e6e3250e586f1d Mon Sep 17 00:00:00 2001 From: anuragsen Date: Mon, 16 Nov 2015 15:23:45 +0530 Subject: [PATCH 6/6] Implementing command Factory + mock classes Change-Id: I47b319199e6912f8ddba38a102ac0249ccd2c013 --- pom.xml | 28 +++++++-- src/main/java/hudson/scm/DerbyUtils.java | 4 +- .../java/hudson/scm/IntegrityCMMember.java | 21 +++---- .../java/hudson/scm/IntegrityCMProject.java | 9 ++- .../hudson/scm/IntegrityCheckinAction.java | 2 +- .../java/hudson/scm/IntegrityCheckinTask.java | 2 +- .../hudson/scm/IntegrityCheckoutTask.java | 2 +- .../scm/IntegrityDeleteNonMembersAction.java | 21 ++++--- .../scm/IntegrityDeleteNonMembersTask.java | 2 +- .../java/hudson/scm/IntegrityItemAction.java | 2 +- .../hudson/scm/IntegrityItemListenerImpl.java | 2 +- .../hudson/scm/IntegrityRevisionState.java | 2 +- .../hudson/scm/IntegrityRunListenerImpl.java | 2 +- src/main/java/hudson/scm/IntegritySCM.java | 11 ++-- .../scm/IntegritySCMCheckinNotifierStep.java | 2 +- .../hudson/scm/IntegritySCMCheckinStep.java | 2 +- .../scm/IntegritySCMChkptNotifierStep.java | 7 +-- .../hudson/scm/IntegritySCMChkptStep.java | 2 +- .../scm/IntegritySCMLabelNotifierStep.java | 4 +- .../hudson/scm/IntegritySCMLabelStep.java | 2 +- src/main/java/hudson/scm/api/APISession.java | 3 +- .../scm/api/command/BasicAPICommand.java | 4 ++ .../scm/api/command/CommandFactory.java | 48 +++++++++++++++ .../{test => }/AbstractIntegrityTestCase.java | 51 ++++++++-------- .../hudson/scm/{test => }/FakeAPISession.java | 5 +- .../hudson/scm/{test => }/FakeCmdRunner.java | 2 +- .../scm/{test => }/FakeIntegrationPoint.java | 2 +- .../hudson/scm/{test => }/FakeObject.java | 2 +- .../hudson/scm/{test => }/FakeResponse.java | 2 +- .../hudson/scm/{test => }/FakeSession.java | 2 +- .../IntegritySCMChkptNotifierStepTest.java | 60 +++++++++++++++++++ .../scm/{test => }/IntegritySCMTest.java | 19 ++---- .../IntegrityTestParametersAction.java | 2 +- src/test/java/hudson/scm/MockAPICommand.java | 50 ++++++++++++++++ .../java/hudson/scm/MockCommandFactory.java | 23 +++++++ .../scm/{test => }/TestIntegrityRepo.java | 2 +- 36 files changed, 298 insertions(+), 108 deletions(-) create mode 100644 src/main/java/hudson/scm/api/command/CommandFactory.java rename src/test/java/hudson/scm/{test => }/AbstractIntegrityTestCase.java (88%) rename src/test/java/hudson/scm/{test => }/FakeAPISession.java (98%) rename src/test/java/hudson/scm/{test => }/FakeCmdRunner.java (99%) rename src/test/java/hudson/scm/{test => }/FakeIntegrationPoint.java (98%) rename src/test/java/hudson/scm/{test => }/FakeObject.java (98%) rename src/test/java/hudson/scm/{test => }/FakeResponse.java (99%) rename src/test/java/hudson/scm/{test => }/FakeSession.java (99%) create mode 100644 src/test/java/hudson/scm/IntegritySCMChkptNotifierStepTest.java rename src/test/java/hudson/scm/{test => }/IntegritySCMTest.java (82%) rename src/test/java/hudson/scm/{test => }/IntegrityTestParametersAction.java (92%) create mode 100644 src/test/java/hudson/scm/MockAPICommand.java create mode 100644 src/test/java/hudson/scm/MockCommandFactory.java rename src/test/java/hudson/scm/{test => }/TestIntegrityRepo.java (98%) diff --git a/pom.xml b/pom.xml index 699764f..1e4e587 100644 --- a/pom.xml +++ b/pom.xml @@ -65,12 +65,32 @@ 4.13.5479 compile + + org.mockito + mockito-all + 1.10.19 + test + + + org.powermock + powermock-api-mockito + 1.6.2 + test + + + org.powermock + powermock-module-junit4 + 1.6.2 + test + + + org.powermock + powermock-api-easymock + 1.6.3 + test + - - - - UTF-8 diff --git a/src/main/java/hudson/scm/DerbyUtils.java b/src/main/java/hudson/scm/DerbyUtils.java index 7a87b5f..e9206ad 100644 --- a/src/main/java/hudson/scm/DerbyUtils.java +++ b/src/main/java/hudson/scm/DerbyUtils.java @@ -42,11 +42,11 @@ */ public class DerbyUtils { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); public static final String DERBY_DRIVER = "org.apache.derby.jdbc.EmbeddedDriver"; public static final String DERBY_SYS_HOME_PROPERTY = "derby.system.home"; public static final String DERBY_URL_PREFIX = "jdbc:derby:"; - private static final String DERBY_DB_NAME = "IntegritySCM"; + private static final String DERBY_DB_NAME = IntegritySCM.class.getName(); public static final String CREATE_INTEGRITY_SCM_REGISTRY = "CREATE TABLE INTEGRITY_SCM_REGISTRY (" + "ID INTEGER NOT NULL PRIMARY KEY GENERATED ALWAYS AS IDENTITY (START WITH 1, INCREMENT BY 1), " + "JOB_NAME VARCHAR(256) NOT NULL, " + diff --git a/src/main/java/hudson/scm/IntegrityCMMember.java b/src/main/java/hudson/scm/IntegrityCMMember.java index 71076cf..874c3de 100644 --- a/src/main/java/hudson/scm/IntegrityCMMember.java +++ b/src/main/java/hudson/scm/IntegrityCMMember.java @@ -23,16 +23,11 @@ import hudson.scm.api.APISession; import hudson.scm.api.APIUtils; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.command.CloseCPCommand; -import hudson.scm.api.command.CreateCPCommand; +import hudson.scm.api.command.CommandFactory; import hudson.scm.api.command.IAPICommand; -import hudson.scm.api.command.LockCommand; import hudson.scm.api.command.ProjectAddCommand; import hudson.scm.api.command.ProjectCheckinCommand; -import hudson.scm.api.command.ProjectCheckoutCommand; -import hudson.scm.api.command.RevisionInfoCommand; import hudson.scm.api.command.SubmitCPCommand; -import hudson.scm.api.command.UnlockCommand; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.FileAPIOption; import hudson.scm.api.option.IAPIOption; @@ -45,7 +40,7 @@ */ public final class IntegrityCMMember { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private static final String ENCODING = "UTF-8"; /** @@ -129,7 +124,7 @@ public static final String getDifferencesLink(String configPath, String memberID public static final boolean checkout(APISession api, String configPath, String memberID, String memberRev, Timestamp memberTimestamp, File targetFile, boolean restoreTimestamp, String lineTerminator) throws APIException { - IAPICommand command = new ProjectCheckoutCommand(); + IAPICommand command = CommandFactory.createCommand(IAPICommand.PROJECT_CHECKOUT_COMMAND, null); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addOption(new FileAPIOption(IAPIOption.TARGET_FILE, targetFile)); @@ -161,7 +156,7 @@ public static String getAuthorFromRevisionInfo(String serverConfigId, String con String author = "unknown"; // Construct the revision-info command - IAPICommand command = new RevisionInfoCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfigId)); + IAPICommand command = CommandFactory.createCommand(IAPICommand.REVISION_INFO_COMMAND, DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfigId)); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addOption(new APIOption(IAPIOption.REVISION, memberRev)); command.addSelection(memberID); @@ -223,7 +218,7 @@ public static final String getMD5Checksum(File targetFile) throws IOException public static final void updateMember(IntegrityConfigurable ciSettings, String configPath, FilePath member, String relativePath, String cpid, String desc) throws AbortException, APIException { // Construct the lock command - IAPICommand command = new LockCommand(ciSettings); + IAPICommand command = CommandFactory.createCommand(IAPICommand.LOCK_COMMAND, ciSettings); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addOption(new APIOption(IAPIOption.CP_ID, cpid)); command.addSelection(relativePath); @@ -286,7 +281,7 @@ public static final void updateMember(IntegrityConfigurable ciSettings, String c public static final void unlockMembers(IntegrityConfigurable integrityConfig, String configPath) throws AbortException, APIException { // Construct the unlock command - IAPICommand command = new UnlockCommand(integrityConfig); + IAPICommand command = CommandFactory.createCommand(IAPICommand.UNLOCK_COMMAND, integrityConfig); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.execute(); } @@ -328,7 +323,7 @@ public static final String createCP(IntegrityConfigurable ciSettings, String ite return cpid; } - IAPICommand command = new CreateCPCommand(ciSettings); + IAPICommand command = CommandFactory.createCommand(IAPICommand.CREATE_CP_COMMAND, ciSettings); command.addOption(new APIOption(IAPIOption.DESCRIPTION,desc)); command.addOption(new APIOption(IAPIOption.SUMMARY,desc)); command.addOption(new APIOption(IAPIOption.ITEM_ID,itemID)); @@ -367,7 +362,7 @@ public static final void submitCP(IntegrityConfigurable ciSettings, String cpid) { LOGGER.fine("Submitting Change Package: " + cpid); - IAPICommand command = new CloseCPCommand(ciSettings); + IAPICommand command = CommandFactory.createCommand(IAPICommand.CLOSE_CP_COMMAND, ciSettings); command.addSelection(cpid); // First we'll attempt to close the cp to release locks on files that haven't changed, diff --git a/src/main/java/hudson/scm/IntegrityCMProject.java b/src/main/java/hudson/scm/IntegrityCMProject.java index 1b471dc..3acadda 100644 --- a/src/main/java/hudson/scm/IntegrityCMProject.java +++ b/src/main/java/hudson/scm/IntegrityCMProject.java @@ -33,8 +33,7 @@ import com.mks.api.response.WorkItem; import hudson.AbortException; -import hudson.scm.api.command.AddProjectLabelCommand; -import hudson.scm.api.command.CheckPointCommand; +import hudson.scm.api.command.CommandFactory; import hudson.scm.api.command.IAPICommand; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -46,7 +45,7 @@ public class IntegrityCMProject implements Serializable { private static final long serialVersionUID = 6452315129657215760L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); public static final String NORMAL_PROJECT = "Normal"; public static final String VARIANT_PROJECT = "Variant"; @@ -377,7 +376,7 @@ private Element writeChangeLog(Element item, Hashtable membe public Response checkpoint(IntegrityConfigurable integrityConfigurable, String chkptLabel) throws APIException, AbortException { // Construct the checkpoint command - IAPICommand command = new CheckPointCommand(integrityConfigurable); + IAPICommand command = CommandFactory.createCommand(IAPICommand.CHECKPOINT_COMMAND, integrityConfigurable); command.addOption(new APIOption(IAPIOption.PROJECT, fullConfigSyntax)); // Set the label and description if applicable command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, chkptLabel); @@ -396,7 +395,7 @@ public Response checkpoint(IntegrityConfigurable integrityConfigurable, String c public Response addProjectLabel(IntegrityConfigurable serverConf, String chkptLabel, String projectName, String projectRevision) throws APIException, AbortException { // Construct the addprojectlabel command - IAPICommand command = new AddProjectLabelCommand(serverConf); + IAPICommand command = CommandFactory.createCommand(IAPICommand.ADD_PROJECT_LABEL_COMMAND, serverConf); command.addOption(new APIOption(IAPIOption.PROJECT, projectName)); command.addOption(new APIOption(IAPIOption.LABEL, chkptLabel)); command.addOption(new APIOption(IAPIOption.PROJECT_REVISION, projectRevision)); diff --git a/src/main/java/hudson/scm/IntegrityCheckinAction.java b/src/main/java/hudson/scm/IntegrityCheckinAction.java index 1fbc542..c8b7923 100644 --- a/src/main/java/hudson/scm/IntegrityCheckinAction.java +++ b/src/main/java/hudson/scm/IntegrityCheckinAction.java @@ -27,7 +27,7 @@ public class IntegrityCheckinAction extends Notifier implements Serializable { private static final long serialVersionUID = 4647604916824363519L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private String ciConfigPath; private String ciWorkspaceDir; private String includes; diff --git a/src/main/java/hudson/scm/IntegrityCheckinTask.java b/src/main/java/hudson/scm/IntegrityCheckinTask.java index 7cb7444..e1da661 100644 --- a/src/main/java/hudson/scm/IntegrityCheckinTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckinTask.java @@ -21,7 +21,7 @@ public class IntegrityCheckinTask implements FileCallable { private static final long serialVersionUID = 4165773747683187630L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private final String itemID; private final String buildID; private final String ciConfigPath; diff --git a/src/main/java/hudson/scm/IntegrityCheckoutTask.java b/src/main/java/hudson/scm/IntegrityCheckoutTask.java index 725d52a..396b028 100644 --- a/src/main/java/hudson/scm/IntegrityCheckoutTask.java +++ b/src/main/java/hudson/scm/IntegrityCheckoutTask.java @@ -34,7 +34,7 @@ public class IntegrityCheckoutTask implements FileCallable { private static final long serialVersionUID = 1240357991626897900L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private static final int CHECKOUT_TRESHOLD = 500; private final List> projectMembersList; private final List dirList; diff --git a/src/main/java/hudson/scm/IntegrityDeleteNonMembersAction.java b/src/main/java/hudson/scm/IntegrityDeleteNonMembersAction.java index 6a10196..2cb4c80 100644 --- a/src/main/java/hudson/scm/IntegrityDeleteNonMembersAction.java +++ b/src/main/java/hudson/scm/IntegrityDeleteNonMembersAction.java @@ -1,29 +1,28 @@ package hudson.scm; +import java.io.IOException; +import java.io.Serializable; +import java.sql.SQLException; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.kohsuke.stapler.StaplerRequest; + import hudson.Extension; import hudson.Launcher; -import hudson.model.BuildListener; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; +import hudson.model.BuildListener; import hudson.tasks.BuildStepDescriptor; import hudson.tasks.BuildStepMonitor; import hudson.tasks.Notifier; import hudson.tasks.Publisher; - -import java.io.IOException; -import java.io.Serializable; -import java.sql.SQLException; -import java.util.logging.Level; -import java.util.logging.Logger; - import net.sf.json.JSONObject; -import org.kohsuke.stapler.StaplerRequest; - public class IntegrityDeleteNonMembersAction extends Notifier implements Serializable { private static final long serialVersionUID = 654691931521381720L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); @Extension public static final IntegrityDeleteNonMembersDescriptorImpl DELETENONMEMBERS_DESCRIPTOR = new IntegrityDeleteNonMembersDescriptorImpl(); diff --git a/src/main/java/hudson/scm/IntegrityDeleteNonMembersTask.java b/src/main/java/hudson/scm/IntegrityDeleteNonMembersTask.java index f296afb..e83e903 100644 --- a/src/main/java/hudson/scm/IntegrityDeleteNonMembersTask.java +++ b/src/main/java/hudson/scm/IntegrityDeleteNonMembersTask.java @@ -22,7 +22,7 @@ public class IntegrityDeleteNonMembersTask implements FileCallable { private static final long serialVersionUID = 6452098989064436149L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private final TaskListener listener; private String alternateWorkspaceDir; private final List> projectMembersList; diff --git a/src/main/java/hudson/scm/IntegrityItemAction.java b/src/main/java/hudson/scm/IntegrityItemAction.java index c808eba..5441aec 100644 --- a/src/main/java/hudson/scm/IntegrityItemAction.java +++ b/src/main/java/hudson/scm/IntegrityItemAction.java @@ -45,7 +45,7 @@ public class IntegrityItemAction extends Notifier implements Serializable { private static final long serialVersionUID = 7067049279037277420L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private String serverConfig; private String queryDefinition; private String stateField; diff --git a/src/main/java/hudson/scm/IntegrityItemListenerImpl.java b/src/main/java/hudson/scm/IntegrityItemListenerImpl.java index 4a1ddf5..5d82bff 100644 --- a/src/main/java/hudson/scm/IntegrityItemListenerImpl.java +++ b/src/main/java/hudson/scm/IntegrityItemListenerImpl.java @@ -21,7 +21,7 @@ @Extension public class IntegrityItemListenerImpl extends ItemListener { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); @DataBoundConstructor public IntegrityItemListenerImpl() diff --git a/src/main/java/hudson/scm/IntegrityRevisionState.java b/src/main/java/hudson/scm/IntegrityRevisionState.java index c42a9d4..7f626cf 100644 --- a/src/main/java/hudson/scm/IntegrityRevisionState.java +++ b/src/main/java/hudson/scm/IntegrityRevisionState.java @@ -9,7 +9,7 @@ public final class IntegrityRevisionState extends SCMRevisionState implements Serializable { private static final long serialVersionUID = 1838332506014398677L; - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private final String projectCacheTable; public IntegrityRevisionState(String jobName, String configurationName, String projectCacheTable) diff --git a/src/main/java/hudson/scm/IntegrityRunListenerImpl.java b/src/main/java/hudson/scm/IntegrityRunListenerImpl.java index 94c0cab..1080c6c 100644 --- a/src/main/java/hudson/scm/IntegrityRunListenerImpl.java +++ b/src/main/java/hudson/scm/IntegrityRunListenerImpl.java @@ -21,7 +21,7 @@ @Extension public class IntegrityRunListenerImpl> extends RunListener { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); @DataBoundConstructor public IntegrityRunListenerImpl() diff --git a/src/main/java/hudson/scm/IntegritySCM.java b/src/main/java/hudson/scm/IntegritySCM.java index 3ad97c6..40efe33 100644 --- a/src/main/java/hudson/scm/IntegritySCM.java +++ b/src/main/java/hudson/scm/IntegritySCM.java @@ -39,9 +39,8 @@ import hudson.scm.api.APISession; import hudson.scm.api.APIUtils; import hudson.scm.api.ExceptionHandler; +import hudson.scm.api.command.CommandFactory; import hudson.scm.api.command.IAPICommand; -import hudson.scm.api.command.ProjectInfoCommand; -import hudson.scm.api.command.ViewProjectCommand; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; import hudson.scm.browsers.IntegrityWebUI; @@ -239,7 +238,7 @@ private Response initializeCMProject(EnvVars environment, String projectCacheTab String resolvedConfigPath = IntegrityCheckpointAction.evalGroovyExpression(environment, configPath); // Get the project information for this project - IAPICommand command = new ProjectInfoCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); + IAPICommand command = CommandFactory.createCommand(IAPICommand.PROJECT_INFO_COMMAND, DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); command.addOption(new APIOption(IAPIOption.PROJECT, resolvedConfigPath)); Response infoRes = command.execute(); @@ -305,7 +304,7 @@ private Response initializeCMProjectMembers() throws APIException, SQLException, IntegrityCMProject siProject = getIntegrityProject(); // Lets parse this project - IAPICommand command = new ViewProjectCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); + IAPICommand command = CommandFactory.createCommand(IAPICommand.VIEW_PROJECT_COMMAND, DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath())); APIUtils.createMultiValueField(",","name","context","cpid","memberrev","membertimestamp","memberdescription","type"); @@ -480,7 +479,7 @@ public void checkout(Run run, Launcher launcher, FilePath workspace, * @throws InterruptedException */ private void checkPointBeforeBuild(Run run, TaskListener listener, - IntegrityCMProject siProject) throws + IntegrityCMProject siProject) throws AbortException, IOException, InterruptedException, com.mks.api.response.InterruptedException, APIException { @@ -496,7 +495,7 @@ private void checkPointBeforeBuild(Run run, TaskListener listener, listener.getLogger().println("Successfully executed pre-build checkpoint for project " + siProject.getConfigurationPath() + ", new revision is " + chkpt); // Update the siProject to use the new checkpoint as the basis for this build - IAPICommand command = new ProjectInfoCommand(DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); + IAPICommand command = CommandFactory.createCommand(IAPICommand.PROJECT_INFO_COMMAND, DescriptorImpl.INTEGRITY_DESCRIPTOR.getConfiguration(serverConfig)); command.addOption(new APIOption(IAPIOption.PROJECT, siProject.getConfigurationPath() + "#forceJump=#b=" + chkpt)); Response infoRes = command.execute(); diff --git a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java index ba724ea..e3ed8c1 100644 --- a/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMCheckinNotifierStep.java @@ -18,7 +18,7 @@ @SuppressWarnings("unchecked") public class IntegritySCMCheckinNotifierStep extends Notifier implements SimpleBuildStep { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private final IntegrityConfigurable ciSettings; private final String configPath; private final String includes; diff --git a/src/main/java/hudson/scm/IntegritySCMCheckinStep.java b/src/main/java/hudson/scm/IntegritySCMCheckinStep.java index c5e4df4..dd9c48b 100644 --- a/src/main/java/hudson/scm/IntegritySCMCheckinStep.java +++ b/src/main/java/hudson/scm/IntegritySCMCheckinStep.java @@ -25,7 +25,7 @@ public class IntegritySCMCheckinStep extends AbstractStepImpl { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private String serverConfig; private String userName; diff --git a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java index 5b3a992..3d5fbed 100644 --- a/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMChkptNotifierStep.java @@ -9,9 +9,8 @@ import hudson.Launcher; import hudson.model.Run; import hudson.model.TaskListener; -import hudson.scm.api.APISession; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.command.CheckPointCommand; +import hudson.scm.api.command.CommandFactory; import hudson.scm.api.command.IAPICommand; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -22,7 +21,7 @@ @SuppressWarnings("unchecked") public class IntegritySCMChkptNotifierStep extends Notifier implements SimpleBuildStep { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private final IntegrityConfigurable ciSettings; private final String configPath; private final String checkpointLabel; @@ -48,7 +47,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi try { // Construct the checkpoint command - IAPICommand command = new CheckPointCommand(ciSettings); + IAPICommand command = CommandFactory.createCommand(IAPICommand.CHECKPOINT_COMMAND, ciSettings); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addAdditionalParameters(IAPIOption.CHECKPOINT_LABEL, checkpointLabel); command.addAdditionalParameters(IAPIOption.CHECKPOINT_DESCRIPTION, checkpointDesc); diff --git a/src/main/java/hudson/scm/IntegritySCMChkptStep.java b/src/main/java/hudson/scm/IntegritySCMChkptStep.java index e930edc..419dbdf 100644 --- a/src/main/java/hudson/scm/IntegritySCMChkptStep.java +++ b/src/main/java/hudson/scm/IntegritySCMChkptStep.java @@ -25,7 +25,7 @@ public class IntegritySCMChkptStep extends AbstractStepImpl { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private String serverConfig; private String userName; diff --git a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java index 6d47c8e..dacba4d 100644 --- a/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java +++ b/src/main/java/hudson/scm/IntegritySCMLabelNotifierStep.java @@ -10,7 +10,7 @@ import hudson.model.Run; import hudson.model.TaskListener; import hudson.scm.api.ExceptionHandler; -import hudson.scm.api.command.AddProjectLabelCommand; +import hudson.scm.api.command.CommandFactory; import hudson.scm.api.command.IAPICommand; import hudson.scm.api.option.APIOption; import hudson.scm.api.option.IAPIOption; @@ -44,7 +44,7 @@ public void perform(Run run, FilePath workspace, Launcher launcher, TaskLi try { // Assumes the checkpoint was done before the build, so lets apply the label now - IAPICommand command = new AddProjectLabelCommand(ciSettings); + IAPICommand command = CommandFactory.createCommand(IAPICommand.ADD_PROJECT_LABEL_COMMAND, ciSettings); command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); command.addOption(new APIOption(IAPIOption.LABEL, checkpointLabel)); diff --git a/src/main/java/hudson/scm/IntegritySCMLabelStep.java b/src/main/java/hudson/scm/IntegritySCMLabelStep.java index 80a288e..f6f9849 100644 --- a/src/main/java/hudson/scm/IntegritySCMLabelStep.java +++ b/src/main/java/hudson/scm/IntegritySCMLabelStep.java @@ -25,7 +25,7 @@ public class IntegritySCMLabelStep extends AbstractStepImpl { - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); private String serverConfig; private String userName; diff --git a/src/main/java/hudson/scm/api/APISession.java b/src/main/java/hudson/scm/api/APISession.java index f48fb19..cfbac29 100644 --- a/src/main/java/hudson/scm/api/APISession.java +++ b/src/main/java/hudson/scm/api/APISession.java @@ -8,6 +8,7 @@ import com.mks.api.response.Response; import hudson.scm.IntegrityConfigurable; +import hudson.scm.IntegritySCM; import com.mks.api.Session; @@ -22,7 +23,7 @@ public class APISession implements ISession { // Initialize our logger - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); // Store the API Version public static final String VERSION = "4.13"; diff --git a/src/main/java/hudson/scm/api/command/BasicAPICommand.java b/src/main/java/hudson/scm/api/command/BasicAPICommand.java index 87dafb3..46accdf 100644 --- a/src/main/java/hudson/scm/api/command/BasicAPICommand.java +++ b/src/main/java/hudson/scm/api/command/BasicAPICommand.java @@ -92,6 +92,10 @@ public Response execute(ISession api) throws APIException @Override public Response execute() throws APIException, AbortException { + if(null == serverConfig){ + throw new AbortException("An Integrity API Session could not be established! Cannot perform "+cmd.getCommandName()+" operation"); + } + // Create an Integrity Session using params from IntegrityConfigurable Object ISession api = APISession.create(serverConfig); // Ensure we've successfully created an API Session diff --git a/src/main/java/hudson/scm/api/command/CommandFactory.java b/src/main/java/hudson/scm/api/command/CommandFactory.java new file mode 100644 index 0000000..03ec488 --- /dev/null +++ b/src/main/java/hudson/scm/api/command/CommandFactory.java @@ -0,0 +1,48 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm.api.command; + +import hudson.scm.IntegrityConfigurable; + +/** + * Factory to centrally instantiate API commands + * @author Author: asen + * @version $Revision: $ + */ +public class CommandFactory +{ + public static IAPICommand createCommand(final String commandName, IntegrityConfigurable integrityConfig){ + if(commandName.equalsIgnoreCase(IAPICommand.ADD_PROJECT_LABEL_COMMAND)) + return new AddProjectLabelCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.CHECKPOINT_COMMAND)) + return new CheckPointCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.CLOSE_CP_COMMAND)) + return new CloseCPCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.CREATE_CP_COMMAND)) + return new CreateCPCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.LOCK_COMMAND)) + return new LockCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.PROJECT_ADD_COMMAND)) + return new ProjectAddCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.PROJECT_CHECKIN_COMMAND)) + return new ProjectCheckinCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.PROJECT_CHECKOUT_COMMAND)) + return new ProjectCheckoutCommand(); + if(commandName.equalsIgnoreCase(IAPICommand.PROJECT_INFO_COMMAND)) + return new ProjectInfoCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.REVISION_INFO_COMMAND)) + return new RevisionInfoCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.SUBMIT_CP_COMMAND)) + return new SubmitCPCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.UNLOCK_COMMAND)) + return new UnlockCommand(integrityConfig); + if(commandName.equalsIgnoreCase(IAPICommand.VIEW_PROJECT_COMMAND)) + return new ViewProjectCommand(integrityConfig); + return null; + } +} diff --git a/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java b/src/test/java/hudson/scm/AbstractIntegrityTestCase.java similarity index 88% rename from src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java rename to src/test/java/hudson/scm/AbstractIntegrityTestCase.java index ea3aba2..0312a92 100644 --- a/src/test/java/hudson/scm/test/AbstractIntegrityTestCase.java +++ b/src/test/java/hudson/scm/AbstractIntegrityTestCase.java @@ -1,23 +1,4 @@ -package hudson.scm.test; - -import hudson.EnvVars; -import hudson.FilePath; -import hudson.Launcher; -import hudson.model.BuildListener; -import hudson.model.FreeStyleBuild; -import hudson.model.Result; -import hudson.model.StreamBuildListener; -import hudson.model.TaskListener; -import hudson.model.AbstractBuild; -import hudson.model.Cause; -import hudson.model.FreeStyleProject; -import hudson.scm.IntegrityCMMember; -import hudson.scm.IntegrityCheckinTask; -import hudson.scm.IntegrityConfigurable; -import hudson.scm.IntegrityItemAction; -import hudson.scm.IntegritySCM; -import hudson.scm.IntegritySCM.DescriptorImpl; -import hudson.util.StreamTaskListener; +package hudson.scm; import java.io.ByteArrayOutputStream; import java.io.File; @@ -30,6 +11,22 @@ import org.jvnet.hudson.test.JenkinsRule; //import org.mockito.Mockito; +import hudson.EnvVars; +import hudson.FilePath; +import hudson.Launcher; +import hudson.model.AbstractBuild; +import hudson.model.BuildListener; +import hudson.model.Cause; +import hudson.model.FreeStyleBuild; +import hudson.model.FreeStyleProject; +import hudson.model.Result; +import hudson.model.StreamBuildListener; +import hudson.model.TaskListener; +import hudson.scm.IntegritySCM.DescriptorImpl; +import hudson.scm.api.command.IAPICommand; +import hudson.scm.api.option.APIOption; +import hudson.scm.api.option.IAPIOption; +import hudson.util.StreamTaskListener; import rpc.IntegrityException; public abstract class AbstractIntegrityTestCase extends JenkinsRule{ @@ -49,6 +46,7 @@ public abstract class AbstractIntegrityTestCase extends JenkinsRule{ String configPath="#/Vipin"; @Rule public JenkinsRule jenkinsRule = new JenkinsRule(); @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); + IntegrityConfigurable fakeConfigObj; @Before public void setUp() throws Exception { @@ -59,7 +57,8 @@ public void setUp() throws Exception { name1=testRepo.userName1; name2=testRepo.userName2; workDir = testRepo.IntegrityDir; - workspace = testRepo.IntegrityDirPath; + workspace = testRepo.IntegrityDirPath; + fakeConfigObj = new IntegrityConfigurable("server1", "dummy.server.com", 7001, "dummy.server.com", 7001, false, "developer", "password"); } catch (Throwable e) { // TODO Auto-generated catch block @@ -162,10 +161,14 @@ protected FreeStyleBuild build(final FreeStyleProject project, final Result expe } protected void testUnlockMembers() throws Exception - { + { IntegrityConfigurable configObj= new IntegrityConfigurable("server1", "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, false, "developer", "password"); FakeAPISession api = FakeAPISession.create(configObj); - IntegrityCMMember.unlockMembers(configObj, configPath); - } + IntegrityCMMember.unlockMembers(configObj, configPath); + + /*IAPICommand command = new MockAPICommand(IAPICommand.UNLOCK_COMMAND); + command.addOption(new APIOption(IAPIOption.PROJECT, configPath)); + command.execute();*/ + } } diff --git a/src/test/java/hudson/scm/test/FakeAPISession.java b/src/test/java/hudson/scm/FakeAPISession.java similarity index 98% rename from src/test/java/hudson/scm/test/FakeAPISession.java rename to src/test/java/hudson/scm/FakeAPISession.java index f563b0d..ea7d114 100644 --- a/src/test/java/hudson/scm/test/FakeAPISession.java +++ b/src/test/java/hudson/scm/FakeAPISession.java @@ -9,7 +9,7 @@ // is strictly prohibited. // -package hudson.scm.test; +package hudson.scm; import java.io.IOException; import java.util.logging.Level; @@ -20,6 +20,7 @@ import com.mks.api.response.Response; import hudson.scm.IntegrityConfigurable; +import hudson.scm.IntegritySCM; import hudson.scm.api.ExceptionHandler; import hudson.scm.api.ISession; @@ -32,7 +33,7 @@ public class FakeAPISession implements ISession { // Initialize our logger - private static final Logger LOGGER = Logger.getLogger("IntegritySCM"); + private static final Logger LOGGER = Logger.getLogger(IntegritySCM.class.getName()); // Store the API Version public static final String VERSION = "4.13"; diff --git a/src/test/java/hudson/scm/test/FakeCmdRunner.java b/src/test/java/hudson/scm/FakeCmdRunner.java similarity index 99% rename from src/test/java/hudson/scm/test/FakeCmdRunner.java rename to src/test/java/hudson/scm/FakeCmdRunner.java index 0106b59..d2bf450 100644 --- a/src/test/java/hudson/scm/test/FakeCmdRunner.java +++ b/src/test/java/hudson/scm/FakeCmdRunner.java @@ -9,7 +9,7 @@ // is strictly prohibited. // -package hudson.scm.test; +package hudson.scm; import com.mks.api.CmdRunner; import com.mks.api.Command; diff --git a/src/test/java/hudson/scm/test/FakeIntegrationPoint.java b/src/test/java/hudson/scm/FakeIntegrationPoint.java similarity index 98% rename from src/test/java/hudson/scm/test/FakeIntegrationPoint.java rename to src/test/java/hudson/scm/FakeIntegrationPoint.java index bac8810..ac8d6ea 100644 --- a/src/test/java/hudson/scm/test/FakeIntegrationPoint.java +++ b/src/test/java/hudson/scm/FakeIntegrationPoint.java @@ -5,7 +5,7 @@ // PTC Inc. Any use or disclosure of this Software without the express // written permission of PTC Inc. is strictly prohibited. -package hudson.scm.test; +package hudson.scm; import java.util.Iterator; diff --git a/src/test/java/hudson/scm/test/FakeObject.java b/src/test/java/hudson/scm/FakeObject.java similarity index 98% rename from src/test/java/hudson/scm/test/FakeObject.java rename to src/test/java/hudson/scm/FakeObject.java index b1f6124..8a5954e 100644 --- a/src/test/java/hudson/scm/test/FakeObject.java +++ b/src/test/java/hudson/scm/FakeObject.java @@ -9,7 +9,7 @@ // is strictly prohibited. // -package hudson.scm.test; +package hudson.scm; import java.util.LinkedHashMap; import java.util.Map; diff --git a/src/test/java/hudson/scm/test/FakeResponse.java b/src/test/java/hudson/scm/FakeResponse.java similarity index 99% rename from src/test/java/hudson/scm/test/FakeResponse.java rename to src/test/java/hudson/scm/FakeResponse.java index b976d4c..4b9a4c2 100644 --- a/src/test/java/hudson/scm/test/FakeResponse.java +++ b/src/test/java/hudson/scm/FakeResponse.java @@ -9,7 +9,7 @@ // is strictly prohibited. // -package hudson.scm.test; +package hudson.scm; import com.mks.api.VersionNumber; import com.mks.api.response.*; diff --git a/src/test/java/hudson/scm/test/FakeSession.java b/src/test/java/hudson/scm/FakeSession.java similarity index 99% rename from src/test/java/hudson/scm/test/FakeSession.java rename to src/test/java/hudson/scm/FakeSession.java index 88c2fbf..3fcd45f 100644 --- a/src/test/java/hudson/scm/test/FakeSession.java +++ b/src/test/java/hudson/scm/FakeSession.java @@ -9,7 +9,7 @@ // is strictly prohibited. // -package hudson.scm.test; +package hudson.scm; import java.io.IOException; import java.util.Iterator; diff --git a/src/test/java/hudson/scm/IntegritySCMChkptNotifierStepTest.java b/src/test/java/hudson/scm/IntegritySCMChkptNotifierStepTest.java new file mode 100644 index 0000000..a874303 --- /dev/null +++ b/src/test/java/hudson/scm/IntegritySCMChkptNotifierStepTest.java @@ -0,0 +1,60 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.powermock.api.easymock.annotation.Mock; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import hudson.model.StreamBuildListener; +import hudson.scm.api.command.CommandFactory; +import hudson.scm.api.command.IAPICommand; + +/** + * @author Author: asen + * @version $Revision: $ + */ +@RunWith(PowerMockRunner.class) +@PrepareForTest({ CommandFactory.class, IntegrityConfigurable.class}) +public class IntegritySCMChkptNotifierStepTest extends AbstractIntegrityTestCase +{ + public IntegritySCMChkptNotifierStepTest() + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + buildListener = new StreamBuildListener(out); + } + + IntegritySCMChkptNotifierStep integritySCMChkptNotifierStep; + + //@Mock private IAPICommand commandMock; + @Mock IntegrityConfigurable ic; + + //@Test (expected = AbortException.class) + public void test_throwsExceptionIfAPINotReachable() throws InterruptedException, IOException{ + integritySCMChkptNotifierStep = new IntegritySCMChkptNotifierStep(ic, configPath, "Test", "Test"); + integritySCMChkptNotifierStep.perform(null, null, null, buildListener); + } + + @Test + public void test_checkpoint() throws InterruptedException, IOException{ + + IAPICommand commandMock = new MockAPICommand(ic, IAPICommand.CHECKPOINT_COMMAND); + PowerMockito.mockStatic(CommandFactory.class); + Mockito.when(CommandFactory.createCommand(IAPICommand.CHECKPOINT_COMMAND, ic)).thenReturn(commandMock); + + integritySCMChkptNotifierStep = new IntegritySCMChkptNotifierStep(ic, configPath, "Test", "Test"); + integritySCMChkptNotifierStep.perform(null, null, null, buildListener); + } +} diff --git a/src/test/java/hudson/scm/test/IntegritySCMTest.java b/src/test/java/hudson/scm/IntegritySCMTest.java similarity index 82% rename from src/test/java/hudson/scm/test/IntegritySCMTest.java rename to src/test/java/hudson/scm/IntegritySCMTest.java index 878fa83..390775d 100644 --- a/src/test/java/hudson/scm/test/IntegritySCMTest.java +++ b/src/test/java/hudson/scm/IntegritySCMTest.java @@ -1,20 +1,9 @@ -package hudson.scm.test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +package hudson.scm; +import org.junit.Test; + import hudson.model.FreeStyleBuild; -import hudson.model.Result; import hudson.model.FreeStyleProject; -import hudson.model.ParametersDefinitionProperty; -import hudson.model.StringParameterDefinition; -import hudson.model.User; -import hudson.scm.IntegrityCMMember; - -import java.util.Set; - -import org.junit.Rule; -import org.junit.Test; -import org.jvnet.hudson.test.JenkinsRule; +import hudson.model.Result; public class IntegritySCMTest extends AbstractIntegrityTestCase diff --git a/src/test/java/hudson/scm/test/IntegrityTestParametersAction.java b/src/test/java/hudson/scm/IntegrityTestParametersAction.java similarity index 92% rename from src/test/java/hudson/scm/test/IntegrityTestParametersAction.java rename to src/test/java/hudson/scm/IntegrityTestParametersAction.java index 492fb1b..5704e11 100644 --- a/src/test/java/hudson/scm/test/IntegrityTestParametersAction.java +++ b/src/test/java/hudson/scm/IntegrityTestParametersAction.java @@ -1,4 +1,4 @@ -package hudson.scm.test; +package hudson.scm; import hudson.EnvVars; import hudson.model.EnvironmentContributingAction; import hudson.model.InvisibleAction; diff --git a/src/test/java/hudson/scm/MockAPICommand.java b/src/test/java/hudson/scm/MockAPICommand.java new file mode 100644 index 0000000..ca6ed6b --- /dev/null +++ b/src/test/java/hudson/scm/MockAPICommand.java @@ -0,0 +1,50 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm; + +import java.util.HashMap; + +import com.mks.api.Command; +import com.mks.api.response.APIException; +import com.mks.api.response.Response; + +import hudson.AbortException; +import hudson.scm.api.ISession; +import hudson.scm.api.command.BasicAPICommand; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class MockAPICommand extends BasicAPICommand +{ + + Command cmd; + IntegrityConfigurable configObj; + + public MockAPICommand(final IntegrityConfigurable serverConfig, String command) + { + super(serverConfig); + cmd = new Command(Command.SI, command); + commandHelperObjects = new HashMap(); + } + + + /* (non-Javadoc) + * @see hudson.scm.api.command.IAPICommand#execute() + */ + @Override + public Response execute() throws APIException, AbortException + { + configObj= new IntegrityConfigurable("server1", "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, "ppumsv-ipdc16d.ptcnet.ptc.com", 7001, false, "developer", "password"); + ISession api = FakeAPISession.create(configObj); + return super.execute(api); + } + +} diff --git a/src/test/java/hudson/scm/MockCommandFactory.java b/src/test/java/hudson/scm/MockCommandFactory.java new file mode 100644 index 0000000..f90b87d --- /dev/null +++ b/src/test/java/hudson/scm/MockCommandFactory.java @@ -0,0 +1,23 @@ +// $Id: $ +// (c) Copyright 2015 by PTC Inc. All rights reserved. +// +// This Software is unpublished, valuable, confidential property of +// PTC Inc. Any use or disclosure of this Software without the express +// written permission of PTC Inc. is strictly prohibited. + +package hudson.scm; + +import hudson.scm.api.command.CommandFactory; +import hudson.scm.api.command.IAPICommand; + +/** + * + * @author Author: asen + * @version $Revision: $ + */ +public class MockCommandFactory extends CommandFactory +{ + public static IAPICommand createCommand(final String commandName, IntegrityConfigurable integrityConfig){ + return new MockAPICommand(integrityConfig, commandName); + } +} diff --git a/src/test/java/hudson/scm/test/TestIntegrityRepo.java b/src/test/java/hudson/scm/TestIntegrityRepo.java similarity index 98% rename from src/test/java/hudson/scm/test/TestIntegrityRepo.java rename to src/test/java/hudson/scm/TestIntegrityRepo.java index e1d1af6..2ed257a 100644 --- a/src/test/java/hudson/scm/test/TestIntegrityRepo.java +++ b/src/test/java/hudson/scm/TestIntegrityRepo.java @@ -1,4 +1,4 @@ -package hudson.scm.test; +package hudson.scm; import hudson.FilePath; import hudson.model.TaskListener;