James Moger
2013-06-03 9e919f500360949c6ddb9deb2b7abb0dfaa1a3a1
commit | author | age
11924d 1 /*
JM 2  * Copyright 2012 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
18 import java.io.IOException;
19 import java.text.MessageFormat;
20 import java.text.ParseException;
7eb982 21 import java.util.ArrayList;
YI 22 import java.util.List;
11924d 23
JM 24 import javax.servlet.ServletContext;
25 import javax.servlet.ServletException;
26 import javax.servlet.http.HttpServlet;
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.http.HttpServletResponse;
29
30 import org.eclipse.jgit.lib.Repository;
31 import org.eclipse.jgit.revwalk.RevCommit;
32 import org.eclipse.jgit.revwalk.RevTree;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import com.gitblit.models.RefModel;
37 import com.gitblit.utils.ArrayUtils;
38 import com.gitblit.utils.JGitUtils;
39 import com.gitblit.utils.MarkdownUtils;
40 import com.gitblit.utils.StringUtils;
41
42 /**
43  * Serves the content of a gh-pages branch.
44  * 
45  * @author James Moger
46  * 
47  */
48 public class PagesServlet extends HttpServlet {
49
50     private static final long serialVersionUID = 1L;
51
52     private transient Logger logger = LoggerFactory.getLogger(PagesServlet.class);
53
54     public PagesServlet() {
55         super();
56     }
57
58     /**
59      * Returns an url to this servlet for the specified parameters.
60      * 
61      * @param baseURL
62      * @param repository
63      * @param path
64      * @return an url
65      */
66     public static String asLink(String baseURL, String repository, String path) {
67         if (baseURL.length() > 0 && baseURL.charAt(baseURL.length() - 1) == '/') {
68             baseURL = baseURL.substring(0, baseURL.length() - 1);
69         }
70         return baseURL + Constants.PAGES + repository + "/" + (path == null ? "" : ("/" + path));
71     }
72
73     /**
74      * Retrieves the specified resource from the gh-pages branch of the
75      * repository.
76      * 
77      * @param request
78      * @param response
79      * @throws javax.servlet.ServletException
80      * @throws java.io.IOException
81      */
82     private void processRequest(HttpServletRequest request, HttpServletResponse response)
83             throws ServletException, IOException {
84         String path = request.getPathInfo();
85         if (path.toLowerCase().endsWith(".git")) {
86             // forward to url with trailing /
87             // this is important for relative pages links
88             response.sendRedirect(request.getServletPath() + path + "/");
89             return;
90         }
91         if (path.charAt(0) == '/') {
92             // strip leading /
93             path = path.substring(1);
94         }
95
96         // determine repository and resource from url
97         String repository = "";
98         String resource = "";
99         Repository r = null;
100         int offset = 0;
101         while (r == null) {
102             int slash = path.indexOf('/', offset);
103             if (slash == -1) {
104                 repository = path;
105             } else {
106                 repository = path.substring(0, slash);
107             }
108             r = GitBlit.self().getRepository(repository, false);
109             offset = slash + 1;
110             if (offset > 0) {
111                 resource = path.substring(offset);
112             }
113             if (repository.equals(path)) {
114                 // either only repository in url or no repository found
115                 break;
116             }
117         }
118
119         ServletContext context = request.getSession().getServletContext();
120
121         try {
122             if (r == null) {
123                 // repository not found!
124                 String mkd = MessageFormat.format(
125                         "# Error\nSorry, no valid **repository** specified in this url: {0}!",
126                         repository);
127                 error(response, mkd);
128                 return;
129             }
130
131             // retrieve the content from the repository
132             RefModel pages = JGitUtils.getPagesBranch(r);
133             RevCommit commit = JGitUtils.getCommit(r, pages.getObjectId().getName());
134
135             if (commit == null) {
136                 // branch not found!
137                 String mkd = MessageFormat.format(
138                         "# Error\nSorry, the repository {0} does not have a **gh-pages** branch!",
139                         repository);
140                 error(response, mkd);
141                 r.close();
142                 return;
143             }
144             response.setDateHeader("Last-Modified", JGitUtils.getCommitDate(commit).getTime());
145
ae9e15 146             String [] encodings = GitBlit.getEncodings();
JM 147
11924d 148             RevTree tree = commit.getTree();
JM 149             byte[] content = null;
150             if (StringUtils.isEmpty(resource)) {
151                 // find resource
7eb982 152                 List<String> markdownExtensions = GitBlit.getStrings(Keys.web.markdownExtensions);
d6bbb2 153                 List<String> extensions = new ArrayList<String>(markdownExtensions.size() + 2);
7eb982 154                 extensions.add("html");
d6bbb2 155                 extensions.add("htm");
7eb982 156                 extensions.addAll(markdownExtensions);
YI 157                 for (String ext : extensions){
158                     String file = "index." + ext;
1dcfd2 159                     String stringContent = JGitUtils.getStringContent(r, tree, file, encodings);
YI 160                     if(stringContent == null){
161                         continue;
162                     }
163                     content = stringContent.getBytes(Constants.ENCODING);
11924d 164                     if (content != null) {
JM 165                         resource = file;
166                         // assume text/html unless the servlet container
167                         // overrides
168                         response.setContentType("text/html; charset=" + Constants.ENCODING);
169                         break;
170                     }
171                 }
172             } else {
173                 // specific resource
d35134 174                 try {
JM 175                     String contentType = context.getMimeType(resource);
176                     if (contentType == null) {
177                         contentType = "text/plain";
178                     }
179                     if (contentType.startsWith("text")) {
ae9e15 180                         content = JGitUtils.getStringContent(r, tree, resource, encodings).getBytes(
d35134 181                                 Constants.ENCODING);
JM 182                     } else {
e4e682 183                         content = JGitUtils.getByteContent(r, tree, resource, false);
d35134 184                     }
JM 185                     response.setContentType(contentType);
186                 } catch (Exception e) {
11924d 187                 }
JM 188             }
189
190             // no content, try custom 404 page
191             if (ArrayUtils.isEmpty(content)) {
ae9e15 192                 String custom404 = JGitUtils.getStringContent(r, tree, "404.html", encodings);
d35134 193                 if (!StringUtils.isEmpty(custom404)) {
JM 194                     content = custom404.getBytes(Constants.ENCODING);
195                 }
196
11924d 197                 // still no content
JM 198                 if (ArrayUtils.isEmpty(content)) {
d35134 199                     String str = MessageFormat.format(
11924d 200                             "# Error\nSorry, the requested resource **{0}** was not found.",
d35134 201                             resource);
JM 202                     content = MarkdownUtils.transformMarkdown(str).getBytes(Constants.ENCODING);
11924d 203                 }
d35134 204
JM 205                 try {
206                     // output the content
207                     logger.warn("Pages 404: " + resource);
208                     response.setStatus(HttpServletResponse.SC_NOT_FOUND);
209                     response.getOutputStream().write(content);
210                     response.flushBuffer();
211                 } catch (Throwable t) {
212                     logger.error("Failed to write page to client", t);
213                 }
214                 return;
11924d 215             }
JM 216
217             // check to see if we should transform markdown files
218             for (String ext : GitBlit.getStrings(Keys.web.markdownExtensions)) {
219                 if (resource.endsWith(ext)) {
220                     String mkd = new String(content, Constants.ENCODING);
221                     content = MarkdownUtils.transformMarkdown(mkd).getBytes(Constants.ENCODING);
94e0bf 222                     response.setContentType("text/html; charset=" + Constants.ENCODING);
11924d 223                     break;
JM 224                 }
225             }
226
227             try {
228                 // output the content
229                 response.getOutputStream().write(content);
230                 response.flushBuffer();
231             } catch (Throwable t) {
232                 logger.error("Failed to write page to client", t);
233             }
234
235             // close the repository
236             r.close();
237         } catch (Throwable t) {
238             logger.error("Failed to write page to client", t);
239         }
240     }
241
242     private void error(HttpServletResponse response, String mkd) throws ServletException,
243             IOException, ParseException {
244         String content = MarkdownUtils.transformMarkdown(mkd);
245         response.setContentType("text/html; charset=" + Constants.ENCODING);
246         response.getWriter().write(content);
247     }
248
249     @Override
250     protected void doPost(HttpServletRequest request, HttpServletResponse response)
251             throws ServletException, IOException {
252         processRequest(request, response);
253     }
254
255     @Override
256     protected void doGet(HttpServletRequest request, HttpServletResponse response)
257             throws ServletException, IOException {
258         processRequest(request, response);
259     }
260 }