View Javadoc
1   /*
2    * Copyright (C) 2009-2010, Google Inc.
3    * and other copyright owners as documented in the project's IP log.
4    *
5    * This program and the accompanying materials are made available
6    * under the terms of the Eclipse Distribution License v1.0 which
7    * accompanies this distribution, is reproduced below, and is
8    * available at http://www.eclipse.org/org/documents/edl-v10.php
9    *
10   * All rights reserved.
11   *
12   * Redistribution and use in source and binary forms, with or
13   * without modification, are permitted provided that the following
14   * conditions are met:
15   *
16   * - Redistributions of source code must retain the above copyright
17   *   notice, this list of conditions and the following disclaimer.
18   *
19   * - Redistributions in binary form must reproduce the above
20   *   copyright notice, this list of conditions and the following
21   *   disclaimer in the documentation and/or other materials provided
22   *   with the distribution.
23   *
24   * - Neither the name of the Eclipse Foundation, Inc. nor the
25   *   names of its contributors may be used to endorse or promote
26   *   products derived from this software without specific prior
27   *   written permission.
28   *
29   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
30   * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
31   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
32   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
34   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
35   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
36   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
38   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
40   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
41   * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42   */
43  
44  package org.eclipse.jgit.http.server;
45  
46  import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
47  import static javax.servlet.http.HttpServletResponse.SC_UNAUTHORIZED;
48  import static org.eclipse.jgit.http.server.GitSmartHttpTools.infoRefsResultType;
49  import static org.eclipse.jgit.http.server.GitSmartHttpTools.sendError;
50  import static org.eclipse.jgit.http.server.ServletUtils.ATTRIBUTE_HANDLER;
51  import static org.eclipse.jgit.http.server.ServletUtils.getRepository;
52  
53  import java.io.IOException;
54  import java.util.List;
55  
56  import javax.servlet.Filter;
57  import javax.servlet.FilterChain;
58  import javax.servlet.FilterConfig;
59  import javax.servlet.ServletException;
60  import javax.servlet.ServletRequest;
61  import javax.servlet.ServletResponse;
62  import javax.servlet.http.HttpServletRequest;
63  import javax.servlet.http.HttpServletResponse;
64  
65  import org.eclipse.jgit.lib.Repository;
66  import org.eclipse.jgit.transport.PacketLineOut;
67  import org.eclipse.jgit.transport.RefAdvertiser.PacketLineOutRefAdvertiser;
68  import org.eclipse.jgit.transport.ServiceMayNotContinueException;
69  import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
70  import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
71  
72  /** Filter in front of {@link InfoRefsServlet} to catch smart service requests. */
73  abstract class SmartServiceInfoRefs implements Filter {
74  	private final String svc;
75  
76  	private final Filter[] filters;
77  
78  	SmartServiceInfoRefs(final String service, final List<Filter> filters) {
79  		this.svc = service;
80  		this.filters = filters.toArray(new Filter[filters.size()]);
81  	}
82  
83  	public void init(FilterConfig config) throws ServletException {
84  		// Do nothing.
85  	}
86  
87  	public void destroy() {
88  		// Do nothing.
89  	}
90  
91  	public void doFilter(ServletRequest request, ServletResponse response,
92  			FilterChain chain) throws IOException, ServletException {
93  		final HttpServletRequest req = (HttpServletRequest) request;
94  		final HttpServletResponse res = (HttpServletResponse) response;
95  
96  		if (svc.equals(req.getParameter("service"))) {
97  			final Repository db = getRepository(req);
98  			try {
99  				begin(req, db);
100 			} catch (ServiceNotAuthorizedException e) {
101 				res.sendError(SC_UNAUTHORIZED, e.getMessage());
102 				return;
103 			} catch (ServiceNotEnabledException e) {
104 				sendError(req, res, SC_FORBIDDEN, e.getMessage());
105 				return;
106 			}
107 
108 			try {
109 				if (filters.length == 0)
110 					service(req, response);
111 				else
112 					new Chain().doFilter(request, response);
113 			} finally {
114 				req.removeAttribute(ATTRIBUTE_HANDLER);
115 			}
116 		} else {
117 			chain.doFilter(request, response);
118 		}
119 	}
120 
121 	private void service(ServletRequest request, ServletResponse response)
122 			throws IOException {
123 		final HttpServletRequest req = (HttpServletRequest) request;
124 		final HttpServletResponse res = (HttpServletResponse) response;
125 		final SmartOutputStream buf = new SmartOutputStream(req, res, true);
126 		try {
127 			res.setContentType(infoRefsResultType(svc));
128 
129 			final PacketLineOut out = new PacketLineOut(buf);
130 			out.writeString("# service=" + svc + "\n");
131 			out.end();
132 			advertise(req, new PacketLineOutRefAdvertiser(out));
133 			buf.close();
134 		} catch (ServiceNotAuthorizedException e) {
135 			res.sendError(SC_UNAUTHORIZED, e.getMessage());
136 		} catch (ServiceNotEnabledException e) {
137 			sendError(req, res, SC_FORBIDDEN, e.getMessage());
138 		} catch (ServiceMayNotContinueException e) {
139 			if (e.isOutput())
140 				buf.close();
141 			else
142 				sendError(req, res, e.getStatusCode(), e.getMessage());
143 		}
144 	}
145 
146 	protected abstract void begin(HttpServletRequest req, Repository db)
147 			throws IOException, ServiceNotEnabledException,
148 			ServiceNotAuthorizedException;
149 
150 	protected abstract void advertise(HttpServletRequest req,
151 			PacketLineOutRefAdvertiser pck) throws IOException,
152 			ServiceNotEnabledException, ServiceNotAuthorizedException;
153 
154 	private class Chain implements FilterChain {
155 		private int filterIdx;
156 
157 		public void doFilter(ServletRequest req, ServletResponse rsp)
158 				throws IOException, ServletException {
159 			if (filterIdx < filters.length)
160 				filters[filterIdx++].doFilter(req, rsp, this);
161 			else
162 				service(req, rsp);
163 		}
164 	}
165 }