James Moger
2012-03-20 aebae04b6d44d90434f5829c2b2242b1aa1f9f7b
commit | author | age
c22722 1 /*
JM 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
8c9a20 18 import java.text.MessageFormat;
38688b 19 import java.util.ArrayList;
c22722 20 import java.util.List;
9bdb91 21 import java.util.Map;
c22722 22
JM 23 import javax.servlet.http.HttpServlet;
24
9bdb91 25 import org.eclipse.jgit.lib.ObjectId;
c22722 26 import org.eclipse.jgit.lib.Repository;
JM 27 import org.eclipse.jgit.revwalk.RevCommit;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
e493cf 31 import com.gitblit.models.FeedEntryModel;
9bdb91 32 import com.gitblit.models.RefModel;
c22722 33 import com.gitblit.models.RepositoryModel;
831469 34 import com.gitblit.utils.HttpUtils;
c22722 35 import com.gitblit.utils.JGitUtils;
JM 36 import com.gitblit.utils.StringUtils;
37 import com.gitblit.utils.SyndicationUtils;
38
892570 39 /**
JM 40  * SyndicationServlet generates RSS 2.0 feeds and feed links.
41  * 
42  * Access to this servlet is protected by the SyndicationFilter.
43  * 
44  * @author James Moger
45  * 
46  */
c22722 47 public class SyndicationServlet extends HttpServlet {
JM 48
49     private static final long serialVersionUID = 1L;
50
51     private transient Logger logger = LoggerFactory.getLogger(SyndicationServlet.class);
52
892570 53     /**
JM 54      * Create a feed link for the specified repository and branch/tag/commit id.
55      * 
56      * @param baseURL
57      * @param repository
58      *            the repository name
59      * @param objectId
60      *            the branch, tag, or first commit for the feed
61      * @param length
62      *            the number of commits to include in the feed
63      * @return an RSS feed url
64      */
c22722 65     public static String asLink(String baseURL, String repository, String objectId, int length) {
8c9a20 66         if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
c22722 67             baseURL = baseURL.substring(0, baseURL.length() - 1);
JM 68         }
8c9a20 69         StringBuilder url = new StringBuilder();
JM 70         url.append(baseURL);
5450d0 71         url.append(Constants.SYNDICATION_PATH);
8c9a20 72         url.append(repository);
JM 73         if (!StringUtils.isEmpty(objectId) || length > 0) {
74             StringBuilder parameters = new StringBuilder("?");
75             if (StringUtils.isEmpty(objectId)) {
76                 parameters.append("l=");
77                 parameters.append(length);
78             } else {
79                 parameters.append("h=");
80                 parameters.append(objectId);
81                 if (length > 0) {
82                     parameters.append("&l=");
83                     parameters.append(length);
84                 }
85             }
86             url.append(parameters);
87         }
88         return url.toString();
89     }
85c2e6 90
892570 91     /**
JM 92      * Determines the appropriate title for a feed.
93      * 
94      * @param repository
95      * @param objectId
96      * @return title of the feed
97      */
8c9a20 98     public static String getTitle(String repository, String objectId) {
JM 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);
c22722 110     }
JM 111
892570 112     /**
JM 113      * Generates the feed content.
114      * 
115      * @param request
116      * @param response
117      * @throws javax.servlet.ServletException
118      * @throws java.io.IOException
119      */
c22722 120     private void processRequest(javax.servlet.http.HttpServletRequest request,
JM 121             javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
122             java.io.IOException {
8c9a20 123
2179fb 124         String servletUrl = request.getContextPath() + request.getServletPath();
JM 125         String url = request.getRequestURI().substring(servletUrl.length());
8c9a20 126         if (url.charAt(0) == '/' && url.length() > 1) {
JM 127             url = url.substring(1);
128         }
129         String repositoryName = url;
c22722 130         String objectId = request.getParameter("h");
JM 131         String l = request.getParameter("l");
e33b91 132         String page = request.getParameter("pg");
9bdb91 133         String searchString = request.getParameter("s");
33d8d8 134         Constants.SearchType searchType = Constants.SearchType.COMMIT;
9bdb91 135         if (!StringUtils.isEmpty(request.getParameter("st"))) {
33d8d8 136             Constants.SearchType type = Constants.SearchType.forName(request.getParameter("st"));
9bdb91 137             if (type != null) {
JM 138                 searchType = type;
139             }
140         }
c22722 141         int length = GitBlit.getInteger(Keys.web.syndicationEntries, 25);
JM 142         if (StringUtils.isEmpty(objectId)) {
143             objectId = org.eclipse.jgit.lib.Constants.HEAD;
144         }
145         if (!StringUtils.isEmpty(l)) {
146             try {
147                 length = Integer.parseInt(l);
148             } catch (NumberFormatException x) {
149             }
150         }
e33b91 151         int offset = 0;
JM 152         if (!StringUtils.isEmpty(page)) {
153             try {
154                 offset = length * Integer.parseInt(page);
155             } catch (NumberFormatException x) {
156             }
157         }
c22722 158
466413 159         response.setContentType("application/rss+xml; charset=UTF-8");
c22722 160         Repository repository = GitBlit.self().getRepository(repositoryName);
JM 161         RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
9bdb91 162         List<RevCommit> commits;
JM 163         if (StringUtils.isEmpty(searchString)) {
164             // standard log/history lookup
e33b91 165             commits = JGitUtils.getRevLog(repository, objectId, offset, length);
9bdb91 166         } else {
JM 167             // repository search
e33b91 168             commits = JGitUtils.searchRevlogs(repository, objectId, searchString, searchType,
JM 169                     offset, length);
9bdb91 170         }
JM 171         Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);
ee458f 172         List<FeedEntryModel> entries = new ArrayList<FeedEntryModel>();
38688b 173
ec5a88 174         boolean mountParameters = GitBlit.getBoolean(Keys.web.mountParameters, true);
JM 175         String urlPattern;
176         if (mountParameters) {
177             // mounted parameters
178             urlPattern = "{0}/commit/{1}/{2}";
179         } else {
180             // parameterized parameters
181             urlPattern = "{0}/commit/?r={1}&h={2}";
182         }
38688b 183         String gitblitUrl = HttpUtils.getGitblitURL(request);
JM 184         // convert RevCommit to SyndicatedEntryModel
185         for (RevCommit commit : commits) {
ee458f 186             FeedEntryModel entry = new FeedEntryModel();
38688b 187             entry.title = commit.getShortMessage();
JM 188             entry.author = commit.getAuthorIdent().getName();
ec5a88 189             entry.link = MessageFormat.format(urlPattern, gitblitUrl,
38688b 190                     StringUtils.encodeURL(model.name), commit.getName());
JM 191             entry.published = commit.getCommitterIdent().getWhen();
e493cf 192             entry.contentType = "text/html";
4eb1d8 193             String message = GitBlit.self().processCommitMessage(model.name,
JM 194                     commit.getFullMessage());
e493cf 195             entry.content = message;
38688b 196             entry.repository = model.name;
4eb1d8 197             entry.branch = objectId;            
JM 198             entry.tags = new ArrayList<String>();
199             
200             // add commit id and parent commit ids
201             entry.tags.add("commit:" + commit.getName());
202             for (RevCommit parent : commit.getParents()) {
203                 entry.tags.add("parent:" + parent.getName());
204             }
205             
206             // add refs to tabs list
9bdb91 207             List<RefModel> refs = allRefs.get(commit.getId());
JM 208             if (refs != null && refs.size() > 0) {
209                 for (RefModel ref : refs) {
4eb1d8 210                     entry.tags.add("ref:" + ref.getName());
9bdb91 211                 }
4eb1d8 212             }            
38688b 213             entries.add(entry);
JM 214         }
ec5a88 215         String feedLink;
JM 216         if (mountParameters) {
217             // mounted url
218             feedLink = MessageFormat.format("{0}/summary/{1}", gitblitUrl,
219                     StringUtils.encodeURL(model.name));
220         } else {
221             // parameterized url
222             feedLink = MessageFormat.format("{0}/summary/?r={1}", gitblitUrl,
223                     StringUtils.encodeURL(model.name));
224         }
225
c22722 226         try {
ec5a88 227             SyndicationUtils.toRSS(gitblitUrl, feedLink, getTitle(model.name, objectId),
JM 228                     model.description, model.name, entries, response.getOutputStream());
c22722 229         } catch (Exception e) {
JM 230             logger.error("An error occurred during feed generation", e);
231         }
232     }
233
234     @Override
235     protected void doPost(javax.servlet.http.HttpServletRequest request,
236             javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
237             java.io.IOException {
238         processRequest(request, response);
239     }
240
241     @Override
242     protected void doGet(javax.servlet.http.HttpServletRequest request,
243             javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException,
244             java.io.IOException {
245         processRequest(request, response);
246     }
247 }