PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 1ms

/src/main/java/com/atlassian/jira/plugins/bitbucket/spi/DvcsRepositoryManager.java

https://bitbucket.org/atlassian/jira-bitbucket-connector/
Java | 255 lines | 214 code | 37 blank | 4 comment | 3 complexity | b83bd9dbdb0d53b3b1d40b15519b6811 MD5 | raw file
  1. package com.atlassian.jira.plugins.bitbucket.spi;
  2. import com.atlassian.jira.plugins.bitbucket.IssueLinker;
  3. import com.atlassian.jira.plugins.bitbucket.activeobjects.v2.IssueMapping;
  4. import com.atlassian.jira.plugins.bitbucket.activeobjects.v2.ProjectMapping;
  5. import com.atlassian.jira.plugins.bitbucket.api.Changeset;
  6. import com.atlassian.jira.plugins.bitbucket.api.Encryptor;
  7. import com.atlassian.jira.plugins.bitbucket.api.ProgressWriter;
  8. import com.atlassian.jira.plugins.bitbucket.api.RepositoryPersister;
  9. import com.atlassian.jira.plugins.bitbucket.api.SourceControlException;
  10. import com.atlassian.jira.plugins.bitbucket.api.SourceControlRepository;
  11. import com.atlassian.jira.plugins.bitbucket.api.SourceControlUser;
  12. import com.atlassian.jira.plugins.bitbucket.api.SynchronizationKey;
  13. import com.atlassian.jira.plugins.bitbucket.api.impl.DefaultSourceControlRepository;
  14. import com.atlassian.jira.plugins.bitbucket.streams.GlobalFilter;
  15. import com.atlassian.jira.plugins.bitbucket.velocity.VelocityUtils;
  16. import com.atlassian.sal.api.ApplicationProperties;
  17. import com.atlassian.templaterenderer.TemplateRenderer;
  18. import com.google.common.base.Function;
  19. import com.google.common.collect.Lists;
  20. import com.google.common.collect.Sets;
  21. import org.slf4j.Logger;
  22. import org.slf4j.LoggerFactory;
  23. import java.io.IOException;
  24. import java.io.StringWriter;
  25. import java.util.HashMap;
  26. import java.util.List;
  27. import java.util.Map;
  28. import java.util.Set;
  29. import java.util.regex.Matcher;
  30. import java.util.regex.Pattern;
  31. public abstract class DvcsRepositoryManager implements RepositoryManager, RepositoryUriFactory
  32. {
  33. private static final Logger log = LoggerFactory.getLogger(DvcsRepositoryManager.class);
  34. public static final int MAX_VISIBLE_FILES = 5;
  35. private final RepositoryPersister repositoryPersister;
  36. private final Communicator communicator;
  37. private final Encryptor encryptor;
  38. private final ApplicationProperties applicationProperties;
  39. private final IssueLinker issueLinker;
  40. private final TemplateRenderer templateRenderer;
  41. /* Maps ProjectMapping to SourceControlRepository */
  42. private final Function<ProjectMapping, SourceControlRepository> TO_SOURCE_CONTROL_REPOSITORY = new Function<ProjectMapping, SourceControlRepository>()
  43. {
  44. @Override
  45. public SourceControlRepository apply(ProjectMapping pm)
  46. {
  47. String decryptedPassword = encryptor.decrypt(pm.getPassword(), pm.getProjectKey(), pm.getRepositoryUrl());
  48. String decryptedAdminPassword = encryptor.decrypt(pm.getAdminPassword(), pm.getProjectKey(),
  49. pm.getRepositoryUrl());
  50. return new DefaultSourceControlRepository(pm.getID(), pm.getRepositoryType(), getRepositoryUri(pm.getRepositoryUrl()),
  51. pm.getProjectKey(), pm.getUsername(), decryptedPassword,
  52. pm.getAdminUsername(), decryptedAdminPassword, pm.getAccessToken());
  53. }
  54. };
  55. private final Function<IssueMapping, Changeset> toChangesetTransformer;
  56. public DvcsRepositoryManager(Communicator communicator, RepositoryPersister repositoryPersister, Encryptor encryptor,
  57. ApplicationProperties applicationProperties, IssueLinker issueLinker, TemplateRenderer templateRenderer)
  58. {
  59. this.communicator = communicator;
  60. this.repositoryPersister = repositoryPersister;
  61. this.encryptor = encryptor;
  62. this.applicationProperties = applicationProperties;
  63. this.issueLinker = issueLinker;
  64. this.templateRenderer = templateRenderer;
  65. toChangesetTransformer = new ToChangesetTransformer(this);
  66. }
  67. public void validateRepositoryAccess(String repositoryType, String projectKey, String repositoryUrl, String username,
  68. String password, String adminUsername, String adminPassword, String accessToken) throws SourceControlException
  69. {
  70. RepositoryUri repositoryUri = getRepositoryUri(repositoryUrl);
  71. getCommunicator().validateRepositoryAccess(repositoryType, projectKey, repositoryUri, username, password, adminUsername, adminPassword, accessToken);
  72. }
  73. @Override
  74. public SourceControlRepository addRepository(String repositoryType, String projectKey, String repositoryUrl, String username,
  75. String password, String adminUsername, String adminPassword, String accessToken)
  76. {
  77. // Remove trailing slashes from URL
  78. if (repositoryUrl.endsWith("/"))
  79. {
  80. repositoryUrl = repositoryUrl.substring(0, repositoryUrl.length() - 1);
  81. }
  82. // Set all URLs to HTTPS
  83. if (repositoryUrl.startsWith("http:"))
  84. {
  85. repositoryUrl = repositoryUrl.replaceFirst("http:", "https:");
  86. }
  87. validateRepositoryAccess(repositoryType, projectKey, repositoryUrl, username, password, adminUsername, adminPassword, accessToken);
  88. String encryptedPassword = encryptor.encrypt(password, projectKey, repositoryUrl);
  89. String encryptedAdminPassword = encryptor.encrypt(adminPassword, projectKey, repositoryUrl);
  90. ProjectMapping pm = repositoryPersister.addRepository(repositoryType, projectKey, repositoryUrl, username,
  91. encryptedPassword, adminUsername, encryptedAdminPassword, accessToken);
  92. return TO_SOURCE_CONTROL_REPOSITORY.apply(pm);
  93. }
  94. @Override
  95. public SourceControlRepository getRepository(int repositoryId)
  96. {
  97. ProjectMapping repository = repositoryPersister.getRepository(repositoryId);
  98. return TO_SOURCE_CONTROL_REPOSITORY.apply(repository);
  99. }
  100. @Override
  101. public List<SourceControlRepository> getRepositories(String projectKey)
  102. {
  103. List<ProjectMapping> repositories = repositoryPersister.getRepositories(projectKey, getRepositoryType());
  104. return Lists.transform(repositories, TO_SOURCE_CONTROL_REPOSITORY);
  105. }
  106. @Override
  107. public List<Changeset> getChangesets(String issueKey)
  108. {
  109. List<IssueMapping> issueMappings = repositoryPersister.getIssueMappings(issueKey, getRepositoryType());
  110. return Lists.transform(issueMappings, toChangesetTransformer);
  111. }
  112. @Override
  113. public void removeRepository(int id)
  114. {
  115. repositoryPersister.removeRepository(id);
  116. }
  117. @Override
  118. public void addChangeset(SourceControlRepository repository, String issueId, Changeset changeset)
  119. {
  120. repositoryPersister.addChangeset(issueId, changeset);
  121. }
  122. @Override
  123. public SourceControlUser getUser(SourceControlRepository repository, String username)
  124. {
  125. return getCommunicator().getUser(repository, username);
  126. }
  127. @Override
  128. public String getHtmlForChangeset(SourceControlRepository repository, Changeset changeset)
  129. {
  130. Map<String, Object> templateMap = new HashMap<String, Object>();
  131. templateMap.put("velocity_utils", new VelocityUtils());
  132. templateMap.put("issue_linker", issueLinker);
  133. templateMap.put("changeset", changeset);
  134. templateMap.put("repository", repository);
  135. String documentJpgUrl = getApplicationProperties().getBaseUrl() + "/download/resources/com.atlassian.jira.plugins.jira-bitbucket-connector-plugin/images/document.jpg";
  136. templateMap.put("document_jpg_url", documentJpgUrl);
  137. String authorName = changeset.getRawAuthor();
  138. String login = changeset.getAuthor();
  139. String commitURL = changeset.getCommitURL(repository);
  140. SourceControlUser user = getUser(repository, changeset.getAuthor());
  141. String gravatarUrl = user.getAvatar().replace("s=32", "s=60");
  142. String commitMessage = changeset.getMessage();
  143. templateMap.put("gravatar_url", gravatarUrl);
  144. templateMap.put("user_url", repository.getRepositoryUri().getUserUrl(CustomStringUtils.encodeUriPath(login)));
  145. templateMap.put("login", login);
  146. templateMap.put("user_name", authorName);
  147. templateMap.put("commit_message", commitMessage);
  148. templateMap.put("commit_url", commitURL);
  149. templateMap.put("commit_hash", changeset.getNode());
  150. StringWriter sw = new StringWriter();
  151. try
  152. {
  153. templateRenderer.render("/templates/com/atlassian/jira/plugins/bitbucket/issuetabpanels/commits-view.vm", templateMap, sw);
  154. } catch (IOException e)
  155. {
  156. log.warn(e.getMessage(), e);
  157. }
  158. return sw.toString();
  159. }
  160. @Override
  161. public SynchronisationOperation getSynchronisationOperation(SynchronizationKey key, ProgressWriter progressProvider)
  162. {
  163. return new DefaultSynchronisationOperation(key, this, getCommunicator(), progressProvider);
  164. }
  165. protected boolean hasValidFormat(String url)
  166. {
  167. // Valid URL
  168. Pattern p = Pattern.compile("^(https|http)://[a-zA-Z0-9][-a-zA-Z0-9]*(.[a-zA-Z0-9]+)+/[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]");
  169. Matcher m = p.matcher(url);
  170. return m.matches();
  171. }
  172. @Override
  173. public abstract String getRepositoryType();
  174. public ApplicationProperties getApplicationProperties()
  175. {
  176. return applicationProperties;
  177. }
  178. public Communicator getCommunicator()
  179. {
  180. return communicator;
  181. }
  182. @Override
  183. public UrlInfo getUrlInfo(String repositoryUrl)
  184. {
  185. if (!hasValidFormat(repositoryUrl)) return null;
  186. return getCommunicator().getUrlInfo(getRepositoryUri(repositoryUrl));
  187. }
  188. @Override
  189. public Changeset reloadChangeset(IssueMapping issueMapping)
  190. {
  191. ProjectMapping pm = repositoryPersister.getRepository(issueMapping.getRepositoryId());
  192. SourceControlRepository repository = TO_SOURCE_CONTROL_REPOSITORY.apply(pm);
  193. Changeset changeset = getCommunicator().getChangeset(repository, issueMapping.getNode());
  194. repositoryPersister.addChangeset(issueMapping.getIssueId(), changeset);
  195. return changeset;
  196. }
  197. @Override
  198. public void setupPostcommitHook(SourceControlRepository repo)
  199. {
  200. getCommunicator().setupPostcommitHook(repo, getPostCommitUrl(repo));
  201. }
  202. private String getPostCommitUrl(SourceControlRepository repo)
  203. {
  204. return getApplicationProperties().getBaseUrl() + "/rest/bitbucket/1.0/repository/" + repo.getId() + "/sync";
  205. }
  206. @Override
  207. public void removePostcommitHook(SourceControlRepository repo)
  208. {
  209. getCommunicator().removePostcommitHook(repo, getPostCommitUrl(repo));
  210. }
  211. @Override
  212. public Set<Changeset> getLatestChangesets(int count, GlobalFilter gf)
  213. {
  214. List<IssueMapping> latestIssueMappings = repositoryPersister.getLatestIssueMappings(count, gf, getRepositoryType());
  215. List<Changeset> changesets = Lists.transform(latestIssueMappings, toChangesetTransformer);
  216. return Sets.newHashSet(changesets);
  217. }
  218. }