package hudson.plugins.codeplex.scm; import java.io.File; import java.io.IOException; import java.rmi.RemoteException; import java.util.Map; import javax.xml.rpc.ServiceException; import org.kohsuke.stapler.DataBoundConstructor; import com.codeplex.soap.ProjectInfoServiceLocator; import hudson.Extension; import hudson.FilePath; import hudson.Launcher; import hudson.Util; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.BuildListener; import hudson.model.Hudson; import hudson.model.Node; import hudson.model.TaskListener; import hudson.plugins.codeplex.CodePlexProjectProperty; import hudson.plugins.codeplex.browsers.CodePlexTfsBrowser; import hudson.plugins.tfs.TeamFoundationServerScm; import hudson.scm.ChangeLogParser; import hudson.scm.RepositoryBrowser; import hudson.scm.SCM; import hudson.scm.SCMDescriptor; import hudson.util.Scrambler; @SuppressWarnings("unchecked") public class CodePlexTfsScm extends SCM { private transient SCM configuredScm; private transient CodePlexTfsBrowser tfsBrowser; private final String path; private final String userName; private final String userPassword; @DataBoundConstructor public CodePlexTfsScm(String path, String userName, String userPassword) { this.userName = userName; this.userPassword = Scrambler.scramble(userPassword); this.path = path; if (Util.fixEmptyAndTrim(path) == null) { path = "."; } } public String getPath() { return path; } public String getUserPassword() { return Scrambler.descramble(userPassword); } public String getUserName() { return userName; } public SCM getScm() { if (configuredScm == null) { try { for (AbstractProject<?, ?> project : Hudson.getInstance().getItems(AbstractProject.class)) { if (this == project.getScm() ) { CodePlexProjectProperty property = project.getProperty(CodePlexProjectProperty.class); if (property != null) { configuredScm = new TeamFoundationServerScm( getTfsUrl(property), String.format("$/%s%s", property.getProjectName(), path), ".", true, null, (getUserName() != null ? getTfsUserName(getUserName()) : null), (getUserPassword() != null ? getUserPassword() : null)); } else { throw new RuntimeException("The project does not have a google code property. Please report this to the plugin author."); } break; } } } catch (RemoteException e) { throw new RuntimeException("Could not communicate with the remote CodePlex SOAP server. Please contact plugin author.", e); } catch (ServiceException e) { throw new RuntimeException("Could not communicate with the remote CodePlex SOAP server. Please contact plugin author.", e); } if (configuredScm == null) { throw new RuntimeException("Could not find the project for this SCM object. Please contact plugin author."); } } return configuredScm; } private String getTfsUserName(String codePlexUserName) throws RemoteException, ServiceException { ProjectInfoServiceLocator locator = new ProjectInfoServiceLocator(); return locator.getProjectInfoServiceSoap().codePlexUserNameToTfsUserName(codePlexUserName); } private String getTfsUrl(CodePlexProjectProperty property) throws RemoteException, ServiceException { ProjectInfoServiceLocator locator = new ProjectInfoServiceLocator(); return locator.getProjectInfoServiceSoap().getTfsInfoForProject(property.getProjectName()).getTfsServerUrl(); } @Override public RepositoryBrowser getBrowser() { if (tfsBrowser == null) { tfsBrowser = new CodePlexTfsBrowser(); } return tfsBrowser; } @Override public boolean checkout(AbstractBuild build, Launcher launcher, FilePath workspace, BuildListener listener, File changelogFile) throws IOException, InterruptedException { return getScm().checkout(build, launcher, workspace, listener, changelogFile); } @Override public ChangeLogParser createChangeLogParser() { return new TfsChangeLogParserDecorator(getScm().createChangeLogParser()); } @Override public boolean pollChanges(AbstractProject project, Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException { return getScm().pollChanges(project, launcher, workspace, listener); } @Override public void buildEnvVars(AbstractBuild build, Map<String, String> env) { getScm().buildEnvVars(build, env); } @Override public FilePath getModuleRoot(FilePath workspace) { return getScm().getModuleRoot(workspace); } @Override public FilePath[] getModuleRoots(FilePath workspace) { return getScm().getModuleRoots(workspace); } @Override public boolean processWorkspaceBeforeDeletion(AbstractProject<?, ?> project, FilePath workspace, Node node) throws IOException, InterruptedException { return getScm().processWorkspaceBeforeDeletion(project, workspace, node); } @Override public boolean requiresWorkspaceForPolling() { return getScm().requiresWorkspaceForPolling(); } @Override public boolean supportsPolling() { return getScm().supportsPolling(); } @Extension public static class DescriptorImpl extends SCMDescriptor<CodePlexTfsScm> { public DescriptorImpl() { super(CodePlexTfsScm.class, CodePlexTfsBrowser.class); } @Override public String getDisplayName() { return "CodePlex"; } } }