Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

SyndicationServlet.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. /*
  2. * Copyright 2011 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit;
  17. import java.text.MessageFormat;
  18. import java.util.ArrayList;
  19. import java.util.Arrays;
  20. import java.util.Collections;
  21. import java.util.List;
  22. import java.util.Map;
  23. import javax.servlet.http.HttpServlet;
  24. import org.eclipse.jgit.lib.ObjectId;
  25. import org.eclipse.jgit.lib.Repository;
  26. import org.eclipse.jgit.revwalk.RevCommit;
  27. import org.slf4j.Logger;
  28. import org.slf4j.LoggerFactory;
  29. import com.gitblit.AuthenticationFilter.AuthenticatedRequest;
  30. import com.gitblit.manager.IProjectManager;
  31. import com.gitblit.manager.IRepositoryManager;
  32. import com.gitblit.manager.IRuntimeManager;
  33. import com.gitblit.models.FeedEntryModel;
  34. import com.gitblit.models.ProjectModel;
  35. import com.gitblit.models.RefModel;
  36. import com.gitblit.models.RepositoryModel;
  37. import com.gitblit.models.UserModel;
  38. import com.gitblit.utils.HttpUtils;
  39. import com.gitblit.utils.JGitUtils;
  40. import com.gitblit.utils.MessageProcessor;
  41. import com.gitblit.utils.StringUtils;
  42. import com.gitblit.utils.SyndicationUtils;
  43. /**
  44. * SyndicationServlet generates RSS 2.0 feeds and feed links.
  45. *
  46. * Access to this servlet is protected by the SyndicationFilter.
  47. *
  48. * @author James Moger
  49. *
  50. */
  51. public class SyndicationServlet extends HttpServlet {
  52. private static final long serialVersionUID = 1L;
  53. private transient Logger logger = LoggerFactory.getLogger(SyndicationServlet.class);
  54. /**
  55. * Create a feed link for the specified repository and branch/tag/commit id.
  56. *
  57. * @param baseURL
  58. * @param repository
  59. * the repository name
  60. * @param objectId
  61. * the branch, tag, or first commit for the feed
  62. * @param length
  63. * the number of commits to include in the feed
  64. * @return an RSS feed url
  65. */
  66. public static String asLink(String baseURL, String repository, String objectId, int length) {
  67. if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
  68. baseURL = baseURL.substring(0, baseURL.length() - 1);
  69. }
  70. StringBuilder url = new StringBuilder();
  71. url.append(baseURL);
  72. url.append(Constants.SYNDICATION_PATH);
  73. url.append(repository);
  74. if (!StringUtils.isEmpty(objectId) || length > 0) {
  75. StringBuilder parameters = new StringBuilder("?");
  76. if (StringUtils.isEmpty(objectId)) {
  77. parameters.append("l=");
  78. parameters.append(length);
  79. } else {
  80. parameters.append("h=");
  81. parameters.append(objectId);
  82. if (length > 0) {
  83. parameters.append("&l=");
  84. parameters.append(length);
  85. }
  86. }
  87. url.append(parameters);
  88. }
  89. return url.toString();
  90. }
  91. /**
  92. * Determines the appropriate title for a feed.
  93. *
  94. * @param repository
  95. * @param objectId
  96. * @return title of the feed
  97. */
  98. public static String getTitle(String repository, String objectId) {
  99. String id = objectId;
  100. if (!StringUtils.isEmpty(id)) {
  101. if (id.startsWith(org.eclipse.jgit.lib.Constants.R_HEADS)) {
  102. id = id.substring(org.eclipse.jgit.lib.Constants.R_HEADS.length());
  103. } else if (id.startsWith(org.eclipse.jgit.lib.Constants.R_REMOTES)) {
  104. id = id.substring(org.eclipse.jgit.lib.Constants.R_REMOTES.length());
  105. } else if (id.startsWith(org.eclipse.jgit.lib.Constants.R_TAGS)) {
  106. id = id.substring(org.eclipse.jgit.lib.Constants.R_TAGS.length());
  107. }
  108. }
  109. return MessageFormat.format("{0} ({1})", repository, id);
  110. }
  111. /**
  112. * Generates the feed content.
  113. *
  114. * @param request
  115. * @param response
  116. * @throws javax.servlet.ServletException
  117. * @throws java.io.IOException
  118. */
  119. private void processRequest(javax.servlet.http.HttpServletRequest request,
  120. javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
  121. java.io.IOException {
  122. IStoredSettings settings = GitBlit.getManager(IRuntimeManager.class).getSettings();
  123. IRepositoryManager repositoryManager = GitBlit.getManager(IRepositoryManager.class);
  124. IProjectManager projectManager = GitBlit.getManager(IProjectManager.class);
  125. String servletUrl = request.getContextPath() + request.getServletPath();
  126. String url = request.getRequestURI().substring(servletUrl.length());
  127. if (url.charAt(0) == '/' && url.length() > 1) {
  128. url = url.substring(1);
  129. }
  130. String repositoryName = url;
  131. String objectId = request.getParameter("h");
  132. String l = request.getParameter("l");
  133. String page = request.getParameter("pg");
  134. String searchString = request.getParameter("s");
  135. Constants.SearchType searchType = Constants.SearchType.COMMIT;
  136. if (!StringUtils.isEmpty(request.getParameter("st"))) {
  137. Constants.SearchType type = Constants.SearchType.forName(request.getParameter("st"));
  138. if (type != null) {
  139. searchType = type;
  140. }
  141. }
  142. int length = settings.getInteger(Keys.web.syndicationEntries, 25);
  143. if (StringUtils.isEmpty(objectId)) {
  144. objectId = org.eclipse.jgit.lib.Constants.HEAD;
  145. }
  146. if (!StringUtils.isEmpty(l)) {
  147. try {
  148. length = Integer.parseInt(l);
  149. } catch (NumberFormatException x) {
  150. }
  151. }
  152. int offset = 0;
  153. if (!StringUtils.isEmpty(page)) {
  154. try {
  155. offset = length * Integer.parseInt(page);
  156. } catch (NumberFormatException x) {
  157. }
  158. }
  159. response.setContentType("application/rss+xml; charset=UTF-8");
  160. boolean isProjectFeed = false;
  161. String feedName = null;
  162. String feedTitle = null;
  163. String feedDescription = null;
  164. List<String> repositories = null;
  165. if (repositoryName.indexOf('/') == -1 && !repositoryName.toLowerCase().endsWith(".git")) {
  166. // try to find a project
  167. UserModel user = null;
  168. if (request instanceof AuthenticatedRequest) {
  169. user = ((AuthenticatedRequest) request).getUser();
  170. }
  171. ProjectModel project = projectManager.getProjectModel(repositoryName, user);
  172. if (project != null) {
  173. isProjectFeed = true;
  174. repositories = new ArrayList<String>(project.repositories);
  175. // project feed
  176. feedName = project.name;
  177. feedTitle = project.title;
  178. feedDescription = project.description;
  179. }
  180. }
  181. if (repositories == null) {
  182. // could not find project, assume this is a repository
  183. repositories = Arrays.asList(repositoryName);
  184. }
  185. boolean mountParameters = settings.getBoolean(Keys.web.mountParameters, true);
  186. String urlPattern;
  187. if (mountParameters) {
  188. // mounted parameters
  189. urlPattern = "{0}/commit/{1}/{2}";
  190. } else {
  191. // parameterized parameters
  192. urlPattern = "{0}/commit/?r={1}&h={2}";
  193. }
  194. String gitblitUrl = HttpUtils.getGitblitURL(request);
  195. char fsc = settings.getChar(Keys.web.forwardSlashCharacter, '/');
  196. List<FeedEntryModel> entries = new ArrayList<FeedEntryModel>();
  197. for (String name : repositories) {
  198. Repository repository = repositoryManager.getRepository(name);
  199. RepositoryModel model = repositoryManager.getRepositoryModel(name);
  200. if (repository == null) {
  201. if (model.isCollectingGarbage) {
  202. logger.warn(MessageFormat.format("Temporarily excluding {0} from feed, busy collecting garbage", name));
  203. }
  204. continue;
  205. }
  206. if (!isProjectFeed) {
  207. // single-repository feed
  208. feedName = model.name;
  209. feedTitle = model.name;
  210. feedDescription = model.description;
  211. }
  212. List<RevCommit> commits;
  213. if (StringUtils.isEmpty(searchString)) {
  214. // standard log/history lookup
  215. commits = JGitUtils.getRevLog(repository, objectId, offset, length);
  216. } else {
  217. // repository search
  218. commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType,
  219. offset, length);
  220. }
  221. Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository, model.showRemoteBranches);
  222. MessageProcessor processor = new MessageProcessor(settings);
  223. // convert RevCommit to SyndicatedEntryModel
  224. for (RevCommit commit : commits) {
  225. FeedEntryModel entry = new FeedEntryModel();
  226. entry.title = commit.getShortMessage();
  227. entry.author = commit.getAuthorIdent().getName();
  228. entry.link = MessageFormat.format(urlPattern, gitblitUrl,
  229. StringUtils.encodeURL(model.name.replace('/', fsc)), commit.getName());
  230. entry.published = commit.getCommitterIdent().getWhen();
  231. entry.contentType = "text/html";
  232. String message = processor.processCommitMessage(model, commit.getFullMessage());
  233. entry.content = message;
  234. entry.repository = model.name;
  235. entry.branch = objectId;
  236. entry.tags = new ArrayList<String>();
  237. // add commit id and parent commit ids
  238. entry.tags.add("commit:" + commit.getName());
  239. for (RevCommit parent : commit.getParents()) {
  240. entry.tags.add("parent:" + parent.getName());
  241. }
  242. // add refs to tabs list
  243. List<RefModel> refs = allRefs.get(commit.getId());
  244. if (refs != null && refs.size() > 0) {
  245. for (RefModel ref : refs) {
  246. entry.tags.add("ref:" + ref.getName());
  247. }
  248. }
  249. entries.add(entry);
  250. }
  251. }
  252. // sort & truncate the feed
  253. Collections.sort(entries);
  254. if (entries.size() > length) {
  255. // clip the list
  256. entries = entries.subList(0, length);
  257. }
  258. String feedLink;
  259. if (isProjectFeed) {
  260. // project feed
  261. if (mountParameters) {
  262. // mounted url
  263. feedLink = MessageFormat.format("{0}/project/{1}", gitblitUrl,
  264. StringUtils.encodeURL(feedName));
  265. } else {
  266. // parameterized url
  267. feedLink = MessageFormat.format("{0}/project/?p={1}", gitblitUrl,
  268. StringUtils.encodeURL(feedName));
  269. }
  270. } else {
  271. // repository feed
  272. if (mountParameters) {
  273. // mounted url
  274. feedLink = MessageFormat.format("{0}/summary/{1}", gitblitUrl,
  275. StringUtils.encodeURL(feedName));
  276. } else {
  277. // parameterized url
  278. feedLink = MessageFormat.format("{0}/summary/?r={1}", gitblitUrl,
  279. StringUtils.encodeURL(feedName));
  280. }
  281. }
  282. try {
  283. SyndicationUtils.toRSS(gitblitUrl, feedLink, getTitle(feedTitle, objectId),
  284. feedDescription, entries, response.getOutputStream());
  285. } catch (Exception e) {
  286. logger.error("An error occurred during feed generation", e);
  287. }
  288. }
  289. @Override
  290. protected void doPost(javax.servlet.http.HttpServletRequest request,
  291. javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
  292. java.io.IOException {
  293. processRequest(request, response);
  294. }
  295. @Override
  296. protected void doGet(javax.servlet.http.HttpServletRequest request,
  297. javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
  298. java.io.IOException {
  299. processRequest(request, response);
  300. }
  301. }